Tablet Mode toggle for Windows 10

Post your working scripts, libraries and tools for AHK v1.1 and older
whitewater
Posts: 17
Joined: 13 Mar 2016, 16:19

Re: Tablet Mode toggle for Windows 10

11 Apr 2016, 02:28

querty12,
I tried changing TMCTRIGGER (-1,0,1,2,3,4,5) with no effect. I can't get Ibid's code to work, but I really don't understand what the DLLCALL is doing. Best I have come up with is the following, which calls up the taskbar menu.

Code: Select all

run control.exe /name Microsoft.Taskbar
sleep, 500
send u  ;A&utohide the Taskbar
ControlClick, OK, A
lblb
Posts: 190
Joined: 30 Sep 2013, 11:31

Re: Tablet Mode toggle for Windows 10

11 Apr 2016, 11:14

@qwerty12:

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!

@whitewater:

For the taskbar autohide toggle: What does not work about the code I posted? It works for me on everything from Windows Vista to Windows 10. Have you tried running the script with AHK 32 bit ANSI (which is what I use)?
whitewater
Posts: 17
Joined: 13 Mar 2016, 16:19

Re: Tablet Mode toggle for Windows 10

11 Apr 2016, 13:30

Ibib,
I followed your link (turtleofdoom) and tried several of the scripts there. They all worked except the turtle of doom. I am new to AHK, and must be missing something. I haven't seen the ToggleAutoHideTaskBar() statement before. Do I need to set the parameter to a value? Thanks for your help.
lblb
Posts: 190
Joined: 30 Sep 2013, 11:31

Re: Tablet Mode toggle for Windows 10

11 Apr 2016, 13:36

No need to change the code. You should be able to just copy the whole code that I put in my post (https://autohotkey.com/boards/viewtopic ... 437#p79437), paste it in a ahk file, then double-click that file to toggle taskbar autohide.
Does that work?
qwerty12
Posts: 468
Joined: 04 Mar 2016, 04:33
Contact:

Re: Tablet Mode toggle for Windows 10

11 Apr 2016, 14:11

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...
whitewater
Posts: 17
Joined: 13 Mar 2016, 16:19

Re: Tablet Mode toggle for Windows 10

11 Apr 2016, 17:21

@Querty12,
First, the new toggle hide/Unhide works as you wrote it on my Surface Pro 3, thanks.
Next I do not have a Send {Lwin} command in the toggle Tablet/Desktop script.
The behavior is as follows:
If one or more windows are visible and Start Menu is off, toggle just changes the Tablet/Desktop mode (in Tablet mode, one of the programs is full screen)
If Start Menu is on in Desktop Mode, then toggle to tablet goes to Start Menu and returning to desktop leaves start menu on.
If no programs are visible (they can be open, but minimized) then the toggle goes from Start Menu to Start Menu.
This seems logical and consistent. This could be changed if I knew if the Start Menu was active or not. Any way to get the start menu status?
Thanks again and I will go read the DLL docs you referenced
qwerty12
Posts: 468
Joined: 04 Mar 2016, 04:33
Contact:

Re: Tablet Mode toggle for Windows 10

11 Apr 2016, 19:58

Ah, thanks for laying out the scenario for me, whitewater. If I open the Start Menu before changing modes, I also get the Start Menu displaying when changing modes, and if I focus the start menu on the stock 10 install, then when exiting I also see the start menu.

For detection, you can try this. I can't say whether it will return the right result in every situation, but I think it should be alright:

Code: Select all

; http://stackoverflow.com/a/22105803

AppVisibility_IsLauncherVisible()
{
	; probably not-as-reliable alternative: return (!!WinActive("Cortana ahk_class Windows.UI.Core.CoreWindow") || !!WinActive("Start ahk_class Windows.UI.Core.CoreWindow"))
	AppVisibility := ComObjCreate("{7E5FE3D9-985F-4908-91F9-EE19F9FD1514}", "{2246EA2D-CAEA-4444-A3C4-6DE827E44313}")
	DllCall(NumGet(NumGet(AppVisibility+0),4*A_PtrSize), "Ptr", AppVisibility, "Int*", isVisible)
	ObjRelease(AppVisibility)
	return isVisible
}

if (AppVisibility_IsLauncherVisible())
	MsgBox Start menu visible
else
	MsgBox Start menu not visible
Depending on what you want to do, you may need to store the result of AppVisibility_IsLauncherVisible() before switching modes etc.
lblb
Posts: 190
Joined: 30 Sep 2013, 11:31

Re: Tablet Mode toggle for Windows 10

14 Apr 2016, 00:55

qwerty12 wrote: I think the DPI can be adjusted by ....
Wow, thanks a lot for all that information qwert12. This is really great and is really going to help me learn about this kind of stuff. Your help and detailed explanations are much appreciated. Now let's study this!
whitewater
Posts: 17
Joined: 13 Mar 2016, 16:19

Re: Tablet Mode toggle for Windows 10

14 Apr 2016, 13:33

querty,
The detection works fine IF I add another
AppVisibility_IsLauncherVisible()

Statement before the code you published. I noticed the same pattern on your Toggle code.
Again, being new to AHK, could you explain the need for 2 function statements.
Thanks again for your info and code!
qwerty12
Posts: 468
Joined: 04 Mar 2016, 04:33
Contact:

Re: Tablet Mode toggle for Windows 10

14 Apr 2016, 14:02

lblb wrote: Wow, thanks a lot for all that information qwert12. This is really great and is really going to help me learn about this kind of stuff. Your help and detailed explanations are much appreciated. Now let's study this!
You're very welcome, lblb. Good luck!
whitewater wrote:querty,
The detection works fine IF I add another
AppVisibility_IsLauncherVisible()

Statement before the code you published. I noticed the same pattern on your Toggle code.
Again, being new to AHK, could you explain the need for 2 function statements.
Thanks again for your info and code!
To use the AppVisibility_IsLauncherVisible() code as an example, the

Code: Select all

AppVisibility_IsLauncherVisible()
{
section defines the AppVisibility_IsLauncherVisible() function - i.e. what it will do when the function is called - which in that example is done by just calling AppVisibility_IsLauncherVisible() - which tells AHK to actually run what's inside those curly brackets. I guess you added a AppVisibility_IsLauncherVisible() to actually have that happen. Saying that, I did already include a call to that function in that script - if you click the Download button, rename the downloaded file's extension from txt to ahk and run it, you should get a message saying the Start Menu's status...
whitewater
Posts: 17
Joined: 13 Mar 2016, 16:19

Re: Tablet Mode toggle for Windows 10

14 Apr 2016, 16:36

Querty,
Your code works fine until I assign the code to a function key, then it only works if I add the initial function call (commented out below)

Code: Select all

#SingleInstance force
F5:: ;test
;AppVisibility_IsLauncherVisible()  ; Need only when assigned to a Function Key
AppVisibility_IsLauncherVisible()
{
	
	AppVisibility := ComObjCreate("{7E5FE3D9-985F-4908-91F9-EE19F9FD1514}", "{2246EA2D-CAEA-4444-A3C4-6DE827E44313}")
	DllCall(NumGet(NumGet(AppVisibility+0),4*A_PtrSize), "Ptr", AppVisibility, "Int*", isVisible)
	ObjRelease(AppVisibility)
	return isVisible
}

if (AppVisibility_IsLauncherVisible())
	MsgBox Start menu visible
else
	MsgBox Start menu not visiible
return
Not sure why, maybe the function code is not run for some reason
whitewater
Posts: 17
Joined: 13 Mar 2016, 16:19

Re: Tablet Mode toggle for Windows 10

14 Apr 2016, 16:49

Querty12,
I deleted the ObjRelease statement, and the code worked with one function call
I moved ObjRelease after the if statement, and it works. Will it release the object and memory?
AlexB

Re: Tablet Mode toggle for Windows 10

30 Mar 2017, 08:21

Hi everybody!
First, thanks for all the scripts and advises I found here :)

I'm using the TabletModeController_SetMode script previously explained to toggle the tablet/desktop mode of my application (made to be launched from Windows 10 only).

My application is coded in C++, and calls the AHK dll, calling itself the AHK script.
The only thing I want is to turn from desktop to tablet mode at the app launch (if not already in tablet mode), and go back to the original mode when application is closed.

So, one of the first thing I do in my application is to get the current mode and turn to tablet mode if necessary.
It works almost perfectly, exept for one case :
When I am in desktop mode, on the desktop (all launched applications are reduced), if I launch my app from a desktop shortcut, the application window appears, and just some milliseconds after, it's hidden and I am on the "windows 10" start menu.

Does someone have a solution for me? :cry:
Thanks!
Alex.
AlexisB

Re: Tablet Mode toggle for Windows 10

30 Mar 2017, 08:24

Hi everybody!
First, thanks for all the scripts and advises I found here :)

I'm using the TabletModeController_SetMode script previously explained to toggle the tablet/desktop mode of my application (made to be launched from Windows 10 only).

My application is coded in C++, and calls the AHK dll, calling itself the AHK script.
The only thing I want is to turn from desktop to tablet mode at the app launch (if not already in tablet mode), and go back to the original mode when application is closed.

So, one of the first thing I do in my application is to get the current mode and turn to tablet mode if necessary.
It works almost perfectly, exept for one case :
When I am in desktop mode, on the desktop (all launched applications are reduced), if I launch my app from a desktop shortcut, the application window appears, and just some milliseconds after, it's hidden and I am on the "windows 10" start menu.

Does someone have a solution for me? :cry:
Thanks!
Alex.

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 227 guests