Двойной буфер общих элементов управления - PullRequest
5 голосов
/ 03 декабря 2009

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

РЕДАКТИРОВАТЬ: если это помогает, это набор элементов управления кнопки и несколько элементов управления редактированием, все они находятся на верхней части вкладки. Элемент управления Tab перерисовывает себя, затем кнопки перерисовывают себя. Когда кнопки перерисовываются, они мерцают.

РЕДАКТИРОВАТЬ2: Вот пример моей проблемы: http://billy -oneal.com / Lobfuscator.exe

Ответы [ 8 ]

4 голосов
/ 13 декабря 2012

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

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

Надеюсь, это может сэкономить время людям, которые ищут ответы. Это немного длинно, но я хотел подробно описать это.

Привет.

4 голосов
/ 08 декабря 2009

Посмотрите на использование стилей WS_EX_COMPOSITED и WS_EX_TRANSPARENT. Они обеспечивают двойной буфер, хотя WM_PAINT будет вызываться, когда базовое растровое изображение завершит рисование, поскольку оно рисует дочерние элементы управления снизу вверх, поэтому вы можете рисовать только в своей оконной процедуре. Я использовал это в прошлом и работаю довольно хорошо.

Установите ваше окно верхнего уровня (контейнер) на расширенный стиль WS_EX_COMPOSITED и ваши дочерние окна с WS_EX_TRANSPARENT. Также не забудьте определить:

#define WINVER 0x501 

См. CreateWindowEx для получения информации о комбинированном стиле. Это также позволяет сделать прозрачность для дочерних окон перпиксельной.

UPDATE

Как насчет того, чтобы использовать WM_PRINTCLIENT для переноса клиентской области в растровое изображение на контроллере домена и уничтожения всей клиентской области в целом?

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

2 голосов
/ 08 декабря 2009

Ларри Остерман недавно написал в блоге на эту тему; Вы можете найти некоторые интересные детали там .

0 голосов
/ 11 декабря 2009

Мы используем WTL::CDoubleBufferImpl для этой цели. Мы даже рисуем вещи с помощью GDI + over. Ноль мерцает.

Использование довольно просто: вы просто общедоступно наследуете от WTL::CDoubleBufferImpl<YourClass> и включаете его в карту сообщений ATL.

0 голосов
/ 08 декабря 2009

Вы не используете WS_EX_TRANSPARENT? Это приведет к тому, что нижние окна будут окрашены перед элементами управления, а когда стерется нижнее окно, вы получите мерцание.

0 голосов
/ 07 декабря 2009

Вы можете создать контекст устройства памяти MemDC в самом начале. Нарисуйте все в MemDC, затем, когда окно получит сообщение WM_PAINT или станет недействительным, скопируйте MemDC в реальный DC с помощью битового бита.

Я помню, как читал технику Герберта Шильдта в своей книге несколько лет назад (Программирование Windows 98 с нуля). Таким образом, все перерисовки происходят быстрее, когда вы переводите память постоянного тока в реальный. Но одна большая проблема, насколько большой объем памяти вы хотите использовать! Но он показал, как это сделать. Для всех глав этой книги, опубликованной Осборном МакГроу Хиллом, загружен код.

Надеюсь, это поможет, С наилучшими пожеланиями, Том.

0 голосов
/ 03 декабря 2009

Не зная точно, что вы делаете, я предполагаю, что вы используете для этого либо MFC, либо Win32 C.

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

Кроме того, я думаю, но я не знаю, возможно, вы могли бы использовать функцию SetWindowPos, а для uFlags, иметь SWP_NOREDRAW. Хотя я не уверен, насколько хорошо это будет работать для обычных элементов управления.

0 голосов
/ 03 декабря 2009

действительно

кто-то опубликовал ответ на этот вопрос в одном из моих постов некоторое время назад. Проверьте это: Здесь

и обязательно поддержите его за то, что он потрясающий.

Код C #, надеюсь, есть простой перевод.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...