Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
ListView UI question
Message
From
31/07/2003 15:01:59
 
 
General information
Forum:
ASP.NET
Category:
WebForms
Miscellaneous
Thread ID:
00815212
Message ID:
00815570
Views:
14
Well, Neil, I guess I will have look into this if I want the end result bad enough. :) I truly appreciate the starting point skeleton. I guess this is why we make the proverbial big bucks...

Thanks again,

>Joe,
>
>The ListView class is just a wrapper around the common controls listview and as such you would have to employ a technique known as owner drawing the subitems. When the control needs to paint a specific area of the control it will send you a message notifying you of this, you respond by providing the code to perform the drawing and returning a notification code.
>
>The bad news is that in native C++ (with the platform SDK) this process is fairly easy, not so in dotnet. The following is a *rough* framework for doing this (educational purposes only), I have left out the details of drawing stuff using the Graphics class but it should give you a starting point.
>
>I am currently in the process of researching better ways of implementing this in C#.
>
>	#region WIN32STDSTUFF
>	[StructLayoutAttribute(LayoutKind.Sequential)]
>	public struct RECT
>	{
>		public int left;
>		public int top;
>		public int right;
>		public int bottom;
>	}
>	#endregion
>
>	#region NM_CustomStructures
>	[StructLayoutAttribute(LayoutKind.Sequential)]
>	public struct NMHDR
>	{
>		public IntPtr hwndFrom;
>		public int idFrom;
>		public int code;
>	}
>
>	[StructLayoutAttribute(LayoutKind.Sequential)]
>	public struct NMCUSTOMDRAW
>	{
>		public NMHDR hdr;
>		public int dwDrawStage;
>		public IntPtr hdc;
>		public RECT rc;
>		public uint dwItemSpec;
>		public uint uItemState;
>		public IntPtr lItemlParam;
>	}
>
>	[StructLayoutAttribute(LayoutKind.Sequential)]
>	public struct NMLVCUSTOMDRAW
>	{
>		public NMCUSTOMDRAW nmcd;
>		public uint clrText;
>		public uint clrTextBk;
>		public int iSubItem;
>	}
>
>	public enum HeaderControlMessages : int
>	{
>		HDM_FIRST        =  0x1200,
>		HDM_GETITEMRECT  = (HDM_FIRST + 7),
>		HDM_HITTEST      = (HDM_FIRST + 6),
>		HDM_SETIMAGELIST = (HDM_FIRST + 8),
>		HDM_GETITEMW     = (HDM_FIRST + 11),
>		HDM_ORDERTOINDEX = (HDM_FIRST + 15)
>	}
>	#endregion
>
>	#region Win32Messages
>	public enum Msg
>	{
>		WM_NULL                   = 0x0000,
>		WM_ERASEBKGND             = 0x0014,
>		WM_NOTIFY                 = 0x004E,
>		WM_COMMAND                = 0x0111,
>		WM_USER                   = 0x0400
>}
>
>	public enum NotififyMessages
>	{
>		NM_FIRST      = (0-0),
>		NM_CUSTOMDRAW = (NM_FIRST-12),
>		NM_NCHITTEST  = (NM_FIRST-14)
>	}
>
>	public enum ReflectedMessages
>	{
>		OCM__BASE				= (Msg.WM_USER+0x1c00),
>		OCM_COMMAND				= (OCM__BASE + Msg.WM_COMMAND),
>		OCM_NOTIFY              = (OCM__BASE + Msg.WM_NOTIFY)
>	}
>
>	public enum OwnerDrawnReturnFlags
>	{
>		CDRF_DODEFAULT          = 0x00000000,
>		CDRF_NEWFONT            = 0x00000002,
>		CDRF_SKIPDEFAULT        = 0x00000004,
>		CDRF_NOTIFYPOSTPAINT    = 0x00000010,
>		CDRF_NOTIFYITEMDRAW     = 0x00000020,
>		CDRF_NOTIFYSUBITEMDRAW  = 0x00000020,
>		CDRF_NOTIFYPOSTERASE    = 0x00000040
>	}
>
>	public enum OwnerDrawnStateFlags : uint
>	{
>		CDIS_SELECTED       = 0x0001,
>		CDIS_GRAYED         = 0x0002,
>		CDIS_DISABLED       = 0x0004,
>		CDIS_CHECKED        = 0x0008,
>		CDIS_FOCUS          = 0x0010,
>		CDIS_DEFAULT        = 0x0020,
>		CDIS_HOT            = 0x0040,
>		CDIS_MARKED         = 0x0080,
>		CDIS_INDETERMINATE  = 0x0100
>	}
>
>	public enum OwnerDrawnDrawStateFlags
>	{
>		CDDS_PREPAINT           = 0x00000001,
>		CDDS_POSTPAINT          = 0x00000002,
>		CDDS_PREERASE           = 0x00000003,
>		CDDS_POSTERASE          = 0x00000004,
>		CDDS_ITEM               = 0x00010000,
>		CDDS_ITEMPREPAINT       = (CDDS_ITEM | CDDS_PREPAINT),
>		CDDS_ITEMPOSTPAINT      = (CDDS_ITEM | CDDS_POSTPAINT),
>		CDDS_ITEMPREERASE       = (CDDS_ITEM | CDDS_PREERASE),
>		CDDS_ITEMPOSTERASE      = (CDDS_ITEM | CDDS_POSTERASE),
>		CDDS_SUBITEM            = 0x00020000
>	}
>	#endregion
>
>	public class OwnerDrawnListView : System.Windows.Forms.ListView
>	{
>		[DllImportAttribute("user32.dll", CharSet=CharSet.Auto)]
>		public static extern int SendMessage(IntPtr hWnd, HeaderControlMessages msg, int wParam, int lParam);
>
>		public OwnerDrawnListView()
>		{
>			SetStyle(ControlStyles.UserPaint, true);
>			FullRowSelect = true;
>			View = View.Details;
>		}
>	
>
>		protected override void WndProc(ref Message newmsg)
>		{
>			base.WndProc(ref newmsg);
>
>			switch (newmsg.Msg)
>			{
>//				case (int)Msg.WM_ERASEBKGND:
>//					IntPtr hDC = (IntPtr)newmsg.WParam;
>//					PaintBackground(hDC);
>
>//					break;
>
>				// WM_NOTIFY message come from the header.
>				case (int)Msg.WM_NOTIFY:
>					NMHDR nm1 = (NMHDR)newmsg.GetLParam(typeof(NMHDR));
>
>					switch(nm1.code)
>					{
>						case (int)NotififyMessages.NM_CUSTOMDRAW:
>// HeaderOwnerDraw(ref newmsg);
>							break;
>
>						default:
>							break;
>					}
>
>					break;
>
>				// Messages from the list itself are reflected using OCM_NOTIFY.
>				case (int)ReflectedMessages.OCM_NOTIFY:
>					NMHDR nm2 = (NMHDR) newmsg.GetLParam(typeof(NMHDR));
>
>					switch (nm2.code)
>					{
>						case (int)NotififyMessages.NM_CUSTOMDRAW:
>//							ListOwnerDraw(ref newmsg);
>							break;
>
>						default:
>							break;
>					}
>
>					break;
>
>					// Default
>				default:
>					break;
>			}
>		}
>
>		private bool ListOwnerDraw(ref Message m)
>		{
>			m.Result = (IntPtr)OwnerDrawnReturnFlags.CDRF_DODEFAULT;
>			NMCUSTOMDRAW nmcd = (NMCUSTOMDRAW)m.GetLParam(typeof(NMCUSTOMDRAW));
>			IntPtr thisHandle = Handle;
>
>			if ( nmcd.hdr.hwndFrom != Handle)
>				return false;
>
>			switch (nmcd.dwDrawStage)
>			{
>				case (int)OwnerDrawnDrawStateFlags.CDDS_PREPAINT:
>					// Ask for Item painting notifications
>					m.Result = (IntPtr)OwnerDrawnReturnFlags.CDRF_NOTIFYITEMDRAW;
>					break;
>
>				case (int)OwnerDrawnDrawStateFlags.CDDS_ITEMPREPAINT:
>					m.Result = (IntPtr)OwnerDrawnReturnFlags.CDRF_NOTIFYSUBITEMDRAW;
>					break;
>
>				case (int)(OwnerDrawnDrawStateFlags.CDDS_ITEMPREPAINT | OwnerDrawnDrawStateFlags.CDDS_SUBITEM):
>					// Draw our new custom background.
>					OwnerDrawListItem(ref m);
>					break;
>
>				default:
>					break;
>			}
>			return false;
>		}
>
>		void OwnerDrawListItem(ref Message m)
>		{
>			NMLVCUSTOMDRAW lvcd = (NMLVCUSTOMDRAW)m.GetLParam(typeof(NMLVCUSTOMDRAW));
>			
>			// Return a structure describing the outcome of the owner drawing process.
>
>//
>// -> Customer drawing goes here <-
>//
>
>			Marshal.StructureToPtr(lvcd, m.LParam, true);
>			m.Result = (IntPtr)OwnerDrawnReturnFlags.CDRF_SKIPDEFAULT;
>		}
>
>As you can see the owner drawing technique allows you the ultimate freedom when designing UI features but it does take some effort.
>
>HTH
>Neil
~Joe Johnston USA

"If ye love wealth better than liberty, the tranquility of servitude better than the animated contest of freedom, go home from us in peace. We ask not your counsel or arms. Crouch down and lick the hands which feed you. May your chains set lightly upon you, and may posterity forget that ye were our countrymen."
~Samuel Adams

Previous
Reply
Map
View

Click here to load this message in the networking platform