c - 如何消除相当大的对话框上的闪烁?

标签 c windows

我有一个带有一个子窗口的相当大的对话框 - 一个列表控件。调整对话框大小时,我适本地调整列表控件的大小;它基本上固定在对话框的所有 4 个边缘上。问题是在调整大小时,列表控件的边缘会明显闪烁,尤其是在存在滚动条时。我是 Win32 GUI 方面的新手,所以我真的不知道如何处理这个问题。我看过很多关于无闪烁绘图的文章,但它们都是关于单独的自定义绘制控件的,没有一篇涉及整个对话框的无闪烁绘图。我怎样才能使它在不闪烁太多的情况下工作?

我的实际对话框显然有多个控件,但这里是重现问题的最小代码示例(IDC_LIST1 是报 TableView 中的列表控件,IDD_DIALOG2 具有 WS_CLIPCHILDREN 样式集)。

#define NUM_COLUMNS  8
#define NUM_ROWS    32

RECT rcDialog2WindowOriginal;
RECT rcDialog2ClientOriginal;
RECT rcList1ClientOriginal;

INT_PTR Dialog2_OnInitDialog(HWND hDlg, WPARAM wParam, LPARAM lParam)
{
    GetWindowRect(hDlg, &rcDialog2WindowOriginal);
    GetClientRect(hDlg, &rcDialog2ClientOriginal);
    GetWindowRect(GetDlgItem(hDlg, IDC_LIST1), &rcList1ClientOriginal);
    ScreenToClient(hDlg, ((LPPOINT)&rcList1ClientOriginal));
    ScreenToClient(hDlg, ((LPPOINT)&rcList1ClientOriginal) + 1);
    SendDlgItemMessage(hDlg, IDC_LIST1, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
    TCHAR szText[32];
    // add some columns
    LVCOLUMN col;
    ZeroMemory(&col, sizeof(LVCOLUMN));
    col.mask = LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;
    col.cx = 60;
    col.pszText = szText;
    for(int i = 0; i < NUM_COLUMNS; i++)
    {
        col.iSubItem = i;
        _stprintf_s(szText, 32, _T("Column %d"), col.iSubItem);
        SendDlgItemMessage(hDlg, IDC_LIST1, LVM_INSERTCOLUMN, col.iSubItem, LPARAM)&col);
    }
    // add some items
    LVITEM item;
    ZeroMemory(&item, sizeof(LVITEM));
    item.mask = LVIF_TEXT;
    item.pszText = szText;
    for(int i = 0; i < NUM_ROWS; i++)
    {
        item.iItem = i;
        for(int j = 0; j < NUM_COLUMNS; j++)
        {
            item.iSubItem = j;
            _stprintf_s(szText, 32, _T("Item %d, SubItem %d"), i, j);
            if(j == 0)
            {
                SendDlgItemMessage(hDlg, IDC_LIST1, LVM_INSERTITEM, 0, (LPARAM)&item);
            }
            else
            {
                SendDlgItemMessage(hDlg, IDC_LIST1, LVM_SETITEM, 0, (LPARAM)&item);
            }
        }
    }
    // autosize the columns
    for(int i = 0; i < NUM_COLUMNS; i++)
    {
        SendDlgItemMessage(hDlg, IDC_LIST1, LVM_SETCOLUMNWIDTH, i, LVSCW_AUTOSIZE);
    }
    return TRUE;
}

INT_PTR Dialog2_OnGetMinMaxInfo(HWND hDlg, WPARAM wParam, LPARAM lParam)
{
    LPMINMAXINFO lpMinMaxInfo = (LPMINMAXINFO)lParam;
    // don't allow dialog to be resized smaller than original size
    lpMinMaxInfo->ptMinTrackSize.x = rcDialog2WindowOriginal.right - rcDialog2WindowOriginal.left;
    lpMinMaxInfo->ptMinTrackSize.y = rcDialog2WindowOriginal.bottom - rcDialog2WindowOriginal.top;
    return TRUE;
}

INT_PTR Dialog2_OnSize(HWND hDlg, WPARAM wParam, LPARAM lParam)
{
    int cx = LOWORD(lParam);
    int cy = HIWORD(lParam);
    // anchor the list control to all edges of the dialog
    int left_delta = rcList1ClientOriginal.left - rcDialog2ClientOriginal.left;
    int right_delta = rcDialog2ClientOriginal.right - rcList1ClientOriginal.right;
    int top_delta = rcList1ClientOriginal.top - rcDialog2ClientOriginal.top;
    int bottom_delta = rcDialog2ClientOriginal.bottom - rcList1ClientOriginal.bottom;
    int left = left_delta;
    int top = top_delta;
    int width = cx - left_delta - right_delta;
    int height = cy - top_delta - bottom_delta;
    HWND hWndList1 = GetDlgItem(hDlg, IDC_LIST1);
    SetWindowPos(hWndList1, NULL, left, top, width, height, SWP_NOZORDER);
    return TRUE;
}

INT_PTR Dialog2_OnClose(HWND hDlg, WPARAM wParam, LPARAM lParam)
{
    EndDialog(hDlg, IDOK);
    return TRUE;
}

INT_PTR CALLBACK Dialog2_DialogProc(HWND hDlg, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
    switch(nMsg)
    {
    case WM_INITDIALOG:
        return Dialog2_OnInitDialog(hDlg, wParam, lParam);
    case WM_GETMINMAXINFO:
        return Dialog2_OnGetMinMaxInfo(hDlg, wParam, lParam);
    case WM_SIZE:
        return Dialog2_OnSize(hDlg, wParam, lParam);
    case WM_CLOSE:
        return Dialog2_OnClose(hDlg, wParam, lParam);
    }
    return FALSE;
}

更新

在查看了许多其他 Windows 应用程序(甚至是 Microsoft 编写的应用程序)后,发现它们中的每一个都遇到了同样的闪烁问题。从左上角调整带有状态栏和滚动条的窗口大小时,这一点尤为明显。我想我只能忍受它。

最佳答案

很多闪烁来自WM_ERASEBKGRD,处理这个消息并返回TRUE;

关于c - 如何消除相当大的对话框上的闪烁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1551062/

相关文章:

c - 使用 C/OpenMP 时的性能问题

c - ZLIB 压缩

c# - 以编程方式启用/禁用设备的 Win32 API 函数

windows - 是否可以使用 AWS 运行普通的 Windows 10 机器?

mysql - ODBC 数据源找不到 MySQL 驱动程序

windows - 获取子项 : Illegal character path error

c - Windows 7 x64 中的 MinGW GCC 不创建可执行文件

c - 如何在文件C中搜索并替换字符串

c - Arduino伺服功能

c++ - CreateProcessWithLogonW : unable to start process