|
Download the Flat Combo Box source code compiled directly into an EXE. (19kb) Download the Flat Combo Box DLL and source (25kb)
  |
Source Code Note
|
  |
  |
|
This DLL is a binary compatible component which works with all other samples.
If you compile your own copy of this DLL yourself please make sure you change
the name. See disclaimer and license for more details.
|
  |
  |
Before you Begin
|
  |
  |
|
This project requires the SSubTmr.DLL component. Make sure you have loaded and registered this before trying the project.
|
  |
Overview
This project demonstrates how to subclass Combo Boxes and other controls so that they
draw like the in a flat style but highlight raised when the mouse is over or they are
in focus. With standard VB Combo Boxes, ComboBoxEx controls and
vbAccelerator Owner Combo and List Box controls the drawing style emulates the Office 97 flat
combo boxes in the format toolbar, right down to drawing the drop-down button "pressed in" when
the drop-down is showing.
This code was originally based on an excellent MFC sample
written by Kirk Stowell (his MFC-only site, Code Jockey, is at
http://www.geocities.com/SiliconValley/Haven/8230/.). It has been restructured for this version to allow other
controls to gain the mouse highlighting style (thanks to Peter Siebler for his suggestion on how this can work), to
support ComboBoxEx controls (thanks to Paul Wilde)
and also to emulate the Office 97 toolbar style more accurately. The original version of this
code (for combo boxes only) is still available, but I recommend using
this version because it does work more nicely than the original.
How Does It Work?
Combo boxes normally draw their own sunken border and a button border around the drop-down button. This code
takes the sneaky approach of intercepting the painting messages and drawing over the default borders with
nice new ones. Here are the messages that are subclassed:
- WM_PAINT
- WM_MOUSEMOVE
- WM_LBUTTONDOWN
- WM_LBUTTONUP
On receiving one of these messages, the code gets the Combo box's DC and then paints over
the sunken and raised borders so that they appear either flat (when the mouse is not over) or
with a soft edge when the mouse is over. Smart!
The code also ensures that it correctly identifies when the mouse moves off the control by
creating a temporary API timer in code. Timer events are responded to by subclassing the WM_TIMER
message sent to the combo box's window handle.
Subclassing other controls cannot be achieved by drawing over the existing border. However, Peter Siebler
pointed out that you can draw a border on the control's container. So if you set the border-style of the
control to None, the DLL can achieve the mouse-over highlighting effect by drawing on the control's container.
How to Make Your Combo Boxes and Controls Flat
This is the easy bit!
There are two versions of this code. One is a private class module (15kb) which you
can compile directly into your executable. The other is exactly the same class built into an ActiveX DLL (25kb).
The reason for providing the DLL is to make it easier to debug code using this class. Because the class
has to subclass the WM_PAINT message, when you break in VB's IDE many events can fire which make
it difficult to debug (and, in the worst case, could cause a crash!). By using the DLL, you don't need to
worry about these problems because all the subclassing
code is isolated from your project. (And since the DLL is binary compatible, and supported, you can ship it
with your project as well).
Start a new project, and add a combo box to the form. If you are using the DLL, add a reference to it (it
will appear as "vbAccelerator Flat Combo Box Extender" in the references list. (Make sure you
have registered vbalFCtl.dll and SSubTmr.Dll before doing this). Otherwise, add the cFlatControl.cls file
to your project.
Then you only need two lines of code:
' In the declarations section of the form:
Private m_c As New cFlatControl
Private Sub Form_Load()
   
' Attach your combo box to the flat combo box
   
' drawing routines:
    m_c.Attach cboThis
End Sub
Erm, and that's it. If you want to give multiple controls in a form a flat style, a simple way to
do is to declare an array of cFlatControl classes and enumerate through the controls in the form,
setting the style:
' In the declarations section of the form:
Private m_c() As cFlatControl
Private m_iCount As Long
Private Sub Form_Load()
Dim ctl As Control
For Each ctl In Controls
If TypeName(ctl) = "ComboBox" Then
m_iCount = m_iCount + 1
ReDim Preserve m_cFlatten(1 To m_iCount) As cFlatControl
Set m_cFlatten(m_iCount) = New cFlatControl
m_cFlatten(m_iCount).Attach ctl
End If
Next
End Sub
In fact, a good addition to this project would be a new class which just maintains
a pretend collection of cFlatControl objects and makes it even quicker to set
up a large number of controls to the flat style. However, in time-honoured programmer's
guide fashion, I leave the implementation of this as an exercise for the reader!
Hope you find it useful. Also, check out the
Creating Flat Combo Boxes in a Rebar sample.
A Note
Kirk Stowell asks on his site that people using code based on his work give him some sort of
credit in the About box or copyright notice of an application.
"Portions of this code are copyright © 1998 Kirk Stowell (kstowel@sprynet.com).
Visit CodeJockey at http://www.geocities.com/SiliconValley/Haven/8230/"
vbAccelerator, has no requirements but is thankful for
credits and would love to hear about your app!
|
  |