Outlook 98-Style FlatHeader Control

CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

This FlatHeader control is my contribution to the effort of
mimicking all the new Microsoft flat style controls. Apart from
the look and feel of the Outlook 98 Header control, it extends
the functionality of the standard Header control with the
following features:

  • Optional size constraints,
  • Optional sorting arrow (without loosing the image nor
    bitmap options),
  • Fixes for the FULLDRAG redraw problem (images are not
    properly redrawn in a standard Header control).

It should be backward compatible wit the standard Header
control in most cases (even for owner drawn header items),
although the current implementation lacks the following features:

  • Item Text callbacks
  • Item Image callbacks
  • Hottracking
  • RTL reading
  • Unicode (not properly tested).

Depending on the feedback and my needs, I’ll extend the
implementation with proper support for these features.

The control can be applied as a straight dropin replacement
for the standard Header control by subclassing the standard
Header control of a CListCtrl control, by overiding the
PreSubclassWindow() in the CListCtrl:

void CFlatListCtrl::PreSubclassWindow()
{
	CListCtrl::PreSubclassWindow();
	VERIFY(m_wndFlatHeader.SubclassWindow(::GetDlgItem(m_hWnd,0)));
}

Or in a CListView:

int CFlatListView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CListView::OnCreate(lpCreateStruct) == -1)
		return -1;

	if (m_wndFlatHeader.SubclassWindow(GetListCtrl().GetDlgItem(0)->GetSafeHwnd()) == 0)
	{
		TRACE0("Unable to subclass header control.\n");
		return -1;
	}

	return 0;
}

Refer to the Demo project (or various CodeGuru articles) for
more information on using a subclassed header control in List
controls or List views.

The control is derived from CHeaderCtrl, and supports most of
the functionality of this control. Refer to the platform SDK and
MFC documentation for more information on using the CHeaderCtrl.

The CHeaderCtrl is extended with the following members:

	BOOL ModifyProperty(WPARAM wParam, LPARAM lParam);

	BOOL GetItemEx(INT iPos, HDITEMEX* phditemex) const;
	BOOL SetItemEx(INT iPos, HDITEMEX* phditemex);

	void SetSortColumn(INT iPos, BOOL bSortAscending);
	INT GetSortColumn(BOOL* pbSortAscending = NULL);
	INT GetDropResult();

ModifyProperty allows you to modify a
property of the control. wParam specifies the property, lParam
the new value of that property. 

wParam (Property) lParam (Data)
FH_PROPERTY_SPACING Text/image/bitmap/arrow spacing
FH_PROPERTY_ARROW size of the sorting arrow, use the MAKELPARAM macro with the
arrow’s cx value in wLow and the arrow’s cy value in wHigh.
FH_PROPERTY_STATICBORDER if lParam is other then 0, the control adjusts it’s layout
for CListCtrls that use the static border style.
FH_PROPERTY_DONTDROPCURSOR The resource ID of the cursor to be displayed when the user
drops a header item outside the header control or drop target.
FH_PROPERTY_DROPTARGET The handle of the window the user can drop a header item to.

GetItemEx/SetItemEx allow
you to get or set the extended features of a Header item, much
like the GetItem member of the standard control, however, the
functions do not require you specify a mask. Currently the
extended item structure only contains the minimum and maximum
width of an item. If the maximum size is smaller then the minimum
size, there will be no size constraints. These members may be
used in future versions to add more per item properties.

GetSortColumn/SetSortColumn
allow you to get or set the item that will display a sort arrow.
iPos identifies the item that will display the sort arrow,
setting iPos to -1 removes the sort arrow. bSortAscending
specifies the order (and is optional in the GetSortColumn).

GetDropResult indicates whether the drop occured in the control (0),
in the drop target(1) or outside the control or the drop target (-1).

Version history:

1.0.0.1	- Initial release
1.0.1.0	- Fixed FHDragWnd destroy warning (thanks Philippe Terrier)
	- Fixed double sent HDN_ITEMCLICK
	- Added a property that adjusts for ListCtrls that use a static
	  border for flat look.
	- Added sample list view support.
1.0.2.0	- Fixed another destroy warning
	- Fixed InsertItem array exception handling
	- Fixed incorrect header width painting
	- Changed DrawItem argument passing
	- Changed HDITEMEX struct item names
	- Added handler for HDM_SETIMAGELIST (precalculate image dimensions)
	- Changed DrawImage to clip images
	- Changed InsertItem ASSERT check to position limitation
	- Added new-style "HotDivider" arrows
	- Fixed some GDI objects
	- Added 'don't drop cursor' support to indicate drag&drop
	  outside control
	- Added drag&drop target window support
	- Changed CFHDragWnd to support externally created items
	- Removed topmost-style from CFHDropWnd
	- Fixed OnSetHotDivider order bug
	- Added extended styles
	- Added item width estimation function

The control uses Keith Rules MemDC class for flicker free
drawing.

Environment: VC6, Windows 98, NT4 (IE4).

Enjoy!

Downloads

Download demo project – 48 KB
Download source – 11 KB

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read