I've got a sizable dialog with one child window - a list control. When the dialog is re-sized, I re-size the list control appropriately; it is basically anchored to all 4 edges of the dialog. The problem is that during sizing there is noticeable flicker around the edges of the list control, especially when the scroll bars are present. I am a novice in Win32 GUI stuff, so I don't really know how to handle this. I've seen a lot of articles about flicker-free drawing, but they are all about individual custom-drawn controls and none of them deal with flicker-free drawing of a dialog as a whole. How can I get this to work without flickering so much?
My actual dialog has multiple controls obviously, but here is a minimal code example that reproduces the issue (IDC_LIST1 is a list control in Report view, IDD_DIALOG2 has WS_CLIPCHILDREN style set).
#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 taking a look at many other Windows applications (even ones written by Microsoft), every single one of them suffers the same flickering issues. It is particularly evident when resizing a window with both a status bar and scroll bar from the top left. I guess I will just have to live with it.