-
Notifications
You must be signed in to change notification settings - Fork 1
/
TFlatAnimWndUnit.pas
222 lines (199 loc) · 6.19 KB
/
TFlatAnimWndUnit.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
unit TFlatAnimWndUnit;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type
TFlatAnimWnd = class;
TFlatAnimHookWnd = class(TWinControl)
private
FAnimateWindow: TFlatAnimWnd;
procedure WMCreate (var Message: TMessage); message WM_CREATE;
procedure WMDestroy (var Message: TMessage); message WM_DESTROY;
public
constructor Create (AOwner: TComponent); override;
end;
TFlatAnimWnd = class(TComponent)
private
FOwner: TComponent;
FNewProc, FOldProc, FNewAppProc, FOldAppProc: TFarProc;
FOnMinimize: TNotifyEvent;
FOnRestore: TNotifyEvent;
procedure NewWndProc (var Message: TMessage);
procedure NewAppWndProc (var Message: TMessage);
procedure MinimizeWnd;
procedure RestoreWnd;
procedure OwnerWndCreated;
procedure OwnerWndDestroyed;
protected
FHookWnd: TFlatAnimHookWnd;
procedure SetParentComponent(Value: TComponent); override;
public
constructor Create (AOwner: TComponent); override;
destructor Destroy; override;
procedure Minimize;
published
property OnMinimize: TNotifyEvent read FOnMinimize write FOnMinimize;
property OnRestore: TNotifyEvent read FOnRestore write FOnRestore;
end;
implementation
var
OwnerList: TList;
constructor TFlatAnimHookWnd.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FAnimateWindow := TFlatAnimWnd(AOwner);
end;
procedure TFlatAnimHookWnd.WMCreate(var Message: TMessage);
begin
inherited;
FAnimateWindow.OwnerWndCreated;
end;
procedure TFlatAnimHookWnd.WMDestroy(var Message: TMessage);
begin
FAnimateWindow.OwnerWndDestroyed;
inherited;
end;
constructor TFlatAnimWnd.Create(AOwner: TComponent);
begin
FOwner := AOwner;
if OwnerList.IndexOf(FOwner) <> -1 then
begin
FOwner := nil;
raise Exception.Create('Owner must be TFORM');
end;
inherited Create(AOwner);
if not (csDesigning in ComponentState) then
begin
FHookWnd := TFlatAnimHookWnd.Create(Self);
if Application.MainForm = nil then
begin
FNewAppProc := MakeObjectInstance(NewAppWndProc);
FOldAppProc := Pointer(GetWindowLong(Application.Handle, GWL_WNDPROC));
SetWindowLong(Application.Handle, GWL_WNDPROC, Longint(FNewAppProc));
end;
end;
OwnerList.Add(FOwner);
end;
destructor TFlatAnimWnd.Destroy;
begin
if not(csDesigning in ComponentState) then
begin
if Application.MainForm = nil then
begin
SetWindowLong(Application.Handle, GWL_WNDPROC, Longint(FOldAppProc));
FreeObjectInstance(FNewAppProc);
end;
end;
if OwnerList.IndexOf(FOwner) <> -1 then
OwnerList.Remove(FOwner);
inherited Destroy;
end;
procedure TFlatAnimWnd.SetParentComponent(Value: TComponent);
begin
inherited SetParentComponent(Value);
if not(csDesigning in ComponentState) then
if Value is TWinControl then
FHookWnd.Parent := TWinControl(Value);
end;
procedure TFlatAnimWnd.OwnerWndCreated;
begin
FNewProc := MakeObjectInstance(NewWndProc);
FOldProc := Pointer(GetWindowLong((FOwner as TForm).Handle, GWL_WNDPROC));
SetWindowLong((FOwner as TForm).Handle, GWL_WNDPROC, Longint(FNewProc));
end;
procedure TFlatAnimWnd.OwnerWndDestroyed;
begin
SetWindowLong((FOwner as TForm).Handle, GWL_WNDPROC, Longint(FOldProc));
FreeObjectInstance(FNewProc);
end;
procedure TFlatAnimWnd.NewAppWndProc(var Message: TMessage);
begin
with Message do
begin
if Msg = WM_SYSCOMMAND then
case WParam of
SC_MINIMIZE:
MinimizeWnd;
SC_RESTORE:
RestoreWnd;
end;
Result := CallWindowProc(FOldAppProc, Application.Handle, Msg, wParam, lParam);
end;
end;
procedure TFlatAnimWnd.NewWndProc(var Message: TMessage);
begin
with Message do
begin
if (Msg = WM_SYSCOMMAND) and (WParam = SC_MINIMIZE) then
begin
if Application.MainForm = FOwner then
MinimizeWnd
else
PostMessage(Application.Handle, WM_SYSCOMMAND, SC_MINIMIZE, 0);
end
else
begin
if (Msg = WM_WINDOWPOSCHANGING) and (PWindowPos(lParam)^.flags = (SWP_NOSIZE or SWP_NOMOVE)) then
begin
if IsIconic(Application.Handle) then
PostMessage(Application.Handle, WM_SYSCOMMAND, SC_RESTORE, 0);
end
end;
Result := CallWindowProc(FOldProc, (FOwner as TForm).Handle, Msg, wParam, lParam);
end;
end;
procedure TFlatAnimWnd.MinimizeWnd;
var
Rect: TRect;
begin
with Application do
begin
if not(IsWindowEnabled(Handle)) then
EnableWindow(Handle, True);
GetWindowRect((FOwner as TForm).Handle, Rect);
SetForegroundWindow(Handle);
SetWindowPos(Handle, 0, Rect.Left, Rect.Top, Rect.Right - Rect.Left, 0, SWP_NOZORDER);
DefWindowProc(Handle, WM_SYSCOMMAND, SC_MINIMIZE, 0);
ShowWindow(Handle, SW_MINIMIZE);
end;
if Assigned(FOnMinimize) then
FOnMinimize(Application);
end;
procedure TFlatAnimWnd.RestoreWnd;
var
MainFormPlacement: TWindowPlacement;
AppWndPlacement: TWindowPlacement;
begin
with Application do
begin
MainFormPlacement.length := SizeOf(TWindowPlacement);
MainFormPlacement.flags := 0;
GetWindowPlacement(MainForm.Handle, @MainFormPlacement);
AppWndPlacement.length := SizeOf(TWindowPlacement);
AppWndPlacement.flags := 0;
GetWindowPlacement(Handle, @AppWndPlacement);
AppWndPlacement.rcNormalPosition := MainFormPlacement.rcNormalPosition;
AppWndPlacement.rcNormalPosition.Bottom := AppWndPlacement.rcNormalPosition.Top;
SetWindowPlacement(Handle, @AppWndPlacement);
SetForegroundWindow(Handle);
DefWindowProc(Application.Handle, WM_SYSCOMMAND, SC_RESTORE, 0);
ShowWindow(Handle, SW_RESTORE);
SetWindowPos(Handle, 0, 0, 0, 0, 0, SWP_NOZORDER);
if not(MainForm.Visible) then
begin
ShowWindow(MainForm.Handle, SW_RESTORE);
MainForm.Visible := True;
end;
end;
if Assigned(FOnRestore) then
FOnRestore(Application);
end;
procedure TFlatAnimWnd.Minimize;
begin
SendMessage((FOwner as TForm).Handle, WM_SYSCOMMAND, SC_MINIMIZE, 0);
end;
initialization
OwnerList := TList.Create;
finalization
OwnerList.Free;
end.