Autor Beitrag
mandras
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 432
Erhaltene Danke: 107

Win 10
Delphi 6 Prof, Delphi 10.4 Prof
BeitragVerfasst: Fr 23.03.12 23:49 
Betr: Delphi 6

Mir fiel folgendes Verhalten eines MainMenu auf (alle Menuitems haben korrekte HelpContext-Einträge):

1- Wenn ein TMenuItem keine Unterpunkte aufweist wird, falls es markiert ist, die Online-Hilfe korrekt aufgerufen
2- Wenn Unterpunkte existieren wird die Online-Hilfe nicht aufgerufen.

Eine Debugger-Session führte zur Erkenntnis daß im Fall 2 kein HELP-Event erzeugt wird, warum auch immer. Ich denke es liegt am Mapping eines Windows-Menüs auf die VCL-Ebene.

Suchmaschinchen halfen mir nicht weiter, daher hier die Frage:
Gibt es einen Workaround so daß für die Einträge gemäß 2) das Hilfesystem aufgerufen wird?
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19314
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Sa 24.03.12 09:04 
user profile iconmandras hat folgendes geschrieben Zum zitierten Posting springen:
Ich denke es liegt am Mapping eines Windows-Menüs auf die VCL-Ebene.
Nein, es liegt wohl eher am Windows-Menü selbst. ;-)
Windows erzeugt auch keine Click-Message für Menüeinträge, die Untermenüeinträge haben. Deshalb vermute ich mal auch in diesem Fall liegt es daran.
mandras Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 432
Erhaltene Danke: 107

Win 10
Delphi 6 Prof, Delphi 10.4 Prof
BeitragVerfasst: So 25.03.12 00:56 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconmandras hat folgendes geschrieben Zum zitierten Posting springen:
Ich denke es liegt am Mapping eines Windows-Menüs auf die VCL-Ebene.
Nein, es liegt wohl eher am Windows-Menü selbst. ;-)


Das meinte ich mit "Mapping".

Immerhin werden "WMMenuSelect"-Nachrichten gesendet. Damit kann ich festellen welcher Menüeintrag von der Maus gerade geärgert wird. Das kann ich abfangen und auch somit die HelpContext der jeweiligen Einträge feststellen. Und in Variablen speichern.

Aber: Solange Windows die Oberhoheit hat (also die Darstellung des Menüs erfolgt etc) reagiert die Applikation nicht auf F1.. Ich würde gerne auf Global Key Hooks verzichten.
Wüßte jemand wie ich auf möglichst einfache Art das Drücken der Taste F1 für die aktuelle Applikation abfangen kann WÄHREND Windows die Menüs handled?

Ja, ich weiß.. esoterische Frage.. Andererseits wäre mir eine konsistente Online-Hilfe auch ganz lieb. "Intiutiv" wäre das richtige Wort.

Moderiert von user profile iconNarses: Beiträge zusammengefasst

Ich denke ich habe das Problem gelöst.

Falls jemand anderes auch darüber stolpert hier der Code incl. Erläuterungen:

ausblenden volle Höhe 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:
// Dieser Programmteil dient dazu kontextsensitive Hilfe per F1 für Menüpunkte
// mit Unterpunkten bereitzustellen da Windows in diesem Fall keine
// WM_Help-Message generiert.
// Arbeitsweise: Keyboard Hook (auf Applikationsebene) erstellen der auf
// F1 reagiert.
// Weiterhin: "Tracken" mittels WM_MenuSelect welcher Menüpunkt gerade
// aktiv ist.
// Wenn nun F1 gedrückt prüfen ob aktiver Menüpunkt Unterpunkte hat.
// - falls ja: Help Context ermitteln, Hilfe anzeigen
// - falls nein: nichts tun, Windows macht den Rest.

// im private-Bereich der Formdeklaration einfügen:
//   ActiveMenu, ActiveMenuItem, ActiveMenuFlag: integer;
//   KBHook: HHook; {this intercepts keyboard input}

// im Interfacebereich deklarieren
// function KeyboardHookProc(Code: Integer; WordParam: Word; LongParam: LongInt): LongInt; stdcall;

// im OnCreate des Formulars:
//  KBHook:=SetWindowsHookEx(WH_KEYBOARD,
//             @KeyboardHookProc,
//             HInstance,
//             GetCurrentThreadId()) ;
// entsprechend im OnDestroy:
//    UnHookWindowsHookEx(KBHook) ;

procedure Tmainform.WMMenuSelect(var Message: TWMMenuSelect);
begin
 ActiveMenu := Message.Menu;
 ActiveMenuItem := Message.IDItem;
 ActiveMenuFlag := Message.MenuFlag;
end;

// Rückgabe:
// Falls keine Untermenüeinträge: Rückgabe = 0 - unbehandelt.
// Windows soll F1 verarbeiten
// Falls Untereinträge existieren: HelpContext aufrufen, Rückgabe 1
// (Windows soll nichts weiteres mehr tun).

function TMainForm.CheckContextHelp:integer;
var
  MenuItem: TMenuItem;
  ID: Integer;
  FindKind: TFindItemKind;
begin
 Result := 0// Windows soll F1 behandeln
  if Menu <> nil then begin
   MenuItem := nil;
   if (ActiveMenuFlag <> $FFFFor (ActiveMenuItem <> 0then begin
    FindKind := fkCommand;
    ID := ActiveMenuItem;
    if ActiveMenuFlag and MF_POPUP <> 0 then begin
     FindKind := fkHandle;
     ID := GetSubMenu(ActiveMenu, ID);
    end;
    MenuItem := Menu.FindItem(ID, FindKind);
   end;
   if (MenuItem <> niland (MenuItem.Count > 0then begin
    if MenuItem.HelpContext <> 0 then Application.HelpContext(MenuItem.HelpContext);
    Result := 1;
   end;
  end;
end;


function KeyboardHookProc(Code: Integer; WordParam: Word; LongParam: LongInt) : LongInt;
begin
 case WordParam of
  vk_F1: begin
   result := Mainform.CheckContextHelp;
   exit;
  end;
 end{case}
 result:=0;
end;
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19314
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: So 25.03.12 14:27 
Vorsicht, du klaust damit anderen Anwendungen den Keyboard-Hook, auch wenn du den Tastendruck gar nicht behandelst... keine gute Idee. ;-)
msdn.microsoft.com/e...esktop/ms644990.aspx hat folgendes geschrieben:
Calling the CallNextHookEx function to chain to the next hook procedure is optional, but it is highly recommended; otherwise, other applications that have installed hooks will not receive hook notifications and may behave incorrectly as a result. You should call CallNextHookEx unless you absolutely need to prevent the notification from being seen by other applications.
mandras Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 432
Erhaltene Danke: 107

Win 10
Delphi 6 Prof, Delphi 10.4 Prof
BeitragVerfasst: So 25.03.12 14:54 
Berechtigter Einwand, ich denke aber hier nicht zutreffend da der (das?) Hook nur auf Applikationsebene definiert wurde. Andererseits, sollte in der Anwendung selbst noch irgendein Hook sein (von dem ich nicht zwangsläufig wissen muß), sollte die Kette korrekt forgesetzt werden. Danke für den Hinweis :)