Общие элементы управления Windows в расширенной области, не являющейся клиентской - PullRequest
0 голосов
/ 15 декабря 2018

В моих приложениях я хочу использовать общие элементы управления (например, EDIT, BUTTON COMBOBOXEX32) для не клиентской области, которая расширяется с помощью DwmExtendFrameIntoClientArea.Весь процесс расширения работает хорошо, но когда я использую Windows Common Controls в этой расширенной области, я получаю неприятные эффекты при рисовании текста.Прочитав некоторое время об этом симптоме, я обнаружил, что с помощью GDI + текст рисуется составным способом, поэтому метки можно рисовать с помощью GDI +.

На рисунке ниже показан образец.Вы увидите кнопку разделения, созданную

  BStyle = BS_PUSHBUTTON Or WS_CHILD Or WS_VISIBLE Or &HC&
  .hwnd = CreateWindowEX(0, "BUTTON", vbNullString, BStyle, _
                         ScaleLeft, ScaleTop, ScaleWidth, ScaleHeight, _
                         UserControl.hwnd, 0&, App.hInstance, _
                         ByVal 0&)

, РЕДАКТИРОВАТЬ, также созданную CreateWindowEx, и кнопку извлечения пользователя, использующую тематику, GDI + метку и изображение.

Элементы управления, созданные CreateWindowEx, очевидно, нарисованы безподдержка GDI +, поэтому весь контент не правильно составлен.Это действительно ужасно, потому что введенный текст не читается.Создавать редакторы самостоятельно - это большая вещь, поэтому я бы предпочел поддержку Windows здесь.

Эта проблема возникает в Win7-Win10, даже если в Win8, Win10 предпочтительнее использовать глянцевый фон Win7 или непрозрачные стили.

Мой вопрос: есть ли в манифесте какие-либо настройки, доступные для настройки, для правильного рисования общих элементов управления, или существуют расширенные стили для его поддержки?Почему Windows не поддерживает его изначально?

Снимок экрана общих элементов управления в области ЧПУ

1 Ответ

0 голосов
/ 18 декабря 2018

Я нашел решение с использованием буферизованных функций рисования uxtheme.

На WM_PAINT общего элемента управления сделайте следующее:

  1. Получите чертеж постоянного тока, вызвав BeginPaint
  2. вызов BufferedPaintInit из lib uxtheme
  3. Создание буферизованного растрового изображения с помощью BeginBufferedPaint
  4. Печать клиентской области общего элемента управления в буфер
  5. Создание всех пикселейнепрозрачного буфера BufferedPaintSetAlpha
  6. отрисовка буфера для рисования постоянного тока с помощью EndBufferedPaint
  7. вызов BufferedPaintUnInit

Для удобства здесь приведен код классического класса VB clsBufferedPaint

Option Explicit

Public Enum BP_BUFFERFORMAT
    BPBF_COMPATIBLEBITMAP = 0
    BPBF_DIB = 1
    BPBF_TOPDOWNDIB = 2
    BPBF_TOPDOWNMONODIB = 3
End Enum

Public Enum BP_PAINTPARAMS_FLAGS
    BPPF_ERASE = 1
    BPPF_NOCLIP = 2
    BPPF_NONCLIENT = 4
End Enum

Public Type BP_PAINTPARAMS
    cbSize As Long
    dwFlags As BP_PAINTPARAMS_FLAGS
    prcExclude As Long
    pBlendFunction As Long
End Type

Private mHandle As Long

Private Declare Function BeginBufferedPaint Lib "uxtheme" (ByVal hdcTarget As Long, ByRef prcTarget As RECT, ByVal dwFormat As BP_BUFFERFORMAT, ByRef pPaintParams As Any, ByRef HDC As Long) As Long
Private Declare Function BufferedPaintClear Lib "uxtheme" (ByVal hBufferedPaint As Long, ByRef prc As RECT) As Long
Private Declare Function BufferedPaintInit Lib "uxtheme" () As Long
Private Declare Function BufferedPaintSetAlpha Lib "uxtheme" (ByVal hBufferedPaint As Long, ByRef prc As RECT, ByVal Alpha As Byte) As Long
Private Declare Function BufferedPaintUnInit Lib "uxtheme" () As Long
Private Declare Function EndBufferedPaint Lib "uxtheme.dll" (ByVal hBufferedPaint As Long, ByVal fUpdateTarget As Long) As Long

Friend Function BeginPaint(ByVal targetDC As Long, ByRef targetRect As RECT, _
                  ByVal format As BP_BUFFERFORMAT) As Long
    mHandle = BeginBufferedPaint(targetDC, targetRect, BPBF_TOPDOWNDIB, ByVal 0&, BeginPaint)
End Function

Public Function EndPaint(ByVal updatetargetDC As Long) As Long
    EndPaint = EndBufferedPaint(mHandle, updatetargetDC)
    mHandle = 0
End Function

Friend Sub SetAlpha(ByRef r As RECT, ByVal Alpha As Byte)
    BufferedPaintSetAlpha mHandle, r, Alpha
End Sub


Private Sub Class_Initialize()
    BufferedPaintInit
End Sub


Private Sub Class_Terminate()
    BufferedPaintUnInit
End Sub

и использование его в WM_PAINT общего элемента управления (должно быть разделено на подклассы при использовании сообщения)

Dim bp As New clsBufferedPaint, rct As RECT, DC As Long, pDC As Long

GetClientRect hwnd, rct

DC = BeginPaint(hwnd, ps)

pDC = bp.BeginPaint(DC, rct, BPBF_TOPDOWNDIB)
SendMessage hwnd, WM_PRINTCLIENT, pDC, PRF_CLIENT
bp.SetAlpha rct, 255
ISubclass_WindowProc = bp.EndPaint(DC)

EndPaint hwnd, ps

Проблемы, которые необходимо решить: углы строки редактирования непрозрачны, но ониПрозрачны в зависимости от темы, используемой системой.

Редактировать строку в не клиентской области

...