2011-02-04 3 views
1

Если у меня есть следующий код ниже, как я могу определить, когда окно было закрыто, я могу уйти? r никогда не получает значение -1 0, и мне нужно обрабатывать сообщения для всего потока, а не только для текущего окна.Циклы сообщений Win32: Выход после закрытия окна с помощью GetMessage (& msg, NULL, 0, 0)?

HWND hWnd = CreateWindowExW(0, L"Edit", L"My Window", WS_OVERLAPPEDWINDOW, 
    CW_USEDEFAULT, CW_USEDEFAULT, 300, 200, NULL, NULL, NULL, NULL); 
ShowWindow(hWnd, SW_SHOWDEFAULT); 
MSG msg; 
BOOL r; 
while ((r = GetMessageW(&msg, NULL, 0, 0)) != 0) 
{ 
    if (r == -1) { break; } 
    TranslateMessage(&msg); 
    DispatchMessageW(&msg); 
} 

ответ

3

Ожидание r = -1 не так, как вы обнаружите, что ваше окно уже закрыто. Возвращаемое значение -1 не является нормальным условием: оно указывает на то, что в контуре сообщения произошла ошибка.

От documentation:

Возвращаемое значение

Тип: BOOL

Если функция извлекает сообщение, отличное WM_QUIT, возвращаемое значение равно нулю.

Если функция получает сообщение WM_QUIT, возвращаемое значение равно нулю.

Если есть ошибка, возвращаемое значение равно -1. Например, функция не работает, если hWnd является недопустимым дескриптором окна или lpMsg является недопустимым указателем. Чтобы получить расширенную информацию об ошибке, звоните GetLastError.

Когда GetMessage извлекает WM_QUIT сообщений из очереди, он возвращает значение 0, и вы должны закончить цикл.

Если вы просто хотите знать, когда окно закрылось, вы, вероятно, захотите обработать либо сообщения WM_CLOSE, либо WM_DESTROY. Для обсуждения этих сообщений см. Ответы на этот вопрос: What is the difference between WM_QUIT, WM_CLOSE, and WM_DESTROY in a windows program?

+1

Извините, я полностью забыл, что 'r == -1' не является близким. Но разве он также не должен выйти с 'r == 0'? Почему это не так? (Кстати, я 'WM_QUIT' никогда не отправляется в цикл.) – Mehrdad

+0

@Mehrdad: Да, мой ответ был адресован, что' WM_QUIT' никогда не отправляется в цикл сообщений. Если 'GetMessage' получает' WM_QUIT', он возвращает значение 0. Предположительно, проблема в том, что вы никогда не отправляете * сообщение 'WM_QUIT'. Вам нужно обработать случай, когда окно закрыто, и использовать функцию '' PostQuitMessage' (http://msdn.microsoft.com/en-us/library/ms644945.aspx), чтобы указать, что цикл должен выйти. –

+0

Ой, подождите ... так что, если мне нужно отправить его, и у меня есть несколько окон с большим количеством элементов управления внутри друг друга, как узнать, открылось ли я в последнем окне, и так ли я должен отправить его из WndProc? Не отслеживает это, становится довольно уродливым? – Mehrdad

0

Я нашел решение для этого: WM_NULL.
Цикл сообщений может обрабатывать этот вопрос сам по себе независимо от WndProc:

// written in C# 
MSG msg = new MSG(); 
while (GetMessage(out msg, window, 0, 0)) 
{ 
    if ((msg.message == WM_NULL) && !IsWindow(window)) 
     break; 
    TranslateMessage(ref msg); 
    DispatchMessage(ref msg); 
} 
Console.WriteLine("yeah, out of loop ^^"); 

Из моих наблюдений: Когда окно уничтожается GetMessage извлекает WM_NULL сообщения без паузы (1 подсказка) и IsWindow можно проверить окно (утверждение).