为什么MessageBox在我创建的桌面中显示窗口,而AllocConsole在上一个桌面中显示它

Why does MessageBox show the window in my created desktop, but AllocConsole show it in the previous?

本文关键字:显示 桌面 AllocConsole 上一个 MessageBox 创建 为什么 窗口      更新时间:2023-10-16

当线程更改为不同的桌面时,使用AllocConsole()创建的新控制台将出现在原始桌面中。创建的消息框和其他窗口会如预期的那样出现在新桌面中,但控制台窗口不会。下面的代码是一个windows应用程序示例,但无论它是否是控制台应用程序,结果都是一样的。

#include <Windows.h>
HDESK hDesk;
DWORD WINAPI Testing(void *)
{
SetThreadDesktop(hDesk);
AllocConsole();
MessageBox(NULL, TEXT("Test"), NULL, MB_OK); //This will show on the new desktop
FreeConsole();
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
hDesk=CreateDesktop(TEXT("Testing"),NULL,NULL,NULL,GENERIC_ALL,NULL);
SwitchDesktop(hDesk);
DWORD thr;
HANDLE thread = CreateThread (0, 0, Testing, 0, 0, &thr);
WaitForSingleObject (thread, 10000); //Wait 10 seconds before automatically exiting.
SwitchDesktop(GetThreadDesktop(GetCurrentThreadId())); //Return to previous desktop
CloseDesktop(hDesk);
return 0;
}

如何在第二个桌面上创建控制台窗口?

这种行为是可以理解的,因为连接到进程的一个控制台由该进程的所有线程共享,将该控制台放在启动进程的桌面上是有意义的,而不是在连接到不同桌面的线程分配和释放控制台时,将控制台从桌面动态移动到桌面。如果允许控制台窗口的这种移动,那么当进程之间共享控制台时,行为将更难理解。

为了回答如何与不同桌面上的控制台关联的问题,我建议在目标桌面上启动一个空白的控制台应用程序窗口,其主要职责是保持控制台窗口的活力。所要做的就是做

int _tmain(int argc, _TCHAR* argv[])
{
Sleep(INFINITE);
return 0;
}

不调用AllocConsole,而是使用新启动的进程的进程id调用AttachConsole,然后调用GetStdHandle以获取控制台缓冲区的句柄,以便进一步调用WriteConsole。

要在与进程(最初)连接的目标桌面不同的目标桌面上启动新进程,您必须在STARTUPINFO结构中设置将传递给CreateProcess调用的桌面名称。