Download source files - 19 Kb
Download demo project - 10 Kb
Overview
This article describes how I implemented the owner drawn section of this font preview
combo box. I will not write about window sub classing but I make use of a subclasses class from which I inherited. I will guide you in detailed steps on how you can make use of this
subclasses control in your own programs.
How I came up with this combo box with font preview
It is some time ago that I started up Word2000 for the first time. I noticed some thing like flat controls, the cool rebar implementation and the most imported one, that cool looking
font selector which previewed the fonts while you are scrolling. I then downloaded kPad from Konstantin Bukreev in the beginning of august 2000 and it almost had the look and feel of Office2000 (the rebar that is), but it
lacked the cool font selector. I then decided to implement it because the kPad source already comes with a
subclasses font combo box.
Requirements
Before you continue downloading the source to use it you should make sure that you have downloaded the Platform SDK with the WTL header files (see another article on this site). I included the original include files for kFlatCombo, kFontCombo and atl/aux (last one by Andrew Nosenko). I altered the kFontCombo implementation because some
data members where private thus not accessible with inheritance. You should also have knowledge about
owner drawn controls and sub classing in WTL if you want to understand the source.
How I did it
As I noted in Overview I primarily relied on classes/code of other developers. I inherited from kFontCombo
after I changed it's
data members from private
to protected
so I could access them from within the new subclass. I then used the WTL chaining method to
receive messages from it's base class. Owner drawn You can see that the combo box
as in the screenshot above does not contain only text items. It draws the true type
symbol when appropriate and previews the font with it's own font name just like the Word2000
font selector. Besides that it also inherits behavior to that it acts like a flat control. You can put anything in a
combo box by overriding the MeasureItem
and DrawItem
methods. Windows will iterate through all items in the
combo box and will ask you it's dimensions for each item by calling (MeasureItem)> After this it will ask you to draw each item and will give you information about the available dimensions (DrawItem). When Windows request
each item it's minimal dimensions I return 0 for the width and 20 pixels for it's height. Then Windows wants me to draw the content for
each item and I just retrieve the font name from the base class, create a font object with the name, I draw the text, restore the previous font and voila.
LRESULT OnMeasureItem(UINT , WPARAM ,
LPARAM lParam, BOOL& )
{
MEASUREITEMSTRUCT* pmis = reinterpret_cast<MEASUREITEMSTRUCT*>(lParam);
ATLASSERT(pmis->CtlType == ODT_COMBOBOX);
if (m_cyItem == -1)
{
CClientDC dc(m_hWnd);
HFONT hFont = ((HFONT)GetStockObject( DEFAULT_GUI_FONT ));
dc.SelectFont( hFont );
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);
pmis->itemHeight = tm.tmHeight + tm.tmInternalLeading;
}else
m_cyItem = 20;
pmis->itemHeight = m_cyItem;
return TRUE;
}
RESULT OnDrawItem(UINT , WPARAM ,
LPARAM lParam, BOOL& )
{
CFont cf;
cf.CreateFont(20,0,0,0,FW_NORMAL,FALSE, FALSE, FALSE,
DEFAULT_CHARSET ,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
ANTIALIASED_QUALITY,DEFAULT_PITCH,psFont);
HFONT hf = dc.SelectFont(cf);
dc.TextOut(rc.left+10, rc.top, psFont);
dc.SelectFont(hf);
}
How to use it in your own applications
I will explain how to use this class in your own application with the use of my demo application. Just download the source to take a look at it.
- After have opened the project file you can see that I just added a normal
combo box on the dialog
- To use the new class you will have to include its header file and the header files on which it depends. These are "AtlAux2.h", "kFlatCombo.h", "kFontCombo.h" and "rsPreviewFontCombo.h" and are located in the 'include' directory.
- Add a data member to the class that implements the dialog (
CMainDlg
in this demo app) of the type rsFontPreviewCombo
.
- Initialize the combo box by adding the following code to the
OnInitDialog
method of the dialog class:
RECT rc;
::GetWindowRect(GetDlgItem(IDC_COMBO_FONT), &rc);
::DestroyWindow(GetDlgItem(IDC_COMBO_FONT));
ScreenToClient(&rc);
rc.bottom += 150;
m_comboFontName.CreateEx(m_hWnd, rc, -1, IDC_COMBO_FONT);
- The last thing to do is to add message reflection so the subclasses controls will receive messages. If you do not add
REFLECT_NOTIFICATIONS()
to the
message map then the combo box will not contain anything.
Rules of engagement
I hope that this article makes any sense so that you can use (and abuse) it in anyway. Please extend,
bug fix and improve it as you wish. It would be nice if you would credit me (and the others) somewhere in your program or documentation if you consider all the time invested in these routines and writing articles.
About me, myself and I:
My name is Ramon Smits and I live in the Netherlands near Rotterdam. My profession is software development and I work for the company InfoSupport. I develop using the programming languages C++, VB, (D)HTML, JavaScript, ASP, T-SQL. Languages that I used in the past are Borland Pascal and even x86 assembler (I still use it if I really have to). I am also familiar with COM/MTS, COM+, ATL/WTL, STL, OLEDB, ADO, DirectX. So you could say that you can put me everywhere in an n-tier environment :-). I have knowledge about SDM-II, Yourdon, Staged Delivery, OMT/UML and general OO design.
At work I develop according the Microsoft DNA structure (this will eventually be .NET
of course) with (primarily) ASP, VB, SQL. But when I'm at home I and I really do not have anything
to-do except watching Jerry Springer I turn on my nice old computer and do some cool coding. I have common knowledge about 3D engines, particle systems and general graphics programming. If you want to know more about me then visit my website @ http://www.exyll.com
Mail me bugs, flames, comments, suggestions, improvements or just for fun.
I have also written another article on this site about how to get a gradient sidebar in your menus with WTL.