• Advertisement

Archived

This topic is now archived and is closed to further replies.

Tooltips and toolbars in MFC, or: why my life sucks right now.

This topic is 5000 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I''m working on a relatively complex little app that has 3 splitter windows. The window on the far right has a toolbar in the edge of its frame that I do border negotiations to accomodate the viewing of. The window on the far right is a fram with 6 views that take turns being shown, maximized. Although I can get command messages from the toolbar docked at the right edge of the frame, I can''t get the text down at the bottom or the tooltip to show for the toolbar. The parent window is a CFrameWnd derivative so it should do it natively. I already tried overriding TTN_NEEDTEXT notification everywhere I can think of... it never gets called at all. Has anyone else had problems with getting tooltips to show in toolbars that are docked to subframes in splitter windows, or is it just me? Also, my mainframe toolbar will show the tooltips for the 3 report views I have, but not for the graphical views when they''re the current active windows on the right. I''ve tried notification overrides there too, no luck. I''m starting to wonder if it isn''t that the graphical views have a timer and that might interfere with the OnIdle while a graphical is the active view, but that really shouldn''t be the case. I''m baffled. Suggestions? -fel

Share this post


Link to post
Share on other sites
Advertisement
umm, I speak for everybody here when I say, huh? Are you speaking english?

Share this post


Link to post
Share on other sites
quote:
Original post by WORF
umm, I speak for everybody here when I say, huh? Are you speaking english?


No, you don''t speak for everybody. felisandria is perfectly comprehensible; I just happen to have not tried that particular situation with MFC before (speaking for myself).

Share this post


Link to post
Share on other sites
Sorry Fel.
I can't help either. Haven't even come close to this situation.
------------------------------------------
Edit. I gave a search through our product, and there was a reference to TTN_NEEDTEXT:

ON_NOTIFY(TTN_NEEDTEXT, 0, OnGetTooltipText)

But it sounds like you already had this.

Here is the function:

void CMapView::OnGetTooltipText(NMHDR* pNMHDR, LRESULT *plRes)

// See C++ Q&A by Paul DiLascia, MSJ, March 1997 pp. 109 - 112.

{
TOOLTIPTEXT& ttt = *((TOOLTIPTEXT *) pNMHDR);

const CPoint pt(pNMHDR->idFrom);

strncpy(ttt.szText, GetSymbolName(pt), sizeof(ttt.szText));
}


Edited by - Gorky on September 26, 2001 10:40:01 AM

Share this post


Link to post
Share on other sites
I liberally sprinkled TTN_NEEDTEXT handlers throughout every view and frame that this toolbar gets anywhere near, and none of them get hit, at all *sigh*

I don''t know where it''s routing, or even IF it''s routing. Command messages work fine, tooltip notification is apparently nonexistent.

-fel

Share this post


Link to post
Share on other sites
I may have a slight bit of insight, something I found out last night working on my little board game. "Message routing" and "Command routing" are two different things. Only the WM_COMMAND messages get sent through the whole chain--from the view to the frame to the doc to the app or whatever the whole order is. All other messages look like they''re only sent to their target window. Since the tooltip stuff is latched onto WM_NOTIFY, not WM_COMMAND, I don''t think it''s routed anywhere.

I''m about 50% sure this doesn''t apply to the problem at hand, but just thought I''d throw it up in case it does. Best I can do right now.

Share this post


Link to post
Share on other sites
I''m not sure this will help but here''s a win32 code I wrote for a button with a tool tip. Tooltips are in string resource file.

  
// Common controls sent this message

case WM_NOTIFY:
switch(((LPNMHDR)lParam)->code)
{
// Main toolbar wants tooltip string info

case TTN_GETDISPINFO:
g_FrameWnd.DisplayToolbarTooltips(lParam);
break;
}
}
break;

void CToolbar::DisplayTooltips(LPARAM lParam)
{
/*
// LOAD TOOLTIP STRINGS FROM STRINGTABLE
*/

((LPNMTTDISPINFO)lParam)->hinst = GetModuleHandle(NULL);
((LPNMTTDISPINFO)lParam)->uFlags = TTF_DI_SETITEM;

// Retain the string info and don''t ask for it again


switch(((LPNMHDR)lParam)->idFrom)
{
case CMDID_FILENEW:
((LPNMTTDISPINFO)lParam)->lpszText = MAKEINTRESOURCE(IDS_NEW);
break;
}

Share this post


Link to post
Share on other sites
Well, I''m aware that NOTIFY is supposed to be restricted to the parent window but I''m not picking it up there.

I know I can write my own into a derived CToolBar class, but... I wince at the thought. *sigh*

-fel

Share this post


Link to post
Share on other sites
On a related note, has anyone ever managed to get tooltips to work for any control other than a bog standard label? (in a normal window, not toolbars) I dont seem to able to do this, despite spending weeks playing about, manually subclassing the controls etc. Nothing seems to work.

The controls I am particularly interested in getting tooltips working for are checkboxes and slider bars. I am not using MFC either, just bog standard common or garden Win32.

Any suggestions?


Edited by - Sandman on September 27, 2001 11:37:18 AM

Share this post


Link to post
Share on other sites
Sandman, if you want to use tool tips for standard windows without MFC, here is some code:

    

//***************************************************************
// Function: CreateMyToolTip
//
// Creates a new tooltip window with the string passed by the
// user
//***************************************************************

void CreateMyTooltip (HWND hwnd,char* string){

// struct specifying info about tool in tooltip control
TOOLINFO ti; // struct containing toolbar info
unsigned int uid = 0; // for ti initialization
RECT rect; // for client area coordinates

/* CREATE A TOOLTIP WINDOW */
hwndTT = CreateWindowEx(WS_EX_TOPMOST, // topmost window
TOOLTIPS_CLASS, // common dialog style tooltip
NULL, // no title bar
WS_POPUP| // popup window
TTS_NOPREFIX| // prevents ampersand stripping
TTS_ALWAYSTIP, // allows tip from inactive window
CW_USEDEFAULT, // generic left position
CW_USEDEFAULT, // generic top position
CW_USEDEFAULT, // generic width
CW_USEDEFAULT, // generic height
hwnd, // the parent window
NULL, // no menu
hInst, // window handle
NULL); // no extra parameters

SetWindowPos(hwndTT, // the window handle
HWND_TOPMOST, // window order
0, // client area x position
0, // client area y position
0, // window width
0, // window height
SWP_NOMOVE| // the window retains its current pos
SWP_NOSIZE| // the window retains its current size
SWP_NOACTIVATE); // the window is inactive

// get the client rectangle
GetClientRect(hwnd,&rect);

/* INITIALIZE MEMBERS OF THE TOOLINFO STRUCTURE */
ti.cbSize = sizeof(TOOLINFO); // structure size
ti.uFlags = TTF_SUBCLASS; // intercepts toolbar messages
ti.hwnd = hwnd; // window handle
ti.hinst = hInst; // window instance
ti.uId = uid; // application identifier
ti.lpszText = string; // tool tip string
// Tooltip control will cover the whole window
ti.rect.left = rect.left; // left position
ti.rect.top = rect.top; // top position
ti.rect.right = rect.right; // width
ti.rect.bottom = rect.bottom; // height

/* SEND AN ADDTOOL MESSAGE TO THE TOOLTIP CONTROL WINDOW */

SendMessage(hwndTT,TTM_ADDTOOL,0,(LPARAM) (LPTOOLINFO) &ti);
// The tooltip is delayed for 25 secs. Hopefully this is long enough

SendMessage(hwndTT,TTM_SETDELAYTIME,TTDT_AUTOPOP,25000);
// Sets a maximum width for the tool tip window

SendMessage(hwndTT,TTM_SETMAXTIPWIDTH,0,300);
}

//lots of more code

//when you want to call the tooltip

// close the tooltip window if active

SendMessage(hwndTT,WM_CLOSE,0,0);
// if the tooltip string isn't empty, create a new tooltip

if(strcmp(string,"")!=0)
CreateMyTooltip(hWnd,string);


Edited by - Nytegard on September 28, 2001 11:59:16 AM

Share this post


Link to post
Share on other sites
Hmmm... something I can actually answer. If you still need it here''s some stuff that uses MFC from a project I worked on. It''s a little abridged though.

  
/////////////////////////////////////////////////////////////////////////

//ToolTip.h


class CMyToolTipCtrl : public CToolTipCtrl
{
public:

BOOL m_bCreated;
BOOL AddWindowTool (CWnd*, LPCTSTR);
BOOL AddRectTool (CWnd*, LPCTSTR, LPCRECT, UINT);
};



/////////////////////////////////////////////////////////////////////////

//ToolTip.Cpp


#include "tooltip.h"

BOOL CMyToolTipCtrl::AddWindowTool (CWnd* pWnd, LPCTSTR pszText)
{
TOOLINFO ti;
ti.cbSize = sizeof (TOOLINFO);
ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
ti.hwnd = pWnd->GetParent ()->GetSafeHwnd ();
ti.uId = (UINT) pWnd->GetSafeHwnd ();
ti.hinst = AfxGetInstanceHandle ();
ti.lpszText = (LPTSTR) pszText;

return (BOOL) SendMessage (TTM_ADDTOOL, 0, (LPARAM) &ti);
}

BOOL CMyToolTipCtrl::AddRectTool (CWnd* pWnd, LPCTSTR pszText,
LPCRECT lpRect, UINT nIDTool)
{
TOOLINFO ti;
ti.cbSize = sizeof (TOOLINFO);
ti.uFlags = TTF_SUBCLASS;
ti.hwnd = pWnd->GetSafeHwnd ();
ti.uId = nIDTool;
ti.hinst = AfxGetInstanceHandle ();
ti.lpszText = (LPTSTR) pszText;
::CopyRect (&ti.rect, lpRect);

return (BOOL) SendMessage (TTM_ADDTOOL, 0, (LPARAM) &ti);
}



////////////////////////////////////////////////////////////////////////////////////

//SomeClass.h


#include "tooltip.h"

class CSomeClass : public CDialog
{
CMyToolTipCtrl m_ctlTT;
void SetTooltips();
};

////////////////////////////////////////////////////////////////////////////////////

//SomeClass.cpp


#include "SomeClass.h"
void CSomeClass::SetTooltips()
{
m_ctlTT.Create (this);

m_ctlTT.AddWindowTool (GetDlgItem (IDC_TAGNAME),
MAKEINTRESOURCE (IDS_REQUIRED));
m_ctlTT.AddWindowTool (GetDlgItem (IDC_TAGDESC),
MAKEINTRESOURCE (IDS_NOT_REQUIRED));
m_ctlTT.AddWindowTool (GetDlgItem (IDC_FLUIDLIST),
MAKEINTRESOURCE (IDS_REQUIRED));
m_ctlTT.AddWindowTool (GetDlgItem (IDC_EDITFLUIDNAME),
MAKEINTRESOURCE (IDS_REQUIRED));
}


Share this post


Link to post
Share on other sites
NyteGard:

Thanks, but I have tried all that stuff. I am using multiline tooltips, and they work fine with labels, but with controls other than labels or the parent window itself, the WM_NOTIFY messages containing TTN_GETDISPINFO do not seem to get sent to the parent window. Neither the TTF_SUBCLASS nor manual subclassing seems to help....

Share this post


Link to post
Share on other sites
Sandman, the code I wrote isn''t designed to use WM_NOTIFY. The code I borrowed from actually calls the tooltip from a window subleveled 4 layers.

What it does is create a new subwindow from the parent window (just pass the subwindow handle to be the parent window). You can call it anywhere, and it will work (I might have stripped out a few keylines, but a little modification should make it work fine).

This weekend if you''re interested, I''ll write a little demo with it built in on any control you want tooltips on.

Share this post


Link to post
Share on other sites
Nytegard: Unfortunately I NEED to get the WM_NOTIFY in order to use the multiline tooltips....

Share this post


Link to post
Share on other sites
The code posted will handle multiline tooltips.

To get something like:

(begin tooltip)
first line
second line
third line
(end tooltip)

just pass it the string

"first line\r\nsecond line\r\nthird line"

Share this post


Link to post
Share on other sites
OK, on which type of control or window do you want a multiline tooltip to appear? I don''t have time today, but I can write a very basic example sometime this weekend.

Share this post


Link to post
Share on other sites
OK. I am using property sheets, and the control I want the tooltip to appear on is a checkbox control.

Currently all mouseover messages seem to get absorbed by the control itself, and no WM_NOTIFY messages are sent to the parent window, and nothing seems to reach the tooltip window either, despite use of the TTF_SUBCLASS flag.

Share this post


Link to post
Share on other sites
OK, a simple, pure Win32 (absolutely no MFC) example demonstrating tooltips on the main window, a child dialog, a check box, and a button is up. Source code and an executable.

Just click go to my main homepage, and go to the download section. If anyone is interested in any other Win32 code examples, just ask.

My homepage at school.

Share this post


Link to post
Share on other sites
AARRRGGH

These &*("ing tooltips do my head in. Now the checkboxes and buttons work, but the labels dont. Presumably something to do with labels forwarding all messages to the parent window.....

Thanks anyway, I should be able to get this working now.... If I can just figure out how to fix this problem cleanly.

Share this post


Link to post
Share on other sites
I had a problem similar to Felisandria''s one. My TTN_NEEDTEXT handler in CFrameWnd-derived class was not called after mouse cursor had been moved upon a toolbar button.

The solution was to write
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, YourHandlerName)
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, YourHandlerName)
instead of
ON_NOTIFY_EX(TTN_NEEDTEXT, 0, YourHandlerName)
in CFrameWnd-derived class'' message map.

Share this post


Link to post
Share on other sites

  • Advertisement