CreateParams in the Compact Framework

290 views Asked by At

I'm using the .NET Compact Framework and would like to subclass a PictureBox control (in this case to remove the CS_DBLCLKS style from specific instances of the PictureBox control). The code below works on .NET standard, but not the Compact Framework:

using System;
using System.Windows.Forms;

namespace NoDblClick
{
    public partial class NoDblClickPicControl : PictureBox
    {
        private const int CS_DBLCLKS = 0x008;
        public NoDblClickPicControl()
        {
        }

        protected override CreateParams CreateParams
        {
            get
            {
                // No compile, missing directive or assembly directive
                CreateParams cp = base.CreateParams;
                cp.ClassStyle &= ~CS_DBLCLKS;
                return cp;
            }
        }
    }
}

How do I get this to work on the Compact Framework? Perhaps I can PInvoke the functionality (from coredll.dll say)?

1

There are 1 answers

5
C.Evenhuis On

These styles are applied when the window class is created, and to my knowledge cannot be changed on the compact framework. Besides CreateParams, the full framework allows a window handle to be recreated, which also is not possible on the compact framework.

You could manually filter the messages sent to the control, and convert the double click message back to a mouse down message:

public partial class NoDblClickPicControl : PictureBox
{
    private const int WM_LBUTTONDBLCLK = 0x0203;
    private const int WM_LBUTTONDOWN = 0x0201;
    private const int GWL_WNDPROC = -4;

    [DllImport("coredll.dll", SetLastError = true)]
    private static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr newWndProc);
    [DllImport("coredll.dll", SetLastError = true)]
    private static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

    private delegate IntPtr WndProcDelegate(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

    private IntPtr prevWndProc;
    private WndProcDelegate @delegate;

    protected override void OnHandleCreated(EventArgs e)
    {
        base.OnHandleCreated(e);
        @delegate = new WndProcDelegate(MyWndProc);
        prevWndProc = SetWindowLong(Handle, GWL_WNDPROC, Marshal.GetFunctionPointerForDelegate(@delegate));
    }

    protected override void OnHandleDestroyed(EventArgs e)
    {
        base.OnHandleDestroyed(e);
        SetWindowLong(Handle, GWL_WNDPROC, prevWndProc);
    }

    private IntPtr MyWndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
    {
        if (msg == WM_LBUTTONDBLCLK)
        {
            msg = WM_LBUTTONDOWN;
        }

        return CallWindowProc(prevWndProc, hWnd, msg, wParam, lParam);
    }
}