Introduction
Delphi has a nice way of displaying its forms: all forms are (by default) top-level forms. This makes it easy to develop applications that are not restricted to the "MainFrame" client area but to the all screen, without having to have your application maximized. However, visually organizing such windows is sometimes hard for the end-user if he wants to maximize the visible area and minimize the window overlaps.
The class presented here tries to overcome this "arrangement" issue helping the end-user better organize their forms by sticking them one to the other and/or to the screen when moved or resized. (Code also takes care of correct sticking in multi screen environments but I did not manage to test it.)
Using the Code
The class inherits from System.Windows.Forms.NativeWindow
, thus no inheritance is required in order to make your class Stick able.
In order to make your top-windows stick-able, all you have to do is declare a member variable of type StickyWindow
and initialize it in your form:
private Blue.Windows.StickyWindow stickyWindow;
[...]
public
Form2()
{
stickyWindow = new
Blue.Windows.StickyWindow ( this );
}
Now you have a form that will automatically stick on resize or move to all other forms that use the StickyWindow
class and to the screen margins;
Customizations
There are few options you can customize about a Sticky Window:
public bool StickOnMove
Allows the form to try to stick when the form is moved.
public bool StickOnResize
Allows the form to try to stick when the form is resized.
public bool StickToOther
Allows the form to try to stick to other stick-able forms.
public bool StickToScreen
Allows the form to try to stick to the screen margins.
public int StickGap
Distance in pixels between two forms or a form and the screen where the sticking should start.
public static void RegisterExternalReferenceForm( Form externalForm )
Registers an external form (not StickyWindow
form) in the list of forms that StickyWindow
s can stick to.
E.g.: If you don't want your MainFrame to be stick-able but you want child forms to try to stick to it, than you will register your MainFrame with RegisterExternalReferenceForm
so that other forms will try to stick to it.
public static void UnregisterExternalReferenceForm ( Form externalForm )
Same as RegisterExternalReferenceForm
but it un-registers the form.
These are all the defined possible customizations of the StickyWindow
.
Implementation Details
The idea behind the implementation is to filter the NC (NonClient) messages from the Form
's message queue and do the own Moving/Resizing of the form by overriding the WndProc
of the NativeWindow
.
When a WM_NCLBUTTONDOWN
is received for the Form
, the StickyWindow
checks the required operation (Move/Resize) and starts the algorithm for the requested operation.
While mouse is moved, the algorithm computes the new Form's position/size and then tries to compute the distance to the closest Form or screen border. If the shortest distance is smaller than the StickGap
, the form will be moved/resized to touch the margins of the form/screen, thus sticking taking place.
While resize takes place, the form will take care not to shrink below Form.MinimumSize
or SystemInformation.MinWindowTrackSize
or to grow above Form.MaximumSize
or SystemInformation.MaxWindowTrackSize
.
Credits
- The main credits go to WinAmp's team who made the idea of sticking windows popular.
- The second credits go to Infopulse, the place where I've developed the first
StickyWindow
s implementation in C++.
History
- 09.Feb.2004: version 1.0
First released version.
Copyright
You can use these sources for absolutely free.