C ++ - цикл сообщений окна зависает - PullRequest
1 голос
/ 02 октября 2010

У меня есть этот класс, который я сделал на основе другого, который у меня был.Предполагается, что он будет обрабатывать все создаваемые окна и все такое, но, похоже, сейчас он зависает.Старая версия работала нормально, я не знаю, ЧТО я, возможно, забыл добавить к этой, которая может вызывать его зависание следующим образом.

Это цикл сообщений:

int Window::HandleMessages()
{
    while(GetMessage(&this->windat.msgs, NULL, 0, 0))
    {
        TranslateMessage(&this->windat.msgs);
        DispatchMessage(&this->windat.msgs);
    }
    return this->windat.msgs.wParam;
}

Довольно простой материал, я не знаю почему, но он просто зависает ... Когда я запускаю программу, она просто показывает мне пустое окно приглашения, и, протестировав, я получил его, чтобы показатьокно сообщения, если я использовал его до цикла while, но внутри он не работает.Я пытался сравнить этот класс и старый и не понял, что может быть с этим не так.Может ли кто-нибудь сказать мне, что может вызвать такое поведение?Спасибо


Хорошо, теперь это очень смутило меня.Возиться с GetLastError, похоже, что он возвращает ошибку 2 (файл не найден) В ЛЮБОМ МЕСТЕ, где я его поместил, даже если он был в самом начале, прежде чем создать экземпляр своего класса Window.Если я вызову GetLastError в любое время после CreateWindowEx, он вернет ошибку, такую ​​как 1047 или что-то, о классе не найден или что-то.HWND тоже становится NULL
Вот код для main.cpp:

#include "SimpWin/SimpWin.h"
#include <stdio.h>

//  Make the class name into a global variable
char szClassName[] = "WindowsApp";


void ErrorExit(LPTSTR lpszFunction)
{
    // Retrieve the system error message for the last-error code

    LPVOID lpMsgBuf;
    LPVOID lpDisplayBuf;
    DWORD dw = GetLastError();

    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        dw,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR) &lpMsgBuf,
        0, NULL );

    // Display the error message and exit the process

    lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
        (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
    sprintf((char*)lpDisplayBuf,
        TEXT("%s failed with error %d: %s"),
        lpszFunction, dw, lpMsgBuf);
    MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);

    LocalFree(lpMsgBuf);
    LocalFree(lpDisplayBuf);
    ExitProcess(dw);
}

LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain (HINSTANCE hThisInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpszArgument,
                    int nFunsterStil)

{
    ErrorExit(TEXT("CreateWindowEx"));
    Window* win = Window::CreateWindowClass(hThisInstance, szClassName, WindowProcedure);
    if(!win->Register())
    {
        return 0;
    }


    win->Show(nFunsterStil);

    int res = win->HandleMessages();

    delete win;

    return res;
}


/*  This function is called by the Windows function DispatchMessage()  */

LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    return DefWindowProc (hwnd, message, wParam, lParam);
}

Здесь приведен код для функции Window :: Register:

int Window::Register()
{
    if(this->windat.wincl.hIcon == NULL)
    {
        this->windat.wincl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    }
    if(this->windat.wincl.hIconSm == NULL)
    {
        this->windat.wincl.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
    }

    if(!RegisterClassEx(&this->windat.wincl))
    {
        return 0;
    }



    this->windat.hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           (char*) this->windat.sName,                  /* Classname */
           (char*) this->windat.sTitle,       /* Title Text */
           WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           this->windat.cDimension.width,         /* The programs width */
           this->windat.cDimension.height,        /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           this->windat.hInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );

    return 1;
}

Iя потерялся здесь, я не знаю, почему это происходит ...: /

Ответы [ 4 ]

0 голосов
/ 02 января 2014

Несмотря на то, что он довольно старый ... с MSDN на GetMessage:

В отличие от GetMessage, функция PeekMessage не ожидает публикации сообщения перед возвратом.

То есть GetMessage ожидает следующего сообщения, которое станет доступным. Вы рассматриваете это ожидание как остановку, предположительно потому, что на самом деле у вас не было намерения ждать сообщений.

Обратите внимание, что вы можете подключить отладчик во время предполагаемого замораживания, приостановить выполнение и проверить стеки вызовов потоков. Как только вы найдете ваш поток и его стек вызовов и его GetMessage в стеке - вы достаточно хорошо изолируете проблему, чтобы знать, где можно прочитать о задокументированном поведении.

0 голосов
/ 02 октября 2010

Проверьте возвращаемое значение для GetMessage () - ваш цикл while не завершится, если возникнут ошибки.Это должно выглядеть так:

while (GetMessage(&this->windat.msgs, NULL, 0, 0) > 0)
{
 ...
}
0 голосов
/ 03 октября 2010

Ну, я наконец-то получил его на работу!: D

Это на самом деле было связано с совершенно несвязанным классом, который у меня был здесь.Это класс String (который произошел от Array), который я создал, и у функции copy была ошибка, он копировал массив символов, который я ему передал, но не обновлял поле длины класса ... Эта функция копированиябудет вызываться всякий раз, когда мне нужно было установить значение класса через operator =.Длина требуется для оператора char * для преобразования класса в строку c-формата.Я бы использовал это приведение при передаче значений ClassName и Title в CreateWindowEx, и он вернул бы мне массив из 0 символов, и вот где, черт возьми, это произошло.
Теперь я исправил эту библиотеку, и теперь она работает нормально.Спасибо: D

0 голосов
/ 02 октября 2010

Используйте PeekMessage вместо GetMessage.

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