ToolTip for a button - no MFC please

I am trying to get tooltip text to show up for a button with id IDC_HOME.  The button is on a dialog window created with the call CreateDialogParam().  In the function addHomeToolTip(), the SendMessage() call returns 0 (meaning failure).  Why? and how do I get this to work?  No MFC please.  Here is some pertinent code:

// In the main() function:

     HWND hMainDlg = CreateDialog (hInstance, szAppName, 0, NULL) ;

     HWND hButtonBar = CreateDialogParam(hInstance, "BUTTON_BAR_DLG", hMainDlg, (DLGPROC)ButtonBarDlgProc, 0) ;
// NOTE:  IDC_HOME is a button created via the resource editor on the dialog hButtonBar.  It shows up fine.

// Just before the message loop:
int ret = addHomeToolTip();  // always returns 0!  WHY?

// ... end main()


// BUG: Can't get this function to work!!!
// returns 1 if successful, 0 if failed.
int addHomeToolTip() {
       RECT  homeRect;
       GetClientRect(GetDlgItem(hButtonBar, IDC_HOME), &homeRect);

       TOOLINFO  ti;
       ti.cbSize = sizeof(TOOLINFO);
       ti.hwnd = hButtonBar;
       //ti.uFlags = TTF_IDISHWND;
       //ti.uId = (UINT)GetDlgItem(hButtonBar, IDC_HOME);
       //ti.rect

       ti.uFlags = TTF_CENTERTIP;
       ti.uId = IDC_HOME;
       ti.rect = homeRect;
       ti.hinst = hInstance;
       ti.lpszText = LPSTR_TEXTCALLBACK;
       ti.lParam = 0;

       return SendMessage(hButtonBar, TTM_ADDTOOL, 0, (LPARAM)(LPTOOLINFO) &ti);   // returns 0!  Why?
}


// In ButtonBarDlgProc:
switch (iMsg)
{

// The following code is never called because addHomeToolTip() fails.
case WM_NOTIFY: {  // respond to tooltip request
 LPTOOLTIPTEXT  TTtext = (LPTOOLTIPTEXT) lParam;
 if (TTtext->hdr.code == TTN_NEEDTEXT) {
       switch(TTtext->hdr.idFrom) {
       case IDC_HOME:
             TTtext->lpszText = "Tooltip text!";
             break;
       }
 }
}

// ... end ButtonBarDlgProc


Thanks for any help with this.
stanrAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Paul SinnemaCommented:
Hi,

In 1995 I've written the following code for a tooltip in our programs. You may need to create some defines for 'SBWORD' and 'VOID' but is should work alright.

Paul.

/*
     ********   ********
    **          **     **
    **          **     **
     ********   ********
            **  **     **
            **  **     **   Software 1995 ( c )
     ********   ********

*/

/*      Doel            :      Tool tip window on current mouse position.

      Datum            :      april 1995.

      Auteur            :      P.R.Sinnema.
*/

#include      <standard.h>
#include      <winglob.h>
#include      <widgets.h>

#pragma      hdrstop

#include      "syslib.h"

static      DLGPROC            lpPop      = 0L;
static      HWND            hWindow      = 0;

static      SBBYTE            szToolTipClass[] = "SBToolTip";

static      SBBYTE            szCurrentText[100] = "";

static      HFONT            hFont = 0;

BOOL      CALLBACK      EXPORT      SBToolTipProc (      HWND      hWnd,
                                                                  UINT      wMsg,
                                                                  WPARAM      wParam,
                                                                  LPARAM      lParam )

{
      switch ( wMsg )
      {      case      WM_CREATE:
            {   TEXTMETRIC      tm;
                  LOGFONT            lf;
                  HFONT            oldFont;
                  POINT            point;
                  SBLONG            size,
                                    len;
                  HDC                  hdc = GetDC ( hWnd );

                  GetCursorPos ( &point );

                  size = strlen ( szCurrentText );

                  memset(&lf, 0, sizeof(LOGFONT));

                  lf.lfHeight             = -MulDiv ( 8, GetDeviceCaps(hdc, LOGPIXELSY), 72 );
                  lf.lfCharSet            = ANSI_CHARSET;
                  lf.lfQuality            = DEFAULT_QUALITY;
                  lf.lfClipPrecision      = CLIP_LH_ANGLES | CLIP_STROKE_PRECIS;
                  lf.lfPitchAndFamily      = FF_SWISS;

                  hFont      = CreateFontIndirect( &lf );

                  oldFont = SelectObject ( hdc, hFont );

                  len = GetTextExtent ( hdc, szCurrentText, (SBWORD)size );

                  GetTextMetrics ( hdc, &tm );

                  SetWindowPos (      hWnd, HWND_TOP,
                                          point.x,
                                          point.y + 20,
                                          (SBWORD)len + 6,
                                          tm.tmHeight + 4,
                                          SWP_SHOWWINDOW|SWP_NOACTIVATE );

                  SelectObject ( hdc, oldFont );

                  ReleaseDC ( hWnd, hdc );

                  return ( FALSE );
            }

            case      WM_MOUSEMOVE:
            {      DestroyWindow ( hWnd );

                  hWindow = 0;

                  return ( FALSE );
            }

            case      WM_PAINT:
            {      HDC                  hdc;
                  PAINTSTRUCT      p;

                  if ( ( hdc = BeginPaint ( hWnd, &p ) ) != 0 )
                  {   SBLONG      size;
                        HFONT      oldFont;
   
                        oldFont = SelectObject ( hdc, hFont );
                        size       = strlen ( szCurrentText );

                        MoveTo            ( hdc, 0, 0 );
                        SetBkMode      ( hdc, TRANSPARENT );

                        TextOut ( hdc, 1, 1, szCurrentText, (SBWORD)size );

                        SelectObject ( hdc, oldFont );

                        EndPaint ( hWnd, &p );

                        return ( FALSE );
                  }

                  return ( FALSE );
            }

            case      WM_DESTROY:
            {      if ( hFont )
                        DeleteObject ( hFont );

                  break;
            }
      }

      return ( (BOOL)DefWindowProc ( hWnd, wMsg, wParam, lParam ) );
}

VOID      EXPORT      SBToolTip ( HWND hParent, SBBYTE *sbp_string, SBWORD sbp_sw )

{
      switch ( sbp_sw )
      {      case      SBT_INIT:
            {   if ( ! sbp_string )
                        break;

                  if ( strcmp ( szCurrentText, sbp_string ) != 0 )
                  {   if ( hWindow )
                        {      DestroyWindow ( hWindow );
                              hWindow = 0;
                        }

                        if ( lpPop )
                        {      FreeProcInstance ( lpPop );

                              UnregisterClass ( szToolTipClass, hInst );

                              lpPop      = NULL;
                        }
                  }

                  strncpy ( szCurrentText, sbp_string, 99 );

                  szCurrentText[99] = 0;

                  if ( ! hWindow )
                  {   WNDCLASS            wc;

                        if ( ! lpPop )
                              if ( ( lpPop = MakeProcInstance (      SBToolTipProc,
                                                                                    hInst ) ) == 0L )
                                    break;

                        wc.style                   = CS_BYTEALIGNCLIENT | CS_SAVEBITS |
                                                        CS_HREDRAW | CS_VREDRAW;
                        wc.hInstance            = hInst;
                        wc.lpfnWndProc            = (WNDPROC)lpPop;
                        wc.cbClsExtra            = 0;
                        wc.cbWndExtra            = 0;
                        wc.hIcon                  = NULL;
                        wc.hCursor                  = NULL;
                        wc.hbrBackground      = (HBRUSH) CreateSolidBrush(RGB(255,255,112));
                        wc.lpszMenuName            = NULL;
                        wc.lpszClassName      = szToolTipClass;

                        RegisterClass ( &wc );
                  /*      {      FreeProcInstance ( lpPop );
                              lpPop = 0L;
                              break;
                        }      */

                        if ( ( hWindow = CreateWindowEx(      0,
                                                                              szToolTipClass,
                                                                              "",
                                                                              WS_POPUP | WS_BORDER,
                                                                              0, 0, 0, 0,
                                                                              hParent,
                                                                              (HMENU)NULL,
                                                                              hInst,
                                                                              NULL ) ) == 0 )
                        {      FreeProcInstance ( lpPop );
                              lpPop = 0L;
                              UnregisterClass ( szToolTipClass, hInst );
                              hWindow = 0L;
                              break;
                        }
                  }

                  break;
            }

            case      SBT_EXIT:
            {   if ( hWindow )
                  {      DestroyWindow ( hWindow );

                        hWindow = 0;
                  }

                  if ( lpPop )
                  {      FreeProcInstance ( lpPop );

                        UnregisterClass ( szToolTipClass, hInst );

                        lpPop      = 0L;
                  }

                  break;
            }
      }
}
0
stanrAuthor Commented:
Thank you very much for the code Paul!  This looks like it would work with some added code to check that the mouse was reasonably stationary over the button before displaying the tooltip.  

I hate to reject the answer, but I really wanted to know why the code I wrote above did not work (and how to fix it).  Am I using the TTM_ADDTOOL message incorrectly or is there some other basic flaw?  If noone is able to answer this then I will give the points to you later.

Thanks.

0
stanrAuthor Commented:
Paul,

Evidentally the TTM_ADDTOOL won't work with user created dialogs (it will work with CreateToolbarEx(), but I want to create my own window) - even with the SBT_TOOLTIPS style - I tried many things but couldn't get it to work.  So I implemented your solution and it works great!   Thanks again.  I don't know how to get you your points unless you lock the question again.  If you do, I will accept your answer.

Thanks!
0
Paul SinnemaCommented:
Alright,

Glad it works.

Paul.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft Development

From novice to tech pro — start learning today.