SHGetImageList returns an icon that is too small for the size - c++

I'm trying to retrieve file icons on Windows. I follow this guide http://pogopixels.com/blog/getting-the-48x48-or-256x256-icon-of-a-file-on-windows/
I use SHIL_JUMBO to get the maximum size possible. However, not all icons returned are big enough, such as the QuickTime icon in the attached image. The size of the whole pixmap returned is still 256x256 but it does not fill the entire space. My program will then scale it down, making it too tiny to see.
I'm wondering if I can retrieve some extra info such as the size of the original icon, so I know that it's too small to scale down.

Related

What size of ImageList icons do I need to make & load for my app (considering higher DPI)?

I have a CListCtrl control (or a ListView in Win32) that is created with LVS_REPORT style.
I am intending to display icons in its items as such:
But the question is what size of icons do I need to make and load?
Let me explain. From the old Win32 samples, I can see that everyone creates image lists with 15x15 pixel icons. But the issue with those is that it looks horribly pixelated on any modern PC with higher DPI settings. Thus I was looking for a dynamic way to determine the appropriate size of image lists for the CListCtrl.
And also the first part of the question, what icon size should I make originally?
EDIT
PS: Since DPI scaling came up, how do you find it out? I'm currently using the following approach:
//No error handling for brevity
HDC hDC = ::GetDC(hAppsMainWindowHandle);
int nCx = ::GetDeviceCaps(hDC, LOGPIXELSX);
int nCy = ::GetDeviceCaps(hDC, LOGPIXELSY);
::ReleaseDC(hAppsMainWindowHandle, hDC);
//I technically get horizontal & vertical scaling --
//can those be different?
double scalingCx = (double)nCx / 96.0; //1.0 = 100%
double scalingCy = (double)nCy / 96.0;
Is font scaling something different?
A list view uses a "small" or "large" image list depending on its mode. In report mode, it uses the "small" image list. You can use GetSystemMetrics() to get the dimensions of "small" images using the SM_CXSMICON and SM_CYSMICON metrics (use SM_CXICON and SM_CYICON for "large" images).
Note that the returned values will be virtual/scaled if your app is not DPI-aware, so to get accurate values, make sure it is DPI-aware via SetProcessDPIAware(), SetProcessDpiAwareness(), or a DPI manifest.
Update: I just ran across this function, might be useful for you when writing a DPI-aware app:
LoadIconWithScaleDown()
Make larger images and let the API scale them down to smaller sizes.
The report style list view wants small icons, that is icons with SM_CXSMICON by SM_CYSMICON metrics. Assuming your app is high DPI aware, then the actual value of these metrics depends on the user's chosen font scaling or DPI setting. So up front you cannot know what size icons should be used. You have to query the system metrics at runtime, and use appropriately sized icons.
Now, what size icons you include in your executable depend on what DPI settings you wish to support. Back in XP days you could reasonably expect to encounter 100% and 125% font scaling. These days, high density display panels are common and you really need to support larger ratios. At least 150% and 200%, and quite probably 175%.
The closest I can find to guidelines is in this MSDN article: http://msdn.microsoft.com/en-US/library/windows/desktop/dn742485.aspx
This article was written around the Vista time frame and already shows its age. I think you have to use these articles as a guide and adapt to the hardware of the day.
You will also find that people run their machines at font scaling values in between the round numbers listed above, and in the article I link to. One of my colleagues runs at 120%. Interestingly this has highlighted various bugs in our code so it's always useful to have someone dog-fooding your program.
When you build your image lists at runtime, size them according to system metrics. And try to avoid scaling icons. For instance, if system metrics suggest an 18px icons, and you only have 16px and 20px icons, then make a new 18px icons. Fill the image with transparent pixels, and blit the 16px icon into the middle of this 18px image. Make the icon out of that. This approach will avoid aliasing problems.

Garbage on top of screen when displaying text over image in devkit pro

I am currently using the 16-bit libnds (Whith devkitpro) example as a basis and am trying to display text and the png background image on the same screen (in this example it is the top sceen). I am having a similar issue as this post.
I have garbage on the top of the screen (only ifconsoleInit(...) is called), similar to the first problem in the thread. The only problem is that I am displaying the background image in a different method so the fixes they made in that thread did not apply to this.
All I am looking for is whether there is a way to fix the garbage on the top of the screen. If there is a more efficient/better way to display the image, I am willing to accept it, just I haven't found a detailed enough tutorial on how to load an image as a background without using this method. Any help would be appreciated. I will answer any further questions anyone has about what is not working.
You can find the project attached here.
Sorry for the long delay but there are a few issues with your code. The first is that in Mode 4 the only background that can be set up as a 16 bit bitmap is layer 3. http://answers.drunkencoders.com/what-graphics-modes-does-the-ds-support/
Next, the layers all share a single chunk of background memory and your garbage is coming from you overwriting part of the bitmap in video memory with the characters for the font and the map for the console background. A simple solution is to move the bitmap by settings its map base to 1. This offsets its in graphics memory by 16KB which leaves 16KB of room for your text layer (this only works because we cant display the entire 256x256 image on screen at once due the the resolution of the DS as 256x256x2bytes fills up all of memory bank A...to be more correct we should assign another memory bank to the main background...but since we cant see the bottom 70 or so lines of pixels of our image anyway its okay that they didnt quite make it into video memory).
libnds also has a macro to make finding the memory for your background a bit simpler called "bgGetGfxPtr(id)" which will get a pointer to your background gfx in video memory after you set it up so you dont have to try to calculate it via an offset from BG_GFX.
In all the changes to your code should look like this (I added a version of this to the libnds code faq at : http://answers.drunkencoders.com/wp-admin/post.php?post=289&action=edit&message=1)
int main(void) {
//Top screen pic init
videoSetMode(MODE_4_2D);
vramSetBankA(VRAM_A_MAIN_BG);
int bg = bgInit(3, BgType_Bmp16, BgSize_B16_256x256, 1,0);
decompress(drunkenlogoBitmap, bgGetGfxPtr(bg), LZ77Vram); //Displays/decompresses top image
//videoSetMode(MODE_4_2D);
consoleInit(0,0, BgType_Text4bpp, BgSize_T_256x256, 4,0, true, true);
iprintf("\x1b[1;1HThe garbage is up here ^^^^^.");
iprintf("\x1b[21;1HTesting the text function...");
while(1) {
swiWaitForVBlank();
scanKeys();
if (keysDown()&KEY_START) break;
}
return 0;
}

GDI+ : Changing DPI

I have two points that i need be to be clarifief on :
changing image DPI from 200 to 100 does it mean that i have to resize the image by half or i could keep the actual dimensions but decrease the DPI.
I herd that GDI+ could be a nice alternative to change the image DPI, i googled in that way but i found no example showing how to change the DPI with GDI+.
Any Idea about those questions, and thank you.
Changing the dpi of an existing image doesn't make much sense. It records the resolution of the device that created the image. So that it can be displayed at the same physical size on another device with a different dpi setting. Which is how an image you drew in a painting program on a monitor with 96 dpi doesn't turn into a postage stamp one-sixth the size when you print it on a printer with 600 dpi resolution.
By changing it in your code when you already have the image, you are basically trying to change the characteristics of the device that created the image. That doesn't make sense, your code cannot reach back and, say, change the CCD in the camera or change the monitor resolution.
It's just a reference number.
You can display or print the image at any size you want, it doesn't have to match the original size.

Resizing a double buffered widget?

Right now, my text widget is double buffered ( it draws the text to a bitmap when an event occurs) . This works great except when I resize the widget. When I resize, I al_destroy_bitmap and create a new one with the new dimensions This is very slow. How do most double buffered guis such as Windows and Mac OSX avoid this issue?
Thanks
Most widgets that are backed by bitmaps (or used to render by OGL or DX) have locked borders and don't allow resizing.
Those that do very often suffer from speed issues caused by that.
You could watch for resizing to begin and end and only update your bitmap when it's done, or if only receiving a resize-happened event, watch for a few back to back and disable your bitmap resizing until they stop coming (after, say, the first 5 in a second, wait until no resize events arrive for 250ms).
I recently did double-buffering for the purpose of collision detection in Flash. It had a similar problem, creating bitmap data structures was relatively slow (this in itself is sad since allocating raw memory should be fast, for Flash and in your case).
What I did was to simply cache the backing bitmaps and reuse them when possible. So if somebody would resize to 250x250 I could reused a bitmap that was 280x260. Whenever a widget was done with the bitmap it'd free it back up to be used again, or if they shrunk and could use a smaller one. I had a cap on the total memory that could be used and would prune the unused bitmaps if exceeded.
But you don't have to be so extreme. For a simple first step ensure you resize in large increments. For example, even if the user has only resized by 2 pixels, you can resize the internal bitmap by 50. That way you can keep reusing the bitmap until the user hits the new size limit.
If the user decreases the size you don't have to do anything, since your existing bitmap is big enough to do the drawing. When you copy it to the screen just copy the upper-left corner of it (the part you actually use).

How can you make buttons on a MSVS C++ CToolBar larger along with their images?

We have a touch screen, and the toolbar is too small to hit with my meaty fingers. Is there an easy way I can have an option to make the toolbar buttons bigger and easier to hit?
So far I've attempted a few things:
m_toolbar.SetSizes( CSize(64,64), CSize(50,50) );
m_toolbar.SetSizes( CSize(64,64), CSize(50,50) );
m_toolbar.GetToolBarCtrl().SetButtonWidth( 64, 64 );
m_toolbar.GetToolBarCtrl().SetButtonSize( CSize(64, 64) );
None of these approaches stretches the images as well. The buttons get larger, and are fully functional, but the images do not overlap the buttons the way they normally would. I would prefer to keep a single image list for the icons, and have the images stretched to fit.
At toolbar creation time, create an empty CImageList with size 64x64 (let's call it large). Load the original image list from resources (we call it small).
Iterate over each image in small and copy/resize it to large.
Then assign large to your toolbar. Somewhat cumbersome bui should work.
HTH,
As far as I know there is no way to make images resize with the size of the buttons. MFC applications use bmp and not vectorial images.
So you will have to supply a bmp images with the disired sizes.
You can use a CImageList and SetImageList to set the images but then you will have to
initialize images there with the disired size also.