Entwickler-Ecke

Windows API - Hilfebutton-Klick bei Dialogen abfangen


galagher - Fr 21.09.07 18:47
Titel: Hilfebutton-Klick bei Dialogen abfangen
Hallo zusammen!

Wie kann ich den Klick auf den Hilfebutton bei Dialogen abfangen? Ich habe zB. einen OpenDialog und möchte beim Klicken auf den Hilfebutton eine eigene Hilfedatei öffnen, nicht die Windows-Hilfe. Ein OnHelp-Ereignis gibt's ja nicht, also wie kann man sowas machen?


Moderiert von user profile iconNarses: Topic aus Algorithmen, Optimierung und Assembler verschoben am Fr 21.09.2007 um 23:41


BenBE - Fr 21.09.07 20:53

Du musst dazu die WndProc des OpenDialogs abfangen und IIRC die Nachricht WM_SYSCOMMAND selber behandeln.


galagher - Fr 21.09.07 21:51

user profile iconBenBE hat folgendes geschrieben:
Du musst dazu die WndProc des OpenDialogs abfangen und IIRC die Nachricht WM_SYSCOMMAND selber behandeln.

Ja, aber wo und wie? Ich habe einfach eine neue Komponente TOpenFileDialog (und dasselbe für Save und OpenPicture usw.) erstellt und auch gleich registriert, die kann das jetzt. Ich habe mir dabei halt eine andere Kompo angesehen, wie so etwas dort aussieht.

War recht einfach, weil das die einzige Änderung war. Hat vor allem den Vorteil, dass die das dann schon kann und ich es nicht immer wieder schreiben muss!

Trotzdem danke!


galagher - Sa 22.09.07 19:56

Es ist doch noch eine Frage aufgetaucht:
Für die diversen Dialog-Klassen habe ich im Grund immer den selben Code:

Delphi-Quelltext
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:
{OpenDlg}
type
  TOpenDlg = class(TOpenDialog)

  private
    FOnHelp: TNotifyEvent;
  protected
    procedure DoHelp; dynamic;
    procedure WndProc(var message: Tmessage); override;
  published
    property OnHelp: TNotifyEvent read FOnHelp write FOnHelp;
  end;

{------------------------------------------------------------------------------}

{SaveDlg}
  TSaveDlg = class(TSaveDialog)

  private
    FOnHelp: TNotifyEvent;
  protected
    procedure DoHelp; dynamic;
    procedure WndProc(var message: Tmessage); override;
  published
    property OnHelp: TNotifyEvent read FOnHelp write FOnHelp;
  end;

//...

procedure Register;

implementation


{OpenDlg}
procedure TOpenDlg.WndProc(var message: Tmessage);
begin
  {Hilfebutton angeklickt}
  message.Result := 0;
  if (message.Msg = WM_INITDIALOG) and
    not (ofOldStyleDialog in Options) then exit
  else if (message.Msg = WM_NOTIFY) then
    case (POFNotify(message.LParam)^.hdr.code) of
      CDN_HELP: DoHelp;
    end;

  inherited WndProc(message);
end;

procedure TOpenDlg.DoHelp;
begin
  if Assigned(FOnHelp) then FOnHelp(Self);
end;

{------------------------------------------------------------------------------}

{SaveDlg}
procedure TSaveDlg.WndProc(var message: Tmessage);
begin
  {Hilfebutton angeklickt}
  message.Result := 0;
  if (message.Msg = WM_INITDIALOG) and
    not (ofOldStyleDialog in Options) then exit
  else if (message.Msg = WM_NOTIFY) then
    case (POFNotify(message.LParam)^.hdr.code) of
      CDN_HELP: DoHelp;
    end;

  inherited WndProc(message);
end;

procedure TSaveDlg.DoHelp;
begin
  if Assigned(FOnHelp) then FOnHelp(Self);
end;

//...

Sie benötigen alle den gleichen Code, kann man das nicht auch einfacher machen? Ich meine, eine Prozedur WndProc und eine Prozedur DoHelp für alle. Hab' schon versucht, diese Prozeduren "allgemeiner" zu schreiben, aber alles führte zu Fehlern. Das ist für 8 Dialoge immer der selbe Quellcode! Geht das nicht auch einfacher?


BenBE - Sa 22.09.07 20:37

Leider nicht, da deine verschiedenen Dialoge immer auch verschiedene Vorfahren haben und daher zueinander inkompatibel sind.


galagher - Sa 22.09.07 21:14

Danke, kann man nichts machen! Funktioniert jedenfalls bestens!


galagher - So 23.09.07 22:56

Hallo!

Der Code funktioniert nur bei Open- und Save-Dialogen, bei Font-, Color- und Print-Dialogen nicht, wenn ich davon Klassen ableite. Es kompiliert zwar fehlerfrei, und es gibt auch ein OnHelp im OI, aber offenbar wird keine entsprechende Nachricht gesendet.

Wie muss der Code denn aussehen, damit es funktioniert?


galagher - Fr 28.09.07 11:23

Hallo!
Habe die Lösung gefunden: MessageHook!

Delphi-Quelltext
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:
//..
type
{FontDlg}
  TFontDlg = class(TFontDialog)
  private
    FOnHelp: TNotifyEvent;
  protected
    procedure DoHelp; dynamic;
    function MessageHook(var Msg: TMessage): Boolean; override;
  published
    property OnHelp: TNotifyEvent read FOnHelp write FOnHelp;
  end;
//..
{FontDlg}
function TFontDlg.MessageHook(var Msg: TMessage): Boolean;
begin
  Result := False;
  if (Msg.Msg = HelpMsg) then
  begin
    DoHelp;
    Result := True;
  end;
end;

procedure TFontDlg.DoHelp;
begin
  if Assigned(FOnHelp) then FOnHelp(Self);
end;


galagher - Di 18.12.07 19:45

Hallo!
Ich poste hier mal die komplette Unit für abgeleitete Dialoge. Soweit ich das getestet habe, funktionieren alle Dialoge und auch das Ereignis OnHelp. Nur bei FindDlg und ReplaceDlg, da funktioniert zwar das Ereignis OnHelp, aber sonst nichts! :nixweiss:

Hat was mit MessageHook zu tun, denn wenn ich MessageHook komplett rausnehme, funktioniert der Dialog plötzlich wieder, nur eben das OnHelp nicht! Wie gesagt, das ist auch bei ReplaceDlg so.
Was also tun? Alle Button-Klicks von FindDlg und ReplaceDlg laufen über MessageHook, wie bekomme ich das hin?


Hier also die Unit, sollte alles einwandfrei laufen, eben bis auf FindDlg und ReplaceDlg!


Delphi-Quelltext
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:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
267:
268:
269:
270:
271:
272:
273:
274:
275:
276:
277:
278:
279:
280:
281:
282:
283:
284:
285:
286:
287:
288:
289:
290:
291:
292:
293:
294:
295:
296:
297:
298:
299:
300:
301:
302:
303:
304:
305:
306:
307:
308:
309:
310:
311:
312:
313:
314:
315:
316:
317:
318:
319:
320:
321:
322:
323:
324:
325:
326:
327:
unit Dlg;

interface

uses
  Windows, Forms, Messages, Classes, ExtDlgs, Dialogs, CommDlg;

var
  HelpMsg: Cardinal;


{OpenDlg}
type
  TOpenDlg = class(TOpenDialog)
  private
    FOnHelp: TNotifyEvent;
  protected
    procedure DoHelp; dynamic;
    procedure WndProc(var message: Tmessage); override;
  published
    property OnHelp: TNotifyEvent read FOnHelp write FOnHelp;
  end;

{------------------------------------------------------------------------------}

{SaveDlg}
  TSaveDlg = class(TSaveDialog)
  private
    FOnHelp: TNotifyEvent;
  protected
    procedure DoHelp; dynamic;
    procedure WndProc(var message: Tmessage); override;
  published
    property OnHelp: TNotifyEvent read FOnHelp write FOnHelp;
  end;

{------------------------------------------------------------------------------}

{OpenPictureDlg}
  TOpenPictureDlg = class(TOpenPictureDialog)
  private
    FOnHelp: TNotifyEvent;
  protected
    procedure DoHelp; dynamic;
    procedure WndProc(var message: Tmessage); override;
  published
    property OnHelp: TNotifyEvent read FOnHelp write FOnHelp;
  end;

{------------------------------------------------------------------------------}

{SavePictureDlg}
  TSavePictureDlg = class(TSavePictureDialog)
  private
    FOnHelp: TNotifyEvent;
  protected
    procedure DoHelp; dynamic;
    procedure WndProc(var message: Tmessage); override;
  published
    property OnHelp: TNotifyEvent read FOnHelp write FOnHelp;
  end;

{------------------------------------------------------------------------------}

{FontDlg}
  TFontDlg = class(TFontDialog)
  private
    FOnHelp: TNotifyEvent;
  protected
    procedure DoHelp; dynamic;
    function MessageHook(var Msg: TMessage): Boolean; override;
  published
    property OnHelp: TNotifyEvent read FOnHelp write FOnHelp;
  end;

{------------------------------------------------------------------------------}

{ColorDlg}
  TColorDlg = class(TColorDialog)
  private
    FOnHelp: TNotifyEvent;
  protected
    procedure DoHelp; dynamic;
    function MessageHook(var Msg: TMessage): Boolean; override;
  published
    property OnHelp: TNotifyEvent read FOnHelp write FOnHelp;
  end;

{------------------------------------------------------------------------------}

{PrntDlg}
  TPrntDlg = class(TPrintDialog)
  private
    FOnHelp: TNotifyEvent;
  protected
    procedure DoHelp; dynamic;
    function MessageHook(var Msg: TMessage): Boolean; override;
  published
    property OnHelp: TNotifyEvent read FOnHelp write FOnHelp;
  end;

{------------------------------------------------------------------------------}

{FindDlg}
  TFindDlg = class(TFindDialog)
  private
    FOnHelp: TNotifyEvent;
  protected
    procedure DoHelp; dynamic;
    function MessageHook(var Msg: TMessage): Boolean; override;
  published
    property OnHelp: TNotifyEvent read FOnHelp write FOnHelp;
  end;

{------------------------------------------------------------------------------}

{ReplaceDlg}
  TReplaceDlg = class(TReplaceDialog)
  private
    FOnHelp: TNotifyEvent;
  protected
    procedure DoHelp; dynamic;
    function MessageHook(var Msg: TMessage): Boolean; override;
  published
    property OnHelp: TNotifyEvent read FOnHelp write FOnHelp;
  end;

procedure Register;

implementation


{OpenDlg}
procedure TOpenDlg.WndProc(var message: Tmessage);
begin
  {Hilfebutton angeklickt}
  message.Result := 0;
  if (message.Msg = WM_INITDIALOG) and
    not (ofOldStyleDialog in Options) then exit
  else if (message.Msg = WM_NOTIFY) then
    case (POFNotify(message.LParam)^.hdr.code) of
      CDN_HELP: DoHelp;
    end;

  inherited WndProc(message);
end;

procedure TOpenDlg.DoHelp;
begin
  if Assigned(FOnHelp) then FOnHelp(Self);
end;

{------------------------------------------------------------------------------}

{SaveDlg}
procedure TSaveDlg.WndProc(var message: Tmessage);
begin
  {Hilfebutton angeklickt}
  message.Result := 0;
  if (message.Msg = WM_INITDIALOG) and
    not (ofOldStyleDialog in Options) then exit
  else if (message.Msg = WM_NOTIFY) then
    case (POFNotify(message.LParam)^.hdr.code) of
      CDN_HELP: DoHelp;
    end;

  inherited WndProc(message);
end;

procedure TSaveDlg.DoHelp;
begin
  if Assigned(FOnHelp) then FOnHelp(Self);
end;

{------------------------------------------------------------------------------}

{OpenPictureDlg}
procedure TOpenPictureDlg.WndProc(var message: Tmessage);
begin
  {Hilfebutton angeklickt}
  message.Result := 0;
  if (message.Msg = WM_INITDIALOG) and
    not (ofOldStyleDialog in Options) then exit
  else if (message.Msg = WM_NOTIFY) then
    case (POFNotify(message.LParam)^.hdr.code) of
      CDN_HELP: DoHelp;
    end;

  inherited WndProc(message);
end;

procedure TOpenPictureDlg.DoHelp;
begin
  if Assigned(FOnHelp) then FOnHelp(Self);
end;

{------------------------------------------------------------------------------}

{SavePictureDlg}
procedure TSavePictureDlg.WndProc(var message: Tmessage);
begin
  {Hilfebutton angeklickt}
  message.Result := 0;
  if (message.Msg = WM_INITDIALOG) and
    not (ofOldStyleDialog in Options) then exit
  else if (message.Msg = WM_NOTIFY) then
    case (POFNotify(message.LParam)^.hdr.code) of
      CDN_HELP: DoHelp;
    end;

  inherited WndProc(message);
end;

procedure TSavePictureDlg.DoHelp;
begin
  if Assigned(FOnHelp) then FOnHelp(Self);
end;

{------------------------------------------------------------------------------}

{FontDlg}
function TFontDlg.MessageHook(var Msg: TMessage): Boolean;
begin
  Result := False;
  if (Msg.Msg = HelpMsg) then
  begin
    DoHelp;
    Result := True;
  end;
end;

procedure TFontDlg.DoHelp;
begin
  if Assigned(FOnHelp) then FOnHelp(Self);
end;

{------------------------------------------------------------------------------}

{ColorDlg}
function TColorDlg.MessageHook(var Msg: TMessage): Boolean;
begin
  Result := False;
  if (Msg.Msg = HelpMsg) then
  begin
    DoHelp;
    Result := True;
  end;
end;

procedure TColorDlg.DoHelp;
begin
  if Assigned(FOnHelp) then FOnHelp(Self);
end;

{------------------------------------------------------------------------------}

{PrntDlg}
function TPrntDlg.MessageHook(var Msg: TMessage): Boolean;
begin
  Result := False;
  if (Msg.Msg = HelpMsg) then
  begin
    DoHelp;
    Result := True;
  end;
end;

procedure TPrntDlg.DoHelp;
begin
  if Assigned(FOnHelp) then FOnHelp(Self);
end;

{------------------------------------------------------------------------------}

{FindDlg}
function TFindDlg.MessageHook(var Msg: TMessage): Boolean;
begin
  Result := False;
  if (Msg.Msg = HelpMsg) then
  begin
    DoHelp;
    Result := True;
  end;
end;

procedure TFindDlg.DoHelp;
begin
  if Assigned(FOnHelp) then FOnHelp(Self);
end;

{------------------------------------------------------------------------------}

{ReplaceDlg}
function TReplaceDlg.MessageHook(var Msg: TMessage): Boolean;
begin
  Result := False;
  if (Msg.Msg = HelpMsg) then
  begin
    DoHelp;
    Result := True;
  end;
end;

procedure TReplaceDlg.DoHelp;
begin
  if Assigned(FOnHelp) then FOnHelp(Self);
end;


{------------------------------------------------------------------------------}


procedure InitGlobals;
begin
  HelpMsg := RegisterWindowMessage(HelpMsgString);
end;

procedure Register;
begin
  RegisterComponents('Dlg', [TOpenDlg, TSaveDlg, TOpenPictureDlg,
   TSavePictureDlg, TFontDlg, TColorDlg, TPrntDlg, TFindDlg, TReplaceDlg]);
end;

initialization
  InitGlobals;

end.