Iczelion - 27 - Tooltip Steuerelement

Tutorial 27: Tooltip Steuerelement


Wir werden lernen was das Tooltip Steuerelement ist, wie man es erzeugt und benutzt. Laden Sie das Beispiel herunter.

Theorie:

Ein Tooltip ist ein kleines rechteckiges Fenster, das angezeigt wird, wenn der Maus-Zeiger über einer bestimmten Fläche ist. Ein Tooltip Fenster enthält einen Text, den der Programmierer angezeigt haben möchte. In dieser Hinsicht spielt ein Tooltip die selbe Rolle wie eine Status Fenster, nur das es verschwindet, wenn der Benutzer klickt oder den Mauszeiger aus dieser Fläche wieder wegbewegt. Sie sind wahrscheinlich mit Tooltips vertraut, die bei Toolbar-Buttons auftauchen. Diese "Tooltips" werden bequem von den Toolbar-Steuerelementen selbst zu verfügung gestellt. Wenn Sie ein Tooltip für andere Fenster/Steuerelemente haben möchten, müssen Sie ihr eigenes Tooltip-Steuerelement erzeugen.
Nun, da Sie wissen, was ein Tooltip ist, lassen Sie uns weiter machen, wie man so was erzeugt und benutzt. Folgende Schritte sind dafür nötig:
  1. Erzeugen Sie ein Tooltip Steuerelement mit CreateWindowEx
  2. Definieren Sie eine Region, wo das Tooltip-Steuerelement angezeigt werden soll, wenn sich der Mauszeiger darüber befindet.
  3. Übermitteln Sie diese Region dem Tooltip-Steuerelement.
  4. Fangen Sie die Maus-Nachrichten für die übermittelte Region zum Tooltip-Steuerelement ab (dieser Schritt kann auch früher geschehen, je nachdem welche Methode Sie verwenden, die Nachrichten abzufangen)
Als nächstes werden wir jeden Schritt im Detail betrachten.

Tooltip erzeugen

Ein Tooltip Steuerelement ist ein Standard Steuerelement. Deswegen, müssen Sie irgendwo in Ihrem Code InitCommonControls aufrufen, so dass MASM implizit comctl32.dll zu Ihrem Programm linkt. Sie erzeugen ein Tooltip Steuerelement mit CreateWindowEx. Das typische Szenario wäre folgendes:
.data TooltipClassName db "Tooltips_class32",0 .code ..... invoke InitCommonControls invoke CreateWindowEx, NULL, addr TooltipClassName, NULL, TIS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL


Beachten Sie den Fenster Stil: TIS_ALWAYSTIP. Der Stil spezifziert, dass der Tooltip angezeigt wird, wenn der Mauszeiger über der definierten Fläche ist, egal welchen Status das Fenster hat, indem sich diese Fläche befindet. Vereinfacht gesagt, wenn Sie dieses Flag benutzen, wird das Tooltip Steuerelement angezeigt, wenn sich der Mauszeiger über der zum Tooltip zugeordneten Fläche befindet, selbst wenn das Fenster nicht aktiv sein sollte.
Sie müssen nicht den WS_POPUP und WS_EX_TOOLWINDOW Stil bei CreateWindowEx angeben, da die Tooltip Steuerelement Fenster Prozedur diese automatisch hinzufügt. Sie müssen auch nicht die Koordinaten, Höhe und Breite des Tooltip Fensters angeben: das Tooltip Steuerelement wird sie automatisch anpassen, damit der Tooltip Text angezeigt werden kann, wehalb wir in allen vier Parametern CW_USEDEFAULT angeben. Die übrigen Parameter sind nicht beachtenswert.

Das Tool spezifizieren

Das Tooltip Steuerelement ist erzeugt, wird aber nicht unverzüglich angezeigt. Wir wollen das Tooltip-Fenster anzeigen lassen, wenn der Mauszeiger sich über eine bestimmte Fläche bewegt. Nun wird es Zeit, diese Fläche zu spezifizieren. Wir nennen eine solche Fläche "Tool". Ein Tool ist eine rechteckige Fläche auf der Client Area des Fensters, welches das Tooltip Steuerelement auf den Mauszeiger hin überwacht. Wenn der Mauszeiger über dem Tool ist, wird das Tooltip-Fenster erscheinen. Die rechteckige Fläche kann die gesamte Client Area einnehmen oder auch nur einen Teil davon. Demnach können wir Tools in zwei Arten einteilen: einmal welche, die als Fenster implementiert werden und welche die als rechteckige Fläche in der Client Area eines Fensters implementiert werden. Beide haben ihren Nutzen. Das Tool, das die gesamte Fläche des Fensters abdeckt, wird meistens bei Steuerelementen wie Buttons, Edit-Steuerelemente und ähnlichen benutzt. Sie müssen nicht die Koordinaten und Dimensionen des Tools spezifizieren: es wird angenommen, dass die gesamte Client Area des Fensters benutzt werden soll. Das Tool, das als rechteckige Fläche einer Client Area implementiert wird, ist nützlich, wenn Sie die Client Area des Fensters in mehrere Regionen teilen möchten, ohne verschiedene Child-Fenster. Mit dieser Art Tool, müssen Sie die Koordinaten der oberen linken Ecke und die Breite und Höhe des Tools angeben.
Sie spezifizieren das Tool mit der TOOLINFO Struktur, welche folgende Definition hat:
TOOLINFO STRUCT cbSize DWORD ? uFlags DWORD ? hWnd DWORD ? uId DWORD ? rect RECT hInst DWORD ? lpszText DWORD ? lParam LPARAM ? TOOLINFO ENDS


Element Name Erklärung
cbSize Die Größe der TOOLINFO Struktur. Sie MÜSSEN dieses Element füllen. Windows meldet keinen Fehler, wenn dieses Element nicht korrekt gefüllt ist, dafür erhalten Sie komische unvorhersehbare Ergebnisse.
uFlags Die Bit Flags, die die Charakteristika eines Tool spezifzieren. Dieser Wert kann eine Kombination aus folgenden Flags sein:
  • TTF_IDISHWND "ID ist hWnd". Wenn Sie dieses Flag angeben, bedeutet das, dass Sie ein Tool benutzen wollen, dass die gesamte Client Area des Fensters einnimmt (die erste Art obiger Tools). Wenn Sie das Flag benutzen MÜSSEN Sie das uId Element dieser Struktur mit dem Handle des Fensters, das Sie benutzen wollen, füllen. Wenn Sie dieses Flag nicht angeben, bedeutet das, dass Sie die zweite Art Tools benutzen wollen, die, die als rechteckige Fläche der Client Area implementiert werden. In diesem Fall müssen Sie das rect Element mit der Dimension des Rechtecks füllen.
  • TTF_CENTERTIP Normalerweise erscheint das Tooltip-Fenster rechts unterhalb des Mauszeigers. Wenn Sie dieses Flag angeben, erscheint das Tooltip-Fenster immer direkt unter dem Tool und ist zentriert, egal welche Position der Mauszeiger hat.
  • TTF_RTLREADING Sie können dieses Flag vergessen, wenn Ihr Programm nicht für arabische oder hebräische Systeme gemacht ist. Dieses Flag zeigt den Tooltip-Text mit der von rechts-nach-links-Lese-Ausrichtung an. Läuft nicht auf anderen Systemen.
  • TTF_SUBCLASS Wenn Sie dieses Flag benutzen, bedeutet das, dass Sie dem Tooltip-Steuerelement mitteilen, dass es das Fenster auf dem es ist, ableiten (subclassing) soll, so dass das Tooltip-Steuerelement Mausnachrichten an das Fenster abfangen kann. Dieses Flag ist sehr nützlich. Wenn Sie dieses Flag nicht benutzen, haben Sie mehr Arbeit, um die Mausnachrichten an das Tooltip-Steuerlement weiterzuleiten.
hWnd Handle des Fensters, dass das Tool enthält. Wenn Sie das TTF_IDISHWND Flag angeben, wird dieses Feld ignoriert, da Windows den Wert im uId Element als Fenster-Handle benutzen wird. Sie müssen dieses Feld füllen, wenn:
  • Sie nicht das TTF_IDISHWND Flag benutzen (in anderen Worten, Sie benutzen ein rechteckiges Tool)
  • Sie den Wert LPSTR_TEXTCALLBACK im lpszText Element angeben. Dieser Wert teilt dem Tooltip Steuerelement mit, dass, wenn es das Tooltip-Fenster anzeigen soll, es das Fenster, in dem das Tool enthalten ist, fragen muss, damit der Text angezeigt wird. Das ist eine Art dynamisches Echtzeit Tooltip Text Update. Wenn Sie den Tooltip Text dynamische ändern wollen, sollten Sie den LPSTR_TEXTCALLBACK Wert im lpszText Element angeben. Das Tooltip Steuerelement wird eine TTN_NEEDTEXT Benachrichtigungs-Nachricht an das Fenster, dass anhand seines Handles in hWnd identifiziert wird, senden.
uId Der Wert in diesem Feld kann zwei Bedeutungen haben, abhängig davon, ob das uFlags Element das TTF_IDISHWND Flag enthält.
  • Applikations-definierte Tool ID, wenn das TTF_IDISHWND Flag nicht angegeben wird. Da das bedeutet, dass Sie ein Tool benutzen, das nur ein Teil der Client Area abdeckt, ist es logisch, dass Sie mehrere solcher Tools auf der selben Client Area haben können (ohne sich zu überlappen). Das Tooltip Steuerelement braucht eine Möglichkeit um zwischen ihnen zu unterscheiden. In diesem Fall ist das Fenster-Handle im hWnd Element nicht ausreichend, da alle Tools im selben Fenster sind. Die Applikations-definierten IDs sind somit notwendig. Die IDs können jeglichen Wert annehmen, solange sie unter einander einmalig sind.
  • Das Handle des Fensters, dessen gesamte Client Area als Tool genutzt wird, wenn Sie das TTF_IDISHWND Flag angeben. Sie werden sich vielleicht wundern, warum dieses Feld benutzt wird, um das Fenster-Handle abzuspeichern, anstatt das obige hWnd Feld. Die Antwort ist: das hWnd Element ist vielleicht schon gefüllt, wenn der Wert LPSTR_TEXTCALLBACK im lpszText Element angegeben ist und das Fenster, das verantwortlich für den Tooltip Text ist und das Fenster, dass das Tool enthält, müssen NICHT die selben sein. (Sie können Ihr Programm so designen, dass ein einzelnes Fenster beide Rollen übernimmt, aber das ist zu restriktiv. In diesem Fall gibt Ihnen Microsoft mehr Freiheit. Cheers.)
rect Eine RECT Struktur, die die Dimensionen des Tools spezifiziert. Diese Struktur definiert ein Rechteck relativ zur oberen linken Ecke der Client Area des Fensters, das im hWnd Element spezifiziert ist. Kurz gesagt, Sie müssen diese Struktur füllen, wenn Sie nur einen Teil der Client Area mit dem Tool abdecken wollen. Das Tooltip Steuerelement wird das Feld ignorieren, wenn Sie das TTF_IDISHWND Flag angeben (Sie wählen, dass das Tool die gesamte Client Area abdecken soll)
hInst Das Handle der Instanz, dass die String Ressource enthält, die als Tooltip Text benutzt werden soll, wenn der Wert im lpszText Element als String Ressource Identifizierer spezifiziert wurde. Das mag verwirrend klingen. Lesen Sie die Erklärung des lpszText Elements als erstes und Sie werden verstehen, wofür dieses Feld ist. Das Tooltip-Steuerelement ignoriert dieses Feld, wenn das lpszText Feld keinen String Ressource Identifizierer enthält
lpszText Dieses Feld kann verschiedene Werte haben:
  • Wenn Sie den Wert LPSTR_TEXTCALLBACK in diesem Feld angeben, wird das Tooltip Steuerelement eine TTN_NEEDTEXT Benachrichtigungs Nachricht an das Fenster, das durch das Handle im hWnd Feld identifiziert wird, senden, damit der Tooltip Text im Tooltip Fenster angezeigt wird. Das ist die dynamischiste Methode um den Tooltip Text upzudaten: Sie können den Tooltip Text jedes Mal ändern, wenn das Tooltip Fenster angezeigt wird.
  • Wenn Sie einen String Ressource Identifizierer in diesem Feld angeben, sucht das Tooltip Steuerelement, sobald es den Tooltip Text im Tooltip Fenster anzeigen soll, den String in der String-Tabelle der Instanz, die durch das hInst Element spezifiziert wird. Das Tooltip Steuerelement identifiziert einen String Ressource Identifizierer indem das obere Word dieses Felds überprüft wird. Da ein String Ressource Identifizierer ein 16-Bit Wert ist, ist das obere Word dieses Feldes immer null. Diese Methode ist nützlich, wenn Sie planen Ihr Programm in andere Sprachen zu portieren. Da die String Ressource im Ressource Skript definiert ist, müssen Sie nicht den Source Code modifizieren. Sie müssen nur die String Tabelle modifizieren und die Tooltip Texte werden sich ändern ohne das Risiko Fehler in Ihr Programm einzubauen.
  • Wenn der Wert in diesem Feld nicht gleich LPSTR_TEXTCALLBACK ist und das obere Word nicht gleich null ist, interpretiert das Tooltip Steuerelement den Wert als Pointer auf einen Text String, der als Tooltip Text benutzt wird. Diese Methode ist am einfachsten zu nutzen, aber auch am wenigsten flexibel.
Kurz zusammgefast, müssen Sie die TOOLINFO Struktur füllen, bevor Sie sie an das Tooltip-Steuerelement weiterleiten. Diese Struktur beschreibt die Charakteristika des Tools das Sie wünschen.

Das Tool beim Tooltip-Steuerelement registrieren

Nachdem Sie die TOOLINFO Struktur gefüllt haben, müssen Sie sie dem Tooltip Steuerelement übermitteln. Ein Tooltip Steurelement kann mehrere Tools bedienen, weshalb es normalerweise unnötig ist mehr als ein Tooltip Steuerelement für ein Fenster zu erstellen. Um das Tool beim Tooltip-Steuerelement zu registrieren, senden Sie die TTM_ADDTOOL Nachricht an das Tooltip Steuerelement. Der wParam wird nicht gebraucht und lParam muss die Adresse der TOOLINFO Struktur enthalten, die Sie registrieren wollen.
.data? ti TOOLINFO ....... .code ....... <füllen der TOOLINFO Struktur> ....... invoke SendMessage, hwndTooltip, TTM_ADDTOOL, NULL, addr ti


SendMessage wird für diese Nachricht TRUE zurückliefern, wenn das Tool erfolgreich registriert wurde, ansonsten FALSE.
Sie können die Registratur wieder rückgängig machen, indem Sie eine TTM_DELTOOL Nachricht an das Tooltip Steuerelement senden.

Maus-Nachrichten zum Tooltip Steuerelement umleiten

Wenn der obige Schritt beendet ist, weiß das Tooltip-Steuerelement, welche Fläche es auf Maus-Nachrichten hin überwachen soll und welchen Text es im Tooltip-Fenstre anzeigen soll. Das einzige was fehlt, ist der *Auslöser* für die Aktion. Denken Sie mal darüber nach: die Fläche ist mittels des Tools auf der Client Area des anderen Fensters spezifziert. Wie kann das Tooltip Steuerelement die Nachriten für ds Ziel Fenster empfangen? Muss es ja, damit es die Zeit messen kann, die sich der Mauszeiger über der Fläche befindet, damit für diese Zeit das Tooltip Fenster angezeigt werden kann. Es gibt zwei Methoden dieses Ziel zu erreichen, eine, die die Kooperation des Fensters benötigt, die das Tool enthält und eine die die Kooperation nicht benötigt.
  • Das Fenster, welches das Tool enthält, muss die Maus-Nachrichten auf das Tooltip-Steuerelement umeleiten, indem die TTM_RELAYEVENT Nachrichten an das Steuerelement gesendet werden. lParam der Nachricht muss dabei die Adresse der MSG Struktur enthalten, die die Nachricht spezifiziert, die an das Tooltip Steuerelement weitergeleitet wird. Ein Tooltip-Steuerelement verarbeitet nur folgende Maus-Nachrichten:
    • WM_LBUTTONDOWN
    • WM_MOUSEMOVE
    • WM_LBUTTONUP
    • WM_RBUTTONDOWN
    • WM_MBUTTONDOWN
    • WM_RBUTTONUP
    • WM_MBUTTONUP
    Alle anderen Nachrichten werden ignoriert. Demnach muss in der Fenster-Prozedur des Fensters, die das Tool enthält ein switch sein, das etwas ähnliches wie folgendes enthält:
    WndProc proc hWnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD ....... if uMsg==WM_CREATE ............. elseif uMsg==WM_LBUTTONDOWN || uMsg==WM_MOUSEMOVE || uMsg==WM_LBUTTONUP || uMsg==WM_RBUTTONDOWN || uMsg==WM_MBUTTONDOWN || uMsg==WM_RBUTTONUP || uMsg==WM_MBUTTONUP invoke SendMessage, hwndTooltip, TTM_RELAYEVENT, NULL, addr msg ..........


  • Sie können das TTF_SUBCLASS Flag im uFlags Element der TOOLINFO Struktur angeben. Dieses Flag teilt dem Tooltip-Steuerelement mit, dass es das Fenster, das das Tool enthält, ableiten soll (subclassing), so dass es die Nachrichten abfangen kann, ohne in Kooperation mit dem Fenster zu stehen. Diese Methode ist einfacher zu benutzen, da es nicht mehr programmierung braucht, als das TTF_SUBCLASS Flag und das Tooltip-Steuerelement händelt alle abgefangenen Nachrichten selbst.
Das ist alles. Nach diesem Schritt ist Ihr Tooltip Steuerelement voll funktionsfähig. Es gibt verschiede nützliche Tooltip-relevante Nachrichten, über die Sie bescheid wissen sollten.
  • TTM_ACTIVATE. Wenn Sie das Tooltip-Steuerelement dynamisch aktivieren/deaktivieren wollen, ist diese Nachricht für Sie. Wenn der wParam Wert gleich TRUE ist, wird das Tooltip-Steuerelement aktiviert. Wenn der wParam Wert gleich FALSE ist, wird das Tooltip-Steuerelement deaktiviert. Ein Tooltip Steuerelement ist aktiviert, wenn es das erste Mal erzeugt wird, weshalb Sie diese Nachricht nicht senden müssen, um es zu aktivieren.
  • TTM_GETTOOLINFO und TTM_SETTOOLINFO. Wenn Sie die Werte in der TOOLINFO Struktur ermitteln oder ändern wollen, nachdem sie an das Tooltip-Steuerelement übermittelt wurde, benutzen Sie diese Nachrichten. Sie müssen das Tool spezifizieren, das Sie ändern möchten, mit den korrekten uID und hWnd Werten. Wenn Sie nur das rect-Element ändern möchten, benutzen Sie die TTM_NEWTOOLRECT Nachricht. Wenn Sie nur den Tooltip-Text ändern möchten, benutzen Sie TTM_UPDATETIPTEXT.
  • TTM_SETDELAYTIME. Mit dieser Nachticht, können Sie die Wartezeit spezifizieren, die das Tooltip-Steuerelement benutzt, wenn es den Tooltip-Text anzeigt und vieles mehr.

Beispiel:

Das folgende Beispiel ist eine einfach Dialog Box mit zwei Buttons. Die Client Area der Dialog Box ist in 4 Flächen unterteilt: oben links, oben recht, unten links und unten rechts. Jede Fläche ist als eigenes Tool mit eigenem Tooltip Text spezifiziert. Die zwei Buttons haben auch ihren eigenen Tooltip Text.
.386 .model flat,stdcall option casemap:none include \masm32\include\windows.inc include \masm32\include\kernel32.inc include \masm32\include\user32.inc include \masm32\include\comctl32.inc includelib \masm32\lib\comctl32.lib includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib DlgProc proto :DWORD,:DWORD,:DWORD,:DWORD EnumChild proto :DWORD,:DWORD SetDlgToolArea proto :DWORD,:DWORD,:DWORD,:DWORD,:DWORD .const IDD_MAINDIALOG equ 101 .data ToolTipsClassName db "Tooltips_class32",0 MainDialogText1 db "Das ist die obere linke Fläche des Dialogs",0 MainDialogText2 db "Das ist die obere rechte Fläche des Dialogs",0 MainDialogText3 db "Das ist die untere linke Fläche des Dialogs",0 MainDialogText4 db "Das ist die untere rechte Fläche des Dialogs",0 .data? hwndTool dd ? hInstance dd ? .code start: invoke GetModuleHandle,NULL mov hInstance,eax invoke DialogBoxParam,hInstance,IDD_MAINDIALOG,NULL,addr DlgProc,NULL invoke ExitProcess,eax DlgProc proc hDlg:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD LOCAL ti:TOOLINFO LOCAL id:DWORD LOCAL rect:RECT .if uMsg==WM_INITDIALOG invoke InitCommonControls invoke CreateWindowEx,NULL,ADDR ToolTipsClassName,NULL,\ TTS_ALWAYSTIP,CW_USEDEFAULT,\ CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\ hInstance,NULL mov hwndTool,eax mov id,0 mov ti.cbSize,sizeof TOOLINFO mov ti.uFlags,TTF_SUBCLASS push hDlg pop ti.hWnd invoke GetWindowRect,hDlg,addr rect invoke SetDlgToolArea,hDlg,addr ti,addr MainDialogText1,id,addr rect inc id invoke SetDlgToolArea,hDlg,addr ti,addr MainDialogText2,id,addr rect inc id invoke SetDlgToolArea,hDlg,addr ti,addr MainDialogText3,id,addr rect inc id invoke SetDlgToolArea,hDlg,addr ti,addr MainDialogText4,id,addr rect invoke EnumChildWindows,hDlg,addr EnumChild,addr ti .elseif uMsg==WM_CLOSE invoke EndDialog,hDlg,NULL .else mov eax,FALSE ret .endif mov eax,TRUE ret DlgProc endp EnumChild proc uses edi hwndChild:DWORD,lParam:DWORD LOCAL buffer[256]:BYTE mov edi,lParam assume edi:ptr TOOLINFO push hwndChild pop [edi].uId or [edi].uFlags,TTF_IDISHWND invoke GetWindowText,hwndChild,addr buffer,255 lea eax,buffer mov [edi].lpszText,eax invoke SendMessage,hwndTool,TTM_ADDTOOL,NULL,edi assume edi:nothing ret EnumChild endp SetDlgToolArea proc uses edi esi hDlg:DWORD,lpti:DWORD,lpText:DWORD,id:DWORD,lprect:DWORD mov edi,lpti mov esi,lprect assume esi:ptr RECT assume edi:ptr TOOLINFO .if id==0 mov [edi].rect.left,0 mov [edi].rect.top,0 mov eax,[esi].right sub eax,[esi].left shr eax,1 mov [edi].rect.right,eax mov eax,[esi].bottom sub eax,[esi].top shr eax,1 mov [edi].rect.bottom,eax .elseif id==1 mov eax,[esi].right sub eax,[esi].left shr eax,1 inc eax mov [edi].rect.left,eax mov [edi].rect.top,0 mov eax,[esi].right sub eax,[esi].left mov [edi].rect.right,eax mov eax,[esi].bottom sub eax,[esi].top mov [edi].rect.bottom,eax .elseif id==2 mov [edi].rect.left,0 mov eax,[esi].bottom sub eax,[esi].top shr eax,1 inc eax mov [edi].rect.top,eax mov eax,[esi].right sub eax,[esi].left shr eax,1 mov [edi].rect.right,eax mov eax,[esi].bottom sub eax,[esi].top mov [edi].rect.bottom,eax .else mov eax,[esi].right sub eax,[esi].left shr eax,1 inc eax mov [edi].rect.left,eax mov eax,[esi].bottom sub eax,[esi].top shr eax,1 inc eax mov [edi].rect.top,eax mov eax,[esi].right sub eax,[esi].left mov [edi].rect.right,eax mov eax,[esi].bottom sub eax,[esi].top mov [edi].rect.bottom,eax .endif push lpText pop [edi].lpszText invoke SendMessage,hwndTool,TTM_ADDTOOL,NULL,lpti assume edi:nothing assume esi:nothing ret SetDlgToolArea endp end start


Analyse:

Nachdem das Hauptdialog-Fenster erzeugt wurde, erzeugen wir mit CreateWindowEx ein Tooltip Steuerelement.
invoke InitCommonControls invoke CreateWindowEx,NULL,ADDR ToolTipsClassName,NULL,\ TTS_ALWAYSTIP,CW_USEDEFAULT,\ CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\ hInstance,NULL mov hwndTool,eax


Danach fahren wir damit fort, unsere vier Tools für jede Ecke der Dialog Box zu definieren.
mov id,0 ; wird als Tool ID benutzt mov ti.cbSize,sizeof TOOLINFO mov ti.uFlags,TTF_SUBCLASS ; teile dem Tooltip Steuerlement mit, dass vom Dialog Fenster abgeleitet werden soll push hDlg pop ti.hWnd ; Handle des Fensters, dass das Tool enthält invoke GetWindowRect,hDlg,addr rect ; ermittele die Masen der Client Area invoke SetDlgToolArea,hDlg,addr ti,addr MainDialogText1,id,addr rect


Wir initialisieren die Elemente der TOOLINFO Struktur. Beachten Sie, dass wir die Client Area in 4 Teile teilen wollen, weshalb wir die Ausmasen der Client Area kennen müssen. Deshalb rufen wir GetWindowRect auf. Wir wollen von uns aus keine Maus-Nachrichten auf die Tooltip Stuerelemente legen, weshalb wir das TIF_SUBCLASS Flag angeben.
SetDlgToolArea ist eine Funktion, die die angrenzenden Rechtecke jedes Tools berechnet und das Tool dem zugehörigen Tooltip Steuerelement registriert. Ich gehe nicht in Details über die Berechnung ein, sie teilt die Client Area einfach in 4 Teile mit jeweils gleicher Größe. Dann sendet sie eine TTM_ADDTOOL Nachricht an das Tooltip Steuerelement und übergibt im lParam Parameter die Adresse der TOOLINFO Struktur.
invoke SendMessage,hwndTool,TTM_ADDTOOL,NULL,lpti


Nachdem alle 4 Tools registriert sind, können wir mit den Buttons in der Dialog Box weiter machen. Wir können jeden einzelnen Button über seine ID händeln. Aber das ist mühsam. Stattdessen werden wir den EnumChildWindows API Aufruf benutzen, um alle Steuerelement in der Dialog Box aufzuzählen und sie dann zu dem Tooltip Steuerelement zu registrieren. EnumChildWindows hat folgende Syntax:
EnumChildWindows proto hWnd:DWORD, lpEnumFunc:DWORD, lParam:DWORD


hWnd ist das Handle des Eltern-Fensters. lpEnumFunc ist die Adresse der EnumChildProc Funktion, die für jedes aufgezählte Element aufgerufen wird. lParam ist der Applikationsdefinierte Wert, der der EnumChildProc Funktion übergeben wird. Die EnumChildProc Funktion hat folgende Definition:
EnumChildProc proto hwndChild:DWORD, lParam:DWORD


hwndChild ist das Handle eines Steuerelement, das mit EnumChildWindows aufgezählt wurde. lParam ist der selbe lParam Wert, den Sie EnumChildWindows übergeben.
In unserem Beispiel rufen wir EnumChildWindows wie folgt auf:
invoke EnumChildWindows,hDlg,addr EnumChild,addr ti


Wir übergeben die Adresse der TOOLINFO Struktur im lParam Parameter, da wir jedes Child-Steuerelement des Tooltip Steuerelementes mit der EnumChild Funktion registrieren. Wenn wir diese Methode nicht benutzen, müssen wir ti als eine globale Variable deklarieren, was fehleranfällig sein kann.
Wenn wir EnumChildWindows aufrufen, wird Windows die Steuerelemente in unserer Dialog Box durchzählen und die EnumChild Funktion einmal für aufgezählten aufrufen. So dass, wenn die Dialog Box zwei Steuerelemente hat, EnumChild zweimal aufgerufen wird.
Die EnumChild Funktion füllt die relevanten Elemente der TOOLINFO Struktur und registriert dann das Tool mit dem Tooltip Steuerelement.
EnumChild proc uses edi hwndChild:DWORD,lParam:DWORD LOCAL buffer[256]:BYTE mov edi,lParam assume edi:ptr TOOLINFO push hwndChild pop [edi].uId ; we use the whole client area of the control as the tool or [edi].uFlags,TTF_IDISHWND invoke GetWindowText,hwndChild,addr buffer,255 lea eax,buffer ; use the window text as the tooltip text mov [edi].lpszText,eax invoke SendMessage,hwndTool,TTM_ADDTOOL,NULL,edi assume edi:nothing ret EnumChild endp


Beachten Sie, dass wir in diesem Fall ein anderes Tool benutzen: eins dass die gesamte Client Area des Fensters abdeckt. Deshalb müssen wir das uID Feld mit dem Handle des Fensters, dass das Tool enthält, füllen. Wir müssen auch das TTF_IDISHWND Flag im uFlags Element angeben.

Deutsche Übersetzung: Joachim Rohde
Die original Win32Asm-Tutorials stammen von Iczelion's Win32 Assembly HomePage