Author: Jonas Bilinkevicius
How can I create a form that will roll up? That is, a form that when clicked will
reduce its height to nothing but the title bar?
Answer:
1 unit testmain;
2
3 interface
4
5 uses
6 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
7 ExtCtrls, StdCtrls, Buttons, ShellAPI;
8
9 type
10 TForm1 = class(TForm)
11 procedure FormCreate(Sender: TObject);
12 private
13 { Private declarations }
14 FOldHeight: Integer;
15 procedure WMNCRButtonDown(var Msg: TWMNCRButtonDown);
16 message WM_NCRBUTTONDOWN;
17 public
18 { Public declarations }
19 end;
20
21 var
22 Form1: TForm1;
23
24 implementation
25
26 {$R *.DFM}
27
28 procedure TForm1.FormCreate(Sender: TObject);
29 begin
30 FOldHeight := ClientHeight;
31 end;
32
33 procedure TForm1.WMNCRButtonDown(var Msg: TWMNCRButtonDown);
34 var
35 I: Integer;
36 begin
37 if (Msg.HitTest = HTCAPTION) then
38 if (ClientHeight = 0) then
39 begin
40 I := 0;
41 while (I < FOldHeight) do
42 begin
43 I := I + 40;
44 if (I > FOldHeight) then
45 I := FOldHeight;
46 ClientHeight := I;
47 Application.ProcessMessages;
48 end;
49 end
50 else
51 begin
52 FOldHeight := ClientHeight;
53 I := ClientHeight;
54 while (I > 0) do
55 begin
56 I := I - 40;
57 if (I < 0) then
58 I := 0;
59 ClientHeight := I;
60 Application.ProcessMessages;
61 end;
62 end;
63 end;
64
65 end.
First, by way of synopsis, the roll-up/down occurs in response to a
WM_NCRBUTTONDOWN message firing off and the WMNCRButtonDown procedure handling the
message, telling the window to roll up/down depending upon the height of the client
area. WM_NCRBUTTONDOWN fires whenever the right mouse button is clicked in a
"non-client" area, such as a border, menu or, for our purposes, the caption bar of
a form. (The client area of a window is the area within the border where most of
the interesting activity usually occurs. In general, the Windows API restricts
application code to drawing only within the client area.)
Delphi encapsulates the WM_NCRBUTTONDOWN in a TWMNCRButtonDown type, which is
actually an assignment from a TWMNCHitMessage type that has the following structure:
66 type
67 TWMNCHitMessage = record
68 Msg: Cardinal;
69 HitTest: Integer;
70 XCursor: SmallInt;
71 YCursor: SmallInt;
72 Result: Longint;
73 end;
It's easy to create message wrappers in Delphi to deal with messages that aren't
handled by an object by default. Since a right-click on the title bar of a form
isn't handled by default, I had to create a wrapper. The procedure procedure
WMNCRButtonDown(var Msg : TWMNCRButtonDown); message WM_NCRBUTTONDOWN; is the
wrapper I created. All that goes on in the procedure is the following:
In order to make this work, I had to create a variable called FOldHeight and set
its value at FormCreate whenever the form was to be rolled up. FOldHeight is used
as a place for the form to remember what size it was before it was re-sized to 0.
When a form is to be rolled up, FOldHeight is immediately set to the current
ClientHeight, which means you can interactively set the form's size, and the
function will always return the form's ClientHeight to what it was before you
rolled it up.
So what use is this? Well, sometimes I don't want to iconize a window; I just want to get it out of the way so I can see what's underneath. Having the capability to roll a form up to its title bar makes it a lot easier to see underneath a window without iconizing it, then having to Alt-tab back to it. (If you are familiar with the Macintosh platform, the System 7.5 environment offers a very similar facility called a "window shade," and makes a roll-up sound when the shade goes up.)
|