Jump to content

Bug In Tooltip - And Fix


Valik
 Share

Recommended Posts

Jon, CyberSlug sent me this message the other day:

When I show a tooltip at the current mouse position and when the mouse is near the bottom of the screen, the tooltip jumps to the very top of the screen!  (This problem does not exist when the mouse is near the right edge of the screen.)

HotKeySet("{Esc}", "Terminate")
Func Terminate()
   Exit
EndFunc

While 1
   sleep(100)
   $p = MouseGetPos()
   Tooltip( '(' & $p[0] & ',' & $p[1] & ')' )
  ;;;Tooltip( '(' & $p[0] & ',' & $p[1] & ')' , $p[0], $p[1]);try this, too
Wend

This jump occurs when  heightOfDetsktop  -  mouseYcoord  <  tooltipHeight.

Could you change this behavior?

I've found the problem and fixed it. The code is below:

See Below
Edited by Valik
Link to comment
Share on other sites

Valik, I just tried Jon's "ultra unstable" build which includes this fix.

The tooltip still does not work quite right.... The tooltip in the example still jumps when my mouse is at the very bottom of the screen.

Did you account for the following offsets?

pt.x += 16;
   pt.y += 16;

I guess my original equation was incorrect and should be something like:

Tooltip jumps if heightOfDetsktop - mouseYcoord - 16 < tooltipHeight

Use Mozilla | Take a look at My Disorganized AutoIt stuff | Very very old: AutoBuilder 11 Jan 2005 prototype I need to update my sig!
Link to comment
Share on other sites

Okay, here is an attempt to keep the Tooltip inside the Desktop. Note that this will likely break any potential support for showing a tooltip on any screen except the primary screen (In the case of 2 displays), however, I'm unable to test it so it could still work. I don't know exactly how Window's treats multiple monitors, so it could still work.

Jon, this change undoes the code I posted above and also moves one of the SendMessage() calls as I don't think it needs called every time.

Windows itself seems to properly handle the top and left parts of the screen, so no code is necessary to keep those regions in bounds.

See Below
Edited by Valik
Link to comment
Share on other sites

  • 2 weeks later...

Jon, I see in the latest unstable still has this bug. The code in my above post actually fixes the bug (Unlike the original code I posted). Just thought I'd give you a little reminder :D

Link to comment
Share on other sites

I hate how this board uses a cookie with a timestamp or however it does it to determine read posts. Some forums will retain unread posts between sessions until you actually read the post. I hope they implement that feature soon.

Link to comment
Share on other sites

  • 2 weeks later...

The fixed code above does not work on my XP system when the tooltip is first displayed. It only works if the tip already exists. I think this is caused by a quirk in Windows, namely the fact that the GetWindowRect for the tooltip itself fails to retrieve the correct height of the window unless you do a TTM_TRACKPOSITION and a TTM_TRACKACTIVATE beforehand.

The following revisions make it work on XP for me (not sure about other OSes):

if (!m_hWndTip)

{

....

// Must do these next two when the window is first created, otherwise GetWindowRect() below will retrieve

// a tooltip window size that is quite a bit taller than it winds up being:

SendMessage (m_hWndTip , TTM_TRACKPOSITION, 0, (LPARAM)MAKELONG(pt.x, pt.y));

SendMessage (m_hWndTip , TTM_TRACKACTIVATE, true, (LPARAM)&ti);

}

Link to comment
Share on other sites

Is it necessary to call TTM_TRACKACTIVATE, too? I see what you are saying and I would think just TTM_TRACKPOSITION would be enough. I would expect calling both will cause the tooltip to flash a bit.

Anyway, leave it to Microsoft to have something that should be simple become a complicated affair.

Link to comment
Share on other sites

Okay, this question is for any and all who care to have an opinion on the matter. I'm getting tired of this Tooltip crap. I like how it wraps itself to stay on the screen, but that's apparently bugged to, and I don't like having to do all the calculations. There is a very simple alternative. It's called:

TTF_ABSOLUTE

Version 4.70. Positions the ToolTip window at the same coordinates provided by TTM_TRACKPOSITION

This does not wrap the tooltip or cause it to warp to some odd place. Simply put, the tooltip appears where you tell it to, even if you tell it to appear 2000 pixels off the screen. This can cause tooltips to appear off the screen or to run off the screen.

Does anybody have a preference for which behavior they would like to see?

Link to comment
Share on other sites

The following code also seems helpful. I was having trouble with the tooltip window obscuring the tray area, and also with the tooltip window growing taller on its own whenever the mouse cursor is left inside it during an update (not sure what causes that last part).

(up with the ttw section)
    int tt_width = ttw.right - ttw.left;
    int tt_height = ttw.bottom - ttw.top;
......
if (one_or_both_coords_unspecified)
{
    // Since Tooltip is being shown at the cursor's coordinates, try to ensure that the above
    // adjustment doesn't result in the cursor being inside the tooltip's window boundaries,
    // since that tends to cause problems such as blocking the tray area (which can make a
    // tootip script impossible to terminate).  Normally, that can only happen in this case
    // (one_or_both_coords_unspecified == true) when the cursor is near the buttom-right
    // corner of the screen (unless the mouse is moving more quickly than the script's
    // tool-tip update-frequency can cope with, but that seems inconsequential since it
    // will adjust when the cursor slows down):
    ttw.left = pt.x;
    ttw.top = pt.y;
    ttw.right = ttw.left + tt_width;
    ttw.bottom = ttw.top + tt_height;
    if (pt_cursor.x >= ttw.left && pt_cursor.x <= ttw.right && pt_cursor.y >= ttw.top && pt_cursor.y <= ttw.bottom)
    {
        // Push the tool tip to the upper-left side, since normally the only way the cursor can
        // be inside its boundaries (when one_or_both_coords_unspecified == true) is when the
        // cursor is near the bottom right corner of the screen.
        pt.x = pt_cursor.x - tt_width - 3;    // Use a small offset since it can't overlap the cursor
        pt.y = pt_cursor.y - tt_height - 3;   // when pushed to the the upper-left side of it.
    }
}
Edited by cmallett
Link to comment
Share on other sites

I'm no developer, but on Windows98SE, when I use the following code with the latest unstable release (15-Jun-2004), I get unexpected results.

ToolTip("Test string... AAAAAAAAAAAAAAAAAAAAA", 400, 500)
Sleep(1500)
ToolTip("Test string... AAAAAAAAAAAAAAAAAAAAA", 400, 500)
Sleep(1500)

The first tooltip displays at the wrong location, but the second one displays at the correct location... just FYI. :D

Kendall

Link to comment
Share on other sites

  • Administrators

Okay, this question is for any and all who care to have an opinion on the matter.  I'm getting tired of this Tooltip crap.  I like how it wraps itself to stay on the screen, but that's apparently bugged to, and I don't like having to do all the calculations.  There is a very simple alternative.  It's called:

This does not wrap the tooltip or cause it to warp to some odd place.  Simply put, the tooltip appears where you tell it to, even if you tell it to appear 2000 pixels off the screen.  This can cause tooltips to appear off the screen or to run off the screen.

Does anybody have a preference for which behavior they would like to see?

Sounds OK to me.
Link to comment
Share on other sites

Here's the new (And hopefully final) fix. This uses TTF_ABSOLUTE so Windows no longer does any handling of the tooltip position. It will no longer wrap or warp when hitting a screen boundary, it will just appear offscreen if that is where the coordinates are.

AUT_RESULT AutoIt_Script::F_ToolTip(VectorVariant &vParams, Variant &vResult)
{
  uint iNumParam = vParams.size();

// MingW missing some include defines
#ifndef TTF_TRACK
  #define TTF_TRACK 0x0020
  #define TTF_ABSOLUTE 0x0080
  #define TTM_SETMAXTIPWIDTH (WM_USER+24)
  #define TTM_TRACKPOSITION (WM_USER+18)
  #define TTM_TRACKACTIVATE (WM_USER+17)
#endif

  TOOLINFO ti;
  POINT  pt;

  ti.cbSize = sizeof(ti);
  ti.uFlags = TTF_TRACK | TTF_ABSOLUTE;
  ti.hwnd  = NULL;
  ti.hinst = NULL;
  ti.uId  = 0;
  ti.lpszText = (LPSTR)vParams[0].szValue();  
  ti.rect.left = ti.rect.top = ti.rect.right = ti.rect.bottom = 0;

  // Set default values for the tip as the current mouse position
  GetCursorPos(&pt);
  pt.x += 16;
  pt.y += 16;

  if (iNumParam >= 2)
      pt.x = vParams[1].nValue();
  if (iNumParam >= 3)
      pt.y = vParams[2].nValue();

  if (!m_hWndTip)
  {
      m_hWndTip = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL, TTS_NOPREFIX | TTS_ALWAYSTIP,
      CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL);

   RECT dtw;
   GetWindowRect(GetDesktopWindow(), &dtw);

      SendMessage (m_hWndTip , TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO)&ti);
      SendMessage(m_hWndTip, TTM_SETMAXTIPWIDTH, 0, (LPARAM)dtw.right);
  }
  else
      SendMessage(m_hWndTip, TTM_UPDATETIPTEXT, 0, (LPARAM)&ti);

  SendMessage (m_hWndTip , TTM_TRACKPOSITION, 0, (LPARAM)MAKELONG(pt.x, pt.y));
  SendMessage (m_hWndTip , TTM_TRACKACTIVATE, true, (LPARAM)&ti);

  return AUT_OK;

} // ToolTip()

I tested with the below script and it seemed to work as I meant:

ToolTip("Test1", 2000, 2000)
TrayTip("Tooltip offscreen", "Tooltip offscreen", 5, 16)
HotKeySet("!x", "Quit")
Sleep(2000)
While 1
    $pos = MouseGetPos()
    ToolTip("x:" & $pos[0] & @CRLF & "y:" & $pos[1])
Wend
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...