Ctl32 Gripper

ctl32_gripper

Links
Properties, Events and Methods of the class
Overview
This class provides a Sizing Grip control that can be used in VFP9 Forms. The primary purpose of this class is to emulate the sizing grip shown on most resizable windows.
This is not just a cosmethic sizing grip, it has the same functionality available in a real sizing grip. You can grab the form by the sizing grip and resize it.
This class uses BINDEVENT with the new features only available in VFP9. It will not work in previous versions of VFP. If you are using a previous version of VFP, you should really upgrade to take advantage of the many new features, and to support VFP.

Class Hierarchy
ctl32
ctl32_gripper

Properties, Events & Methods
You can find a complete reference to all properties, events & methods of the class here.


Pictures

 Themed sizing grip


Classic sizing grip


The sizing grip hot zone can be configured

Quick Start
If you want a ctl32_gripper on a form, drag the ctl32_gripper control from the Project Manager window and drop it into the Form. You should only have ONE instance of the class in a form.

Sample Project
See the ctl32_example project included in the samples folder.

BindEvent
This class does Bindevents to the following windows and window messages:
Form Activate
Form BorderStyle
Form Resize
See the _BindEvents() method of the class for details.

Bugs
The themed colors are not exactly right, but the alternative is to draw the sizing grip using the uxtheme functions, and I will not get into that for a sizing grip, not now at least, maybe in the future.

Known Problems

Change Log
20080314
Docs updated, added ctlScale
20070727
WM_NCHITTEST is not used anymore. Problems with Mrow() and Mcol(9 have been solved.
Changed the _ThemeStatus, _HostHWnd, _FormType functions in _util of ctl32_common. Eliminated all references to ThisForm, now the form is determined from the control that is passed as a parameter to this functions.
Changed the way _Util object is added to control, from newobject to addproperty, so it will not count as another control.
Added ctlVcxStructs and ctlVcxCommon, they specify the name/location of the ctl32_structs and ctl32_common classes.

Under The Hood
Usually, the sizing grip is an integral part of a window status bar, or is found in the lower right corner of a window scrollbars.
Since the sizing grip by itself is not part of the Windows common controls, we have to find a way to build one.
We could use the sizing grip of a scrollbar as a starting point, but a simpler approach is available:
Drawing the thing:
A large portion of the code is dedicated to drawing the sizing grip interface, be it Themed (dots) or Classic (lines).
The dots are just regular VFP shapes. The method that adds the dots is made of two nested FOR/ENDFOR loops, that just steps thru the x and y coordinates values of each dot and creates them. The way to avoid creating the 3 "missing" dots in the 3x3 pattern is to just calculate x * y, and loop if the result is less than the minimum result of the dots we want.



The lines are a little more interesting, they are created by adding two labels, and the help of the hidden Marlett TrueType font.
Try running this code in the Command Window:
_Screen.AddObject([oMarlett], [Label])
With _Screen
.oMarlett
      .
AutoSize = .T.
      .
FontName = [Marlett]
      .
FontSize = 12
      .
Caption = [0123456789abcdefghijklmnopqrstuvwxy]
      .
Visible = .T.
Endwith
Some more info can be found here: http://blogs.msdn.com/michkap/archive/2006/01/26/517738.aspx
To draw the classic shape, we use two transparent labels one on top for each other, one with Caption = [o] and a light Forecolor, and the other with Caption [p] and a darker ForeColor.



+=

We are lucky that the Marlett font does not get ClearTyped, so we don't get the bolding/bleeding bug of VFP:
http://blogs.msdn.com/oldnewthing/archive/2006/06/14/630864.aspx
To draw the lines, we could have used the API DrawFrameControl function, but is much easier to just use the labels, and we can have a transparent background too, just in case the developer decides to change the Formīs BackColor.
The dots and the lines are each created in two different containers, so we can easily switch styles (dots/lines) by just setting the Visible property of each container.
Some details:
We do BINDEVENT to the Form Resize event and BorderStyle property, so we can hide the sizing grip if the BorderStyle changes from Sizable (unlikely) or if after a resize the form WindowState is other than Normal. If the form is maximized (likely to happen), we shoud not show the sizing grip of course. If the form is minimized, we don't need it so we hide it just in case.
If the Form BorderStyle is set to other that Sizable in the properties pane, the sizing grip will not show when you run the form.
We also BINDEVENT to the form Activate event, to bring the sizing grip control to the top of the ZOrder, just in case the is some other control over it, that got its own ZOrder changed to the top.
Now we just do a Bindevent to oMouseTrap MouseDown event and send a wm_lmousedown message to the window with the coordinates of the right bottom point of the form.
The WM_NCHITTEST Message:
"The WM_NCHITTEST message is sent to a window when the cursor moves, or when a mouse button is pressed or released."
That's from MSDN
That doesn't tell us much, but it gives as a hint, then I found this gem:
"When you move the mouse around the form, by default Windows automatically determines when you are at a border, or in the title bar, and changes the mouse pointer as required and allows resizing or moving.
This default behaviour can be overridden by changing the response to the WM_NCHITTEST message which is sent to the window whenever the mouse moves over it."
I found it here: Moving Forms and Creating Resize Gripper Boxes
Now it was just downhill from here: just a simple BINDEVENT to the window message, determine if the mouse is over the sizing grip hot area, determine if the sizing grip is visible, and then cheat and respond with HTBOTTOMRIGHT to the message, effectively fooling Windows into thinking that the mouse is over the bottom right corner of the form, so we let Windows do all the form resizing work for us.
That's all there is to it, very simple indeed.

LAST UPDATED (YYYY.MM.DD): 2008.03.20
 

No comments:

Post a Comment