【问题标题】:C++ WTL8.1 How to create a window in a new thread with message loop?C++ WTL8.1 如何在带有消息循环的新线程中创建一个窗口?
【发布时间】:2012-05-02 13:54:06
【问题描述】:

我看到这个问了很多方法,但从未见过实际工作的代码片段。

毫无疑问,我尝试了这种天真的尝试来创建一个带有新窗口和消息循环的新线程。我有一个必须打开一个窗口并处理其消息的函数,并且必须在可以从没有现有消息循环(也没有其他窗口)或通常的 mfc 消息循环或 WTL 消息循环的应用程序调用的环境中运行。我看到了一些关于 AddMessageLoop 和 Modules 的东西?但它似乎是针对主要应用程序的。无论如何,那里可能有也可能没有 WTL 模块。需要一个带有基本消息循环的独立窗口。传入一个窗口尚未打开的 WTL 类,因此窗口在与循环相同的线程中打开。类对象是否也必须在新线程中创建?

// does not work.... 
static DWORD WINAPI MyRunThread(__in LPVOID lpParameter)
{
CMessageLoop theLoop;
WTLsubclass *nav = (WTLsubclass *) lpParameter;

nav->CreateWindow(); 
int nRet = theLoop.Run();

return nRet;
}

CreateThread(0,0,MyRunThread,&nav,0,0);

【问题讨论】:

  • 如果它可以从没有窗口的应用程序中调用,您可能无法使用 Window 类参数创建它。
  • 那么你的这个代码sn-p,有用吗?对我来说看起来不错 - 您启动一个线程,在那里创建窗口并不断发送消息。

标签: c++ windows multithreading wtl


【解决方案1】:

请参阅 cmets 了解所需的更改。 问题 #1 是 & 运算符不适用于 WTL 类 Gotcha #2,永远不要为你的事件命名。如果您与未知的其他对象链接, 可能有人已经使用了相同的名称,并且 Windows 决定相同的名称表示相同的事件,即使使用了多个 CreateEvent() 调用。无名, 没有所谓的不同事件的“别名”。

Non-Gotcha,如果您不希望“主”消息处理程序处理您的消息,则不需要 _Module 或“告诉”有关消息循环的任何内容。如果你想独立 带有独立循环的窗口,见下文。

================================================ ====

static DWORD WINAPI MyRunThread(__in LPVOID lpParameter)
{
CMessageLoop theLoop;
WTLsubclass *nav = (WTLsubclass *) lpParameter;

nav->CreateWindow(); 
SetEvent(WindowCreatedEvent) // signal event HANDLE type for worker thread

int nRet = theLoop.Run();

return nRet;
}

//CreateThread(0,0,MyRunThread,&nav,0,0); // & wont work on WTL class objects
// some genius overloaded the & operator on WTL class objects, just because in C++ you can

//Workaround to get address of WTL class object
CLASSnav nav[1];
CLASSnav *pnav = nav; // because arrays is address of first element.
CreateThread(0,0,MyRunThread,pnav,0,0);

【讨论】:

  • 其实命名事件没有任何问题,只要你包含一个 GUID 使名称唯一。
【解决方案2】:

SetWindowLongPtrGetWindowLongPtr,使用它们从窗口 proc 中访问您的实例,然后在 WM_ACTIVATE 上设置条件变量。

在您的客户端代码中:

// Create window, this setups the window and runs a message loop, its guts are ran in a different thread
createwindow();
// Wait to be shown, this presumes the existence of a mutext (m) and a condition_variable (cv) in your instance
std::unique_lock<std::mutex> lock(m);
cv.wait_for(lock, std::chrono::milliseconds(800));

在窗口设置和创建期间,这可以在您的线程进程中:

// Create window (RegisterClass, CreateWindow, etc)
...
SetWindowLongPtr(hwnd, GWLP_USERDATA, /*your instance*/ ...);   
ShowWindow(hwnd, ...);
...
// Pump

在你的窗口进程中:

...
switch(msg)
{
    case WM_ACTIVATE:
    {
        your_instance* inst = (your_instance*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
        inst->cv->notify_one();
    }
    break;
...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-14
    • 1970-01-01
    相关资源
    最近更新 更多