ShowWindow() showing blank app until is interacted with via mouse/keyboard after restoring from systray in C++ - Flutter App

0

I've been wanting to incorporate systray functionality into my Flutter app so I went to modify the native C++ code that initiates the window etc to see if I could hook into it. Despite not having much prior experience in C++ I have been able to create an icon for my app in the systray with a menu that allows the window to be shown again when hidden (using ShowWindow(hwnd, SW_HIDE);) and to quit entirely.

However when an option in my systray menu is selected to show the window again using ShowWindow(hwnd, SW_NORMAL); after being hidden, the app stays blank like this:

enter image description here

Then, when the window is finally interacted with, the contents of the window show again:

enter image description here

Here is the code that I have added so far to my win32_window.cpp (from a default Flutter application). I haven't included the entire functions because I thought it would make things less clear, but I will also attach the full win32_window.cpp at the end of this post. Win32Window::CreateAndShow():

//Systray:
HICON hMainIcon;
hMainIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_APP_ICON));
nidApp.cbSize = sizeof(NOTIFYICONDATA); // sizeof the struct in bytes
nidApp.hWnd = (HWND) window;              //handle of the window which will process this app. messages
nidApp.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; //ORing of all the flags
nidApp.hIcon = hMainIcon; // handle of the Icon to be displayed, obtained from LoadIcon
nidApp.uCallbackMessage = WM_USER_SHELLICON;
StringCchCopy(nidApp.szTip, ARRAYSIZE(nidApp.szTip), L"All Platforms Test");
Shell_NotifyIcon(NIM_ADD, &nidApp);

return OnCreate();

Win32Window::WndProc():

if (message == WM_NCCREATE) { ... }
else if (message == WM_USER_SHELLICON) { //interacting with systray icon
    if (LOWORD(lparam) == WM_RBUTTONDOWN) { //right clicked
        POINT lpClickPoint;
        GetCursorPos(&lpClickPoint);
        hPopMenu = CreatePopupMenu();
        InsertMenu(hPopMenu,0xFFFFFFFF,MF_BYPOSITION|MF_STRING,IDM_SHOW,_T("Show"));
        InsertMenu(hPopMenu,0xFFFFFFFF,MF_BYPOSITION|MF_STRING,IDM_EXIT,_T("Quit"));
        SetForegroundWindow(window);
        TrackPopupMenu(hPopMenu,TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_BOTTOMALIGN,lpClickPoint.x, lpClickPoint.y,0,window,NULL);
    }
    else if (LOWORD(lparam) == WM_LBUTTONDOWN) { //left clicked
        ShowWindow(window, SW_NORMAL);
        //LOOK: works but shows blank screen until is interacted with (mouse enters or key is pressed etc)
    }
}
else if (message == WM_COMMAND) { //if message is a command event such as a click on the exit menu option
    int wmId;
    wmId = LOWORD(wparam);

    if (wmId == IDM_EXIT) { //if quit has been pressed
        Shell_NotifyIcon(NIM_DELETE,&nidApp);
        DestroyWindow(window);
    }
    else if (wmId == IDM_SHOW) {
        ShowWindow(window, SW_NORMAL);
        //LOOK: works but shows blank screen until is interacted with (mouse enters or key is pressed etc)
    }

Win32Window::MessageHandler():

switch (message) {
  ...
  case WM_CLOSE: //stop window from closing normally, can only be closed when DestroyWindow() is run from systray
    //Hide window and continue running in background.
    ShowWindow(hwnd, SW_HIDE);
    return 0;
}

Link to full win32_window.cpp here.

What's going on here? I thought using UpdateWindow() would help but then I realise the app is painted upon ShowWindow() anyway. My guess is that this has something to do with Flutter's run loop being blocked but I can't figure out where to go next, especially considering I usually don't dabble in C++ but just wanted to add an extra feature to my app when running on Windows.

Any help would be greatly appreciated, thanks.

c++
flutter
winapi
systray
asked on Stack Overflow May 18, 2021 by Letal1s • edited May 18, 2021 by Letal1s

1 Answer

0

Ok so I've worked out why it wasn't working. When closing the window, I couldn't just use SW_HIDE, but SW_MINIMIZE too. Otherwise attempting to redraw the window wouldn't work correctly:

ShowWindow(hwnd, SW_MINIMIZE);
ShowWindow(hwnd, SW_HIDE);

After that, when showing the window it got drawn but wasn't the active window, but adding SetForegroundWindow() fixed that:

ShowWindow(window, SW_NORMAL);
SetForegroundWindow(window);

Thanks for everyone's help :)

answered on Stack Overflow May 20, 2021 by Letal1s • edited May 20, 2021 by Letal1s

User contributions licensed under CC BY-SA 3.0