【问题标题】:Why does MessageBox show the window in my created desktop, but AllocConsole show it in the previous?为什么MessageBox在我创建的桌面显示窗口,而AllocConsole在前面显示?
【发布时间】:2012-11-15 03:58:22
【问题描述】:

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

#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;
}

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

【问题讨论】:

  • 我怀疑这种行为是因为控制台窗口是由 [csrss.exe] 创建和维护的。考虑使用 Console2 或 Cygwin 中的替代方法,而不是 Windows 控制台窗口。
  • 我怀疑这是因为控制台窗口与进程相关联,而不是与线程相关联。因此,如果要更改创建控制台窗口的桌面,则必须设置主线程的桌面。它也可能与能够附加到单个控制台的多个进程有关。
  • 设置主线程的桌面似乎对我不起作用。
  • 这只是假设。可能是控制台窗口始终位于进程启动时处于活动状态的桌面上。这可能是一个疏忽。很难说。
  • @JimMischel,确实如此。最好明确指出可能的解决方案不起作用,这样更多的人就不会尝试并一无所获:)

标签: c++ winapi console


【解决方案1】:

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

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

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

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

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

【讨论】:

  • 这很奇怪...dwProcessId 包含一个有效的 PID,但 AllocConsole 失败,根据文档,该进程不存在。
  • @chris 你的意思是 AttachConsole。可能是在 AttachConsole 调用时有效的 pid 没有控制台。
  • 是的,我确实是这个意思,谢谢。哦,嘿,Sleep() 之前 AttachConsole 工作。我认为???? Writ 的输出只是我:p
  • 是的,这只是我 derping 并传递了 char * 而不是 wchar_t *。愚蠢的void *参数。
猜你喜欢
  • 2010-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-13
  • 1970-01-01
  • 1970-01-01
  • 2011-09-22
  • 1970-01-01
相关资源
最近更新 更多