Несмотря ни на что, я не могу получить этот индикатор выполнения для обновления из потока - PullRequest
1 голос
/ 21 декабря 2010

У меня есть приложение для 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, чтобы он определенно работал. Тем не менее, даже если я пытаюсь обновить индикатор выполнения таким образом. все равно не обновится.

Что мне не хватает?

Ответы [ 2 ]

1 голос
/ 21 декабря 2010

Я подозреваю, что проблема заключается в вашем цикле сообщений. В любом случае, три вещи:

  • Не думаю, что есть причина отправлять сообщение PBM_STEPIT, просто отправьте его.
  • Проверьте цикл сообщений и убедитесь, что вы не делаете глупостей, таких как GetMessage (& msg, hwnd, ... - всегда передавайте NULL для параметра hwnd для GetMessage, в противном случае отправленные сообщения, предназначенные для других окон, никогда не будут отправлены.
  • WindowProc всегда вызывается окнами в правильном потоке. Таким образом, вы можете отправить SendMessage или PostMessage непосредственно из рабочего потока в элемент управления прогрессом, чтобы обновить его.

Бонус 4-го очка:

  • MessageBox создает окно и запускает свой цикл сообщений в вызывающем потоке. В вашем случае все окна созданы и работают в основном потоке. Но нет реального минуса в отображении окон сообщений в вашем рабочем потоке (кроме того факта, что обработка рабочих потоков будет остановлена, пока окно сообщений не будет закрыто).
1 голос
/ 21 декабря 2010

Из документации MSDN для PBM_STEPIT :

wParam
    Must be zero.
lParam
    Must be zero.

CLR_DEFAULT определяется как 0xFF000000L.Что произойдет, если вы измените свой код на:

PostMessage(progress_bar, PBM_STEPIT, 0, 0);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...