0
votes

I'm trying to allow the user of my application to set their own custom icons, but loading the icon file through LoadImage function and setting it via WM_SETICON message doesn't seem to do the trick. The icon in Windows explorer doesn't update, and the ones on task bar and in upper left corner reset each time I run the program (the user has to set them again). None of these problems occurred when I used resources instead, but I can't change the .rc file after I compile the program, do I? What am I doing wrong? I have a menu function which calls GetOpenFileName to get icon file, then loads it through LoadImage and sets via SendMessage.

Here's my code (I skipped checking return values of functions to shorten the code)

void DoFileIcon(HWND hwnd)
{
    OPENFILENAME ofn;
    char szFileName[MAX_PATH] = "";

    ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = sizeof(OPENFILENAME);
    ofn.hwndOwner = hwnd;
    ofn.lpstrFilter = "Icons (*.ico)\0*.ico\0All files (*.*)\0*.*\0";
    ofn.lpstrFile = szFileName;
    ofn.nMaxFile = MAX_PATH;
    ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
    ofn.lpstrDefExt = "ico";

    if(GetOpenFileName(&ofn))
    {
        HICON hIcon, hIconSm;
        hIcon = LoadImage(NULL, szFileName, IMAGE_ICON, 32, 32, 
        LR_LOADFROMFILE);
        SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
        hIconSm = LoadImage(NULL, szFileName, IMAGE_ICON, 16, 16, 
        LR_LOADFROMFILE);
        SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hIconSm);
    }
}
1
UpdateResource() et al can do this by rewriting the internal resource, may be more sensible to create a shortcut to your app and modify that via IShellLink: stackoverflow.com/questions/35665476/…Alex K.
@AlexK. beat me to the IShellLink suggestion.Chris Becke

1 Answers

1
votes

By the icon in Windows Explorer I presume you mean the icon associated by the shell with the .exe file. That is always determined to be the first icon resource in the file. Unless you are prepared to allow modifications to the .exe file, then you won't be able to change this. And I would strongly advise you not to modify your .exe file after deployment. That is liable to lead to corruptions and will appear suspicious to anti-malware software.

As for the icon associated with your main window, that is simple enough. You already know how to change that, send WM_SETICON messages. Or register the custom icon when you register the window class. Your problem here appears to be simply that your program does neither of these things on startup, but instead only when you make a call to DoFileIcon. The system isn't going to remember the custom icon for you, you need to write code to do that. Store the information in the registry, or an application configuration file. Then at application startup, read this configuration, and apply the custom icon.