Introduction
Here, in continuation to my previous article, I present two more methods to do the same.
Method 1 Project Name: ReversePaint
As suggested by a reader, we do have an equivalent to DrawDragRect(…)
that is the public static void DrawReversibleFrame (Rectangle rectangle, Color backColor, FrameStyle style)
but the features like resizing the selection rectangle like how one resizes a normal window and Drag-Drop do require similar code as in my earlier sample code. As a POC, I present the sample code in the ReversePaint
download. Please see the function public void DrawDragRect()
for the only major difference. The CDrawDragRect
can derive from both Panel
and Form
depending upon the coder’s choice.
Method 2 Project Name: WindowPosChanging
Here I take a totally new approach. As one can see, resizing and Dragging and Dropping the selection rectangle needs to behave like a normal window, then why not use a normal window to do the same? So Windows will handle resize and other features automatically. For this, the Window (which is actually going to be a form, let us call it the childLike
form; see Figure below) will have to have a kind of hole in it so that the user can see through it for selecting a part of an image.
There is a Win32-API specifically for it, namely:
[DllImport("user32.dll")]
public static extern long SetLayeredWindowAttributes
(IntPtr Handle, int Clr, byte transparency, int clrkey);
The fourth parameter int clrKey
, is the key, When calling this API, I mention a particular color for the clrKey
parameter and further I paint the childLike
form with the same color. This will create a hole in the form’s client region.
But there is one down side to it - it will not create a hole in child windows (forms), this API will work only in a Pop-Up Window.
Now our childLike
form will have to be a Pop-up Form, and not an MDI Child or Child window. If it is a Pop-up, it will move out of our main Window which host’s the Image. So the form movement needs to be restricted to the Main form. This is achieved by trapping the WM_WINDOWPOSCHANGING
message in the form’s WndProc(ref Message m)
function.
When handing this message, I just ensure that WINDOWPOS winPos
(which I get through the m.Lparam
) does not leave the Main form.
The handling of the message works two fold:
- The
childLike
form cannot be dragged outside the Mainform
.
- When the main form is moved I just need to fire a
WM_MOVE
message for the childLike
form and this ensures that the childLike
form does not go outside the main form. Just take a look at the following code:
protected override void OnMove(EventArgs e)
{
if (chFrm != null)
{
MoveWindow(chFrm.Handle, chFrm.Location.X, chFrm.Location.Y,
chFrm.Size.Width, chFrm.Size.Height, true);
MinimumSize = new Size(chFrm.Size.Width + 100, chFrm.Size.Height);
}
base.OnMove(e);
}
Please note that the MoveWindow(...)
call made inside the OnMove(...)
function is a dummy.
This is kind of a free gift, just move the Main form all over your desktop and see how the childLike
form follows it dutifully.
That's all for the resize feature, now for the Drag And Drop feature.
Since the form has a hole in it, a user can drag-drop the childLike
form as shown in the image below:
This is achieved by overriding the Mouse-move function and inside it, I call the BestSelfMoveOnMoveNotRequired ()
function. This function performs the movement of the childLike
form.
History
- 10th June, 2008: Initial version
- 2nd July, 2008: Article updated