whitewater wrote:querty12,
I tried changing TMCTRIGGER (-1,0,1,2,3,4,5) with no effect.
Alright, I'll see if I can determine the possible values for TMCTRIGGER. I won't actually know what the right values to use will be on account of me not actually having a Windows 10 tablet. I'm also sure I'm calling the right method in the vtable since it's next to GetMode. If anyone else has tried the script on a tablet, could they confirm if the start menu appears when switching modes for them? It'll help me determine whether I've made a mistake or there's something odd about the configuration the script is running on.
EDIT: I checked. The Settings application definitely sends 4 for the TMCTRIGGER, no matter if it's activating or deactivating tablet mode, and not doing any funny things with bitmasks as I initially thought. I also definitely have the right index for the ::SetMode function in the vtable. As it works fine for me on a stock Windows install and on my normal Windows install, I'm sure the problem is not in the script I've posted.
I can't get Ibid's code to work
Ah, thanks to lblb's latest post, I know why. Try this modified version which works here on AHK_L 64-bit Unicode:
Code: Select all
;TurtleOfDoom: http://www.autohotkey.com/board/topic/25932-trying-to-toggle-autohide-taskbar-with-keystroke-in-vista/?p=327990
ToggleAutoHideTaskBar()
ToggleAutoHideTaskBar()
{
VarSetCapacity( APPBARDATA, 48, 0 )
NumPut(48, APPBARDATA, 0, "UInt")
bits := DllCall("Shell32.dll\SHAppBarMessage"
,"UInt", 4
,"Ptr", &APPBARDATA )
NumPut( (bits ^ 0x1), APPBARDATA, 40, "UInt" )
DllCall("Shell32.dll\SHAppBarMessage"
,"UInt", ( ABM_SETSTATE := 0xA )
,"Ptr", &APPBARDATA )
}
lblb wrote:
Your code is great! I'll have to dig more into it, but thanks a lot for your work. I'll have to see if I can adapt it in some way to adjusting the scaling factor. I'm really just getting into COM and dllcalls, so there is much in your code that is mysterious to me and I am puzzled as to how you figured it out and found some of the values that were needed. Thanks again!
Thanks!
I think the DPI can be adjusted by calling SystemParametersInfo with SPI_SETLOGICALDPIOVERRIDE (but don't take my word on that - as a person using a 1366x768 12.5" TN screen, I take the MSDN page's description ["Do not use."] of SPI_SETLOGICALDPIOVERRIDE to heart), and then
restarting Explorer. Even if that does work, however, I think it only affects applications opened since the call to SPI.
I'm not good at reversing things at all, so I wouldn't treat this post as one containing the best practices.
First of all, I recommend reading
https://maul-esel.github.io/tutorials/C ... faces.html. It will explain what the vTable is and how a particular COM function is called from it. AHK was the first language I ever did anything with COM in and it's because of that page. The
DllCall page is also a must to read for knowing how to properly call C functions from AHK.
You'll need to configure downloading of program Symbols. These make all the difference between seeing "TabletModeController::SetMode" and "sub_401560" for the same function. Create an environment variable with a name of
_NT_SYMBOL_PATH and use
SRV*C:\Symbols*https://msdl.microsoft.com/download/symbols for the value.
I used
strings and grep (from my install of MSYS2, but maybe Ubuntu on Windows would work? Else, I guess using the findstr program that comes with Windows is really the best option, but I'm too used to running grep) to find "TabletMode" references in all the DLL files that were present in %SystemRoot%\system32. After seeing "TabletModeController" in the results, I knew what I was looking for. I found three DLLs of note containing references to that, but to cut a long story short, the actual function that changes the tablet mode state is in twinui.dll, so we'll work with that.
Use the disassembler named
IDA to open the DLL file. Wait for the debugging symbols to download and for the analysis to finish. I looked in the list of functions and filtered on TabletModeController. I found the SetMode function. You can get the disassembly program to show you the function's signature. This will tell you how the function needs to be called. I can't remember how I found the GUID, but it was referenced in either/both twinapi.dll/actxproxy.dll when I searched in those DLL files first. When it came to determining the values needed for the TABLETMODE and TMTRIGGER, I was lazy (it beats looking for actual invocations of ::SetMode) - after rooting around in the TabletModeController functions, it was apparent that it saves what was passed into SetMode into the Registry. Thanks to your post, lblb, and NirSoft's RegScanner, I found where those values were being stored.
I mocked up an AHK script using
ComObjCreate("{4fda780a-acd2-41f7-b4f2-ebe674c9bf2a}", "{00000000-0000-0000-C000-000000000046}") and the call failed because the COM object wasn't exported. I guessed that I needed to obtain an instance of the ImmersiveShell object first because of
this (while there are clues in the TabletModeController class that you need to do this, it's not something I would've known to do were it not for NickoTin's reversing of the Virtual Desktop API). So I tried again (you can see the ComObjCreate call followed by the ComObjQuery call in my script) and it succeeded. Most COM objects can be instantiated using an IID of "00000000-0000-0000-C000-000000000046" (IUnknown's Interface ID), since all COM objects derive from IUnknown and that's what I usually do. This wasn't working for TabletModeController, though, so I guessed the IID for that was the same as the CLSID because I couldn't find another GUID that was referencing TabletModeController.
As for the vtable, I guessed the position - you can usually find it in the same DLL as the implementation, but since TabletModeController is weird and goes through actxproxy.dll first, I couldn't find it. Since I knew how ::SetMode should be called and I had an instance of TabletModeController, I just ran the DllCall in a loop...