; ScrollBind(简单生成可滚动的子页面) By FeiYue ; ; 使用方法: ; 参考下面的例子,将父控件和GUI子窗口绑定即可 #NoEnv #SingleInstance force ; 在GUI创建过程避免中途触发GuiSize线程 Critical, % (bak:=A_IsCritical)?"":"" ; 先备份GUI主窗口的句柄 Gui, +Hwndgui_id -DPIScale +ReSize ; +AlwaysOnTop Gui, Margin, 15, 15 Gui, Color, DDEEFF Gui, Font, s12 Gui, Add, Tab3, HwndhMyTab w350, 第1页|第2页|第3页|第4页 For k,v in StrSplit("第1页|第2页|第3页|第4页", "|") { Gui, Tab, % k ; 添加一个文本控件作为父控件,获取父控件句柄 Gui, Add, Text, Hwndparent_id w300 h400 ;---------------------------- ; 新建一个GUI子窗口,获取子窗口句柄 Gui, New, +Hwndsub_id -DPIScale Gui, Color, DDEEFF Gui, Font, s12 Loop 50 Gui, Add, Button, w250 gRunButton, %v% %A_Index% ; 利用ScrollBind类,将GUI子窗口绑定到父控件中 ScrollBind.Bind(parent_id, sub_id) ; 绑定之后备份父子两个句柄用于调整大小 parent_id%k%:=parent_id, sub_id%k%:=sub_id ;---------------------------- ; 利用GUI主窗口的句柄返回默认的GUI Gui, %gui_id%: Default } Gui, Tab ; 获取Tab3控件的高度用于编辑控件对齐 GuiControlGet, p, Pos, %hMyTab% Gui, Add, Edit, ym w500 h%pH% HwndhMyEdit Gui, Show, Center, 简单生成可滚动的子页面 - By FeiYue ; 在GUI创建完毕后允许GuiSize线程触发 Critical, %bak% ; 可选的左键任意拖动窗口 OnMessage(0x201, Func("LButton_Down")) LButton_Down() { if (A_Gui!="") and (A_GuiControl="") SendMessage, 0xA1, 2 } return ; 使用函数可避免修改全局变量 RunButton() { k:=A_GuiControl Gui, +OwnDialogs MsgBox, 4096, Tip, % k } ; 使用函数可避免修改全局变量 GuiSize() { global local id, w, h, k, v Critical ; 只响应GUI主窗口的调整大小消息 Gui, +Hwndid if (ErrorLevel=1) or (id!=gui_id) return w:=Floor(A_GuiWidth-350-15*3), h:=Floor(A_GuiHeight-15*2) GuiControl, Move, %hMyEdit%, w%w% h%h% GuiControl, Move, %hMyTab%, h%h% ; 对GUI子窗口的调整大小,先确保创建完毕 For k,v in StrSplit("第1页|第2页|第3页|第4页", "|") if (parent_id%k% and sub_id%k%) { h:=Floor(A_GuiHeight-15*2-60) GuiControl, Move, % parent_id%k%, h%h% ScrollBind.ReSize(sub_id%k%, 300, h) } } GuiClose() { ExitApp } ;===== 下面是 ScrollBind 类 ===== ; 这个类只用于绑定父控件和GUI子窗口,不干涉子窗口的生成 Class ScrollBind { ;-- 类开始 __New(args*) { ; 不生成实体对象,只使用类对象本身 return this.base } ; 核心的绑定函数,参数是父控件的句柄和GUI子窗口的句柄 Bind(parent_id, sub_id) { static init:=0 if !DllCall("IsWindow", "Ptr",parent_id) or !DllCall("IsWindow", "Ptr",sub_id) return if (!init) { init:=1, this.Scroll_ID:=[] OnMessage(WM_MOUSEWHEEL:=0x20A, this.WM_MOUSEWHEEL.Bind(this)) OnMessage(WM_KeyDown:=0x100, this.WM_KEYDOWN.Bind(this)) OnMessage(WM_VSCROLL:=0x115, this.WM_VSCROLL.Bind(this)) OnMessage(WM_HSCROLL:=0x114, this.WM_VSCROLL.Bind(this)) } ; 避免Gui,Show触发GuiSize线程中断当前线程 Critical, % (bak:=A_IsCritical)?"":"" VarSetCapacity(rect,16) DllCall("GetClientRect", "Ptr",parent_id, "Ptr",&rect) w:=NumGet(rect, 8, "Int"), h:=NumGet(rect, 12, "Int") Gui, %sub_id%: +Parent%parent_id% -Caption +ToolWindow -Border Gui, %sub_id%: Show, NA x0 y0 w%w% h%h% this.UpdateScrollBars(sub_id, w, h) this.Scroll_ID[parent_id]:=sub_id this.Scroll_ID[sub_id]:=sub_id Critical, %bak% } ; 调整GUI子窗口的大小 ReSize(sub_id, w, h) { DllCall("MoveWindow","Ptr",sub_id,"int",0,"int",0,"int",w,"int",h,"int",1) this.UpdateScrollBars(sub_id, w, h) } ; 当鼠标在可滚动的子窗口上时,可以用鼠标滚轮来滚动 WM_MOUSEWHEEL(wParam) { Critical if (A_Gui="") return MouseGetPos,,,, id, 2 if (this.Scroll_ID[id]) or (this.Scroll_ID[id:=DllCall("GetParent","ptr",id)]) or (this.Scroll_ID[id:=DllCall("GetParent","ptr",id)]) { id:=this.Scroll_ID[id], wParam:=(wParam>>16&0xFFFF)>0x7FFF Loop 4 this.WM_VSCROLL(wParam, 0, 0x115, id) return 1 } } ; 当鼠标在可滚动的子窗口上时,可以用方向键和翻页键来滚动 WM_KEYDOWN(wParam) { static arr:={ GetKeyVK("Up"):0, GetKeyVK("Down"):1 , GetKeyVK("PgUp"):2, GetKeyVK("PgDn"):3 } Critical if (A_Gui="") or (!arr.HasKey(wParam)) return MouseGetPos,,,, id, 2 if (this.Scroll_ID[id]) or (this.Scroll_ID[id:=DllCall("GetParent","ptr",id)]) or (this.Scroll_ID[id:=DllCall("GetParent","ptr",id)]) { id:=this.Scroll_ID[id], wParam:=arr[wParam] this.WM_VSCROLL(wParam, 0, 0x115, id) return 1 } } ; thanks lexikos, FeiYue 作了改进 UpdateScrollBars(GuiHwnd, GuiWidth, GuiHeight) { static SIF_RANGE:=1, SIF_PAGE:=2, SB_HORZ:=0, SB_VERT:=1 if (GuiWidth<0 or GuiHeight<0) return DetectHiddenWindows, % (bak:=A_DetectHiddenWindows)?"On":"On" WinGet, List, ControlListHwnd, ahk_id %GuiHwnd% DetectHiddenWindows, %bak% Left:=Top:=9999, Right:=Bottom:=0 Loop, Parse, List, `n { GuiControlGet, c, Pos, %A_LoopField% Left:=Min(Left, cX), Top:=Min(Top, cY) Right:=Max(Right, cX+cW), Bottom:=Max(Bottom, cY+cH) } Left-=8, Top-=8, Right+=8, Bottom+=8 ScrollWidth:=Right-Left, ScrollHeight:=Bottom-Top ;-- Initialize SCROLLINFO VarSetCapacity(si, 28, 0) NumPut(28, si) ; cbSize NumPut(SIF_RANGE | SIF_PAGE, si, 4) ; fMask ;-- Update horizontal scroll bar NumPut(ScrollWidth, si, 12) ; nMax NumPut(GuiWidth, si, 16) ; nPage DllCall("SetScrollInfo", "Ptr",GuiHwnd, "uint",SB_HORZ, "Ptr",&si, "int",1) ;-- Update vertical scroll bar NumPut(ScrollHeight, si, 12) ; nMax NumPut(GuiHeight, si, 16) ; nPage DllCall("SetScrollInfo", "Ptr",GuiHwnd, "uint",SB_VERT, "Ptr",&si, "int",1) x:=(Left<0 && Right<GuiWidth) ? Min(-Left, GuiWidth-Right) : 0 y:=(Top<0 && Bottom<GuiHeight) ? Min(-Top, GuiHeight-Bottom) : 0 if (x || y) DllCall("ScrollWindow", "Ptr",GuiHwnd, "int",x, "int",y, "int",0, "int",0) } ; thanks lexikos, FeiYue 作了改进 WM_VSCROLL(wParam, lParam, msg, hwnd) { static SIF_ALL:=0x17, SCROLL_STEP:=10 Critical bar:=(msg=0x115) VarSetCapacity(si, 28, 0), NumPut(28, si, "UInt") ; cbSize NumPut(SIF_ALL, si, 4, "UInt") ; fMask if !DllCall("GetScrollInfo", "Ptr",hwnd, "Int",bar, "Ptr",&si) return VarSetCapacity(rect,16), DllCall("GetClientRect", "Ptr",hwnd, "Ptr",&rect) h:=bar ? NumGet(rect, 12, "Int") : NumGet(rect, 8, "Int") new_pos:=old_pos:=NumGet(si, 20, "UInt") ; nPos Switch (wParam & 0xFFFF) { Case 0: new_pos-=SCROLL_STEP ; SB_LINEUP Case 1: new_pos+=SCROLL_STEP ; SB_LINEDOWN Case 2: new_pos-=h-SCROLL_STEP ; SB_PAGEUP Case 3: new_pos+=h-SCROLL_STEP ; SB_PAGEDOWN Case 4, 5: new_pos:=wParam>>16 ; SB_THUMBPOSITION, SB_THUMBTRACK Case 6: new_pos:=NumGet(si, 8, "Int") ; nMin ; SB_TOP Case 7: new_pos:=NumGet(si, 12, "Int") ; nMax ; SB_BOTTOM Default: return } min:=NumGet(si, 8, "Int") ; nMin max:=NumGet(si, 12, "Int") - NumGet(si, 16, "UInt") ; nMax-nPage new_pos:=Min(Max(min, new_pos), max) (bar) ? (x:=0, y:=old_pos-new_pos) : (x:=old_pos-new_pos, y:=0) DllCall("ScrollWindow", "Ptr",hwnd, "Int",x, "Int",y, "Int",0, "Int",0) NumPut(new_pos, si, 20, "Int") ; nPos DllCall("SetScrollInfo", "Ptr",hwnd, "Int",bar, "Ptr",&si, "Int",1) } } ;-- 类结束
声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。
评论(0)