Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何消除大对话框上的闪烁?_C_Windows - Fatal编程技术网

C 如何消除大对话框上的闪烁?

C 如何消除大对话框上的闪烁?,c,windows,C,Windows,我有一个相当大的对话框,有一个子窗口——一个列表控件。当对话框重新调整大小时,我会适当地重新调整列表控件的大小;它基本上固定在对话框的所有4条边上。问题在于,在调整大小的过程中,列表控件的边缘会出现明显的闪烁,尤其是当存在滚动条时。我是Win32 GUI方面的新手,所以我真的不知道如何处理这个问题。我看过很多关于无闪烁绘图的文章,但它们都是关于单个自定义绘制控件的,没有一篇文章作为一个整体处理对话框的无闪烁绘图。我怎样才能让它工作而不闪烁这么多 我的实际对话框显然有多个控件,但这里有一个最小的代

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

我的实际对话框显然有多个控件,但这里有一个最小的代码示例再现了这个问题(IDC_LIST1是报表视图中的列表控件,IDD_DIALOG2设置了WS_CLIPCHILDREN样式)

#定义NUM_列8
#定义NUM_行32
RECT rcDialog2WindowOriginal;
直肠肾盂;
直肠直肠1脾阴道;
INT\u PTR对话框2\u ONINITALOG(HWND hDlg、WPARAM WPARAM、LPARAM LPARAM)
{
GetWindowRect(hDlg和rcDialog2WindowOriginal);
GetClientRect(hDlg和RCDialog2Clientorginal);
GetWindowRect(GetDlgItem(hDlg、IDC_列表1)和RCList1Client-ginal);
ScreenToClient(hDlg、((LPPOINT)和RCList1Client-ginal));
ScreenToClient(hDlg、((LPPOINT)和RCList1客户端)+1;
Senddlgit消息(hDlg、IDC_列表1、LVM_SETEXTENDEDLISTVIEWSTYLE、LVS_EX_FULLROWSELECT、LVS_EX_FULLROWSELECT);
TCHAR szText[32];
//添加一些列
LVCOL柱;
零内存(&col,sizeof(LVCOLUMN));
col.mask=LVCF_子项| LVCF_文本| LVCF_宽度;
cx=60;
col.pszText=szText;
对于(int i=0;iptMinTrackSize.x=rcDialog2WindowOriginal.right-rcDialog2WindowOriginal.left;
lpMinMaxInfo->ptMinTrackSize.y=rcDialog2WindowOriginal.bottom-rcDialog2WindowOriginal.top;
返回TRUE;
}
INT_PTR对话框2_OnSize(HWND hDlg、WPARAM WPARAM、LPARAM LPARAM)
{
int cx=低ORD(LPRAM);
int-cy=HIWORD(lParam);
//将列表控件锚定到对话框的所有边缘
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=左_delta;
int top=top_delta;
int width=cx-左_delta-右_delta;
int height=cy-顶部_delta-底部_delta;
HWND hWndList1=GetDlgItem(hDlg,IDC_列表1);
设置窗口位置(hWndList1、空、左、顶、宽、高、SWP_NOZORDER);
返回TRUE;
}
INT_PTR对话框2_OnClose(HWND hDlg、WPARAM WPARAM、LPARAM LPARAM)
{
EndDialog(hDlg、IDOK);
返回TRUE;
}
INT_PTR回调对话框2_DialogProc(HWND hDlg、UINT nMsg、WPARAM WPARAM、LPARAM LPARAM)
{
交换机(nMsg)
{
案例WM_初始化对话框:
返回对话框2_OnInitDialog(hDlg、wParam、lParam);
案例WM_GETMINMAXINFO:
返回对话框2_OnGetMinMaxInfo(hDlg、wParam、lParam);
案例WM_大小:
返回对话框2_OnSize(hDlg、wParam、lParam);
案例WM_结束:
返回对话框2_OnClose(hDlg、wParam、lParam);
}
返回FALSE;
}
更新


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

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

你可以做几件事

  • 处理你自己。您可能仍然需要擦除一些背景,但是您可以在窗口的边缘绘制4个矩形来填充对话框的背景区域,而不必在儿童控件所在的中间画出矩形。

  • 调用SetWindowPos后,尝试调用UpdateWindow()立即重新绘制窗口(在列表视图控件和您自己的窗口上都尝试)。这样可以最大限度地缩短更改大小和完成重新绘制之间的时间

  • 另一种方法是双缓冲(您将整个窗口表面绘制为屏幕外位图,并仅在完成后才将其绘制到屏幕上。这将最小化屏幕上更新过程开始和结束之间的时间,从而减少闪烁。但使用对话框和windows控件很难实现这一点,因此在您的情况下并不真正适用)

  • 一般来说,不要这样做
    #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;
    }
    
    LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch (uMsg)
        {
        case WM_ERASEBKGND:
            // Lie and tell Windows that this window has cleared its background.
            return (-1);
        
        case WM_PAINT:
            // Lie and tell Windows that this window has completed all its painting.
            ValidateRect(hwnd, nullptr);
            return 0;
        
        default:
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
        }
    }