c++ - 对话框卡住并停止响应

标签 c++ winapi

我有一个非常具体的问题,涉及我的应用程序中的无模式对话框。

对话框卡住并且不再响应我的应用程序中其他功能发送给它的任何消息。有趣的是,我的调试告诉我,当对话过程收到它没有处理的大约 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/

相关文章:

c++拆分字符串并获取空格之后的部分

c - 为什么 64 位 Visual Studio C 中的 CreateWindow 在创建时会自行销毁?

c - winapi 最小化窗口通知(橙色冲洗)

c++ - MSVC 中的分解

c++ - 头文件包含在纯虚类中

c++ - 如何从 boost::spirit::lex 标记确定行/列号?

c++ - 重载函数候选匹配问题

c++ - Paint Job Estimator C++

winapi - 自动调整静态控件大小的正确方法是什么?

c++ - 由于查找 Windows.h 时出现问题,无法设置 openGL superBible 示例