Tooltip (bzw. QuickInfo) bei disabelten Controls



  • Hi Leutz,

    habe ein Dialog, im dem u.a. 8 Radio-Buttons enthalten sind.
    Für jedes dieser Radio-Buttons habe ich ein Tool zum Tooltip hinzugefügt (über TTM_ADDTOOL).
    Jedes Tool habe ich als mehrzeiligen (multiline) Text ausgelegt (über WM_NOTIFY mit TTN_GETDISPINFO).

    In der ganzen Applikation habe ich ein einziges Tooltip-Window definiert, d.h. auch die Tools z.B. für die Statusbar-Felder des Hauptfensters verwenden diesen gemeinsamen Tootlip.
    Der Tooltip funtkioniert soweit wunderbar.

    ABER nur solange die Radio-Buttons nicht disabled (ausgegraut) sind!
    Nach dem Googeln muß ich feststellen ich für diesen speziellen Fall selbst dafür sorgen muß, daß der Tooltip die Mausinformationen bekommt.
    Und zwar über TTM_RELAYEVENT.
    Bis jetzt habe ich es nicht geschafft, daß ein Tooltip über ein disabled Control erscheint.

    Hier meine Code Snippets (stark vereinfacht, sämtliche Fehlerabfragen der Übersicht halber entfernt):

    Fensterprozedur für Hauptfenster mit hwnd_window_frame:

    LRESULT CALLBACK Proc_Window_Frame( HWND hwnd_frame, //Handle-Nr. des Fensters.
                                        UINT message,    //Message Identifier.
                                        WPARAM wParam,   //Erster Message Parameter.
                                        LPARAM lParam )  //Zweiter Message Parameter.
    {
      switch ( message )
      {
        case WM_CREATE:
        hwnd_window_tooltip = CreateWindowEx( WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
                                              CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                                              hwnd_frame, (HMENU)NULL, hinstance_app, NULL );
                                                         //Tooltip als Popupfenster generieren.
                                                         //Der Stil TTS_NOPREFIX muß gesetzt sein, sonst wird bei
                                                         //Vorkommen eines "&"-Zeichens im Tooltip-Text automatisch
                                                         //auf 80 Zeichen begrenzt!
        SetWindowPos( hwnd_window_tooltip, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE );
        SendMessage( hwnd_window_tooltip, TTM_SETDELAYTIME, (WPARAM)TTDT_AUTOMATIC, (LPARAM)MAKELONG( -1, 0 ) );
        break;
    
        case WM_NOTIFY:
        switch ( ( (LPNMHDR)lParam )->code )
        {
          case TTN_GETDISPINFO:
          //lpnmtdi = (LPNMTTDISPINFO)lParam; //Address of an NMTTDISPINFO structure.
          if( GetDlgCtrlID( (HWND)( (LPNMTTDISPINFO)lParam->hdr.idFrom ) ) == HWND des Controls)
          {
            (LPNMTTDISPINFO)lParam->lpszText = "Zeile1 \r\nZeile2 \r\nZeile3";
                                                         //Neuen Tooltip-Text übergeben. Die Variable muß static oder global
                                                         //Typ oder dynamisch reserviert worden sein, da lokale Variablen
                                                         //nach der Rückker der Nachricht ihre Gültigkeit verlieren.
                                                         //The tooltip control allocates a buffer and copies the text into this new buffer.
                                                         //Siehe KB180646: Howto display more than 80 characters in a ToolTip control.
            SendMessage( hwnd_window_tooltip, TTM_SETMAXTIPWIDTH, (WPARAM)0, (LPARAM)400 );
                                                         //We want to display multiline Tooltip.
          }
          break;
        }
        break;
      }
    }
    

    Hier die Dialogprozedur (WM_INITDIALOG usw. bereits entfernt):

    BOOL CALLBACK Proc_Dialog( HWND hwnd_dialog,         //Handle-Nr. des Dialogs (ist eigentlich ein Fenster).
                               UINT message,             //Message Identifier.
                               WPARAM wParam,            //Erster Message Parameter.
                               LPARAM lParam )           //Zweiter Message Parameter.
    {
    uint32 ui32_idx;
    HWND hwnd_return;
    HWND hwnd_disabledcontrol;
    POINT struct_point_cursor;
    TOOLINFO struct_toolinfo;
    
    switch ( message )
    {
      case WM_INITDIALOG:
      //Tools für Tooltip anlegen.
      ui32_idx = 0;
      do
      {
        struct_toolinfo.cbSize = sizeof( TOOLINFO );
        struct_toolinfo.uFlags = TTF_SUBCLASS | TTF_IDISHWND;
                                                         //Bei TTF_IDISHWND wird an Member 'uId' der HWND des
                                                         //Controls übergeben, Member 'rect' wird ignoriert.
        struct_toolinfo.hwnd = hwnd_window_frame;        //Notifikationen werden an Proc_Window_Frame() gesendet.
        struct_toolinfo.hinst = NULL;
        struct_toolinfo.uId = (UINT_PTR)GetDlgItem( hwnd_dialog, IDC_RADIOBUTTON_1 + ui32_idx );
                                                         //HWND des jeweiligen Controls eintragen.
        struct_toolinfo.lpReserved = NULL;
        struct_toolinfo.lpszText = LPSTR_TEXTCALLBACK;
        SendMessage( hwnd_window_tooltip, TTM_ADDTOOL, (WPARAM)0, (LPARAM)(LPTOOLINFO)&struct_toolinfo );
                                                         //Tool für Tooltip registrieren.
      } while ( ++ui32_idx < 8 );                        //Alle 8 Tools fertig?
      SendMessage( hwnd_window_tooltip, TTM_SETDELAYTIME, (WPARAM)TTDT_AUTOPOP, (LPARAM)MAKELONG( 15000, 0 ) );
                                                         //15s Anzeigedauer.
      break;
    
      case WM_MOUSEMOVE:
      //Der Mauszeiger wurde bewegt.
      struct_point_cursor.x = LOWORD(lParam);
      struct_point_cursor.y = HIWORD(lParam);
      hwnd_return = ChildWindowFromPoint( hwnd_dialog, struct_point_cursor );
      if ( ( hwnd_return != NULL )
           && ( hwnd_return != hwnd_dialog ) )
      {
        hwnd_disabledcontrol = GetDlgItem( hwnd_dialog, IDC_RADIOBUTTON_1 );
                                                         //Dieser Radio-Button ist disabled.
        if ( hwnd_return == hwnd_disabledcontrol )
        {
          //Neue Message wird so zusammengestellt, als ob sie vom Radio-Button käme.
          struct_message.hwnd = hwnd_disabledcontrol;
          struct_message.lParam = lParam;
          struct_message.message = WM_MOUSEMOVE;
          struct_message.pt.x = LOWORD( GetMessagePos() );
          struct_message.pt.y = HIWORD( GetMessagePos() );
          struct_message.time = GetMessageTime();
          struct_message.wParam = wParam;
          SendMessage( hwnd_window_tooltip, TTM_RELAYEVENT, (WPARAM)0, (LPARAM)&struct_message );
                                                         //Message an Tooltip-Window senden.
        }
      }
    }
    }
    

    Ich habe sicherlich irgendwas grundsätzliches übersehen, doch ich komme selber nicht drauf 😕
    Die Nachricht mit TTM_RELAYEVENT soll an hwnd_window_tooltip übermittelt werden, oder nicht? Habe ich vielleicht das Konzept falsch verstanden?
    Deshalb bitte ich um Eure Mithilfe.

    Martin


Anmelden zum Antworten