0

I want to be able to remove my Win32 application's button from the Taskbar. I also want to be able to add it back later. How can this be done? I found this approach, but it is written in Delphi, and I'm using C++ instead.

I tried modifying this code by changing one line of Remy's code from:

SetWindowLong(hWnd, GWL_EXSTYLE, Style | WS_EX_APPWINDOW); 

to

SetWindowLong(hWnd, GWL_EXSTYLE, Style | WS_EX_TOOLWINDOW);

But this doesn't work, the button is still on the Taskbar.

UPDATE: the code I'm using (that originated from Remy of course):

void __fastcall TForm1::CreateHandle()   // this is code from Remy i added to help me trap screen lock
{
 TForm::CreateHandle();

 HWND hWnd = Fmx::Platform::Win::FormToHWND(this);
 if (SetWindowSubclass(hWnd, &SubclassWndProc, 1, reinterpret_cast<DWORD_PTR>(this)))
 {
    MonitoringWTS = WTSRegisterSessionNotification(hWnd, NOTIFY_FOR_THIS_SESSION);
    if (!MonitoringWTS)
        RemoveWindowSubclass(hWnd, &SubclassWndProc, 1);
 }
 else {
    MonitoringWTS = false;
 }

 if (hWnd != NULL)   // this code added from https://stackoverflow.com/questions/28929163/how-to-show-a-secondary-form-on-taskbar-using-fmx-c
 {
 LONG Style = GetWindowLong(hWnd, GWL_EXSTYLE); // <-- don't forget this step!
 SetWindowLong(hWnd, GWL_EXSTYLE, Style | WS_EX_APPWINDOW);
 }
}

Using C++Builder 10.2 Version 25.0.31059.3231.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
relayman357
  • 793
  • 1
  • 6
  • 30
  • I tried setting BorderStyle to those options but the icon still shows up on the taskbar (Windows 10). I tried the corrected `SetWindowLong` but doesn't remove the icon from taskbar either. I'll post my code as UPDATE 1 above. – relayman357 Dec 13 '18 at 20:12
  • 1
    Which version of C++Builder are you using? Please include that in your update. It makes a big difference, as different versions handle FMX windows differently. – Remy Lebeau Dec 13 '18 at 20:17

1 Answers1

1

It is not enough to just add the WS_EX_TOOLWINDOW style if you also leave behind the default WS_EX_APPWINDOW style in place. Try using this instead:

LONG_PTR ExStyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE);
SetWindowLongPtr(hWnd, GWL_EXSTYLE, (Style & ~WS_EX_APPWINDOW) | WS_EX_TOOLWINDOW);

Though, the easier way to make a TForm behave like a tool window is to simply set its BorderStyle property to bsToolWindow or bsSizeToolWin.

However, note that in XE7+, you should use ApplicationHWND() to get the HWND that is actually on the Taskbar, as it may be different than the TForm's window. This was even pointed out in an answer to the question you dismissed just because it was written in Delphi instead of C++. The relevant function calls don't change, just the code syntax.

Try this:

#include <FMX.Platform.Win.hpp>
#include <Winapi.Windows.hpp>

void HideAppOnTaskbar()
{
    HWND hAppWnd = Fmx::Platform::Win::ApplicationHWND();
    ShowWindow(hAppWnd, SW_HIDE);
    LONG_PTR ExStyle = GetWindowLongPtr(hAppWnd, GWL_EXSTYLE);
    SetWindowLongPtr(hAppWnd, GWL_EXSTYLE, (ExStyle & ~WS_EX_APPWINDOW) | WS_EX_TOOLWINDOW);
    //ShowWindow(hAppWnd, SW_SHOW);
}

void ShowAppOnTaskbar()
{
    HWND hAppWnd = Fmx::Platform::Win::ApplicationHWND();
    ShowWindow(hAppWnd, SW_HIDE);
    LONG_PTR ExStyle = GetWindowLongPtr(hAppWnd, GWL_EXSTYLE);
    SetWindowLongPtr(hAppWnd, GWL_EXSTYLE, (ExStyle & ~WS_EX_TOOLWINDOW) | WS_EX_APPWINDOW);
    ShowWindow(hAppWnd, SW_SHOW);
}

void __fastcall TForm1::CreateHandle()
{
    //...
    HideAppOnTaskbar(); // or ShowAppOnTaskbar(), as needed
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Works perfectly, thank you. I also tried changing BorderStyle to every option and all still result in icon still on taskbar. I tried that with a new FMX app to and same result (always icon on taskbar regardless of BorderStyle setting). I didn't know what to do with the Delphi code because i'm a fish out of water. – relayman357 Dec 13 '18 at 20:39
  • That is fantastic! – relayman357 Dec 13 '18 at 20:42
  • Remy - i load some user preferences from an SQLite db in the FormShow event. I'd like to store a variable to control "hide" or "show" of the taskbar button. It looks like the CreateHandle fires before the FormShow. I tried my SQLite code in the CreateHandle function but it is too early I think and I get firedac errors. I guess because the form isn't constructed and the firedac components aren't ready. I'm thinking i may have to save that one preference (to show or hide taskbar button) to a text file. – relayman357 Dec 14 '18 at 02:57
  • 1
    @relayman357 try overriding the Form's `Loaded()` method, which is called after the DFM is done being streamed in. – Remy Lebeau Dec 14 '18 at 05:20
  • This is beyond me so i took easy path and create a text file whose presence tracks the preference to hide or show the form button on taskbar. Then in CreateHandle i simply test for the existence of that file (if present i hide). – relayman357 Dec 14 '18 at 18:00
  • 1
    @relayman357 using the Registry instead would make more sense than using a file. – Remy Lebeau Dec 14 '18 at 19:56
  • As usual you are correct. I found [this nice example](http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/Registry_TRegistry.html) of doing just that. Thank you. – relayman357 Dec 14 '18 at 20:21