У меня есть значительный диалог с одним дочерним окном - элементом управления списком. Когда размер диалогового окна изменяется, я соответствующим образом изменяю размер элемента управления списком; это в основном привязано ко всем 4 краям диалога. Проблема заключается в том, что во время изменения размера по краям элемента управления списка заметно мерцание, особенно при наличии полос прокрутки. Я новичок в Win32 GUI, поэтому я не знаю, как с этим справиться. Я видел много статей о рисовании без мерцания, но все они посвящены отдельным нарисованным элементам управления, и ни одна из них не касается рисования диалога без мерцания в целом. Как я могу заставить это работать без особого мерцания?
В моем реальном диалоговом окне, очевидно, имеется несколько элементов управления, но здесь приведен минимальный пример кода, который воспроизводит проблему (IDC_LIST1 - это элемент управления списком в представлении отчета, в 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), у каждого из них возникают те же проблемы с мерцанием. Это особенно заметно при изменении размера окна с панелью состояния и полосой прокрутки слева вверху. Я думаю, мне просто придется с этим смириться.