Need help with registering app bar (DllCall)

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
diaewad
Posts: 101
Joined: 17 Feb 2015, 10:55

Need help with registering app bar (DllCall)

24 Mar 2017, 09:35

I'm trying to use Skan's AppBar code located here: https://autohotkey.com/board/topic/2063 ... /?p=135958
But it won't register as an AppBar. I won't lie... his whole APPBARDATA stuff is insanely confusing to me. I don't understand what is going on with the VarSetCapacity and NumPut, but as far as I can tell it's some form of an object used for the DLL call; however, no matter what I change, it still won't register the area needed for the taskbar, meaning all windows maximize behind the bar, instead of to the bottom of the bar.

I'm using Windows 10 and have spent 2 days trying to figure this out. Could someone please tell me how to get the registration to work?
qwerty12
Posts: 468
Joined: 04 Mar 2016, 04:33
Contact:

Re: Need help with registering app bar (DllCall)

24 Mar 2017, 13:55

When the script's that old and says that it's been tested on XP SP2 and there's nary a mention of A_PtrSize in the script, it's a good indicator that the script will only work with AutoHotkeyU32.exe, a.k.a. the 32-bit Unicode build of AutoHotkey (and if the situation is really dire, then shudders AutoHotkeyA32.exe). I just tried it with the 32-bit AutoHotkey on Windows 10 and the script works as expected - a bar gets placed on the top of my screen and my work area is reduced.
diaewad
Posts: 101
Joined: 17 Feb 2015, 10:55

Re: Need help with registering app bar (DllCall)

24 Mar 2017, 14:00

I see. Hmmm... I was pretty sure it had to do with its age. When I was researching everything, it seemed as though it actually missed a couple of things, but you say it works with AHK32, so I may just use that. You wouldn't know how to update it would you? Or, better yet... would you be willing to update it?
qwerty12
Posts: 468
Joined: 04 Mar 2016, 04:33
Contact:

Re: Need help with registering app bar (DllCall)

24 Mar 2017, 14:33

diaewad wrote:Or, better yet... would you be willing to update it?
If I've not made any mistakes, this should work:

Code: Select all

; Quick Launcher Appbar                                           :: By Skan - 28/Aug/2007

SetBatchLines -1
CoordMode, Mouse  , Screen
CoordMode, Tooltip, Screen
Menu, Tray, NoStandard
Menu, Tray, Add, AppBar Hide/Show, ToggleGUI
Menu, Tray, Add
Menu, Tray, Standard
Menu, Tray, Default, AppBar Hide/Show
Menu, Tray, Click, 1
Menu, Tray, Tip, Quick Launcher

Menu, RClick, Add, &Properties, ShowProperties
QLF := A_AppData . "\Microsoft\Internet Explorer\Quick Launch"
Sz := 32 , Sp := 9 ; Icon Size and Spacing
Gui, Margin, 2,2
Gui -Caption +ToolWindow +AlwaysOnTop +Border +LastFound +hwndhAB

Loop %QLF%\*.lnk {
 LINK := A_LoopFileLongPath 
 SplitPath, LINK,,,, FN 
 FileGetShortcut, %LINK%, Tar, Dir, Args, Desc, Ico, IcoN, Run 
 Target := ( Ico!="" ) ? ICO : TAR
 SplitPath, Target,,, Ext
 If Ext not in DLL,EXE,ICO,ICL
    {
      ; http://www.autohotkey.com/forum/viewtopic.php?p=57646#57646
      RegRead, From   , HKEY_CLASSES_ROOT, .%Ext%              ; Thanks KIU
      RegRead, default, HKEY_CLASSES_ROOT, %From%\DefaultIcon  ; 
      StringSplit, IC, default, `,
      IcoN := Ic2, Target := Ic1
    }
 Gui, Add, Picture, X+%Sp% y2 w%Sz% h%Sz% Icon%IcoN% vI%A_Index% gRun, % Target
 AppData .= FN "|" LINK "`n"
}

Gui, Show, x0 y0 w%A_ScreenWidth%
WinGetPos, GX,GY,GW,GH, ahk_id %hAB%

ABM := DllCall( "RegisterWindowMessage", Str,"AppBarMsg", "UInt" )
OnMessage( ABM, "ABM_Callback" )
OnMessage( (WM_MOUSEMOVE := 0x200) , "CheckMousePos" )

; APPBARDATA : http://msdn2.microsoft.com/en-us/library/ms538008.aspx
VarSetCapacity( APPBARDATA , (cbAPPBARDATA := A_PtrSize == 8 ? 48 : 36), 0 )
Off :=  NumPut(  cbAPPBARDATA, APPBARDATA, "Ptr" )
Off :=  NumPut( hAB, Off+0, "Ptr" )
Off :=  NumPut( ABM, Off+0, "UInt" )
Off :=  NumPut(   1, Off+0, "UInt" ) 
Off :=  NumPut(  GX, Off+0, "Int" ) 
Off :=  NumPut(  GY, Off+0, "Int" ) 
Off :=  NumPut(  GW, Off+0, "Int" ) 
Off :=  NumPut(  GH, Off+0, "Int" )
;MsgBox % Off - &APPBARDATA
Off :=  NumPut(   1, Off+0, "Ptr" )
GoSub, RegisterAppBar

OnExit, QuitScript
Return

ToggleGUI:
 If DllCall("IsWindowVisible", Ptr,hAB) {
    Gui, Hide
    GoSub, RemoveAppBar
 } Else {
    Gui, Show, NoActivate
    GoSub, RegisterAppBar
 }
Return

RegisterAppBar:
  DllCall("Shell32.dll\SHAppBarMessage", UInt,(ABM_NEW:=0x0)     , Ptr,&APPBARDATA )
  DllCall("Shell32.dll\SHAppBarMessage", UInt,(ABM_QUERYPOS:=0x2), Ptr,&APPBARDATA )
  DllCall("Shell32.dll\SHAppBarMessage", UInt,(ABM_SETPOS:=0x3)  , Ptr,&APPBARDATA )
Return

RemoveAppBar:
  DllCall("Shell32.dll\SHAppBarMessage", UInt,(ABM_REMOVE := 0x1), Ptr,&APPBARDATA )
Return

Run:
  Index := SubStr(A_GuiControl,2,3)
  RowData := AGetF( AppData, Index, "`n" ) , LinkFile := AGetF( RowData, 2 )
  Run, %LinkFile%
Return

GuiContextMenu:
  Index := SubStr(A_GuiControl,2,3) 
  ToolTip
  Menu, RClick, Show
Return

ShowProperties:
  RowData  := AGetF( AppData, Index, "`n" )
  LinkFile := AGetF( RowData, 2 )
  Run, Properties %LinkFile%
Return

CheckMousePos()  { ; Triggered with WM_MOUSEMOVE
Global Mouse
If ( !Mouse ) {
                Mouse := True
                SetTimer, ShowToolTip, 400
                SetTimer, ToolTipOff , 400
}             }

ShowToolTip:
   MouseGetPos,,,,ClassNN,1
   ControlGetPos, X, Y, W, H, %ClassNN%, ahk_id %hAB%
   Index := SubStr(ClassNN,7,3) , RowData := AGetF( AppData, Index, "`n" ) 
   FileGetShortcut, % AGetF( RowData, 2 ),,,, Desc
   Tooltip % AGetF( RowData, 1 ) . ((Desc!="") ? "`n" Desc : "" ), % X, % H+Y+3
Return

ToolTipOff:
   MouseGetPos,,, hWnd,Ctrl,3
   If ( hWnd != hAB ) {
      Tooltip
      Mouse := False
      SetTimer, ToolTipOff , OFF
      SetTimer, ShowToolTip, OFF
} Return

AGetF(Str="",Fld=1, D="" )  {  ;                                           ArrayGetField() 
  Loop,Parse,Str, % ( D="" ? "|" : D ) 
    IfEqual,A_Index,%Fld%, Return,A_LoopField 
                            } 

ABM_Callback( wParam, LParam, Msg, HWnd ) {
; Not much messages received. When Taskbar settings are
; changed the wParam becomes 1, else it is always 2
}

QuitScript:
  GoSub, RemoveAppbar
  ExitApp
Return
diaewad
Posts: 101
Joined: 17 Feb 2015, 10:55

Re: Need help with registering app bar (DllCall)

24 Mar 2017, 14:38

That did it! That's awesome, man. God, I wish I knew what that meant. That's like the last thing I need to learn to feel like I've finally mastered AHK. If you know of any tutorials that would explain that section of code, that would be kick ass. At any rate, thank you very much!!
qwerty12
Posts: 468
Joined: 04 Mar 2016, 04:33
Contact:

Re: Need help with registering app bar (DllCall)

24 Mar 2017, 15:02

diaewad wrote:If you know of any tutorials that would explain that section of code, that would be kick ass. At any rate, thank you very much!!
No tutorials come to mind, sorry. I got my start with working in that stuff from this which covers some related concepts, but, yeah... https://maul-esel.github.io/ahkbook/en/Structures.html seems like a good read.

If the Structures page isn't enough, I can try explaining the changes I made and why if you really want but I'd honestly rather not because:
  • I'm really bad at doing so, generally :(
  • My basic understanding of structures and arrays and how they are laid out in memory comes from AutoHotkey - as such, because of lack of specialised knowledge, I'm likely to give you a flawed explanation
diaewad
Posts: 101
Joined: 17 Feb 2015, 10:55

Re: Need help with registering app bar (DllCall)

24 Mar 2017, 15:06

That all looks like really good reading! Thank you! I'm sure it will help a lot, and trust me, you telling me via AHK instead of C/C++ is probably more beneficial for me, personally, but I think (see: hope) that these will be enough. :D
qwerty12
Posts: 468
Joined: 04 Mar 2016, 04:33
Contact:

Re: Need help with registering app bar (DllCall)

24 Mar 2017, 16:15

diaewad wrote:I'm sure it will help a lot, and trust me, you telling me via AHK instead of C/C++ is probably more beneficial for me
OK, fine, but I'm not holding myself responsible if all this has just served to make you more confused afterwards than you were when starting. :p

One instance of an APPBARDATA structure occupies 36 (sizeof(uint32_t) + sizeof(void*) + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(RECT) [sizeof(long) * 4] + sizeof(void*) - look at the MSDN page for APPBARDATA) bytes in memory under a 32-bit process and 48 bytes (the same, but with an extra four bytes after the first sizeof) under a 64-bit one. The structure size is simply the cumulative size of the structure's members(I know, I know, I'm not telling the whole truth here - I'll get to it). The disparity in size comes down to two things:
  • A pointer's size is 8 bytes for 64-bit vs. 4 bytes for 32-bit. The size of an int etc. remains the same, however.
  • As part of some compiler optimisation I don't understand, the compiler may choose to pad out the structure so that some members begin on an offset that is aligned to a multiple of the pointer size - this is why it's 48 bytes under 64-bit rather than 44 (36 + the extra eight bytes taken by the two pointer members together) because there's an extra 4 bytes added by the compiler after the cbSize member so that hWnd starts at offset 8
VarSetCapacity( APPBARDATA , (cbAPPBARDATA := A_PtrSize == 8 ? 48 : 36), 0 ) creates the space for this structure in the AHK code. I guess that's roughly equivalent to APPBARDATA something = { 0 }; in C (though I would guess AutoHotkey doesn't allocate the memory on the stack, so roughly is a bit of an understatement but w/e). cbAPPBARDATA is just me saving the size to avoid repeating myself - the struct requires us to put the size of it as the first member, and we do so with NumPut( cbAPPBARDATA, APPBARDATA, "Ptr" ), which writes the size right into the beginning of the structure, where the cbSize member lives. That's roughly equivalent to something.cbSize = cbAPPBARDATA; //of course, you'd probably use sizeof(something)... (for the sake of simplicity, I'll pretend the memory for the struct in AHK is on the stack and we're not dealing with a pointer that needs to be dereferenced). And it goes on.
One thing to look out for in this case is that a RECT struct is part of the APPBARDATA struct. It's not a pointer to one elsewhere - no, we have a RECT struct in our main struct. In C, you would do something.rc.left = ... (typically you would use a WinAPI function to fill the RECT in from elsewhere, I guess, but just play along with me), which visually enforces the separation of the two, but in memory there's no separation and the struct is merged with the main one, so you actually have something like this:

Code: Select all

typedef struct {
  DWORD  cbSize;
  HWND   hWnd;
  UINT   uCallbackMessage;
  UINT   uEdge;
  LONG left; // beginning of RECT struct
  LONG top;
  LONG right;
  LONG bottom; // end of RECT struct
  LPARAM lParam;
} APPBARDATA
SKAN is using a feature of NumPut where it returns the address of the address it's been given to write to plus the size of whatever it's written. Thankfully, the only time I have to watch out for padding here is with the first member, which is why I use "Ptr" instead of "UInt" (UInt being the proper type for a DWORD) - NumPut will return &APPBARDATA + A_PtrSize, taking care of getting the right offset for the hWnd member. Thankfully, the rest of the members don't need special consideration and we can just use their actual types as per the DllCall page (read it for a mapping of C types to AHK DllCall types). NumPut will return the next member's offset relative to the address of the APPBARDATA struct instance in memory.

The call to SHAppBarMessage was failing with the original script because the 64-bit shell32.dll would've looked at the first member of the struct, saw that the size didn't match what it was expecting and bailed out. If the size check wasn't there, it still wouldn't have worked anyway because of the increased size of the hWnd member and the padding after cbSize, which shifts down the rest of the members' offsets, meaning shell32.dll would've been looking in the wrong places.
diaewad
Posts: 101
Joined: 17 Feb 2015, 10:55

Re: Need help with registering app bar (DllCall)

27 Mar 2017, 12:25

That was insanely informative! Now I feel like I need to go through all the Windows Api docs to try and make some weird shit, to see if I can figure this all out. Thank you so much for going through the trouble of typing that all out! You're really cool.
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: Need help with registering app bar (DllCall)

27 Mar 2017, 20:01

Anyone know if the AutoHide setting has the be handled manually or something? I found that Majkinetor wrapped this in the forms framework but that the woman Dow was shown manually still, even though the autohide feature was set.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: No registered users and 244 guests