Your topic sounds quite intriguing, and I've tried to tackle it personally, but could only achieve partial success.
Since the scroll area corresponds to the non-client area of the window, that needs to be considered.
I managed to pinpoint when the cursor enters and leaves the Edit control by considering
.
, I'm still puzzled by why occasional remnants of the scroll graphics persist.
bit is indeed present, but honestly, I'm at a loss.
I hope someone with more insight into this issue can offer some assistance...
Code: Select all
#Requires AutoHotkey v2.0
#SingleInstance Force
GWL_STYLE := -16
WM_SHOWWINDOW := 0x0018
WM_MOUSEMOVE := 0x0200
WM_NCMOUSELEAVE := 0x02A2
WM_MOUSELEAVE := 0x02A3
WS_HSCROLL := 0x00100000
WS_VSCROLL := 0x00200000
onMessage(WM_SHOWWINDOW, winProc)
onMessage(WM_MOUSEMOVE, winProc)
onMessage(WM_NCMOUSELEAVE, winProc)
onMessage(WM_MOUSELEAVE, winProc)
G:=gui()
TB:=G.addEdit("-E0x200 +ReadOnly x100 y50 w200 r10", "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
TB.opt("+VScroll")
G.show("w400 h300")
dllCall("User32.dll\SetFocus", "Ptr",0, "Ptr")
winProc(wParam, lParam, Msg, hWnd) {
static prevHwnd:=0
prevIC:=critical("On")
switch (hRootWnd:=winExist())
{
case G.Hwnd:
switch (Msg)
{
case WM_SHOWWINDOW:
if (wParam)
prevHwnd:=0
return
case WM_MOUSEMOVE:
if (prevHwnd!==hWnd) {
switch (prevHwnd:=hWnd)
{
case TB.Hwnd: newShow:=true
}
}
case WM_NCMOUSELEAVE, WM_MOUSELEAVE:
POINT:=buffer(8,0)
dllCall("User32.dll\GetCursorPos", "Ptr",POINT.Ptr)
x:=numGet(POINT,0,"Int")
y:=numGet(POINT,4,"Int")
hPoint:=dllCall("User32.dll\WindowFromPoint", "Int64",(x&0xFFFFFFFF)|(y<<32), "Ptr")
if (hWnd!==hPoint) {
switch (hWnd)
{
case TB.Hwnd: newShow:=false
}
}
}
if (isSet(newShow)) {
currShow:=!!(WS_VSCROLL&dllCall("User32.dll\GetWindowLong" (A_PtrSize==8?"Ptr":""), "Ptr",hWnd, "Int",GWL_STYLE, (A_PtrSize==8?"Ptr":"Int")))
if (newShow!==currShow) {
; TB_VScroll.show(newShow)
TB_VScroll.delayedShow(newShow, 100)
}
}
}
critical(prevIC)
}
class TB_VScroll
{
static bShow:=0
,objbmShow:=objBindMethod(this,"show")
static delayedShow(newShow, tick) {
this.bShow:=newShow
setTimer this.objbmShow, -abs(tick)
}
static show(bShow?) {
static OBJID_VSCROLL:=0xFFFFFFFB
,STATE_SYSTEM_INVISIBLE:=0x00008000
if (!dllCall("User32.dll\IsWindow", "Ptr",TB.Gui.Hwnd))
return
bShow:=bShow??this.bShow
TB.opt((bShow?"+":"-") "VScroll")
TB.redraw()
/*
tooltip isVisible:=!!(WS_VSCROLL&dllCall("User32.dll\GetWindowLong" (A_PtrSize==8?"Ptr":""), "Ptr",TB.Hwnd, "Int",GWL_STYLE, (A_PtrSize==8?"Ptr":"Int")))
*/
/*
this._getScrollBarInfo(TB.Hwnd,OBJID_VSCROLL,&objsbi)
tooltip isVisible:=!(objsbi.rgstate.0&STATE_SYSTEM_INVISIBLE)
*/
}
static _getScrollBarInfo(hWnd, idObject, &objsbi) {
objsbi:={cbSize:"",rcScrollBar:{left:"",top:"",right:"",bottom:""},dxyLineButton:"",xyThumbTop:"",xyThumbBottom:"",reserved:"",rgstate:{0:"",1:"",2:"",3:"",4:"",5:""}}
,psbi:=buffer(60,0)
,numPut("UInt",60,psbi,0)
if (bRet:=dllCall("User32.dll\GetScrollBarInfo", "Ptr",hWnd, "Int",idObject, "Ptr",psbi.Ptr)) {
objsbi.cbSite:=numGet(psbi,0,"UInt")
,objsbi.rcScrollBar.left:=numGet(psbi,4,"Int")
,objsbi.rcScrollBar.top:=numGet(psbi,8,"Int")
,objsbi.rcScrollBar.right:=numGet(psbi,12,"Int")
,objsbi.rcScrollBar.bottom:=numGet(psbi,16,"Int")
,objsbi.dxyLineButton:=numGet(psbi,20,"Int")
,objsbi.xyThumbTop:=numGet(psbi,24,"Int")
,objsbi.xyThumbBottom:=numGet(psbi,28,"Int")
,objsbi.reserved:=numGet(psbi,32,"Int")
loop 6
objsbi.rgstate.%A_Index-1%:=numGet(psbi,32+A_Index*4,"Int")
}
return bRet
}
}