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

C++ 为什么MessageBox在我创建的桌面中显示窗口,而AllocConsole在上一个桌面中显示窗口?,c++,winapi,console,C++,Winapi,Console,将线程更改为其他桌面时,使用AllocConsole()创建的新控制台将显示在原始桌面中。消息框和其他创建的窗口会按预期显示在新桌面中,但控制台窗口不会。下面的代码是一个windows应用程序示例,但是不管它是否是控制台应用程序,结果都是一样的 #include <Windows.h> HDESK hDesk; DWORD WINAPI Testing(void *) { SetThreadDesktop(hDesk); AllocConsole(); M

将线程更改为其他桌面时,使用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;
}
#包括
HDESK-HDESK;
DWORD WINAPI测试(void*)
{
SetThreadDesktop(hDesk);
allocsole();
MessageBox(NULL,文本(“测试”),NULL,MB_OK);//这将显示在新桌面上
FreeConsole();
返回0;
}
int-WINAPI WinMain(HINSTANCE-HINSTANCE、HINSTANCE-hPrevInstance、LPSTR-lpCmdLine、int-nShowCmd)
{
hDesk=CreateDesktop(文本(“测试”),NULL,NULL,NULL,GENERIC_ALL,NULL);
交换机桌面(hDesk);
德沃德苏尔;
HANDLE thread=CreateThread(0,0,Testing,0,0,&thr);
WaitForSingleObject(线程,10000);//等待10秒后自动退出。
SwitchDesktop(GetThreadDesktop(GetCurrentThreadId());//返回上一个桌面
CloseDesktop(hDesk);
返回0;
}

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

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

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

int _tmain(int argc, _TCHAR* argv[])
{
Sleep(INFINITE);
return 0;
}
而不是调用AllocConsole,而是使用新启动进程的进程id调用AttachConsole,然后调用GetStdHandle以获得控制台缓冲区的句柄,以便进一步调用WriteConsole


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

我怀疑这种行为是因为控制台窗口是由[csrss.exe]创建和维护的。而不是Windows控制台窗口,考虑一个替代方案,如COSOLe2,或者CygWin中的一个。我怀疑这是因为控制台窗口与进程相关,而不是线程。因此,如果要更改创建控制台窗口的桌面,则必须设置主线程的桌面。这可能还与多个进程能够连接到一个控制台有关。设置主线程的桌面对我来说似乎不起作用。这只是一个假设。可能是控制台窗口始终位于进程启动时处于活动状态的桌面上。这可能是疏忽。很难说。@JimMischel,真的。清楚地表明可能的解决方案不起作用是好的,这样更多的人就不会尝试它而一无所获:)这很奇怪
dwProcessId
包含有效的PID,但是
AllocConsole
失败,根据文档,该进程不存在。@chris您是说AttachConsole吗。可能是有效的pid在AttachConsole调用时没有控制台。是的,我的意思是,谢谢。哦,嘿,
AttachConsole
之前的
Sleep()。我认为
的输出????write
就是我:pYep,就是我去除根并传递一个
char*
而不是
wchar\u t*
。愚蠢的
void*
参数。