Solved

Tool tip for subclassed CButton

Posted on 2003-10-23
11
1,813 Views
Last Modified: 2013-11-20
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





0
Comment
Question by:wilsonian
  • 6
  • 5
11 Comments
 
LVL 49

Expert Comment

by:DanRollins
ID: 9611078
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
 
LVL 49

Expert Comment

by:DanRollins
ID: 9611092
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
 

Author Comment

by:wilsonian
ID: 9611165
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
 
LVL 49

Accepted Solution

by:
DanRollins earned 125 total points
ID: 9611429
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
 

Author Comment

by:wilsonian
ID: 9611761
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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 49

Expert Comment

by:DanRollins
ID: 9611798
Myabe it's something you are doing in your OnCreate fn.  I did not use one.

-- Dan
0
 

Author Comment

by:wilsonian
ID: 9611853
I deleted OnCreate when I put the PreSubclassWindow function in, so that can't be it.
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 9611938
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
 
LVL 49

Expert Comment

by:DanRollins
ID: 9618294
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
 

Author Comment

by:wilsonian
ID: 9636964
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
 

Author Comment

by:wilsonian
ID: 9661533
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

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Introduction: Displaying information on the statusbar.   Continuing from the third article about sudoku.   Open the project in visual studio. Status bar – let’s display the timestamp there.  We need to get the timestamp from the document s…
Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now