Click here to Skip to main content
15,892,575 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I use the following code for adding tooltip to selected window region (RECT):

C++
INITCOMMONCONTROLSEX icc;
InitCommonControlsEx(&icc);
icc.dwSize = sizeof(INITCOMMONCONTROLSEX);
icc.dwICC = ICC_BAR_CLASSES;

HWND tooltip_hwnd = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, "MyTooltip", WS_POPUP | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, hwnd, NULL, (HINSTANCE)GetModuleHandle(NULL), NULL);

SetWindowPos(tooltip_hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |WP_NOACTIVATE);

SendMessage(tooltip_hwnd, TTM_SETMAXTIPWIDTH, 0, 200);
SendMessage(tooltip_hwnd, TTM_SETDELAYTIME, TTDT_AUTOPOP, 15000);
SendMessage(tooltip_hwnd, TTM_SETDELAYTIME, TTDT_RESHOW, 10);

TOOLINFO ti = {0};
ti.cbSize = sizeof(TOOLINFO);
ti.uFlags = TTF_SUBCLASS;
ti.hwnd = hwnd;
ti.hinst = (HINSTANCE)GetModuleHandle(NULL);
ti.uId = 1;
ti.lpszText = "tooltip_text";
ti.rect.left = 10;
ti.rect.top = 10;
ti.rect.right = 100;
ti.rect.bottom = 80;
SendMessage(tooltip_hwnd, TTM_ADDTOOL, 0, (LPARAM)(LPTOOLINFO)&ti);


OK. And problem is in here: when the mouse cursor appears above the selected rect, then tooltip window quickly shows, then hides and then shows again. Where is mistake in this code? And how to fix this bug?
Posted
Comments
enhzflep 2-Oct-14 0:48am    
Which OS, and where do you have the above code? Is it in the WM_CREATE handler, or elsewhere?
I tried your code and experienced only normal tool-tip behaviour. (with win7 and in the WM_CREATE handler)
Igor-84 2-Oct-14 1:16am    
I use Windows7. Yes, it is in WM_CREATE handler. In all other programs tooltips behave normally, except my program.

1 solution

The following works just fine for me.

Things I've changed:
1. Moved initcommoncontrols to before any windows are created
2. changed WP_NOACTIVATE --> SWP_NOACTIVATE
3. Set the size of the tip to CW_USEDEFAULT,CW_USEDEFAULT (you forgot to specify this)
4. added a define for _WIN32_IE and included commctrl.h

The code below does not display the artefacts that you describe, not sure what's wrong in your case.

main.cpp
C++
#define _WIN32_IE 0x0300    // for INITCOMMONCONTROLSEX struct

#if defined(UNICODE) && !defined(_UNICODE)
    #define _UNICODE
#elif defined(_UNICODE) && !defined(UNICODE)
    #define UNICODE
#endif

#include <tchar.h>
#include <windows.h>
#include <commctrl.h>       // for INITCOMMONCONTROLSEX struct

/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/*  Make the class name into a global variable  */
TCHAR szClassName[ ] = _T("CodeBlocksWindowsApp");

int WINAPI WinMain (HINSTANCE hThisInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpszArgument,
                     int nCmdShow)
{
    HWND hwnd;               /* This is the handle for our window */
    MSG messages;            /* Here messages to the application are saved */
    WNDCLASSEX wincl;        /* Data structure for the windowclass */

    /* The Window structure */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
    wincl.cbSize = sizeof (WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 /* No menu */
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default colour as the background of the window */
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    /* Register the window class, and if it fails quit the program */
    if (!RegisterClassEx (&wincl))
        return 0;

    INITCOMMONCONTROLSEX icc;
    InitCommonControlsEx(&icc);
    icc.dwSize = sizeof(INITCOMMONCONTROLSEX);
    icc.dwICC = ICC_BAR_CLASSES;

    /* The class is registered, let's create the program*/
    hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           szClassName,         /* Classname */
           _T("Code::Blocks Template Windows App"),       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           544,                 /* The programs width */
           375,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           hThisInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );

    /* Make the window visible on the screen */
    ShowWindow (hwnd, nCmdShow);

    /* Run the message loop. It will run until GetMessage() returns 0 */
    while (GetMessage (&messages, NULL, 0, 0))
    {
        /* Translate virtual-key messages into character messages */
        TranslateMessage(&messages);
        /* Send message to WindowProcedure */
        DispatchMessage(&messages);
    }

    /* The program return-value is 0 - The value that PostQuitMessage() gave */
    return messages.wParam;
}


/*  This function is called by the Windows function DispatchMessage()  */

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)                  /* handle the messages */
    {
        case WM_CREATE:
        {
            HWND tooltip_hwnd = CreateWindowEx(WS_EX_TOPMOST,
                                               TOOLTIPS_CLASS,
                                               "MyTooltip",
                                               WS_POPUP | TTS_ALWAYSTIP,
                                               CW_USEDEFAULT, CW_USEDEFAULT,
                                               CW_USEDEFAULT, CW_USEDEFAULT,
                                               hwnd, NULL, (HINSTANCE)GetModuleHandle(NULL), NULL);

            SetWindowPos(tooltip_hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |SWP_NOACTIVATE);

            SendMessage(tooltip_hwnd, TTM_SETMAXTIPWIDTH, 0, 200);
            SendMessage(tooltip_hwnd, TTM_SETDELAYTIME, TTDT_AUTOPOP, 15000);
            SendMessage(tooltip_hwnd, TTM_SETDELAYTIME, TTDT_RESHOW, 10);

            TOOLINFO ti = {0};
            ti.cbSize = sizeof(TOOLINFO);
            ti.uFlags = TTF_SUBCLASS;
            ti.hwnd = hwnd;
            ti.hinst = (HINSTANCE)GetModuleHandle(NULL);
            ti.uId = 1;
            ti.lpszText = "tooltip_text";
            ti.rect.left = 10;
            ti.rect.top = 10;
            ti.rect.right = 100;
            ti.rect.bottom = 80;
            SendMessage(tooltip_hwnd, TTM_ADDTOOL, 0, (LPARAM)(LPTOOLINFO)&ti);
        }
        return 0;

        case WM_DESTROY:
            PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
            break;
        default:                      /* for messages that we don't deal with */
            return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}
 
Share this answer
 
Comments
Igor-84 2-Oct-14 2:03am    
I made ​​changes to my code. But nothing has changed. See: broken tooltip
enhzflep 2-Oct-14 2:09am    
I see you've got a red rectangle there. How/where is this drawn? Is this a control, or is it just something you draw in the WM_PAINT or WM_ERASEBKG handlers?

Perhaps, providing a fully compilable, minimal example would help. :)
Igor-84 2-Oct-14 2:24am    
Red rectangle it is simple color filled rectangle region.
case WM_PAINT:
{
HBRUSH brush = CreateSolidBrush(RGB(220, 0, 0));
RECT b = {11, 26, 89, 143};
FillRect(GetDC(hwnd), &b, brush);
DeleteObject(brush);
}
break;
But even if I do not draw a rectangle, tooltip does not change its behavior.
I compile this code under C++Builder XE5. If it helps, here is project: http://www.datafilehost.com/d/ff47a0b1
enhzflep 2-Oct-14 2:32am    
Ahhhh! Your WM_PAINT handler is broken.
Inside it, you need to have the region validated.You can mess about with that manually (not recommended), or you can do it with the accepted method, using BeginPaint and EndPaint - the EndPaint call takes care of validation.

Try this alternate handler:

case WM_PAINT:
{
HDC hdc;
PAINTSTRUCT ps;
RECT b= {11,26,89,143};
HBRUSH brush = CreateSolidBrush( RGB(220,0,0) );

hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &b, brush);
DeleteObject(brush);
EndPaint(hwnd, &ps);
}


I'm a little busy and will take a look at your code in an hour or two if this doesn't solve the problem. :)
Igor-84 2-Oct-14 2:48am    
Unfortunately this did not solve the problem. Waiting for help.
P.S. Try quickly to enter the cursor to the red rectangle, and you should see it.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900