Balloon tooltip at specified X/Y window position?

Just starting out? Need help? Post your questions and find answers here.
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Balloon tooltip at specified X/Y window position?

Post by Dude »

Hi all, I've seen lots of balloon tooltip examples in these forums but they're all for gadgets. What I'd like to do, is have a balloon tooltip appear at an X/Y window position of my choice, to point the tip of the balloon at something. In a specific case, I want it to point at the window title like below.

Image

Here's some code I found on these forums to show a balloon tip, but I'm not sure how I'd flip the Y axis (when needed) and make it point at the title bar, or how to position it at a given X/Y position (there's no X/Y flags in the TOOLINFO structure). Any tips? Thanks.

Code: Select all

Procedure MyBalloonToolTips(btWindow.l, btGadget.l, btText.s)
  ToolTipControl = CreateWindowEx_(0, "ToolTips_Class32", "", #WS_POPUP | #TTS_NOPREFIX | #TTS_BALLOON, 0, 0, 0, 0, WindowID(btWindow), 0, GetModuleHandle_(0), 0)
  SetWindowPos_(ToolTipControl,#HWND_TOPMOST, 0, 0, 0, 0, #SWP_NOMOVE | #SWP_NOSIZE)
  ;SendMessage_(ToolTipControl, #TTM_SETTIPTEXTCOLOR, 0, 0)
  ;SendMessage_(ToolTipControl, #TTM_SETTIPBKCOLOR, #Yellow, 0)
  SendMessage_(ToolTipControl, #TTM_SETMAXTIPWIDTH, 0, 300)
  Button.TOOLINFO\cbSize  = SizeOf(TOOLINFO)
  Button\uFlags           = #TTF_IDISHWND|#TTF_SUBCLASS
  Button\hwnd             = WindowID(btWindow)
  Button\uID              = GadgetID(btGadget)
  Button\hInst            = 0
  Button\lpszText         = @btText
  SendMessage_(ToolTipControl, #TTM_ADDTOOL, 0, Button)
  SendMessage_(ToolTipControl, #TTM_UPDATE, 0, 0)
EndProcedure

If OpenWindow(0,0,0,140,120,"test",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  StringGadget(1,10,10,100,100,"string",#ES_MULTILINE)
  MyBalloonToolTips(0,1,"test")
  SetActiveWindow(0)
  Repeat
    ev=WaitWindowEvent()
  Until ev=#PB_Event_CloseWindow
EndIf
IdeasVacuum
Always Here
Always Here
Posts: 6425
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Balloon tooltip at specified X/Y window position?

Post by IdeasVacuum »

Hi Dude

You can DIY them - hidden image gadget, 32bit image, check cursor position at the start of your main loop.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: Balloon tooltip at specified X/Y window position?

Post by Dude »

Okay... is there a way to force a tooltip to be shown, rather than wait for the mouse to hover over it?
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4636
Joined: Sun Apr 12, 2009 6:27 am

Re: Balloon tooltip at specified X/Y window position?

Post by RASHAD »

Hi Dude
Suit yourself

#1 :

Code: Select all

Procedure MyBalloonToolTips(btWindow.l, btText.s)
  httip = CreateWindowEx_(0, "ToolTips_Class32", "", #WS_POPUP | #TTS_NOPREFIX | #TTS_BALLOON |#TTS_ALWAYSTIP, 0, 0, 0, 0, WindowID(btWindow), 0, GetModuleHandle_(0), 0)
  SetWindowTheme_(httip, @null.w, @null.w)
  ttip.TOOLINFO\cbSize  = SizeOf(TOOLINFO)
  SendMessage_(httip, #TTM_SETTIPTEXTCOLOR,$2E35FE, 0)
  SendMessage_(httip, #TTM_SETTIPBKCOLOR, $C8FEFE, 0)
  ttip\uFlags           = #TTF_SUBCLASS
  ttip\hwnd             = WindowID(btWindow)
  ttip\uID              = WindowID(btWindow)
  SetRect_(@ttip\rect, 20,-25,80,20) 
  ttip\lpszText         = @btText
  SendMessage_(httip, #TTM_ADDTOOL, 0, ttip)
EndProcedure

If OpenWindow(0,0,0,140,120,"test",#PB_Window_SystemMenu| #PB_Window_ScreenCentered)
  MyBalloonToolTips(0,"test")
  SetActiveWindow(0)
  Repeat
    ev=WaitWindowEvent()
  Until ev=#PB_Event_CloseWindow
EndIf
2 : Full demo

Code: Select all

Global TTip,TTip2

#TTS_BUBBLE    = $40
#TTF_TRACK     =  $20
#TTF_ABSOLUTE  =  $80

Procedure GadToolTip(Gadget,Tip$)
  ti.TOOLINFO
  ti\cbSize = SizeOf(ti) 
  ti\hInst = GetModuleHandle_(0)
  ti\uFlags = #TTF_IDISHWND | #TTF_SUBCLASS
  ti\hwnd = GadgetID(Gadget) 
  ti\uId = GadgetID(Gadget)
  ti\lpszText = @Tip$ 
  SendMessage_(TTip, #TTM_ADDTOOL, 0, ti)
EndProcedure 

Procedure TTip_Command(x,y,dTime,Title$,Tip$,Icon)
  ti2.TOOLINFO
  ti2\cbSize = SizeOf(ti2) 
  ti2\hInst = GetModuleHandle_(0)
  ti2\uFlags = #TTF_TRACK | #TTF_ABSOLUTE
  ti2\lpszText = @Tip$
  SendMessage_(TTip2, #TTM_ADDTOOL, 0, ti2) 
  SendMessage_(TTip2,#TTM_SETTOOLINFO,0,ti2)
  SendMessage_(TTip2, #TTM_SETTITLE, Icon, @Title$)
  SendMessage_(TTip2,#TTM_TRACKPOSITION,0,x+y<<16)
  SendMessage_(TTip2,#TTM_TRACKACTIVATE,1,ti2)                      
  SendMessage_(TTip2,#TTM_TRACKPOSITION,0,x + 50 + y<<16)                    
  Delay(dTime)
  SendMessage_(TTip2,#TTM_TRACKACTIVATE,0,ti2)
EndProcedure

TTip = CreateWindowEx_(#WS_EX_TOPMOST, "tooltips_class32", 0, #TTS_ALWAYSTIP| #TTS_NOPREFIX| #WS_POPUP| #TTS_BUBBLE,0,0,0,0, 0, 0, GetModuleHandle_(0), 0)
  SetWindowTheme_(TTip, @null.w, @null.w)
  SendMessage_(TTip,#TTM_SETTIPTEXTCOLOR,$0202FD,0)
  SendMessage_(TTip,#TTM_SETTIPBKCOLOR,$DCFFFF,0)

TTip2 = CreateWindowEx_(#WS_EX_TOPMOST, "tooltips_class32", 0, #TTS_ALWAYSTIP| #TTS_NOPREFIX| #WS_POPUP| #TTS_BUBBLE,0,0,0,0, 0, 0, GetModuleHandle_(0), 0)
  SetWindowTheme_(TTip2, @null.w, @null.w)
  SendMessage_(TTip2,#TTM_SETTIPTEXTCOLOR,$0202FD,0)
  SendMessage_(TTip2,#TTM_SETTIPBKCOLOR,$DCFFFF,0)  

If OpenWindow(0, 0, 0, 300, 300, "Tooltips by Command",#PB_Window_ScreenCentered| #PB_Window_SystemMenu)  
  
  ButtonGadget(0,10,10,80,20,"TEST # 0")
  GadToolTip(0,"This is a test for"+#CRLF$+"Multiline Balloon")
  
  ButtonGadget(1,10,40,80,20,"TEST # 1")
  GadToolTip(1,"Gadget # 1 Tooltip") 
  
  StringGadget(2,10,70,120,20,"This is a test")
  GadToolTip(2,"Gadget # 2 Tooltip") 
    
  ButtonGadget(3,10,260,80,20,"Title Bar")
  ButtonGadget(4,100,260,80,20,"TEST 1")

AddWindowTimer(0,100,100)  
Repeat
  Select WaitWindowEvent()      
      Case #PB_Event_CloseWindow
            Quit = 1
            
      Case #PB_Event_Timer
          x = DesktopMouseX()
          y = DesktopMouseY()
          If x > WindowX(0) And x < WindowX(0) + 80 And y > WindowY(0) And y < WindowY(0)+20
            TTip_Command(WindowX(0)-20,WindowY(0)+20,1500,"Hi","This is a test for"+#CRLF$+"Multiline Balloon",#TOOLTIP_WARNING_ICON)
          EndIf
     
      Case #PB_Event_Gadget
          Select EventGadget()
            Case 3
                x = WindowX(0)-20
                y = WindowY(0)+10
                TTip_Command(x,y,1500,"Hi","This is a test for"+#CRLF$+"Multiline Balloon",#TOOLTIP_WARNING_ICON)
                    
            Case 4
                x = GadgetX(1,#PB_Gadget_ScreenCoordinate)
                y = GadgetY(1,#PB_Gadget_ScreenCoordinate)
                TTip_Command(x,y,1500,"Remember","Gadget # 1 Tooltip",#TOOLTIP_INFO_ICON)
                       
          EndSelect          
      EndSelect 
      
Until Quit = 1
End
EndIf
Edit :Bugs fixed for #2 example
Egypt my love
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: Balloon tooltip at specified X/Y window position?

Post by Dude »

Thank you, Rashad. :) Wish I had just 1% of your knowledge.
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5342
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Balloon tooltip at specified X/Y window position?

Post by Kwai chang caine »

Code: Select all

Thank you, Rashad. :)
+1 8)

Code: Select all

Wish I had just 1% of your knowledge.
+10 :mrgreen:
ImageThe happiness is a road...
Not a destination
User avatar
RSBasic
Moderator
Moderator
Posts: 1218
Joined: Thu Dec 31, 2009 11:05 pm
Location: Gernsbach (Germany)
Contact:

Re: Balloon tooltip at specified X/Y window position?

Post by RSBasic »

Kwai chang caine wrote:

Code: Select all

Wish I had just 1% of your knowledge.
+10 :mrgreen:
You can acquire the knowledge. WinAPI is very simple. :)
There are many books about WinAPI on amazon.com. Or useful help pages. E.g.:
Index: https://msdn.microsoft.com/us-en/librar ... s.85).aspx
List of functions from A to Z: https://msdn.microsoft.com/en-us/library/aa383688.aspx
List of functions in categories: https://msdn.microsoft.com/en-us/library/aa383686.aspx
There are also tutorials on purearea.net and google.com.
Image
Image
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: Balloon tooltip at specified X/Y window position?

Post by Dude »

Thanks, RSBasic -- I'll definitely browse it. 8)

But as an example of what I mean: clicking both the "A-Z" and "Categories" lists don't show anything about ToolTips, so... I would still be lost without Rashad's generous and kind help. The MSDN is not always obvious on how to find something. :(
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5342
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Balloon tooltip at specified X/Y window position?

Post by Kwai chang caine »

And furthermore for a french guy talking english like a spanish cow :oops:
So thanks RsBasic :wink:
ImageThe happiness is a road...
Not a destination
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: Balloon tooltip at specified X/Y window position?

Post by Dude »

Dude wrote:is there a way to force a tooltip to be shown, rather than wait for the mouse to hover over it?
Revisiting this question (sorry!). What about for normal tooltips created with GadgetToolTip(), instead of creating a custom one to show when forced?
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4636
Joined: Sun Apr 12, 2009 6:27 am

Re: Balloon tooltip at specified X/Y window position?

Post by RASHAD »

Workaround

Code: Select all

OpenWindow(0,0,0,320,240,"",#PB_Window_SystemMenu  | #PB_Window_ScreenCentered)
StringGadget(1,10,40,200,20,"stuff")
GadgetToolTip(1, "This is a StringGadget")

ButtonGadget(2,10,80,60,22,"TEST")
GadgetToolTip(2, "This is Button 2")

ButtonGadget(3,10,200,60,20,"Test 1")
ButtonGadget(4,80,200,60,20,"Test 2")

Repeat
  Select WaitWindowEvent()     
      Case #PB_Event_CloseWindow
            Quit = 1       
 
      Case #PB_Event_Gadget
          Select EventGadget()
            Case 3
              x = WindowX(0)+GadgetX(1)+30
              y = WindowY(0)+GadgetY(1)+40              
              SetCursorPos_(x,y)
              
            Case 4
              x = WindowX(0)+GadgetX(2)+30
              y = WindowY(0)+GadgetY(2)+40              
              SetCursorPos_(x,y)                 
                       
          EndSelect         
      EndSelect
     
Until Quit = 1
End
For On or Off

Code: Select all

; test program
OpenWindow(0,0,0,320,240,"",#PB_Window_SystemMenu  | #PB_Window_ScreenCentered)
StringGadget(1,10,40,200,20,"stuff")
GadgetToolTip(1, "This is a StringGadget")

ButtonGadget(2,10,80,60,22,"TEST")
GadgetToolTip(2, "This is Button 2")

ButtonGadget(3,10,200,60,20,"Test 1")
ButtonGadget(4,80,200,60,20,"Test 2")

Repeat
  Select WaitWindowEvent()     
      Case #PB_Event_CloseWindow
            Quit = 1       
 
      Case #PB_Event_Gadget
          Select EventGadget()
            Case 3  ;On or off
                x = WindowX(0)+GadgetX(1)+30
                y = WindowY(0)+GadgetY(1)+40
                SetCapture_(GadgetID(1))              
                SetCursorPos_(x,y)
              
            Case 4
              x = WindowX(0)+GadgetX(2)+30
              y = WindowY(0)+GadgetY(2)+40              
              SetCursorPos_(x,y)                 
                       
          EndSelect         
      EndSelect
     
Until Quit = 1
End
Egypt my love
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: Balloon tooltip at specified X/Y window position?

Post by Dude »

Thanks Rashad. Still gives a small delay so it's not quite what I was looking for - I was hoping to make its tooltip appear instantly. But I don't see how that's possible without making a custom tooltip, right?
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4636
Joined: Sun Apr 12, 2009 6:27 am

Re: Balloon tooltip at specified X/Y window position?

Post by RASHAD »

Hi Dude
- Best one
- PB x86 & PB x64
- Repeated is allowed

Code: Select all

#TTS_BUBBLE    = $40
#TTF_TRACK     =  $20
#TTF_ABSOLUTE  =  $80

Global TTip,Run

Structure GadgetGlobals
   CurrentWindow.i
   FirstOptionGadget.i
   DefaultFont.i
   *PanelStack
   PanelStackIndex.l
   PanelStackSize.l
  ToolTipWindow.i
EndStructure

Import ""
  PB_Object_GetThreadMemory(*Mem)
  PB_Gadget_Globals
EndImport

Procedure ToolTipID() 
  Protected *gg.GadgetGlobals 
  *gg = PB_Object_GetThreadMemory(PB_Gadget_Globals) 
  ProcedureReturn *gg\ToolTipWindow 
EndProcedure

Procedure TTip_Command(gad,x,y,text$,dTime)
  ti.TOOLINFO
  ti\cbSize = SizeOf(ti)
  ti\hInst = GetModuleHandle_(0)
  ti\uFlags = #TTF_TRACK | #TTF_ABSOLUTE
  ti\lpszText = @Text$ 
  SendMessage_(TTip, #TTM_ADDTOOL, 0, ti) 
  SendMessage_(TTip,#TTM_TRACKACTIVATE,1,ti)                     
  SendMessage_(TTip,#TTM_TRACKPOSITION,0,x+10 + (y+10)<<16)                   
  Delay(dTime)
  SendMessage_(TTip,#TTM_TRACKACTIVATE,0,ti)
  SendMessage_(TTip, #TTM_DELTOOL, 0, ti)
EndProcedure

; test program
LoadFont(0,"Consolas",12)
OpenWindow(0,0,0,320,240,"" ,#PB_Window_SystemMenu | #PB_Window_ScreenCentered)
StringGadget(1,10,10,200,20,"stuff")
GadgetToolTip(1, "StringGadget() tooltip")
ttip = ToolTipID()
SendMessage_(ttip,#WM_SETFONT,FontID(0),0)

ButtonGadget(2,10,40,200,20,"stuff")
GadgetToolTip(2, "ButtonGadget() tooltip")
SetWindowLongPtr_(ttip,#GWL_STYLE, GetWindowLongPtr_(ttip,#GWL_STYLE)|#TTS_BALLOON &~#WS_BORDER)

ButtonGadget(3,10,200,80,20,"TEST 1")
ButtonGadget(4,100,200,80,20,"TEST 2")
Repeat
  Select WaitWindowEvent()     
      Case #PB_Event_CloseWindow
            Quit = 1
     
      Case #PB_Event_Gadget
          Select EventGadget()
            Case 3
              Run3 ! 1
              If Run3 = 1
                x = GadgetX(1,#PB_Gadget_ScreenCoordinate)+1
                y = GadgetY(1,#PB_Gadget_ScreenCoordinate)
              Else
                x = GadgetX(1,#PB_Gadget_ScreenCoordinate)
                y = GadgetY(1,#PB_Gadget_ScreenCoordinate)
              EndIf                 
              TTip_Command(1,x,y,"StringGadget() tooltip",2000)
                             
            Case 4
              Run4 ! 1
              If Run4 = 1
                x = GadgetX(2,#PB_Gadget_ScreenCoordinate)+1
                y = GadgetY(2,#PB_Gadget_ScreenCoordinate)
              Else
                x = GadgetX(2,#PB_Gadget_ScreenCoordinate)
                y = GadgetY(2,#PB_Gadget_ScreenCoordinate)
              EndIf   
              TTip_Command(2,x,y,"ButtonGadget() tooltip",2000)
                       
          EndSelect         
      EndSelect
     
Until Quit = 1
- Get the ToolTip text

Code: Select all

#TTS_BUBBLE    = $40
#TTF_TRACK     =  $20
#TTF_ABSOLUTE  =  $80

Global TTip

Structure GadgetGlobals
   CurrentWindow.i
   FirstOptionGadget.i
   DefaultFont.i
   *PanelStack
   PanelStackIndex.l
   PanelStackSize.l
  ToolTipWindow.i
EndStructure

Import ""
  PB_Object_GetThreadMemory(*Mem)
  PB_Gadget_Globals
EndImport

Procedure ToolTipID() 
  Protected *gg.GadgetGlobals 
  *gg = PB_Object_GetThreadMemory(PB_Gadget_Globals) 
  ProcedureReturn *gg\ToolTipWindow 
EndProcedure

Procedure.s GetToolTipText(win,gad)
  Buffer.s = Space(#MAX_PATH)
  ti.TOOLINFO
  ti\cbSize = SizeOf(ti) 
  ti\hwnd = WindowID(win) 
  ti\uId = GadgetID(gad) 
  ti\lpszText = @Buffer 
  SendMessage_(TTip,#TTM_GETTEXT,0,@ti) 
  ProcedureReturn Buffer 
EndProcedure 

Procedure TTip_Command(win,gad,x,y,dTime)
  ti.TOOLINFO
  ti\cbSize = SizeOf(ti)
  ti\hInst = GetModuleHandle_(0)
  ti\uFlags = #TTF_TRACK | #TTF_ABSOLUTE
  SendMessage_(TTip, #TTM_DELTOOL, 0, ti)
  text$ = GetToolTipText(win,gad)
  ti\lpszText = @Text$
  SendMessage_(TTip, #TTM_ADDTOOL, 0, ti)  
  SendMessage_(TTip,#TTM_TRACKACTIVATE,1,ti)                     
  SendMessage_(TTip,#TTM_TRACKPOSITION,0,x+10 + (y+10)<<16)                   
  Delay(dTime)
  SendMessage_(TTip,#TTM_TRACKACTIVATE,0,ti)
EndProcedure

; test program
OpenWindow(0,0,0,320,240,"" ,#PB_Window_SystemMenu | #PB_Window_ScreenCentered)
StringGadget(1,10,10,200,20,"stuff")
GadgetToolTip(1, "StringGadget() tooltip")
ttip = ToolTipID()

ButtonGadget(2,10,40,200,20,"stuff")
GadgetToolTip(2, "ButtonGadget() tooltip")
;SetWindowLongPtr_(ttip,#GWL_STYLE, GetWindowLongPtr_(ttip,#GWL_STYLE)|#TTS_BALLOON &~#WS_BORDER)

ButtonGadget(3,10,200,80,20,"TEST 1")
ButtonGadget(4,100,200,80,20,"TEST 2")

Repeat
  Select WaitWindowEvent()     
      Case #PB_Event_CloseWindow
            Quit = 1
     
      Case #PB_Event_Gadget
          Select EventGadget()
            Case 3
                x = GadgetX(1,#PB_Gadget_ScreenCoordinate)
                y = GadgetY(1,#PB_Gadget_ScreenCoordinate)
                TTip_Command(0,1,x,y,2000)                    
            Case 4
                x = GadgetX(2,#PB_Gadget_ScreenCoordinate)
                y = GadgetY(2,#PB_Gadget_ScreenCoordinate)
                TTip_Command(0,2,x,y,2000)
                       
          EndSelect         
      EndSelect
     
Until Quit = 1
Egypt my love
Post Reply