Outlook 98-Style FlatHeader Control

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