Die kontextsensitive Hilfe verwenden


Um in der API-Programmierung die kontextsensitive Hilfe nutzen zu können müssen wir den jeweiligen Elementen zuerst eine Kontext-ID zuordnen. Dazu verwenden wir den Befehl SetWindowContextHelpId. Da wir ja wissen, dass auch Buttons, Eingabefelder usw. im Prinzip nur Fenster sind, dürfte es uns nicht schwer fallen, unserem ersten Button und unserem Eingabefeld eine solche Kontext-ID zu geben. Üblicherweise besitzen Fenster mit einer kontextsensitiven Hilfe einen entsprechenden Button in der Titelzeile



Allerdings darf unser Fenster dann keine Minimierungs- und Maximierungsschaltfläche besitzen. Eine "Designschwäche" seitens Microsoft, möchte ich mal sagen. Sei´s drum ... Wenn wir diesen Hilfe-Button benutzen wollen, müssen wir unser Fenster mit einem erweiterten Stil-Attribut erstellen:

CreateWindowEx({ erweitertes Attribut --> }WS_EX_CONTEXTHELP, ... );

Klicken Sie diesen Button an, ändert sich der Mauszeiger. Damit klicken Sie nun auf das gewünschte Element, zu dem Sie die kontextbezogene Hilfe sehen wollen, und es wird eine "WM_HELP"-Nachricht ausgelöst.
An dieser Stelle kurz zum Nachdenken: Unsere Anwendung reagiert bereits auf diese Nachricht. Wir müssen natürlich auch dafür sorgen, dass sie auf die kontextsensitive Hilfe reagiert. Hier ist allerdings wichtig, in welcher Reihenfolge wir vorgehen. Als Beispiel: die "WM_HELP"-Nachricht wird bisher wie folgt behandelt:

if(PHelpInfo(lp)^.hItemHandle = wnd) or
  (GetParent(PHelpInfo(lp)^.hItemHandle) = wnd)
then
  SendMessage(wnd,WM_COMMAND,MAKELONG(IDC_TOCBTN,BN_CLICKED),0)

Würden wir jetzt den für die Kontext-Hilfe notwendigen Code einfach anhängen ergäbe sich ein Problem, das mit der Dialogbox aus dem vorigen Kapitel zu tun hat: Diesmal ist es ja nicht das Fenster-Handle, das übergeben wird, sondern es ist das Handle des jeweiligen Controls (ein Button, ein Eingabefeld, usw.). Da sich dieses Control aber auf unserem Fenster befindet, wird die o.g. Bedingung wirksam, und die Anwendung zeigt nicht die gewünschte Kontext-Hilfe sondern das Inhaltsverzeichnis oder die erste Seite der Hilfe.
Aus dem Grund sollten Sie immer zuerst prüfen, ob eine Kontext-ID übergeben wurde oder nicht. Das heißt, der Code für die kontextsensitive Hilfe muss zuerst geschrieben werden, womit die erweiterte "WM_HELP"-Behandlung dann so aussieht:

WM_HELP:
  if(PHelpInfo(lp)^.dwContextId > 0) then
    WinHelp(wnd,@szHelpFile[1],HELP_CONTEXTPOPUP,
    PHelpInfo(lp)^.dwContextId)
  else
  if(PHelpInfo(lp)^.hItemHandle = wnd) or
    (GetParent(PHelpInfo(lp)^.hItemHandle) = wnd)
  then
    SendMessage(wnd,WM_COMMAND,MAKELONG(IDC_TOCBTN,BN_CLICKED),0)
  else
    Result := DefWindowProc(wnd,uMsg,wp,lp);


Direkthilfe via Popupmenü

Widmen wir uns noch diesem Problem. Sie kennen das vielleicht aus einigen Anwendungen, dass Sie ein Element auch mit der rechten Maustaste anklicken können. Ein Menü erscheint, üblicherweise mit dem Eintrag "Direkthilfe", das Ihnen ebenfalls die Kontext-Informationen anzeigt.
Allzu schwer ist es zum Glück nicht. Für unser Menü fangen wir zunächst die Nachricht "WM_CONTEXTMENU" ab. Im WPARAM-Wert finden wir dann das Fenster-Handle, bei dem diese Nachricht ausgelöst wurde. Auf die Weise können wir bestimmen, wo das Popupmenü erscheinen soll:

WM_CONTEXTMENU:
  if(wp = hTocBtn) or (wp = hIdxBtn) then
  begin
    // Popupmenü erzeugen
// Kontext-Id holen
cId := GetWindowContextHelpId(wp); end else cId := -1;

In dem Fall sind es nur zwei Buttons, bei denen wir das Menü anzeigen lassen. Sie sollten Eingabefelder u.ä. bitte generell ausklammern, da diese ein eigenes Kontextmenü zur Textbearbeitung (Kopieren, Ausschneiden, Einfügen usw.) besitzen. Für solche Elemente stehen Ihnen nach wie vor der Hilfe-Button in der Titelleiste und die F1-Taste zur Verfügung.

Die Anzeige der Kontext-Information erfolgt dann über die normale Abfrage des Menüeintrags:

WM_COMMAND:
  case HIWORD(wp) of
    BN_CLICKED:
      case LOWORD(wp) of
        IDC_DIRECTHELP:
          if(cId > 0) then
            WinHelp(wnd,@szHelpFile[1],HELP_CONTEXTPOPUP,cId);
      end;
  end;