AutoHotkey Community

It is currently May 26th, 2012, 5:47 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 46 posts ]  Go to page 1, 2, 3, 4  Next
Author Message
PostPosted: February 10th, 2008, 9:24 pm 
Offline

Joined: June 26th, 2006, 6:14 pm
Posts: 1379
Location: USA
Many Thanks to the Guest Jamey in this post: http://www.autohotkey.com/forum/viewtopic.php?t=3730
If it originally came form someone else, let me know please.


This is just something I was playing with....maybe someone can make it better. Just posting for fun.

There are currently multiple bugs....tabbing through controls does not work....some issues with resizing....etc etc...

I do not care to really do anything more with it, so if some one makes enhancements, post them here, and I will refer to them from the first post.

Here is the code:
Code:
DetectHiddenWindows, On
Gui, 1:+LastFound +0x200000 +Resize +0x2000000
hGui := WinExist()
Gui, 1:Add, Edit, r2 w150 , Edit 1
Gui, 1:Add, Edit, r2 w150 , Edit 2
Gui, 1:Add, Edit, r2 w150 , Edit 3
Gui, 1:Add, Edit, r2 w150 , Edit 4
Gui, 1:Add, Edit, ym r2 w150 , Edit 5
Gui, 1:Add, Edit, r2 w150 , Edit 6
Gui, 1:Add, Edit, r2 w150 , Edit 7
Gui, 1:Add, Edit, r2 w150 , Edit 8
Gui, 1:Add, Button, gGo, Go
Gui, 1:Show, Hide
ScrollInit()
Gui, 1:Show, h100   
Return

ScrollInit() {
   Global
   VarSetCapacity(SCROLLBAR_INFO, 28, 0)   ;Allocate SCROLLBAR_INFO structure and zero it
   NumPut(28, &SCROLLBAR_INFO)         ;Initialize its count-bytes parameter
   NumPut(0x17, &SCROLLBAR_INFO + 4)      ;Initialize the mask for what properties to get or set, SIF_ALL = 0x17
   SetScrollBar(hGui, 0, 100, 10, 0)
   C_Create(1)
   GuiWinProc := RegisterCallback("GuiWindowProc", ""  ; "" to avoid fast-mode for subclassing.
       , 4, hGui)  ; Must specify exact ParamCount when EventInfo parameter is present.
   GuiWinProcOld := DllCall("SetWindowLong", UInt, hGui, Int, -4  ; -4 is GWL_WNDPROC
       , Int, GuiWinProc, UInt)  ; Return value must be set to UInt vs. Int.
   ConWinProc := RegisterCallback("ConWinProc", ""  ; "" to avoid fast-mode for subclassing.
       , 4, hGui)  ; Must specify exact ParamCount when EventInfo parameter is present.
   ConWinProcOld := DllCall("SetWindowLong", UInt, hContainer, Int, -4  ; -4 is GWL_WNDPROC
       , Int, ConWinProc, UInt)  ; Return value must be set to UInt vs. Int.
   }

C_Create(GuiNum,Height=0,Width=0) {
   global hContainer, Container
   Gui %GuiNum%:+LastFound
   hGui := WinExist()
   If !Height && !Width
      WinGetPos,,, Width, Height, ahk_id %hGui%
   Gui %GuiNum%:Add, Text,x0 y0 h%Height% w%Width% +0x4000000 +0x2000000 hwndhContainer vContainer
   WinGet, CList, ControlListhWnd, ahk_id %hGui%
   ;MsgBox % CList
   Loop, Parse, CList, `n
      DllCall("SetParent", "uint", A_LoopField, "uint", hContainer)
   }

GuiSize:

VScrollPixelsPerLine := A_GuiHeight / 100
Return



Esc::ExitApp

ConWinProc(hwnd, uMsg, wParam, lParam) {
   global ConWinProcOld, GuiWinProcOld, GuiWinProc
   ;Critical
   OldFormat := A_FormatInteger
   SetFormat, Integer, Hex
   MsgLst := WM_COMMAND := 0x111
   MsgLst .= "," . WM_SYSCOMMAND := 0x112
   uMsg += 0
   SetFormat, Integer, %OldFormat%
   if uMsg in %MsgLst%
      {   
      ReturnVal := DllCall("CallWindowProcA", UInt, GuiWinProcOld, UInt, A_EventInfo, UInt, uMsg, UInt, wParam, UInt, lParam)
      return ReturnVal
      }
   return DllCall("CallWindowProcA", UInt, ConWinProcOld, UInt, hwnd, UInt, uMsg, UInt, wParam, UInt, lParam)
   }

Go:
MsgBox
Return

GuiWindowProc(hwnd, uMsg, wParam, lParam) {
   ;Critical
   OldFormat := A_FormatInteger
   SetFormat, Integer, Hex
   global GuiWinProcOld, GuiWinProc, VScrollPixelsPerLine, Container, hContainer
   MsgLst := WM_VSCROLL := 0x115
   uMsg += 0
   SetFormat, Integer, %OldFormat%
   if uMsg in %MsgLst%
      {   
      global hGui      ;Only handle messages for the window we want to scroll
      if (hwnd != hGui)
         return DllCall("CallWindowProcA", UInt, GuiWinProcOld, UInt, hwnd, UInt, uMsg, UInt, wParam, UInt, lParam)

      wParamWordLow := Mod(wParam, 0x10000)
      wParamWordHigh := (wParam - wParamWordLow) / 0x10000

      if (wParamWordLow = 5 or wParamWordLow = 8)      ;SB_THUMBTRACK or SB_ENDSCROLL
         return DllCall("CallWindowProcA", UInt, GuiWinProcOld, UInt, hwnd, UInt, uMsg, UInt, wParam, UInt, lParam)

      QueryScrollBar(hwnd, nMin, nMax, nPage, nPos, nTrackPos)

      if (wParamWordLow = 7)            ;SB_BOTTOM
         a:= "" ; MsgBox, SB_BOTTOM
      else if (wParamWordLow = 6)            ;SB_TOP
         a:= "" ; MsgBox, SB_TOP
      else if (wParamWordLow = 1) {            ;SB_LINEDOWN
         SetScrollBar(hwnd, nMin, nMax, nPage, NewPos := nPos+1)
         GuiControl,1:Move, Container, % "y" . -NewPos * VScrollPixelsPerLine
         }else if (wParamWordLow = 0) {            ;SB_LINEUP
         SetScrollBar(hwnd, nMin, nMax, nPage, NewPos := nPos-1)
         GuiControl,1:Move, Container, % "y" . -NewPos * VScrollPixelsPerLine
            }else if (wParamWordLow = 3) {            ;SB_PAGEDOWN
         SetScrollBar(hwnd, nMin, nMax, nPage, NewPos := nPos+nPage)
         GuiControl,1:Move, Container, % "y" . -NewPos * VScrollPixelsPerLine
      }else if (wParamWordLow = 2) {            ;SB_PAGEUP
         SetScrollBar(hwnd, nMin, nMax, nPage, NewPos := nPos-nPage)
         GuiControl,1:Move, Container, % "y" . -NewPos * VScrollPixelsPerLine
      }else if (wParamWordLow = 4) {            ;SB_THUMBPOSITION
         SetScrollBar(hwnd, nMin, nMax, nPage, NewPos := wParamWordHigh)
         GuiControl,1:Move, Container, % "y" . -NewPos * VScrollPixelsPerLine
         }
;      ToolTip wParamWordLow = %wParamWordLow%`nContainerY = %ContainerY%`nVScrollPixelsPerLine = %VScrollPixelsPerLine%`nhwnd = %hwnd%`nnMin = %nMin%`nnMax = %nMax%`nnPage = %nPage%`nnPos = %nPos%`nnTrackPos = %nTrackPos% ;`nMsgLst= |%MsgLst%|
      return DllCall("CallWindowProcA", UInt, GuiWinProcOld, UInt, hwnd, UInt, uMsg, UInt, wParam, UInt, lParam)
      }
; Otherwise (since above didn't return), pass all unhandled events to the original WindowProc.
;   SetFormat, Integer, %OldFormat%
   return DllCall("CallWindowProcA", UInt, GuiWinProcOld, UInt, hwnd, UInt, uMsg, UInt, wParam, UInt, lParam)
   }

QueryScrollBar(hwnd, ByRef nMin, ByRef nMax, ByRef nPage, ByRef nPos, ByRef nTrackPos)
{
   ;Win32 API:   BOOL GetScrollInfo( HWND hwnd, int fnBar, LPSCROLLINFO lpsi )

   global SCROLLBAR_INFO

   bSuccess := DllCall("GetScrollInfo", UInt, hwnd, Int, 1, UInt, &SCROLLBAR_INFO)   ;SB_VERT = 1
   if (!bSuccess)
      return false

   nMin := NumGet(&SCROLLBAR_INFO, 8)
   nMax := NumGet(&SCROLLBAR_INFO, 12)
   nPage := NumGet(&SCROLLBAR_INFO, 16)
   nPos := NumGet(&SCROLLBAR_INFO, 20)
   nTrackPos := NumGet(&SCROLLBAR_INFO, 24)

   return true
}
;---------------------------------------------------------------------------------------------------------------
SetScrollBar(hwnd, nMin, nMax, nPage, nPos)
{
   ;Win32 API:   int SetScrollInfo( HWND hwnd, int fnBar, LPCSCROLLINFO lpsi, BOOL fRedraw )

   global SCROLLBAR_INFO
   NumPut(nMin, &SCROLLBAR_INFO + 8)      ;Min
   NumPut(nMax, &SCROLLBAR_INFO + 12)      ;Max
   NumPut(nPage, &SCROLLBAR_INFO + 16)      ;Page
   NumPut(nPos, &SCROLLBAR_INFO + 20)      ;Pos
   iReturnPos := DllCall("SetScrollInfo", UInt, hwnd, Int, 1, UInt, &SCROLLBAR_INFO, Int, true)   ;SB_VERT = 1
   return (iReturnPos == nPos)
}
;---------------------------------------------------------------------------------------------------------------
GuiClose:
   ExitApp
return
;---------------------------------------------------------------------------------------------------------------

_________________
Image
ʞɔпɟ əɥʇ ʇɐɥʍ


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 11th, 2008, 3:50 am 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7501
Location: Australia
Here is my attempt (based on some C++ code I wrote long ago.)
Code:
#NoEnv

OnMessage(0x115, "OnScroll") ; WM_VSCROLL
OnMessage(0x114, "OnScroll") ; WM_HSCROLL

Gui, +Resize +0x300000 ; WS_VSCROLL | WS_HSCROLL

Loop 8
    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)
}

The main differences are:
  • OnMessage is used rather than subclassing the window.
  • SB_THUMBTRACK is handled instead of SB_THUMBPOSITION, so the controls scroll in real-time (before you release the button.)
  • Resizing is handled better.
  • Tabbing works, though it doesn't scroll automatically (so the control tabbed to may not be visible.)
  • ScrollWindow() is used to move all of the controls.

Bug: The horizontal scroll bar isn't accounted for until the next resize after it is shown. (This is usually only noticeable when restoring the window after maximizing.)

Updated to support mouse wheel.

Updated to support ScrollMomentum. (2008/12/09)


Last edited by Lexikos on December 9th, 2008, 11:51 am, edited 2 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 11th, 2008, 3:58 am 
Offline

Joined: June 26th, 2006, 6:14 pm
Posts: 1379
Location: USA
Well now, That is just freaking awesome!!!!!

Thanks for sharing.

_________________
Image
ʞɔпɟ əɥʇ ʇɐɥʍ


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 20th, 2008, 2:20 am 
Offline

Joined: September 27th, 2007, 7:32 am
Posts: 25
Location: http://lifehacker.com
This really is incredible, thanks a lot. It's perfect for a script I'm putting together right now. One question, though: Is it possible to get scrolling to work with the mouse scroll wheel? Or even from the keyboard with the up/down arrows?


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 20th, 2008, 2:35 am 
Offline
User avatar

Joined: August 30th, 2005, 8:43 pm
Posts: 8666
Location: Salem, MA
Adam, Is your code based on lexiKos' or ahklerner's code?

_________________
Image
(Common Answers) - New Tutorials Forum - Humongous FAQ


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 20th, 2008, 2:37 am 
Offline

Joined: September 27th, 2007, 7:32 am
Posts: 25
Location: http://lifehacker.com
Ah, sorry about that. It's based on lexiKos'.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 20th, 2008, 4:16 am 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7501
Location: Australia
I originally tried catching WM_MOUSEWHEEL, but apparently that is only sent to the focused control. I've updated the script to support the mouse wheel, via hotkeys.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 21st, 2008, 4:36 pm 
Offline

Joined: February 27th, 2006, 5:55 pm
Posts: 24
Location: Italy
lexiKos wrote:
Here is my attempt (based on some C++ code I wrote long ago.)

This is a very good job lexiKos, thank you!

And is it possible to retrieve the absolute coordinates of the displayed page, specially when I scroll down the wheel mouse ??? (i.e: if the page dimension exceed the screen widht?)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 22nd, 2008, 1:10 am 
Offline

Joined: September 27th, 2007, 7:32 am
Posts: 25
Location: http://lifehacker.com
That mouse scroll update worked like a charm, thanks a lot lexiKos!

I also included the up and down keys with the rest of the hotkeys to scroll the window using those (there's user input where that'll be a problem with my GUI window, so there's no concern for conflict). So now it just looks like this:

Code:
WheelUp::
WheelDown::
+WheelUp::
+WheelDown::
Up::
Down::
    ; 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


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 22nd, 2008, 1:22 am 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7501
Location: Australia
Wdb wrote:
And is it possible to retrieve the absolute coordinates of the displayed page, specially when I scroll down the wheel mouse ??? (i.e: if the page dimension exceed the screen widht?)
You could get the position of the scroll bar using GetScrollPos or similar. There is no "page" - ScrollWindow just offsets each control by the difference in scroll bar position (when it moves.)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 22nd, 2008, 8:38 am 
Offline

Joined: February 27th, 2006, 5:55 pm
Posts: 24
Location: Italy
lexiKos wrote:
Wdb wrote:
And is it possible to retrieve the absolute coordinates of the displayed page, specially when I scroll down the wheel mouse ??? (i.e: if the page dimension exceed the screen widht?)
You could get the position of the scroll bar using GetScrollPos or similar. There is no "page" - ScrollWindow just offsets each control by the difference in scroll bar position (when it moves.)


Ok, thank you.

Another question:
what happens if I de-comment your statements NumPut:
Code:
    ; Update vertical scroll bar.
;     NumPut(SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL, si, 4) ; fMask


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 22nd, 2008, 10:45 am 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7501
Location: Australia
That adds the SIF_DISABLENOSCROLL flag, which causes the scroll bar to be disabled rather than hidden when it is not needed.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 22nd, 2008, 3:20 pm 
Offline

Joined: October 27th, 2006, 10:12 am
Posts: 649
A zoomable GUI (=ZUI), proof of concept would be also interesting.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 19th, 2008, 11:30 am 
Offline

Joined: June 18th, 2008, 10:40 am
Posts: 3
Quote:
Tabbing works, though it doesn't scroll automatically (so the control tabbed to may not be visible.)


Is there anyway to make it so that you can use tab and it scrolls to where the cursor is?


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: December 2nd, 2008, 3:01 am 
Offline

Joined: May 25th, 2007, 6:13 pm
Posts: 373
Only saw this when SKAN pointed it out, but it looks great!

Ciao,
Dra'Gon

_________________
Image
For a good laugh {hopefully} >> megamatts.50megs.com

My WritersCafe profile>>
http://www.writerscafe.org/writers/BlueDragonFire/


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 46 posts ]  Go to page 1, 2, 3, 4  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: Alpha Bravo, Google [Bot], jrav, Stigg and 16 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group