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:
- Change its parent from Desktop-window to the
Main
form
- 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:
- Toggle the parent of the child form; from the Main form to the Desktop-Window
- 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