[solved] How to make my simple GUI window scrollable? Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
Benny-D
Posts: 302
Joined: 12 Mar 2014, 10:09

[solved] How to make my simple GUI window scrollable?

07 Feb 2020, 03:58

Here I have a simple code of a GUI window:

Code: Select all

FWC := "55a0ff" ; first window window's color
FWFS := "16" ; first window window's font size
FWFT := "Verdana" ; first window window's font

gosub, CreateFirstWindow
gosub, Go
return

CreateFirstWindow:
Gui New,  hwndFW
Gui +LabelFW  
Gui, % FW . ":color", % FWC
Gui, % FW . ":font", % "s" . FWFS, % FWFT
Gui, % FW . ":add", Button,  , Something
Gui, % FW . ":add", Button,  , Something
Gui, % FW . ":add", Button,  , Something
Gui, % FW . ":add", Button,  , Something
Gui, % FW . ":add", Button,  , Something
Gui, % FW . ":add", Button, x+10 gFWClose , Exit
return

Go:
Gui, % FW . ":show", w220 h265, 1st window
return

FWClose:
Gui % FW . ":Default" 
Gui, % FW . ":destroy"
exitapp
return
Here is what it produces:
Image

As it can be seen, some of the buttons don't fit in, which is deliberately done so in the script.
I need to make this window scrollable, that is, having the possibility of scrolling it vertically and horizontally so as to see all the controls that don't fit in the specified client area.

How could I do that?

I know that I probably have to use DllCalls like "ScrollWindow" and "SetScrollInfo", but I don't know how.
Can anyone show me, please, how to apply them to my simple code?
Last edited by Benny-D on 11 Feb 2020, 06:00, edited 1 time in total.
wbm1113
Posts: 18
Joined: 28 Aug 2018, 11:19

Re: How to make my simple GUI window scrollable?

07 Feb 2020, 21:07

There's no simple way to do it, unfortunately: https://autohotkey.com/board/topic/26033-scrollable-gui-proof-of-concept/page-4

I usually just stick to using Tab controls when I need to cram pack a GUI.
User avatar
Benny-D
Posts: 302
Joined: 12 Mar 2014, 10:09

Re: How to make my simple GUI window scrollable?

08 Feb 2020, 00:25

Thank you for the link. But can you give me a clue as to which script from that thread I could use? Lexikos's script seems to be good, but the scroll bars don't seem to get dragged smoothly and often just jump back to the initial position.
xroot
Posts: 40
Joined: 21 Jun 2019, 08:45

Re: How to make my simple GUI window scrollable?

09 Feb 2020, 09:37

Hi, Benny-D
Here is a simple sample I wrote in V2.0-a108 to scroll a GUI window.
I hope it helps you in making your GUI scrollable.

Main GUI

Code: Select all

#include winapi.ahk

global si := SCROLLINFO.New()
global w  := 500,h := 500,vt := 50,ht := 50,hs := 5,vs := 5,oldPos := 0

RandomSeed Random(1,2**30)

global Gui    := GuiCreate(,"Scroll Gui")
Gui.BackColor := Random(1,2**24)
Gui.OnEvent "Close",(*) => ExitApp()
Gui.OnEvent "Escape",(*) => ExitApp()

Loop 6{
    But := Gui.Add("Button","w150 h75 ","Button " a_index)
    But.SetFont "s18 bold underline","Times New Roman"
}

But := Gui.Add("Button","x310 y370 w120 h45","Exit")
But.SetFont "s18 bold underline","Times New Roman"
But.OnEvent "Click",(*) => ExitApp()

OnMessage WM_HScroll,"Scroll_Msg"
OnMessage WM_VScroll,"Scroll_Msg"

si.fMask := SIF_All
si.nMax  := h
si.nPage := vt

SetScrollInfo Gui.hWnd,SB_VERT,si.Ptr.Ptr,True

si.nMax  := w
si.nPage := ht

SetScrollInfo Gui.hWnd,SB_HORZ,si.Ptr.Ptr,True

Gui.Show "w" w "h400"
WINAPI.AHK

Code: Select all

global SB_HORZ          := 0
global SB_VERT          := 1

global SIF_POS          := 4
global SIF_PAGE         := 2
global SIF_RANGE        := 1
global SIF_TRACKPOS     := 16
global SIF_ALL          := SIF_RANGE|SIF_PAGE|SIF_POS|SIF_TRACKPOS

global SB_LINELEFT      := 0
global SB_LINERIGHT     := 1
global SB_PAGELEFT      := 2
global SB_PAGERIGHT     := 3
; global SB_THUMBPOSITION := 4
global SB_THUMBTRACK    := 5
global SB_LINEDOWN      := 1
global SB_LINEUP        := 0
global SB_PAGEDOWN      := 3
global SB_PAGEUP        := 2
; global SB_SCROLLCARET   := 4
; global SB_TOP           := 6
; global SB_BOTTOM        := 7
global WM_HSCROLL := 0x114
global WM_VSCROLL := 0x115

GetScrollInfo(hwnd,nbar,lpsi){
    return DllCall("GetScrollInfo","ptr",hwnd,"int",nbar,"ptr",lpsi,"int")
}

ScrollWindow(hwnd,xamount,yamount,lprect,lpcliprect){
    return DllCall("ScrollWindow","ptr",hwnd,"int",xamount,"int",yamount,"ptr",lprect,"ptr",lpcliprect,"int")
}

SetScrollInfo(hwnd,nbar,lpsi,redraw){
    return DllCall("SetScrollInfo","ptr",hwnd,"int",nbar,"ptr",lpsi,"int",redraw,"int")
}

HiWord(iLong){
    Return (iLong >> 16)
}

LoWord(iLong){
   Return (iLong & 0xFFFF)
}

Scroll_Bar(HorzVert,wParam){
    GetScrollInfo Gui.hWnd,HorzVert,si.Ptr.Ptr
    oldPos := si.nPos
    Switch LoWord(wParam){
        Case SB_LineLeft,SB_LineUp:
            si.nPos := si.nPos - (HorzVert) ? hs : vs
        Case SB_PageLeft,SB_PageUp:
            si.nPos := si.nPos - si.nPage
        Case SB_LineRight,SB_LineDown:
            si.nPos := si.nPos + (HorzVert) ? hs : vs
        Case SB_PageRight,SB_PageDown:
            si.nPos := si.nPos + si.nPage
        Case SB_ThumbTrack:
            si.nPos := HiWord(wParam)
        Default:
            Return
    }
    si.nPos := Max(si.nMin,Min(si.nPos,si.nMax - si.nPage + HorzVert))
    SetScrollInfo Gui.hWnd,HorzVert,si.Ptr.Ptr,1
}

Scroll_Msg(wParam,lParam,umsg,hwnd){
    Switch umsg{
        Case WM_HScroll:
            Scroll_Bar SB_HORZ,wParam
            ScrollWindow hwnd,oldPos - si.nPos,0,0,0
        Case WM_VScroll:
            Scroll_Bar SB_VERT,wParam
            ScrollWindow hwnd,0,oldPos - si.nPos,0,0
    }
}

Class SCROLLINFO{
    ptr := BufferAlloc(28,0)
    __New(){
        NumPut "uint",this.ptr.size,this.ptr
    }
    cbSize[] => NumGet(this.ptr,"uint")
    fMask[]{
        get => NumGet(this.ptr,4,"uint")
        set => NumPut("uint",value,this.ptr,4)
    }
    nMin[]{
        get => NumGet(this.ptr,8,"int")
        set => NumPut("int",value,this.ptr,8)
    }
    nMax[]{
        get => NumGet(this.ptr,12,"int")
        set => NumPut("int",value,this.ptr,12)
    }
    nPage[]{
        get => NumGet(this.ptr,16,"uint")
        set => NumPut("uint",value,this.ptr,16)
    }
    nPos[]{
        get => NumGet(this.ptr,20,"int")
        set => NumPut("ptr",value,this.ptr,20)
    }
    nTrackPos[]{
        get => NumGet(this.ptr,24,"int")
        set => NumPut("ptr",value,this.ptr,24)
    }
}
User avatar
Benny-D
Posts: 302
Joined: 12 Mar 2014, 10:09

Re: How to make my simple GUI window scrollable?

09 Feb 2020, 11:19

Hi, xroot!

Thank you for this script, but I am afraid I don't know what to do with it. I've created the "winapi.ahk" file with your second script inside and then a second .ahk file with your first script inside. But when I tried to run the second file, I only got an error message saying:
Error at line 47 in #include file

"winapi.ahk".

Line Text: GetScrollInfo Gui.hWnd,HorzVert,si.Ptr.Ptr
Error: This line does not contain a recognized action.

The program will exit.
I must be missing something basic here.
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: How to make my simple GUI window scrollable?

09 Feb 2020, 20:08

You’re not running it with AHK version 2 then
just me
Posts: 9451
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: How to make my simple GUI window scrollable?

10 Feb 2020, 04:33

Benny-D wrote:
07 Feb 2020, 03:58
...
I know that I probably have to use DllCalls like "ScrollWindow" and "SetScrollInfo", but I don't know how.
...
If you think you'd have to call the ScrollWindow and/or SetScrollInfo functions, why don't you search the forums for this terms? scrollable GUI might provide even more results.
User avatar
Benny-D
Posts: 302
Joined: 12 Mar 2014, 10:09

Re: How to make my simple GUI window scrollable?

10 Feb 2020, 05:05

@kczx3
I've downloaded by clicking on "Current Version" from the main website. There was also "V2 Alfa Version" button there, but I was afraid to download that one because I had never been running my scripts with V2 Alfa. Should I try it? What risks am I running then? Will all my scripts still work?
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: How to make my simple GUI window scrollable?

10 Feb 2020, 06:53

No they won’t. I’m just saying that because the user specifically said the code provided was for v2
User avatar
Benny-D
Posts: 302
Joined: 12 Mar 2014, 10:09

Re: How to make my simple GUI window scrollable?

10 Feb 2020, 07:29

@kczx3 "I’m just saying that because the user specifically said the code provided was for v2"

- Gosh! How did I miss that! Thank you.

Is there any source here saying briefly and in general terms about why V2 is better than V1?
Is it like V2 is inevitable in the future and sooner or later everyone will have to switch to V2?

I just read this page: https://www.autohotkey.com/v2/ and was literally terrified by how many things have been changed.
User avatar
Benny-D
Posts: 302
Joined: 12 Mar 2014, 10:09

Re: How to make my simple GUI window scrollable?

10 Feb 2020, 08:16

@just me: "If you think you'd have to call the ScrollWindow and/or SetScrollInfo functions, why don't you search the forums for this terms?"

-- I did, but there were so many different scripts that I got overwhelmed by them. So I decided to ask a question for a simple way - in case such one existed. Besides, I wasn't really sure that ScrollWindow or SetScrollInfo were the most simple ways, I mean understandable for me.
Odlanir
Posts: 659
Joined: 20 Oct 2016, 08:20

Re: How to make my simple GUI window scrollable?  Topic is solved

10 Feb 2020, 11:51

You can try this. I've copied from someone else in the forum but I don't remember who.
It must be run in 32 bit mode.

Code: Select all

#SingleInstance force
#Persistent
#NoEnv

if (A_PtrSize = 8) {
   Run, "C:\Program Files\AutoHotkey\AutoHotkeyU32.exe" %A_ScriptFullPath%
   ExitApp
}   

SetTitleMatchMode 2
SetWorkingDir %A_ScriptDir%

OnMessage(0x115, "OnScroll") ; WM_VSCROLL
OnMessage(0x114, "OnScroll") ; WM_HSCROLL
numX = 10
Gui, +Resize +0x300000 ; WS_VSCROLL | WS_HSCROLL
Gui, Add, Button,x10 y30 w160 h30 vBut1 gGo, Top
Loop, %numX%
    Gui, Add, Edit, R5 W160 vEd%A_Index%, Edit %A_Index%
Gui, Add, Button,x10 w160 h30 vBut2 gGo, Bottom
Gui, Add, text, vTxt, %A_Space%
Gui, Show, W200 H200

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

return

GuiSize:
    UpdateScrollBars(A_Gui, A_GuiWidth, A_GuiHeight)
return

GuiEscape:
GuiClose:
    ExitApp

Go:
    MsgBox % "You pressed the button : " A_GuiControl
return

#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)
}
____________________________________________________________________________
Windows 10 Pro 64 bit - Autohotkey v1.1.30.01 64-bit Unicode
User avatar
Benny-D
Posts: 302
Joined: 12 Mar 2014, 10:09

Re: How to make my simple GUI window scrollable?

10 Feb 2020, 12:00

@Odlanir,
Thank you! This script works really well and the scroll bars are scrolled very smoothly without jumping back after being dragged for a while.

You said "It must be run in 32 bit mode", but I've just run it on my 64-bit version. What kind of pitfalls am I running into if I continue using this script in my 64-bit version?
Odlanir
Posts: 659
Joined: 20 Oct 2016, 08:20

Re: How to make my simple GUI window scrollable?

10 Feb 2020, 13:17

Maybe you miss this at the very top of the script:

Code: Select all

if (A_PtrSize = 8) {
   Run, "C:\Program Files\AutoHotkey\AutoHotkeyU32.exe" %A_ScriptFullPath%
   ExitApp
}   
It silentily run your code in 32 bit.
If the pointersize is 8 ( which is true, in case of a 64 bit run ) it starts again the program in 32 bit with the run instruction.
Hope is clear.
Cheers
____________________________________________________________________________
Windows 10 Pro 64 bit - Autohotkey v1.1.30.01 64-bit Unicode
User avatar
Benny-D
Posts: 302
Joined: 12 Mar 2014, 10:09

Re: How to make my simple GUI window scrollable?

10 Feb 2020, 21:35

@Odlanir,

I just tried to run your code without that part at the top and the scrollbars began to jump back after scrolling.

So it will only run this particular script in 32 and my all other scripts will still be run in 64, right?

But what if I want to put something of Unicode on the GUI window of this script, for example, create Text control in Chinese or Japanese, does running this script in 32 mean I won't be able to do that?

If I still can do that, than I honestly don't understand the difference between 32 and 64 versions.
Odlanir
Posts: 659
Joined: 20 Oct 2016, 08:20

Re: How to make my simple GUI window scrollable?

11 Feb 2020, 04:52

Benny-D wrote:I just tried to run your code without that part at the top and the scrollbars began to jump back after scrolling.
That's normal 'cause, as I stated, it must be run in 32 bit mode.
Benny-D wrote:So it will only run this particular script in 32 and my all other scripts will still be run in 64, right?
Yes.
Benny-D wrote:But what if I want to put something of Unicode on the GUI window of this script, for example, create Text control in Chinese or Japanese, does running this script in 32 mean I won't be able to do that?
The AutoHotkeyU32.exe means that the code it will run in Unicode 32 bit.
Benny-D wrote:If I still can do that, than I honestly don't understand the difference between 32 and 64 versions.
If the code is written for a 32 bit version all the DllCall, NumGet/NumPut, VarSetCapacity and struct sizes/offsets are not totally compatible with the 64 bit AutoHotkey.exe.

To be more clear, a standard 64 bit Unicode installation of AutoHotkey writes these exe in the Autohotkey folder:
  • AutoHotkey.exe Default exe 64 bit Unicode.
    AutoHotkeyA32.exe Ascii 32 bit exe.
    AutoHotkeyU32.exe Unicode 32 bit exe.
    AutoHotkeyU64.exe Unicode 64 bit exe ( same as AutoHotkey.exe )
You can run your script with any of these exe without affecting the normal behaviour of other scripts.

EDIT:
The initial part of the script should be:

Code: Select all

if (A_PtrSize = 8) {
   SplitPath, A_AhkPath,, dir
   Run, "%dir%\AutoHotkeyU32.exe" "%A_ScriptFullPath%"
   ExitApp
}   

to dinamically get the AutoHotkey folder and with quotes around the A_ScriptFullPath to allow a scriptName with blank.
____________________________________________________________________________
Windows 10 Pro 64 bit - Autohotkey v1.1.30.01 64-bit Unicode
User avatar
Benny-D
Posts: 302
Joined: 12 Mar 2014, 10:09

Re: How to make my simple GUI window scrollable?

11 Feb 2020, 05:59

@Odlanir,
Thank you very much for the detailed answer and for the script you've provided.
just me
Posts: 9451
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: How to make my simple GUI window scrollable?

11 Feb 2020, 06:09

Benny-D wrote:
10 Feb 2020, 08:16
...
-- I did, but there were so many different scripts that I got overwhelmed by them.
...
Class_ScrollGUI.ahk provides a short How to use document and a sample script. It should run on 32-bit and 64-bit without any 'tricks'. It will need only a few statements to make it work with your GUI.
User avatar
Benny-D
Posts: 302
Joined: 12 Mar 2014, 10:09

Re: [solved] How to make my simple GUI window scrollable?

11 Feb 2020, 07:51

@just me

Can you, please, tell me where I could find that document? I typed "Class_ScrollGUI.ahk" into the search field of the AHK Help file that I downloaded (Version 1.1.30.01), but it didn't return any results.
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: [solved] How to make my simple GUI window scrollable?

11 Feb 2020, 07:54

Just google it. There are no user contributed scripts in the help file.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Anput, Google [Bot], Nerafius and 132 guests