How to eliminate flicker in a large dialogue?

I have an important dialog with one child window - a list control. When the dialog box is resized, I resize the list control accordingly; it is basically tied to all 4 edges of the dialog box. The problem is that during calibration, there is a noticeable flicker around the edges of the list control, especially when scroll bars are present. I am new to Win32 GUI, so I don’t know how to handle this. I have seen many articles on flicker-free drawing, but they all relate to individual custom controls and none of them relate to flicker-free diaphragm in general. How can I make it work without flickering?

There are several controls in my actual dialog box, but here is an example of minimal code that reproduces the problem (IDC_LIST1 is a list control in the Report view, IDD_DIALOG2 has the WS_CLIPCHILDREN style).

#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; } 

Update

After viewing many other Windows applications (even those written by Microsoft), each of them faces the same flickering problems. This is especially noticeable when you resize a window with a status bar and a scroll bar in the upper left corner. I think I just need to live with it.

+4
source share
3 answers

After viewing many other Windows applications (even those written by Microsoft), each of them faces the same flickering problems. This is especially noticeable when you resize a window with a status bar and a scroll bar in the upper left corner. I think I just need to live with it.

+1
source

Due to WM_ERASEBKGRD, a lot of flicker appears, processes this message and returns TRUE;

+2
source

You can do a few things.

  • Process WM_ERASE yourself. You may still need to erase part of the background, but you can draw 4 rectangles around the edges of the window to fill the background area of ​​the dialog box without scribbling the rectangle in the middle where your child control is.

  • After calling SetWindowPos, try calling UpdateWindow () to immediately redraw the window (try it both in the list view and in your own window). This minimizes the time between resizing and completing the redraw.

  • Another approach is double buffering (you draw the entire surface of the window on the screen bitmap and only draw it on the screen when it is all over. This minimizes the time between the start and end of the update on the screen, so it reduces flicker. This is more difficult to achieve with the help of dialogue and control windows, although this is not applicable in your case).

  • In general, don't be afraid to experiment with things. Try to do something in different orders, etc. And look what results. If something (for example, UpdateWindow ()) does not give a noticeable improvement, then it is easy to remove the code again and try something else until you get the best results.

change - additional ideas

  • see also this SO question

  • When updating controls, you can also pause and resume redrawing (BeginUpdate () and EndUpdate ()) to stop them from drawing more than once when adding many elements, etc. This is unlikely to help when resizing the window though.

+2
source

All Articles