我有一个非常具体的问题,涉及我的应用程序中的无模式对话框。
对话框卡住并且不再响应我的应用程序中其他功能发送给它的任何消息。有趣的是,我的调试告诉我,当对话过程收到它没有处理的大约 5000 条消息时,它会卡住。我能想到的唯一解释是 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();
}
}
我真的希望你们中的一个知道哪里出了问题,因为这真的很难调试!
Dialog 过程是这样实现的:(对不起,你必须看到我的实际代码)
首先,静态对话过程将消息重定向到自定义方法:
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;
}
最佳答案
您的对话过程在每次调用时都会创建两个 GDI 对象,一个画笔和一支笔。它从不破坏这些对象。默认情况下,GDI 对象的每个进程限制为 10,000。一旦达到该限制,创建对象的调用就会失败。然后,您的代码将尝试使用无效的句柄值进行绘制,使您的窗口看起来像是已卡住。
解决方案是在处理 WM_INITDIALOG 消息时只创建一次对象。还要始终检查您调用的函数的返回值是否有错误。如果您已经检查了 CreateSolidBrush 和 CreatePen 的返回值,您可能会更早地发现这一点。
关于c++ - 对话框卡住并停止响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31550685/