У меня есть очень специфическая проблема, связанная с немодальным диалоговым окном в моем приложении.Диалоговое окно зависает и перестает отвечать
Диалоговое окно замерзает и перестает отвечать на любые сообщения, отправленные ему другими функциями в моем приложении. Интересно, что моя отладка говорит мне, что он зависает, когда в процедуре диалога было получено около 5000 сообщений, которые DID NOT. Единственное объяснение, о котором я могу думать, это то, что очередь сообщений Windows может быть полной, и это более или менее подтверждается тем фактом, что поток сообщений, проходящих через диалоговое окно, кажется, сильно смягчается.
Теперь - я никогда раньше не использовал диалоговые окна в сочетании с обычным основным окном, и поэтому я могу совершать незаконные действия. Под этим я подразумеваю, что я обновляю элементы диалогового окна (статические тексты и список) напрямую, отправляя конкретные сообщения управления с помощью функций SendMessage или SetWindowText.
Что мне кажется странным, так это то, что эта техника отлично работает до тех пор, пока не пройдет 5000 сообщений.
Главный цикл отправляет сообщения в диалоговое окно через дескриптор родительского окна и использует функцию IsDialogMessage.
Главное окно и диалоговое окно по-прежнему получают сообщения, но диалоговое окно замерзает.
Есть ли способ освободить очередь сообщений вручную или проверить текущий том, чтобы проверить, действительно ли это проблема? Я использую функцию PeekMessage для получения моих сообщений, которые, согласно MSDN, должны удалить сообщение из нижней части очереди сообщений.
Вот как я реализовал мой основной цикл (я уверен, что это вполне законно):
while (true) //while there is a message
{
//if there was a windows message
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
{
if (msg.message == WM_QUIT ) //if the message was WM_QUIT
return 0; //Exit the message loop
if ( !IsDialogMessage(m_StatusHwnd, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
advanceFrame();
}
}
Я действительно надеюсь, что один из вас есть идея о том, что это неправильно, потому что это действительно трудно трудно отлаживать!
Диалог процедура реализована следующим образом: (К сожалению, что вы должны увидеть мой фактический код)
Первый статический диалог процедура перенаправляет сообщения на пользовательский метод:
BOOL CALLBACK DXCore::statusDlgProc(HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
if (msg == WM_INITDIALOG) SetWindowLongPtr(hwnd, DWLP_USER, lParam);
DXCore * pCore = reinterpret_cast<DXCore*>(GetWindowLongPtr(hwnd, DWLP_USER)) ;
if (pCore) return pCore->displayStatusDlgProc(hwnd, msg, wParam, lParam);
//return the message for windows to handle it
return FALSE;
}
Тогда фактическое процедура выглядит так:
BOOL DXCore::displayStatusDlgProc(HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
HBRUSH brush = CreateSolidBrush(COLORREF(RGB(255, 0, 0))); //red
HPEN blackPen = CreatePen(PS_SOLID, 2, COLORREF(RGB(0,0,0)));
HDC hdc; PAINTSTRUCT ps;
RECT clientArea;
GetClientRect(hwnd, &clientArea);
int gizmoRadius= 5;
m_GismoOrigon.x = clientArea.left + 150;
m_GismoOrigon.y = clientArea.top + 460;
//OutputDebugString("Dillermand\n");
dlgProcCounter += 1;
switch (msg)
{
case WM_INITDIALOG:
m_FPSCount = GetDlgItem(hwnd, IDC_STATIC_FPS);
if (!m_FPSCount) MessageBox(NULL, "ghFPSCount", "DAMN", MB_OK);
m_CamPosX = GetDlgItem(hwnd, IDC_CAMPOSX);
if (!m_CamPosX) MessageBox(NULL, "ghCamPosX", "DAMN", MB_OK);
m_CamPosY = GetDlgItem(hwnd, IDC_CAMPOSY);
if (!m_CamPosY) MessageBox(NULL, "ghCamPosY", "DAMN", MB_OK);
m_CamPosZ = GetDlgItem(hwnd, IDC_CAMPOSZ);
if (!m_CamPosZ) MessageBox(NULL, "ghCamPosZ", "DAMN", MB_OK);
m_hStatusMessages = GetDlgItem(hwnd, IDSTATUS_PROGMSG);
if (!m_hStatusMessages) MessageBox(NULL, "ghStatusMessages", "DAMN", MB_OK);
else
{
SetParent(m_hStatusMessages, hwnd);
}
m_RunButton = GetDlgItem(hwnd, IDCSTATUS_RUN_BTN);
if (!m_RunButton) MessageBox(NULL, "ghRunButton ", "DAMN", MB_OK);
m_PauseButton = GetDlgItem(hwnd, IDSTATUS_PAUSE_BTN);
if (!m_PauseButton) MessageBox(NULL, "ghPauseButton", "DAMN", MB_OK);
SetWindowText(m_CamPosX, "0");
SetWindowText(m_CamPosY, "0");
SetWindowText(m_CamPosZ, "0");
return TRUE;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
SelectObject(hdc, brush);
SelectObject(hdc, blackPen);
Ellipse(hdc, m_GismoOrigon.x - gizmoRadius, m_GismoOrigon.y - gizmoRadius, m_GismoOrigon.x + gizmoRadius, m_GismoOrigon.y + gizmoRadius) ;
EndPaint(hwnd, &ps);
return TRUE;
case WM_COMMAND:
return TRUE;
case WM_NOTIFY:
return TRUE;
case WM_CTLCOLORSTATIC:
return TRUE;
case WM_TIMER:
return TRUE;
case WM_DESTROY:
if (MessageBox(hwnd, "Exit Program?", "Do Not Want!", MB_YESNO) == IDYES)
{
PostQuitMessage(0);
}
else ShowWindow(m_StatusHwnd, true);
return TRUE;
case WM_CLOSE:
DestroyWindow(m_StatusHwnd);
return TRUE;
default:
string s = std::to_string(dlgProcCounter) + " Unhandled Dlg message: " + std::to_string(msg) + "\n";
OutputDebugString(s.c_str());
return (INT_PTR)FALSE;
}
return FALSE;
}
Можете ли вы показать окно proc для диалогового окна? –
Также, как долго выполняется 'advanceFrame()'? Если вы измените свой цикл сообщений с 'if (PeekMessage (...' to 'while (PeekMessage (...' это имеет значение? –
(для объяснения моего вышеизложенного комментария - скажем, advanceFrame() занимает 1/50-е секунды, это означает, что ваш цикл сообщений может обрабатывать не более 50 сообщений в секунду. Легко видеть, как это может увязнуть в этом) –