0

Code:

public partial class Form1 : Form {
public Form1() {
  InitializeComponent();
  this.FormBorderStyle = FormBorderStyle.None; // no borders
  this.DoubleBuffered = true;
  this.SetStyle(ControlStyles.ResizeRedraw, true); // this is to avoid visual artifacts
}

protected override void OnPaint(PaintEventArgs e) // you can safely omit this method if you want
{
    e.Graphics.FillRectangle(Brushes.Green, Top);
    e.Graphics.FillRectangle(Brushes.Green, Left);
    e.Graphics.FillRectangle(Brushes.Green, Right);
    e.Graphics.FillRectangle(Brushes.Green, Bottom);
}

private const int
    HTLEFT = 10,
    HTRIGHT = 11,
    HTTOP = 12,
    HTTOPLEFT = 13,
    HTTOPRIGHT = 14,
    HTBOTTOM = 15,
    HTBOTTOMLEFT = 16,
    HTBOTTOMRIGHT = 17;

const int _ = 10; // you can rename this variable if you like

Rectangle Top { get { return new Rectangle(0, 0, this.ClientSize.Width, _); } }
Rectangle Left { get { return new Rectangle(0, 0, _, this.ClientSize.Height); } }
Rectangle Bottom { get { return new Rectangle(0, this.ClientSize.Height - _, this.ClientSize.Width, _); } }
Rectangle Right { get { return new Rectangle(this.ClientSize.Width - _, 0, _, this.ClientSize.Height); } }

Rectangle TopLeft { get { return new Rectangle(0, 0, _, _); } }
Rectangle TopRight { get { return new Rectangle(this.ClientSize.Width - _, 0, _, _); } }
Rectangle BottomLeft { get { return new Rectangle(0, this.ClientSize.Height - _, _, _); } }
Rectangle BottomRight { get { return new Rectangle(this.ClientSize.Width - _, this.ClientSize.Height - _, _, _); } }


protected override void WndProc(ref Message message)
{
    base.WndProc(ref message);

    if (message.Msg == 0x84) // WM_NCHITTEST
    {
        var cursor = this.PointToClient(Cursor.Position);

        if (TopLeft.Contains(cursor)) message.Result = (IntPtr)HTTOPLEFT;
   else if (TopRight.Contains(cursor)) message.Result = (IntPtr)HTTOPRIGHT;
   else if (BottomLeft.Contains(cursor)) message.Result = (IntPtr)HTBOTTOMLEFT;
   else if (BottomRight.Contains(cursor)) message.Result = (IntPtr)HTBOTTOMRIGHT;

   else if (Top.Contains(cursor)) message.Result = (IntPtr)HTTOP;
   else if (Left.Contains(cursor)) message.Result = (IntPtr)HTLEFT;
   else if (Right.Contains(cursor)) message.Result = (IntPtr)HTRIGHT;
   else if (Bottom.Contains(cursor)) message.Result = (IntPtr)HTBOTTOM;
    }
}}

But for some reason the Message only fires when I have my control NOT full-size of my form. For example if I set a padding of 1 on my Form, so there's a 1-pixel border, then it fires. But if my control takes up the full size, it doesn't fire at all ever.

I'm using a CEFSharp WinForms control on a WinForms project with it StyleMode.Fill to fill the entire Form.

The Control-Based wndProc hook code

using System;
using System.Drawing;
using System.Windows.Forms;

class wndProcGlobalHook : NativeWindow
{
    private Form form;
    private Control child;
    const int _ = 8;
    Rectangle _Top { get { return new Rectangle(0, 0, form.ClientSize.Width, _); } }
    Rectangle _Left { get { return new Rectangle(0, 0, _, form.ClientSize.Height); } }
    Rectangle _Bottom { get { return new Rectangle(0, form.ClientSize.Height - _, form.ClientSize.Width, _); } }
    Rectangle _Right { get { return new Rectangle(form.ClientSize.Width - _, 0, _, form.ClientSize.Height); } }
    Rectangle TopLeft { get { return new Rectangle(0, 0, _, _); } }
    Rectangle TopRight { get { return new Rectangle(form.ClientSize.Width - _, 0, _, _); } }
    Rectangle BottomLeft { get { return new Rectangle(0, form.ClientSize.Height - _, _, _); } }
    Rectangle BottomRight { get { return new Rectangle(form.ClientSize.Width - _, form.ClientSize.Height - _, _, _); } }
    public wndProcGlobalHook(Form form, Control child)
    {
        this.form = form;
        this.child = child;
        AssignHandle(child.Handle);
    }
    protected override void WndProc(ref Message m)
    {
        System.Diagnostics.Debug.Write("wndProc executed");
        if (m.Msg == 0x84) {
            System.Diagnostics.Debug.Write("0x84 :D:D:D");
            Point cursor = child.PointToClient(Cursor.Position);
            System.Diagnostics.Debug.Write("Cursor: " + cursor.ToString());
            if (TopLeft.Contains(cursor)) {
                m.Result = (IntPtr)13;
            } else if (TopRight.Contains(cursor)) {
                m.Result = (IntPtr)14;
            } else if (BottomLeft.Contains(cursor)) {
                m.Result = (IntPtr)16;
            } else if (BottomRight.Contains(cursor)) {
                m.Result = (IntPtr)17;
            } else if (_Top.Contains(cursor)) {
                m.Result = (IntPtr)12;
            } else if (_Left.Contains(cursor)) {
                m.Result = (IntPtr)10;
            } else if (_Right.Contains(cursor)) {
                m.Result = (IntPtr)11;
            } else if (_Bottom.Contains(cursor)) {
                m.Result = (IntPtr)15;
            }
        }
        base.WndProc(ref m);
    }
}

Then in Form1:

//where ui == ChromiumWebBrowser control
new wndProcGlobalHook(this, ui);
foreach (Control ctrl in ui.Controls) {
    new wndProcGlobalHook(this, ctrl);
}

Calling tons of other Messages but never 0x84. Closest one called was 0x85 on startup.

Capture = true

If I set control.Capture = true; before sending it to wndProcGlobalHook it starts sending 0x200 which is a general hover event and then stops firing it once I click my app. But still no 0x84

Ma Dude
  • 477
  • 1
  • 5
  • 17
  • Please provide your code in the question. – Mathieu de Lorimier Apr 18 '18 at 17:00
  • @MathieudeLorimier Done – Ma Dude Apr 18 '18 at 17:40
  • 2
    The message is sent to the control that is being hovered by the mouse. If your control completely covers the form's client area then the mouse is always going to hover the control, never the form. – Hans Passant Apr 18 '18 at 17:45
  • 1
    https://stackoverflow.com/a/31357074/17034 – Hans Passant Apr 18 '18 at 17:46
  • @HansPassant So thats how wndProc works I see. Never actually knew that before. Is there a way to do wndProc on the Control or just globally hook it? (Since I cant easily override the CEFSharp Browser WinForms control) – Ma Dude Apr 18 '18 at 18:04
  • The post I linked shows both approaches. – Hans Passant Apr 18 '18 at 18:07
  • @HansPassant Perfect the 1st solution wont work for me, but the 2nd one has (kinda). Its giving me one issue, wndProc seems to fire on it, but only for clicking. Hovering wont do anything (0x84 doesnt fire, but another message on that control does). I posted my code that I hooked above. – Ma Dude Apr 18 '18 at 18:24
  • Still need help on this :/ – Ma Dude Apr 27 '18 at 23:32

0 Answers0