You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在WndProc外部触发WM_PAINT消息执行?

问题描述

我是WinAPI初学者,若问题表述幼稚请见谅。我想要实现的是:点击对话框中的按钮后,触发主窗口执行对应TextOut绘制文本。但目前修改pageID后,文本要等到WndProc下次执行才会显示。我知道UpdateWindow可触发重绘,但在对话框回调中无法获取主窗口hWnd,请求快速解决思路。

注:代码中部分变量暂未生效,是我尝试解决问题时添加的,但尚未成功。


相关代码
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    WCHAR greeting[] = _T("line1");
    WCHAR greeting1[] = _T("another line");

    switch (message)
    {
    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            // Parse the menu selections:
            switch (wmId)
            {
            case IDM_ABOUT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;
            case IDM_EXIT:
                DestroyWindow(hWnd);
                break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;

    case WM_PAINT:
        {
        repaint = false;
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);

        switch (pageID) {
        case 1: {//display first string
            TextOut(hdc, 5, 5, greeting, _tcslen(greeting));
            break;
        }
        case 2: {//display the other string
            TextOut(hdc, 5, 100, greeting1, _tcslen(greeting1));
            break;
        }
        }
            EndPaint(hWnd, &ps);
        }
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}
/*****************************************************************************/
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
            pageID = 1;
            repaint = true;
        }
        if (LOWORD(wParam) == IDC_BUTTON1) {
            pageID = 2;
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

快速解决思路
  1. 获取主窗口句柄:在对话框回调About中,调用GetParent(hDlg)即可拿到主窗口的句柄——因为对话框是由主窗口作为父窗口创建的。
  2. 强制触发重绘:拿到主窗口句柄后,先用InvalidateRect(hMainWnd, NULL, TRUE)标记整个窗口区域为需要重绘,再调用UpdateWindow(hMainWnd)立即发送WM_PAINT消息,让主窗口立刻重新绘制。
  3. 修正代码顺序错误:当前IDOK/IDCANCEL分支中,return (INT_PTR)TRUE;写在了pageID = 1;之前,会导致后续代码完全不执行,必须把return语句移到变量修改和重绘操作之后。

修改后的关键代码片段

INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            pageID = 1;
            HWND hMainWnd = GetParent(hDlg);
            InvalidateRect(hMainWnd, NULL, TRUE);
            UpdateWindow(hMainWnd);
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        if (LOWORD(wParam) == IDC_BUTTON1) {
            pageID = 2;
            HWND hMainWnd = GetParent(hDlg);
            InvalidateRect(hMainWnd, NULL, TRUE);
            UpdateWindow(hMainWnd);
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

补充说明:确保pageID是全局变量或能被对话框回调访问到的变量,否则修改无法同步到主窗口的WM_PAINT逻辑中。

内容的提问来源于stack exchange,提问作者Vroom ZOOM

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 02:06:52