65.9K
CodeProject is changing. Read more.
Home

A C# Sample Code/Article Extending the Capabilities of GDI+ in C# (.NET) - Part III

Jul 13, 2008

CPOL

2 min read

viewsIcon

23570

downloadIcon

238

An article about a C# Sample Code/Article Extending the Capabilities of GDI+ in C# (.NET)

Figure 1

Introduction

Here, in continuation to my previous article, I present one more method to select portions of an Image. Like my method 2 in the previous article, one does not have to be bothered about resize/movement problems of the selection rectangle as those will be taken care of by the selection window which is a.k.a. Win32 window.

The approach taken here is that, I trap the WM_EXITSIZEMOVE message in the window procedure of the child form. Earlier in the main form, I override the OnLoad(…) method and create another form, let us call it child-like form (since it almost behaves like a child to the Main Form) and set its owner to my main form. See Figure 1.

protected override void OnLoad(EventArgs e)
{
      chFrm = new ChildForm();
      chFrm.Owner = this;
      chFrm.Show();
      chFrm.Location = new Point(Location.X + 50, Location.Y + 50);
      base.OnLoad(e);
}

Now the current parent of the child-like form is the Desktop-Window and thereby, it becomes transparent (transparency is exhibited in its client area), since it is now equivalent to a pop-up window. When a user tries to move the child-like form, I quickly do two things:

  1. Change its parent from Desktop-window to the Main form
  2. Remove its WS_EX_LAYERED attribute through SetWindowLong(…)win32 API

This ensures that the child-like from can never leave the Main form. And I just need to do the reverse when the user stops the above action.

Note: To get the handle of the Desktop-Window, I use the Win32 API as shown below through pInvoke.

[DllImport("user32.dll")]
static extern IntPtr GetDesktopWindow();

Since we know that if a form becomes a child, we cannot apply the SetLayeredWindowAttributes (…) API on it. So how does the child form still become transparent? Enter WM_EXITSIZEMOVE, of the child Form. The WM_EXITSIZEMOVE message is sent one time to a window, after it has exited the moving or sizing modal loop. So to do the reverse as said above, I quickly do two more things:

  1. Toggle the parent of the child form; from the Main form to the Desktop-Window
  2. Toggle its layered attributes, in that I add the WS_EX_LAYERED attribute back to the child form

The above two things help the child form regain its transparency thus enabling the user to see through its client area.

The Win32-API setting transparency is shown below namely:

[DllImport ("user32.dll")]
public static extern long SetLayeredWindowAttributes
    (IntPtr Handle, int Clr, byte transparency, int clrkey);

The 4th parameter int clrKey, is the key, When calling this API, I mention a particular color for the clrKey parameter and further, I paint the child-like form with the same color. This will create a hole in the form’s client region.

Note: Whenever the form changes its parent, it will also reposition itself in accordance with its current parent, changing its location based on its earlier relative position in the WM_NCLBUTTONDOWN and WM_EXITSIZEMOVE messages which prevent this unwanted change of location.

History

  • 11th July, 2008: Initial version