Tool tip for subclassed CButton

Hi there,

I have subclassed CButton and want to have a tooltip on it.

I have previously got tooltips working for several controls in a CWnd, controlled by the CWnd, but I want this CButton to have all the code for its own tooltips, not its parent window.  I have tried transplanting the code that worked for the CWnd, but using this instead of the controls in AddTool, ie:

in MyButton::OnCreate:
      EnableToolTips(TRUE);
      m_tooltip.Create(this, TTS_NOPREFIX| TTS_ALWAYSTIP);
      m_tooltip.Activate(TRUE);
      m_tooltip.AddTool(this, _T("text"));

I've overloaded PreTranslateMessage to have m_tooltip.RelayEvent(pMsg);

This isn't working.  I don't know whether I'm going about this right but making a mistake somewhere, or whether I need a completely different approach. What should I be doing?

Thank you





wilsonianAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
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.

DanRollinsCommented:
One normally handles the tooltips in the parent.  There is some good code here:

     http:/MFC/Q_10037333.html

And it is covered nicely in MDSN.

-- Dan
0
DanRollinsCommented:
It is also possible to do it in the button itself, but the technique description differs depending upon how you are creating the button.  If you place a breakpoint in your OnCreate fn, does it get executed?

-- Dan
0
wilsonianAuthor Commented:
Heh, you'd think I'd check something like that.  No, OnCreate is not getting called. What function should the tooltip code live in, or do I have to write one that I call explicitly?

The buttons are member variables of a couple of different types of CWnd (CDialog and CPropertyPage at the moment)

I don't want to handle the tooltips in the parent because the buttons appear in different contexts and it would save doing it more than once, also the tool tips really are part of the functionality of the button itself (they're not serving the normal purpose of tool tips).
0
Introduction to Web Design

Develop a strong foundation and understanding of web design by learning HTML, CSS, and additional tools to help you develop your own website.

DanRollinsCommented:
Heres' the header:
#pragma once

/////////////////////////////////////////////////////////////////////////////
// CMyButton window

class CMyButton : public CButton
{
// Construction
public:
      CMyButton();
      virtual ~CMyButton();

      BOOL PreTranslateMessage(MSG* pMsg);

      CString m_sTipText;
      void SetTipText( LPCSTR sz ) { m_sTipText= sz; };

      CToolTipCtrl m_tooltip;

      // ClassWizard generated virtual function overrides
      //{{AFX_VIRTUAL(CMyButton)
      protected:
      virtual void PreSubclassWindow();
      //}}AFX_VIRTUAL


      // Generated message map functions
protected:
      //{{AFX_MSG(CMyButton)
      //}}AFX_MSG

      DECLARE_MESSAGE_MAP()
};
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
here's the CPP file:

// MyButton.cpp : implementation file
//
#include "stdafx.h"
#include "MyButton.h"

CMyButton::CMyButton() { }
CMyButton::~CMyButton() { }

BEGIN_MESSAGE_MAP(CMyButton, CButton)
      //{{AFX_MSG_MAP(CMyButton)
      //}}AFX_MSG_MAP
END_MESSAGE_MAP()

void CMyButton::PreSubclassWindow()
{
      CButton::PreSubclassWindow();
      if (m_sTipText > "" ) {
            EnableToolTips( TRUE );
            m_tooltip.Create(this, TTS_NOPREFIX| TTS_ALWAYSTIP );
            m_tooltip.AddTool(this, (LPCSTR)m_sTipText );
            m_tooltip.Activate(TRUE);
      }
}
//-------------------------------------------------------------
BOOL CMyButton::PreTranslateMessage(MSG* pMsg)
{
      switch(pMsg->message) {
            case WM_LBUTTONDOWN:
            case WM_LBUTTONUP:
            case WM_MOUSEMOVE:
                  if ( m_tooltip.m_hWnd ) {
                        m_tooltip.RelayEvent(pMsg);
                  }
            break;
      }
      return CButton::PreTranslateMessage(pMsg);
}
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
here's an example impementation (partial):

void CD18Dlg::DoDataExchange(CDataExchange* pDX)
{
      CDialog::DoDataExchange(pDX);
      //{{AFX_DATA_MAP(CD18Dlg)
      DDX_Control(pDX, IDPB_MyButton, m_ctlMyButton);
      //}}AFX_DATA_MAP
}

.... etc...

BOOL CD18Dlg::OnInitDialog()
{
      m_ctlMyButton.SetTipText("this is the tip text");

      CDialog::OnInitDialog();

.... etc...

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
You could use other method to set the tip text... my implementation is not dynamic, but this should get you going.

It seems to boil down to
   provide a CToolTip member for the CButton-derived object
   Create the tooltip in PreSubclassWindow
   Handle PreTranslateMessage and use .RelayEvent on certain msgs

-- Dan
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
wilsonianAuthor Commented:
I now get an assert failure in the following line:

      m_tooltip.Create(this, TTS_NOPREFIX| TTS_ALWAYSTIP);

in AfxHookWindowCreate.  It's on line 627 and says:

ASSERT(pThreadState->m_hHookOldCbtFilter != NULL);

Any idea what's going on here?
0
DanRollinsCommented:
Myabe it's something you are doing in your OnCreate fn.  I did not use one.

-- Dan
0
wilsonianAuthor Commented:
I deleted OnCreate when I put the PreSubclassWindow function in, so that can't be it.
0
DanRollinsCommented:
I'm pretty certain that that ASSERT indicates that some window is being created while another window is still in the process of being created.  Does that narrow it down?  

I assure you that the code I posted does work in a minimal AppWizard-generated Dialog-based program.

-- Dan
0
DanRollinsCommented:
Be sure to call
   m_tooltip.Create( this, ...
when the 'this' pointer identifies a CWnd-derived object that has already been created (that is, its m_hWnd member is valid).

-- Dan
0
wilsonianAuthor Commented:
Sorry, my email was playing up and I didn't get your message.

I'll check it out on Friday when I'm next at work.
0
wilsonianAuthor Commented:
It's still not working, but I'm sure it's some weird unrelated thing I'm doing.  I'm awarding you the points.
0
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
System Programming

From novice to tech pro — start learning today.