Hide A Console C++ Program From Taskbar - c++

I have a little console game that calls another console app. Something like Winamp's many windows (main and playlist). The thing is when I call two for example console windows the programs opened in the taskbar get too many, I don't need to open the windows separately, I want only the main window to stay in the taskbar and when I click on it, it and all its child apps to pop up.
P.S. I am familiar with ShowWindow ( GetConsoleWindow(), SW_HIDE );, but it hides the window as well and I want it to be hidden only from the taskbar.

Thanks to Captain Obvlious and some research, the following code:
ITaskbarList *pTaskList = NULL;
HRESULT initRet = CoInitialize(NULL);
HRESULT createRet = CoCreateInstance( CLSID_TaskbarList,
NULL,
CLSCTX_INPROC_SERVER,
IID_ITaskbarList,
(LPVOID*)&pTaskList );
if(createRet == S_OK)
{
pTaskList->DeleteTab(GetConsoleWindow());
pTaskList->Release();
}
CoUninitialize();
with included ShObjIdl.h works great!
Note: You should get S_OK as a value in initRet and createRet!

The only way I am aware of to accomplish this on a console window is to use the shell interface ITaskbarList.
hr = CoCreateInstance(
CLSID_TaskbarList,
NULL,
CLSCTX_INPROC_SERVER,
IID_ITaskbarList,
reinterpret_cast<void**>(&taskbar));
if(!FAILED(hr))
{
// Remove the icon from the task bar
taskbar->DeleteTab(GetConsoleWindow());
// Release it
taskbar->Release();
}

Related

Name of process for active window in Windows 8/10

The following sample has reliably returned the name of the process that is associated with the active window, but does not work with the newer modern/universal apps because it returns the name of a helper process WWAHost.exe on Windows 8 and ApplicationFrameHost.exe on Windows 10 rather than the name of the app.
HWND active_window = GetForegroundWindow();
GetWindowThreadProcessId(active_window, &active_process_id);
HANDLE active_process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, active_process_id);
GetProcessImageFileName(active_process, image_name, 512);
With Windows 10 the ApplicationFrameHost.exe is the process that creates the window handles and is what gets returned by GetWindowThreadProcessId(), is there another Win32 API that can be used to get the active process of universal app that is active?
Also tried using GetApplicationUserModelId() and GetPackageFullName() with no success as they return APPMODEL_ERROR_NO_APPLICATION and APPMODEL_ERROR_NO_PACKAGE respectively because the active_process handle is just the helper process and not the process of the active application.
Any other APIs to use to get the process name of a Modern/Universal application given the hwnd of the window, or otherwise figure out the process name of the universal app is active.
Thanks in advance!
Be sure to use the Spy++ utility when you want to reverse-engineer something like this. Included with Visual Studio, you need the 64-bit version in Common7\Tools\spyxx_amd64.exe. Use Search > Find Window and drag the bullseye to a UWP app, like Weather.
You'll see the window you'll find with GetForegroundWindow(), it has at least 3 child windows:
ApplicationFrameTitleBarWindow
ApplicationFrameInputSinkWindow
Windows.Core.UI.CoreWindow, that's the host window for the UWP app and the one you are interested in. Right-click it and select Properties, Process tab, click the Process ID. That takes you to the real owner process you want to know.
So you just need to make an extra step from the code you already have, you just have to enumerate the child windows and look for one with a different owner process. Some C code, trying to make it as universal as possible without making too many assumptions and not enough error checking:
#include <stdio.h>
#include <Windows.h>
typedef struct {
DWORD ownerpid;
DWORD childpid;
} windowinfo;
BOOL CALLBACK EnumChildWindowsCallback(HWND hWnd, LPARAM lp) {
windowinfo* info = (windowinfo*)lp;
DWORD pid = 0;
GetWindowThreadProcessId(hWnd, &pid);
if (pid != info->ownerpid) info->childpid = pid;
return TRUE;
}
int main()
{
Sleep(2000);
HWND active_window = GetForegroundWindow();
windowinfo info = { 0 };
GetWindowThreadProcessId(active_window, &info.ownerpid);
info.childpid = info.ownerpid;
EnumChildWindows(active_window, EnumChildWindowsCallback, (LPARAM)&info);
HANDLE active_process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, info.childpid);
WCHAR image_name[MAX_PATH] = { 0 };
DWORD bufsize = MAX_PATH;
QueryFullProcessImageName(active_process, 0, image_name, &bufsize);
wprintf(L"%s\n", image_name);
CloseHandle(active_process);
return 0;
}
Output on the Weather program:
C:\Program Files\WindowsApps\Microsoft.BingWeather_4.5.168.0_x86__8wekyb3d8bbwe\
Microsoft.Msn.Weather.exe
Here is a small console app application that continuously (so you can test it easily selecting different windows on your desktop) display information about the current foreground window process and store process, if any.
Apps can have a window hierarchy that can span multiple processes. What I do here is search the first sub window that has the 'Windows.UI.Core.CoreWindow' class name.
This app uses the UIAutomation API (and also smart pointers, smart BSTRs and smart VARIANTs provided by the #import directive). I suppose you can do the same with standard Windows SDK, but I find the UIAutomation used this way quite elegant.
#include "stdafx.h"
#import "UIAutomationCore.dll"
using namespace UIAutomationClient;
int main()
{
// initialize COM, needed for UIA
CoInitialize(NULL);
// initialize main UIA class
IUIAutomationPtr pUIA(__uuidof(CUIAutomation));
do
{
// get the Automation element for the foreground window
IUIAutomationElementPtr foregroundWindow = pUIA->ElementFromHandle(GetForegroundWindow());
wprintf(L"pid:%i\n", foregroundWindow->CurrentProcessId);
// prepare a [class name = 'Windows.UI.Core.CoreWindow'] condition
_variant_t prop = L"Windows.UI.Core.CoreWindow";
IUIAutomationConditionPtr condition = pUIA->CreatePropertyCondition(UIA_ClassNamePropertyId, prop);
// get the first element (window hopefully) that satisfies this condition
IUIAutomationElementPtr coreWindow = foregroundWindow->FindFirst(TreeScope::TreeScope_Children, condition);
if (coreWindow)
{
// get the process id property for that window
wprintf(L"store pid:%i\n", coreWindow->CurrentProcessId);
}
Sleep(1000);
} while (TRUE);
cleanup:
CoUninitialize();
return 0;
}
Does taking snapshot of running processes and pulling the name out of it by comparing process id not work?
Full reference here:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms686837(v=vs.85).aspx
But you fix the snapshot with CreateToolhelp32Snapshot().
Or from WTSEnumerateProcesses() and surrounding API?
Pretty sure it worked in Win 8. Is it broken in 10?
Starting from Win10 Anniversary Update ApplicationFrameHost child window return anything but UWP application. It worked only in Tablet mode after relogon.

CFileDialog freezes when launched from Modeless Dialog

I'm attempting to call CFileDialog to allow the user to select a file.
My program is a MFC application and I am using VS2005.
Here is my problem:
I have main View that creates a modeless dialog box. In this dialog box I have a menu item that makes a simple CFileDialog call:
CFileDialog dlgFile(true);
dlgFile.DoModal();
But the program always hangs on the DoModal. The program does not respond to commands and Task manager says it has stopped responding.
Other interesting pieces of information:
This has only been observed on Windows 8, Windows 7 machines seem to be unaffected.
I created a new project with the same basic View->modeless dialog->CFileDialog scheme and it worked just fine.
When I make a call to MessageBox, it appears behind the dialog box (I have to hit alt to get it up front), but the program is still responsive.
If I make the same CFileDialog call in the main View, it pops up without any problem.
Another annoying issue that may or may not be related to this: When the CFileDialog call is working (on Win 7), selecting "computer" in the browse window shows a blank white screen (Everything else works fine).
The closest questions I could find is this: Why does CFileDialog::DoModal() Hang?
However, I don't use threads (At least I'm 95% sure I don't, this isn't just my project). Is my project automatically being threaded? If so, how can I make sure that isn't causing me problems?
I've the same problem in VS2008.
Try to set to false the last parameter in CFileDialog constructor (bVistaStyle)
dlgFile.DoModal() calls run modal routine, it enables/disables and refocus windows, maybe that's the problem. You can try GetOpenFileName instead:
void CModeless::foo()
{
//EnableWindow(0);
OPENFILENAME ofn = { 0 };
char buf[300];
memset(buf, 0, 300);
ofn.lpstrFile = buf;
ofn.nMaxFile = 300;
ofn.lStructSize = sizeof(OPENFILENAME);
//ofn.hwndOwner = AfxGetApp()->m_pMainWnd->m_hWnd;
GetOpenFileName(&ofn);
//EnableWindow(1);
}
If there is no bug, then uncomment EnableWindow and ofn.hwndOwner, try again. You can also try this method:
void CModeless::foo()
{
CWnd *wnd = GetParent(); //or AfxGetApp()->m_pMainWnd
EnableWindow(0);
CFileDialog dlg(TRUE, 0, 0, 0, 0, wnd, 0, 1);
dlg.DoModal();
EnableWindow(1);
MSG msg;
while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
if (!AfxGetApp()->PumpMessage())
break;
SetFocus();
}
My CDialogEx based dialog was unable to show the CFileDialog. From within my CDocument, everything worked fine.
I found, that my dialog had a custom control, that was derived from CStatic and overrode the virtual WindowProc( ).
After commenting the WindowProc, the CFileDialog showed as usual.
The issue is only for the "m_bVistaStyle" CFileDialog, and the freeze occours in IFileDialog->Show().

Order at which my icon is added to the system tray?

I'm coding an MFC/C++ app that places several icons on the system tray. (The number of icons is controlled by a user and can reach up to 10 or so if the user wishes to do so -- each per certain function of the app.)
My question is, can I control the order at which those icons are placed on the tray?
What happens now is that when I call
Shell_NotifyIcon(NIM_ADD, &nid);
in a certain order, the order at which icons appear on the actual tray is different.
The task tray is just a ToolBar32 control. You can get a handle to it with something like this:
HWND hWnd = ::FindWindow(_T("Shell_TrayWnd"), NULL);
if(hWnd)
{
hWnd = ::FindWindowEx(hWnd,NULL,_T("TrayNotifyWnd"), NULL);
if(hWnd)
{
hWnd = ::FindWindowEx(hWnd,NULL,_T("SysPager"), NULL);
if(hWnd)
{
hWnd = ::FindWindowEx(hWnd, NULL,_T("ToolbarWindow32"), NULL);
}
}
}
Then you should be able to call this:
::SendMessage(hWnd, TB_MOVEBUTTON, nFrom, nTo);

IAxWinHostWindow CreateControl returns E_NOINTERFACE when trying to host WMP within a CAxWindow

I am trying to embed a WMP control inside my Win32 App.
I have followed the example code here: Hosting the Windows Media Player Control in a Windows Application
However when I step through this example, the line:
hr = spHost->CreateControl(CComBSTR(_T("{6BF52A52-394A-11d3-B153-00C04F79FAA6}")), m_wndView, 0);
returns E_NOINTERFACE;
The line:
hr = m_wndView.QueryHost(&spHost);
succeeds and seems to populate spHost correctly.
Here's the code:
CAxWindow m_wndView;
CComPtr<IObjectWithSite> spHostObject;
CComPtr<IAxWinHostWindow> spHost;
CComBSTR classID = __uuidof(WindowsMediaPlayer);
RECT rcClient = { 0, 0, 560, 335 };
m_wndView.Create(m_hWnd, rcClient, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE);
hr = m_wndView.QueryHost(&spHost);
if( SUCCEEDED(hr) )
{
hr = spHost->CreateControl(classID, m_wndView, 0); //E_NOINTERFACE
}
hr = m_wndView.QueryControl(&m_spPlayer); //E_FAIL
Can anybody give me any idea as to why this happens?
Thanks.
Edit: The line that actually fails is this one inside the ActivateAx() function:
hr = m_spOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, spClientSite, 0, m_hWnd, &m_rcPos);
If anyone could shed any more light on this that would be great.
Edit2: Just noticed I get this spammed in my output window whilst i'm stepping through this code:
"An outgoing call cannot be made since the application is dispatching an input-synchronous call"
Any Ideas?
The code is right and works as is, and as suggested on MSDN page.
An problem exactly as described might come up if you your UI window is in MTA apartment, that is the thread you are running on was initialized with CoInitializeEx(NULL, COINIT_MULTITHREADED).
What is happening then, your WMP is instantiated on a side STA thread and its interface marshaled into your thread/apartment. Not every required interface can be transferred this way, so once you keep on initializing it some of the mandatory interfaces is missing...
WMP is using "Apartment" threading model, use it on STA threads.

Retrieve Handle to Windows Explorer's Address bar Edit Control

I need to retrieve full path of most active Windows Explorer instance.
So I have got the handle to Explorer.exe by making a call to
HWND l_pExplorerhwnd = ::GetForegroundWindow();
Using this handle retrieved, I need to retrieve it's Address bar edit control.
I have used Spy++ and got the class name of edit control as ToolbarWindow32
Now, I have tried to find the window using FindWindowEx using the following code snippet. But I am unable to retrieve it. Please help
HWND l_pExplorerhwnd = ::GetForegroundWindow();
TCHAR l_szTempName[MAX_PATH];
if(l_pExplorerhwnd)
{
::GetWindowModuleFileName(l_pExplorerhwnd, l_szTempName, MAX_PATH);
MessageBox(0, l_szTempName, 0, 0);
if(::FindWindowEx(l_pExplorerhwnd, NULL, L"ToolbarWindow32", NULL))
{
::GetWindowText(::FindWindowEx(l_pExplorerhwnd, NULL, L"ToolbarWindow32", NULL), l_szTempName, MAX_PATH);
MessageBox(0, l_szTempName, 0, 0);
}
else
{
MessageBox(0, L"Error Error ", 0, 0);
}
}
else
{
MessageBox(0, L"Error Error Error", 0, 0);
}
To answer your question directly, FindWindowEx works on direct children of the parent window, not descendants. Hence, you would need to traverse down the children one by one:
CabinetWClass
WorkerW
ReBarWindow32
Address Band Root
msctls_progress32
Breadcrumb Parent
ToolbarWindow32
Note that this hierarchy is only what it is on my system right now. As mentioned by Tom Whittock, it would be very bad practice to use this. You have no idea whether the window hierarchy could change across updates, or even by design at runtime.
One more comment about your code. Since you are using TCHAR mappings (even though there is usually no reason to use it now unless you are intending to support Win98-), your string literals should be _T("") instead of L"".