How to: Use a Helper Class for Platform Invokes

This sample program encapsulates the structures, platform invoke declarations, and the delegate for calling native window procedures. The following topics use this class:

How to: Subclass a TreeView by Using Native Callbacks

How to: Subclass a Button by Using Native Callbacks

This example program is described in detail in Subclassing Controls with a Managed Window Procedure.

Example

using System;
using System.Drawing;
using System.Runtime.InteropServices;

// Contains managed wrappers and implementations of Win32 
// structures, delegates, constants and platform invokes 
// used by the GradientFill and Subclassing samples. 

public sealed class Win32
    {
        public struct TRIVERTEX
        {
            public int x;
            public int y;
            public ushort Red;
            public ushort Green;
            public ushort Blue;
            public ushort Alpha;
            public TRIVERTEX(int x, int y, Color color)
                : this(x, y, color.R, color.G, color.B, color.A)
            {
            }
            public TRIVERTEX(
                int x, int y,
                ushort red, ushort green, ushort blue,
                ushort alpha)
            {
                this.x = x;
                this.y = y;
                this.Red = (ushort)(red << 8);
                this.Green = (ushort)(green << 8);
                this.Blue = (ushort)(blue << 8);
                this.Alpha = (ushort)(alpha << 8);
            }
        }
        public struct GRADIENT_RECT
        {
            public uint UpperLeft;
            public uint LowerRight;
            public GRADIENT_RECT(uint ul, uint lr)
            {
                this.UpperLeft = ul;
                this.LowerRight = lr;
            }
        }
        public struct GRADIENT_TRIANGLE
        {
            public uint Vertex1;
            public uint Vertex2;
            public uint Vertex3;
            public GRADIENT_TRIANGLE(uint v1, uint v2, uint v3)
            {
                this.Vertex1 = v1;
                this.Vertex2 = v2;
                this.Vertex3 = v3;
            }
        }

        // WM_NOTIFY notification message header.
        [System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
        public class NMHDR
        {
            private IntPtr hwndFrom;
            public uint idFrom;
            public uint code;
        }

        //[System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)] 
        public struct TVITEM
        {
            public int mask;
            private IntPtr hItem;
            public int state;
            public int stateMask;
            private IntPtr pszText;
            public int cchTextMax;
            public int iImage;
            public int iSelectedImage;
            public int cChildren;
            private IntPtr lParam;
        }

        // Native representation of a point. 
        public struct POINT
        {
            public int X;
            public int Y;
        }

        public struct TVHITTESTINFO
        {
            public POINT pt;
            public uint flags;
            private IntPtr hItem;
        }

        // A callback to a Win32 window procedure (wndproc): 
        // Parameters: 
        //   hwnd - The handle of the window receiving a message. 
        //   msg - The message 
        //   wParam - The message's parameters (part 1). 
        //   lParam - The message's parameters (part 2). 
        //  Returns an integer as described for the given message in MSDN. 
        public delegate int WndProc(IntPtr hwnd, uint msg, uint wParam, int lParam);

        [DllImport("coredll.dll", SetLastError = true, EntryPoint = "GradientFill")]
        public extern static bool GradientFill(
            IntPtr hdc,
            TRIVERTEX[] pVertex,
            uint dwNumVertex,
            GRADIENT_RECT[] pMesh,
            uint dwNumMesh,
            uint dwMode);

        public const int GRADIENT_FILL_RECT_H = 0x00000000;
        public const int GRADIENT_FILL_RECT_V = 0x00000001;

        // Not supported on Windows CE: 
        public const int GRADIENT_FILL_TRIANGLE = 0x00000002;


        [DllImport("coredll.dll")]
        public extern static IntPtr SetWindowLong(
            IntPtr hwnd, int nIndex, IntPtr dwNewLong);
        public const int GWL_WNDPROC = -4;

        [DllImport("coredll.dll")]
        public extern static int CallWindowProc(
            IntPtr lpPrevWndFunc, IntPtr hwnd, uint msg, uint wParam, int lParam);

        [DllImport("coredll.dll")]
        public extern static int DefWindowProc(
            IntPtr hwnd, uint msg, uint wParam, int lParam);

        [DllImport("coredll.dll")]
        public extern static int SendMessage(
            IntPtr hwnd, uint msg, uint wParam, ref TVHITTESTINFO lParam);

        [DllImport("coredll.dll", SetLastError = true)]
        public extern static int SendMessage(
            IntPtr hwnd, uint msg, uint wParam, ref TVITEM lParam);

        [DllImport("coredll.dll")]
        public extern static uint GetMessagePos();

        [DllImport("coredll.dll")]
        public extern static IntPtr BeginPaint(IntPtr hwnd, ref PAINTSTRUCT ps);

        [DllImport("coredll.dll")]
        public extern static bool EndPaint(IntPtr hwnd, ref PAINTSTRUCT ps);

        public struct PAINTSTRUCT
        {
            private IntPtr hdc;
            public bool fErase;
            public Rectangle rcPaint;
            public bool fRestore;
            public bool fIncUpdate;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
            public byte[] rgbReserved;
        }

        [DllImport("coredll.dll")]
        public extern static IntPtr GetDC(IntPtr hwnd);

        [DllImport("coredll.dll")]
        public extern static bool ReleaseDC(IntPtr hwnd, IntPtr hdc);

        // Helper function to convert a Windows lParam into a Point. 
        //   lParam - The parameter to convert. 
        // Returns a Point where X is the low 16 bits and Y is the 
        // high 16 bits of the value passed in. 
        public static Point LParamToPoint(int lParam)
        {
            uint ulParam = (uint)lParam;
            return new Point(
                (int)(ulParam & 0x0000ffff),
                (int)((ulParam & 0xffff0000) >> 16));
        }

        // Windows messages 
        public const uint WM_PAINT = 0x000F;
        public const uint WM_ERASEBKGND = 0x0014;
        public const uint WM_KEYDOWN = 0x0100;
        public const uint WM_KEYUP = 0x0101;
        public const uint WM_MOUSEMOVE = 0x0200;
        public const uint WM_LBUTTONDOWN = 0x0201;
        public const uint WM_LBUTTONUP = 0x0202;
        public const uint WM_NOTIFY = 0x4E;

        // Notifications 
        public const uint NM_CLICK = 0xFFFFFFFE;
        public const uint NM_DBLCLK = 0xFFFFFFFD;
        public const uint NM_RCLICK = 0xFFFFFFFB;
        public const uint NM_RDBLCLK = 0xFFFFFFFA;

        // Key 
        public const uint VK_SPACE = 0x20;
        public const uint VK_RETURN = 0x0D;

        // Treeview 
        public const uint TV_FIRST = 0x1100;
        public const uint TVM_HITTEST = TV_FIRST + 17;

        public const uint TVHT_NOWHERE = 0x0001;
        public const uint TVHT_ONITEMICON = 0x0002;
        public const uint TVHT_ONITEMLABEL = 0x0004;
        public const uint TVHT_ONITEM = (TVHT_ONITEMICON | TVHT_ONITEMLABEL | TVHT_ONITEMSTATEICON);
        public const uint TVHT_ONITEMINDENT = 0x0008;
        public const uint TVHT_ONITEMBUTTON = 0x0010;
        public const uint TVHT_ONITEMRIGHT = 0x0020;
        public const uint TVHT_ONITEMSTATEICON = 0x0040;
        public const uint TVHT_ABOVE = 0x0100;
        public const uint TVHT_BELOW = 0x0200;
        public const uint TVHT_TORIGHT = 0x0400;
        public const uint TVHT_TOLEFT = 0x0800;

        public const uint TVM_GETITEM = TV_FIRST + 62;  //TVM_GETITEMW 

        public const uint TVIF_TEXT = 0x0001;
        public const uint TVIF_IMAGE = 0x0002;
        public const uint TVIF_PARAM = 0x0004;
        public const uint TVIF_STATE = 0x0008;
        public const uint TVIF_HANDLE = 0x0010;
        public const uint TVIF_SELECTEDIMAGE = 0x0020;
        public const uint TVIF_CHILDREN = 0x0040;
        public const uint TVIF_DI_SETITEM = 0x1000;

}

See Also

Tasks

How to: Use a Class for Hooking Windows Procedures

How to: Subclass a TreeView by Using Native Callbacks

How to: Subclass a Button by Using Native Callbacks

Concepts

Subclassing Controls with a Managed Window Procedure

.NET Compact Framework How-to Topics

Other Resources

Interoperability in the .NET Compact Framework