Двойной буфер общих элементов управления
Есть ли способ двойной буферизации общих элементов управления? В настоящее время, когда они изменяют размер, они мерцают. Много.....
РЕДАКТИРОВАТЬ: Если это помогает, это набор элементов управления кнопки и несколько элементов управления редактированием, все они находятся на верхней части элемента управления вкладки. Элемент управления Tab перерисовывает себя, затем кнопки перерисовывают себя. Когда кнопки перерисовываются, они мерцают.
РЕДАКТИРОВАТЬ 2: Вот пример моей проблемы: http://billy-oneal.com/Lobfuscator.exe
8 ответов
Посмотрите на использование WS_EX_COMPOSITED
а также WS_EX_TRANSPARENT
стили. Они обеспечивают двойной буфер, хотя WM_PAINT будет вызываться, когда базовое растровое изображение завершит рисование, поскольку оно рисует дочерние элементы управления снизу вверх, поэтому вы можете рисовать только в своей оконной процедуре. Я использовал это в прошлом и работаю довольно хорошо.
Установите для вашего окна верхнего уровня (контейнера) расширенный стиль WS_EX_COMPOSITED, а для дочерних окон - WS_EX_TRANSPARENT. Также не забудьте определить:
#define WINVER 0x501
См. CreateWindowEx для информации о составном стиле. Это также позволяет делать прозрачность для дочерних окон.
ОБНОВИТЬ
Как насчет использования WM_PRINTCLIENT для переноса клиентской области в растровое изображение на контроллере домена и уничтожения всей клиентской области в целом?
Я понимаю, что тема довольно старая, но это может относиться к тем, у кого возникли проблемы с мерцанием.
Как и у Билли, я столкнулся с проблемой, возникающей при переключении вкладок, когда элементы управления, размещенные на вкладке, мерцают при показе и скрытии. Для справки, я широко использую функцию ShowWindow, чтобы скрыть и показать элементы управления.
Я возился с WS_EX_COMPOSITED в течение нескольких часов, и это дало мне очень странные результаты. Я также ничего не изменяю, диалоговое окно предназначено для работы в полноэкранном режиме и адаптируется к текущему разрешению рабочего стола.
Это макет моего диалога, который я создал вручную, вызывая функцию CreateWindowEx для каждого элемента управления:
Главное окно - некоторые элементы управления - элемент управления вкладками ---- еще несколько элементов управления
Отступ представляет собой отношения родитель-ребенок. Элемент управления вкладки имеет стили WS_CHILD и WS_CLIPCHILDREN, установленные при создании, все элементы управления имеют набор стилей WS_CHILD.
Что в итоге сделал трюк был следующим
MainProc proc hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
mov eax,uMsg
cmp eax,WM_INITDIALOG
je @WM_INITDIALOG
...
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
@WM_INITDIALOG:
...
invoke GetWindowLong,hWnd,GWL_EXSTYLE
or eax,WS_EX_COMPOSITED
invoke SetWindowLong,hWnd,GWL_EXSTYLE,eax
...
MainProc endp
Этот бит написан на ассемблере (MASM32), но я уверен, что вы понимаете суть этого. Просто получите EX_STYLE вашего главного окна где-то во время WM_INITDIALOG и добавьте в него WS_EX_COMPOSITED.
В этом единственном случае этот метод работает как на 32-битной Windows XP SP3, так и на 64-битной Windows 7 SP1. Не было необходимости добавлять стиль WS_EX_COMPOSITED ни к одному из дочерних элементов управления вкладки (некоторые статические элементы управления, которые я использую, имеют установленный WS_EX_TRANSPARENT, но это по другим причинам), и в настоящее время нет очевидной необходимости возвращать ненулевое значение для WM_ERASEBKGND. сообщение. Я также не испытываю проблем с производительностью на умеренно мощной C2D-машине.
Для справки, это мой главный
Main proc hInst:DWORD,hPrevInst:DWORD,CmdLine:DWORD,CmdShow:DWORD
LOCAL wc:WNDCLASSEX,msg:MSG
mov wc.cbSize,sizeof WNDCLASSEX
mov wc.style,CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc,offset MainProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,DLGWINDOWEXTRA
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_BTNFACE+1
mov wc.lpszClassName,offset szClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx,addr wc
invoke CreateDialogParam,hInstance,IDD_MAIN,NULL,addr MainProc,NULL
invoke ShowWindow,hWin,SW_SHOWNORMAL
invoke UpdateWindow,hWin
invoke LoadAccelerators,hInstance,IDD_ACC_TABLE
mov hAcc,eax
jmp @2
@1:
invoke TranslateAccelerator,hWin,hAcc,addr msg
test eax,eax
jne @2
invoke TranslateMessage,addr msg
invoke DispatchMessage,addr msg
@2:
invoke GetMessage,addr msg,NULL,0,0
test eax,eax
jne @1
mov eax,msg.wParam
ret
Main endp
Здесь нет ничего особенного. Я устанавливаю "серый элемент управления диалоговым окном" в качестве цвета фона и использую стили CS_*REDRAW, которые, кажется, не влияют на эту ситуацию. "Пустой" шаблон диалога, который я использовал для создания главных окон
IDD_MAIN DIALOGEX 0,0,318,177
FONT 8,"MS Sans Serif",0,0,0
CLASS "DLGCLASS"
STYLE 0x90800000
EXSTYLE 0x00000008
BEGIN
END
Надеюсь, это может сэкономить время людям, которые ищут ответы. Это немного долго, но я хотел как можно подробнее описать это.
С уважением.
Ларри Остерман недавно написал в блоге на эту тему; Вы можете найти некоторые интересные детали там.
Мы используем WTL::CDoubleBufferImpl
вмешиваться для этой цели. Мы даже рисуем вещи с помощью GDI+ over. Ноль мерцает.
Использование довольно просто: вы просто публично наследуете от WTL::CDoubleBufferImpl<YourClass>
и зацепите его в карте сообщений ATL.
Не зная точно, что вы делаете, я предполагаю, что вы используете для этого либо MFC, либо Win32 C.
Вы, вероятно, хотите изменить размер сообщения WM_SIZE. Я не уверен, где вы изменяете размеры элементов управления, но я думаю, что вы делаете это во время изменения размера, именно поэтому он вызывает мерцание.
Кроме того, я думаю, но я не знаю, вы, вероятно, могли бы использовать функцию SetWindowPos, а для uFlags, иметь SWP_NOREDRAW. Хотя я не уверен, насколько хорошо это будет работать для общего контроля.
Вы не используете WS_EX_TRANSPARENT? Это приведет к тому, что нижележащие окна будут окрашены перед элементами управления, а когда стерется нижнее окно, вы получите мерцание.
Вы можете создать контекст устройства памяти MemDC в самом начале. Нарисуйте все в MemDC, затем, когда окно получит сообщение WM_PAINT или станет недействительным, скопируйте MemDC в реальный DC с помощью битового бита.
Я помню, как читал технику Герберта Шильдта в его книге несколько лет назад (программирование Windows 98 с нуля). Таким образом, все перерисовки происходят быстрее, когда вы переводите память постоянного тока в реальный. Но одна большая проблема - насколько большой объем памяти вы хотите использовать! Но он показал, как это сделать. Для всех глав этой книги, опубликованной Осборном МакГроу Хиллом, загружен код.
Надеюсь, это поможет, С наилучшими пожеланиями, Том.
В самом деле,
кто-то опубликовал ответ на этот вопрос в одном из моих постов некоторое время назад. Проверьте это: здесь
и обязательно поддержите его за то, что он потрясающий.
Код C#, надеюсь, есть простой перевод.