Change the ForeColor of the text in a command button. Option ExplicitPrivate Type RECT Left As Long Top As Long Right As Long Bottom As Long End TypePrivate Declare Function GetParent Lib "user32" _ (ByVal hWnd As Long) As LongPrivate Declare Function GetWindowLong Lib "user32" Alias _ "GetWindowLongA" (ByVal hWnd As Long, _ ByVal nIndex As Long) As Long Private Declare Function SetWindowLong Lib "user32" Alias _ "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, _ ByVal dwNewLong As Long) As Long Private Const GWL_WNDPROC = (-4)Private Declare Function GetProp Lib "user32" Alias "GetPropA" _ (ByVal hWnd As Long, ByVal lpString As String) As Long Private Declare Function SetProp Lib "user32" Alias "SetPropA" _ (ByVal hWnd As Long, ByVal lpString As String, _ ByVal hData As Long) As Long Private Declare Function RemoveProp Lib "user32" Alias _ "RemovePropA" (ByVal hWnd As Long, _ ByVal lpString As String) As LongPrivate Declare Function CallWindowProc Lib "user32" Alias _ "CallWindowProcA" (ByVal lpPrevWndFunc As Long, _ ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, _ ByVal lParam As Long) As LongPrivate Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _ (Destination As Any, Source As Any, ByVal Length As Long)'Owner draw constants Private Const ODT_BUTTON = 4 Private Const ODS_SELECTED = &H1 'Window messages we're using Private Const WM_DESTROY = &H2 Private Const WM_DRAWITEM = &H2BPrivate Type DRAWITEMSTRUCT CtlType As Long CtlID As Long itemID As Long itemAction As Long itemState As Long hwndItem As Long hDC As Long rcItem As RECT itemData As Long End TypePrivate Declare Function GetWindowText Lib "user32" Alias _ "GetWindowTextA" (ByVal hWnd As Long, ByVal lpString As String, _ ByVal cch As Long) As Long 'Various GDI painting-related functions Private Declare Function DrawText Lib "user32" Alias "DrawTextA" _ (ByVal hDC As Long, ByVal lpStr As String, ByVal nCount As Long, _ lpRect As RECT, ByVal wFormat As Long) As Long Private Declare Function SetTextColor Lib "gdi32" (ByVal hDC As Long, _ ByVal crColor As Long) As Long Private Declare Function SetBkMode Lib "gdi32" (ByVal hDC As Long, _ ByVal nBkMode As Long) As Long Private Const TRANSPARENT = 1Private Const DT_CENTER = &H1 Public Enum TextVAligns DT_VCENTER = &H4 DT_BOTTOM = &H8 End Enum Private Const DT_SINGLELINE = &H20 Private Sub DrawButton(ByVal hWnd As Long, ByVal hDC As Long, _ rct As RECT, ByVal nState As Long)Dim s As String Dim va As TextVAlignsva = GetProp(hWnd, "VBTVAlign")'Prepare DC for drawing SetBkMode hDC, TRANSPARENT SetTextColor hDC, GetProp(hWnd, "VBTForeColor")'Prepare a text buffer s = String$(255, 0) 'What should we print on the button? GetWindowText hWnd, s, 255 'Trim off nulls s = Left$(s, InStr(s, Chr$(0)) - 1)If va = DT_BOTTOM Then 'Adjust specially for VB's CommandButton control rct.Bottom = rct.Bottom - 4 End IfIf (nState And ODS_SELECTED) = ODS_SELECTED Then 'Button is in down state - offset 'the text rct.Left = rct.Left + 1 rct.Right = rct.Right + 1 rct.Bottom = rct.Bottom + 1 rct.Top = rct.Top + 1 End IfDrawText hDC, s, Len(s), rct, DT_CENTER Or DT_SINGLELINE _ Or vaEnd SubPublic Function ExtButtonProc(ByVal hWnd As Long, _ ByVal wMsg As Long, ByVal wParam As Long, _ ByVal lParam As Long) As LongDim lOldProc As Long Dim di As DRAWITEMSTRUCTlOldProc = GetProp(hWnd, "ExtBtnProc")ExtButtonProc = CallWindowProc(lOldProc, hWnd, wMsg, wParam, lParam)If wMsg = WM_DRAWITEM Then CopyMemory di, ByVal lParam, Len(di) If di.CtlType = ODT_BUTTON Then If GetProp(di.hwndItem, "VBTCustom") = 1 Then DrawButton di.hwndItem, di.hDC, di.rcItem, _ di.itemStateEnd IfEnd IfElseIf wMsg = WM_DESTROY Then ExtButtonUnSubclass hWndEnd IfEnd FunctionPublic Sub ExtButtonSubclass(hWndForm As Long)Dim l As Longl = GetProp(hWndForm, "ExtBtnProc") If l <> 0 Then 'Already subclassed Exit Sub End IfSetProp hWndForm, "ExtBtnProc", _ GetWindowLong(hWndForm, GWL_WNDPROC) SetWindowLong hWndForm, GWL_WNDPROC, AddressOf ExtButtonProcEnd SubPublic Sub ExtButtonUnSubclass(hWndForm As Long)Dim l As Longl = GetProp(hWndForm, "ExtBtnProc") If l = 0 Then 'Isn't subclassed Exit Sub End IfSetWindowLong hWndForm, GWL_WNDPROC, l RemoveProp hWndForm, "ExtBtnProc"End SubPublic Sub SetButtonForecolor(ByVal hWnd As Long, _ ByVal lForeColor As Long, _ Optional ByVal VAlign As TextVAligns = DT_VCENTER)Dim hWndParent As LonghWndParent = GetParent(hWnd) If GetProp(hWndParent, "ExtBtnProc") = 0 Then ExtButtonSubclass hWndParent End IfSetProp hWnd, "VBTCustom", 1 SetProp hWnd, "VBTForeColor", lForeColor SetProp hWnd, "VBTVAlign", VAlignEnd SubPublic Sub RemoveButton(ByVal hWnd As Long)RemoveProp hWnd, "VBTCustom" RemoveProp hWnd, "VBTForeColor" RemoveProp hWnd, "VBTVAlign"End Sub To use this, set the target command button's Style property to 1 - GraphicalEXAMPLES:To set command button forecolor(doesn't have to be in form_load)Private Sub Form_Load() SetButtonForecolor Command1.Hwnd, vbBlue End SubThat will set Command1's Forecolor to BlueTo remove the color(can be put anywhere)Private Sub Command2_Click() RemoveButton Command1.Hwnd Command1.Refresh End Sub
新建一个文本文档,贴入下面的代码,另存为frm文件。用VB打开看看,是不是你想要的。VERSION 5.00 Begin VB.Form Form1 Caption = "Form1" ClientHeight = 3195 ClientLeft = 60 ClientTop = 345 ClientWidth = 4680 LinkTopic = "Form1" ScaleHeight = 3195 ScaleWidth = 4680 StartUpPosition = 3 '窗口缺省 Begin VB.Line LinR BorderColor = &H80000010& BorderWidth = 2 X1 = 2880 X2 = 2880 Y1 = 1140 Y2 = 1500 End Begin VB.Line LinD BorderColor = &H80000010& BorderWidth = 2 X1 = 1320 X2 = 2880 Y1 = 1500 Y2 = 1500 End Begin VB.Line LinL BorderColor = &H80000014& BorderWidth = 2 X1 = 1320 X2 = 1320 Y1 = 1140 Y2 = 1500 End Begin VB.Line LinU BorderColor = &H80000014& BorderWidth = 2 X1 = 1320 X2 = 2880 Y1 = 1140 Y2 = 1140 End Begin VB.Label lblCommand Alignment = 2 'Center Caption = "确定(&O)" BeginProperty Font Name = "宋体" Size = 10.5 Charset = 134 Weight = 400 Underline = 0 'False Italic = 0 'False Strikethrough = 0 'False EndProperty Height = 255 Left = 1380 TabIndex = 0 Top = 1200 Width = 1455 End End Attribute VB_Name = "Form1" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = False Attribute VB_PredeclaredId = True Attribute VB_Exposed = False Option ExplicitPrivate Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) lblCommand.ForeColor = &H80000012 End SubPrivate Sub lblCommand_Click() MsgBox "你按下了确定!", vbInformation End SubPrivate Sub lblCommand_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) If Button = 1 Then LinU.BorderColor = &H80000010 LinL.BorderColor = &H80000010 LinR.BorderColor = &H80000014 LinD.BorderColor = &H80000014 End If End SubPrivate Sub lblCommand_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) If Button = 0 Then lblCommand.ForeColor = &HFF0000 End If End SubPrivate Sub lblCommand_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single) If Button = 1 Then LinU.BorderColor = &H80000014 LinL.BorderColor = &H80000014 LinD.BorderColor = &H80000010 LinR.BorderColor = &H80000010 End If End Sub
将Check的Style改为1-Graphical 然后就可以模拟一个按钮Private Sub Check1_Click() Check1.Value = 0 End SubPrivate Sub Form_Load() Check1.BackColor = vbRed Check1.ForeColor = vbWhite End Sub
测试了一下,因为check1.value=0是会触发click事件,下面这样会比较好一些 Private Sub Check1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single) Check1.Value = 0 End SubPrivate Sub Form_Load() Check1.BackColor = vbRed Check1.ForeColor = vbWhite End Sub
其实不用什么 Subclass 和 Ownerdraw 的 用 Hook 拦截 WM_CTLCOLORBTN 消息就可以了 不过没试过 WM_CTLCOLORBTN The WM_CTLCOLORBTN message is sent to the parent window of a button when the button is about to be drawn. By responding to this message, the parent window can set a button's text and background colors. WM_CTLCOLORBTN hdcButton = (HDC) wParam; // handle of button display context hwndButton = (HWND) lParam; // handle of button ParametershdcButton Value of wParam. Identifies the display context for the button. hwndButton Value of lParam. Identifies the button. Return ValuesIf an application processes this message, it must return the handle of a brush. Windows uses the brush to paint the background of the button. Default ActionThe DefWindowProc function selects the default system colors for the button. ResThe WM_CTLCOLORBTN message is never sent between threads. It is sent only within one thread. The text color of a check box or radio button applies to the box or button, its check , and the text. The focus rectangle for these buttons remains the system default color (typically black). The text color of a group box applies to the text but not to the line that defines the box. The text color of a push button applies only to its focus rectangle; it does not affect the color of the text.
Option ExplicitPrivate Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End TypePrivate Declare Function GetParent Lib "user32" _
(ByVal hWnd As Long) As LongPrivate Declare Function GetWindowLong Lib "user32" Alias _
"GetWindowLongA" (ByVal hWnd As Long, _
ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias _
"SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, _
ByVal dwNewLong As Long) As Long
Private Const GWL_WNDPROC = (-4)Private Declare Function GetProp Lib "user32" Alias "GetPropA" _
(ByVal hWnd As Long, ByVal lpString As String) As Long
Private Declare Function SetProp Lib "user32" Alias "SetPropA" _
(ByVal hWnd As Long, ByVal lpString As String, _
ByVal hData As Long) As Long
Private Declare Function RemoveProp Lib "user32" Alias _
"RemovePropA" (ByVal hWnd As Long, _
ByVal lpString As String) As LongPrivate Declare Function CallWindowProc Lib "user32" Alias _
"CallWindowProcA" (ByVal lpPrevWndFunc As Long, _
ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, _
ByVal lParam As Long) As LongPrivate Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As Any, Source As Any, ByVal Length As Long)'Owner draw constants
Private Const ODT_BUTTON = 4
Private Const ODS_SELECTED = &H1
'Window messages we're using
Private Const WM_DESTROY = &H2
Private Const WM_DRAWITEM = &H2BPrivate Type DRAWITEMSTRUCT
CtlType As Long
CtlID As Long
itemID As Long
itemAction As Long
itemState As Long
hwndItem As Long
hDC As Long
rcItem As RECT
itemData As Long
End TypePrivate Declare Function GetWindowText Lib "user32" Alias _
"GetWindowTextA" (ByVal hWnd As Long, ByVal lpString As String, _
ByVal cch As Long) As Long
'Various GDI painting-related functions
Private Declare Function DrawText Lib "user32" Alias "DrawTextA" _
(ByVal hDC As Long, ByVal lpStr As String, ByVal nCount As Long, _
lpRect As RECT, ByVal wFormat As Long) As Long
Private Declare Function SetTextColor Lib "gdi32" (ByVal hDC As Long, _
ByVal crColor As Long) As Long
Private Declare Function SetBkMode Lib "gdi32" (ByVal hDC As Long, _
ByVal nBkMode As Long) As Long
Private Const TRANSPARENT = 1Private Const DT_CENTER = &H1
Public Enum TextVAligns
DT_VCENTER = &H4
DT_BOTTOM = &H8
End Enum
Private Const DT_SINGLELINE = &H20
Private Sub DrawButton(ByVal hWnd As Long, ByVal hDC As Long, _
rct As RECT, ByVal nState As Long)Dim s As String
Dim va As TextVAlignsva = GetProp(hWnd, "VBTVAlign")'Prepare DC for drawing
SetBkMode hDC, TRANSPARENT
SetTextColor hDC, GetProp(hWnd, "VBTForeColor")'Prepare a text buffer
s = String$(255, 0)
'What should we print on the button?
GetWindowText hWnd, s, 255
'Trim off nulls
s = Left$(s, InStr(s, Chr$(0)) - 1)If va = DT_BOTTOM Then
'Adjust specially for VB's CommandButton control
rct.Bottom = rct.Bottom - 4
End IfIf (nState And ODS_SELECTED) = ODS_SELECTED Then
'Button is in down state - offset
'the text
rct.Left = rct.Left + 1
rct.Right = rct.Right + 1
rct.Bottom = rct.Bottom + 1
rct.Top = rct.Top + 1
End IfDrawText hDC, s, Len(s), rct, DT_CENTER Or DT_SINGLELINE _
Or vaEnd SubPublic Function ExtButtonProc(ByVal hWnd As Long, _
ByVal wMsg As Long, ByVal wParam As Long, _
ByVal lParam As Long) As LongDim lOldProc As Long
Dim di As DRAWITEMSTRUCTlOldProc = GetProp(hWnd, "ExtBtnProc")ExtButtonProc = CallWindowProc(lOldProc, hWnd, wMsg, wParam, lParam)If wMsg = WM_DRAWITEM Then
CopyMemory di, ByVal lParam, Len(di)
If di.CtlType = ODT_BUTTON Then
If GetProp(di.hwndItem, "VBTCustom") = 1 Then
DrawButton di.hwndItem, di.hDC, di.rcItem, _
di.itemStateEnd IfEnd IfElseIf wMsg = WM_DESTROY Then
ExtButtonUnSubclass hWndEnd IfEnd FunctionPublic Sub ExtButtonSubclass(hWndForm As Long)Dim l As Longl = GetProp(hWndForm, "ExtBtnProc")
If l <> 0 Then
'Already subclassed
Exit Sub
End IfSetProp hWndForm, "ExtBtnProc", _
GetWindowLong(hWndForm, GWL_WNDPROC)
SetWindowLong hWndForm, GWL_WNDPROC, AddressOf ExtButtonProcEnd SubPublic Sub ExtButtonUnSubclass(hWndForm As Long)Dim l As Longl = GetProp(hWndForm, "ExtBtnProc")
If l = 0 Then
'Isn't subclassed
Exit Sub
End IfSetWindowLong hWndForm, GWL_WNDPROC, l
RemoveProp hWndForm, "ExtBtnProc"End SubPublic Sub SetButtonForecolor(ByVal hWnd As Long, _
ByVal lForeColor As Long, _
Optional ByVal VAlign As TextVAligns = DT_VCENTER)Dim hWndParent As LonghWndParent = GetParent(hWnd)
If GetProp(hWndParent, "ExtBtnProc") = 0 Then
ExtButtonSubclass hWndParent
End IfSetProp hWnd, "VBTCustom", 1
SetProp hWnd, "VBTForeColor", lForeColor
SetProp hWnd, "VBTVAlign", VAlignEnd SubPublic Sub RemoveButton(ByVal hWnd As Long)RemoveProp hWnd, "VBTCustom"
RemoveProp hWnd, "VBTForeColor"
RemoveProp hWnd, "VBTVAlign"End Sub
To use this, set the target command button's Style property to 1 - GraphicalEXAMPLES:To set command button forecolor(doesn't have to be in form_load)Private Sub Form_Load()
SetButtonForecolor Command1.Hwnd, vbBlue
End SubThat will set Command1's Forecolor to BlueTo remove the color(can be put anywhere)Private Sub Command2_Click()
RemoveButton Command1.Hwnd
Command1.Refresh
End Sub
Begin VB.Form Form1
Caption = "Form1"
ClientHeight = 3195
ClientLeft = 60
ClientTop = 345
ClientWidth = 4680
LinkTopic = "Form1"
ScaleHeight = 3195
ScaleWidth = 4680
StartUpPosition = 3 '窗口缺省
Begin VB.Line LinR
BorderColor = &H80000010&
BorderWidth = 2
X1 = 2880
X2 = 2880
Y1 = 1140
Y2 = 1500
End
Begin VB.Line LinD
BorderColor = &H80000010&
BorderWidth = 2
X1 = 1320
X2 = 2880
Y1 = 1500
Y2 = 1500
End
Begin VB.Line LinL
BorderColor = &H80000014&
BorderWidth = 2
X1 = 1320
X2 = 1320
Y1 = 1140
Y2 = 1500
End
Begin VB.Line LinU
BorderColor = &H80000014&
BorderWidth = 2
X1 = 1320
X2 = 2880
Y1 = 1140
Y2 = 1140
End
Begin VB.Label lblCommand
Alignment = 2 'Center
Caption = "确定(&O)"
BeginProperty Font
Name = "宋体"
Size = 10.5
Charset = 134
Weight = 400
Underline = 0 'False
Italic = 0 'False
Strikethrough = 0 'False
EndProperty
Height = 255
Left = 1380
TabIndex = 0
Top = 1200
Width = 1455
End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option ExplicitPrivate Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
lblCommand.ForeColor = &H80000012
End SubPrivate Sub lblCommand_Click()
MsgBox "你按下了确定!", vbInformation
End SubPrivate Sub lblCommand_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
If Button = 1 Then
LinU.BorderColor = &H80000010
LinL.BorderColor = &H80000010
LinR.BorderColor = &H80000014
LinD.BorderColor = &H80000014
End If
End SubPrivate Sub lblCommand_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
If Button = 0 Then
lblCommand.ForeColor = &HFF0000
End If
End SubPrivate Sub lblCommand_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
If Button = 1 Then
LinU.BorderColor = &H80000014
LinL.BorderColor = &H80000014
LinD.BorderColor = &H80000010
LinR.BorderColor = &H80000010
End If
End Sub
然后就可以模拟一个按钮Private Sub Check1_Click()
Check1.Value = 0
End SubPrivate Sub Form_Load()
Check1.BackColor = vbRed
Check1.ForeColor = vbWhite
End Sub
Private Sub Check1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
Check1.Value = 0
End SubPrivate Sub Form_Load()
Check1.BackColor = vbRed
Check1.ForeColor = vbWhite
End Sub
用 Hook 拦截 WM_CTLCOLORBTN 消息就可以了
不过没试过
WM_CTLCOLORBTN The WM_CTLCOLORBTN message is sent to the parent window of a button when the button is about to be drawn. By responding to this message, the parent window can set a button's text and background colors. WM_CTLCOLORBTN
hdcButton = (HDC) wParam; // handle of button display context
hwndButton = (HWND) lParam; // handle of button ParametershdcButton
Value of wParam. Identifies the display context for the button.
hwndButton
Value of lParam. Identifies the button. Return ValuesIf an application processes this message, it must return the handle of a brush. Windows uses the brush to paint the background of the button. Default ActionThe DefWindowProc function selects the default system colors for the button. ResThe WM_CTLCOLORBTN message is never sent between threads. It is sent only within one thread.
The text color of a check box or radio button applies to the box or button, its check , and the text. The focus rectangle for these buttons remains the system default color (typically black). The text color of a group box applies to the text but not to the line that defines the box. The text color of a push button applies only to its focus rectangle; it does not affect the color of the text.
http://expert.csdn.net/Expert/topic/1608/1608315.xml?temp=.7380335
字也显示了但不能正确显示,仅显一个字然后为一方框。
是否还能修改?正确显示中文呢?另问SSTAB的背景色也能用此方法修改吗?
只能运行时改变颜色,是吗?