【发布时间】:2015-07-21 22:24:23
【问题描述】:
我有一个非常具体的问题,涉及我的应用程序中的无模式对话框。
对话框冻结并且对我的应用程序中的其他函数发送给它的任何消息都没有响应。有趣的是,我的调试告诉我,当对话过程收到大约 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;
}
【问题讨论】:
-
你能显示你的对话框的窗口过程吗?
-
另外,
advanceFrame()需要多长时间才能完成?如果您将消息循环从if (PeekMessage(...更改为while (PeekMessage(...会有所不同吗? -
(解释我上面的评论 - 说 advanceFrame() 需要 1/50 秒,这意味着您的消息循环每秒最多可以处理 50 条消息。很容易看出它是如何陷入困境的这样做)
-
感谢您的意见:AdvanceFrame() 现在不需要时间 - 因为它几乎什么都不做(我们说的是 200 - 1000 纳秒)。我不知道如何实现一段时间( peekMessage ... ),但仍然确保 AdvanceFrame 已运行。危险在于,如果只有一次没有消息,循环就会结束。
-
实际上,您只需将
if更改为while并取出else。