Post by just me » 11 Apr 2024, 06:52
Moin
@Nussbeisser,
ich habe noch eine weitgehend umgestellte Version gefunden (die Methode
AdjustToChild() fehlt). Du kannst das ja mal ausprobieren:
Code: Select all
#Requires AutoHotkey v2.0
; ======================================================================================================================
; Namepace: ScrollGUI
; Function: Creates a scrollable GUI as a parent for GUI windows.
; Tested with: AHK 2.0.2
; Tested on: Win 10 Pro (x64)
; License: The Unlicense -> http://unlicense.org
; Change log: 2.0.0/2023-01-??/just me - Initial release for AHK v2
; ======================================================================================================================
Class ScrollGUI {
; ===================================================================================================================
; __New Creates a scrollable parent window (ScrollGUI) for the passed GUI.
; Parameters:
; Child - The GUI object of the child window.
; Width - Width of the client area of the ScrollGUI.
; Pass 0 to set the client area to the width of the child GUI.
; Height - Height of the client area of the ScrollGUI.
; Pass 0 to set the client area to the height of the child GUI.
; ----------- Optional:
; GuiOpts - GUI options to be used when creating the ScrollGUI (e.g. +LabelMyLabel).
; Default: empty (no options)
; ScrollBars - Scroll bars to register:
; 1 : horizontal
; 2 : vertical
; 3 : both
; Default: 3
; Wheel - Register WM_MOUSEWHEEL / WM_MOUSEHWHEEL messages:
; 1 : register WM_MOUSEHWHEEL for horizontal scrolling (reqires Win Vista+)
; 2 : register WM_MOUSEWHEEL for vertical scrolling
; 3 : register both
; 4 : register WM_MOUSEWHEEL for vertical and Shift+WM_MOUSEWHEEL for horizontal scrolling
; Default: 0
; Return values:
; On failure: False
; Remarks:
; The dimensions of the child GUI are determined internally according to the visible children.
; The maximum width and height of the parent GUI will be restricted to the dimensions of the child GUI.
; If you register mouse wheel messages, the messages will be passed to the focused control, unless the mouse
; is hovering on one of the ScrollGUI's scroll bars. If the control doesn't process the message, it will be
; returned back to the ScrollGUI.
; Common controls seem to ignore wheel messages whenever the CTRL is down. So you can use this modifier to
; scroll the ScrollGUI even if a scrollable control has the focus.
; ===================================================================================================================
BF_SCROLL := 0
BF_SIZE := 0
BF_WHEEL := 0
Child := 0
Parent := 0
; ===================================================================================================================
__New(Child, Width := 0, Height := 0, GuiOpts := "", ScrollBars := 3, Wheel := 0) {
Static WS_HSCROLL := "0x100000", WS_VSCROLL := "0x200000"
If !(Type(Child) = "Gui")
Throw TypeError("Paramweter Child must be a Gui object!", -1, Type(Child))
HGUI := Child.Hwnd
If !(Type(Width) = "Integer")
Throw TypeError("Paramweter Width must be an integer!", -1, Type(Width))
If !(Type(Height) = "Integer")
Throw TypeError("Paramweter Height must be an integer!", -1, Type(Height))
If !(Type(ScrollBars) = "Integer")
Throw TypeError("Paramweter ScrollBars must be an integer!", -1, Type(ScrollBars))
If !(Type(Wheel) = "Integer")
Throw TypeError("Paramweter Wheel must be an integer!", -1, Type(Wheel))
Bars := ScrollBars & 3
Wheel &= 7
If (Bars = 0)
Throw ValueError("Paramweter ScrollBars must be an integer between 1 and 3!", -1, ScrollBars)
AutoSize := (Width = -1)
This.BF_SCROLL := ObjBindMethod(This, "On_WM_Scroll")
This.BF_SIZE := ObjBindMethod(This, "On_WM_Size")
This.BF_WHEEL := ObjBindMethod(This, "On_WM_Wheel")
Child.Opt("-Caption -Resize")
Child.Show((AutoSize ? "AutoSize " : "") . "Hide")
Child.GetClientPos( , , &GW, &GH)
WinGetClientPos( , , &CW, &CH, Child.Hwnd)
MaxH := CW
MaxV := CH
LineH := Ceil(MaxH / 20)
LineV := Ceil(MaxV / 20)
; ScrollGUI
If (Width = 0)
Width := GW
If (Height = 0)
Height := GH
Styles := (Bars & 1 ? " +" . WS_HSCROLL : "") . (Bars & 2 ? " +" . WS_VSCROLL : "")
Parent := Gui(GuiOpts . Styles)
Parent.Show("w" . Width . " h" . Height . " Hide")
If AutoSize
Parent.Opt("+MaxSize" . GW . "x" . GH)
WinGetClientPos( , , &CW, &CH, Parent.Hwnd)
PageH := CW + 1
PageV := CH + 1
; Instance variables
This.Parent := Parent
This.Child := Child
This.Width := Width
This.Height := Height
This.UseShift := False
If (Bars & 1) {
This.SetScrollInfo(0, {Max: MaxH, Page: PageH, Pos: 0}) ; SB_HORZ = 0
OnMessage(0x0114, This.BF_SCROLL) ; WM_HSCROLL = 0x0114
If (Wheel & 1)
OnMessage(0x020E, This.BF_WHEEL) ; WM_MOUSEHWHEEL = 0x020E
Else If (Wheel & 4) {
OnMessage(0x020A, This.BF_WHEEL) ; WM_MOUSEWHEEL = 0x020A
This.UseShift := True
}
This.MaxH := MaxH
This.LineH := LineH
This.PageH := PageH
This.PosH := 0
This.ScrollH := True
If (Wheel & 5)
This.WheelH := True
}
If (Bars & 2) {
This.SetScrollInfo(1, {Max: MaxV, Page: PageV, Pos: 0}) ; SB_VERT = 1
OnMessage(0x0115, This.BF_SCROLL) ; WM_VSCROLL = 0x0115
If (Wheel & 6)
OnMessage(0x020A, This.BF_WHEEL) ; WM_MOUSEWHEEL = 0x020A
This.MaxV := MaxV
This.LineV := LineV
This.PageV := PageV
This.PosV := 0
This.ScrollV := True
If (Wheel & 6)
This.WheelV := True
}
; Set the position of the child GUI
Child.Opt("+Parent" . Parent.Hwnd)
Child.Show("x0 y0")
; Adjust the scroll bars
This.Size()
OnMessage(0x0005, This.BF_SIZE) ; WM_SIZE = 0x0005
}
; ===================================================================================================================
; __Delete Destroy the GUIs, if they still exist.
; ===================================================================================================================
__Delete() {
This.Destroy()
}
; ===================================================================================================================
; Show Shows the ScrollGUI.
; Parameters:
; Title - Title of the ScrollGUI window
; ShowOptions - Gui, Show command options, width or height options are ignored
; Return values:
; On success: True
; On failure: False
; ===================================================================================================================
Show(Title := "", ShowOptions := "") {
ShowOptions := RegExReplace(ShowOptions, "i)\+?AutoSize")
WH := Format(" w{:} h{:}", This.Width, This.Height)
If Title != ""
This.Parent.Title := Title
This.Parent.Show(ShowOptions . WH)
Return True
}
; ===================================================================================================================
; Destroy Destroys the ScrollGUI and the associated child GUI.
; Parameters:
; None.
; Return values:
; On success: True
; On failure: False
; Remarks:
; Use this method instead of 'Gui, Destroy' to remove the ScrollGUI from the 'Instances' object.
; ===================================================================================================================
Destroy() {
If This.Parent {
This.Parent.Destroy()
This.Parent := 0
}
If This.BF_SCROLL {
OnMessage(0x0114, This.BF_SCROLL, 0) ; WM_HSCROLL = 0x0114
This.BF_SCROLL := 0
}
If This.BF_SIZE {
OnMessage(0x0005, This.BF_SIZE, 0) ; WM_SIZE = 0x0005
This.BF_SIZE := 0
}
If This.This.BF_WHEEL {
OnMessage(0x020A, This.BF_WHEEL, 0) ; WM_MOUSEWHEEL = 0x020A
OnMessage(0x020E, This.BF_WHEEL, 0) ; WM_MOUSEHWHEEL = 0x020E
This.BF_WHEEL := 0
}
Return True
}
; ===================================================================================================================
; AdjustToChild Adjust the scroll bars to the new child dimensions.
; Parameters:
; None
; Return values:
; On success: True
; On failure: False
; Remarks:
; Call this method whenever the visible area of the child GUI has to be changed, e.g. after adding, hiding,
; unhiding, resizing, or repositioning controls.
; The dimensions of the child GUI are determined internally according to the visible children.
; ===================================================================================================================
AdjustToChild() {
; This.Child.GetPos(&CX, &CY, &CW, &CH)
; VarSetCapacity(RC, 16, 0)
; DllCall("User32.dll\GetWindowRect", "Ptr", This.HGUI, "Ptr", &RC)
; PrevW := NumGet(RC, 8, "Int") - NumGet(RC, 0, "Int")
; PrevH := Numget(RC, 12, "Int") - NumGet(RC, 4, "Int")
; DllCall("User32.dll\ScreenToClient", "Ptr", This.HWND, "Ptr", &RC)
; XC := XN := NumGet(RC, 0, "Int")
; YC := YN := NumGet(RC, 4, "Int")
; If !This.AutoSize(This.HGUI, GuiW, GuiH)
; Return False
; Gui, % This.HGUI . ":Show", x%XC% y%YC% w%GuiW% h%GuiH%
; MaxH := GuiW
; MaxV := GuiH
; Gui, % This.HWND . ":+MaxSize" . MaxH . "x" . MaxV
; If (GuiW < This.Width) || (GuiH < This.Height) {
; Gui, % This.HWND . ":Show", w%GuiW% h%GuiH%
; This.Width := GuiW
; This.SetPage(1, MaxH + 1)
; This.Height := GuiH
; This.SetPage(2, MaxV + 1)
; }
; LineH := Ceil(MaxH / 20)
; LineV := Ceil(MaxV / 20)
; If This.ScrollH {
; This.SetMax(1, MaxH)
; This.LineH := LineH
; If (XC + MaxH) < This.Width {
; XN += This.Width - (XC + MaxH)
; If (XN > 0)
; XN := 0
; This.SetScrollInfo(0, {Pos: XN * -1})
; This.GetScrollInfo(0, SI)
; This.PosH := NumGet(SI, 20, "Int")
; }
; }
; If This.ScrollV {
; This.SetMax(2, MaxV)
; This.LineV := LineV
; If (YC + MaxV) < This.Height {
; YN += This.Height - (YC + MaxV)
; If (YN > 0)
; YN := 0
; This.SetScrollInfo(1, {Pos: YN * -1})
; This.GetScrollInfo(1, SI)
; This.PosV := NumGet(SI, 20, "Int")
; }
; }
; If (XC != XN) || (YC != YN)
; DllCall("User32.dll\ScrollWindow", "Ptr", This.Parent.Hwnd, "Int", XN - XC, "Int", YN - YC, "Ptr", 0, "Ptr", 0)
Return True
}
; ===================================================================================================================
; SetMax Sets the width or height of the scrolling area.
; Parameters:
; SB - Scroll bar to set the value for:
; 1 = horizontal
; 2 = vertical
; Max - Width respectively height of the scrolling area in pixels
; Return values:
; On success: True
; On failure: False
; ===================================================================================================================
SetMax(SB, Max) {
; SB_HORZ = 0, SB_VERT = 1
SB--
If (SB != 0) && (SB != 1)
Return False
If (SB = 0)
This.MaxH := Max
Else
This.MaxV := Max
Return This.SetScrollInfo(SB, {Max: Max})
}
; ===================================================================================================================
; SetLine Sets the number of pixels to scroll by line.
; Parameters:
; SB - Scroll bar to set the value for:
; 1 = horizontal
; 2 = vertical
; Line - Number of pixels.
; Return values:
; On success: True
; On failure: False
; ===================================================================================================================
SetLine(SB, Line) {
; SB_HORZ = 0, SB_VERT = 1
SB--
If (SB != 0) && (SB != 1)
Return False
If (SB = 0)
This.LineH := Line
Else
This.LineV := Line
Return True
}
; ===================================================================================================================
; SetPage Sets the number of pixels to scroll by page.
; Parameters:
; SB - Scroll bar to set the value for:
; 1 = horizontal
; 2 = vertical
; Page - Number of pixels.
; Return values:
; On success: True
; On failure: False
; Remarks:
; If the ScrollGUI is resizable, the page size will be recalculated automatically while resizing.
; ===================================================================================================================
SetPage(SB, Page) {
; SB_HORZ = 0, SB_VERT = 1
SB--
If (SB != 0) && (SB != 1)
Return False
If (SB = 0)
This.PageH := Page
Else
This.PageV := Page
Return This.SetScrollInfo(SB, {Page: Page})
}
; ===================================================================================================================
GetScrollInfo(SB, &SI) {
SI := Buffer(28, 0) ; SCROLLINFO
NumPut("UInt", 28, "UInt", 0x17, SI) ; SIF_ALL = 0x17
Return DllCall("GetScrollInfo", "Ptr", This.Parent.Hwnd, "Int", SB, "Ptr", SI, "UInt")
}
; ===================================================================================================================
SetScrollInfo(SB, Values) {
Static SIF := {Max: 0x01, Page: 0x02, Pos: 0x04}
Static Off := {Max: 12, Page: 16, Pos: 20}
Mask := 0
SI := Buffer(28, 0) ; SCROLLINFO
NumPut("UInt", 28, SI)
For Key, Value In Values.OwnProps() {
If SIF.HasProp(Key) {
Mask |= SIF.%Key%
NumPut("UInt", Value, SI, Off.%Key%)
}
}
If (Mask) {
NumPut("UInt", Mask | 0x08, SI, 4) ; SIF_DISABLENOSCROLL = 0x08
Return DllCall("SetScrollInfo", "Ptr", This.Parent.Hwnd, "Int", SB, "Ptr", SI, "UInt", 1, "UInt")
}
Return False
}
; ===================================================================================================================
On_WM_Scroll(WP, LP, Msg, HWND) {
; WM_HSCROLL = 0x0114, WM_VSCROLL = 0x0115
If (HWND = This.Parent.Hwnd) && (((Msg = 0x0114) && This.ScrollH) || ((Msg = 0x0115) && This.ScrollV))
Return This.Scroll(WP, LP, Msg, HWND)
}
; ===================================================================================================================
Scroll(WP, LP, Msg, HWND) {
; WM_HSCROLL = 0x0114, WM_VSCROLL = 0x0115
Static SB_LINEMINUS := 0, SB_LINEPLUS := 1, SB_PAGEMINUS := 2, SB_PAGEPLUS := 3, SB_THUMBTRACK := 5
If (LP != 0)
Return
SB := (Msg = 0x0114 ? 0 : 1) ; SB_HORZ : SB_VERT
SC := WP & 0xFFFF
SD := (Msg = 0x0114 ? This.LineH : This.LineV)
SI := 0
If !This.GetScrollInfo(SB, &SI)
Return
PA := PN := NumGet(SI, 20, "Int")
Switch SC {
Case 0: PN := PA - SD ; SB_LINEMINUS
Case 1: PN := PA + SD ; SB_LINEPLUS
Case 2: PN := PA - NumGet(SI, 16, "UInt") ; SB_PAGEMINUS
Case 3: PN := PA + NumGet(SI, 16, "UInt") ; SB_PAGEPLUS
Case 5: PN := NumGet(SI, 24, "Int") ; SB_THUMBTRACK
}
If (PN = PA)
Return 0
This.SetScrollInfo(SB, {Pos: PN})
This.GetScrollInfo(SB, &SI)
PN := NumGet(SI, 20, "Int")
If (SB = 0)
This.PosH := PN
Else
This.PosV := PN
If (PA != PN) {
HS := (Msg = 0x0114) ? PA - PN : 0
VS := (Msg = 0x0115) ? PA - PN : 0
DllCall("ScrollWindow", "Ptr", HWND, "Int", HS, "Int", VS, "Ptr", 0, "Ptr", 0)
}
Return 0
}
; ===================================================================================================================
On_WM_Size(WP, LP, Msg, HWND) {
If (HWND = This.Parent.Hwnd) && ((WP = 0) || (WP = 2))
Return This.Size(LP & 0xFFFF, (LP >> 16) & 0xFFFF)
}
; ===================================================================================================================
Size(Width := 0, Height := 0) {
If (Width = 0) || (Height = 0)
WinGetClientPos( , , &Width, &Height, This.Parent.Hwnd)
SH := SV := 0
If This.ScrollH && (Width != This.Width) {
This.SetScrollInfo(0, {Page: Width + 1}),
This.Width := Width,
This.GetScrollInfo(0, &SI),
PosH := NumGet(SI, 20, "Int"),
SH := This.PosH - PosH,
This.PosH := PosH
}
If This.ScrollV && (Height != This.Height) {
This.SetScrollInfo(1, {Page: Height + 1}),
This.Height := Height,
This.GetScrollInfo(1, &SI),
PosV := NumGet(SI, 20, "Int"),
SV := This.PosV - PosV,
This.PosV := PosV
}
If (SH) || (SV)
DllCall("User32.dll\ScrollWindow", "Ptr", This.Parent.Hwnd, "Int", SH, "Int", SV, "Ptr", 0, "Ptr", 0)
Return 0
}
; ===================================================================================================================
On_WM_Wheel(WP, LP, Msg, HWND) {
; MK_SHIFT = 0x0004, WM_MOUSEWHEEL = 0x020A, WM_MOUSEHWHEEL = 0x020E, WM_NCHITTEST = 0x0084
If (HWND != This.Parent.Hwnd) {
If (WinActive("A") = This.Parent.Hwnd) {
OnBar := SendMessage(0x0084, 0, LP & 0xFFFFFFFF, This.Parent.Hwnd)
If (OnBar = 6) && This.WheelH ; HTHSCROLL = 6
Return This.Wheel(WP, LP, 0x020E, This.Parent.Hwnd)
If (OnBar = 7) && This.WheelV ; HTVSCROLL = 7
Return This.Wheel(WP, LP, 0x020A, This.Parent.Hwnd)
}
}
Else If ((Msg = 0x020E) && This.WheelH) ||
((Msg = 0x020A) && (This.WheelV || (This.WheelH && This.UseShift && (WP & 0x0004))))
Return This.Wheel(WP, LP, Msg, HWND)
}
; ===================================================================================================================
Wheel(WP, LP, Msg, HWND) {
; MK_SHIFT = 0x0004, WM_MOUSEWHEEL = 0x020A, WM_MOUSEHWHEEL = 0x020E, WM_HSCROLL = 0x0114, WM_VSCROLL = 0x0115
; SB_LINEMINUS = 0, SB_LINEPLUS = 1
If (Msg = 0x020A) && This.UseShift && (WP & 0x0004)
Msg := 0x020E
Msg := (Msg = 0x020A ? 0x0115 : 0x0114)
SB := ((WP >> 16) > 0x7FFF) || (WP < 0) ? 1 : 0
Return This.Scroll(SB, 0, Msg, HWND)
}
}
Minibeispiel:
Code: Select all
#Requires AutoHotkey v2.0.0
#Include Class_ScrollGUI.ahk
; -------------------------------------------------------------------------------------------------------------------
; ChildGUI 1
Lines := "1`n2`n3`n4`n5`n6`n7`n8"
ChildGui := Gui()
ChildGui.MarginX := 20
ChildGui.MarginY := 20
I := 0
ChildGui.AddText("w370 h20 0x200 Section", "Edit " . ++I)
ChildGui.AddEdit("xp y+0 wp r6")
Loop 4 {
ChildGui.AddText("xp y+0 wp h20 0x200", "Edit " . ++I)
ChildGui.AddEdit("xp y+0 wp r6", Lines)
}
ChildGui.AddText("ys wp h20 0x200", "Edit " . ++I)
ChildGui.AddEdit("xp y+0 wp r6")
Loop 4 {
ChildGui.AddText("xp y+0 wp h20 0x200", "Edit " . ++I)
ChildGui.AddEdit("xp y+0 wp r6", Lines)
}
; Create ScrollGUI1 with both horizontal and vertical scrollbars
SG1 := ScrollGUI(ChildGui, 300, 400, "+Resize +MinSize", , 3)
SG1.Parent.OnEvent("Close", Scroll1Close)
SG1.Parent.OnEvent("Escape", Scroll1Close)
; Show ScrollGUI1
SG1.Show("ScrollGUI1 Title", "")
Return
; ----------------------------------------------------------------------------------------------------------------------
Scroll1Close(*) {
ExitApp
}
Moin [mention]Nussbeisser[/mention],
ich habe noch eine weitgehend umgestellte Version gefunden (die Methode [c]AdjustToChild()[/c] fehlt). Du kannst das ja mal ausprobieren:
[code]#Requires AutoHotkey v2.0
; ======================================================================================================================
; Namepace: ScrollGUI
; Function: Creates a scrollable GUI as a parent for GUI windows.
; Tested with: AHK 2.0.2
; Tested on: Win 10 Pro (x64)
; License: The Unlicense -> http://unlicense.org
; Change log: 2.0.0/2023-01-??/just me - Initial release for AHK v2
; ======================================================================================================================
Class ScrollGUI {
; ===================================================================================================================
; __New Creates a scrollable parent window (ScrollGUI) for the passed GUI.
; Parameters:
; Child - The GUI object of the child window.
; Width - Width of the client area of the ScrollGUI.
; Pass 0 to set the client area to the width of the child GUI.
; Height - Height of the client area of the ScrollGUI.
; Pass 0 to set the client area to the height of the child GUI.
; ----------- Optional:
; GuiOpts - GUI options to be used when creating the ScrollGUI (e.g. +LabelMyLabel).
; Default: empty (no options)
; ScrollBars - Scroll bars to register:
; 1 : horizontal
; 2 : vertical
; 3 : both
; Default: 3
; Wheel - Register WM_MOUSEWHEEL / WM_MOUSEHWHEEL messages:
; 1 : register WM_MOUSEHWHEEL for horizontal scrolling (reqires Win Vista+)
; 2 : register WM_MOUSEWHEEL for vertical scrolling
; 3 : register both
; 4 : register WM_MOUSEWHEEL for vertical and Shift+WM_MOUSEWHEEL for horizontal scrolling
; Default: 0
; Return values:
; On failure: False
; Remarks:
; The dimensions of the child GUI are determined internally according to the visible children.
; The maximum width and height of the parent GUI will be restricted to the dimensions of the child GUI.
; If you register mouse wheel messages, the messages will be passed to the focused control, unless the mouse
; is hovering on one of the ScrollGUI's scroll bars. If the control doesn't process the message, it will be
; returned back to the ScrollGUI.
; Common controls seem to ignore wheel messages whenever the CTRL is down. So you can use this modifier to
; scroll the ScrollGUI even if a scrollable control has the focus.
; ===================================================================================================================
BF_SCROLL := 0
BF_SIZE := 0
BF_WHEEL := 0
Child := 0
Parent := 0
; ===================================================================================================================
__New(Child, Width := 0, Height := 0, GuiOpts := "", ScrollBars := 3, Wheel := 0) {
Static WS_HSCROLL := "0x100000", WS_VSCROLL := "0x200000"
If !(Type(Child) = "Gui")
Throw TypeError("Paramweter Child must be a Gui object!", -1, Type(Child))
HGUI := Child.Hwnd
If !(Type(Width) = "Integer")
Throw TypeError("Paramweter Width must be an integer!", -1, Type(Width))
If !(Type(Height) = "Integer")
Throw TypeError("Paramweter Height must be an integer!", -1, Type(Height))
If !(Type(ScrollBars) = "Integer")
Throw TypeError("Paramweter ScrollBars must be an integer!", -1, Type(ScrollBars))
If !(Type(Wheel) = "Integer")
Throw TypeError("Paramweter Wheel must be an integer!", -1, Type(Wheel))
Bars := ScrollBars & 3
Wheel &= 7
If (Bars = 0)
Throw ValueError("Paramweter ScrollBars must be an integer between 1 and 3!", -1, ScrollBars)
AutoSize := (Width = -1)
This.BF_SCROLL := ObjBindMethod(This, "On_WM_Scroll")
This.BF_SIZE := ObjBindMethod(This, "On_WM_Size")
This.BF_WHEEL := ObjBindMethod(This, "On_WM_Wheel")
Child.Opt("-Caption -Resize")
Child.Show((AutoSize ? "AutoSize " : "") . "Hide")
Child.GetClientPos( , , &GW, &GH)
WinGetClientPos( , , &CW, &CH, Child.Hwnd)
MaxH := CW
MaxV := CH
LineH := Ceil(MaxH / 20)
LineV := Ceil(MaxV / 20)
; ScrollGUI
If (Width = 0)
Width := GW
If (Height = 0)
Height := GH
Styles := (Bars & 1 ? " +" . WS_HSCROLL : "") . (Bars & 2 ? " +" . WS_VSCROLL : "")
Parent := Gui(GuiOpts . Styles)
Parent.Show("w" . Width . " h" . Height . " Hide")
If AutoSize
Parent.Opt("+MaxSize" . GW . "x" . GH)
WinGetClientPos( , , &CW, &CH, Parent.Hwnd)
PageH := CW + 1
PageV := CH + 1
; Instance variables
This.Parent := Parent
This.Child := Child
This.Width := Width
This.Height := Height
This.UseShift := False
If (Bars & 1) {
This.SetScrollInfo(0, {Max: MaxH, Page: PageH, Pos: 0}) ; SB_HORZ = 0
OnMessage(0x0114, This.BF_SCROLL) ; WM_HSCROLL = 0x0114
If (Wheel & 1)
OnMessage(0x020E, This.BF_WHEEL) ; WM_MOUSEHWHEEL = 0x020E
Else If (Wheel & 4) {
OnMessage(0x020A, This.BF_WHEEL) ; WM_MOUSEWHEEL = 0x020A
This.UseShift := True
}
This.MaxH := MaxH
This.LineH := LineH
This.PageH := PageH
This.PosH := 0
This.ScrollH := True
If (Wheel & 5)
This.WheelH := True
}
If (Bars & 2) {
This.SetScrollInfo(1, {Max: MaxV, Page: PageV, Pos: 0}) ; SB_VERT = 1
OnMessage(0x0115, This.BF_SCROLL) ; WM_VSCROLL = 0x0115
If (Wheel & 6)
OnMessage(0x020A, This.BF_WHEEL) ; WM_MOUSEWHEEL = 0x020A
This.MaxV := MaxV
This.LineV := LineV
This.PageV := PageV
This.PosV := 0
This.ScrollV := True
If (Wheel & 6)
This.WheelV := True
}
; Set the position of the child GUI
Child.Opt("+Parent" . Parent.Hwnd)
Child.Show("x0 y0")
; Adjust the scroll bars
This.Size()
OnMessage(0x0005, This.BF_SIZE) ; WM_SIZE = 0x0005
}
; ===================================================================================================================
; __Delete Destroy the GUIs, if they still exist.
; ===================================================================================================================
__Delete() {
This.Destroy()
}
; ===================================================================================================================
; Show Shows the ScrollGUI.
; Parameters:
; Title - Title of the ScrollGUI window
; ShowOptions - Gui, Show command options, width or height options are ignored
; Return values:
; On success: True
; On failure: False
; ===================================================================================================================
Show(Title := "", ShowOptions := "") {
ShowOptions := RegExReplace(ShowOptions, "i)\+?AutoSize")
WH := Format(" w{:} h{:}", This.Width, This.Height)
If Title != ""
This.Parent.Title := Title
This.Parent.Show(ShowOptions . WH)
Return True
}
; ===================================================================================================================
; Destroy Destroys the ScrollGUI and the associated child GUI.
; Parameters:
; None.
; Return values:
; On success: True
; On failure: False
; Remarks:
; Use this method instead of 'Gui, Destroy' to remove the ScrollGUI from the 'Instances' object.
; ===================================================================================================================
Destroy() {
If This.Parent {
This.Parent.Destroy()
This.Parent := 0
}
If This.BF_SCROLL {
OnMessage(0x0114, This.BF_SCROLL, 0) ; WM_HSCROLL = 0x0114
This.BF_SCROLL := 0
}
If This.BF_SIZE {
OnMessage(0x0005, This.BF_SIZE, 0) ; WM_SIZE = 0x0005
This.BF_SIZE := 0
}
If This.This.BF_WHEEL {
OnMessage(0x020A, This.BF_WHEEL, 0) ; WM_MOUSEWHEEL = 0x020A
OnMessage(0x020E, This.BF_WHEEL, 0) ; WM_MOUSEHWHEEL = 0x020E
This.BF_WHEEL := 0
}
Return True
}
; ===================================================================================================================
; AdjustToChild Adjust the scroll bars to the new child dimensions.
; Parameters:
; None
; Return values:
; On success: True
; On failure: False
; Remarks:
; Call this method whenever the visible area of the child GUI has to be changed, e.g. after adding, hiding,
; unhiding, resizing, or repositioning controls.
; The dimensions of the child GUI are determined internally according to the visible children.
; ===================================================================================================================
AdjustToChild() {
; This.Child.GetPos(&CX, &CY, &CW, &CH)
; VarSetCapacity(RC, 16, 0)
; DllCall("User32.dll\GetWindowRect", "Ptr", This.HGUI, "Ptr", &RC)
; PrevW := NumGet(RC, 8, "Int") - NumGet(RC, 0, "Int")
; PrevH := Numget(RC, 12, "Int") - NumGet(RC, 4, "Int")
; DllCall("User32.dll\ScreenToClient", "Ptr", This.HWND, "Ptr", &RC)
; XC := XN := NumGet(RC, 0, "Int")
; YC := YN := NumGet(RC, 4, "Int")
; If !This.AutoSize(This.HGUI, GuiW, GuiH)
; Return False
; Gui, % This.HGUI . ":Show", x%XC% y%YC% w%GuiW% h%GuiH%
; MaxH := GuiW
; MaxV := GuiH
; Gui, % This.HWND . ":+MaxSize" . MaxH . "x" . MaxV
; If (GuiW < This.Width) || (GuiH < This.Height) {
; Gui, % This.HWND . ":Show", w%GuiW% h%GuiH%
; This.Width := GuiW
; This.SetPage(1, MaxH + 1)
; This.Height := GuiH
; This.SetPage(2, MaxV + 1)
; }
; LineH := Ceil(MaxH / 20)
; LineV := Ceil(MaxV / 20)
; If This.ScrollH {
; This.SetMax(1, MaxH)
; This.LineH := LineH
; If (XC + MaxH) < This.Width {
; XN += This.Width - (XC + MaxH)
; If (XN > 0)
; XN := 0
; This.SetScrollInfo(0, {Pos: XN * -1})
; This.GetScrollInfo(0, SI)
; This.PosH := NumGet(SI, 20, "Int")
; }
; }
; If This.ScrollV {
; This.SetMax(2, MaxV)
; This.LineV := LineV
; If (YC + MaxV) < This.Height {
; YN += This.Height - (YC + MaxV)
; If (YN > 0)
; YN := 0
; This.SetScrollInfo(1, {Pos: YN * -1})
; This.GetScrollInfo(1, SI)
; This.PosV := NumGet(SI, 20, "Int")
; }
; }
; If (XC != XN) || (YC != YN)
; DllCall("User32.dll\ScrollWindow", "Ptr", This.Parent.Hwnd, "Int", XN - XC, "Int", YN - YC, "Ptr", 0, "Ptr", 0)
Return True
}
; ===================================================================================================================
; SetMax Sets the width or height of the scrolling area.
; Parameters:
; SB - Scroll bar to set the value for:
; 1 = horizontal
; 2 = vertical
; Max - Width respectively height of the scrolling area in pixels
; Return values:
; On success: True
; On failure: False
; ===================================================================================================================
SetMax(SB, Max) {
; SB_HORZ = 0, SB_VERT = 1
SB--
If (SB != 0) && (SB != 1)
Return False
If (SB = 0)
This.MaxH := Max
Else
This.MaxV := Max
Return This.SetScrollInfo(SB, {Max: Max})
}
; ===================================================================================================================
; SetLine Sets the number of pixels to scroll by line.
; Parameters:
; SB - Scroll bar to set the value for:
; 1 = horizontal
; 2 = vertical
; Line - Number of pixels.
; Return values:
; On success: True
; On failure: False
; ===================================================================================================================
SetLine(SB, Line) {
; SB_HORZ = 0, SB_VERT = 1
SB--
If (SB != 0) && (SB != 1)
Return False
If (SB = 0)
This.LineH := Line
Else
This.LineV := Line
Return True
}
; ===================================================================================================================
; SetPage Sets the number of pixels to scroll by page.
; Parameters:
; SB - Scroll bar to set the value for:
; 1 = horizontal
; 2 = vertical
; Page - Number of pixels.
; Return values:
; On success: True
; On failure: False
; Remarks:
; If the ScrollGUI is resizable, the page size will be recalculated automatically while resizing.
; ===================================================================================================================
SetPage(SB, Page) {
; SB_HORZ = 0, SB_VERT = 1
SB--
If (SB != 0) && (SB != 1)
Return False
If (SB = 0)
This.PageH := Page
Else
This.PageV := Page
Return This.SetScrollInfo(SB, {Page: Page})
}
; ===================================================================================================================
GetScrollInfo(SB, &SI) {
SI := Buffer(28, 0) ; SCROLLINFO
NumPut("UInt", 28, "UInt", 0x17, SI) ; SIF_ALL = 0x17
Return DllCall("GetScrollInfo", "Ptr", This.Parent.Hwnd, "Int", SB, "Ptr", SI, "UInt")
}
; ===================================================================================================================
SetScrollInfo(SB, Values) {
Static SIF := {Max: 0x01, Page: 0x02, Pos: 0x04}
Static Off := {Max: 12, Page: 16, Pos: 20}
Mask := 0
SI := Buffer(28, 0) ; SCROLLINFO
NumPut("UInt", 28, SI)
For Key, Value In Values.OwnProps() {
If SIF.HasProp(Key) {
Mask |= SIF.%Key%
NumPut("UInt", Value, SI, Off.%Key%)
}
}
If (Mask) {
NumPut("UInt", Mask | 0x08, SI, 4) ; SIF_DISABLENOSCROLL = 0x08
Return DllCall("SetScrollInfo", "Ptr", This.Parent.Hwnd, "Int", SB, "Ptr", SI, "UInt", 1, "UInt")
}
Return False
}
; ===================================================================================================================
On_WM_Scroll(WP, LP, Msg, HWND) {
; WM_HSCROLL = 0x0114, WM_VSCROLL = 0x0115
If (HWND = This.Parent.Hwnd) && (((Msg = 0x0114) && This.ScrollH) || ((Msg = 0x0115) && This.ScrollV))
Return This.Scroll(WP, LP, Msg, HWND)
}
; ===================================================================================================================
Scroll(WP, LP, Msg, HWND) {
; WM_HSCROLL = 0x0114, WM_VSCROLL = 0x0115
Static SB_LINEMINUS := 0, SB_LINEPLUS := 1, SB_PAGEMINUS := 2, SB_PAGEPLUS := 3, SB_THUMBTRACK := 5
If (LP != 0)
Return
SB := (Msg = 0x0114 ? 0 : 1) ; SB_HORZ : SB_VERT
SC := WP & 0xFFFF
SD := (Msg = 0x0114 ? This.LineH : This.LineV)
SI := 0
If !This.GetScrollInfo(SB, &SI)
Return
PA := PN := NumGet(SI, 20, "Int")
Switch SC {
Case 0: PN := PA - SD ; SB_LINEMINUS
Case 1: PN := PA + SD ; SB_LINEPLUS
Case 2: PN := PA - NumGet(SI, 16, "UInt") ; SB_PAGEMINUS
Case 3: PN := PA + NumGet(SI, 16, "UInt") ; SB_PAGEPLUS
Case 5: PN := NumGet(SI, 24, "Int") ; SB_THUMBTRACK
}
If (PN = PA)
Return 0
This.SetScrollInfo(SB, {Pos: PN})
This.GetScrollInfo(SB, &SI)
PN := NumGet(SI, 20, "Int")
If (SB = 0)
This.PosH := PN
Else
This.PosV := PN
If (PA != PN) {
HS := (Msg = 0x0114) ? PA - PN : 0
VS := (Msg = 0x0115) ? PA - PN : 0
DllCall("ScrollWindow", "Ptr", HWND, "Int", HS, "Int", VS, "Ptr", 0, "Ptr", 0)
}
Return 0
}
; ===================================================================================================================
On_WM_Size(WP, LP, Msg, HWND) {
If (HWND = This.Parent.Hwnd) && ((WP = 0) || (WP = 2))
Return This.Size(LP & 0xFFFF, (LP >> 16) & 0xFFFF)
}
; ===================================================================================================================
Size(Width := 0, Height := 0) {
If (Width = 0) || (Height = 0)
WinGetClientPos( , , &Width, &Height, This.Parent.Hwnd)
SH := SV := 0
If This.ScrollH && (Width != This.Width) {
This.SetScrollInfo(0, {Page: Width + 1}),
This.Width := Width,
This.GetScrollInfo(0, &SI),
PosH := NumGet(SI, 20, "Int"),
SH := This.PosH - PosH,
This.PosH := PosH
}
If This.ScrollV && (Height != This.Height) {
This.SetScrollInfo(1, {Page: Height + 1}),
This.Height := Height,
This.GetScrollInfo(1, &SI),
PosV := NumGet(SI, 20, "Int"),
SV := This.PosV - PosV,
This.PosV := PosV
}
If (SH) || (SV)
DllCall("User32.dll\ScrollWindow", "Ptr", This.Parent.Hwnd, "Int", SH, "Int", SV, "Ptr", 0, "Ptr", 0)
Return 0
}
; ===================================================================================================================
On_WM_Wheel(WP, LP, Msg, HWND) {
; MK_SHIFT = 0x0004, WM_MOUSEWHEEL = 0x020A, WM_MOUSEHWHEEL = 0x020E, WM_NCHITTEST = 0x0084
If (HWND != This.Parent.Hwnd) {
If (WinActive("A") = This.Parent.Hwnd) {
OnBar := SendMessage(0x0084, 0, LP & 0xFFFFFFFF, This.Parent.Hwnd)
If (OnBar = 6) && This.WheelH ; HTHSCROLL = 6
Return This.Wheel(WP, LP, 0x020E, This.Parent.Hwnd)
If (OnBar = 7) && This.WheelV ; HTVSCROLL = 7
Return This.Wheel(WP, LP, 0x020A, This.Parent.Hwnd)
}
}
Else If ((Msg = 0x020E) && This.WheelH) ||
((Msg = 0x020A) && (This.WheelV || (This.WheelH && This.UseShift && (WP & 0x0004))))
Return This.Wheel(WP, LP, Msg, HWND)
}
; ===================================================================================================================
Wheel(WP, LP, Msg, HWND) {
; MK_SHIFT = 0x0004, WM_MOUSEWHEEL = 0x020A, WM_MOUSEHWHEEL = 0x020E, WM_HSCROLL = 0x0114, WM_VSCROLL = 0x0115
; SB_LINEMINUS = 0, SB_LINEPLUS = 1
If (Msg = 0x020A) && This.UseShift && (WP & 0x0004)
Msg := 0x020E
Msg := (Msg = 0x020A ? 0x0115 : 0x0114)
SB := ((WP >> 16) > 0x7FFF) || (WP < 0) ? 1 : 0
Return This.Scroll(SB, 0, Msg, HWND)
}
}[/code]
Minibeispiel:
[code]#Requires AutoHotkey v2.0.0
#Include Class_ScrollGUI.ahk
; -------------------------------------------------------------------------------------------------------------------
; ChildGUI 1
Lines := "1`n2`n3`n4`n5`n6`n7`n8"
ChildGui := Gui()
ChildGui.MarginX := 20
ChildGui.MarginY := 20
I := 0
ChildGui.AddText("w370 h20 0x200 Section", "Edit " . ++I)
ChildGui.AddEdit("xp y+0 wp r6")
Loop 4 {
ChildGui.AddText("xp y+0 wp h20 0x200", "Edit " . ++I)
ChildGui.AddEdit("xp y+0 wp r6", Lines)
}
ChildGui.AddText("ys wp h20 0x200", "Edit " . ++I)
ChildGui.AddEdit("xp y+0 wp r6")
Loop 4 {
ChildGui.AddText("xp y+0 wp h20 0x200", "Edit " . ++I)
ChildGui.AddEdit("xp y+0 wp r6", Lines)
}
; Create ScrollGUI1 with both horizontal and vertical scrollbars
SG1 := ScrollGUI(ChildGui, 300, 400, "+Resize +MinSize", , 3)
SG1.Parent.OnEvent("Close", Scroll1Close)
SG1.Parent.OnEvent("Escape", Scroll1Close)
; Show ScrollGUI1
SG1.Show("ScrollGUI1 Title", "")
Return
; ----------------------------------------------------------------------------------------------------------------------
Scroll1Close(*) {
ExitApp
}[/code]