Home | Shorter Path | About Me
Home
About Me

Archive

2004

01

02

03

04

05

06

07

08

09

10

11

12

 

2005

01

02

03

04

05

06

07

08

09

10

11

12

 

2006

01

02

03

04

05

06

07

08

09

10

11

12


Non-client area in .NET

Friday, September 03, 2004 10:33 AM

Among the hundreds of ridiculous search phrases leading to this blog, there are a few valid technical issues. For some, there is very little information available out there. One of these is the issue of non-client messages in .NET.

The .NET Framework does a pretty good job of wrapping the existing Win32 functionality in managed objects, while providing a lot of new functionality. However, because of the sheer size of the platform, Microsoft chose not to include certain capabilities in versions 1.0 and 1.1 of the Framework. The bits left out are usually the least-frequently used parts of Win32, but if you need them, you're stuck.

Non-client message handling is one of the things left behind. If you need to handle non-client messages in your applications or custom components, there are no events you can handle, and no methods you can override. You can, however, still handle these messages in the old Win32 way - checking the message number in the window procedure and interpreting the message record yourself.

The way to do this is to override the control's WndProc method. WndProc is a protected method called as part of the control's message processing, and pretty much corresponds to the traditional window procedure. By overriding it, you can handle any message received by the control. Since the Windows messages are not defined in the .NET Framework, you'll have to declare any message constants (and other related values and structures) yourself. So, if you wanted to handle the WM_NCHITTEST message, for example, so that dragging any part of the window would move it, you'd write this code:

public class MovableForm : System.Windows.Forms.Form
{
    //[...]

    private const int WM_NCHITTEST = 0x0084;
    private const int HTCLIENT = 1;
    private const int HTCAPTION = 2;

    protected override void WndProc(ref Message m)
    {
        base.WndProc (ref m);
        if (m.Msg == WM_NCHITTEST)
        {
            if (m.Result.ToInt32() == HTCLIENT)
            {
                m.Result = new IntPtr(HTCAPTION);
            }
        }
    }
}

Or, in Delphi:

procedure TWinForm.WndProc(var m: Message);
const
  WM_NCHITTEST = $0084;
  HTCLIENT = 1;
  HTCAPTION = 2;
begin
  inherited WndProc(m);
  if m.Msg = WM_NCHITTEST then
  begin
    if m.Result.ToInt32 = HTCLIENT then
      m.Result := IntPtr.Create(HTCAPTION);
  end;
end;

Copyright 2004 Yorai Aminov