У меня есть приложение для Windows, написанное на C (использующее gcc / MinGW), которое работает довольно хорошо, за исключением нескольких проблем с пользовательским интерфейсом. Во-первых, я просто не могу обновить индикатор выполнения из потока. На самом деле, я, вероятно, не могу обновить ЛЮБОЙ интерфейс для пользовательского интерфейса.
По сути, у меня есть порожденный поток, который выполняет некоторую обработку, и из этого потока я пытаюсь обновить индикатор выполнения в основном потоке. Я попробовал это с помощью PostMessage () для основного hwnd, но не повезло, хотя я могу делать другие вещи, такие как открытые окна сообщений. Однако неясно, вызывается ли окно сообщения в потоке или в основном потоке.
Вот код:
// in header/globally accessible
HWND wnd; // main application window
HWND progress_bar; //progress bar
typedef struct { //to pass to thread
DWORD mainThreadId;
HWND mainHwnd;
char *filename;
} THREADSTUFF;
//callback function
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){
switch (msg){
case WM_CREATE:{
// create progress bar
progress_bar = CreateWindowEx(
0,
PROGRESS_CLASS,
(LPCTSTR) NULL,
WS_CHILD | WS_VISIBLE,
79,164,455,15,
hwnd,
(HMENU)20,
NULL,
NULL);
SendMessage(progress_bar, PBM_SETSTEP, 1, 0 );
SendMessage(progress_bar, PBM_SETPOS, 0, 0 );
//test to make sure it actually works
SendMessage(progress_bar, PBM_STEPIT, 0, 0 ); //works fine
SendMessage(progress_bar, PBM_STEPIT, 0, 0 ); //works fine
SendMessage(progress_bar, PBM_STEPIT, 0, 0 ); //works fine
SendMessage(progress_bar, PBM_STEPIT, 0, 0 ); //works fine
break;
}
case WM_COMMAND: {
if(LOWORD(wParam)==2){ //do some processing in a thread
//struct of stuff I need to pass to thread
THREADSTUFF *threadStuff;
threadStuff = (THREADSTUFF*)malloc(sizeof(*threadStuff));
threadStuff->mainThreadId = GetCurrentThreadId();
threadStuff->mainHwnd = hwnd;
threadStuff->filename = (void*)&filename;
hThread1 = CreateThread(NULL,0,convertFile (LPVOID)threadStuff,0,NULL);
}else if(LOWORD(wParam)==5){ //update progress bar
MessageBox(hwnd,"I got a message!", "Message", MB_OK | MB_ICONINFORMATION);
PostMessage(progress_bar,PBM_STEPIT,0,0);
}
break;
}
}
}
Все это работает нормально. Проблема в теме:
DWORD WINAPI convertFile(LPVOID params){
//get passed params, this works perfectly fine
THREADSTUFF *tData = (THREADSTUFF*)params;
MessageBox(tData->mainHwnd,tData->filename,"File name",MB_OK | MB_ICONINFORMATION); //yep
PostMessage(tData->mainHwnd,WM_COMMAND,5,0); //only shows message
PostThreadMessage(tData->mainThreadId,WM_COMMAND,5,0); //does nothing
}
Когда я говорю «показывает только сообщение», это означает, что функция MessageBox () в обратном вызове работает, но не PostMessage () для обновления позиции индикатора выполнения.
Если я использую PostThreadMessage () для отправки сообщения в цикл сообщений основного потока, я могу перехватить его и запустить MessageBoxes, чтобы он определенно работал. Тем не менее, даже если я пытаюсь обновить индикатор выполнения таким образом. все равно не обновится.
Что мне не хватает?