Remove window from taskbar on Windows 10 - c++

I want to remove window from taskbar on Windows 10 with multiple desktops.
For Windows 8.1 i used ITaskbarList::DeleteTab and it works excellent.
For Windows 10 this method hides Windows from taskbar too, but after it i see this window on all desktops. I want to see this window only on one desktop.
Does anyone know the method to hide window from task bar in Windows 10 and stay this window on one desktop?
Below you can see, what i meant under "hide window from task bar in Windows 10":

In my understanding, borne out by my empirical tests, the windows that appear in the taskbar previews are exactly the same windows that would ordinarily appear in the taskbar. A long time ago, say in Windows 2000, each of an application's eligible windows would just appear as buttons on the taskbar. Starting in Windows XP, taskbar grouping became an option, so that all eligible windows from a single application could be grouped together and appear as a single button on the taskbar. Then, in Windows Vista, it became possible to display previews of these open windows when you hovered over the corresponding taskbar button. Neither Windows 8 nor Windows 10 changed that fundamental rule; they only changed the appearance of the previews.
As such, we can refer back to the MSDN documentation for the rules about which windows appear on the taskbar:
The Shell creates a button on the taskbar whenever an application creates a window that isn't owned. To ensure that the window button is placed on the taskbar, create an unowned window with the WS_EX_APPWINDOW extended style. To prevent the window button from being placed on the taskbar, create the unowned window with the WS_EX_TOOLWINDOW extended style. As an alternative, you can create a hidden window and make this hidden window the owner of your visible window.
Raymond Chen has summarized these rules more precisely here. Quoting him:
There are some basic rules on which windows go into the taskbar. In short:
If the WS_EX_APPWINDOW extended style is set, then it will show (when visible).
If the window is a top-level unowned window, then it will show (when visible).
Otherwise it doesn't show.
(Though the ITaskbarList interface muddies this up a bit.)
You were muddying it up before, calling ITaskbarList::DeleteTab. That is not necessary. To ensure that a window does not appear in the taskbar, just apply the converse of the rules governing when a window does appear in the taskbar.
If you have a top-level unowned window, it will be shown in the taskbar unless you remove the WS_EX_APPWINDOW extended window style. If you have an owned window, then it will not be shown in the taskbar unless the WS_EX_APPWINDOW extended window style is set to force it there.
So if you have the WS_EX_APPWINDOW extended window style set, you should remove it. That is forcing the window to be displayed in the taskbar.
Otherwise, you should set an owner for your window. For example, make the second window be owned by the first.

TL;DR:
Remove both WS_EX_APPWINDOW and WS_EX_TOOLWINDOW from the extended style.
Set an owner for the window.
Example:
Removing flags from the extended style:
SetWindowLong(myHWND, GWL_EXSTYLE,
GetWindowLong(myHWND, GWL_EXSTYLE) & ~WS_EX_APPWINDOW & ~WS_EX_TOOLWINDOW);
Setting an owner:
SetWindowLongPtr(myHWND, GWLP_HWNDPARENT, myOwnerHWND);
Full explanation:
Despite Cody's answer being great, it does not quite answer the exact question.
The exact question is: "How to display a window that does not appear in the taskbar, yet appears only on one virtual desktop?
As Cody explained, there are several ways to remove the taskbar button for a window. However, there is only one way among them that makes it display on only one virtual desktop at the same time.
If you include the flag WS_EX_APPWINDOW in your extended style, it will force the window to show in the taskbar. That's why it must be cleared in this case.
If you include the flag WS_EX_TOOLWINDOW in your extended style, it will force the window not to show in the taskbar, but will force the window to be shown on all virtual desktops. Thus it's not an option either here.
Finally, if your window has neither flags, it will show in the taskbar if and only if it does not have an owner. Either way, it will not force itself on all virtual desktops. Hence, the solution is to have neither flags but to set an owner.

Add WS_EX_NOACTIVATE to the ex styles of the window.
https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles
A top-level window created with this style does not become the
foreground window when the user clicks it. The system does not bring
this window to the foreground when the user minimizes or closes the
foreground window. The window should not be activated through
programmatic access or via keyboard navigation by accessible
technology, such as Narrator. To activate the window, use the
SetActiveWindow or SetForegroundWindow function. The window does not
appear on the taskbar by default. To force the window to appear on the
taskbar, use the WS_EX_APPWINDOW style.

Related

Win32: Is it possible to show the window but to hide it from taskbar?

If I have an win32 application with several windows, is it possible to show a window but hide the window icon in the taskbar?
I have tried creating the window with WS_EX_TOOLWINDOW and WS_EX_APPWINDOW.
You have a few options:
Tool windows do not have taskbar buttons. Create a tool window by including the WS_EX_TOOLWINDOW extended window style.
Owned windows without the WS_EX_APPWINDOW extended style do not have taskbar buttons.
Hidden windows do not have taskbar buttons.
Option 1 is simple enough. If you don't want to use a tool window, use a combination of 2 and 3. Create a hidden unowned window that is the owner of your main window.

Fullscreen mode for ActiveX control

I tried to implement a switch-to-fullscreen mode for an ActiveX control. This currently works by removing and hiding the parent window and changing my control's placement and position.
However, I have a problem with switching between applications while the control is in fullscreen mode. If I switch to another application and then click on my window area (not in the taskbar), it seems to not be activated. You can see in the taskbar, that another application still has the highlight and on the main screen, my window is partly hidden behind the taskbar unless it has the focus.
I process the WM_LBUTTONDOWN window message to detect if my window is clicked. And I already tried to call the following WINAPI functions:
::ShowWindow(m_hWnd, SW_RESTORE);
::SwitchToThisWindow(m_hWnd, FALSE);
::SetForegroundWindow(m_hWnd);
::SetActiveWindow(m_hWnd);
::SetFocus(m_hWnd);
::BringWindowToTop(m_hWnd);
::SetWindowPos(m_hWnd, HWND_TOP, m_monitorInfo.rcMonitor.left, m_monitorInfo.rcMonitor.top, m_monitorInfo.rcMonitor.right, m_monitorInfo.rcMonitor.bottom, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW); // SWP_NOACTIVATE, SWP_NOOWNERZORDER
I also tried to use ::SetWindowLongW(m_hWnd, GWL_STYLE, WS_VISIBLE); which surprisingly gave my window the focus back. But it then suddenly disappeared when trying to switch back from fullscreen mode again.
I have no idea why there are so many different functions that for me seem all to do roughly the same. But it doesn't matter as none of them worked anyway.
What is the/one correct way to behave my control correctly?
Windows might be getting a bit confused because you're filling the screen with a child window, but you want it to behave like a top-level (overlapped) window. The host application is probably not getting activated because you've hidden its window.
You might do better to create a new top-level full-screen window for full-screen mode. If this is owned by the top-level window that (ultimately) hosts your control then your new window will always be above it, so you don't need to hide the existing window. Activation should just work. In short, you want your window to behave like a pop-up modal dialog.
Adobe's flash player seems to do something similar. Full-screen playback is in a window of class ShockwaveFlashFullScreen.

Needed: A popup window without a taskbar icon

I am designing a UI engine that needs to render into popup (WS_POPUP) windows. As these windows cannot be children of other windows, each instance is given its own taskbar icon.
I need a way to prevent the taskbar icons from appearing for certain windows that are created as "dialogs". I cannot use an OS-provided dialog because they all have frames (and I can't figure out how to render into them) or a tool-created custom dialog (which seem to require the CLR).
I am not an expert with the windows API and I feel that I have missed something obvious...
Also: Anything involving CLI/CLR is not an option.
EDIT:
The WS_EX_NOACTIVATE style can be used for this purpose as well, though the activation behavior would need to be emulated by the program.
If you set the WS_EX_TOOLWINDOW extended style for your window, it won't be shown in the task bar or Alt+Tab list. This does cause the window to be rendered slightly differently, however (thinking floating tool palette).

flicker free tab control with WS_EX_COMPOSITED

I have a VS2008 C++ application for Windows XP SP3 developed using WTL 8.1. My application contains a tab control that flickers when the application border is resized.
My window hierarchy looks like this:
CFrameWindowImpl CMainFrm
|-CSplitterWindow Splitter
|-CTabView Configuration Tabs
| |-CDialogImpl Configuration View 1
| |-CDialogImpl Configuration View 2
| |-CDialogImpl Configuration View 3
|-CDialogImpl Control View
The solution I'm trying is to make the CFrameWindowImpl derived class use the WS_EX_COMPOSITED style and all windows beneath it use the WS_EX_TRANSPARENT style. Unfortunately, this makes the tab control buttons show as an empty black bar and the controls of any Configuration View to not show at all.
If I remove the WS_EX_COMPOSITED and WS_EX_TRANSPARENT styles, the form displays properly, but the CTabView and everything beneath it flickers horribly when resized.
What do I need to change to eliminate the flicker and draw the controls properly?
Thanks,
PaulH
Edit:
Got it working. I removed all the WS_EX_TRANSPARENT styles per Mark Ransom's suggestion. I put the WS_EX_COMPOSITED style on only the CTabCtrl (contained within the CTabView). Other controls get double-buffering as needed through WTL::CDoubleBufferImpl<>.
A window flickers because it gets erased before it's drawn. To eliminate this you need to disable erasing of the window entirely and use double buffering - draw the window contents into a bitmap, then copy the bitmap to the window. Because the bitmap contains the entire contents including the background, there's no need to erase anymore.
It looks like WS_EX_COMPOSITED will handle the double buffering automatically, but you still probably need to use a NULL background brush and/or handle the WM_ERASEBKGND message.
Whats not mentioned in MSDN is that the Desktop Window Manager - the component that hooks window painting on Windows Vista and 7 to perform the desktop composition necessary to get the aero glass effect - does NOT implement WS_EX_COMPOSITED.
Which means all the work you put into getting this style to work on XP, is doomed to become irrelevent on Vista or later.
The other problem with WS_EX_COMPOSITED - and why it was an optional style and not a default on XP: The double buffering only picks up painting performed during the BeginPaint / EndPaint block of the parent window. Lots of, even standard controls, perform painting outside of their WM_PAINT handlers, and as a result the backbuffer gets only partially painted.
Sadly, the result is, the only way to "eliminate" flicker in native API apps is to try to minimize it: WS_CLIPCHILDREN and WS_CLIPSIBLINGS can help if you dont have overlapping controls - to ensure that each control's area is painted only once. And ensure that the main dialog does not perform any flood filling in WM_ERASEBKGND
It is not, in my experience, possible to use double-buffering for anything that contains child controls (unless they all fully support WM_PRINT, which most do not).

How do you have a window that has no icon in the tasktray?

I found the windows style WS_EX_TOOLWINDOW but this changes the title bar. Is there a way to not have the tasktray icon but keep the normal window titlebar?
You usually do want to do this if you have added an alternate means to restore the window - for example placing an icon in the notification tray.
The usual way of ensuring the taskbar does not display your window is to create it with a hidden parent window. Whenever a window has a parent, the parent window is used to create the button - hidden windows are not shown on the taskbar.
Also, WS_EX_APPWINDOW should be removed as that performs the opposite hint to the shell and forces the window onto the taskbar even if it would otherwise not have been shown.