4

I have a problem, I hope you can help me out. Already out of my research luck... tried stackoverflow, google, even yahoo...

How can I force a tooltip to come out NOT using the mouse?

I am currently implementing some windows automatization and need to force the tooltips to appear.

Like this. Usually you have to hold your mouse over that bar for like 1 - 2 seconds.

I want to force these tooltips to appear using the WINAPI or something similar.

Somethink like "SendMessage/Postmessage(hwnd, "WM_COMEOUTTOOLTIP", 0, lParam (with x and y Position)".

Does something like this exist in WINAPI? Have googled crazy but found nothing.

Thanks guys for your help!

Jonathan

JonathanSchmied
  • 137
  • 1
  • 7

3 Answers3

6

This SO Answer mentions that you can use the TTM_POPUP message to bring up a tooltip, using TTM_TRACKPOSITION to set the position of the tooltip.

EDIT: I got a bit curious about this and tried to make a working sample:

a) include common controls in the manifest or use the following line in the source

#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

b) create and set up the tooltip window

hWndtoolTip = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, 0, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT, hWndParent, 0, hInstance, 0);
SetWindowPos(hWndtoolTip, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);

TOOLINFO ti = {};
ti.cbSize = sizeof(TOOLINFO);
ti.uFlags = TTF_SUBCLASS;
ti.hwnd   = hWndParent;
ti.hinst  = hInstance;
ti.uId    = (UINT)hWndtoolTip;
ti.lpszText = L"tool-tip";
GetClientRect(hWndParent, &ti.rect);
SendMessage(hWndtoolTip, TTM_ADDTOOL, 0, (LPARAM)&ti);

c) to show the tooltip at a specific postion (say, x=300, y=300):

SetCursorPos(300, 300);
SendMessage(hWndtoolTip, TTM_POPUP, 0, 0);
Community
  • 1
  • 1
Edward Clements
  • 5,040
  • 2
  • 21
  • 27
  • First of all, thanks for the reply. Really got some insight here. I also tried a couple of things using the piece of code you provided. However, the ToolTips are not(!) created by me. Thus, I cannot get a grip on the hwnds of the tooltips (they are not visible at runtime), which I need to run the piece of code u provided: SendMessage(hwnd, TTM_POPUP,0,0), hwnd is unknown??!! You have an idea on this? Thanks! – JonathanSchmied Mar 30 '14 at 21:02
  • `hwnd` I the handle of the window which invokes the tooltip, maybe you could use Spy to look at the window messages when the application is running "normally" and the tooltip is displayed? – Edward Clements Mar 31 '14 at 07:24
  • great! thanks... I tried your method and modified it a bit. now it works perfectly! this programm starts the tooltip as a own window... so was able to get the hwnd out of it. – JonathanSchmied Apr 14 '14 at 10:00
  • This is a hack. If I want my cursor position to be independent of the tooltip this won't do. But good try. Can't believe microsoft created such a dumb control. Even subclassing the control fails as tooltip does vital code in WM_TIMER. which means returning 0 from WM_TIMER will cause undefined behaviour, such as the tooltip being drawn with no text, no background color, no shape. – user13947194 May 17 '22 at 05:08
2

Maybe this is what you are looking for?

And since tooltips are created with the CreateWindowEx function, can't you just use ShowWindow?

Eejin
  • 770
  • 1
  • 8
  • 29
  • nope. ShowWindow doesn't show tooltips. Note that WM_SHOWWINDOW can be implemented to prevent this default behaviour. You can however, subclass the tooltip and override WM_SHOWWINDOW. – user13947194 May 17 '22 at 04:31
  • According to MSDN; tool tip implements WM_TIMER, not WM_SHOWWINDOW. If mouse is not inside the tool, then WM_TIMER will hide the tool. – user13947194 May 17 '22 at 04:45
0

Hallelujah. I know how to manually display a tooltip!!! We do this by using tracking tooltips. But there is one trick/ pitfall.

Create tooltip

HWND createToolTip(HWND owner)
{
 INITCOMMONCONTROLSEX ic{ sizeof(ic), ICC_WIN95_CLASSES };
 InitCommonControlsEx(&ic);

 HWND tip = CreateWindowExA(
               WS_EX_TOPMOST|ex_style, //MSDN states that WS_EX_TOOLWINDOW is always apart of ToolTip style
               TOOLTIPS_CLASSA,
               NULL,
               style, // MSDN states that WS_POPUP is always apart of ToolTip style
               CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
               owner,
               NULL,
               (HINSTANCE)0x400000,
               NULL
           );

 //SetWindowPos(tip,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
 return tip;
}

Create and add Tracking Tool. Note that the tooltip itself is not tracking. It is the tool that is a tracking tool. Thus you can have multiple tools that are tracking and non-tracking registered for the same tool tip.

TOOLINFOA createTrackingTool(HWND owner,HWND tool)
{
    TOOLINFOA info = {};
    info.cbSize   = sizeof(info);
    info.uFlags   = TTF_IDISHWND | //dictates that TOOLINFO::uId is Window Handle of tool
                    TTF_TRACK |    //dictates that this is a tracking tool
                    TTF_ABSOLUTE;  //Required for TTF_TRACK, ass tracking tools use absolute co-ords; Don't ask why.
                                   //TTF_SUBCLASS is not needed for our case.
                                   //  but I think using TTF_SUBCLASS with TTF_TRACK can cause
                                   //  tooltip to automatically popup and balloon arrow pointing
                                   //  to a point we specify
    info.hwnd     = owner;
    info.uId      = (UINT_PTR)tool;

    return info;
}

TOOLINFOA createTrackingTool(HWND owner,uint id,const RECT &toolRect)
{
    TOOLINFOA info = {};
    info.cbSize   = sizeof(info);
    info.uFlags   = TTF_TRACK | TTF_ABSOLUTE;
    info.hwnd     = owner;
    info.uId      = id; // owner and id uniquely identifies a tool
    info.rect     = toolRect;

    return info;
}

void addTool(HWND toolTip,const TOOLINFOA &info)
{
 SendMessage(toolTip, TTM_ADDTOOL, 0, (LPARAM)&info);
}

Manipulate tool tip

void setText(HWND toolTip,TOOLINFOA &info,const char *text)
{
 info.lpszText = text;
 SendMessage(toolTip, TTM_SETTOOLINFO, 0, (LPARAM)&info);
}


void setPos(HWND toolTip,HWND relHwnd,int x,int y)
{
 SendMessage(widget,TTM_TRACKACTIVATE,true,(LPARAM)&info);

 POINT pt = {x,y};
 ClientToScreen(relHwnd,&pt);
 SendMessage(widget,TTM_TRACKPOSITION,0,MAKELPARAM(pt.x,pt.y));
}

void redraw(HWND toolTip)
{
 RedrawWindow(toolTip,NULL,NULL,RDW_INVALIDATE);
}

Put Every together

LRESULT CALLBACK proc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
{
    if(msg == WM_CREATE)
    {
        HWND tip = createToolTip(mainWindow);
        TOOLINFOA info = createTrackingTool(mainWindow,button);
        addTool(tip,info);
        
        // By causing the tooltip to draw itself now, it will be overdrawn
        // by this window once WM_CREATE is finished.
        // By redrawing the tooltip later you can see that the tooltip 
        // was really activated at this point.
        setText(tip,info,"MyText");
        setPos(tip,hwnd,20,20);
        
        return 0;
    }
    if(msg == WM_SHOWWINDOW)
    {
        redraw(tip); //Cause the tool tip to redraw so it is visible on screen
        return 0;
    }
    if(msg == WM_KEYDOWN)
    {
        // You can draw the tooltip now and not have to worry about this window 
        // drawing over the tooltip.
        setText(tip,info,"Time to activate track tooltip");
        setPos(tip,hwnd,20,20); 
    }
    
    return DefWindowProc(hwnd,msg,wparam,lparam);
}
user13947194
  • 337
  • 5
  • 7