2012-04-21 1 views
1

Я видел, что это спросило много путей, но никогда не видел фактического рабочего кода.C++ WTL8.1 Как создать окно в новом потоке с контуром сообщения?

Я пробовал это, без сомнения, наивную попытку создать новый поток с новым окном и контуром сообщений. У меня есть функция, которая должна открывать окно & обрабатывать его сообщения и запускаться в средах, где он может быть вызван из приложения без существующего цикла сообщений (и никаких других окон) или обычного цикла сообщений mfc или цикла сообщений WTL. Я видел кое-что о AddMessageLoop и Модулях? но оказалось, что это было для основного приложения. В любом случае там может быть или не быть модуль 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); 
+0

Если это может быть вызван из приложения без окон, вы, вероятно, не сможете создать его с помощью параметра класса Window. –

+0

Итак, этот фрагмент кода, работает ли он? Выглядит хорошо для меня - вы начинаете нить, вы создаете окно там, и вы продолжаете накачивать сообщения. –

ответ

0

Просмотреть комментарии для необходимых изменений. Gotcha # 1 был & Оператор не работает на классах WTL Gotcha # 2, никогда не назвал ваши события. Если вы связываетесь с неизвестными другими объектами, , вероятно, кто-то уже использовал одно и то же имя, и Windows решает, что те же имена означают одно и то же событие, даже если используются несколько вызовов CreateEvent(). No Name, нет «псевдонимов» предположительно разных событий.

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); 
+0

На самом деле нет ничего плохого в том, чтобы именовать события, пока вы включаете GUID, чтобы сделать имя уникальным. – 0xC0000022L

0

SetWindowLongPtr и GetWindowLongPtr, использовать их, чтобы получить к экземпляру из окна прок, а затем установить переменную условие на 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; 
...