Met veel klooien heb ik het volgende uitgevonden.
tomatoman schreef op vrijdag 18 november 2005 @ 23:38:
Ten eerste worden panel en checkbox pas zichtbaar als het dialoogvenster geresized wordt. Zelfs InvalidateRect voor het venster of een WM_PAINT message naar het venster sturen maakt geen verschil. Ten tweede zie je soms na het resizen de restanten van de vorige weergave er nog doorheen.
Dit probleem verdwijnt als sneeuw voor de zon als je een template gebruikt, ongeacht of de controls in de template zijn gedefinieerd. Het lijkt erop dat Windows de ontbrekende WM_PAINT messages alleen verstuurt als er een template wordt gebruikt.
Ten derde zit er om de checkbox geen focus rectangle, zelfs als hij de focus heeft.
Dit blijkt een rare eigenschap van een TPanel. Als de checkbox in een TGroupBox staat is de focus rectangle er weer.
Uiteindelijk heb ik het probleem opgelost door een lege template te gebruiken. De standaard 'open as read-only' check box van het dialoogvenster verberg ik en in plaats daarvan zet ik een eigen 'open as read-only' checkbox neer met daaronder een 'open exclusively' check box. De reden om een eigen check box te gebruiken is dat het anders niet lukt om ze in de tab order direct achter elkaar te krijgen. Het resultaat:
Er bleken nog heel wat andere addertjes onder het gras te zittten, vandaar dat ik hier de complete code post.
De .RC file:
code:
1
2
3
4
5
| SPECIALOPENDIALOGTEMPLATE DIALOG 0, 0, 320, 34
STYLE WS_CHILD | WS_CLIPSIBLINGS | DS_3DLOOK | DS_CONTROL
FONT 8, "MS Sans Serif"
BEGIN
END |
De Delphi unit:
Delphi:
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
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
| {-------------------------------------------------------------------------------
Specialized dialogs
Copyright (c) 2005 Robin Gerrets. All rights reserved.
________________________________________________________________________________
TSpecialOpenDialog is a dialog with two extra check boxes:
- 'Open as read-only' (replaces the default read-only check box)
- 'Open exclusively'
These check boxes can be accessed via the ReadOnly and Exclusive properties.
The ReadOnly property maps to Options.ofReadOnly.
-------------------------------------------------------------------------------}
unit SpecialDlg;
interface
uses Messages, Windows, SysUtils, Classes, Controls, StdCtrls, ExtCtrls,
Forms, Dialogs, Dlgs;
type
TSpecialOpenDialog = class(TOpenDialog)
private
FBasePanel: TPanel;
FExclusive: Boolean;
FExclusiveCheck: TCheckBox;
FOpenModeBox: TGroupBox;
FReadOnly: Boolean;
FReadOnlyCheck: TCheckBox;
function GetOptions: TOpenOptions;
procedure SetExclusive(Value: Boolean);
procedure SetOptions(Value: TOpenOptions);
procedure SetReadOnly(Value: Boolean);
procedure ExclusiveClick(Sender: TObject);
procedure ReadOnlyClick(Sender: TObject);
protected
procedure DoClose; override;
procedure DoResizeBasePanel;
procedure DoShow; override;
procedure FixupZOrder(WinControl: TWinControl);
procedure WndProc(var Message: TMessage); override;
property BasePanel: TPanel read FBasePanel;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function Execute: Boolean; override;
published
property Exclusive: Boolean read FExclusive write SetExclusive;
property Options read GetOptions write SetOptions default [ofEnableSizing];
property ReadOnly: Boolean read FReadOnly write SetReadOnly stored False;
end;
resourcestring
SSpecialOpenMode = 'Open mode';
SSpecialOpenReadOnly = 'Open as &read-only';
SSpecialOpenExclusive = 'Open e&xclusively';
implementation
{$R *.RES}
function TSpecialOpenDialog.GetOptions: TOpenOptions;
begin
Result := inherited Options - [ofHideReadOnly];
if FReadOnly then
Include(Result, ofReadOnly)
else
Exclude(Result, ofReadOnly);
end;
procedure TSpecialOpenDialog.SetExclusive(Value: Boolean);
begin
if FExclusive <> Value then
begin
FExclusive := Value;
FExclusiveCheck.Checked := Value;
end;
end;
procedure TSpecialOpenDialog.SetOptions(Value: TOpenOptions);
begin
inherited Options := Value + [ofHideReadOnly];
ReadOnly := ofReadOnly in Value;
end;
procedure TSpecialOpenDialog.SetReadOnly(Value: Boolean);
begin
if FReadOnly <> Value then
begin
FReadOnly := Value;
FReadOnlyCheck.Checked := Value;
end;
end;
procedure TSpecialOpenDialog.ExclusiveClick(Sender: TObject);
begin
FExclusive := FExclusiveCheck.Checked;
end;
procedure TSpecialOpenDialog.ReadOnlyClick(Sender: TObject);
begin
FReadOnly := FReadOnlyCheck.Checked;
end;
procedure TSpecialOpenDialog.DoClose;
begin
inherited DoClose;
{ Hide any hint windows left behind }
Application.HideHint;
end;
procedure TSpecialOpenDialog.DoResizeBasePanel;
var
FileTypeCombo: THandle;
FileTypeComboRect: TRect;
begin
{ Retrieve the window rectangle for the file type combo box, which has ID
cmb1 }
FileTypeCombo := GetDlgItem(GetParent(Handle), cmb1);
GetWindowRect(FileTypeCombo, FileTypeComboRect);
MapWindowPoints(0, Handle, FileTypeComboRect, 2);
{ Resize the base panel width to the width of the combo box + label }
FBasePanel.Width := FileTypeComboRect.Right - FBasePanel.Left;
end;
procedure TSpecialOpenDialog.DoShow;
var
FileTypeLbl: THandle;
FileTypeLblRect: TRect;
begin
{ Retrieve the window rectangle for the label of the file type combo box,
which has ID stc2 }
FileTypeLbl := GetDlgItem(GetParent(Handle), stc2);
GetWindowRect(FileTypeLbl, FileTypeLblRect);
MapWindowPoints(0, Handle, FileTypeLblRect, 2);
FBasePanel.Left := FileTypeLblRect.Left;
FBasePanel.Top := FileTypeLblRect.Top + 30;
FBasePanel.Height := 64;
DoResizeBasePanel; // Initialize the base panel's width
FBasePanel.ParentWindow := Handle;
{ The captions are reset to empty strings every time the dialog box is closed.
Set the captions whenever the dialog box is shown. }
FOpenModeBox.Caption := ' ' + SSpecialOpenMode + ' ';
FReadOnlyCheck.Caption := SSpecialOpenReadOnly;
FExclusiveCheck.Caption := SSpecialOpenExclusive;
inherited DoShow;
end;
procedure TSpecialOpenDialog.FixupZOrder(WinControl: TWinControl);
var
TabList: TList;
i: Integer;
begin
{ By default the dialog uses the order in which the windowed controls were
added as the tab order, where the last added control is placed first in the
tab order. Rearrange the Z-order of the windowed controls to make the
controls reflect the tab order as set by their TabOrder property. }
try
TabList := TList.Create;
try
WinControl.GetTabOrderList(TabList);
for i := 0 to TabList.Count -1 do
try
TWinControl(TabList.Items[i]).SendToBack;
except
end;
finally
TabList.Free;
end;
except
end;
end;
procedure TSpecialOpenDialog.WndProc(var Message: TMessage);
begin
inherited;
if Message.Msg = WM_SIZE then
DoResizeBasePanel;
end;
constructor TSpecialOpenDialog.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FBasePanel := TPanel.Create(nil);
with FBasePanel do
begin
Caption := '';
BevelOuter := bvNone;
BorderWidth := 0;
TabStop := True;
Font.Name := 'MS Shell Dlg';
FullRepaint := False;
end;
FOpenModeBox := TGroupBox.Create(FBasePanel);
with FOpenModeBox do
begin
Align := alClient;
Parent := FBasePanel;
end;
FReadOnlyCheck := TCheckBox.Create(FBasePanel);
with FReadOnlyCheck do
begin
Checked := ofReadOnly in Options;
Left := 8;
Top := 20;
Width := FOpenModeBox.Width - 40;
Parent := FOpenModeBox;
OnClick := ReadOnlyClick;
end;
FExclusiveCheck := TCheckBox.Create(FBasePanel);
with FExclusiveCheck do
begin
Checked := FExclusive;
Left := 8;
Top := FReadOnlyCheck.Top + FReadOnlyCheck.Height + 4;
Width := FOpenModeBox.Width - 40;
Parent := FOpenModeBox;
OnClick := ExclusiveClick;
end;
FixupZOrder(FBasePanel);
end;
destructor TSpecialOpenDialog.Destroy;
begin
FreeAndNil(FReadOnlyCheck);
FreeAndNil(FExclusiveCheck);
FreeAndNil(FOpenModeBox);
FreeAndNil(FBasePanel);
inherited Destroy;
end;
function TSpecialOpenDialog.Execute: Boolean;
begin
if not NewStyleControls or (ofOldStyleDialog in Options) then
Template := nil
else
Template := 'SPECIALOPENDIALOGTEMPLATE';
Result := inherited Execute;
end;
end. |
[
Voor 16% gewijzigd door
Tomatoman op 26-11-2005 19:52
]
Een goede grap mag vrienden kosten.