October 28, 2025, 04:44:12 PM

News:

IWBasic runs in Windows 11!


Tooltips

Started by LarryMc, November 14, 2010, 02:30:54 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

LarryMc

I like tooltips.

Is there a way to take control of where tooltip text appears?
Instead of having it in a little box next to the item it refers to I would like to have one dedicated location in my own custom window that is always present(when I want it to be).

Or is this something done in some way with WINHELP or is it something that has to be coded from scratch?
WickedRush's VisiBasic did it apparently from scratch by displaying individual html files

LarryMc
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

fasecero

Hi Larry... maybe something like this can help?



$INCLUDE "WindowsSDK.inc"
$INCLUDE "CommCtrl.inc"

CONST BUTTON_1 = 1
CONST BUTTON_2 = 2
CONST BUTTON_3 = 3
WINDOW w1
OPENWINDOW w1,0,0,512,347,0x80C80080,0,"Tooltip",&w1_handler
CONTROL w1,@BUTTON,"Button1",28,55,70,20,0x50000000,BUTTON_1
CONTROL w1,@BUTTON,"Button2",28,89,70,20,0x50000000,BUTTON_2
CONTROL w1,@BUTTON,"Button3",28,125,70,20,0x50000000,BUTTON_3

INT WinOldProc
UINT hwndTooltip

Init()
WAITUNTIL w1=0

SUB w1_handler
SELECT @MESSAGE
CASE @IDCREATE
CENTERWINDOW w1
/* Initialize any controls here */
CASE @IDCLOSEWINDOW
SetWindowLong(w1.hwnd, GWL_WNDPROC, WinOldProc)
CLOSEWINDOW w1
CASE @IDCONTROL
SELECT @CONTROLID
CASE BUTTON_1
IF @NOTIFYCODE = 0
/*button clicked*/
ENDIF
CASE BUTTON_2
IF @NOTIFYCODE = 0
/*button clicked*/
ENDIF
CASE BUTTON_3
IF @NOTIFYCODE = 0
/*button clicked*/
ENDIF
ENDSELECT
ENDSELECT
RETURN
ENDSUB

SUB MainProc(INT hWin, INT uMsg, INT wParam, INT lParam), INT
pointer pnmhdr : SETTYPE pnmhdr, NMHDR

SELECT uMsg
CASE WM_NOTIFY
pnmhdr = *<NMHDR> lParam
RETURN OnNotify(hWin, #pnmhdr.idFrom, #pnmhdr.code, #pnmhdr.hwndFrom, lParam)
ENDSELECT

RETURN CallWindowProc(WinOldProc, hWin, uMsg, wParam, lParam)
ENDSUB

SUB OnNotify(int hWin, int ctrlid, int code, int hwndCtrl, int lParam), INT
WINRECT rc
POINT pnt

SELECT hwndCtrl
CASE hwndTooltip
SELECT code
CASE TTN_SHOW
GetClientRect(hWin, &rc)
pnt.x = rc.right
pnt.y = rc.bottom
ClientToScreen(hWin, &pnt)

MoveWindow(hwndTooltip, pnt.x-200, pnt.y-200, 200, 200, 0)

RETURN 1
ENDSELECT
ENDSELECT

RETURN 0
ENDSUB

SUB Init()
' create the tool tip control
hwndTooltip = ToolTipControl(w1, @TTS_ALWAYSTIP, 0)

'add tooltips for our buttons
ttAddTool hwndTooltip,@TTF_SUBCLASS|@TTF_IDISHWND|@TTF_CENTERTIP,GetControlHandle(w1,BUTTON_1),w1.hwnd,"Button number one"
ttAddTool hwndTooltip,@TTF_SUBCLASS|@TTF_IDISHWND|@TTF_CENTERTIP,GetControlHandle(w1,BUTTON_2),w1.hwnd,"Button number two"
ttAddTool hwndTooltip,@TTF_SUBCLASS|@TTF_IDISHWND|@TTF_CENTERTIP,GetControlHandle(w1,BUTTON_3),w1.hwnd,"Button number three"

WinOldProc = SetWindowLong(w1.hwnd, GWL_WNDPROC, &MainProc)
ENDSUB


LarryMc

Thanks

That's real close.
The only rhing that is missing is for the tip to remain as long as the mouse sits on a button.

With this one it times out and closes.

LarryMc
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

fasecero

November 14, 2010, 10:34:02 PM #3 Last Edit: November 14, 2010, 11:21:20 PM by fasecero
You can set the tooltip duration with TTM_SETDELAYTIME message:


SUB Init()
' create the tool tip control
hwndTooltip = ToolTipControl(w1, @TTS_ALWAYSTIP, 0)
[s]SENDMESSAGE hwndTooltip, TTM_SETDELAYTIME, TTDT_AUTOPOP, 3600000 ' 1 hour[/s]
'add tooltips for our buttons
ttAddTool hwndTooltip,@TTF_SUBCLASS|@TTF_IDISHWND|@TTF_CENTERTIP,GetControlHandle(w1,BUTTON_1),w1.hwnd,"Button number one"
ttAddTool hwndTooltip,@TTF_SUBCLASS|@TTF_IDISHWND|@TTF_CENTERTIP,GetControlHandle(w1,BUTTON_2),w1.hwnd,"Button number two"
ttAddTool hwndTooltip,@TTF_SUBCLASS|@TTF_IDISHWND|@TTF_CENTERTIP,GetControlHandle(w1,BUTTON_3),w1.hwnd,"Button number three"

WinOldProc = SetWindowLong(w1.hwnd, GWL_WNDPROC, &MainProc)
ENDSUB



LarryMc

Alright!

Thanks again

LarryMc
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

fasecero

My last post was wrong. Here is the fixed way:


int iTime = 32767 ' millisecs
SENDMESSAGE hwndTooltip, TTM_SETDELAYTIME, TTDT_AUTOPOP, MAKELONG(iTime, 0)


but the maximum allowed timeout value is 32 seconds, so maybe this might not work for your purposes.

sapero

Maybe the following class with raw api's will do what you want?
$include "windowssdk.inc"
$include "commctrl.inc"
$include "stdio.inc"

'======================================= the class
$ifndef CTOOLTIP_CCHMAX
$define CTOOLTIP_CCHMAX 256
$endif

$ifndef __windowssdk_inc__
$include "windowssdk.inc"
$endif

class CTooltip
declare CTooltip()

declare Create(HWND hwndParent)
declare Show()
declare SetPosition(int x, int y, BOOL ClientRelative)
declare Hide()
declare SetText(LPTSTR text)

declare OnNotify(LPARAM lParam)
declare OnSize(opt int width=-1, opt int height)

HWND     m_hwnd
HWND     m_hwndParent
int      m_maxWidth ' 0:SingleLine; >0:multiline
TOOLINFO m_ti
TCHAR    m_szTooltipText[CTOOLTIP_CCHMAX]
endclass

'======================================= demo
enum controls
IDC_STATIC = 1000
IDC_TRACKING
IDC_FIXEDPOS
endenum

DIALOG d1
CTooltip tooltip
CREATEDIALOG d1,0,0,480,286,0x80CA0080,0,"CTooltip demo",&d1_handler
CONTROL d1,@STATIC,"Non-tooltip area",32,41,100,100,0x5000010B|@BORDER,IDC_STATIC
CONTROL d1,@RADIOBUTTON,"tracking",210,29,70,20,0x50010009,IDC_TRACKING
CONTROL d1,@RADIOBUTTON,"fixed pos",210,52,70,20,0x50000009,IDC_FIXEDPOS
DOMODAL d1


SUB d1_handler
SELECT @MESSAGE
CASE @IDINITDIALOG
CENTERWINDOW d1
/* Initialize any controls here */
tooltip.Create(d1.hWnd)
tooltip.m_maxWidth = 300

CASE @IDCLOSEWINDOW
CLOSEDIALOG d1,@IDOK

CASE @IDSIZE
tooltip.OnSize()

CASE @IDMOUSEMOVE
istring text[32]
_snprintf(&text, 32, "cursor at %dx%d", @MOUSEX, @MOUSEY)

if (GETSTATE(d1, IDC_TRACKING))
tooltip.SetPosition(@MOUSEX+16, @MOUSEY+16, TRUE)
elseif (GETSTATE(d1, IDC_FIXEDPOS))
tooltip.SetPosition(0, 0, TRUE)
else
return 0
endif
tooltip.SetText(text)
tooltip.Show()

TRACKMOUSEEVENT tme
tme.cbSize      = LEN(tme)
tme.dwFlags     = TME_HOVER | TME_LEAVE
tme.hwndTrack   = tooltip.m_hwndParent
tme.dwHoverTime = 25
TrackMouseEvent(tme)

CASE WM_MOUSELEAVE
tooltip.Hide()

CASE @IDCONTROL
SELECT @NOTIFYCODE
CASE  TTN_GETDISPINFOA
CASE& TTN_GETDISPINFOW
tooltip.OnNotify(@LPARAM)
ENDSELECT
ENDSELECT
RETURN 0
ENDSUB




'======================================= the class

'$include "ctooltip.inc" ' include class definition

$ifndef __commctrl_inc__
$include "commctrl.inc"
$endif

sub CTooltip::CTooltip()
m_hwnd             = 0
m_maxWidth         = 0
InitCommonControls()
$ifdef UNICODE
SetText(L"x")
$else
SetText("x")
$endif
endsub


sub CTooltip::Create(HWND hwndParent)

m_hwndParent = hwndParent

m_hwnd = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL, _
WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, _
CW_USEDEFAULT, CW_USEDEFAULT, hwndParent, 0, _hinstance,0)

GetClientRect(hwndParent, &m_ti._rect)

m_ti.cbSize   = TTTOOLINFO_V2_SIZE
m_ti.uFlags   = TTF_TRANSPARENT | TTF_ABSOLUTE | TTF_TRACK
m_ti.hwnd     = hwndParent
m_ti.hinst    = 0'_hinstance
m_ti.uId      = 0
m_ti.lpszText = LPSTR_TEXTCALLBACK

_SendMessage(m_hwnd, TTM_ADDTOOL, 0, &m_ti)
_SendMessage(m_hwnd, TTM_TRACKACTIVATE, TRUE, &m_ti)
Hide()
endsub


sub CTooltip::OnNotify(LPARAM lParam)
BOOL active = FALSE

if (*<NMHDR>lParam.hwndFrom = m_hwnd)
if (*<NMHDR>lParam.code = TTN_GETDISPINFOA)

$ifdef UNICODE
' convert unicode string m_szTooltipText to ansi NMTTDISPINFO.szText
WideCharToMultiByte(0,0,m_szTooltipText,-1,*<NMTTDISPINFO>lParam.szText,80,0,0)
$else
*<NMTTDISPINFO>lParam.lpszText = m_szTooltipText
$endif
active = TRUE

elseif (*<NMHDR>lParam.code = TTN_GETDISPINFOW)

$ifdef UNICODE
*<NMTTDISPINFO>lParam.lpszText = m_szTooltipText
$else
' convert ansi string m_szTooltipText to unicode NMTTDISPINFO.szText
MultiByteToWideChar(0,0,m_szTooltipText,-1,*<NMTTDISPINFO>lParam.szText,80)
$endif
active = TRUE

endif
endif

if (active)
*<NMTTDISPINFO>lParam.hinst = 0
if (m_maxWidth)
_SendMessage(*<NMHDR>lParam.hwndFrom, TTM_SETMAXTIPWIDTH, 0, m_maxWidth)
endif
endif
endsub


sub CTooltip::OnSize(int width, int height)
if (width = -1)
GetClientRect(m_hwndParent, &m_ti._rect)
else
m_ti._rect.right = width
m_ti._rect.bottom = height
endif
_SendMessage(m_hwnd, TTM_NEWTOOLRECT, 0, &m_ti)
endsub


sub CTooltip::Show()
_SendMessage(m_hwnd, TTM_POPUP, 0, 0)
endsub


sub CTooltip::SetPosition(int x, int y, BOOL ClientRelative)
if (ClientRelative)
ClientToScreen(m_hwndParent, &x)
endif
_SendMessage(m_hwnd, TTM_TRACKPOSITION, 0, MAKELONG(x, y))
endsub


sub CTooltip::Hide()
_ShowWindow(m_hwnd, SW_HIDE)
endsub


sub CTooltip::SetText(LPTSTR text)
lstrcpyn(m_szTooltipText, text, CTOOLTIP_CCHMAX)
if (m_hwnd) then _SendMessage(m_hwnd, TTM_UPDATE, 0, 0)
endsub

LarryMc

LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library