1

Тема: AHK: ScrollBar

Приветствую. Недавно наткнулся на функции, позволяющие создавать скролл gui окна. Но в них присутствуют проблемы, которые я не знаю как решить.

1) Gui Edit поле для ввода по непонятным причинам растягивается на весь экран (Запустите ahk файл у себя, сразу увидите это)

2) При прокрутке gui файла происходят 2-3 секундные задержки, очень хотелось бы от них избавиться.

3) Не особо мешает, но всё же: Нельзя листать список через колёсико мышки.

Знатоки. Помогите пожалуйста) Может быть у вас есть более усовершенствованная версия такого скролл-бара, либо вы знаете как это можно исправить.. Буду благодарен!


code

+ открыть спойлер
#SingleInstance Force
#Persistent
#NoEnv

Loop 100
{
	Gui, Add, Edit, % "x40 y" A_Index*30, % A_Index
	Gui, Add, Edit, % "x90 y" A_Index*30, % A_Index
	Gui, Add, Edit, % "x140 y" A_Index*30, % A_Index
	Gui, Add, Edit, % "x190 y" A_Index*30, % A_Index
	Gui, Add, Edit, % "x240 y" A_Index*30, % A_Index
	Gui, Add, Text, % "x30 y" A_Index*30, % A_Index
	Gui, Add, Text, % "x80 y" A_Index*30, % A_Index
	Gui, Add, Text, % "x120 y" A_Index*30, % A_Index
	Gui, Add, Text, % "x170 y" A_Index*30, % A_Index
	Gui, Add, Text, % "x220 y" A_Index*30, % A_Index
}

ScrollSize := 5000
global WS_VSCROLL := 0x200000, SIZE_MINIMIZED := 1, SIF_RANGE := 0x1, SIF_PAGE := 0x2
 , SB_VERT := 1, SB_LINEUP := 0, SB_LINEDOWN := 1, WM_VSCROLL := 0x115
OnMessage(0x20A, Func("WM_MOUSEWHEEL").Bind(hGui))
OnMessage(0x5, Func("WM_SIZE").Bind(ScrollSize))
OnMessage(0x115, "WM_VSCROLL")
;UpdateScrollBar(hGui, ScrollSize, 400)
Gui, Show, w380 h700

WM_SIZE(ScrollSize, wp, lp, msg, hWnd)
{
   if (wp = SIZE_MINIMIZED)
      Return
   
   GuiWidth := lp & 0xFFFF, GuiHeight := lp >> 16
   Loop 20
      GuiControl, Move, Edit%A_Index%, % "w" GuiWidth - 20
   UpdateScrollBar(hWnd, ScrollSize, GuiHeight)
}

WM_MOUSEWHEEL(hWnd, wp)
{
   Loop 4
      WM_VSCROLL(wp>>16 & 0xFFFF < 0x7FFF ? SB_LINEUP : SB_LINEDOWN, 0, WM_VSCROLL, hWnd)
}

UpdateScrollBar(hWnd, ScrollHeight, GuiHeight)
{
   VarSetCapacity(si, 28, 0)
   NumPut(28, si) ; cbSize
   NumPut(SIF_RANGE | SIF_PAGE, si, 4)
   NumPut(ScrollHeight, si, 12) ; nMax
   NumPut(GuiHeight, si, 16) ; nPage
   DllCall("SetScrollInfo", Ptr, hWnd, UInt, SB_VERT, Ptr, &si, UInt, 1)
   
   GuiControlGet, Pos, %hWnd%: Pos, Edit1
   if (PosY = 10)
      Return
   
   top := PosY - 10
   GuiControlGet, Pos, %hWnd%: Pos, Edit20
   bottom := PosY + PosH + 10
   if (top < 0 && bottom < GuiHeight)
   {
      y := (a := Abs(top)) > (b := GuiHeight-bottom) ? b : a
      DllCall("ScrollWindow", Ptr, hWnd, Int, 0, Int, y, Ptr, 0, Ptr, 0)
   }
}

WM_VSCROLL(wParam, lParam, msg, hwnd)
{
   static SIF_ALL:=0x17, SCROLL_STEP:=10
   bar := msg=0x115 ; SB_HORZ=0, SB_VERT=1

   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)

   new_pos := NumGet(si, 20, "UInt") ; nPos

   action := wParam & 0xFFFF
   if action = 0 ; SB_LINEUP
     new_pos -= SCROLL_STEP
   else if action = 1 ; SB_LINEDOWN
     new_pos += SCROLL_STEP
   else if action = 2 ; SB_PAGEUP
     new_pos -= NumGet(rect, 12, "Int") - SCROLL_STEP
   else if action = 3 ; SB_PAGEDOWN
     new_pos += NumGet(rect, 12, "Int") - SCROLL_STEP
   else if (action = 5 || action = 4) ; SB_THUMBTRACK || SB_THUMBPOSITION
     new_pos := wParam>>16
   else if action = 6 ; SB_TOP
     new_pos := NumGet(si, 8, "Int") ; nMin
   else if action = 7 ; SB_BOTTOM
     new_pos := NumGet(si, 12, "Int") ; nMax
   else
     return

   min := NumGet(si, 8, "Int") ; nMin
   max := NumGet(si, 12, "Int") - NumGet(si, 16, "UInt") ; nMax-nPage
   new_pos := new_pos > max ? max : new_pos
   new_pos := new_pos < min ? min : new_pos

   old_pos := NumGet(si, 20, "Int") ; nPos

   y := old_pos-new_pos
   ; Scroll contents of window and invalidate uncovered area.
   DllCall("ScrollWindow", Ptr, hwnd, Int, 0, Int, y, UInt, 0, UInt, 0)

   ; Update scroll bar.
   NumPut(new_pos, si, 20, "Int") ; nPos
   DllCall("SetScrollInfo", Ptr, hwnd, Int, bar, Ptr, &si, Int, 1)
}

screenshots

+ открыть спойлер

https://i.imgur.com/0OfmgzL.png
https://i.imgur.com/bXTaKp8.png

2

Re: AHK: ScrollBar

kolotilov256 пишет:

Недавно наткнулся на функции, позволяющие создавать скролл gui окна.

Интересно, где вы на них наткнулись? Похоже на обрывок моего кода, который был применён к конкретному окну. Для скроллинга довольно проблематично написать универсальный вариант, в каждом случае нужно учитывать специфику расположения контролов.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

3

Re: AHK: ScrollBar

https://www.autohotkey.com/boards/viewt … amp;t=6316
По моему универсальный вариант.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

4

Re: AHK: ScrollBar

Не думаю.

just me пишет:

Creates a scrollable parent window for AHK Guis.

В чём же тут универсальность?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

5 (изменено: serzh82saratov, 2020-07-05 17:41:46)

Re: AHK: ScrollBar

В том что это окно можно легко добавить, особо ни во что не вникая.
А по твоему в чём должна заключаться универсальность в данном случае?


#SingleInstance force
#NoEnv 
SetBatchLines, -1

Gui, New, +hwndHGUI

Loop 100
{
	i := A_Index
	Loop 5
	{
		If A_Index = 1 
			Gui, Add, Text, xm y+10 w21 h21 0x201, % i  
		Else  
			Gui, Add, Text, x+10 w21 yp h21 0x201, % i 
		Gui, Add, Edit, x+10 yp w55 hp r1, % A_Index
	}
} 
; Create ScrollGUI1 with both horizontal and vertical scrollbars and mouse wheel capturing
SG1 := New ScrollGUI(HGUI, 0, 700, "+Resize +LabelGui1", 2, 2)
; Show ScrollGUI1
SG1.Show("ScrollGUI1 Title", "y0 xcenter")
Return
; ----------------------------------------------------------------------------------------------------------------------
Gui1Close:
Gui1Escape:
	ExitApp
; ----------------------------------------------------------------------------------------------------------------------
Gui1Size:
   If (A_EventInfo <> 1)
      SG1.AdjustToParent()
Return



; ======================================================================================================================
; Namepace:       ScrollGUI
; Function:       Create a scrollable GUI as a parent for GUI windows.
; Tested with:    AHK 1.1.19.02
; Tested on:      Win 8.1 (x64)
; Change log:     1.0.00.00/2015-02-06/just me        -  initial release on ahkscript.org
;                 1.0.01.00/2015-02-08/just me        -  bug fixes
;                 1.1.00.00/2015-02-09/just me        -  bug fixes and mouse wheel handling
; License:        The Unlicense -> http://unlicense.org
; ======================================================================================================================
Class ScrollGUI {
   Static Instances := []
   ; ===================================================================================================================
   ; __New          Creates a scrollable parent window (ScrollGUI) for the passed GUI.
   ; Parameters:
   ;    HGUI        -  HWND of the GUI 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 (doesn't really make sense).
   ;    Height      -  Height of the client area of the ScrollGUI.
   ;                   Pass 0 to set the client area to the height of the child GUI (doesn't really make sense).
   ;    ----------- Optional:
   ;    GuiOptions  -  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
   ;                   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
   ;                   Add 8 to require the Ctrl key as modifier for wheel messages which shall be processed by the
   ;                   ScrollGUI. Unmodified wheel messages will be passed to the child GUI in this case.
   ; Return values:
   ;    On failure:    False
   ; Remarks:
   ;    The rect of the child GUI is determined using the 'AutoSize' option of the 'Gui, Show' command, after
   ;    '-Caption' is applied to the child GUI.
   ;    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 captured to scroll the ScrollGUI.
   ;    You won't be able to use the wheel to scroll child GUI controls unless Ctrl is required as modifier.
   ; ===================================================================================================================
   __New(HGUI, Width, Height, GuiOptions := "", ScrollBars := 3, Wheel := 0) {
      Static SB_HORZ := 0, SB_VERT = 1
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
      Static WM_MOUSEWHEEL := 0x020A, WM_MOUSEHWHEEL := 0x020E
      Static WS_HSCROLL := "0x100000", WS_VSCROLL := "0x200000"
      RequireCtrl := False
      If (Wheel & 8) {
         RequireCtrl := True
         Wheel &= (8 - 1)
      }
      If ((ScrollBars <> 1) && (ScrollBars <> 2) && (ScrollBars <> 3))
      || ((Wheel <> 0) && (Wheel <> 1) && (Wheel <> 2) && (Wheel <> 3) && (Wheel <> 4))
         Return False
      If !DllCall("User32.dll\IsWindow", "Ptr", HGUI, "UInt")
         Return False
      VarSetCapacity(RC, 16, 0)
      ; Child GUI
      If !This.AutoSize(HGUI, GuiW, GuiH)
         Return False
      Gui, %HGUI%:-Caption -Resize
      Gui, %HGUI%:Show, w%GuiW% h%GuiH% Hide
      MaxH := GuiW
      MaxV := GuiH
      ; Gui, %HGUI%:Show, AutoSize Hide
      ; DllCall("User32.dll\GetWindowRect", "Ptr", HGUI, "Ptr", &RC)
      ; MaxH := NumGet(RC, 8, "Int") - NumGet(RC, 0, "Int")
      ; MaxV := Numget(RC, 12, "Int") - NumGet(RC, 4, "Int")
      LineH := Ceil(MaxH / 20)
      LineV := Ceil(MaxV / 20)
      ; ScrollGUI
      If (Width = 0)
         Width := MaxH
      If (Height = 0)
         Height := MaxV
      MX := MY := Styles := ""
      If (ScrollBars & 1) {
         MX := MaxH + 1
         Styles .= " +" . WS_HSCROLL
      }
      If (ScrollBars & 2) {
         Styles .= " +" . WS_VSCROLL
         MY := MaxV + 1
      }
      Gui, New, %GuiOptions% %Styles% +hwndHWND
      Gui, %HWND%:Show, w%Width% h%Height% Hide
      If (MX <> "") || (MY <> "")
         Gui, %HWND%:+MaxSize%MX%x%MY%
      DllCall("User32.dll\GetClientRect", "Ptr", HWND, "Ptr", &RC)
      PageH := NumGet(RC, 8, "Int") + 1
      PageV := Numget(RC, 12, "Int") + 1
      ; Instance variables
      This.HWND := HWND
      This.HGUI := HGUI
      This.Width := Width
      This.Height := Height
      This.RequireCtrl := RequireCtrl
      This.UseShift := False
      If (ScrollBars & 1) {
         This.SetScrollInfo(SB_HORZ, {Max: MaxH, Page: PageH, Pos: 0})
         OnMessage(WM_HSCROLL, "ScrollGUI.On_WM_Scroll")
         If (Wheel & 1)
            OnMessage(WM_MOUSEHWHEEL, "ScrollGUI.On_WM_Wheel")
         Else If (Wheel & 4) {
            OnMessage(WM_MOUSEWHEEL, "ScrollGUI.On_WM_Wheel")
            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 (ScrollBars & 2) {
         This.SetScrollInfo(SB_VERT, {Max: MaxV, Page: PageV, Pos: 0})
         OnMessage(WM_VSCROLL, "ScrollGUI.On_WM_Scroll")
         If (Wheel & 6)
            OnMessage(WM_MOUSEWHEEL, "ScrollGUI.On_WM_Wheel")
         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
      Gui, %HGUI%:+parent%HWND%
      Gui, %HGUI%:Show, x0 y0
      This.Instances[HWND] := &This
   }
   ; ===================================================================================================================
   ; __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")
      W := This.Width
      H := This.Height
      Gui, % This.HWND . ":Show", %ShowOptions% w%W% h%H%, %Title%
      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.Instances.HasKey(This.HWND) {
         Gui, % This.HWND . ":Destroy"
         This.Instances.Remove(This.HWND, "")
         Return True
      }
   }
   ; ===================================================================================================================
   ; AdjustToParent Adjust the scroll bars to the new parent dimensions.
   ; Parameters:
   ;    Width       -  New width of the client area of the ScrollGUI in pixels.
   ;                   Default: 0 -> current width
   ;    Height      -  New height of the client area of the ScrollGUI in pixels.
   ;                   Default: 0 -> current height
   ; Return values:
   ;    On success: True
   ;    On failure: False
   ; Remarks:
   ;    Call this method whenever the dimensions of the parent GUI have changed, e.g. after the GUI was resized,
   ;    restored or maximized. If either Width or Height is zero, both values will be set to the current dimensions.
   ; ===================================================================================================================
   AdjustToParent(Width := 0, Height := 0) {
      If (Width = 0) || (Height = 0) {
         VarSetCapacity(RC, 16, 0)
         DllCall("User32.dll\GetClientRect", "Ptr", This.HWND, "Ptr", &RC)
         Width := NumGet(RC, 8, "Int")
         Height := Numget(RC, 12, "Int")
      }
      SH := SV := 0
      If This.ScrollH {
         If (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 {
         If (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.HWND, "Int", SH, "Int", SV, "Ptr", 0, "Ptr", 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 client area of the child GUI is determined using the 'AutoSize' option of a 'Gui, Show' command.
   ; ===================================================================================================================
   AdjustToChild() {
      Static WS_HSCROLL := 0x100000, WS_VSCROLL := 0x200000
      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
      MX := This.ScrollH ? MaxH + 1 : ""
      MY := This.ScrollV ? MaxV + 1 : ""
      If (MX <> "") || (MY <> "") {
         Gui, % This.HWND . ":+MaxSize" . MX . "x" . MY
         W := ((MX <> "") && (MX < PrevW)) ? "w" . MX : ""
         H := ((MY <> "") && (MY < PrevH)) ? "h" . MY : ""
         If (W || H ) {
            Gui, % This.HWND . ":Show", %W% %H%
            If (W) {
               This.Width := MX
               This.SetScrollInfo(0, {Page: MX + 1})
            }
            If (H) {
               This.Height := MY
               This.SetScrollInfo(1, {Page: MY + 1})
            }
         }
      }
      ; Gui, % This.HGUI . ":Show", x%XC% y%YC% AutoSize
      ; DllCall("User32.dll\GetWindowRect", "Ptr", This.HGUI, "Ptr", &RC)
      ; MaxH := NumGet(RC, 8, "Int") - NumGet(RC, 0, "Int")
      ; MaxV := Numget(RC, 12, "Int") - NumGet(RC, 4, "Int")
      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.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) {
      Static SB_HORZ := 0, SB_VERT = 1
      SB--
      If (SB <> SB_HORZ) && (SB <> SB_VERT)
         Return False
      If (SB = SB_HORZ)
         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) {
      Static SB_HORZ := 0, SB_VERT = 1
      SB--
      If (SB <> SB_HORZ) && (SB <> SB_VERT)
         Return False
      If (SB = SB_HORZ)
         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) {
      Static SB_HORZ := 0, SB_VERT = 1
      SB--
      If (SB <> SB_HORZ) && (SB <> SB_VERT)
         Return False
      If (SB = SB_HORZ)
         This.PageH := Page
      Else
         This.PageV := Page
      Return This.SetScrollInfo(SB, {Page: Page})
   }
   ; ===================================================================================================================
   ; Methods for internal or system use!!!
   ; ===================================================================================================================
   AutoSize(HGUI, ByRef Width, ByRef Height) {
      DHW := A_DetectHiddenWindows
      DetectHiddenWindows, On
      VarSetCapacity(RECT, 16, 0)
      Width := Height := 0
      HWND := HGUI
      CMD := 5 ; GW_CHILD
      L := T := R := B := LH := TH := ""
      While (HWND := DllCall("GetWindow", "Ptr", HWND, "UInt", CMD, "UPtr")) && (CMD := 2) {
         WinGetPos, X, Y, W, H, ahk_id %HWND%
         W += X, H += Y
         WinGet, Styles, Style, ahk_id %HWND%
         If (Styles & 0x10000000) { ; WS_VISIBLE
            If (L = "") || (X < L)
               L := X
            If (T = "") || (Y < T)
               T := Y
            If (R = "") || (W > R)
               R := W
            If (B = "") || (H > B)
               B := H
         }
         Else {
            If (LH = "") || (X < LH)
               LH := X
            If (TH = "") || (Y < TH)
               TH := Y
         }
      }
      DetectHiddenWindows, %DHW%
      If (LH <> "") {
         VarSetCapacity(POINT, 8, 0)
         NumPut(LH, POINT, 0, "Int")
         DllCall("ScreenToClient", "Ptr", HGUI, "Ptr", &POINT)
         LH := NumGet(POINT, 0, "Int")
      }
      If (TH <> "") {
         VarSetCapacity(POINT, 8, 0)
         NumPut(TH, POINT, 4, "Int")
         DllCall("ScreenToClient", "Ptr", HGUI, "Ptr", &POINT)
         TH := NumGet(POINT, 4, "Int")
      }
      NumPut(L, RECT, 0, "Int"), NumPut(T, RECT,  4, "Int")
      NumPut(R, RECT, 8, "Int"), NumPut(B, RECT, 12, "Int")
      DllCall("MapWindowPoints", "Ptr", 0, "Ptr", HGUI, "Ptr", &RECT, "UInt", 2)
      Width := NumGet(RECT, 8, "Int") + (LH <> "" ? LH : NumGet(RECT, 0, "Int"))
      Height := NumGet(RECT, 12, "Int") + (TH <> "" ? TH : NumGet(RECT,  4, "Int"))
      Return True
   }
   ; ===================================================================================================================
   GetScrollInfo(SB, ByRef SI) {
      Static SI_SIZE := 28
      Static SIF_ALL := 0x17
      VarSetCapacity(SI, SI_SIZE, 0)
      NumPut(SI_SIZE, SI, 0, "UInt")
      NumPut(SIF_ALL, SI, 4, "UInt")
      Return DllCall("User32.dll\GetScrollInfo", "Ptr", This.HWND, "Int", SB, "Ptr", &SI, "UInt")
   }
   ; ===================================================================================================================
   SetScrollInfo(SB, Values) {
      Static SI_SIZE := 28
      Static SIF := {Max: 0x01, Page: 0x02, Pos: 0x04}
      Static Off := {Max: 12, Page: 16, Pos: 20}
      Static SIF_DISABLENOSCROLL := 0x08
      Mask := 0
      VarSetCapacity(SI, SI_SIZE, 0)
      NumPut(SI_SIZE, SI, 0, "UInt")
      For Key, Value In Values {
         If SIF.HasKey(Key) {
            Mask |= SIF[Key]
            NumPut(Value, SI, Off[Key], "UInt")
         }
      }
      If (Mask) {
         NumPut(Mask | SIF_DISABLENOSCROLL, SI, 4, "UInt")
         Return DllCall("User32.dll\SetScrollInfo", "Ptr", This.HWND, "Int", SB, "Ptr", &SI, "UInt", 1, "UInt")
      }
      Return False
   }
   ; ===================================================================================================================
   On_WM_Scroll(LP, Msg, HWND) {
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
      If ScrollGUI.Instances.HasKey(HWND) {
         Instance := Object(ScrollGUI.Instances[HWND])
         If ((Msg = WM_HSCROLL) && Instance.ScrollH)
         || ((Msg = WM_VSCROLL) && Instance.ScrollV)
            Return Instance.Scroll(This, LP, Msg, HWND)
      }
   }
   ; ===================================================================================================================
   Scroll(WP, LP, Msg, HWND) {
      Static SB_LINEMINUS := 0, SB_LINEPLUS := 1, SB_PAGEMINUS := 2, SB_PAGEPLUS := 3, SB_THUMBTRACK := 5
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
      If (LP <> 0)
         Return
      SB := (Msg = WM_HSCROLL ? 0 : 1) ; SB_HORZ : SB_VERT
      SC := WP & 0xFFFF
      SD := (Msg = WM_HSCROLL ? This.LineH : This.LineV)
      SI := 0
      If !This.GetScrollInfo(SB, SI)
         Return
      PA := PN := NumGet(SI, 20, "Int")
      If (SC = SB_LINEMINUS)
         PN := PA - SD
      Else If (SC = SB_LINEPLUS)
         PN := PA + SD
      Else If (SC = SB_PAGEMINUS)
         PN := PA - NumGet(SI, 16, "UInt")
      Else If (SC = SB_PAGEPLUS)
         PN := PA + NumGet(SI, 16, "UInt")
      Else If (SC = SB_THUMBTRACK)
         PN := NumGet(SI, 24, "Int")
      If (PA = PN)
         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 := VS := 0
         If (Msg = WM_HSCROLL)
            HS := PA - PN
         Else
            VS := PA - PN
         DllCall("User32.dll\ScrollWindow", "Ptr", This.HWND, "Int", HS, "Int", VS, "Ptr", 0, "Ptr", 0)
      }
      Return 0
   }
   ; ===================================================================================================================
   On_WM_Wheel(LP, Msg, H) {
      Static MK_CONTROL := 0x0008
      Static MK_SHIFT := 0x0004
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
      Static WM_MOUSEWHEEL := 0x020A, WM_MOUSEHWHEEL := 0x020E
      HWND := WinExist("A")
      If ScrollGUI.Instances.HasKey(HWND) {
         Instance := Object(ScrollGUI.Instances[HWND])
         If (Instance.RequireCtrl && (This & MK_CONTROL)) || (!Instance.RequireCtrl && !(This & MK_CONTROL))
            If (Instance.WheelH && (Msg = WM_MOUSEHWHEEL))
            || (Instance.WheelH && ((Msg = WM_MOUSEWHEEL) && Instance.UseShift && (This & MK_SHIFT)))
            || (Instance.WheelV && (Msg = WM_MOUSEWHEEL))
               Return Instance.Wheel(This, LP, Msg, HWND)
      }
   }
   ; ===================================================================================================================
   Wheel(WP, LP, Msg, H) {
      Static MK_SHIFT := 0x0004
      Static SB_LINEMINUS := 0, SB_LINEPLUS := 1
      Static WM_MOUSEWHEEL := 0x020A, WM_MOUSEHWHEEL := 0x020E
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
      If (Msg = WM_MOUSEWHEEL) && (WP & MK_SHIFT) && This.UseShift
         Msg := WM_MOUSEHWHEEL
      MSG := (Msg = WM_MOUSEWHEEL ? WM_VSCROLL : WM_HSCROLL)
      SB := ((WP >> 16) > 0x7FFF) || (WP < 0) ? SB_LINEPLUS : SB_LINEMINUS
      Return This.Scroll(SB, 0, MSG, H)
   }
}
 
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

6

Re: AHK: ScrollBar

Ну тут какое-то дополнительное окно создаётся, которое в принципе не нужно, и в некоторых случаях может внести путаницу, если «ни во что не вникать». Универсальность — это просто скармливаешь хендл любого окна, и в нём появляется скроллбар.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

7

Re: AHK: ScrollBar

Пример неуниверсальности. Хочу сделать скроллинг в дочернем окне:


#SingleInstance force
#NoEnv 
SetBatchLines, -1

Gui, New, +hwndhParentGUI
Gui, Color, Red
Gui, New, +hwndhGui +Parent%hParentGUI%

Loop 100
{
   i := A_Index
   Loop 5
   {
      If A_Index = 1 
         Gui, Add, Text, xm y+10 w22 0x201, % i  
      Else  
         Gui, Add, Text, x+10 w22 yp 0x201, % i 
      Gui, Add, Edit, x+10 yp w55 hp r1, % i
   }
} 
; Create ScrollGUI1 with both horizontal and vertical scrollbars and mouse wheel capturing
SG1 := New ScrollGUI(HGUI, 0, 700, "", 2, 2)
; Show ScrollGUI1
SG1.Show("ScrollGUI1 Title", "y10 w500 x10 h500 NA")
Gui, %hParentGui%: Show, w520 h520
Return




; ======================================================================================================================
; Namepace:       ScrollGUI
; Function:       Create a scrollable GUI as a parent for GUI windows.
; Tested with:    AHK 1.1.19.02
; Tested on:      Win 8.1 (x64)
; Change log:     1.0.00.00/2015-02-06/just me        -  initial release on ahkscript.org
;                 1.0.01.00/2015-02-08/just me        -  bug fixes
;                 1.1.00.00/2015-02-09/just me        -  bug fixes and mouse wheel handling
; License:        The Unlicense -> http://unlicense.org
; ======================================================================================================================
Class ScrollGUI {
   Static Instances := []
   ; ===================================================================================================================
   ; __New          Creates a scrollable parent window (ScrollGUI) for the passed GUI.
   ; Parameters:
   ;    HGUI        -  HWND of the GUI 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 (doesn't really make sense).
   ;    Height      -  Height of the client area of the ScrollGUI.
   ;                   Pass 0 to set the client area to the height of the child GUI (doesn't really make sense).
   ;    ----------- Optional:
   ;    GuiOptions  -  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
   ;                   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
   ;                   Add 8 to require the Ctrl key as modifier for wheel messages which shall be processed by the
   ;                   ScrollGUI. Unmodified wheel messages will be passed to the child GUI in this case.
   ; Return values:
   ;    On failure:    False
   ; Remarks:
   ;    The rect of the child GUI is determined using the 'AutoSize' option of the 'Gui, Show' command, after
   ;    '-Caption' is applied to the child GUI.
   ;    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 captured to scroll the ScrollGUI.
   ;    You won't be able to use the wheel to scroll child GUI controls unless Ctrl is required as modifier.
   ; ===================================================================================================================
   __New(HGUI, Width, Height, GuiOptions := "", ScrollBars := 3, Wheel := 0) {
      Static SB_HORZ := 0, SB_VERT = 1
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
      Static WM_MOUSEWHEEL := 0x020A, WM_MOUSEHWHEEL := 0x020E
      Static WS_HSCROLL := "0x100000", WS_VSCROLL := "0x200000"
      RequireCtrl := False
      If (Wheel & 8) {
         RequireCtrl := True
         Wheel &= (8 - 1)
      }
      If ((ScrollBars <> 1) && (ScrollBars <> 2) && (ScrollBars <> 3))
      || ((Wheel <> 0) && (Wheel <> 1) && (Wheel <> 2) && (Wheel <> 3) && (Wheel <> 4))
         Return False
      If !DllCall("User32.dll\IsWindow", "Ptr", HGUI, "UInt")
         Return False
      VarSetCapacity(RC, 16, 0)
      ; Child GUI
      If !This.AutoSize(HGUI, GuiW, GuiH)
         Return False
      Gui, %HGUI%:-Caption -Resize
      Gui, %HGUI%:Show, w%GuiW% h%GuiH% Hide
      MaxH := GuiW
      MaxV := GuiH
      ; Gui, %HGUI%:Show, AutoSize Hide
      ; DllCall("User32.dll\GetWindowRect", "Ptr", HGUI, "Ptr", &RC)
      ; MaxH := NumGet(RC, 8, "Int") - NumGet(RC, 0, "Int")
      ; MaxV := Numget(RC, 12, "Int") - NumGet(RC, 4, "Int")
      LineH := Ceil(MaxH / 20)
      LineV := Ceil(MaxV / 20)
      ; ScrollGUI
      If (Width = 0)
         Width := MaxH
      If (Height = 0)
         Height := MaxV
      MX := MY := Styles := ""
      If (ScrollBars & 1) {
         MX := MaxH + 1
         Styles .= " +" . WS_HSCROLL
      }
      If (ScrollBars & 2) {
         Styles .= " +" . WS_VSCROLL
         MY := MaxV + 1
      }
      Gui, New, %GuiOptions% %Styles% +hwndHWND
      Gui, %HWND%:Show, w%Width% h%Height% Hide
      If (MX <> "") || (MY <> "")
         Gui, %HWND%:+MaxSize%MX%x%MY%
      DllCall("User32.dll\GetClientRect", "Ptr", HWND, "Ptr", &RC)
      PageH := NumGet(RC, 8, "Int") + 1
      PageV := Numget(RC, 12, "Int") + 1
      ; Instance variables
      This.HWND := HWND
      This.HGUI := HGUI
      This.Width := Width
      This.Height := Height
      This.RequireCtrl := RequireCtrl
      This.UseShift := False
      If (ScrollBars & 1) {
         This.SetScrollInfo(SB_HORZ, {Max: MaxH, Page: PageH, Pos: 0})
         OnMessage(WM_HSCROLL, "ScrollGUI.On_WM_Scroll")
         If (Wheel & 1)
            OnMessage(WM_MOUSEHWHEEL, "ScrollGUI.On_WM_Wheel")
         Else If (Wheel & 4) {
            OnMessage(WM_MOUSEWHEEL, "ScrollGUI.On_WM_Wheel")
            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 (ScrollBars & 2) {
         This.SetScrollInfo(SB_VERT, {Max: MaxV, Page: PageV, Pos: 0})
         OnMessage(WM_VSCROLL, "ScrollGUI.On_WM_Scroll")
         If (Wheel & 6)
            OnMessage(WM_MOUSEWHEEL, "ScrollGUI.On_WM_Wheel")
         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
      Gui, %HGUI%:+parent%HWND%
      Gui, %HGUI%:Show, x0 y0
      This.Instances[HWND] := &This
   }
   ; ===================================================================================================================
   ; __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")
      W := This.Width
      H := This.Height
      Gui, % This.HWND . ":Show", %ShowOptions% w%W% h%H%, %Title%
      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.Instances.HasKey(This.HWND) {
         Gui, % This.HWND . ":Destroy"
         This.Instances.Remove(This.HWND, "")
         Return True
      }
   }
   ; ===================================================================================================================
   ; AdjustToParent Adjust the scroll bars to the new parent dimensions.
   ; Parameters:
   ;    Width       -  New width of the client area of the ScrollGUI in pixels.
   ;                   Default: 0 -> current width
   ;    Height      -  New height of the client area of the ScrollGUI in pixels.
   ;                   Default: 0 -> current height
   ; Return values:
   ;    On success: True
   ;    On failure: False
   ; Remarks:
   ;    Call this method whenever the dimensions of the parent GUI have changed, e.g. after the GUI was resized,
   ;    restored or maximized. If either Width or Height is zero, both values will be set to the current dimensions.
   ; ===================================================================================================================
   AdjustToParent(Width := 0, Height := 0) {
      If (Width = 0) || (Height = 0) {
         VarSetCapacity(RC, 16, 0)
         DllCall("User32.dll\GetClientRect", "Ptr", This.HWND, "Ptr", &RC)
         Width := NumGet(RC, 8, "Int")
         Height := Numget(RC, 12, "Int")
      }
      SH := SV := 0
      If This.ScrollH {
         If (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 {
         If (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.HWND, "Int", SH, "Int", SV, "Ptr", 0, "Ptr", 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 client area of the child GUI is determined using the 'AutoSize' option of a 'Gui, Show' command.
   ; ===================================================================================================================
   AdjustToChild() {
      Static WS_HSCROLL := 0x100000, WS_VSCROLL := 0x200000
      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
      MX := This.ScrollH ? MaxH + 1 : ""
      MY := This.ScrollV ? MaxV + 1 : ""
      If (MX <> "") || (MY <> "") {
         Gui, % This.HWND . ":+MaxSize" . MX . "x" . MY
         W := ((MX <> "") && (MX < PrevW)) ? "w" . MX : ""
         H := ((MY <> "") && (MY < PrevH)) ? "h" . MY : ""
         If (W || H ) {
            Gui, % This.HWND . ":Show", %W% %H%
            If (W) {
               This.Width := MX
               This.SetScrollInfo(0, {Page: MX + 1})
            }
            If (H) {
               This.Height := MY
               This.SetScrollInfo(1, {Page: MY + 1})
            }
         }
      }
      ; Gui, % This.HGUI . ":Show", x%XC% y%YC% AutoSize
      ; DllCall("User32.dll\GetWindowRect", "Ptr", This.HGUI, "Ptr", &RC)
      ; MaxH := NumGet(RC, 8, "Int") - NumGet(RC, 0, "Int")
      ; MaxV := Numget(RC, 12, "Int") - NumGet(RC, 4, "Int")
      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.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) {
      Static SB_HORZ := 0, SB_VERT = 1
      SB--
      If (SB <> SB_HORZ) && (SB <> SB_VERT)
         Return False
      If (SB = SB_HORZ)
         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) {
      Static SB_HORZ := 0, SB_VERT = 1
      SB--
      If (SB <> SB_HORZ) && (SB <> SB_VERT)
         Return False
      If (SB = SB_HORZ)
         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) {
      Static SB_HORZ := 0, SB_VERT = 1
      SB--
      If (SB <> SB_HORZ) && (SB <> SB_VERT)
         Return False
      If (SB = SB_HORZ)
         This.PageH := Page
      Else
         This.PageV := Page
      Return This.SetScrollInfo(SB, {Page: Page})
   }
   ; ===================================================================================================================
   ; Methods for internal or system use!!!
   ; ===================================================================================================================
   AutoSize(HGUI, ByRef Width, ByRef Height) {
      DHW := A_DetectHiddenWindows
      DetectHiddenWindows, On
      VarSetCapacity(RECT, 16, 0)
      Width := Height := 0
      HWND := HGUI
      CMD := 5 ; GW_CHILD
      L := T := R := B := LH := TH := ""
      While (HWND := DllCall("GetWindow", "Ptr", HWND, "UInt", CMD, "UPtr")) && (CMD := 2) {
         WinGetPos, X, Y, W, H, ahk_id %HWND%
         W += X, H += Y
         WinGet, Styles, Style, ahk_id %HWND%
         If (Styles & 0x10000000) { ; WS_VISIBLE
            If (L = "") || (X < L)
               L := X
            If (T = "") || (Y < T)
               T := Y
            If (R = "") || (W > R)
               R := W
            If (B = "") || (H > B)
               B := H
         }
         Else {
            If (LH = "") || (X < LH)
               LH := X
            If (TH = "") || (Y < TH)
               TH := Y
         }
      }
      DetectHiddenWindows, %DHW%
      If (LH <> "") {
         VarSetCapacity(POINT, 8, 0)
         NumPut(LH, POINT, 0, "Int")
         DllCall("ScreenToClient", "Ptr", HGUI, "Ptr", &POINT)
         LH := NumGet(POINT, 0, "Int")
      }
      If (TH <> "") {
         VarSetCapacity(POINT, 8, 0)
         NumPut(TH, POINT, 4, "Int")
         DllCall("ScreenToClient", "Ptr", HGUI, "Ptr", &POINT)
         TH := NumGet(POINT, 4, "Int")
      }
      NumPut(L, RECT, 0, "Int"), NumPut(T, RECT,  4, "Int")
      NumPut(R, RECT, 8, "Int"), NumPut(B, RECT, 12, "Int")
      DllCall("MapWindowPoints", "Ptr", 0, "Ptr", HGUI, "Ptr", &RECT, "UInt", 2)
      Width := NumGet(RECT, 8, "Int") + (LH <> "" ? LH : NumGet(RECT, 0, "Int"))
      Height := NumGet(RECT, 12, "Int") + (TH <> "" ? TH : NumGet(RECT,  4, "Int"))
      Return True
   }
   ; ===================================================================================================================
   GetScrollInfo(SB, ByRef SI) {
      Static SI_SIZE := 28
      Static SIF_ALL := 0x17
      VarSetCapacity(SI, SI_SIZE, 0)
      NumPut(SI_SIZE, SI, 0, "UInt")
      NumPut(SIF_ALL, SI, 4, "UInt")
      Return DllCall("User32.dll\GetScrollInfo", "Ptr", This.HWND, "Int", SB, "Ptr", &SI, "UInt")
   }
   ; ===================================================================================================================
   SetScrollInfo(SB, Values) {
      Static SI_SIZE := 28
      Static SIF := {Max: 0x01, Page: 0x02, Pos: 0x04}
      Static Off := {Max: 12, Page: 16, Pos: 20}
      Static SIF_DISABLENOSCROLL := 0x08
      Mask := 0
      VarSetCapacity(SI, SI_SIZE, 0)
      NumPut(SI_SIZE, SI, 0, "UInt")
      For Key, Value In Values {
         If SIF.HasKey(Key) {
            Mask |= SIF[Key]
            NumPut(Value, SI, Off[Key], "UInt")
         }
      }
      If (Mask) {
         NumPut(Mask | SIF_DISABLENOSCROLL, SI, 4, "UInt")
         Return DllCall("User32.dll\SetScrollInfo", "Ptr", This.HWND, "Int", SB, "Ptr", &SI, "UInt", 1, "UInt")
      }
      Return False
   }
   ; ===================================================================================================================
   On_WM_Scroll(LP, Msg, HWND) {
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
      If ScrollGUI.Instances.HasKey(HWND) {
         Instance := Object(ScrollGUI.Instances[HWND])
         If ((Msg = WM_HSCROLL) && Instance.ScrollH)
         || ((Msg = WM_VSCROLL) && Instance.ScrollV)
            Return Instance.Scroll(This, LP, Msg, HWND)
      }
   }
   ; ===================================================================================================================
   Scroll(WP, LP, Msg, HWND) {
      Static SB_LINEMINUS := 0, SB_LINEPLUS := 1, SB_PAGEMINUS := 2, SB_PAGEPLUS := 3, SB_THUMBTRACK := 5
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
      If (LP <> 0)
         Return
      SB := (Msg = WM_HSCROLL ? 0 : 1) ; SB_HORZ : SB_VERT
      SC := WP & 0xFFFF
      SD := (Msg = WM_HSCROLL ? This.LineH : This.LineV)
      SI := 0
      If !This.GetScrollInfo(SB, SI)
         Return
      PA := PN := NumGet(SI, 20, "Int")
      If (SC = SB_LINEMINUS)
         PN := PA - SD
      Else If (SC = SB_LINEPLUS)
         PN := PA + SD
      Else If (SC = SB_PAGEMINUS)
         PN := PA - NumGet(SI, 16, "UInt")
      Else If (SC = SB_PAGEPLUS)
         PN := PA + NumGet(SI, 16, "UInt")
      Else If (SC = SB_THUMBTRACK)
         PN := NumGet(SI, 24, "Int")
      If (PA = PN)
         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 := VS := 0
         If (Msg = WM_HSCROLL)
            HS := PA - PN
         Else
            VS := PA - PN
         DllCall("User32.dll\ScrollWindow", "Ptr", This.HWND, "Int", HS, "Int", VS, "Ptr", 0, "Ptr", 0)
      }
      Return 0
   }
   ; ===================================================================================================================
   On_WM_Wheel(LP, Msg, H) {
      Static MK_CONTROL := 0x0008
      Static MK_SHIFT := 0x0004
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
      Static WM_MOUSEWHEEL := 0x020A, WM_MOUSEHWHEEL := 0x020E
      HWND := WinExist("A")
      If ScrollGUI.Instances.HasKey(HWND) {
         Instance := Object(ScrollGUI.Instances[HWND])
         If (Instance.RequireCtrl && (This & MK_CONTROL)) || (!Instance.RequireCtrl && !(This & MK_CONTROL))
            If (Instance.WheelH && (Msg = WM_MOUSEHWHEEL))
            || (Instance.WheelH && ((Msg = WM_MOUSEWHEEL) && Instance.UseShift && (This & MK_SHIFT)))
            || (Instance.WheelV && (Msg = WM_MOUSEWHEEL))
               Return Instance.Wheel(This, LP, Msg, HWND)
      }
   }
   ; ===================================================================================================================
   Wheel(WP, LP, Msg, H) {
      Static MK_SHIFT := 0x0004
      Static SB_LINEMINUS := 0, SB_LINEPLUS := 1
      Static WM_MOUSEWHEEL := 0x020A, WM_MOUSEHWHEEL := 0x020E
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
      If (Msg = WM_MOUSEWHEEL) && (WP & MK_SHIFT) && This.UseShift
         Msg := WM_MOUSEHWHEEL
      MSG := (Msg = WM_MOUSEWHEEL ? WM_VSCROLL : WM_HSCROLL)
      SB := ((WP >> 16) > 0x7FFF) || (WP < 0) ? SB_LINEPLUS : SB_LINEMINUS
      Return This.Scroll(SB, 0, MSG, H)
   }
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

8

Re: AHK: ScrollBar

teadrinker пишет:

Универсальность — это просто скармливаешь хендл любого окна, и в нём появляется скроллбар.

Ну какие то параметры почти всегда требуются, тем более в случаях универсальности.

teadrinker пишет:

тут какое-то дополнительное окно создаётся

Согласен, я не вникал, но думаю этот класс неплохая база для допиливания.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

9

Re: AHK: ScrollBar

Да не, сам принцип не очень. Я подумал, можно сделать наверно что-то такое, если перед применением класса уже установить стиль WM_VSCROLL и/или WM_HSCROLL.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

10

Re: AHK: ScrollBar

teadrinker пишет:

перед применением класса уже установить стиль WM_VSCROLL и/или WM_HSCROLL.

Это ведь можно и в __New сделать.

teadrinker пишет:

Да не, сам принцип не очень.

А зачем по твоему автор мог добавить дополнительное окно, без которого на первый взгляд можно обойтись?

На скорую руку:



#SingleInstance force
#NoEnv 
SetBatchLines, -1

Gui, New, +hwndhParentGUI
Gui, Color, Red
Gui, New, +hwndhGui +Parent%hParentGUI% -Caption -Resize

Loop 10
{
   i := A_Index
   Loop 5
   {
      If A_Index = 1 
         Gui, Add, Text, xm y+10 w22 0x201, % i  
      Else  
         Gui, Add, Text, x+10 w22 yp 0x201, % i 
      Gui, Add, Edit, x+10 yp w55 hp r1, % i
   }
} 
; Create ScrollGUI1 with both horizontal and vertical scrollbars and mouse wheel capturing
SG1 := New ScrollGUI(HGUI, 0, 200, "", 2, 2)
; Show ScrollGUI1
SG1.Show("ScrollGUI1 Title", "x0 y0 w503 h300 NA")
Gui, %hParentGui%: Show, w520 h500
Return




; ======================================================================================================================
; Namepace:       ScrollGUI
; Function:       Create a scrollable GUI as a parent for GUI windows.
; Tested with:    AHK 1.1.19.02
; Tested on:      Win 8.1 (x64)
; Change log:     1.0.00.00/2015-02-06/just me        -  initial release on ahkscript.org
;                 1.0.01.00/2015-02-08/just me        -  bug fixes
;                 1.1.00.00/2015-02-09/just me        -  bug fixes and mouse wheel handling
; License:        The Unlicense -> http://unlicense.org
; ======================================================================================================================
Class ScrollGUI {
   Static Instances := []
   ; ===================================================================================================================
   ; __New          Creates a scrollable parent window (ScrollGUI) for the passed GUI.
   ; Parameters:
   ;    HGUI        -  HWND of the GUI 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 (doesn't really make sense).
   ;    Height      -  Height of the client area of the ScrollGUI.
   ;                   Pass 0 to set the client area to the height of the child GUI (doesn't really make sense).
   ;    ----------- Optional:
   ;    GuiOptions  -  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
   ;                   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
   ;                   Add 8 to require the Ctrl key as modifier for wheel messages which shall be processed by the
   ;                   ScrollGUI. Unmodified wheel messages will be passed to the child GUI in this case.
   ; Return values:
   ;    On failure:    False
   ; Remarks:
   ;    The rect of the child GUI is determined using the 'AutoSize' option of the 'Gui, Show' command, after
   ;    '-Caption' is applied to the child GUI.
   ;    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 captured to scroll the ScrollGUI.
   ;    You won't be able to use the wheel to scroll child GUI controls unless Ctrl is required as modifier.
   ; ===================================================================================================================
   __New(HGUI, Width, Height, GuiOptions := "", ScrollBars := 3, Wheel := 0) {
      Static SB_HORZ := 0, SB_VERT = 1
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
      Static WM_MOUSEWHEEL := 0x020A, WM_MOUSEHWHEEL := 0x020E
      Static WS_HSCROLL := "0x100000", WS_VSCROLL := "0x200000"
      RequireCtrl := False
      If (Wheel & 8) {
         RequireCtrl := True
         Wheel &= (8 - 1)
      }
      If ((ScrollBars <> 1) && (ScrollBars <> 2) && (ScrollBars <> 3))
      || ((Wheel <> 0) && (Wheel <> 1) && (Wheel <> 2) && (Wheel <> 3) && (Wheel <> 4))
         Return False
      If !DllCall("User32.dll\IsWindow", "Ptr", HGUI, "UInt")
         Return False
      VarSetCapacity(RC, 16, 0)
      ; Child GUI
      If !This.AutoSize(HGUI, GuiW, GuiH)
         Return False 
      Gui, %HGUI%:Show, w%GuiW% h%GuiH% Hide
      MaxH := GuiW
      MaxV := GuiH
	  If 0
      {
	      Gui, %HGUI%:Show, AutoSize Hide
	      DllCall("User32.dll\GetWindowRect", "Ptr", HGUI, "Ptr", &RC)
	      MaxH := NumGet(RC, 8, "Int") - NumGet(RC, 0, "Int")
	      MaxV := Numget(RC, 12, "Int") - NumGet(RC, 4, "Int")
      }
      LineH := Ceil(MaxH / 20)
      LineV := Ceil(MaxV / 20)
      ; ScrollGUI
      If (Width = 0)
         Width := MaxH
      If (Height = 0)
         Height := MaxV
      MX := MY := Styles := ""
      If (ScrollBars & 1) {
         MX := MaxH + 1
         Styles .= " +" . WS_HSCROLL
      }
      If (ScrollBars & 2) {
         Styles .= " +" . WS_VSCROLL
         MY := MaxV + 1
      }
      Gui, %HGUI%:%Styles% +hwndHWND
      Gui, %HGUI%:Show, w%Width% h%Height% Hide
      If (MX <> "") || (MY <> "")
         Gui, %HGUI%:+MaxSize%MX%x%MY%
      DllCall("User32.dll\GetClientRect", "Ptr", HGUI, "Ptr", &RC)
      PageH := NumGet(RC, 8, "Int") + 1
      PageV := Numget(RC, 12, "Int") + 1
      ; Instance variables
      This.HWND := HGUI
      This.HGUI := HGUI
      This.Width := Width
      This.Height := Height
      This.RequireCtrl := RequireCtrl
      This.UseShift := False
      If (ScrollBars & 1) {
         This.SetScrollInfo(SB_HORZ, {Max: MaxH, Page: PageH, Pos: 0})
         OnMessage(WM_HSCROLL, "ScrollGUI.On_WM_Scroll")
         If (Wheel & 1)
            OnMessage(WM_MOUSEHWHEEL, "ScrollGUI.On_WM_Wheel")
         Else If (Wheel & 4) {
            OnMessage(WM_MOUSEWHEEL, "ScrollGUI.On_WM_Wheel")
            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 (ScrollBars & 2) {
         This.SetScrollInfo(SB_VERT, {Max: MaxV, Page: PageV, Pos: 0})
         OnMessage(WM_VSCROLL, "ScrollGUI.On_WM_Scroll")
         If (Wheel & 6)
            OnMessage(WM_MOUSEWHEEL, "ScrollGUI.On_WM_Wheel")
         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
      ; Gui, %HGUI%:+parent%HWND%
      Gui, %HGUI%:Show, x0 y0
      This.Instances[HGUI] := &This
   }
   ; ===================================================================================================================
   ; __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")
      ; W := This.Width
      ; H := This.Height
      Gui, % This.HWND . ":Show", %ShowOptions% , %Title%
      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.Instances.HasKey(This.HWND) {
         Gui, % This.HWND . ":Destroy"
         This.Instances.Remove(This.HWND, "")
         Return True
      }
   }
   ; ===================================================================================================================
   ; AdjustToParent Adjust the scroll bars to the new parent dimensions.
   ; Parameters:
   ;    Width       -  New width of the client area of the ScrollGUI in pixels.
   ;                   Default: 0 -> current width
   ;    Height      -  New height of the client area of the ScrollGUI in pixels.
   ;                   Default: 0 -> current height
   ; Return values:
   ;    On success: True
   ;    On failure: False
   ; Remarks:
   ;    Call this method whenever the dimensions of the parent GUI have changed, e.g. after the GUI was resized,
   ;    restored or maximized. If either Width or Height is zero, both values will be set to the current dimensions.
   ; ===================================================================================================================
   AdjustToParent(Width := 0, Height := 0) {
      If (Width = 0) || (Height = 0) {
         VarSetCapacity(RC, 16, 0)
         DllCall("User32.dll\GetClientRect", "Ptr", This.HWND, "Ptr", &RC)
         Width := NumGet(RC, 8, "Int")
         Height := Numget(RC, 12, "Int")
      }
      SH := SV := 0
      If This.ScrollH {
         If (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 {
         If (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.HWND, "Int", SH, "Int", SV, "Ptr", 0, "Ptr", 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 client area of the child GUI is determined using the 'AutoSize' option of a 'Gui, Show' command.
   ; ===================================================================================================================
   AdjustToChild() {
      Static WS_HSCROLL := 0x100000, WS_VSCROLL := 0x200000
      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
      MX := This.ScrollH ? MaxH + 1 : ""
      MY := This.ScrollV ? MaxV + 1 : ""
      If (MX <> "") || (MY <> "") {
         Gui, % This.HWND . ":+MaxSize" . MX . "x" . MY
         W := ((MX <> "") && (MX < PrevW)) ? "w" . MX : ""
         H := ((MY <> "") && (MY < PrevH)) ? "h" . MY : ""
         If (W || H ) {
            Gui, % This.HWND . ":Show", %W% %H%
            If (W) {
               This.Width := MX
               This.SetScrollInfo(0, {Page: MX + 1})
            }
            If (H) {
               This.Height := MY
               This.SetScrollInfo(1, {Page: MY + 1})
            }
         }
      }
      ; Gui, % This.HGUI . ":Show", x%XC% y%YC% AutoSize
      ; DllCall("User32.dll\GetWindowRect", "Ptr", This.HGUI, "Ptr", &RC)
      ; MaxH := NumGet(RC, 8, "Int") - NumGet(RC, 0, "Int")
      ; MaxV := Numget(RC, 12, "Int") - NumGet(RC, 4, "Int")
      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.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) {
      Static SB_HORZ := 0, SB_VERT = 1
      SB--
      If (SB <> SB_HORZ) && (SB <> SB_VERT)
         Return False
      If (SB = SB_HORZ)
         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) {
      Static SB_HORZ := 0, SB_VERT = 1
      SB--
      If (SB <> SB_HORZ) && (SB <> SB_VERT)
         Return False
      If (SB = SB_HORZ)
         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) {
      Static SB_HORZ := 0, SB_VERT = 1
      SB--
      If (SB <> SB_HORZ) && (SB <> SB_VERT)
         Return False
      If (SB = SB_HORZ)
         This.PageH := Page
      Else
         This.PageV := Page
      Return This.SetScrollInfo(SB, {Page: Page})
   }
   ; ===================================================================================================================
   ; Methods for internal or system use!!!
   ; ===================================================================================================================
   AutoSize(HGUI, ByRef Width, ByRef Height) {
      DHW := A_DetectHiddenWindows
      DetectHiddenWindows, On
      VarSetCapacity(RECT, 16, 0)
      Width := Height := 0
      HWND := HGUI
      CMD := 5 ; GW_CHILD
      L := T := R := B := LH := TH := ""
      While (HWND := DllCall("GetWindow", "Ptr", HWND, "UInt", CMD, "UPtr")) && (CMD := 2) {
         WinGetPos, X, Y, W, H, ahk_id %HWND%
         W += X, H += Y
         WinGet, Styles, Style, ahk_id %HWND%
         If (Styles & 0x10000000) { ; WS_VISIBLE
            If (L = "") || (X < L)
               L := X
            If (T = "") || (Y < T)
               T := Y
            If (R = "") || (W > R)
               R := W
            If (B = "") || (H > B)
               B := H
         }
         Else {
            If (LH = "") || (X < LH)
               LH := X
            If (TH = "") || (Y < TH)
               TH := Y
         }
      }
      DetectHiddenWindows, %DHW%
      If (LH <> "") {
         VarSetCapacity(POINT, 8, 0)
         NumPut(LH, POINT, 0, "Int")
         DllCall("ScreenToClient", "Ptr", HGUI, "Ptr", &POINT)
         LH := NumGet(POINT, 0, "Int")
      }
      If (TH <> "") {
         VarSetCapacity(POINT, 8, 0)
         NumPut(TH, POINT, 4, "Int")
         DllCall("ScreenToClient", "Ptr", HGUI, "Ptr", &POINT)
         TH := NumGet(POINT, 4, "Int")
      }
      NumPut(L, RECT, 0, "Int"), NumPut(T, RECT,  4, "Int")
      NumPut(R, RECT, 8, "Int"), NumPut(B, RECT, 12, "Int")
      DllCall("MapWindowPoints", "Ptr", 0, "Ptr", HGUI, "Ptr", &RECT, "UInt", 2)
      Width := NumGet(RECT, 8, "Int") + (LH <> "" ? LH : NumGet(RECT, 0, "Int"))
      Height := NumGet(RECT, 12, "Int") + (TH <> "" ? TH : NumGet(RECT,  4, "Int"))
      Return True
   }
   ; ===================================================================================================================
   GetScrollInfo(SB, ByRef SI) {
      Static SI_SIZE := 28
      Static SIF_ALL := 0x17
      VarSetCapacity(SI, SI_SIZE, 0)
      NumPut(SI_SIZE, SI, 0, "UInt")
      NumPut(SIF_ALL, SI, 4, "UInt")
      Return DllCall("User32.dll\GetScrollInfo", "Ptr", This.HWND, "Int", SB, "Ptr", &SI, "UInt")
   }
   ; ===================================================================================================================
   SetScrollInfo(SB, Values) {
      Static SI_SIZE := 28
      Static SIF := {Max: 0x01, Page: 0x02, Pos: 0x04}
      Static Off := {Max: 12, Page: 16, Pos: 20}
      Static SIF_DISABLENOSCROLL := 0x08
      Mask := 0
      VarSetCapacity(SI, SI_SIZE, 0)
      NumPut(SI_SIZE, SI, 0, "UInt")
      For Key, Value In Values {
         If SIF.HasKey(Key) {
            Mask |= SIF[Key]
            NumPut(Value, SI, Off[Key], "UInt")
         }
      }
      If (Mask) {
         NumPut(Mask | SIF_DISABLENOSCROLL, SI, 4, "UInt")
         Return DllCall("User32.dll\SetScrollInfo", "Ptr", This.HWND, "Int", SB, "Ptr", &SI, "UInt", 1, "UInt")
      }
      Return False
   }
   ; ===================================================================================================================
   On_WM_Scroll(LP, Msg, HWND) {
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
      If ScrollGUI.Instances.HasKey(HWND) {
         Instance := Object(ScrollGUI.Instances[HWND])
         If ((Msg = WM_HSCROLL) && Instance.ScrollH)
         || ((Msg = WM_VSCROLL) && Instance.ScrollV)
            Return Instance.Scroll(This, LP, Msg, HWND)
      }
   }
   ; ===================================================================================================================
   Scroll(WP, LP, Msg, HWND) {
      Static SB_LINEMINUS := 0, SB_LINEPLUS := 1, SB_PAGEMINUS := 2, SB_PAGEPLUS := 3, SB_THUMBTRACK := 5
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
      If (LP <> 0)
         Return
      SB := (Msg = WM_HSCROLL ? 0 : 1) ; SB_HORZ : SB_VERT
      SC := WP & 0xFFFF
      SD := (Msg = WM_HSCROLL ? This.LineH : This.LineV)
      SI := 0
      If !This.GetScrollInfo(SB, SI)
         Return
      PA := PN := NumGet(SI, 20, "Int")
      If (SC = SB_LINEMINUS)
         PN := PA - SD
      Else If (SC = SB_LINEPLUS)
         PN := PA + SD
      Else If (SC = SB_PAGEMINUS)
         PN := PA - NumGet(SI, 16, "UInt")
      Else If (SC = SB_PAGEPLUS)
         PN := PA + NumGet(SI, 16, "UInt")
      Else If (SC = SB_THUMBTRACK)
         PN := NumGet(SI, 24, "Int")
      If (PA = PN)
         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 := VS := 0
         If (Msg = WM_HSCROLL)
            HS := PA - PN
         Else
            VS := PA - PN
         DllCall("User32.dll\ScrollWindow", "Ptr", This.HWND, "Int", HS, "Int", VS, "Ptr", 0, "Ptr", 0)
      }
      Return 0
   }
   ; ===================================================================================================================
   On_WM_Wheel(LP, Msg, H) {
      Static MK_CONTROL := 0x0008
      Static MK_SHIFT := 0x0004
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
      Static WM_MOUSEWHEEL := 0x020A, WM_MOUSEHWHEEL := 0x020E
      HWND := WinExist("A")
      If ScrollGUI.Instances.HasKey(HWND) {
         Instance := Object(ScrollGUI.Instances[HWND])
         If (Instance.RequireCtrl && (This & MK_CONTROL)) || (!Instance.RequireCtrl && !(This & MK_CONTROL))
            If (Instance.WheelH && (Msg = WM_MOUSEHWHEEL))
            || (Instance.WheelH && ((Msg = WM_MOUSEWHEEL) && Instance.UseShift && (This & MK_SHIFT)))
            || (Instance.WheelV && (Msg = WM_MOUSEWHEEL))
               Return Instance.Wheel(This, LP, Msg, HWND)
      }
   }
   ; ===================================================================================================================
   Wheel(WP, LP, Msg, H) {
      Static MK_SHIFT := 0x0004
      Static SB_LINEMINUS := 0, SB_LINEPLUS := 1
      Static WM_MOUSEWHEEL := 0x020A, WM_MOUSEHWHEEL := 0x020E
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
      If (Msg = WM_MOUSEWHEEL) && (WP & MK_SHIFT) && This.UseShift
         Msg := WM_MOUSEHWHEEL
      MSG := (Msg = WM_MOUSEWHEEL ? WM_VSCROLL : WM_HSCROLL)
      SB := ((WP >> 16) > 0x7FFF) || (WP < 0) ? SB_LINEPLUS : SB_LINEMINUS
      Return This.Scroll(SB, 0, MSG, H)
   }
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

11

Re: AHK: ScrollBar

serzh82saratov пишет:

Это ведь можно и в __New сделать.

После создания окна уже криво получается:

WS_VSCROLL := 0x200000
Gui, New, +%WS_VSCROLL%
Gui, Add, Edit, w300 h300
Gui, Show, x200

Gui, New
Gui, Add, Edit, w300 h300
Gui, Show, x600
Gui, +%WS_VSCROLL%
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

12

Re: AHK: ScrollBar

Добавил (GuiStyle & 0x40000000) проверку дочерних, и ещё пару мелких правок, вроде всё работает.
Плюс колёсико стало работать в неактивном окне, что мне кажется гуд.



#SingleInstance force
#NoEnv 
SetBatchLines, -1

Gui, New, +hwndhParentGUI
Gui, Color, Red
Gui, New, +hwndhGui +Parent%hParentGUI%

Loop 10
{
   i := A_Index
   Loop 5
   {
      If A_Index = 1 
         Gui, Add, Text, xm y+10 w22 0x201, % i  
      Else  
         Gui, Add, Text, x+10 w22 yp 0x201, % i 
      Gui, Add, Edit, x+10 yp w55 hp r1, % i
   }
} 
; Create ScrollGUI1 with both horizontal and vertical scrollbars and mouse wheel capturing
SG1 := New ScrollGUI(HGUI, 0, 200, "-Caption -Resize", 2, 2)

Gui, New, +hwndhGui +Parent%hParentGUI%
Loop 10
{
   i := A_Index
   Loop 5
   {
      If A_Index = 1 
         Gui, Add, Text, xm y+10 w22 0x201, % i  
      Else  
         Gui, Add, Text, x+10 w22 yp 0x201, % i 
      Gui, Add, Edit, x+10 yp w55 hp r1, % i
   }
} 
SG2 := New ScrollGUI(HGUI, 0, 200, "-Caption -Resize", 2, 2)

SG1.Show("ScrollGUI1 Title", "x0 y0 NA")
SG2.Show("ScrollGUI2 Title", "x0 y" SG1.GuiSizeH + 1 " NA")

Gui, %hParentGui%: Show, % "w" SG1.GuiSizeW " h" SG1.GuiSizeH + SG2.GuiSizeH + 1
Return

GuiClose:
	ExitApp



; 23:36 04.07.2020 Добавлены дочерние окна
; ======================================================================================================================
; Namepace:       ScrollGUI
; Function:       Create a scrollable GUI as a parent for GUI windows.
; Tested with:    AHK 1.1.19.02
; Tested on:      Win 8.1 (x64)
; Change log:     1.0.00.00/2015-02-06/just me        -  initial release on ahkscript.org
;                 1.0.01.00/2015-02-08/just me        -  bug fixes
;                 1.1.00.00/2015-02-09/just me        -  bug fixes and mouse wheel handling
; License:        The Unlicense -> http://unlicense.org
; ======================================================================================================================
Class ScrollGUI {
   Static Instances := []
   ; ===================================================================================================================
   ; __New          Creates a scrollable parent window (ScrollGUI) for the passed GUI.
   ; Parameters:
   ;    HGUI        -  HWND of the GUI 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 (doesn't really make sense).
   ;    Height      -  Height of the client area of the ScrollGUI.
   ;                   Pass 0 to set the client area to the height of the child GUI (doesn't really make sense).
   ;    ----------- Optional:
   ;    GuiOptions  -  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
   ;                   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
   ;                   Add 8 to require the Ctrl key as modifier for wheel messages which shall be processed by the
   ;                   ScrollGUI. Unmodified wheel messages will be passed to the child GUI in this case.
   ; Return values:
   ;    On failure:    False
   ; Remarks:
   ;    The rect of the child GUI is determined using the 'AutoSize' option of the 'Gui, Show' command, after
   ;    '-Caption' is applied to the child GUI.
   ;    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 captured to scroll the ScrollGUI.
   ;    You won't be able to use the wheel to scroll child GUI controls unless Ctrl is required as modifier.
   ; ===================================================================================================================
   __New(HGUI, Width, Height, GuiOptions := "", ScrollBars := 3, Wheel := 0) {
      Static SB_HORZ := 0, SB_VERT = 1
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
      Static WM_MOUSEWHEEL := 0x020A, WM_MOUSEHWHEEL := 0x020E
      Static WS_HSCROLL := "0x100000", WS_VSCROLL := "0x200000"
      RequireCtrl := False
      If (Wheel & 8) {
         RequireCtrl := True
         Wheel &= (8 - 1)
      }
      If ((ScrollBars <> 1) && (ScrollBars <> 2) && (ScrollBars <> 3))
      || ((Wheel <> 0) && (Wheel <> 1) && (Wheel <> 2) && (Wheel <> 3) && (Wheel <> 4))
         Return False
      If !DllCall("User32.dll\IsWindow", "Ptr", HGUI, "UInt")
         Return False
      VarSetCapacity(RC, 16, 0)
      ; Child GUI
      If !This.AutoSize(HGUI, GuiW, GuiH)
         Return False
      Gui, %HGUI%:-Caption -Resize
      Gui, %HGUI%:Show, w%GuiW% h%GuiH% Hide
      MaxH := GuiW
      MaxV := GuiH
      ; Gui, %HGUI%:Show, AutoSize Hide
      ; DllCall("User32.dll\GetWindowRect", "Ptr", HGUI, "Ptr", &RC)
      ; MaxH := NumGet(RC, 8, "Int") - NumGet(RC, 0, "Int")
      ; MaxV := Numget(RC, 12, "Int") - NumGet(RC, 4, "Int")
      LineH := Ceil(MaxH / 20)
      LineV := Ceil(MaxV / 20)
      ; ScrollGUI
      If (Width = 0)
         Width := MaxH
      If (Height = 0)
         Height := MaxV
      MX := MY := Styles := ""
      If (ScrollBars & 1) {
         MX := MaxH + 1
         Styles .= " +" . WS_HSCROLL
      }
      If (ScrollBars & 2) {
         Styles .= " +" . WS_VSCROLL
         MY := MaxV + 1
      } 
      Gui, New, %GuiOptions% %Styles% +hwndHWND
      Gui, %HWND%:Show, w%Width% h%Height% Hide
      If (MX <> "") || (MY <> "")
         Gui, %HWND%:+MaxSize%MX%x%MY%
      DllCall("User32.dll\GetClientRect", "Ptr", HWND, "Ptr", &RC)
	  PageH := NumGet(RC, 8, "Int") + 1
      PageV := Numget(RC, 12, "Int") + 1 
      ; Instance variables
      This.HWND := HWND
      This.HGUI := HGUI
      This.Width := Width
      This.Height := Height
      This.RequireCtrl := RequireCtrl
      This.UseShift := False
      If (ScrollBars & 1) {
         This.SetScrollInfo(SB_HORZ, {Max: MaxH, Page: PageH, Pos: 0})
         OnMessage(WM_HSCROLL, "ScrollGUI.On_WM_Scroll")
         If (Wheel & 1)
            OnMessage(WM_MOUSEHWHEEL, "ScrollGUI.On_WM_Wheel")
         Else If (Wheel & 4) {
            OnMessage(WM_MOUSEWHEEL, "ScrollGUI.On_WM_Wheel")
            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 (ScrollBars & 2) {
         This.SetScrollInfo(SB_VERT, {Max: MaxV, Page: PageV, Pos: 0})
         OnMessage(WM_VSCROLL, "ScrollGUI.On_WM_Scroll")
         If (Wheel & 6)
            OnMessage(WM_MOUSEWHEEL, "ScrollGUI.On_WM_Wheel")
         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
	  WinGet, GuiStyle, Style, ahk_id %HGUI%
	  If (GuiStyle & 0x40000000)
	  {
         WS_POPUP := 0x80000000, WS_CHILD := 0x40000000
	  	 Gui, %HWND%:+%WS_CHILD% -%WS_POPUP%
		 This.hParentGui := DllCall("GetParent", "Ptr", HGUI)
	  	 DllCall("SetParent", "Ptr", HWND, "Ptr", This.hParentGui)
	  } 
	  WinGetPos, X, Y, W, H, ahk_id %HWND% 
      This.GuiSizeX := X
      This.GuiSizeY := Y
      This.GuiSizeW := W
      This.GuiSizeH := H
      Gui, %HGUI%:+parent%HWND%
      Gui, %HGUI%:Show, x0 y0
      This.Instances[HWND] := &This
   }
   ; ===================================================================================================================
   ; __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")
      W := This.Width
      H := This.Height
      Gui, % This.HWND . ":Show", %ShowOptions% w%W% h%H%, %Title%
      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.Instances.HasKey(This.HWND) {
         Gui, % This.HWND . ":Destroy"
         This.Instances.Remove(This.HWND, "")
         Return True
      }
   }
   ; ===================================================================================================================
   ; AdjustToParent Adjust the scroll bars to the new parent dimensions.
   ; Parameters:
   ;    Width       -  New width of the client area of the ScrollGUI in pixels.
   ;                   Default: 0 -> current width
   ;    Height      -  New height of the client area of the ScrollGUI in pixels.
   ;                   Default: 0 -> current height
   ; Return values:
   ;    On success: True
   ;    On failure: False
   ; Remarks:
   ;    Call this method whenever the dimensions of the parent GUI have changed, e.g. after the GUI was resized,
   ;    restored or maximized. If either Width or Height is zero, both values will be set to the current dimensions.
   ; ===================================================================================================================
   AdjustToParent(Width := 0, Height := 0) {
      If (Width = 0) || (Height = 0) {
         VarSetCapacity(RC, 16, 0)
         DllCall("User32.dll\GetClientRect", "Ptr", This.HWND, "Ptr", &RC)
         Width := NumGet(RC, 8, "Int")
         Height := Numget(RC, 12, "Int")
      }
      SH := SV := 0
      If This.ScrollH {
         If (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 {
         If (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.HWND, "Int", SH, "Int", SV, "Ptr", 0, "Ptr", 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 client area of the child GUI is determined using the 'AutoSize' option of a 'Gui, Show' command.
   ; ===================================================================================================================
   AdjustToChild() {
      Static WS_HSCROLL := 0x100000, WS_VSCROLL := 0x200000
      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
      MX := This.ScrollH ? MaxH + 1 : ""
      MY := This.ScrollV ? MaxV + 1 : ""
      If (MX <> "") || (MY <> "") {
         Gui, % This.HWND . ":+MaxSize" . MX . "x" . MY
         W := ((MX <> "") && (MX < PrevW)) ? "w" . MX : ""
         H := ((MY <> "") && (MY < PrevH)) ? "h" . MY : ""
         If (W || H ) {
            Gui, % This.HWND . ":Show", %W% %H%
            If (W) {
               This.Width := MX
               This.SetScrollInfo(0, {Page: MX + 1})
            }
            If (H) {
               This.Height := MY
               This.SetScrollInfo(1, {Page: MY + 1})
            }
         }
      }
      ; Gui, % This.HGUI . ":Show", x%XC% y%YC% AutoSize
      ; DllCall("User32.dll\GetWindowRect", "Ptr", This.HGUI, "Ptr", &RC)
      ; MaxH := NumGet(RC, 8, "Int") - NumGet(RC, 0, "Int")
      ; MaxV := Numget(RC, 12, "Int") - NumGet(RC, 4, "Int")
      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.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) {
      Static SB_HORZ := 0, SB_VERT = 1
      SB--
      If (SB <> SB_HORZ) && (SB <> SB_VERT)
         Return False
      If (SB = SB_HORZ)
         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) {
      Static SB_HORZ := 0, SB_VERT = 1
      SB--
      If (SB <> SB_HORZ) && (SB <> SB_VERT)
         Return False
      If (SB = SB_HORZ)
         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) {
      Static SB_HORZ := 0, SB_VERT = 1
      SB--
      If (SB <> SB_HORZ) && (SB <> SB_VERT)
         Return False
      If (SB = SB_HORZ)
         This.PageH := Page
      Else
         This.PageV := Page
      Return This.SetScrollInfo(SB, {Page: Page})
   }
   ; ===================================================================================================================
   ; Methods for internal or system use!!!
   ; ===================================================================================================================
   AutoSize(HGUI, ByRef Width, ByRef Height) {
      DHW := A_DetectHiddenWindows
      DetectHiddenWindows, On
      VarSetCapacity(RECT, 16, 0)
      Width := Height := 0
      HWND := HGUI
      CMD := 5 ; GW_CHILD
      L := T := R := B := LH := TH := ""
      While (HWND := DllCall("GetWindow", "Ptr", HWND, "UInt", CMD, "UPtr")) && (CMD := 2) {
         WinGetPos, X, Y, W, H, ahk_id %HWND%
         W += X, H += Y
         WinGet, Styles, Style, ahk_id %HWND%
         If (Styles & 0x10000000) { ; WS_VISIBLE
            If (L = "") || (X < L)
               L := X
            If (T = "") || (Y < T)
               T := Y
            If (R = "") || (W > R)
               R := W
            If (B = "") || (H > B)
               B := H
         }
         Else {
            If (LH = "") || (X < LH)
               LH := X
            If (TH = "") || (Y < TH)
               TH := Y
         }
      }
      DetectHiddenWindows, %DHW%
      If (LH <> "") {
         VarSetCapacity(POINT, 8, 0)
         NumPut(LH, POINT, 0, "Int")
         DllCall("ScreenToClient", "Ptr", HGUI, "Ptr", &POINT)
         LH := NumGet(POINT, 0, "Int")
      }
      If (TH <> "") {
         VarSetCapacity(POINT, 8, 0)
         NumPut(TH, POINT, 4, "Int")
         DllCall("ScreenToClient", "Ptr", HGUI, "Ptr", &POINT)
         TH := NumGet(POINT, 4, "Int")
      }
      NumPut(L, RECT, 0, "Int"), NumPut(T, RECT,  4, "Int")
      NumPut(R, RECT, 8, "Int"), NumPut(B, RECT, 12, "Int")
      DllCall("MapWindowPoints", "Ptr", 0, "Ptr", HGUI, "Ptr", &RECT, "UInt", 2)
      Width := NumGet(RECT, 8, "Int") + (LH <> "" ? LH : NumGet(RECT, 0, "Int"))
      Height := NumGet(RECT, 12, "Int") + (TH <> "" ? TH : NumGet(RECT,  4, "Int"))
      Return True
   }
   ; ===================================================================================================================
   GetScrollInfo(SB, ByRef SI) {
      Static SI_SIZE := 28
      Static SIF_ALL := 0x17
      VarSetCapacity(SI, SI_SIZE, 0)
      NumPut(SI_SIZE, SI, 0, "UInt")
      NumPut(SIF_ALL, SI, 4, "UInt")
      Return DllCall("User32.dll\GetScrollInfo", "Ptr", This.HWND, "Int", SB, "Ptr", &SI, "UInt")
   }
   ; ===================================================================================================================
   SetScrollInfo(SB, Values) {
      Static SI_SIZE := 28
      Static SIF := {Max: 0x01, Page: 0x02, Pos: 0x04}
      Static Off := {Max: 12, Page: 16, Pos: 20}
      Static SIF_DISABLENOSCROLL := 0x08
      Mask := 0
      VarSetCapacity(SI, SI_SIZE, 0)
      NumPut(SI_SIZE, SI, 0, "UInt")
      For Key, Value In Values {
         If SIF.HasKey(Key) {
            Mask |= SIF[Key]
            NumPut(Value, SI, Off[Key], "UInt")
         }
      }
      If (Mask) {
         NumPut(Mask | SIF_DISABLENOSCROLL, SI, 4, "UInt")
         Return DllCall("User32.dll\SetScrollInfo", "Ptr", This.HWND, "Int", SB, "Ptr", &SI, "UInt", 1, "UInt")
      }
      Return False
   }
   ; ===================================================================================================================
   On_WM_Scroll(LP, Msg, HWND) {
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115 
      If ScrollGUI.Instances.HasKey(HWND) {
         Instance := Object(ScrollGUI.Instances[HWND])
         If ((Msg = WM_HSCROLL) && Instance.ScrollH)
         || ((Msg = WM_VSCROLL) && Instance.ScrollV)
            Return Instance.Scroll(This, LP, Msg, HWND)
      }
   }
   ; ===================================================================================================================
   Scroll(WP, LP, Msg, HWND) {
      Static SB_LINEMINUS := 0, SB_LINEPLUS := 1, SB_PAGEMINUS := 2, SB_PAGEPLUS := 3, SB_THUMBTRACK := 5
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
      If (LP <> 0)
         Return
      SB := (Msg = WM_HSCROLL ? 0 : 1) ; SB_HORZ : SB_VERT
      SC := WP & 0xFFFF
      SD := (Msg = WM_HSCROLL ? This.LineH : This.LineV)
      SI := 0
      If !This.GetScrollInfo(SB, SI)
         Return
      PA := PN := NumGet(SI, 20, "Int")
      If (SC = SB_LINEMINUS)
         PN := PA - SD
      Else If (SC = SB_LINEPLUS)
         PN := PA + SD
      Else If (SC = SB_PAGEMINUS)
         PN := PA - NumGet(SI, 16, "UInt")
      Else If (SC = SB_PAGEPLUS)
         PN := PA + NumGet(SI, 16, "UInt")
      Else If (SC = SB_THUMBTRACK)
         PN := NumGet(SI, 24, "Int")
      If (PA = PN)
         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 := VS := 0
         If (Msg = WM_HSCROLL)
            HS := PA - PN
         Else
            VS := PA - PN
         DllCall("User32.dll\ScrollWindow", "Ptr", This.HWND, "Int", HS, "Int", VS, "Ptr", 0, "Ptr", 0)
      }
      Return 0
   }
   ; ===================================================================================================================
   On_WM_Wheel(LP, Msg, HWND) {
      Static MK_CONTROL := 0x0008
      Static MK_SHIFT := 0x0004
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
      Static WM_MOUSEWHEEL := 0x020A, WM_MOUSEHWHEEL := 0x020E
      ; HWND := WinExist("A") 
      If ScrollGUI.Instances.HasKey(HWND) {
         Instance := Object(ScrollGUI.Instances[HWND])
         If (Instance.RequireCtrl && (This & MK_CONTROL)) || (!Instance.RequireCtrl && !(This & MK_CONTROL))
            If (Instance.WheelH && (Msg = WM_MOUSEHWHEEL))
            || (Instance.WheelH && ((Msg = WM_MOUSEWHEEL) && Instance.UseShift && (This & MK_SHIFT)))
            || (Instance.WheelV && (Msg = WM_MOUSEWHEEL))
               Return Instance.Wheel(This, LP, Msg, HWND)
      }
   }
   ; ===================================================================================================================
   Wheel(WP, LP, Msg, H) {
      Static MK_SHIFT := 0x0004
      Static SB_LINEMINUS := 0, SB_LINEPLUS := 1
      Static WM_MOUSEWHEEL := 0x020A, WM_MOUSEHWHEEL := 0x020E
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
      If (Msg = WM_MOUSEWHEEL) && (WP & MK_SHIFT) && This.UseShift
         Msg := WM_MOUSEHWHEEL
      MSG := (Msg = WM_MOUSEWHEEL ? WM_VSCROLL : WM_HSCROLL)
      SB := ((WP >> 16) > 0x7FFF) || (WP < 0) ? SB_LINEPLUS : SB_LINEMINUS
      Return This.Scroll(SB, 0, MSG, H)
   }
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

13

Re: AHK: ScrollBar

Ну, теперь осталось только лишнее окно убрать. Думаю, если при этом нужно будет заранее прописывать WS_VSCROLL/WS_HSCROLL — не страшно. Само наличие стиля может служить знаком того, что нужно делать обработку данного скролла.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

14

Re: AHK: ScrollBar

teadrinker пишет:

Ну, теперь осталось только лишнее окно убрать.

Ты про создаваемое окно?

https://www.autohotkey.com/boards/viewt … 80#p309973

Кстати, похоже что все подобные вещи подвисают при большом количестве контролов, например код Lexikos тоже.

#NoEnv
SetBatchLines -1
OnMessage(0x115, "OnScroll") ; WM_VSCROLL
OnMessage(0x114, "OnScroll") ; WM_HSCROLL

Gui, +Resize +0x300000 ; WS_VSCROLL | WS_HSCROLL

Loop 1555
    Gui, Add, Edit, R5 W400, Edit %A_Index%
Gui, Add, Button,, Do absolutely nothing
Gui, Show, W200 H200

Gui, +LastFound
GroupAdd, MyGui, % "ahk_id " . WinExist()

return

GuiSize:
    UpdateScrollBars(A_Gui, A_GuiWidth, A_GuiHeight)
return

GuiClose:
ExitApp

#IfWinActive ahk_group MyGui
WheelUp::
WheelDown::
+WheelUp::
+WheelDown::
    ; SB_LINEDOWN=1, SB_LINEUP=0, WM_HSCROLL=0x114, WM_VSCROLL=0x115
    OnScroll(InStr(A_ThisHotkey,"Down") ? 1 : 0, 0, GetKeyState("Shift") ? 0x114 : 0x115, WinExist())
return
#IfWinActive

UpdateScrollBars(GuiNum, GuiWidth, GuiHeight)
{
    static SIF_RANGE=0x1, SIF_PAGE=0x2, SIF_DISABLENOSCROLL=0x8, SB_HORZ=0, SB_VERT=1
    
    Gui, %GuiNum%:Default
    Gui, +LastFound
    
    ; Calculate scrolling area.
    Left := Top := 9999
    Right := Bottom := 0
    WinGet, ControlList, ControlList
    Loop, Parse, ControlList, `n
    {
        GuiControlGet, c, Pos, %A_LoopField%
        if (cX < Left)
            Left := cX
        if (cY < Top)
            Top := cY
        if (cX + cW > Right)
            Right := cX + cW
        if (cY + cH > Bottom)
            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", "uint", WinExist(), "uint", SB_HORZ, "uint", &si, "int", 1)
    
    ; Update vertical scroll bar.
;     NumPut(SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL, si, 4) ; fMask
    NumPut(ScrollHeight, si, 12) ; nMax
    NumPut(GuiHeight, si, 16) ; nPage
    DllCall("SetScrollInfo", "uint", WinExist(), "uint", SB_VERT, "uint", &si, "int", 1)
    
    if (Left < 0 && Right < GuiWidth)
        x := Abs(Left) > GuiWidth-Right ? GuiWidth-Right : Abs(Left)
    if (Top < 0 && Bottom < GuiHeight)
        y := Abs(Top) > GuiHeight-Bottom ? GuiHeight-Bottom : Abs(Top)
    if (x || y)
        DllCall("ScrollWindow", "uint", WinExist(), "int", x, "int", y, "uint", 0, "uint", 0)
}

OnScroll(wParam, lParam, msg, hwnd)
{
    static SIF_ALL=0x17, SCROLL_STEP=10
    
    bar := msg=0x115 ; SB_HORZ=0, SB_VERT=1
    
    VarSetCapacity(si, 28, 0)
    NumPut(28, si) ; cbSize
    NumPut(SIF_ALL, si, 4) ; fMask
    if !DllCall("GetScrollInfo", "uint", hwnd, "int", bar, "uint", &si)
        return
    
    VarSetCapacity(rect, 16)
    DllCall("GetClientRect", "uint", hwnd, "uint", &rect)
    
    new_pos := NumGet(si, 20) ; nPos
    
    action := wParam & 0xFFFF
    if action = 0 ; SB_LINEUP
        new_pos -= SCROLL_STEP
    else if action = 1 ; SB_LINEDOWN
        new_pos += SCROLL_STEP
    else if action = 2 ; SB_PAGEUP
        new_pos -= NumGet(rect, 12, "int") - SCROLL_STEP
    else if action = 3 ; SB_PAGEDOWN
        new_pos += NumGet(rect, 12, "int") - SCROLL_STEP
    else if (action = 5 || action = 4) ; SB_THUMBTRACK || SB_THUMBPOSITION
        new_pos := wParam>>16
    else if action = 6 ; SB_TOP
        new_pos := NumGet(si, 8, "int") ; nMin
    else if action = 7 ; SB_BOTTOM
        new_pos := NumGet(si, 12, "int") ; nMax
    else
        return
    
    min := NumGet(si, 8, "int") ; nMin
    max := NumGet(si, 12, "int") - NumGet(si, 16) ; nMax-nPage
    new_pos := new_pos > max ? max : new_pos
    new_pos := new_pos < min ? min : new_pos
    
    old_pos := NumGet(si, 20, "int") ; nPos
    
    x := y := 0
    if bar = 0 ; SB_HORZ
        x := old_pos-new_pos
    else
        y := old_pos-new_pos
    ; Scroll contents of window and invalidate uncovered area.
    DllCall("ScrollWindow", "uint", hwnd, "int", x, "int", y, "uint", 0, "uint", 0)
    
    ; Update scroll bar.
    NumPut(new_pos, si, 20, "int") ; nPos
    DllCall("SetScrollInfo", "uint", hwnd, "int", bar, "uint", &si, "int", 1)
}
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

15

Re: AHK: ScrollBar

А что там по ссылке? Я не совсем понял. Подвисают, это если дополнительное окно не делать, или в любом случае?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

16

Re: AHK: ScrollBar

Так понял что когда в окне более 1000 или около того контролов, то после скроллинга скрипт вешает комп пока не отработает всю очередь WM_*SCROLL.
У меня так.
Визуально всё норм с прокруткой, но я не могу активировать другое окно или даже запустить hotkey какое то время после прокрутки.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

17

Re: AHK: ScrollBar

А, ну это не критично, думаю. В реальности такие окна редко когда пригодятся, лучше таблицу Excel использовать.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

18

Re: AHK: ScrollBar

По моему критично.
Таблица ексель не айс, может тебе понадобится сделать таблицу со своими кнопками и.т.д.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

19

Re: AHK: ScrollBar

Ну, можно просто окно управления с кнопками к таблице добавить.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

20

Re: AHK: ScrollBar

Ну, или если нужно что-то вроде таблицы, тогда просто ActiveX с html использовать, там и со скроллингом особо заморачиваться не придётся.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

21

Re: AHK: ScrollBar

Даже пример из шапки нормально тормозит.
Думаю проблема с ScrollWindow, может это как то связано с двумя последними параметрами, они не используются в примерах на AutoHotkey, в примечании msdn я не особо понял что к чему. https://docs.microsoft.com/en-us/window … rollwindow

Размер области прокрутки не влияет на производительность, я проверил.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

22

Re: AHK: ScrollBar

В примере всё из шапки правильно, они могут быть нулевыми.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

23

Re: AHK: ScrollBar

Дело в обработке ненужных сообщений, когда скроллинг уже по факту осуществлён, продолжается их обработка. Не пойму как их отфильтровать в методе "Scroll". Там есть проверка (PA <> PN), но она не помогает.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

24 (изменено: serzh82saratov, 2020-07-05 03:46:05)

Re: AHK: ScrollBar

Если ScrollWindow заменить на GuiShow, то никаких тормозов нет с любым количеством контролов.
Таким образом нельзя удалить создаваемое родительское окно.
Если использовать ScrollWindowEx без SW_SCROLLCHILDREN, то тормозов нет, но окно перестаёт нормально рендерится, в коде есть для тестов.



#SingleInstance force
#NoEnv
SetBatchLines, -1 

Gui, New, +hwndhParentGUI
Gui, Color, Red
Gui, New, +hwndhGui +Parent%hParentGUI%

Loop 100
{
   i := A_Index
   Loop 5
   {
      If A_Index = 1 
         Gui, Add, Text, xm y+10 w21 h21 0x201, % i
      Else  
         Gui, Add, Text, x+10 w21 h21 yp 0x201, % i 
      Gui, Add, Edit, x+10 yp w55 hp r1, % A_Index
   }
} 
SG1 := New ScrollGUI(HGUI, 0, 200, "-Caption -Resize", 2, 2)
SG1.SetLine(2, 31) 

Gui, New, +hwndhGui +Parent%hParentGUI%
Loop 10
{
   i := A_Index
   Loop 5
   {
      If A_Index = 1 
         Gui, Add, Text, xm y+10 w22 0x201, % i  
      Else  
         Gui, Add, Text, x+10 w22 yp 0x201, % i 
      Gui, Add, Edit, x+10 yp w55 hp r1, % A_Index
   }
} 
SG2 := New ScrollGUI(HGUI, 330, 200, "-Caption -Resize", 3, 4)

SG1.Show("ScrollGUI1 Title", "x0 y0 NA")
SG2.Show("ScrollGUI2 Title", "x0 y" SG1.GuiSizeH + 1 " NA")

Gui, %hParentGui%:Add, Edit, % "+0x100000 +0x4 +0x80 -wrap w" SG1.GuiSizeW - SG2.GuiSizeW - 2
	. " h" SG2.GuiSizeH
	. " x" SG2.GuiSizeW + 2
	. " y" SG1.GuiSizeH + 1
	
Gui, %hParentGui%: Show, % "w" SG1.GuiSizeW " h" SG1.GuiSizeH + SG2.GuiSizeH + 1
Return

GuiClose:
	ExitApp



; 23:36 04.07.2020 Добавлены дочерние окна
; 02:30 05.07.2020 ScrollWindow заменён на GuiShow
; http://forum.script-coding.com/viewtopic.php?pid=140580#p140580



; ======================================================================================================================
; Namepace:       ScrollGUI
; Function:       Create a scrollable GUI as a parent for GUI windows.
; Tested with:    AHK 1.1.19.02
; Tested on:      Win 8.1 (x64)
; Change log:     1.0.00.00/2015-02-06/just me        -  initial release on ahkscript.org
;                 1.0.01.00/2015-02-08/just me        -  bug fixes
;                 1.1.00.00/2015-02-09/just me        -  bug fixes and mouse wheel handling
; License:        The Unlicense -> http://unlicense.org
; ======================================================================================================================
Class ScrollGUI {
   Static Instances := []
   ; ===================================================================================================================
   ; __New          Creates a scrollable parent window (ScrollGUI) for the passed GUI.
   ; Parameters:
   ;    HGUI        -  HWND of the GUI 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 (doesn't really make sense).
   ;    Height      -  Height of the client area of the ScrollGUI.
   ;                   Pass 0 to set the client area to the height of the child GUI (doesn't really make sense).
   ;    ----------- Optional:
   ;    GuiOptions  -  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
   ;                   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
   ;                   Add 8 to require the Ctrl key as modifier for wheel messages which shall be processed by the
   ;                   ScrollGUI. Unmodified wheel messages will be passed to the child GUI in this case.
   ; Return values:
   ;    On failure:    False
   ; Remarks:
   ;    The rect of the child GUI is determined using the 'AutoSize' option of the 'Gui, Show' command, after
   ;    '-Caption' is applied to the child GUI.
   ;    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 captured to scroll the ScrollGUI.
   ;    You won't be able to use the wheel to scroll child GUI controls unless Ctrl is required as modifier.
   ; ===================================================================================================================
   __New(HGUI, Width, Height, GuiOptions := "", ScrollBars := 3, Wheel := 0) {
      Static SB_HORZ := 0, SB_VERT = 1
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
      Static WM_MOUSEWHEEL := 0x020A, WM_MOUSEHWHEEL := 0x020E
      Static WS_HSCROLL := "0x100000", WS_VSCROLL := "0x200000"
      RequireCtrl := False
      If (Wheel & 8) {
         RequireCtrl := True
         Wheel &= (8 - 1)
      }
      If ((ScrollBars <> 1) && (ScrollBars <> 2) && (ScrollBars <> 3))
      || ((Wheel <> 0) && (Wheel <> 1) && (Wheel <> 2) && (Wheel <> 3) && (Wheel <> 4))
         Return False
      If !DllCall("User32.dll\IsWindow", "Ptr", HGUI, "UInt")
         Return False
      VarSetCapacity(RC, 16, 0)
      ; Child GUI
      If !This.AutoSize(HGUI, GuiW, GuiH)
         Return False
      Gui, %HGUI%:-Caption -Resize
      Gui, %HGUI%:Show, w%GuiW% h%GuiH% Hide
      MaxH := GuiW
      MaxV := GuiH
      ; Gui, %HGUI%:Show, AutoSize Hide
      ; DllCall("User32.dll\GetWindowRect", "Ptr", HGUI, "Ptr", &RC)
      ; MaxH := NumGet(RC, 8, "Int") - NumGet(RC, 0, "Int")
      ; MaxV := Numget(RC, 12, "Int") - NumGet(RC, 4, "Int")
      LineH := Ceil(MaxH / 20)
      LineV := Ceil(MaxV / 20)
      ; ScrollGUI
      If (Width = 0)
         Width := MaxH
      If (Height = 0)
         Height := MaxV
      MX := MY := Styles := ""
      If (ScrollBars & 1) {
         MX := MaxH + 1
         Styles .= " +" . WS_HSCROLL
      }
      If (ScrollBars & 2) {
         Styles .= " +" . WS_VSCROLL
         MY := MaxV + 1
      } 
      Gui, New, %GuiOptions% %Styles% +hwndHWND
      Gui, %HWND%:Show, w%Width% h%Height% Hide
      If (MX <> "") || (MY <> "")
         Gui, %HWND%:+MaxSize%MX%x%MY%
      DllCall("User32.dll\GetClientRect", "Ptr", HWND, "Ptr", &RC)
	  PageH := NumGet(RC, 8, "Int") + 1
      PageV := Numget(RC, 12, "Int") + 1 
      ; Instance variables
      This.HWND := HWND
      This.HGUI := HGUI
      This.Width := Width
      This.Height := Height
      This.RequireCtrl := RequireCtrl
      This.UseShift := False
      If (ScrollBars & 1) {
         This.SetScrollInfo(SB_HORZ, {Max: MaxH, Page: PageH, Pos: 0})
         OnMessage(WM_HSCROLL, "ScrollGUI.On_WM_Scroll")
         If (Wheel & 1)
            OnMessage(WM_MOUSEHWHEEL, "ScrollGUI.On_WM_Wheel")
         Else If (Wheel & 4) {
            OnMessage(WM_MOUSEWHEEL, "ScrollGUI.On_WM_Wheel")
            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 (ScrollBars & 2) {
         This.SetScrollInfo(SB_VERT, {Max: MaxV, Page: PageV, Pos: 0})
         OnMessage(WM_VSCROLL, "ScrollGUI.On_WM_Scroll")
         If (Wheel & 6)
            OnMessage(WM_MOUSEWHEEL, "ScrollGUI.On_WM_Wheel")
         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
	  WinGet, GuiStyle, Style, ahk_id %HGUI%
	  If (GuiStyle & 0x40000000)  ; WS_CHILD
	  {
         WS_POPUP := 0x80000000, WS_CHILD := 0x40000000
	  	 Gui, %HWND%:+%WS_CHILD% -%WS_POPUP%
		 This.hParentGui := DllCall("GetParent", "Ptr", HGUI)
	  	 DllCall("SetParent", "Ptr", HWND, "Ptr", This.hParentGui)
	  } 
	  WinGetPos, X, Y, W, H, ahk_id %HWND% 
      This.GuiSizeX := X
      This.GuiSizeY := Y
      This.GuiSizeW := W
      This.GuiSizeH := H
      Gui, %HGUI%:+parent%HWND%
      Gui, %HGUI%:Show, x0 y0
      This.Instances[HWND] := &This
   }
   ; ===================================================================================================================
   ; __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")
      W := This.Width
      H := This.Height
      Gui, % This.HWND . ":Show", %ShowOptions% w%W% h%H%, %Title%
      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.Instances.HasKey(This.HWND) {
         Gui, % This.HWND . ":Destroy"
         This.Instances.Remove(This.HWND, "")
         Return True
      }
   }
   ; ===================================================================================================================
   ; AdjustToParent Adjust the scroll bars to the new parent dimensions.
   ; Parameters:
   ;    Width       -  New width of the client area of the ScrollGUI in pixels.
   ;                   Default: 0 -> current width
   ;    Height      -  New height of the client area of the ScrollGUI in pixels.
   ;                   Default: 0 -> current height
   ; Return values:
   ;    On success: True
   ;    On failure: False
   ; Remarks:
   ;    Call this method whenever the dimensions of the parent GUI have changed, e.g. after the GUI was resized,
   ;    restored or maximized. If either Width or Height is zero, both values will be set to the current dimensions.
   ; ===================================================================================================================
   AdjustToParent(Width := 0, Height := 0) {
      If (Width = 0) || (Height = 0) {
         VarSetCapacity(RC, 16, 0)
         DllCall("User32.dll\GetClientRect", "Ptr", This.HWND, "Ptr", &RC)
         Width := NumGet(RC, 8, "Int")
         Height := Numget(RC, 12, "Int")
      }
      SH := SV := 0
      If This.ScrollH {
         If (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 {
         If (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.HWND, "Int", SH, "Int", SV, "Ptr", 0, "Ptr", 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 client area of the child GUI is determined using the 'AutoSize' option of a 'Gui, Show' command.
   ; ===================================================================================================================
   AdjustToChild() {
      Static WS_HSCROLL := 0x100000, WS_VSCROLL := 0x200000
      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
      MX := This.ScrollH ? MaxH + 1 : ""
      MY := This.ScrollV ? MaxV + 1 : ""
      If (MX <> "") || (MY <> "") {
         Gui, % This.HWND . ":+MaxSize" . MX . "x" . MY
         W := ((MX <> "") && (MX < PrevW)) ? "w" . MX : ""
         H := ((MY <> "") && (MY < PrevH)) ? "h" . MY : ""
         If (W || H ) {
            Gui, % This.HWND . ":Show", %W% %H%
            If (W) {
               This.Width := MX
               This.SetScrollInfo(0, {Page: MX + 1})
            }
            If (H) {
               This.Height := MY
               This.SetScrollInfo(1, {Page: MY + 1})
            }
         }
      }
      ; Gui, % This.HGUI . ":Show", x%XC% y%YC% AutoSize
      ; DllCall("User32.dll\GetWindowRect", "Ptr", This.HGUI, "Ptr", &RC)
      ; MaxH := NumGet(RC, 8, "Int") - NumGet(RC, 0, "Int")
      ; MaxV := Numget(RC, 12, "Int") - NumGet(RC, 4, "Int")
      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.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) {
      Static SB_HORZ := 0, SB_VERT = 1
      SB--
      If (SB <> SB_HORZ) && (SB <> SB_VERT)
         Return False
      If (SB = SB_HORZ)
         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) {
      Static SB_HORZ := 0, SB_VERT = 1
      SB--
      If (SB <> SB_HORZ) && (SB <> SB_VERT)
         Return False
      If (SB = SB_HORZ)
         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) {
      Static SB_HORZ := 0, SB_VERT = 1
      SB--
      If (SB <> SB_HORZ) && (SB <> SB_VERT)
         Return False
      If (SB = SB_HORZ)
         This.PageH := Page
      Else
         This.PageV := Page
      Return This.SetScrollInfo(SB, {Page: Page})
   }
   ; ===================================================================================================================
   ; Methods for internal or system use!!!
   ; ===================================================================================================================
   AutoSize(HGUI, ByRef Width, ByRef Height) {
      DHW := A_DetectHiddenWindows
      DetectHiddenWindows, On
      VarSetCapacity(RECT, 16, 0)
      Width := Height := 0
      HWND := HGUI
      CMD := 5 ; GW_CHILD
      L := T := R := B := LH := TH := ""
      While (HWND := DllCall("GetWindow", "Ptr", HWND, "UInt", CMD, "UPtr")) && (CMD := 2) {
         WinGetPos, X, Y, W, H, ahk_id %HWND%
         W += X, H += Y
         WinGet, Styles, Style, ahk_id %HWND%
         If (Styles & 0x10000000) { ; WS_VISIBLE
            If (L = "") || (X < L)
               L := X
            If (T = "") || (Y < T)
               T := Y
            If (R = "") || (W > R)
               R := W
            If (B = "") || (H > B)
               B := H
         }
         Else {
            If (LH = "") || (X < LH)
               LH := X
            If (TH = "") || (Y < TH)
               TH := Y
         }
      }
      DetectHiddenWindows, %DHW%
      If (LH <> "") {
         VarSetCapacity(POINT, 8, 0)
         NumPut(LH, POINT, 0, "Int")
         DllCall("ScreenToClient", "Ptr", HGUI, "Ptr", &POINT)
         LH := NumGet(POINT, 0, "Int")
      }
      If (TH <> "") {
         VarSetCapacity(POINT, 8, 0)
         NumPut(TH, POINT, 4, "Int")
         DllCall("ScreenToClient", "Ptr", HGUI, "Ptr", &POINT)
         TH := NumGet(POINT, 4, "Int")
      }
      NumPut(L, RECT, 0, "Int"), NumPut(T, RECT,  4, "Int")
      NumPut(R, RECT, 8, "Int"), NumPut(B, RECT, 12, "Int")
      DllCall("MapWindowPoints", "Ptr", 0, "Ptr", HGUI, "Ptr", &RECT, "UInt", 2)
      Width := NumGet(RECT, 8, "Int") + (LH <> "" ? LH : NumGet(RECT, 0, "Int"))
      Height := NumGet(RECT, 12, "Int") + (TH <> "" ? TH : NumGet(RECT,  4, "Int"))
      Return True
   }
   ; ===================================================================================================================
   GetScrollInfo(SB, ByRef SI) {
      Static SI_SIZE := 28
      Static SIF_ALL := 0x17
      VarSetCapacity(SI, SI_SIZE, 0)
      NumPut(SI_SIZE, SI, 0, "UInt")
      NumPut(SIF_ALL, SI, 4, "UInt")
      Return DllCall("User32.dll\GetScrollInfo", "Ptr", This.HWND, "Int", SB, "Ptr", &SI, "UInt")
   }
   ; ===================================================================================================================
   SetScrollInfo(SB, Values) {
      Static SI_SIZE := 28
      Static SIF := {Max: 0x01, Page: 0x02, Pos: 0x04}
      Static Off := {Max: 12, Page: 16, Pos: 20}
      Static SIF_DISABLENOSCROLL := 0x08
      Mask := 0
      VarSetCapacity(SI, SI_SIZE, 0)
      NumPut(SI_SIZE, SI, 0, "UInt")
      For Key, Value In Values {
         If SIF.HasKey(Key) {
            Mask |= SIF[Key]
            NumPut(Value, SI, Off[Key], "UInt")
         }
      }
      If (Mask) {
         NumPut(Mask | SIF_DISABLENOSCROLL, SI, 4, "UInt")
         Return DllCall("User32.dll\SetScrollInfo", "Ptr", This.HWND, "Int", SB, "Ptr", &SI, "UInt", 1, "UInt")
      }
      Return False
   }
   ; ===================================================================================================================
   On_WM_Scroll(LP, Msg, HWND) {
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115 
	   
      If ScrollGUI.Instances.HasKey(HWND) {
         Instance := Object(ScrollGUI.Instances[HWND])
         If ((Msg = WM_HSCROLL) && Instance.ScrollH)
         || ((Msg = WM_VSCROLL) && Instance.ScrollV)
            Return Instance.Scroll(This, LP, Msg, HWND)
      }
   }
   ; ===================================================================================================================
   Scroll(WP, LP, Msg, HWND) {
      Static SB_LINEMINUS := 0, SB_LINEPLUS := 1, SB_PAGEMINUS := 2, SB_PAGEPLUS := 3, SB_THUMBTRACK := 5
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
		Static i := 0
      If (LP <> 0)
         Return 
      SB := (Msg = WM_HSCROLL ? 0 : 1) ; SB_HORZ : SB_VERT
      SC := WP & 0xFFFF
      SD := (Msg = WM_HSCROLL ? This.LineH : This.LineV)
      SI := 0
      If !This.GetScrollInfo(SB, SI)
         Return 
		PA := PN := NumGet(SI, 20, "Int")
		
      If (SC = SB_LINEMINUS)
         PN := PA - SD
      Else If (SC = SB_LINEPLUS)
         PN := PA + SD
      Else If (SC = SB_PAGEMINUS)
         PN := PA - NumGet(SI, 16, "UInt")
      Else If (SC = SB_PAGEPLUS)
         PN := PA + NumGet(SI, 16, "UInt")
      Else If (SC = SB_THUMBTRACK)
         PN := NumGet(SI, 24, "Int")
      If (PA = PN)
         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) { 
		If 0
         {
	         HS := VS := 0
	         If (Msg = WM_HSCROLL)
	            HS := PA - PN
	         Else
	            VS := PA - PN  
	         DllCall("User32.dll\ScrollWindow", "Ptr", This.HWND, "Int", HS, "Int", VS, "Ptr", 0, "Ptr", 0)
			; SW_SCROLLCHILDREN := 0x1
			; SW_INVALIDATE := 0x2
			; SW_ERASE := 0x4
			; SW_SMOOTHSCROLL := 0x10
	        ; DllCall("User32.dll\ScrollWindowEx", "Ptr", This.HWND, "Int", HS, "Int", VS, "Ptr", 0, "Ptr", 0, "Ptr", 0, "Ptr", 0, "Int", 0x10)
         } 
		 Else 
         { 
			This.GetScrollInfo((Msg = WM_HSCROLL), SI)
			c := NumGet(SI, 20, "Int")
	         If (Msg = WM_HSCROLL)
	            op := "NA y" -c " x" -PN
	         Else
	            op := "NA x" -c " y" -PN
			  Gui, % This.HGUI . ":Show", % op
         }
      }
      Return 0
   }
   
   ; ===================================================================================================================
   On_WM_Wheel(LP, Msg, HWND) {
      Static MK_CONTROL := 0x0008
      Static MK_SHIFT := 0x0004
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
      Static WM_MOUSEWHEEL := 0x020A, WM_MOUSEHWHEEL := 0x020E
      ; HWND := WinExist("A") 
      If ScrollGUI.Instances.HasKey(HWND) {
         Instance := Object(ScrollGUI.Instances[HWND])
         If (Instance.RequireCtrl && (This & MK_CONTROL)) || (!Instance.RequireCtrl && !(This & MK_CONTROL))
            If (Instance.WheelH && (Msg = WM_MOUSEHWHEEL))
            || (Instance.WheelH && ((Msg = WM_MOUSEWHEEL) && Instance.UseShift && (This & MK_SHIFT)))
            || (Instance.WheelV && (Msg = WM_MOUSEWHEEL))
               Return Instance.Wheel(This, LP, Msg, HWND)
      }
   }
   ; ===================================================================================================================
   Wheel(WP, LP, Msg, H) {
      Static MK_SHIFT := 0x0004
      Static SB_LINEMINUS := 0, SB_LINEPLUS := 1
      Static WM_MOUSEWHEEL := 0x020A, WM_MOUSEHWHEEL := 0x020E
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
      If (Msg = WM_MOUSEWHEEL) && (WP & MK_SHIFT) && This.UseShift
         Msg := WM_MOUSEHWHEEL
      MSG := (Msg = WM_MOUSEWHEEL ? WM_VSCROLL : WM_HSCROLL)
      SB := ((WP >> 16) > 0x7FFF) || (WP < 0) ? SB_LINEPLUS : SB_LINEMINUS
      Return This.Scroll(SB, 0, MSG, H)
   }
}

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

25 (изменено: kolotilov256, 2020-07-06 12:32:07)

Re: AHK: ScrollBar

serzh82saratov, попробовал использовать ваш код в связке с IniRead/IniWrite, и что-то пошло не так...

При scroll := 0 всё работает, при scroll := 1 уже нет.

Наверно я где-то не до конца корректно использовал ваш код, слишком трудный для меня просто, не до конца вник в его работу) Просьба помочь исправить проблему.

#SingleInstance Force
#Persistent
#NoEnv
#Include %A_Desktop%\Scripts\ScrollGUI.ahk

scroll := 0

if scroll
{
	SetBatchLines, -1 
	Gui, New, +hwndhParentGUI
	Gui, New, +hwndhGui +Parent%hParentGUI%
}

Loop 20
{
	IniRead, param%A_Index%, settings.ini, set, param%A_Index%
}

Loop 20
{
	Gui, Add, Edit, % "x10 y" A_Index*30 " w100 h16 w100 vNewParam" A_Index, % param%A_Index%
}

if scroll
{
	SG1 := New ScrollGUI(HGUI, 130, 300, "-Caption -Resize", 2, 2)
	SG1.SetLine(4, 40) 
	SG1.Show("ScrollGUI1 Title", "x0 y0 NA")
	Gui, %hParentGui%: Show, % "w150 h300"
}
else gui, show
return

GuiClose:
Gui, Submit, NoHide
Loop 20
{
	IniWrite, % NewParam%A_Index%, settings.ini, set, param%A_Index%
}
ExitApp
Post's attachments

ScrollGUI.ahk 23.79 kb, 1 downloads since 2020-07-06 

You don't have the permssions to download the attachments of this post.

26

Re: AHK: ScrollBar

У меня работает.


#SingleInstance Force
#Persistent
#NoEnv 

scroll := 1

if scroll
{
	SetBatchLines, -1 
	Gui, New, +hwndhParentGUI
	Gui, New, +hwndhGui +Parent%hParentGUI%
}

Loop 20
{
	IniRead, param%A_Index%, settings.ini, set, param%A_Index%
}

Loop 20
{
	Gui, Add, Edit, % "x10 y" A_Index*30 " w100 h16 w100 vNewParam" A_Index, % param%A_Index%
}

if scroll
{
	SG1 := New ScrollGUI(HGUI, 130, 300, "-Caption -Resize", 2, 2)
	SG1.SetLine(4, 40) 
	SG1.Show("ScrollGUI1 Title", "x0 y0 NA")
	Gui, %hParentGui%: Show, % "w150 h300"
}
else gui, show
return

GuiClose:
Gui, Submit, NoHide
Loop 20
{
	IniWrite, % NewParam%A_Index%, settings.ini, set, param%A_Index%
}
ExitApp













; https://www.autohotkey.com/boards/viewtopic.php?f=6&t=6316&sid=3d408106d4c70b431530247bb388a9ed
; https://github.com/AHK-just-me/Class_ScrollGUI

; 16:50 05.07.2020 add GetClientPos & ControlGetPos
; 16:03 05.07.2020 add SysGet

; 02:30 05.07.2020 ScrollWindow заменён на GuiShow
; http://forum.script-coding.com/viewtopic.php?pid=140580#p140580

; 23:36 04.07.2020 Добавлены дочерние окна
; http://forum.script-coding.com/viewtopic.php?pid=140567#p140567




; ======================================================================================================================
; Namepace:       ScrollGUI
; Function:       Create a scrollable GUI as a parent for GUI windows.
; Tested with:    AHK 1.1.19.02
; Tested on:      Win 8.1 (x64)
; Change log:     1.0.00.00/2015-02-06/just me        -  initial release on ahkscript.org
;                 1.0.01.00/2015-02-08/just me        -  bug fixes
;                 1.1.00.00/2015-02-09/just me        -  bug fixes and mouse wheel handling
; License:        The Unlicense -> http://unlicense.org
; ======================================================================================================================
Class ScrollGUI {
   Static Instances := []
   Static SM_CXVSCROLL := ScrollGUI.SysGet(2), SM_CYHSCROLL := ScrollGUI.SysGet(3)
   
   ; ===================================================================================================================
   ; __New          Creates a scrollable parent window (ScrollGUI) for the passed GUI.
   ; Parameters:
   ;    HGUI        -  HWND of the GUI 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 (doesn't really make sense).
   ;    Height      -  Height of the client area of the ScrollGUI.
   ;                   Pass 0 to set the client area to the height of the child GUI (doesn't really make sense).
   ;    ----------- Optional:
   ;    GuiOptions  -  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
   ;                   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
   ;                   Add 8 to require the Ctrl key as modifier for wheel messages which shall be processed by the
   ;                   ScrollGUI. Unmodified wheel messages will be passed to the child GUI in this case.
   ; Return values:
   ;    On failure:    False
   ; Remarks:
   ;    The rect of the child GUI is determined using the 'AutoSize' option of the 'Gui, Show' command, after
   ;    '-Caption' is applied to the child GUI.
   ;    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 captured to scroll the ScrollGUI.
   ;    You won't be able to use the wheel to scroll child GUI controls unless Ctrl is required as modifier.
   ; ===================================================================================================================
   __New(HGUI, Width, Height, GuiOptions := "", ScrollBars := 3, Wheel := 0) {
      Static SB_HORZ := 0, SB_VERT = 1
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
      Static WM_MOUSEWHEEL := 0x020A, WM_MOUSEHWHEEL := 0x020E
      Static WS_HSCROLL := "0x100000", WS_VSCROLL := "0x200000"
	  
      RequireCtrl := False
      If (Wheel & 8) {
         RequireCtrl := True
         Wheel &= (8 - 1)
      }
      If ((ScrollBars <> 1) && (ScrollBars <> 2) && (ScrollBars <> 3))
      || ((Wheel <> 0) && (Wheel <> 1) && (Wheel <> 2) && (Wheel <> 3) && (Wheel <> 4))
         Return False
      If !DllCall("User32.dll\IsWindow", "Ptr", HGUI, "UInt")
         Return False
      VarSetCapacity(RC, 16, 0)
      ; Child GUI
      If !This.AutoSize(HGUI, GuiW, GuiH)
         Return False
      Gui, %HGUI%:-Caption -Resize
      Gui, %HGUI%:Show, w%GuiW% h%GuiH% Hide
      MaxH := GuiW
      MaxV := GuiH
      ; Gui, %HGUI%:Show, AutoSize Hide
      ; DllCall("User32.dll\GetWindowRect", "Ptr", HGUI, "Ptr", &RC)
      ; MaxH := NumGet(RC, 8, "Int") - NumGet(RC, 0, "Int")
      ; MaxV := Numget(RC, 12, "Int") - NumGet(RC, 4, "Int")
      LineH := Ceil(MaxH / 20)
      LineV := Ceil(MaxV / 20)
      ; ScrollGUI
      If (Width = 0)
         Width := MaxH
      If (Height = 0)
         Height := MaxV
      MX := MY := Styles := ""
	  this.SizeWSCROLL := this.SizeHSCROLL := 0
      If (ScrollBars & 1) {
         MX := MaxH + 1
         Styles .= " +" . WS_HSCROLL
		 this.SizeHSCROLL := this.SM_CYHSCROLL
      }
      If (ScrollBars & 2) {
         Styles .= " +" . WS_VSCROLL
         MY := MaxV + 1
		 this.SizeVSCROLL := this.SM_CXVSCROLL
      } 
      Gui, New, %GuiOptions% %Styles% +hwndHWND
      Gui, %HWND%:Show, w%Width% h%Height% Hide
      If (MX <> "") || (MY <> "")
         Gui, %HWND%:+MaxSize%MX%x%MY%
      DllCall("User32.dll\GetClientRect", "Ptr", HWND, "Ptr", &RC)
	  PageH := NumGet(RC, 8, "Int") + 1
      PageV := Numget(RC, 12, "Int") + 1 
      ; Instance variables
      This.HWND := HWND
      This.HGUI := HGUI
      This.Width := Width
      This.Height := Height
      This.RequireCtrl := RequireCtrl
      This.UseShift := False
      If (ScrollBars & 1) {
         This.SetScrollInfo(SB_HORZ, {Max: MaxH, Page: PageH, Pos: 0})
         OnMessage(WM_HSCROLL, "ScrollGUI.On_WM_Scroll")
         If (Wheel & 1)
            OnMessage(WM_MOUSEHWHEEL, "ScrollGUI.On_WM_Wheel")
         Else If (Wheel & 4) {
            OnMessage(WM_MOUSEWHEEL, "ScrollGUI.On_WM_Wheel")
            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 (ScrollBars & 2) {
         This.SetScrollInfo(SB_VERT, {Max: MaxV, Page: PageV, Pos: 0})
         OnMessage(WM_VSCROLL, "ScrollGUI.On_WM_Scroll")
         If (Wheel & 6)
            OnMessage(WM_MOUSEWHEEL, "ScrollGUI.On_WM_Wheel")
         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
	  WinGet, GuiStyle, Style, ahk_id %HGUI%
	  If (GuiStyle & 0x40000000)  ; WS_CHILD
	  {
         WS_POPUP := 0x80000000, WS_CHILD := 0x40000000
	  	 Gui, %HWND%:+%WS_CHILD% -%WS_POPUP%
		 This.hParentGui := DllCall("GetParent", "Ptr", HGUI)
	  	 DllCall("SetParent", "Ptr", HWND, "Ptr", This.hParentGui)
		 this.GetClientPos(This.hParentGui, left, top)
		 This.ParentClientX := left
		 This.ParentClientY := top
	  }    
	  WinGetPos, , , W, H, ahk_id %HWND%
	  This.GuiSizeW := W
      This.GuiSizeH := H
      Gui, %HGUI%:+parent%HWND%
      Gui, %HGUI%:Show, x0 y0
      This.Instances[HWND] := &This
   }
   ; ===================================================================================================================
   ; __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")
      W := This.Width
      H := This.Height
      Gui, % This.HWND . ":Show", %ShowOptions% w%W% h%H%, %Title%
      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.Instances.HasKey(This.HWND) {
         Gui, % This.HWND . ":Destroy"
         This.Instances.Remove(This.HWND, "")
         Return True
      }
   }
   SysGet(N) {
      SysGet, OutputVar, %N% 
      Return OutputVar
   }
	GetClientPos(hwnd, ByRef left, ByRef top, ByRef w := "", ByRef h := "") {
		Static _ := VarSetCapacity(pwi, 60, 0)
		DllCall("GetWindowInfo", "Ptr", hwnd, "Ptr", &pwi)
		left := NumGet(pwi, 20, "Int") - NumGet(pwi, 4, "Int")
		top := NumGet(pwi, 24, "Int") - NumGet(pwi, 8, "Int")
		w := NumGet(pwi, 28, "Int") - NumGet(pwi, 20, "Int")
		h := NumGet(pwi, 32, "Int") - NumGet(pwi, 24, "Int")
	}
   ; ===================================================================================================================
   ; AdjustToParent Adjust the scroll bars to the new parent dimensions.
   ; Parameters:
   ;    Width       -  New width of the client area of the ScrollGUI in pixels.
   ;                   Default: 0 -> current width
   ;    Height      -  New height of the client area of the ScrollGUI in pixels.
   ;                   Default: 0 -> current height
   ; Return values:
   ;    On success: True
   ;    On failure: False
   ; Remarks:
   ;    Call this method whenever the dimensions of the parent GUI have changed, e.g. after the GUI was resized,
   ;    restored or maximized. If either Width or Height is zero, both values will be set to the current dimensions.
   ; ===================================================================================================================
   AdjustToParent(Width := 0, Height := 0) {
      If (Width = 0) || (Height = 0) {
         VarSetCapacity(RC, 16, 0)
         DllCall("User32.dll\GetClientRect", "Ptr", This.HWND, "Ptr", &RC)
         Width := NumGet(RC, 8, "Int")
         Height := Numget(RC, 12, "Int") 
      } 
	  If This.hParentGui
	  { 
	     ControlGetPos, GuiX, GuiY, GuiW, GuiH, , %  "ahk_id" This.HWND 
	     This.GuiPosX := GuiX - This.ParentClientX
	     This.GuiPosY := GuiY - This.ParentClientY
	     This.GuiSizeW := GuiW
	     This.GuiSizeH := GuiH
	  }
      SH := SV := 0
      If This.ScrollH {
         If (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 {
         If (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)
	  {
		; ScrollWindow при ресайзе бывает зависает, надо перевести на Gui
		; SH и SV бывают редко оба со значением
		  DllCall("User32.dll\ScrollWindow", "Ptr", This.HWND, "Int", SH, "Int", SV, "Ptr", 0, "Ptr", 0)
		   
			; This.GetScrollInfo(!ScrollH, SI)
			; c := NumGet(SI, 20, "Int")
			; If (ScrollH)
				; op := "NA y" -c " x" -PN
			; Else
				; op := "NA x" -c " y" -PN
			; Gui, % This.HGUI . ":Show", % op
			; ToolTip % c "`n" PN "`n" op "`n" PosV 
	  }
      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 client area of the child GUI is determined using the 'AutoSize' option of a 'Gui, Show' command.
   ; ===================================================================================================================
   AdjustToChild() {
      Static WS_HSCROLL := 0x100000, WS_VSCROLL := 0x200000
      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
      MX := This.ScrollH ? MaxH + 1 : ""
      MY := This.ScrollV ? MaxV + 1 : ""
      If (MX <> "") || (MY <> "") {
         Gui, % This.HWND . ":+MaxSize" . MX . "x" . MY
         W := ((MX <> "") && (MX < PrevW)) ? "w" . MX : ""
         H := ((MY <> "") && (MY < PrevH)) ? "h" . MY : ""
         If (W || H ) {
            Gui, % This.HWND . ":Show", %W% %H%
            If (W) {
               This.Width := MX
               This.SetScrollInfo(0, {Page: MX + 1})
            }
            If (H) {
               This.Height := MY
               This.SetScrollInfo(1, {Page: MY + 1})
            }
         }
      }
      ; Gui, % This.HGUI . ":Show", x%XC% y%YC% AutoSize
      ; DllCall("User32.dll\GetWindowRect", "Ptr", This.HGUI, "Ptr", &RC)
      ; MaxH := NumGet(RC, 8, "Int") - NumGet(RC, 0, "Int")
      ; MaxV := Numget(RC, 12, "Int") - NumGet(RC, 4, "Int")
      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.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) {
      Static SB_HORZ := 0, SB_VERT = 1
      SB--
      If (SB <> SB_HORZ) && (SB <> SB_VERT)
         Return False
      If (SB = SB_HORZ)
         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) {
      Static SB_HORZ := 0, SB_VERT = 1
      SB--
      If (SB <> SB_HORZ) && (SB <> SB_VERT)
         Return False
      If (SB = SB_HORZ)
         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) {
      Static SB_HORZ := 0, SB_VERT = 1
      SB--
      If (SB <> SB_HORZ) && (SB <> SB_VERT)
         Return False
      If (SB = SB_HORZ)
         This.PageH := Page
      Else
         This.PageV := Page
      Return This.SetScrollInfo(SB, {Page: Page})
   }
   ; ===================================================================================================================
   ; Methods for internal or system use!!!
   ; ===================================================================================================================
   AutoSize(HGUI, ByRef Width, ByRef Height) {
      DHW := A_DetectHiddenWindows
      DetectHiddenWindows, On
      VarSetCapacity(RECT, 16, 0)
      Width := Height := 0
      HWND := HGUI
      CMD := 5 ; GW_CHILD
      L := T := R := B := LH := TH := ""
      While (HWND := DllCall("GetWindow", "Ptr", HWND, "UInt", CMD, "UPtr")) && (CMD := 2) {
         WinGetPos, X, Y, W, H, ahk_id %HWND%
         W += X, H += Y
         WinGet, Styles, Style, ahk_id %HWND%
         If (Styles & 0x10000000) { ; WS_VISIBLE
            If (L = "") || (X < L)
               L := X
            If (T = "") || (Y < T)
               T := Y
            If (R = "") || (W > R)
               R := W
            If (B = "") || (H > B)
               B := H
         }
         Else {
            If (LH = "") || (X < LH)
               LH := X
            If (TH = "") || (Y < TH)
               TH := Y
         }
      }
      DetectHiddenWindows, %DHW%
      If (LH <> "") {
         VarSetCapacity(POINT, 8, 0)
         NumPut(LH, POINT, 0, "Int")
         DllCall("ScreenToClient", "Ptr", HGUI, "Ptr", &POINT)
         LH := NumGet(POINT, 0, "Int")
      }
      If (TH <> "") {
         VarSetCapacity(POINT, 8, 0)
         NumPut(TH, POINT, 4, "Int")
         DllCall("ScreenToClient", "Ptr", HGUI, "Ptr", &POINT)
         TH := NumGet(POINT, 4, "Int")
      }
      NumPut(L, RECT, 0, "Int"), NumPut(T, RECT,  4, "Int")
      NumPut(R, RECT, 8, "Int"), NumPut(B, RECT, 12, "Int")
      DllCall("MapWindowPoints", "Ptr", 0, "Ptr", HGUI, "Ptr", &RECT, "UInt", 2)
      Width := NumGet(RECT, 8, "Int") + (LH <> "" ? LH : NumGet(RECT, 0, "Int"))
      Height := NumGet(RECT, 12, "Int") + (TH <> "" ? TH : NumGet(RECT,  4, "Int"))
      Return True
   }
   ; ===================================================================================================================
   GetScrollInfo(SB, ByRef SI) {
      Static SI_SIZE := 28
      Static SIF_ALL := 0x17
      VarSetCapacity(SI, SI_SIZE, 0)
      NumPut(SI_SIZE, SI, 0, "UInt")
      NumPut(SIF_ALL, SI, 4, "UInt")
      Return DllCall("User32.dll\GetScrollInfo", "Ptr", This.HWND, "Int", SB, "Ptr", &SI, "UInt")
   }
   ; ===================================================================================================================
   SetScrollInfo(SB, Values) {
      Static SI_SIZE := 28
      Static SIF := {Max: 0x01, Page: 0x02, Pos: 0x04}
      Static Off := {Max: 12, Page: 16, Pos: 20}
      Static SIF_DISABLENOSCROLL := 0x08
      Mask := 0
      VarSetCapacity(SI, SI_SIZE, 0)
      NumPut(SI_SIZE, SI, 0, "UInt")
      For Key, Value In Values {
         If SIF.HasKey(Key) {
            Mask |= SIF[Key]
            NumPut(Value, SI, Off[Key], "UInt")
         }
      }
      If (Mask) {
         NumPut(Mask | SIF_DISABLENOSCROLL, SI, 4, "UInt")
         Return DllCall("User32.dll\SetScrollInfo", "Ptr", This.HWND, "Int", SB, "Ptr", &SI, "UInt", 1, "UInt")
      }
      Return False
   }
   ; ===================================================================================================================
   On_WM_Scroll(LP, Msg, HWND) {
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115 
	   
      If ScrollGUI.Instances.HasKey(HWND) {
         Instance := Object(ScrollGUI.Instances[HWND])
         If ((Msg = WM_HSCROLL) && Instance.ScrollH)
         || ((Msg = WM_VSCROLL) && Instance.ScrollV)
            Return Instance.Scroll(This, LP, Msg, HWND)
      }
   }
   ; ===================================================================================================================
   Scroll(WP, LP, Msg, HWND) {
      Static SB_LINEMINUS := 0, SB_LINEPLUS := 1, SB_PAGEMINUS := 2, SB_PAGEPLUS := 3, SB_THUMBTRACK := 5
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
		Static i := 0
      If (LP <> 0)
         Return 
      SB := (Msg = WM_HSCROLL ? 0 : 1) ; SB_HORZ : SB_VERT
      SC := WP & 0xFFFF
      SD := (Msg = WM_HSCROLL ? This.LineH : This.LineV)
      SI := 0
      If !This.GetScrollInfo(SB, SI)
         Return 
		PA := PN := NumGet(SI, 20, "Int")
		
      If (SC = SB_LINEMINUS)
         PN := PA - SD
      Else If (SC = SB_LINEPLUS)
         PN := PA + SD
      Else If (SC = SB_PAGEMINUS)
         PN := PA - NumGet(SI, 16, "UInt")
      Else If (SC = SB_PAGEPLUS)
         PN := PA + NumGet(SI, 16, "UInt")
      Else If (SC = SB_THUMBTRACK)
         PN := NumGet(SI, 24, "Int")
      If (PA = PN)
         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) {
		 If 0
         {
	         HS := VS := 0
	         If (Msg = WM_HSCROLL)
	            HS := PA - PN
	         Else
	            VS := PA - PN
			 ; https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-scrollwindow
	         DllCall("User32.dll\ScrollWindow", "Ptr", This.HGUI, "Int", HS, "Int", VS, "Ptr", 0, "Ptr", &RECT)
         } 
		 Else 
         {
			This.GetScrollInfo((Msg = WM_HSCROLL), SI)
			c := NumGet(SI, 20, "Int")
			If (Msg = WM_HSCROLL)
				op := "NA y" -c " x" -PN
			Else
				op := "NA x" -c " y" -PN
			Gui, % This.HGUI . ":Show", % op
         }
      }
      Return 0
   }
   
   ; ===================================================================================================================
   On_WM_Wheel(LP, Msg, HWND) {
      Static MK_CONTROL := 0x0008
      Static MK_SHIFT := 0x0004
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
      Static WM_MOUSEWHEEL := 0x020A, WM_MOUSEHWHEEL := 0x020E
      ; HWND := WinExist("A") 
      If ScrollGUI.Instances.HasKey(HWND) {
         Instance := Object(ScrollGUI.Instances[HWND])
         If (Instance.RequireCtrl && (This & MK_CONTROL)) || (!Instance.RequireCtrl && !(This & MK_CONTROL))
            If (Instance.WheelH && (Msg = WM_MOUSEHWHEEL))
            || (Instance.WheelH && ((Msg = WM_MOUSEWHEEL) && Instance.UseShift && (This & MK_SHIFT)))
            || (Instance.WheelV && (Msg = WM_MOUSEWHEEL))
               Return Instance.Wheel(This, LP, Msg, HWND)
      }
   }
   ; ===================================================================================================================
   Wheel(WP, LP, Msg, H) {
      Static MK_SHIFT := 0x0004
      Static SB_LINEMINUS := 0, SB_LINEPLUS := 1
      Static WM_MOUSEWHEEL := 0x020A, WM_MOUSEHWHEEL := 0x020E
      Static WM_HSCROLL := 0x0114, WM_VSCROLL := 0x0115
      If (Msg = WM_MOUSEWHEEL) && (WP & MK_SHIFT) && This.UseShift
         Msg := WM_MOUSEHWHEEL
      MSG := (Msg = WM_MOUSEWHEEL ? WM_VSCROLL : WM_HSCROLL)
      SB := ((WP >> 16) > 0x7FFF) || (WP < 0) ? SB_LINEPLUS : SB_LINEMINUS
      Return This.Scroll(SB, 0, MSG, H)
   }
}


По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

27 (изменено: serzh82saratov, 2020-07-08 19:01:42)

Re: AHK: ScrollBar

serzh82saratov пишет:

Если ScrollWindow заменить на GuiShow, то никаких тормозов нет с любым количеством контролов.

Надо бы ещё в AdjustToParent ScrollWindow заменить, иногда несистемно зависает при ресайзе. У меня не получилось с первой попытки.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

28

Re: AHK: ScrollBar

serzh82saratov, скопировал в точности ваш код. Не работает.
Т.е я запускаю, открывается окошко gui и в нём в каждой строке ERROR. Я ввожу туда какой-то текст, далее закрываю gui окно. Перезагружаю скрипт, открывается окошко gui и в нём в каждой строке простая пустота, а должен быть мой текст.

29

Re: AHK: ScrollBar

kolotilov256 пишет:

а должен быть мой текст

У меня нет вашего текста.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

30 (изменено: serzh82saratov, 2020-07-08 20:22:26)

Re: AHK: ScrollBar

Тут ошибка.


Gui, Submit, NoHide

надо


Gui, %hGui%:Submit, NoHide
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

31

Re: AHK: ScrollBar

Вы сохраняете пустоту, я думал вы проверили свой ини файл, перед тем как описали свою проблему.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru
Win10x64 v2004, AutoHotkey_L v1.1.33.02 (Unicode 32-bit). AhkSpy, Hotkey, ClockGui

32

Re: AHK: ScrollBar

serzh82saratov, во. Теперь работает, благодарю.