Win32ComponentPeer patch


#1

If Explorer dies, and you’ve set a taskbar icon, it won’t reappear when Explorer comes up again. This patch fixes that:

Win32ComponentPeer.cpp :

static unsigned s_uTaskbarCreatedMessage = 0;

In Win32ComponentPeer constructor:
{
  ...

  // Get the taskbar creation message
  s_uTaskbarCreatedMessage = RegisterWindowMessage(TEXT("TaskbarCreated"));
}
    void setTaskBarIcon (const Image& image)
    {
        if (image.isValid())
        {
            HICON hicon = IconConverters::createHICONFromImage (image, TRUE, 0, 0);

            if (taskBarIcon == 0)
            {
                taskBarIcon = new NOTIFYICONDATA();
                memset(taskBarIcon, 0, sizeof(NOTIFYICONDATA));
                taskBarIcon->cbSize = sizeof (NOTIFYICONDATA);
                taskBarIcon->hWnd = (HWND) hwnd;
                taskBarIcon->uID = (int) (pointer_sized_int) hwnd;
                taskBarIcon->uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
                taskBarIcon->uCallbackMessage = WM_TRAYNOTIFY;
                taskBarIcon->hIcon = hicon;
                taskBarIcon->szTip[0] = 0;

                Shell_NotifyIcon (NIM_ADD, taskBarIcon);
            }
            else
            {
                HICON oldIcon = taskBarIcon->hIcon;

                taskBarIcon->hIcon = hicon;
                taskBarIcon->uFlags = NIF_ICON;
                Shell_NotifyIcon (NIM_MODIFY, taskBarIcon);

                DestroyIcon (oldIcon);
            }

            // Need to hang on to it (to be able to handle taskbar creation message)
            //DestroyIcon (hicon);
        }
        else if (taskBarIcon != 0)
        {
            taskBarIcon->uFlags = 0;
            Shell_NotifyIcon (NIM_DELETE, taskBarIcon);
            DestroyIcon (taskBarIcon->hIcon);
            taskBarIcon = 0;
        }
    }
    LRESULT peerWindowProc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
    {
        [...snip...]

        // Need to check taskbar creation whether or not peer is "valid"
        if (message == s_uTaskbarCreatedMessage && taskBarIcon != 0)
        {
            taskBarIcon->uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
            Shell_NotifyIcon(NIM_ADD, taskBarIcon);
        }

        return DefWindowProcW (h, message, wParam, lParam);
    }

#2

Cool, thanks, I’ll get that sorted out for you.


#3

Turns out it is not working (on Vista + Win 7), due to UAC issues (see http://social.msdn.microsoft.com/Forums/en/windowsuidevelopment/thread/f4370108-9cf9-4353-a086-a6f5112947ce). So the patch to get it working is by calling the ChangeWindowMessageFilter function to remove the “TaskbarCreated” message from filtering:

In Win32ComponentPeer::createWindow():

        ...
        hwnd = CreateWindowEx (exstyle, WindowClassHolder::getInstance()->getWindowClassName(),
                               L"", type, 0, 0, 0, 0, parentToAddTo, 0,
                               (HINSTANCE) PlatformUtilities::getCurrentModuleInstanceHandle(), 0);

       #if JUCE_DIRECT2D
        setCurrentRenderingEngine (1);
       #endif

        if (hwnd != 0)
        {
            // In order to receive the "TaskbarCreated" message, we need to request it not being filtered out explicitly
            // Note that ChangeWindowMessageFilter is available only on Vista and later
            HMODULE hMod = LoadLibrary(TEXT("user32.dll"));
            if (hMod)
            {
                typedef BOOL (WINAPI *TChangeWindowMessageFilter)(UINT,DWORD);
                TChangeWindowMessageFilter fn = (TChangeWindowMessageFilter)GetProcAddress(hMod,"ChangeWindowMessageFilter");
                if (fn)
                {
                    // taskbarCreatedMessage must be initialized prior to this, i.e. not in the peerWindowProc function...
                    fn(taskbarCreatedMessage,1);  // 1 == MSGFLT_ADD
                }
                FreeLibrary(hMod);
            }
            ...

Oh, btw, I’m using v1.53 (the zipped version on SF), is there any chance getting a v1.54 soon (with this included) ? :slight_smile:


#4

Also, it seems that sometimes if you start an application really early in the logon process, the icon never gets added to the Taskbar, so I propose the following change:

    //==============================================================================
    void setTaskBarIcon (const Image& image)
    {
        if (image.isValid())
        {
            HICON hicon = IconConverters::createHICONFromImage (image, TRUE, 0, 0);

            if (taskBarIcon == 0)
            {
                taskBarIcon = new NOTIFYICONDATA();
                zeromem (taskBarIcon, sizeof (NOTIFYICONDATA));
                taskBarIcon->cbSize = sizeof (NOTIFYICONDATA);
                taskBarIcon->hWnd = (HWND) hwnd;
                taskBarIcon->uID = (int) (pointer_sized_int) hwnd;
                taskBarIcon->uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
                taskBarIcon->uCallbackMessage = WM_TRAYNOTIFY;
                taskBarIcon->hIcon = hicon;
                taskBarIcon->szTip[0] = 0;

                Shell_NotifyIcon (NIM_ADD, taskBarIcon);
            }
            else
            {
                HICON oldIcon = taskBarIcon->hIcon;

                taskBarIcon->hIcon = hicon;
                taskBarIcon->uFlags = NIF_ICON;
                if (!Shell_NotifyIcon (NIM_MODIFY, taskBarIcon))
                {
                    taskBarIcon->uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
                    Shell_NotifyIcon (NIM_ADD, taskBarIcon);
                }

                DestroyIcon (oldIcon);
            }
        }
        else if (taskBarIcon != 0)
        {
            taskBarIcon->uFlags = 0;
            Shell_NotifyIcon (NIM_DELETE, taskBarIcon);
            DestroyIcon (taskBarIcon->hIcon);
            taskBarIcon = nullptr;
        }
    }

#5

Thanks Rob! I’ll take a look through that and get it implemented.

I’m doing all my current changes in the new modules branch though, and since the taskbar icon stuff has been totally restructured (I’ve actually split it out completely from the core windowing code, and it lives in a different module), it probably won’t be too easy to also replicate in the old main branch.


#6

[quote=“jules”]Thanks Rob! I’ll take a look through that and get it implemented.

I’m doing all my current changes in the new modules branch though, and since the taskbar icon stuff has been totally restructured (I’ve actually split it out completely from the core windowing code, and it lives in a different module), it probably won’t be too easy to also replicate in the old main branch.[/quote]
You’re welcome :slight_smile: Ok, I’ll just make a patched zip and use that instead for a while.