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
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
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
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
Alright!
Thanks again
LarryMc
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.
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
Thanks Sapero
LarryMc