Re: ToolTips in a View and TTN_NEEDTEXT
From: Bill Thompson (billt61_at_rgv.rr.com)
Date: 11/19/04
- Next message: Mihajlo Cvetanovic: "Re: How can I access the worker thread data ?"
- Previous message: Mihajlo Cvetanovic: "Re: How can I access the worker thread data ?"
- In reply to: Rick Lee: "ToolTips in a View and TTN_NEEDTEXT"
- Next in thread: Rick Lee: "Re: ToolTips in a View and TTN_NEEDTEXT"
- Reply: Rick Lee: "Re: ToolTips in a View and TTN_NEEDTEXT"
- Messages sorted by: [ date ] [ thread ]
Date: Fri, 19 Nov 2004 10:36:30 -0600
"Rick Lee" <Rick@Custom-Made-SoftwareNOSPAM.com> wrote in message
news:419DA3E0.3F98810B@Custom-Made-SoftwareNOSPAM.com...
> I have been trying to reuse code for ToolTips in a View ("Data Tips")
> that I found in the
> April 97 issue of MSJ:
> http://www.microsoft.com/msj/0497/tooltip/tooltip.aspx
>
> Most of the required functions and portions of functions --
> OnMouseMove(), OnInitialUpdate(),
> PreTranslateMessage() HitTest() -- are called correctly. But for some
> reason the TTN_NEEDTEXT
> message appears never to be sent because OnToolTipNeedText() is never
> called.
>
> Note that the only value of pMsg->message that is relayed to the ToolTip
> is 512, and I have
> no idea if that's right. But it does seem to be the case in the Sample
> Project I downloaded.
> (Click tooltips.exe at the top of the article for the self-extracting
> archive. The Data Tips
> is in the DTTest directory.)
>
> Thanks,
> Rick Lee
>
[code snipped]
This class works for me. You derive your dialog based classes off of
CToolTipDialog instead of CDialog, and 'voilez' your dialog has tooltips.
NOTES:
1) Derive CToolTipDialog from CDialog (or whatever other base Dialog class
you wish to use) instead of CResizeDialog
2) Derive dialogs that you want tool tips from this class.
3) A context menu has been included that allows you to set the
tooltip from your program at run time. You have to either
create a context menu resource with the resource ID
IDR_TOOLTIP_MENU and a menu item to set the tooltip
with ID IDR_SET_TOOLTIP, or delete the OnContextMenu
code
4) This code uses a 'tooltip manager'. Since it's a database application,
I store all toolips in a database. You may have another way to
store your tooltips. Here's a (slightly revised) tooltip manager class:
5) You might want to associate resource ID's with the Dialog/Control ID's
instead of strings.
#ifndef TOOLTIPMANAGER_H
#define TOOLTIPMANAGER_H
class CToolTipManager
{
public:
CToolTipManager();
~CToolTipManager();
void Fini();
// gets the tool tip associated with a given dialog/control
void GetToolTipText(int DialogID, int ControlID, CString &ToolTip);
// associates a tool tip with a given dialog/control
bool SetToolTipText(int DialogID, int ControlID, CString &ToolTip);
// invokes a dialog that let's the user add a tooltip
void InvokeDialog(int DialogID, int ControlID);
private:
// you will want some member, such as a CMap type class
// to associate tooltip text with dialog/controls here
};
////////////////////////////////////////////////////////////////
//***** Following is the tooltip dialog class:
////////////////////////////////////////////////////////////////
#if
!defined(AFX_TOOLTIPDIALOG_H__4FCE09A3_FBF1_4FB1_BAE6_1B1549FC88EE__INCLUDED
_)
#define AFX_TOOLTIPDIALOG_H__4FCE09A3_FBF1_4FB1_BAE6_1B1549FC88EE__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// ToolTipDialog.h : header file
//
////////////////////////////////////////////////////////////////////////////
/
// CToolTipDialog dialog
// NOTE: replace CResizeDialog with CDialog,
// or whatever base dialog class you are using.
class CToolTipDialog : public CResizeDialog
{
DECLARE_DYNAMIC(CToolTipDialog)
// Construction
public:
CToolTipDialog(UINT nIDD, LPCTSTR DialogTitle, bool UseScrollbars =
false, CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CToolTipDialog)
// NOTE: the ClassWizard will add data members here
//}}AFX_DATA
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CToolTipDialog)
public:
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
LPCTSTR GetToolTipText(int ControlID);
void GetToolTipControlFromPoint(CPoint point, int &ControlID, HWND
&hWndChild) const;
void OnSetToolTip();
UINT m_nIDD;
// stores the point from which the context menu was invoked
CPoint m_PopupPoint;
// Generated message map functions
//{{AFX_MSG(CToolTipDialog)
virtual BOOL OnInitDialog();
afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
//}}AFX_MSG
BOOL OnToolTipNotify(UINT id, NMHDR *pNMH, LRESULT *pResult);
virtual int OnToolHitTest( CPoint point, TOOLINFO* pTI ) const;
DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately
before the previous line.
#endif //
!defined(AFX_TOOLTIPDIALOG_H__4FCE09A3_FBF1_4FB1_BAE6_1B1549FC88EE__INCLUDED
_)
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// ToolTipDialog.cpp : implementation file
//
#include "stdafx.h"
#include "NewTrader.h"
#include "ToolTipDialog.h"
#include "ToolTipManager.h"
#include "Afx_OldToolInfo.h" // for OnToolHitTest
extern CToolTipManager TheToolTipManager;
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// NOTE: again, you might want to replace all instances of CResizeDialog
// with CDialog
IMPLEMENT_DYNAMIC(CToolTipDialog, CResizeDialog)
////////////////////////////////////////////////////////////////////////////
/
// CToolTipDialog dialog
CToolTipDialog::CToolTipDialog(UINT nIDD, LPCTSTR DialogTitle, bool
UseScrollbars, CWnd* pParent)
: CResizeDialog(nIDD, DialogTitle, UseScrollbars, pParent)
{
//{{AFX_DATA_INIT(CToolTipDialog)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
m_nIDD = nIDD;
}
void CToolTipDialog::DoDataExchange(CDataExchange* pDX)
{
CResizeDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CToolTipDialog)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CToolTipDialog, CResizeDialog)
//{{AFX_MSG_MAP(CToolTipDialog)
ON_WM_CONTEXTMENU()
ON_COMMAND(IDR_SET_TOOLTIP, OnSetToolTip)
//}}AFX_MSG_MAP
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXT, 0, 0xFFFF, OnToolTipNotify)
END_MESSAGE_MAP()
////////////////////////////////////////////////////////////////////////////
/////
// get the tool tip associated with a given control id
LPCTSTR CToolTipDialog::GetToolTipText(int ControlID)
{
LPCTSTR RetVal = "";
CWnd* pWndChild = GetWindow(GW_CHILD);
int counter = 0;
while (pWndChild != NULL)
{
int TestControlID = pWndChild->GetDlgCtrlID();
if (ControlID == TestControlID)
{
static TCHAR MyBuf[256];
CString ToolTipText;
TheToolTipManager.GetToolTipText(m_nIDD, ControlID,
ToolTipText);
_tcscpy(MyBuf, ToolTipText);
RetVal = MyBuf;
}
pWndChild = pWndChild->GetWindow(GW_HWNDNEXT);
}
return RetVal;
}
////////////////////////////////////////////////////////////////////////////
//
// override the default OnToolHitTest
// the code was copied from the MFC Source code.
// the reason?
// so tool tips follow the cursor rather than the bottom of the control
int CToolTipDialog::OnToolHitTest(CPoint point, TOOLINFO* pTI) const
{
int nHit = -1;
if (pTI != NULL && pTI->cbSize >= sizeof(AFX_OLDTOOLINFO))
{
// find child window which hits the point
// (don't use WindowFromPoint, because it ignores disabled
windows)
HWND hWndChild = ::ChildWindowFromPoint(m_hWnd, point);
if (hWndChild != NULL)
{
// back to the original code
// return positive hit if control ID isn't -1
nHit = ::GetDlgCtrlID(hWndChild);
if (nHit != 0)
{
// setup the TOOLINFO structure
pTI->hwnd = m_hWnd;
pTI->uId = (UINT)hWndChild;
pTI->uFlags |= TTF_IDISHWND;
pTI->lpszText = LPSTR_TEXTCALLBACK;
}
}
}
return nHit;
}
////////////////////////////////////////////////////////////////////////////
/////
// handle tool tip notification messages
BOOL CToolTipDialog::OnToolTipNotify(UINT id, NMHDR *pNMH, LRESULT *pResult)
{
BOOL RetVal = FALSE;
if (pNMH)
{
TOOLTIPTEXT *pText = (TOOLTIPTEXT *) pNMH;
int ControlID = ::GetDlgCtrlID((HWND) pNMH->idFrom);
if (ControlID)
{
pText->lpszText = (LPTSTR) GetToolTipText(ControlID);
pText->hinst = AfxGetInstanceHandle();
RetVal = TRUE;
}
}
return RetVal;
}
////////////////////////////////////////////////////////////////////////////
/////
////////////////////////////////////////////////////////////////////////////
/////
void CToolTipDialog::GetToolTipControlFromPoint(CPoint point, int
&ControlID, HWND &hWndChild) const
{
ControlID = -1;
// find child window which hits the point
// (don't use WindowFromPoint, because it ignores disabled windows)
hWndChild = ::ChildWindowFromPoint(m_hWnd, point);
if (hWndChild != NULL)
{
ControlID = ::GetDlgCtrlID(hWndChild);
}
}
////////////////////////////////////////////////////////////////////////////
/
// CToolTipDialog message handlers
////////////////////////////////////////////////////////////////////////////
/
////////////////////////////////////////////////////////////////////////////
/
BOOL CToolTipDialog::OnInitDialog()
{
EnableToolTips(TRUE);
CResizeDialog::OnInitDialog();
return TRUE;
}
////////////////////////////////////////////////////////////////////////////
/
////////////////////////////////////////////////////////////////////////////
/
void CToolTipDialog::OnContextMenu(CWnd* /*pWnd*/, CPoint point)
{
m_PopupPoint = point;
ScreenToClient(&m_PopupPoint);
// make sure window is active
GetParentFrame()->ActivateFrame();
CMenu menu;
if (menu.LoadMenu(IDR_TOOLTIP_MENU))
{
CMenu* pPopup = menu.GetSubMenu(0);
ASSERT(pPopup != NULL);
// check for admin mode later
bool ToolTipsEnabled = true;
pPopup->EnableMenuItem(IDR_SET_TOOLTIP, ToolTipsEnabled ? MF_ENABLED
: MF_GRAYED);
pPopup->TrackPopupMenu(TPM_RIGHTBUTTON | TPM_LEFTALIGN,
point.x, point.y, this); // route commands
through this window
}
}
////////////////////////////////////////////////////////////////////////////
/
////////////////////////////////////////////////////////////////////////////
/
void CToolTipDialog::OnSetToolTip()
{
int ControlID;
HWND hWndChild;
GetToolTipControlFromPoint(m_PopupPoint, ControlID, hWndChild);
if (ControlID != -1)
{
TheToolTipManager.InvokeDialog(m_nIDD, ControlID);
}
}
- Next message: Mihajlo Cvetanovic: "Re: How can I access the worker thread data ?"
- Previous message: Mihajlo Cvetanovic: "Re: How can I access the worker thread data ?"
- In reply to: Rick Lee: "ToolTips in a View and TTN_NEEDTEXT"
- Next in thread: Rick Lee: "Re: ToolTips in a View and TTN_NEEDTEXT"
- Reply: Rick Lee: "Re: ToolTips in a View and TTN_NEEDTEXT"
- Messages sorted by: [ date ] [ thread ]