Over the last week, I have been searching and searching for a method that would allow me to change the background color of a DTPicker control. The reason I wanted to do this was as the user moves from field to field in my application, I highlight the current field that has focus. This worked fine for all the controls I used besides the DTPicker because it doesn't have a .back color property. I know you can change the colors of the dropdown calendar, but this is not what I wanted. I wanted to change the color of the entry portion of the field when the dropdown calendar wasn't displayed.

After not being able to find a method to accomplish this, I decided to tackle it myself. After a few hours, I came up with the following approach after seeing how other people have suggested or attempted to do it. Basically, you sublcass the DTPicker control to capture and monitor its messages. The message that I discovered that would need to be captured was WM_ERASEBKGND which occurs when the control is being created or refreshed. During this message, I simply get the rectangle area of the control and fill it with my desired highlighted color.

You than place your subclassing routine in the GotFocus event to highlight, and then remove the subclassing from the control in the lostfocus to remove the highlight.


I'm hoping somebody will come up with a better way to do this ( I didn't have much time to do this), but at least this puts people on the right track on how to make this functionality happen. I would be interested in better ways of doing this, but at least it works for me now.

*** USE AT YOUR OWN RISK ***

------------
DECLARATIONS
------------
Public Declare Function GetProp Lib "user32.dll" Alias "GetPropA" (ByVal hWnd As Long, ByVal lpString As String) As Long

Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

Public 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 Long

Public Declare Function DeleteObject Lib "gdi32" Alias "DeleteObject" (ByVal hObject As Long) As Long

Public Declare Function SetProp Lib "user32.dll" Alias "SetPropA" (ByVal hWnd As Long, ByVal lpString As String, ByVal hData As Long) As Long

Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long

Public Declare Function GetClientRect Lib "user32" Alias "GetClientRect" (ByVal hwnd As Long, lpRect As RECT) As Long

Public Declare Function CreateSolidBrush Lib "gdi32" Alias "CreateSolidBrush" (ByVal crColor As Long) As Long

Public Declare Function FillRect Lib "user32.dll" (ByVal hdc As Long, lpRect As RECT, ByVal hBrush As Long) As Long

Type RECT
left As Long
top As Long
right As Long
bottom As Long
End Type

Public Const GWL_WNDPROC = -4
Public Const WM_ERASEBKGND = &H14

-----------------------------------------------------------
Module Code That Work's To Subclass DTPicker Control Events
-----------------------------------------------------------
Note: You can probably use your own and it still will work.

Public Function DTPProc(ByVal hwnd As Long, ByVal iMsg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long

Select Case iMsg

Case WM_ERASEBKGND

Dim lngBrush As Long ' Brush color
Dim rct As RECT ' Rectangle structure

' Color of highlighted field
lngBrush = CreateSolidBrush(&HFFFF80)


' Get rectangle area of dtpicker control
GetClientRect hwnd, rct

' Fill rectangle area with highlight color
FillRect wParam, rct, lngBrush

' Remove object from memory
DeleteObject lngBrush

Exit Function

End Select

DTPProc = CallWindowProc(GetProp(hwnd, "OldDTPProc"), hwnd, _
iMsg, wParam, lParam)

* Note: The GetProp(hwnd, "OldDTPProc") command above is how I keep
a past reference to the old handle of the control. You should substitute
this with how you keep reference to the old handle.

---------------------------------
DTPicker Control's GotFocus Event
---------------------------------

Note: In this event, subclass your DTPicker control
so that it's events are captured. You probably can
use your own or the countless subclassing routines
that do this.

HookControl ' Name of the routine I used to hook the control.

DTPicker.Refresh ' Issue a refresh so the highlight can be displayed.

----------------------------------
DTPicker Control's LostFocus Event
----------------------------------

Note: In this event, remove the hook to the subclassed DTPicker.
You probably can use your own or the countless subclassing routines
that do this.

UnhookControl

DTPicker.Refresh ' Issue a refresh so the highlight is removed.

----------------------------------------------
HookControl Procedure - This is the one I use.
----------------------------------------------
' Stores previous instance of handle
Call SetProp(DTPicker.hwnd, "OldDTPProc", GetWindowLong(DT_Picker.hwnd, GWL_WNDPROC))

' Subclasses the dtpicker control
mlngPrevDTPProc = SetWindowLong(dtpicker.hwnd, _
GWL_WNDPROC, _
AddressOf DTPProc)

--------------------------------------
UnHookControl - This is the one I use.
--------------------------------------
' mlngdtpHandle = Variable I use to store handle to current control
' mlngPrevDTPProc = Variable I use to store old handle

SetWindowLong mlngDTPHandle, GWL_WNDPROC, mlngPrevDTPProc