在我的应用程序中,我想在非客户区域使用由DwmExtendFrameIntoClientArea扩展的通用控件(即EDIT,BUTTON COMBOBOXEX32)。整个扩展过程效果很好,但是当我在此扩展区域上使用Windows公共控件时,绘制文本时会出现讨厌的效果。阅读一段时间后,我发现使用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创建的EDIT和使用主题,GDI +标签和图像的用户绘制按钮。
由CreateWindowEx创建的控件显然是在没有GDI +支持的情况下绘制的,因此所有内容均未正确合成。这确实很难看,因为输入的文本不可读。自己创建编辑器是一件大事,所以我在这里更喜欢Windows的支持。
在Win7到Win10下,即使在Win8,Win10下首选有光泽的Win7背景或不透明样式,也会出现此问题。
我的问题是:清单中是否有可用于正确绘制常用控件的设置,或者是否存在扩展样式来支持它? Windows为什么不原生支持它?
答案 0 :(得分:0)
我找到了使用uxtheme缓冲绘画功能的解决方案。
在通用控件的WM_PAINT上执行以下操作:
为方便起见,这里是经典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
要解决的问题:编辑线的角是不透明的,但根据系统使用的主题它们是透明的。