Click here to Skip to main content
15,897,187 members
Articles / Programming Languages / C#

RCM v1.4 - Theming library: Customize the Appearance of Forms and Common Controls

Rate me:
Please Sign up or sign in to vote.
4.98/5 (49 votes)
27 Feb 2010CPOL11 min read 196.7K   5.3K   132  
A complete skinning engine; modify the appearance of forms, scrollbars, listviews, buttons, and most common controls.
  • rcm_1.4.zip
    • Harness
      • bin
        • Debug
      • frmMain.cs
      • frmMain.Designer.cs
      • frmMain.resx
      • obj
        • Debug
      • Program.cs
      • Properties
      • RCM_Harness.csproj
      • Resources
        • fader.png
        • gtk-cancel.png
        • Thumbs.db
        • vienna-checkbox.png
        • vienna-closebutton.png
        • vienna-combo.png
        • vienna-command.png
        • vienna-FrameBottom.png
        • vienna-FrameLeft.png
        • vienna-FrameRight.png
        • vienna-FrameTop.png
        • vienna-header.bmp
        • vienna-helpbutton.png
        • vienna-maxbutton.png
        • vienna-minbutton.png
        • vienna-Progress.bmp
        • vienna-radiobutton.png
        • vienna-restorebutton.png
        • vienna-ScrollHorzArrow.bmp
        • vienna-ScrollHorzShaft.bmp
        • vienna-ScrollHorzThumb.bmp
        • vienna-ScrollVertArrow.bmp
        • vienna-ScrollVertShaft.bmp
        • vienna-ScrollVertThumb.bmp
        • vienna-spin.bmp
        • vienna-Tab.png
        • vienna-thumb.png
        • vienna-Track.bmp
        • vista-checkbox.png
        • vista-closebutton.png
        • vista-combo.png
        • vista-command.png
        • vista-FrameBottom.png
        • vista-FrameLeft.png
        • vista-FrameRight.png
        • vista-FrameTop.png
        • vista-header.bmp
        • vista-helpbutton.png
        • vista-maxbutton.png
        • vista-minbutton.png
        • vista-Progress.bmp
        • vista-radiobutton.png
        • vista-restorebutton.png
        • vista-ScrollHorzArrow.bmp
        • vista-ScrollHorzShaft.bmp
        • vista-ScrollHorzThumb.bmp
        • vista-ScrollVertArrow.bmp
        • vista-ScrollVertShaft.bmp
        • vista-ScrollVertThumb.bmp
        • vista-spin.bmp
        • vista-Tab.png
        • vista-thumb.png
        • vista-Track.bmp
    • Images
      • fader.png
      • Thumbs.db
      • vienna-checkbox.png
      • vienna-closebutton.png
      • vienna-combo.png
      • vienna-command.png
      • vienna-FrameBottom.png
      • vienna-FrameLeft.png
      • vienna-FrameRight.png
      • vienna-FrameTop.png
      • vienna-header.bmp
      • vienna-helpbutton.png
      • vienna-maxbutton.png
      • vienna-minbutton.png
      • vienna-Progress.bmp
      • vienna-radiobutton.png
      • vienna-restorebutton.png
      • vienna-ScrollHorzArrow.bmp
      • vienna-ScrollHorzShaft.bmp
      • vienna-ScrollHorzThumb.bmp
      • vienna-ScrollVertArrow.bmp
      • vienna-ScrollVertShaft.bmp
      • vienna-ScrollVertThumb.bmp
      • vienna-spin.bmp
      • vienna-Tab.png
      • vienna-thumb.png
      • vienna-Track.bmp
      • vista-checkbox.png
      • vista-closebutton.png
      • vista-combo.png
      • vista-command.png
      • vista-FrameBottom.png
      • vista-FrameLeft.png
      • vista-FrameRight.png
      • vista-FrameTop.png
      • vista-header.bmp
      • vista-helpbutton.png
      • vista-maxbutton.png
      • vista-minbutton.png
      • vista-Progress.bmp
      • vista-radiobutton.png
      • vista-restorebutton.png
      • vista-ScrollHorzArrow.bmp
      • vista-ScrollHorzShaft.bmp
      • vista-ScrollHorzThumb.bmp
      • vista-ScrollVertArrow.bmp
      • vista-ScrollVertShaft.bmp
      • vista-ScrollVertThumb.bmp
      • vista-spin.bmp
      • vista-Tab.png
      • vista-thumb.png
      • vista-Track.bmp
    • RCM.sln
    • RCM
    • VBHarness
      • bin
        • Debug
      • frmMain.Designer.vb
      • frmMain.resx
      • frmMain.vb
      • My Project
      • obj
        • Debug
      • RCM_HarnessVB.vbproj
      • RCM_HarnessVB.vbproj.user
      • Resources
        • fader.png
        • gtk-cancel.png
        • vienna-checkbox.png
        • vienna-closebutton.png
        • vienna-combo.png
        • vienna-command.png
        • vienna-FrameBottom.png
        • vienna-FrameLeft.png
        • vienna-FrameRight.png
        • vienna-FrameTop.png
        • vienna-header.bmp
        • vienna-helpbutton.png
        • vienna-maxbutton.png
        • vienna-minbutton.png
        • vienna-Progress.bmp
        • vienna-radiobutton.png
        • vienna-restorebutton.png
        • vienna-ScrollHorzArrow.bmp
        • vienna-ScrollHorzShaft.bmp
        • vienna-ScrollHorzThumb.bmp
        • vienna-ScrollVertArrow.bmp
        • vienna-ScrollVertShaft.bmp
        • vienna-ScrollVertThumb.bmp
        • vienna-spin.bmp
        • vienna-Tab.png
        • vienna-thumb.png
        • vienna-Track.bmp
        • vista-checkbox.png
        • vista-closebutton.png
        • vista-combo.png
        • vista-command.png
        • vista-FrameBottom.png
        • vista-FrameLeft.png
        • vista-FrameRight.png
        • vista-FrameTop.png
        • vista-header.bmp
        • vista-helpbutton.png
        • vista-maxbutton.png
        • vista-minbutton.png
        • vista-Progress.bmp
        • vista-radiobutton.png
        • vista-restorebutton.png
        • vista-ScrollHorzArrow.bmp
        • vista-ScrollHorzShaft.bmp
        • vista-ScrollHorzThumb.bmp
        • vista-ScrollVertArrow.bmp
        • vista-ScrollVertShaft.bmp
        • vista-ScrollVertThumb.bmp
        • vista-spin.bmp
        • vista-Tab.png
        • vista-thumb.png
        • vista-Track.bmp
  • vtRCM.zip
    • RCM_Harness.exe
    • RCM_Harness.vshost.exe
    • RCM_Harness.vshost.exe.manifest
    • vtRCM.dll
    • WindowsFormsApplication1.vshost.exe.manifest
    • frmMain.cs
    • frmMain.Designer.cs
    • frmMain.resx
    • Program.cs
    • AssemblyInfo.cs
    • Resources.Designer.cs
    • Resources.resx
    • Settings.Designer.cs
    • Settings.settings
    • RCM_Harness.csproj
    • fader.png
    • gtk-cancel.png
    • vienna-checkbox.png
    • vienna-closebutton.png
    • vienna-combo.png
    • vienna-command.png
    • vienna-FrameBottom.png
    • vienna-FrameLeft.png
    • vienna-FrameRight.png
    • vienna-FrameTop.png
    • vienna-header.bmp
    • vienna-maxbutton.png
    • vienna-minbutton.png
    • vienna-Progress.bmp
    • vienna-radiobutton.png
    • vienna-restorebutton.png
    • vienna-ScrollHorzArrow.bmp
    • vienna-ScrollHorzShaft.bmp
    • vienna-ScrollHorzThumb.bmp
    • vienna-ScrollVertArrow.bmp
    • vienna-ScrollVertShaft.bmp
    • vienna-ScrollVertThumb.bmp
    • vienna-spin.bmp
    • vienna-Tab.png
    • vienna-thumb.png
    • vienna-Track.bmp
    • vista-checkbox.png
    • vista-closebutton.png
    • vista-combo.png
    • vista-command.png
    • vista-FrameBottom.png
    • vista-FrameLeft.png
    • vista-FrameRight.png
    • vista-FrameTop.png
    • vista-header.bmp
    • vista-maxbutton.png
    • vista-minbutton.png
    • vista-Progress.bmp
    • vista-radiobutton.png
    • vista-restorebutton.png
    • vista-ScrollHorzArrow.bmp
    • vista-ScrollHorzShaft.bmp
    • vista-ScrollHorzThumb.bmp
    • vista-ScrollVertArrow.bmp
    • vista-ScrollVertShaft.bmp
    • vista-ScrollVertThumb.bmp
    • vista-spin.bmp
    • vista-Tab.png
    • vista-thumb.png
    • vista-Track.bmp
    • fader.png
    • gt-checkbox.png
    • gt-closebutton.bmp
    • gt-combo.bmp
    • gt-command.bmp
    • gt-FrameBottom.png
    • gt-FrameLeft.png
    • gt-FrameRight.png
    • gt-FrameTop.png
    • gt-header.bmp
    • gt-maxbutton.bmp
    • gt-minbutton.bmp
    • gt-progress.bmp
    • gt-radiobutton.png
    • gt-restorebutton.bmp
    • gt-ScrollHorzArrow.bmp
    • gt-ScrollHorzShaft.bmp
    • gt-ScrollHorzThumb.png
    • gt-ScrollVertArrow.bmp
    • gt-ScrollVertShaft.bmp
    • gt-ScrollVertThumb.png
    • gt-spin.bmp
    • gt-Tab.png
    • gt-thumb.png
    • gt-Track.bmp
    • vienna-checkbox.png
    • vienna-closebutton.png
    • vienna-combo.png
    • vienna-command.png
    • vienna-FrameBottom.png
    • vienna-FrameLeft.png
    • vienna-FrameRight.png
    • vienna-FrameTop.png
    • vienna-header.bmp
    • vienna-maxbutton.png
    • vienna-minbutton.png
    • vienna-Progress.bmp
    • vienna-radiobutton.png
    • vienna-restorebutton.png
    • vienna-ScrollHorzArrow.bmp
    • vienna-ScrollHorzShaft.bmp
    • vienna-ScrollHorzThumb.bmp
    • vienna-ScrollVertArrow.bmp
    • vienna-ScrollVertShaft.bmp
    • vienna-ScrollVertThumb.bmp
    • vienna-spin.bmp
    • vienna-Tab.png
    • vienna-thumb.png
    • vienna-Track.bmp
    • vista-checkbox.png
    • vista-closebutton.png
    • vista-combo.png
    • vista-command.png
    • vista-FrameBottom.png
    • vista-FrameLeft.png
    • vista-FrameRight.png
    • vista-FrameTop.png
    • vista-header.bmp
    • vista-maxbutton.png
    • vista-minbutton.png
    • vista-Progress.bmp
    • vista-radiobutton.png
    • vista-restorebutton.png
    • vista-ScrollHorzArrow.bmp
    • vista-ScrollHorzShaft.bmp
    • vista-ScrollHorzThumb.bmp
    • vista-ScrollVertArrow.bmp
    • vista-ScrollVertShaft.bmp
    • vista-ScrollVertThumb.bmp
    • vista-spin.bmp
    • vista-Tab.png
    • vista-thumb.png
    • vista-Track.bmp
    • xbox_body_bottom.bmp
    • xbox_body_left.bmp
    • xbox_body_right.bmp
    • xbox_body_top.bmp
    • xbox_iconuis1_close.bmp
    • xbox_iconuis1_max1.bmp
    • xbox_iconuis1_max2.bmp
    • xbox_iconuis1_min.bmp
    • RCM.sln
    • vtRCM.dll
    • vtRCM.pdb
    • cButton.cs
    • cComboBox.cs
    • cGraphics.cs
    • cHeader.cs
    • cInternalScrollBar.cs
    • cListBox.cs
    • cListView.cs
    • cNumericUpDown.cs
    • cProgressBar.cs
    • cRCM.cs
    • cScrollBar.cs
    • cStoreDc.cs
    • cTabControl.cs
    • cThemeManager.cs
    • cToolTip.cs
    • cTrackBar.cs
    • cTransition.cs
    • cTreeView.cs
    • frmRef.cs
    • frmRef.Designer.cs
    • vtRCM.dll
    • ResolveAssemblyReference.cache
    • vtRCM.csproj.FileListAbsolute.txt
    • vtRCM.dll
    • vtRCM.pdb
    • AssemblyInfo.cs
    • vtRCM.csproj
    • RCM_HarnessVB.exe
    • RCM_HarnessVB.vshost.exe
    • RCM_HarnessVB.vshost.exe.manifest
    • RCM_HarnessVB.xml
    • vtRCM.dll
    • WindowsApplication1.exe
    • WindowsApplication1.vshost.exe
    • WindowsApplication1.vshost.exe.manifest
    • WindowsApplication1.xml
    • frmMain.Designer.vb
    • frmMain.resx
    • frmMain.vb
    • Application.Designer.vb
    • Application.myapp
    • AssemblyInfo.vb
    • Resources.Designer.vb
    • Resources.resx
    • Settings.Designer.vb
    • Settings.settings
    • RCM_HarnessVB.vbproj
    • RCM_HarnessVB.vbproj.user
    • fader.png
    • gtk-cancel.png
    • vienna-checkbox.png
    • vienna-closebutton.png
    • vienna-combo.png
    • vienna-command.png
    • vienna-FrameBottom.png
    • vienna-FrameLeft.png
    • vienna-FrameRight.png
    • vienna-FrameTop.png
    • vienna-header.bmp
    • vienna-maxbutton.png
    • vienna-minbutton.png
    • vienna-Progress.bmp
    • vienna-radiobutton.png
    • vienna-restorebutton.png
    • vienna-ScrollHorzArrow.bmp
    • vienna-ScrollHorzShaft.bmp
    • vienna-ScrollHorzThumb.bmp
    • vienna-ScrollVertArrow.bmp
    • vienna-ScrollVertShaft.bmp
    • vienna-ScrollVertThumb.bmp
    • vienna-spin.bmp
    • vienna-Tab.png
    • vienna-thumb.png
    • vienna-Track.bmp
    • vista-checkbox.png
    • vista-closebutton.png
    • vista-combo.png
    • vista-command.png
    • vista-FrameBottom.png
    • vista-FrameLeft.png
    • vista-FrameRight.png
    • vista-FrameTop.png
    • vista-header.bmp
    • vista-maxbutton.png
    • vista-minbutton.png
    • vista-Progress.bmp
    • vista-radiobutton.png
    • vista-restorebutton.png
    • vista-ScrollHorzArrow.bmp
    • vista-ScrollHorzShaft.bmp
    • vista-ScrollHorzThumb.bmp
    • vista-ScrollVertArrow.bmp
    • vista-ScrollVertShaft.bmp
    • vista-ScrollVertThumb.bmp
    • vista-spin.bmp
    • vista-Tab.png
    • vista-thumb.png
    • vista-Track.bmp
    • vtRCM
      • Harness
        • bin
        • frmMain.cs
        • frmMain.Designer.cs
        • frmMain.resx
        • Program.cs
        • Properties
        • RCM_Harness.csproj
        • Resources
          • gtk-cancel.png
          • vienna-checkbox.png
          • vienna-closebutton.png
          • vienna-combo.png
          • vienna-command.png
          • vienna-FrameBottom.png
          • vienna-FrameLeft.png
          • vienna-FrameRight.png
          • vienna-FrameTop.png
          • vienna-header.bmp
          • vienna-maxbutton.png
          • vienna-minbutton.png
          • vienna-Progress.bmp
          • vienna-radiobutton.png
          • vienna-restorebutton.png
          • vienna-ScrollHorzArrow.bmp
          • vienna-ScrollHorzShaft.bmp
          • vienna-ScrollHorzThumb.bmp
          • vienna-ScrollVertArrow.bmp
          • vienna-ScrollVertShaft.bmp
          • vienna-ScrollVertThumb.bmp
          • vienna-spin.bmp
          • vienna-Tab.png
          • vienna-thumb.png
          • vienna-Track.bmp
          • vista-checkbox.png
          • vista-closebutton.png
          • vista-combo.png
          • vista-command.png
          • vista-FrameBottom.png
          • vista-FrameLeft.png
          • vista-FrameRight.png
          • vista-FrameTop.png
          • vista-header.bmp
          • vista-maxbutton.png
          • vista-minbutton.png
          • vista-Progress.bmp
          • vista-radiobutton.png
          • vista-restorebutton.png
          • vista-ScrollHorzArrow.bmp
          • vista-ScrollHorzShaft.bmp
          • vista-ScrollHorzThumb.bmp
          • vista-ScrollVertArrow.bmp
          • vista-ScrollVertShaft.bmp
          • vista-ScrollVertThumb.bmp
          • vista-spin.bmp
          • vista-Tab.png
          • vista-thumb.png
          • vista-Track.bmp
      • Images
        • gt-checkbox.png
        • gt-closebutton.bmp
        • gt-combo.bmp
        • gt-command.bmp
        • gt-FrameBottom.png
        • gt-FrameLeft.png
        • gt-FrameRight.png
        • gt-FrameTop.png
        • gt-header.bmp
        • gt-maxbutton.bmp
        • gt-minbutton.bmp
        • gt-progress.bmp
        • gt-radiobutton.png
        • gt-restorebutton.bmp
        • gt-ScrollHorzArrow.bmp
        • gt-ScrollHorzShaft.bmp
        • gt-ScrollHorzThumb.png
        • gt-ScrollVertArrow.bmp
        • gt-ScrollVertShaft.bmp
        • gt-ScrollVertThumb.png
        • gt-spin.bmp
        • gt-Tab.png
        • gt-thumb.png
        • gt-Track.bmp
        • vienna-checkbox.png
        • vienna-closebutton.png
        • vienna-combo.png
        • vienna-command.png
        • vienna-FrameBottom.png
        • vienna-FrameLeft.png
        • vienna-FrameRight.png
        • vienna-FrameTop.png
        • vienna-header.bmp
        • vienna-maxbutton.png
        • vienna-minbutton.png
        • vienna-Progress.bmp
        • vienna-radiobutton.png
        • vienna-restorebutton.png
        • vienna-ScrollHorzArrow.bmp
        • vienna-ScrollHorzShaft.bmp
        • vienna-ScrollHorzThumb.bmp
        • vienna-ScrollVertArrow.bmp
        • vienna-ScrollVertShaft.bmp
        • vienna-ScrollVertThumb.bmp
        • vienna-spin.bmp
        • vienna-Tab.png
        • vienna-thumb.png
        • vienna-Track.bmp
        • vista-checkbox.png
        • vista-closebutton.png
        • vista-combo.png
        • vista-command.png
        • vista-FrameBottom.png
        • vista-FrameLeft.png
        • vista-FrameRight.png
        • vista-FrameTop.png
        • vista-header.bmp
        • vista-maxbutton.png
        • vista-minbutton.png
        • vista-Progress.bmp
        • vista-radiobutton.png
        • vista-restorebutton.png
        • vista-ScrollHorzArrow.bmp
        • vista-ScrollHorzShaft.bmp
        • vista-ScrollHorzThumb.bmp
        • vista-ScrollVertArrow.bmp
        • vista-ScrollVertShaft.bmp
        • vista-ScrollVertThumb.bmp
        • vista-spin.bmp
        • vista-Tab.png
        • vista-thumb.png
        • vista-Track.bmp
        • xbox_body_bottom.bmp
        • xbox_body_left.bmp
        • xbox_body_right.bmp
        • xbox_body_top.bmp
        • xbox_iconuis1_close.bmp
        • xbox_iconuis1_max1.bmp
        • xbox_iconuis1_max2.bmp
        • xbox_iconuis1_min.bmp
      • RCM.sln
      • RCM
      • VBHarness
        • bin
        • frmMain.Designer.vb
        • frmMain.resx
        • frmMain.vb
        • My Project
        • RCM_HarnessVB.vbproj
        • RCM_HarnessVB.vbproj.user
        • Resources
          • gtk-cancel.png
          • vienna-checkbox.png
          • vienna-closebutton.png
          • vienna-combo.png
          • vienna-command.png
          • vienna-FrameBottom.png
          • vienna-FrameLeft.png
          • vienna-FrameRight.png
          • vienna-FrameTop.png
          • vienna-header.bmp
          • vienna-maxbutton.png
          • vienna-minbutton.png
          • vienna-Progress.bmp
          • vienna-radiobutton.png
          • vienna-restorebutton.png
          • vienna-ScrollHorzArrow.bmp
          • vienna-ScrollHorzShaft.bmp
          • vienna-ScrollHorzThumb.bmp
          • vienna-ScrollVertArrow.bmp
          • vienna-ScrollVertShaft.bmp
          • vienna-ScrollVertThumb.bmp
          • vienna-spin.bmp
          • vienna-Tab.png
          • vienna-thumb.png
          • vienna-Track.bmp
          • vista-checkbox.png
          • vista-closebutton.png
          • vista-combo.png
          • vista-command.png
          • vista-FrameBottom.png
          • vista-FrameLeft.png
          • vista-FrameRight.png
          • vista-FrameTop.png
          • vista-header.bmp
          • vista-maxbutton.png
          • vista-minbutton.png
          • vista-Progress.bmp
          • vista-radiobutton.png
          • vista-restorebutton.png
          • vista-ScrollHorzArrow.bmp
          • vista-ScrollHorzShaft.bmp
          • vista-ScrollHorzThumb.bmp
          • vista-ScrollVertArrow.bmp
          • vista-ScrollVertShaft.bmp
          • vista-ScrollVertThumb.bmp
          • vista-spin.bmp
          • vista-Tab.png
          • vista-thumb.png
          • vista-Track.bmp
namespace RCM
{
    #region Directives
    using System;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Text;
    #endregion
 
    [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
    public class cHeader : NativeWindow, IDisposable
    {
        #region Constants
        // misc
        private const int GWL_STYLE = (-16);
        private const int GWL_EXSTYLE = (-20);
        private const int WS_ENABLED = 0x02;
        private const int CLR_NONE = -1;
        private const int ILD_TRANSPARENT = 0x1;
        // mouse buttons
        private const int VK_LBUTTON = 0x1;
        private const int VK_RBUTTON = 0x2;
        private const int SM_SWAPBUTTON = 23;
        // theming
        private const int HP_HEADERSORTARROW = 4;
        private const int HSAS_SORTEDUP = 1;
        private const int HSAS_SORTEDDOWN = 2;

        // header flags
        private const int HDF_LEFT = 0x0000;
        private const int HDF_RIGHT = 0x0001;
        private const int HDF_CENTER = 0x0002;
        private const int HDF_JUSTIFYMASK = 0x0003;
        private const int HDF_RTLREADING = 4;
        private const int HDF_OWNERDRAW = 0x8000;
        private const int HDF_STRING = 0x4000;
        private const int HDF_BITMAP = 0x2000;
        private const int HDF_BITMAP_ON_RIGHT = 0x1000;
        private const int HDF_IMAGE = 0x0800;
        private const int HDF_SORTUP = 0x0400;
        private const int HDF_SORTDOWN = 0x0200;
        private const int HDF_CHECKBOX = 0x0040;
        private const int HDF_CHECKED = 0x0080;
        private const int HDF_FIXEDWIDTH = 0x0100;
        private const int HDF_SPLITBUTTON = 0x1000000;
        private const int HDFT_ISSTRING = 0x0000;
        private const int HDFT_ISNUMBER = 0x0001;
        private const int HDFT_ISDATE = 0x0002;
        private const int HDFT_HASNOVALUE = 0x8000;
        // header item
        private const int HDI_WIDTH = 0x0001;
        private const int HDI_HEIGHT = HDI_WIDTH;
        private const int HDI_TEXT = 0x0002;
        private const int HDI_FORMAT = 0x0004;
        private const int HDI_LPARAM = 0x0008;
        private const int HDI_BITMAP = 0x0010;
        private const int HDI_IMAGE = 0x0020;
        private const int HDI_DI_SETITEM = 0x0040;
        private const int HDI_ORDER = 0x0080;
        private const int HDI_FILTER = 0x0100;
        private const int HDI_STATE = 0x0200;
        private const int HDIS_FOCUSED = 0x00000001;
        // header messages  
        private const int HDIS_STATE = 0x8;
        private const int HDM_FIRST = 0x1200;
        private const int HDM_GETITEMCOUNT = (HDM_FIRST + 0);
        private const int HDM_INSERTITEMA = (HDM_FIRST + 1);
        private const int HDM_INSERTITEMW = (HDM_FIRST + 10);
        private const int HDM_DELETEITEM = (HDM_FIRST + 2);
        private const int HDM_GETITEMA = (HDM_FIRST + 3);
        private const int HDM_GETITEMW = (HDM_FIRST + 11);
        private const int HDM_SETITEMA = (HDM_FIRST + 4);
        private const int HDM_SETITEMW = (HDM_FIRST + 12);
        private const int HDM_LAYOUT = (HDM_FIRST + 5);
        private const int HDM_HITTEST = (HDM_FIRST + 6);
        private const int HDM_GETITEMRECT = (HDM_FIRST + 7);
        private const int HDM_SETIMAGELIST = (HDM_FIRST + 8);
        private const int HDM_GETIMAGELIST = (HDM_FIRST + 9);
        private const int HDM_ORDERTOINDEX = (HDM_FIRST + 15);
        private const int HDM_CREATEDRAGIMAGE = (HDM_FIRST + 16);
        private const int HDM_GETORDERARRAY = (HDM_FIRST + 17);
        private const int HDM_SETORDERARRAY = (HDM_FIRST + 18);
        private const int HDM_SETHOTDIVIDER = (HDM_FIRST + 19);
        private const int HDM_SETBITMAPMARGIN = (HDM_FIRST + 20);
        private const int HDM_GETBITMAPMARGIN = (HDM_FIRST + 21);
        private const int HDM_SETFILTERCHANGETIMEOUT = (HDM_FIRST + 22);
        private const int HDM_EDITFILTER = (HDM_FIRST + 23);
        private const int HDM_CLEARFILTER = (HDM_FIRST + 24);
        private const int HDM_GETITEMDROPDOWNRECT = (HDM_FIRST + 25);
        private const int HDM_GETOVERFLOWRECT = (HDM_FIRST + 26);
        private const int HDM_GETFOCUSEDITEM = (HDM_FIRST + 27);
        private const int HDM_SETFOCUSEDITEM = (HDM_FIRST + 28);
        // header notify
        private const int HDN_FIRST = -300;
        private const int HDN_LAST = -399;
        private const int HDN_ITEMCHANGINGA = (HDN_FIRST - 0);
        private const int HDN_ITEMCHANGINGW = (HDN_FIRST - 20);
        private const int HDN_ITEMCHANGEDA = (HDN_FIRST - 1);
        private const int HDN_ITEMCHANGEDW = (HDN_FIRST - 21);
        private const int HDN_ITEMCLICKA = (HDN_FIRST - 2);
        private const int HDN_ITEMCLICKW = (HDN_FIRST - 22);
        private const int HDN_ITEMDBLCLICKA = (HDN_FIRST - 3);
        private const int HDN_ITEMDBLCLICKW = (HDN_FIRST - 23);
        private const int HDN_DIVIDERDBLCLICKA = (HDN_FIRST - 5);
        private const int HDN_DIVIDERDBLCLICKW = (HDN_FIRST - 25);
        private const int HDN_BEGINTRACKA = (HDN_FIRST - 6);
        private const int HDN_BEGINTRACKW = (HDN_FIRST - 26);
        private const int HDN_ENDTRACKA = (HDN_FIRST - 7);
        private const int HDN_ENDTRACKW = (HDN_FIRST - 27);
        private const int HDN_TRACKA = (HDN_FIRST - 8);
        private const int HDN_TRACKW = (HDN_FIRST - 28);
        private const int HDN_GETDISPINFOA = (HDN_FIRST - 9);
        private const int HDN_GETDISPINFOW = (HDN_FIRST - 29);
        private const int HDN_BEGINDRAG = (HDN_FIRST - 10);
        private const int HDN_ENDDRAG = (HDN_FIRST - 11);
        private const int HDN_FILTERCHANGE = (HDN_FIRST - 12);
        private const int HDN_FILTERBTNCLICK = (HDN_FIRST - 13);
        private const int HDN_BEGINFILTEREDIT = (HDN_FIRST - 14);
        private const int HDN_ENDFILTEREDIT = (HDN_FIRST - 15);
        private const int HDN_ITEMSTATEICONCLICK = (HDN_FIRST - 16);
        private const int HDN_ITEMKEYDOWN = (HDN_FIRST - 17);
        private const int HDN_DROPDOWN = (HDN_FIRST - 18);
        private const int HDN_OVERFLOWCLICK = (HDN_FIRST - 19);
        // header styles
        private const int HDS_HORZ = 0x0000;
        private const int HDS_BUTTONS = 0x0002;
        private const int HDS_HOTTRACK = 0x0004;
        private const int HDS_HIDDEN = 0x0008;
        private const int HDS_DRAGDROP = 0x0040;
        private const int HDS_FULLDRAG = 0x0080;
        private const int HDS_FILTERBAR = 0x0100;
        private const int HDS_FLAT = 0x0200;
        private const int HDS_CHECKBOXES = 0x0400;
        private const int HDS_NOSIZING = 0x0800;
        private const int HDS_OVERFLOW = 0x1000;
        // window messages
        private const int WM_MOUSEMOVE = 0x200;
        private const int WM_MOUSELEAVE = 0x2A3;
        private const int WM_LBUTTONDOWN = 0x201;
        private const int WM_LBUTTONUP = 0x202;
        private const int WM_MOUSEHOVER = 0x2A1;
        private const int WM_PAINT = 0xF;
        // message handler
        private static IntPtr MSG_HANDLED = new IntPtr(1);
        #endregion

        #region Enums
        private enum HITEST : int
        {
            HHT_NOWHERE = 0x0001,
            HHT_ONHEADER = 0x0002,
            HHT_ONDIVIDER = 0x0004,
            HHT_ONDIVOPEN = 0x0008,
            HHT_ONFILTER = 0x0010,
            HHT_ONFILTERBUTTON = 0x0020,
            HHT_ABOVE = 0x0100,
            HHT_BELOW = 0x0200,
            HHT_TORIGHT = 0x0400,
            HHT_TOLEFT = 0x0800,
            HHT_ONITEMSTATEICON = 0x1000,
            HHT_ONDROPDOWN = 0x2000,
            HHT_ONOVERFLOW = 0x4000
        }
        #endregion

        #region Structs
        [StructLayout(LayoutKind.Sequential)]
        private struct PAINTSTRUCT
        {
            internal IntPtr hdc;
            internal int fErase;
            internal RECT rcPaint;
            internal int fRestore;
            internal int fIncUpdate;
            internal int Reserved1;
            internal int Reserved2;
            internal int Reserved3;
            internal int Reserved4;
            internal int Reserved5;
            internal int Reserved6;
            internal int Reserved7;
            internal int Reserved8;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct RECT
        {
            internal RECT(int X, int Y, int Width, int Height)
            {
                this.Left = X;
                this.Top = Y;
                this.Right = Width;
                this.Bottom = Height;
            }
            internal int Left;
            internal int Top;
            internal int Right;
            internal int Bottom;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct HDITEM
        {
            internal int mask;
            internal int cxy;
            internal string pszText;
            internal IntPtr hbm;
            internal int cchTextMax;
            internal int fmt;
            internal IntPtr lParam;
            internal int iImage;
            internal int iOrder;
            internal uint type;
            internal IntPtr pvFilter;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct HDHITTESTINFO
        {
	        internal Point pt;
            internal HITEST flags;
	        internal int iItem;
        }
        #endregion

        #region API
        [DllImport("user32.dll")]
        private static extern IntPtr BeginPaint(IntPtr hWnd, ref PAINTSTRUCT ps);

        [DllImport("user32.dll")]
        private static extern bool EndPaint(IntPtr hWnd, ref PAINTSTRUCT ps);

        [DllImport("gdi32.dll")]
        private static extern IntPtr SelectObject(IntPtr hdc, IntPtr hObject);

        [DllImport("gdi32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool BitBlt(IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop);

        [DllImport("user32.dll")]
        private static extern IntPtr GetDC(IntPtr handle);

        [DllImport("user32.dll")]
        private static extern int ReleaseDC(IntPtr handle, IntPtr hdc);

        [DllImport("gdi32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool StretchBlt(IntPtr hDest, int X, int Y, int nWidth, int nHeight, IntPtr hdcSrc,
        int sX, int sY, int nWidthSrc, int nHeightSrc, int dwRop);

        [DllImport("user32.dll")]
        private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
        [DllImport("user32.dll")]
        private static extern IntPtr SendMessage (IntPtr hwnd, int msg, int wParam, ref HDITEM lParam);
        [DllImport("user32.dll")]
        private static extern IntPtr SendMessage(IntPtr hwnd, int msg, int wParam, ref RECT lParam);
        [DllImport("user32.dll")]
        private static extern IntPtr SendMessage(IntPtr hwnd, int msg, int wParam, ref HDHITTESTINFO lParam);
        
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool GetClientRect(IntPtr hWnd, ref RECT r);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool GetCursorPos(ref Point lpPoint);

        [DllImport("user32.dll")]
        private static extern int ScreenToClient(IntPtr hwnd, ref Point lpPoint);

        [DllImport("user32.dll")]
        private static extern int GetWindowLong(IntPtr hwnd, int nIndex);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool PtInRect([In] ref RECT lprc, Point pt);

        [DllImport("user32.dll")]
        private static extern bool ValidateRect(IntPtr hWnd, ref RECT lpRect);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);

        [DllImport("user32.dll")]
        private static extern int OffsetRect(ref RECT lpRect, int x, int y);

        [DllImport("uxtheme.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool IsAppThemed();

        [DllImport("uxtheme.dll", ExactSpelling = true, CharSet = CharSet.Unicode)]
        private static extern IntPtr OpenThemeData(IntPtr hWnd, String classList);

        [DllImport("uxtheme.dll", ExactSpelling = true)]
        private static extern int DrawThemeBackground(IntPtr hTheme, IntPtr hdc, int iPartId,
           int iStateId, ref RECT pRect, ref RECT pClipRect);

        [DllImport("uxtheme.dll", ExactSpelling = true)]
        private static extern int CloseThemeData(IntPtr hTheme);

        [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
        private static extern IntPtr GetParent(IntPtr hWnd);

        [DllImport("comctl32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool ImageList_DrawEx(IntPtr himl, int i, IntPtr hdcDst, int x, int y, int dx, int dy, int rgbBk, int rgbFg, int fStyle);

        [DllImport("comctl32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool ImageList_GetIconSize(IntPtr himl, out int cx, out int cy);

        [DllImport("user32.dll")]
        private static extern int GetSystemMetrics(int smIndex);

        [DllImport("user32.dll")]
        private static extern short GetKeyState(int nVirtKey);
        #endregion

        #region Fields
        private bool _bPainting = false;
        private IntPtr _hHeaderWnd = IntPtr.Zero;
        private cStoreDc _cHeaderDc = new cStoreDc();
        private Bitmap _oHeaderBitmap;
        #endregion

        #region Constructor
        public cHeader(IntPtr hWnd, Bitmap skin)
        {
            if (hWnd == IntPtr.Zero)
                throw new Exception("The header handle is invalid.");
            if (skin == null)
                throw new Exception("The header image is invalid.");
            HeaderGraphic = skin;
            _hHeaderWnd = hWnd;
            this.AssignHandle(_hHeaderWnd);
        }
        #endregion

        #region Properties
        private int ColumnCount
        {
            get { return (SendMessage(_hHeaderWnd, HDM_GETITEMCOUNT, 0, 0)); }
        }

        /// <summary>
        /// Get/Set Header bitmap.
        /// </summary>
        public Bitmap HeaderGraphic
        {
            get { return _oHeaderBitmap; }
            set
            {
                _oHeaderBitmap = value;
                if (_cHeaderDc.Hdc != IntPtr.Zero)
                {
                    _cHeaderDc.Dispose();
                    _cHeaderDc = new cStoreDc();
                }
                _cHeaderDc.Width = _oHeaderBitmap.Width;
                _cHeaderDc.Height = _oHeaderBitmap.Height;
                SelectObject(_cHeaderDc.Hdc, _oHeaderBitmap.GetHbitmap());
            }
        }
        #endregion

        #region Methods
        private int columnAtIndex(int column)
        {
            HDITEM hd = new HDITEM();
            hd.mask = HDI_ORDER;
            for (int i = 0; i < ColumnCount; i++)
            {
                if (SendMessage(_hHeaderWnd, HDM_GETITEMA, column, ref hd) != IntPtr.Zero)
                    return hd.iOrder;
            }
            return 0;
        }

        private void drawHeader()
        {
            RECT tr = new RECT();
            RECT wr = new RECT();
            cStoreDc tempDc = new cStoreDc();
            int offset = 0;

            // set up the temp dc
            GetWindowRect(_hHeaderWnd, ref wr);
            OffsetRect(ref wr, -wr.Left, -wr.Top);
            tempDc.Height = wr.Bottom;
            tempDc.Width = wr.Right;

            int width = _cHeaderDc.Width / 4;

            for (int i = 0; i < ColumnCount; i++) 
            {
                if (!Enabled())
                {
                    offset = width * 3;
                }
                else if (i == focusedColumn())
                {
                    if (leftKeyPressed())
                        offset = width * 2;
                    else
                        offset = width;
                }
                else
                {
                    offset = 0;
                }
                SendMessage(_hHeaderWnd, HDM_GETITEMRECT, i, ref tr);
                using (StretchImage st = new StretchImage(_cHeaderDc.Hdc, tempDc.Hdc, new Rectangle(offset, 0, width, _cHeaderDc.Height), new Rectangle(tr.Left, tr.Top, tr.Right - tr.Left, tr.Bottom - tr.Top), 3, StretchModeEnum.STRETCH_HALFTONE)) { }
                // button, icon, sort arrows and text
                if (hasButton(i))
                    drawButton(tempDc.Hdc, i, tr);
                if (hasSort(i))
                    drawSortArrow(tempDc.Hdc, i, tr);
                if (hasIcon(i))
                    drawIcon(tempDc.Hdc, i, tr);
                drawText(tempDc.Hdc, i, tr);
            }
            // draw the end piece
            SendMessage(_hHeaderWnd, HDM_GETITEMRECT, columnAtIndex(ColumnCount - 1), ref tr);
            int left = tr.Right;
            GetWindowRect(_hHeaderWnd, ref tr);
            OffsetRect(ref tr, -tr.Left, -tr.Top);
            tr.Left = left;
            tr.Right += 10;
            using (StretchImage st = new StretchImage(_cHeaderDc.Hdc, tempDc.Hdc, new Rectangle(0, 0, (_cHeaderDc.Width / 3) - 2, _cHeaderDc.Height), new Rectangle(tr.Left, tr.Top, tr.Right - tr.Left + 2, tr.Bottom - tr.Top), 3, StretchModeEnum.STRETCH_HALFTONE)) { }
            // blit the temp dc
            IntPtr hdc = GetDC(_hHeaderWnd);
            BitBlt(hdc, 0, 0, wr.Right, wr.Bottom, tempDc.Hdc, 0, 0, 0xCC0020);
            ReleaseDC(_hHeaderWnd, hdc);
            tempDc.Dispose();
        }

        private bool leftKeyPressed()
        {
            if (mouseButtonsSwitched())
                return (GetKeyState(VK_RBUTTON) < 0);
            else
                return (GetKeyState(VK_LBUTTON) < 0);
        }

        private bool mouseButtonsSwitched()
        {
            return (GetSystemMetrics(SM_SWAPBUTTON) != 0);
        }

        private void drawButton(IntPtr hdc, int column, RECT tr)
        {
            HITEST state = columnState();
            if (state == HITEST.HHT_ONHEADER || state == HITEST.HHT_ONDROPDOWN)
            {
                // as with windows implementation, only draw if column is in focus
                if (column == focusedColumn())
                {
                    RECT br = new RECT();
                    int offset = _cHeaderDc.Width / 3;
                    Point pt = new Point();

                    // get the button size
                    SendMessage(_hHeaderWnd, HDM_GETITEMDROPDOWNRECT, column, ref br);
                    int height = br.Bottom - br.Top;
                    int width = br.Right - br.Left;
                    // fix for position bug?
                    br.Left = tr.Right - (width + 2);
                    br.Right = br.Left + width;
                    using (Graphics g = Graphics.FromHdc(hdc))
                    {
                        using (Pen borderPen = new Pen(Color.FromKnownColor(KnownColor.ControlDark), 0.5f))
                            g.DrawRectangle(borderPen, new Rectangle(br.Left, br.Top, width, height - 3));
                    }
                    GetCursorPos(ref pt);
                    ScreenToClient(_hHeaderWnd, ref pt);
                    // if selected shade the button
                    if (PtInRect(ref br, pt))
                        drawFocusedButton(hdc, new Rectangle(br.Left, br.Top, width, height - 3), LinearGradientMode.Vertical);
                    br.Left += (width - 5) / 2;
                    br.Bottom = br.Top + 6;
                    br.Top = (height / 2) - 3;
                    // draw the arrow
                    drawArrow(hdc, new Rectangle(br.Left, br.Top, 12, 6), true);
                }
            }
        }

        private void drawFocusedButton(IntPtr hdc, Rectangle bounds, LinearGradientMode gradient)
        {
            using (Graphics g = Graphics.FromHdc(hdc))
            {
                // draw using anti alias
                using (GraphicsMode mode = new GraphicsMode(g, SmoothingMode.AntiAlias))
                {
                    // create the path
                    using (GraphicsPath buttonPath = createRoundRectanglePath(
                        g,
                        bounds.X, bounds.Y,
                        bounds.Width, bounds.Height,
                        1.0f))
                    {
                        // draw the outer edge
                        using (Pen borderPen = new Pen(Color.FromArgb(150, Color.SlateGray), 1f))
                            g.DrawPath(borderPen, buttonPath);
                    }
                    bounds.Inflate(-1, -1);

                    using (GraphicsPath buttonPath = createRoundRectanglePath(
                        g,
                        bounds.X, bounds.Y,
                        bounds.Width, bounds.Height,
                        1.0f))
                    {
                        // draw the inner edge
                        using (Pen borderPen = new Pen(Color.FromArgb(150, Color.DarkGray), 1.5f))
                            g.DrawPath(borderPen, buttonPath);

                        // create a thin gradient cover
                        using (LinearGradientBrush fillBrush = new LinearGradientBrush(
                            bounds,
                            Color.FromArgb(50, Color.White),
                            Color.FromArgb(50, Color.SlateGray),
                            gradient))
                        {
                            // shift the blend factors
                            Blend blend = new Blend();
                            blend.Positions = new float[] { 0f, .3f, .6f, 1f };
                            blend.Factors = new float[] { 0f, .5f, .8f, .2f };
                            fillBrush.Blend = blend;
                            // fill the path
                            g.FillPath(fillBrush, buttonPath);
                        }
                    }
                }
            }
        }

        private void drawSortArrow(IntPtr hdc, int column, RECT tr)
        {
            if (Environment.OSVersion.Version.Major > 5)
            {
                HDITEM hi = new HDITEM();
                hi.mask = HDI_FORMAT;
                SendMessage(_hHeaderWnd, HDM_GETITEMA, column, ref hi);
                int left = (tr.Right - tr.Left) / 2 - 4;
                Rectangle ar = new Rectangle(tr.Left + left, 0, 12, 6);
                if ((hi.fmt & (HDF_SORTDOWN)) == HDF_SORTDOWN)
                {
                    if (!drawThemeArrow(hdc, ar, true))
                        drawArrow(hdc, ar, true);
                }
                else
                {
                    if (!drawThemeArrow(hdc, ar, false))
                        drawArrow(hdc, ar, false);
                }
            }
        }

        private GraphicsPath createRoundRectanglePath(Graphics g, float X, float Y, float width, float height, float radius)
        {
            // create a path
            GraphicsPath pathBounds = new GraphicsPath();
            pathBounds.AddLine(X + radius, Y, X + width - (radius * 2), Y);
            pathBounds.AddArc(X + width - (radius * 2), Y, radius * 2, radius * 2, 270, 90);
            pathBounds.AddLine(X + width, Y + radius, X + width, Y + height - (radius * 2));
            pathBounds.AddArc(X + width - (radius * 2), Y + height - (radius * 2), radius * 2, radius * 2, 0, 90);
            pathBounds.AddLine(X + width - (radius * 2), Y + height, X + radius, Y + height);
            pathBounds.AddArc(X, Y + height - (radius * 2), radius * 2, radius * 2, 90, 90);
            pathBounds.AddLine(X, Y + height - (radius * 2), X, Y + radius);
            pathBounds.AddArc(X, Y, radius * 2, radius * 2, 180, 90);
            pathBounds.CloseFigure();
            return pathBounds;
        }

        private bool drawThemeArrow(IntPtr hdc, Rectangle bounds, bool down)
        {
            if (IsAppThemed())
            {
                IntPtr hTheme = OpenThemeData(GetParent(_hHeaderWnd), "Header");
                if (hTheme != IntPtr.Zero)
                {
                    RECT tr = new RECT(bounds.Left, bounds.Top, bounds.Right, bounds.Bottom);
                    // draw part
                    DrawThemeBackground(hTheme, hdc, HP_HEADERSORTARROW, down ? HSAS_SORTEDDOWN : HSAS_SORTEDUP, ref tr, ref tr);
                    CloseThemeData(hTheme);
                    return true;
                }
            }
            return false;
        }

        private void drawArrow(IntPtr hdc, Rectangle bounds, bool down)
        {
            using (Graphics g = Graphics.FromHdc(hdc))
            {
                using (GraphicsMode mode = new GraphicsMode(g, SmoothingMode.AntiAlias))
                {
                    using (GraphicsPath gp = new GraphicsPath())
                    {
                        if (down)
                        {
                            // draw the frame
                            gp.AddLine(new Point(bounds.X, bounds.Top), new Point(bounds.X + 4, bounds.Top));
                            gp.AddLine(new Point(bounds.X, bounds.Top), new Point(bounds.X + 2, bounds.Top + 2));
                            gp.AddLine(new Point(bounds.X + 2, bounds.Top + 2), new Point(bounds.X + 4, bounds.Top));
                            gp.CloseFigure();
                        }
                        else
                        {
                            gp.AddLine(new Point(bounds.X, bounds.Top + 4), new Point(bounds.X + 4, bounds.Top + 4));
                            gp.AddLine(new Point(bounds.X, bounds.Top + 4), new Point(bounds.X + 2, bounds.Top + 2));
                            gp.AddLine(new Point(bounds.X + 4, bounds.Top + 4), new Point(bounds.X + 2, bounds.Top + 2));
                            gp.CloseFigure();
                        }
                        // draw border
                        using (Pen borderPen = new Pen(Color.FromArgb(240, Color.Black), 0.5f))
                            g.DrawPath(borderPen, gp);
                        // fill path
                        using (Brush backBrush = new SolidBrush(Color.SlateGray))
                            g.FillPath(backBrush, gp);
                    }
                }
            }
        }

        private void drawIcon(IntPtr hdc, int column, RECT tr)
        {
            IntPtr iml = (IntPtr)SendMessage(_hHeaderWnd, HDM_GETIMAGELIST, HDIS_STATE, 0);
            if (iml != IntPtr.Zero)
            {
                int cx = 0;
                int cy = 0;
                HDITEM hi = new HDITEM();
                ImageList_GetIconSize(iml, out cx, out cy);
                hi.mask = HDI_IMAGE;
                SendMessage(_hHeaderWnd, HDM_GETITEMA, column, ref hi);
                tr.Top = (tr.Bottom - cy) / 2;
                tr.Left += 4;
                ImageList_DrawEx(iml, hi.iImage, hdc, tr.Left, tr.Top, cx, cy, CLR_NONE, 0, ILD_TRANSPARENT);
            }
        }

        private void drawText(IntPtr hdc, int column, RECT tr)
        {
            HDITEM hi = new HDITEM();
            hi.mask = HDI_TEXT | HDI_FORMAT | HDI_IMAGE;
            hi.cchTextMax = 255;
            hi.pszText = new String('0', 255);
            SendMessage(_hHeaderWnd, HDM_GETITEMA, column, ref hi);

            if (String.IsNullOrEmpty(hi.pszText))
                return;

            string text = hi.pszText;

            using (Graphics g = Graphics.FromHdc(hdc))
            {
                using (StringFormat sf = new StringFormat())
                {
                    g.SmoothingMode = SmoothingMode.AntiAlias;
                    g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
                    sf.Trimming = StringTrimming.EllipsisCharacter;
                    if ((hi.fmt & HDF_RIGHT) == HDF_RIGHT)
                    {
                        sf.Alignment = StringAlignment.Far;
                        sf.LineAlignment = StringAlignment.Center;
                    }
                    else if ((hi.fmt & HDF_CENTER) == HDF_CENTER)
                    {
                        sf.Alignment = StringAlignment.Center;
                        sf.LineAlignment = StringAlignment.Center;
                    }
                    else
                    {
                        sf.Alignment = StringAlignment.Near;
                        sf.LineAlignment = StringAlignment.Center;
                    }
                    if ((hi.fmt & HDF_IMAGE) == HDF_IMAGE)
                        tr.Left += 18;

                    if ((hi.fmt & HDF_RTLREADING) == HDF_RTLREADING)
                        sf.FormatFlags = StringFormatFlags.DirectionRightToLeft;

                    if (hasButton(column))
                        tr.Right -= 12;

                    Control ct = (ListView)Control.FromHandle(GetParent(_hHeaderWnd));
                    SizeF sz = g.MeasureString(text, ct.Font);
                    tr.Top = (tr.Bottom / 2) - (int)sz.Height;
                    tr.Bottom = tr.Top + (int)sz.Height;
                    // draw the text
                    using (Brush captionBrush = new SolidBrush(ct.ForeColor))
                        g.DrawString(text, ct.Font, captionBrush, new RectangleF(tr.Left, tr.Top + 5, tr.Right - tr.Left, tr.Bottom - tr.Top), sf);
                }
            }
        }

        private bool Enabled()
        {
            if ((GetWindowLong(_hHeaderWnd, GWL_STYLE) & WS_ENABLED) == WS_ENABLED)
                return true;
            return false;
        }

        private bool hasButton(int column)
        {
            if (Environment.OSVersion.Version.Major > 5)
            {
                HDITEM hi = new HDITEM();
                hi.mask = HDI_FORMAT;
                SendMessage(_hHeaderWnd, HDM_GETITEMA, columnAtIndex(column), ref hi);
                if ((hi.fmt & HDF_SPLITBUTTON) == HDF_SPLITBUTTON)
                    return true;
            }
            return false;
        }

        private bool hasIcon(int column)
        {
            HDITEM hi = new HDITEM();
            hi.mask = HDI_FORMAT;
            SendMessage(_hHeaderWnd, HDM_GETITEMA, column, ref hi);
            if ((hi.fmt & HDF_IMAGE) == HDF_IMAGE)
                return true;
            return false;
        }

        private bool hasSort(int column)
        {
            if (Environment.OSVersion.Version.Major > 5)
            {
                HDITEM hi = new HDITEM();
                hi.mask = HDI_FORMAT;
                SendMessage(_hHeaderWnd, HDM_GETITEMA, column, ref hi);
                if ((hi.fmt & (HDF_SORTUP | HDF_SORTDOWN)) > 0)
                    return true;
            }
            return false;
        }

        private HITEST columnState()
        {
            HDHITTESTINFO ht = new HDHITTESTINFO();
            GetCursorPos(ref ht.pt);
            ScreenToClient(_hHeaderWnd, ref ht.pt);
            SendMessage(_hHeaderWnd, HDM_HITTEST, 0, ref ht);

            if (ht.iItem != -1)
                return ht.flags;
            return HITEST.HHT_NOWHERE;
        }

        private int focusedColumn()
        {
            HDHITTESTINFO ht = new HDHITTESTINFO();
            GetCursorPos(ref ht.pt);
            ScreenToClient(_hHeaderWnd, ref ht.pt);
            SendMessage(_hHeaderWnd, HDM_HITTEST, 0, ref ht);
            return ht.iItem;
        }

        public void Dispose()
        {
            try
            {
                this.ReleaseHandle();
                if (_oHeaderBitmap != null) _oHeaderBitmap.Dispose();
                if (_cHeaderDc != null) _cHeaderDc.Dispose();
            }
            catch { }
        }
        #endregion

        #region WndProc
        protected override void WndProc(ref Message m)
        {
            PAINTSTRUCT ps = new PAINTSTRUCT();
            switch (m.Msg)
            {
                case WM_PAINT:
                    if (!_bPainting)
                    {
                        _bPainting = true;
                        // start painting engine
                        BeginPaint(m.HWnd, ref ps);
                        drawHeader();
                        ValidateRect(m.HWnd, ref ps.rcPaint);
                        // done
                        EndPaint(m.HWnd, ref ps);
                        _bPainting = false;
                        m.Result = MSG_HANDLED;
                    }
                    else
                    {
                        base.WndProc(ref m);
                    }
                    break;

                default:
                    base.WndProc(ref m);
                    break;
            }
        }
        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Network Administrator vtdev.com
Canada Canada
Network and programming specialist. Started in C, and have learned about 14 languages since then. Cisco programmer, and lately writing a lot of C# and WPF code, (learning Java too). If I can dream it up, I can probably put it to code. My software company, (VTDev), is on the verge of releasing a couple of very cool things.. keep you posted.

Comments and Discussions