1

After I send a TB_DELETEBUTTON message to delete a button (of a external application) in the system-tray toolbar, it remains a blank/empty rectangle from that deleted button, and the toolbar does not remove this empty rectangle until I do left or right click on some other icon, then finally the toolbar window gets redrawn and the empty rectangle from he button that I deleted disappears.

This is an aesthetic issue that I would like to avoid. I just would like to programatically update/redraw the toolbar window after I send the TB_DELETEBUTTON message, however after I call the UpdateWindow, UpdateLayeredWindow or RedrawWindow, the empty rectangle of the deleted button remains there.

The flags cobmination that I tried to use with RedrawWindow are: RDW_FRAME, RDW_ALLCHILDREN, RDW_UPDATENOW and RDW_INVALIDATE, all together.

The window handle that I'm passing to these functions is the window with class name: "ToolbarWindow32" (on which reside the system-tray buttons/icons of the applications), a example for getting this window handle can be found here.

My question is: how can I properly update/redraw this window?.

ElektroStudios
  • 19,105
  • 33
  • 200
  • 417
  • Use SendInput to move the mouse over the button and the shell will remove it. As for "how can I properly", well that ship sailed once you started hacking at another application and the system implementation details. There is no proper way to do this. – David Heffernan Apr 16 '19 at 10:36
  • 1
    Just a note: have you checked out which *System Promoted Notification Area* you're getting the handle of? There may be two of them. One, child of `TrayNotifyWnd::SysPager`, is the one you want. The other, direct child of `TrayNotifyWnd` is not. – Jimi Apr 16 '19 at 13:34
  • @Jimi same as in the 'GetSystemTrayHandle' function from this question: https://stackoverflow.com/questions/5174120/c-sharp-how-to-determine-if-hwnd-is-in-tray-icons is this the right handle to which I must invoke a paint? – ElektroStudios Apr 16 '19 at 14:37
  • 1
    Yes, that's the one. The `GetSystemTrayHandle()` method (in the question) seaches for a child of `SysPager`. That `ToolbarWindow32` is the right one. You'll have a hard time to interact with the Shell, though. Those interfaces are not public, AFAIK. – Jimi Apr 16 '19 at 14:44

1 Answers1

0

After calling the InvalidateRect function I noticed that the notification area window is redrawn (because the window flicks for a moment), so redrawing the window seems not a valid solution to solve this issue...

However, in the next thread I found a solution:

The thing is that in order to "properly" refresh the size of the notification area to remove any empty space from previously deleted buttons, I just need to send WM_LBUTTONDOWN and WM_LBUTTONUP messages through the SendMessage function.

These window messages must be sent two times (at least for Windows 10) to the ToolbarWindow32 window following the next order: WM_LBUTTONDOWN, WM_LBUTTONUP, WM_LBUTTONDOWN, WM_LBUTTONUP. This is to reproduce two single clicks (not a double click) in the first button inside the system-tray, which is what I manually needed to do before applying this automated solution. After sending the messages, the window becomes "auto-sized" properly.

The only aesthetic problem would be if the first button is a button from an application that performs some undesired action when doing a single click on its button, but this is not typical to see. Typically the user only can do a double-click to restore the window from the button on system-tray, or do right click to open its context menu, but nothing should happens for doing a single click on a button... if the developer didn't programmed anything to happen.

Note that this methodology also works when there is the up arrow that contains "hidden" buttons.

ElektroStudios
  • 19,105
  • 33
  • 200
  • 417