Двойной буфер общих элементов управления

Есть ли способ двойной буферизации общих элементов управления? В настоящее время, когда они изменяют размер, они мерцают. Много.....

РЕДАКТИРОВАТЬ: Если это помогает, это набор элементов управления кнопки и несколько элементов управления редактированием, все они находятся на верхней части элемента управления вкладки. Элемент управления 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 для переноса клиентской области в растровое изображение на контроллере домена и уничтожения всей клиентской области в целом?

http://blogs.msdn.com/larryosterman/archive/2008/08/27/larry-s-new-favorite-windows-message-wm-printclient.aspx

Я понимаю, что тема довольно старая, но это может относиться к тем, у кого возникли проблемы с мерцанием.

Как и у Билли, я столкнулся с проблемой, возникающей при переключении вкладок, когда элементы управления, размещенные на вкладке, мерцают при показе и скрытии. Для справки, я широко использую функцию 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#, надеюсь, есть простой перевод.

Другие вопросы по тегам