Microsoft Surface Pro 3 pen barrel button customization

Post your working scripts, libraries and tools for AHK v1.1 and older
Randy31416
Posts: 58
Joined: 15 Jan 2014, 19:09

Microsoft Surface Pro 3 pen barrel button customization

12 May 2015, 08:20

Microsoft provides no way to customize the two barrel buttons on the Surface Pro 3 pen. Many users have been searching for a way, and the person behind http://radialmenu.weebly.com/ did find a way, but the customization is embedded opaquely within a larger project. I have been search to find a more direct mechanism, suitable for use in AutoHotkey scripts, and here is the result.

A bit of background first. The pen has two buttons on the barrel. If the upper button is pressed and the screen is tapped, AutoHotkey sees a right-mouse-button click, and no special code is required to isolate this. If neither button is pressed, AutoHotkey sees a left-mouse-button click, and again no special code is required. The problem is that if the bottom button is pressed and the screen is tapped, then AutoHotkey sees again a normal left-mouse-button click, identical to the case when the bottom button is not pressed. This script intends to isolate these three cases so that they may be easily customized.

The script is interested only in trappng taps of the pen on the screen. I do not use inking, and do not know how the script interacts with inking. I don't exploit hovering, and so have not really considered hovering. But the script does allow the state of the buttons to be detected when the screen is tapped with the pen.

The sample script below is illustrative. It isolates plain taps and taps with concurrent CTRL, ALT, and CTRL+ALT keyboard button presses. Only as many combinations as are useful need be supplied; additional combinations, using SHIFT and WIN and using the left and right variants of all of these, may be defined if useful. In my own work I fully populate the code with the eight combinations of CTRL, ALT, and SHIFT.

The code works by intercepting and analyzing WM_INPUT messages sent by the pen as it does its work. When the pen is tapped on the screen, a WM_INPUT message is sent, and this is seen by AutoHotkey before the subsequent LButton or RButton event. The WM_INPUT message provides information to isolate the state of the buttons. This state is copied into a global variable, and this global variable can be tested when the subsequent LButton or RButton event occurs. This script uses the HID funnctions at http://www.autohotkey.com/board/topic/3 ... functions/ and its hidfuncs.ahk must be included by a standard include mechanism (I put that file in the standard library folder and the script is written to fetch it from there). The HID testing functions at that thread are interesting to try and explore.

The code works on my Surface Pro 3, but has not been tested by others (yet). Likely there will be glitches. One anomaloy noted so far is that Windows may present the right-click-menu on some flavors of the upper-button-pressed events (those involving CTRL) in spite of the fact that AutoHotkey has trapped these events. But for me at least I finally can override the barrel buttons on the mouse.

Other users may have more devices. They may present WM_INPUT messages that I do not know about and that the code below may not simply ignore. On my system, the value for AnyFlag in the code below is always 67 for the surface pen and always zero for anything else, so I simply compare to zero to distinguish the two cases. I can find no documentation about this (binary) flag for values higher than 8 (IIRC). If additional devices are present on your system and things act strangely, consider investigating this flag.

Code: Select all

    #SingleInstance Force
    #UseHook
    SurfacePenBegin()
    Return


; trap pen taps with the top button pressed
  #If (SurfacePenState = "tap down with upper side button pressed (seen in AutoHotkey as RButton event)")
    ^!RButton::OutputDebug CTRL+ALT Top Side Button
    ^RButton::OutputDebug CTRL Top Side Button
    !RButton::OutputDebug ALT Top Side Button
    RButton::OutputDebug plain Top Side Button
  #If (SurfacePenState = "tap up with upper side button pressed (seen in AutoHotkey as RButton up event)")
    ^!RButton::OutputDebug CTRL+ALT Top Side Button Up
    ^RButton::OutputDebug CTRL Top Side Button Up
    !RButton::OutputDebug ALT Top Side Button Up
    RButton Up::OutputDebug plain Top Side Button Up
    #If

; trap pen taps with the bottom button pressed
  #If (SurfacePenState = "tap down with bottom side button pressed (seen in AutoHotkey as LButton event)")
    ^!LButton::OutputDebug CTRL+ALT Bottom Side Button
    ^LButton::OutputDebug CTRL Bottom Side Button
    !LButton::OutputDebug ALT Bottom Side Button
    LButton::OutputDebug plain Bottom Side Button
  #If (SurfacePenState = "tap up with bottom side button pressed (seen in AutoHotkey as LButton up event)")
    ^!LButton::OutputDebug CTRL+ALT Bottom Side Button Up
    ^LButton::OutputDebug CTRL Bottom Side Button Up
    !LButton::OutputDebug ALT Bottom Side Button Up
    LButton Up::OutputDebug plain Bottom Side Button Up
    #If

; trap pen taps with no buttons pressed
  #If (SurfacePenState = "tap down with no side button pressed (seen in AutoHotkey as LButton event)")
    ^!LButton::OutputDebug CTRL+ALT Neither Button
    ^LButton::OutputDebug CTRL Neither Button
    !LButton::OutputDebug ALT Neither Button
    LButton::OutputDebug plain Neither Button
  #If (SurfacePenState = "tap up with no side button pressed (seen in AutoHotkey as LButton up event)")
    ^!LButton::OutputDebug CTRL+ALT Neither Button Up
    ^LButton::OutputDebug CTRL Neither Button Up
    !LButton::OutputDebug ALT Neither Button Up
    LButton Up::OutputDebug plain Neither Button Up
    #If


; initialize to trap input messages
  SurfacePenBegin( )
  {
    Global SurfacePenState
    SurfacePenState := ""
    AHKHID_Register(1, 2, A_ScriptHwnd, RIDEV_INPUTSINK := 0x00000100)
    OnMessage(WM_INPUT := 0xFF, "SurfacePenEvent")
  }

; trap wm_input messages and analyze them
  SurfacePenEvent( wParam, lParam, msg, hwnd )
  {
    Global SurfacePenState
    Critical
    AnyType := AHKHID_GetInputInfo(lParam, II_DEVTYPE := 0)
    AnyFlag := AHKHID_GetInputInfo(lParam, II_MSE_FLAGS := (08 + A_PtrSize * 2) | 0x0100)
    AnyButt := AHKHID_GetInputInfo(lParam, II_MSE_BUTTONFLAGS := ((12 + A_PtrSize * 2) | 0x0100))
    AnyData := AHKHID_GetInputInfo(lParam, II_MSE_EXTRAINFO := 28 + A_PtrSize * 2)
    SurfacePenState := ""
    If (AnyType = 0 And AnyFlag <> 0 And AnyButt <> 0)
    {
      If (AnyButt = 1 And (AnyData & 3) = 2)
        SurfacePenState := "tap down with no side button pressed (seen in AutoHotkey as LButton event)"
      If (AnyButt = 2 And (AnyData & 3) = 2)
        SurfacePenState := "tap up with no side button pressed (seen in AutoHotkey as LButton up event)"
      If (AnyButt = 1 And (AnyData & 3) = 3)
        SurfacePenState := "tap down with bottom side button pressed (seen in AutoHotkey as LButton event)"
      If (AnyButt = 2 And (AnyData & 3) = 3)
        SurfacePenState := "tap up with bottom side button pressed (seen in AutoHotkey as LButton up event)"
      If (AnyButt = 4)
        SurfacePenState := "tap down with upper side button pressed (seen in AutoHotkey as RButton event)"
      If (AnyButt = 8)
        SurfacePenState := "tap up with upper side button pressed (seen in AutoHotkey as RButton up event)"
      OutputDebug, SurfacePenEvent [%SurfacePenState%]
    }
  }


#Include <hidfuncs>

A final remark. I use this code primarily to turn bottom-button-pressed pen taps (of all flavors of CTRL, ALT, and SHIFT) into equivalently-modified middle-button mouse clicks. That way, the pen with no buttons sends left mouse clicks, with the bottom button it sends middle mouse clicks, and with the top button it sens right mosue clicks. Lexicos and Nextron at http://ahkscript.org/boards/viewtopic.php?f=5&t=7462 helped me find a very succinct way to write this remapping and make it work. If you are overriding other hotkeys in your script with the hotkeys detected by the above script, you should read that other thread to see the discussion on SendLevel.

[edit] changed typo in a comment; added remark about AnyFlag
Last edited by Randy31416 on 15 May 2015, 06:57, edited 2 times in total.
lblb
Posts: 190
Joined: 30 Sep 2013, 11:31

Re: Microsoft Surface Pro 3 pen barrel button customization

12 May 2015, 19:39

Hi Randy31416,

Thanks for your work. This could become very popular as customizing the SP3's pen barrel is often requested.

I may be wrong but looking at the code you provided, it seems you only show how to trap the taps but you actually don't do anything (customize or remap) them. Maybe I'm wrong. Can you show an example where you also customize the the two buttons to something else?

Thanks in advance!
Randy31416
Posts: 58
Joined: 15 Jan 2014, 19:09

Re: Microsoft Surface Pro 3 pen barrel button customization

13 May 2015, 07:40

In the script, which is intended as an example, the taps are customized to do "OutputDebug" operations -- replace that with something else. However, in real life, I have this, which changes taps with the bottom button pressed into middle mouse button clicks. That way, no buttons equals left click, upper button equals right click, bottom button equals middle clidk for me, and the SendLevel and explicit listing of the key combinations ensures that subseuqent middle-button hotkeys in my script get executed (see the thread referenced in the original post).

Code: Select all

  #If SurfacePenState = "tap down with bottom side button pressed (seen in AutoHotkey as LButton event)")
    ^!+LButton::
    ^!LButton::
    ^+LButton::
    !+LButton::
    ^LButton::
    !LButton::
    +LButton::
    LButton::
      SendLevel, 5
      Click, Middle
      SendLevel, 0
      Return
    #If
lblb
Posts: 190
Joined: 30 Sep 2013, 11:31

Re: Microsoft Surface Pro 3 pen barrel button customization

15 May 2015, 01:42

Hi Randy31416,

Thanks for the quick reply. I'll test it out when I have my tablet around. Cheers!
genem

Re: Microsoft Surface Pro 3 pen barrel button customization

16 Oct 2015, 13:45

newbie here...
Is it possible to program the top button on a Surface pen to open Evernote, instead of Onenote?
mn_qwin

Re: Microsoft Surface Pro 3 pen barrel button customization

18 Mar 2016, 03:36

Can this script be used to reverse the actions between the top button and the side button?

i.e. right now, the side button erases for me, while the top button is right click. I'd like to make the top button erase, and the side button the right click, a simple reverse.

I tried to poke around with this script, but I didn't get any expected result, and rather just caused some weird pen hangups in my test program.
Randy31416
Posts: 58
Joined: 15 Jan 2014, 19:09

Re: Microsoft Surface Pro 3 pen barrel button customization

20 Mar 2016, 08:02

mn_qwin wrote:Can this script be used to reverse the actions between the top button and the side button?
I suspect not. The top button is actually translated by driver software into F20 and F21 for single and double clicks (see the second post above, with the link given by lblb), and so it is trivial to do whatever normal thing you want with that button (but probably not erase -- I've no idea how erase is processed). All the script here was trying to accomplish was to detect what side buttons are pressed when the pen is tapped against the screens, and it does this for me, but I am sure it is not a robust and generalizable solution. At the time I wrote this I could find no information at all on how to detect the button state, and put a lot of effort into finding out how, so I was sharing here mainly the solution to the detection problem.

Further, I've no idea what if anything Microsoft has done to the drivers for Windows 10 or for the Surface (and Pro) 4 and its pen (perhaps this still works there but I'm on Surface Pro 3 with Windows 8.1).

I'd sort of recommend that nothing too ambitious be based on this code. But it was worth sharing because of how difficult it was to find any detection mechanism.
tabletpro
Posts: 14
Joined: 07 Mar 2016, 17:40

Re: Microsoft Surface Pro 3 pen barrel button customization

25 Nov 2016, 01:11

is anyone doing any work on this anymore? I know its been a bit. I'm trying to get this to work on my sp4 pen and copied the bottom script into my ahk file. its spitting out an interesting variant of #^f20 with a barrel button hover click. Not sure why as i'm definitely a noob. I am thrilled to be this far, I've remapped the #^f20 output into a simple ^z. Its slow and a little inconsistent and i'm curious if you could help me decipher how to get a clean input from the pen barrel. just wanting to optimize the speed. as it is. so grateful! wanted to do this for the longest time!

okay, so here is what i'm getting out of key history when mapped to ^z
my script is

Code: Select all

 #If SurfacePenState = ;"tap down with bottom side button pressed (seen in AutoHotkey as LButton event)")
      SendLevel, 5
      Click, Middle
      SendLevel, 0
      Return
    #If
~#F20::^z

key history info

5B 15B d 2.20 LWin
83 06B h d 0.00 F20
5B 15B u 0.02 LWin
A2 01D i d 0.00 LControl
A2 01D i u 0.00 LControl
83 06B h u 0.00 F20
A2 01D i d 0.03 LControl
5A 02C i d 0.00 z
A2 01D i u 0.00 LControl
5A 02C i u 0.00 z

5B 15B d 2.69 LWin
83 06B d 0.02 F20
5B 15B u 0.00 LWin
83 06B u 0.00 F20
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Microsoft Surface Pro 3 pen barrel button customization

25 Nov 2016, 01:21

You as not using #if correctly, it seems like.
tabletpro
Posts: 14
Joined: 07 Mar 2016, 17:40

Re: Microsoft Surface Pro 3 pen barrel button customization

03 Dec 2016, 11:34

i'm confused, i'm a super noob. are you saying it is completely useless in this code or should be used differently? any way you could copy my code and re post it with the corrections?
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Microsoft Surface Pro 3 pen barrel button customization

03 Dec 2016, 11:50

You have not stated what you want to achive with the code above the remapping, I can't help you with that. See #if.
For the ~#F20::^z remapping, try, *F20 up::^z instead.

Good luck
tabletpro
Posts: 14
Joined: 07 Mar 2016, 17:40

Re: Microsoft Surface Pro 3 pen barrel button customization

03 Dec 2016, 17:18

oh I see,

I have only one goal and that is to remap the one surface pro 4 pen barrel button to a new action. I'll try the

Code: Select all

*F20 up::^z

I really appreciate that help!

basically I've just been copying code into my ahk file and seeing if anything works.
Nathan Kennedy
Posts: 3
Joined: 22 Dec 2016, 12:39

Re: Microsoft Surface Pro 3 pen barrel button customization

22 Dec 2016, 12:46

Did you ever figure this out? I have been looking EVERYWHERE for this. I want to be able to have my 3 buttons (#F18, #F19, #F20) do cut, paste and copy. And if i hold down the side button while the top button is pressed, I went them to do other commands. I'm using a Surface Book Pen, which i'm pretty sure is the same as the SP4 Pen.
McGrathfx
Posts: 1
Joined: 02 Feb 2017, 18:04

Re: Microsoft Surface Pro 3 pen barrel button customization

02 Feb 2017, 18:31

Anyone successful at remapping the Surface Pro 3 pen barrel buttons to something like CTRL? I remapped the purple eraser button to CTRL + Z for "undo" but have not had much luck with the bottom barrel button. Any help would be greatly appreciated. :)
Amitloaf

Re: Microsoft Surface Pro 3 pen barrel button customization

28 Jun 2017, 02:09

How come one of the barrel buttons is mapped to LButton and also clicking without buttons is mapped to LButton. How can you tell?
smudg3r
Posts: 1
Joined: 05 Jul 2017, 04:54

Re: Microsoft Surface Pro 3 pen barrel button customization

05 Jul 2017, 05:07

Am a relative newbie to win 10 / tablet / "smart" pens (but know windows etc) - this is the closest forum I've found to what I'm looking to achieve, so apologies if I've missed something basic or am in the wrong place.

What I'm looking to do is control a Powerpoint presentation using just the upper / lower buttons on the pen:
-top button=back/left arrow
-bottom button=forward/right arrow
Importantly: I want to use this to present to people sat in front of my tablet - I would be close & be able to see the screen, but not able to tap the screen with the pen. Is this possible? Are the buttons on the pen simply modifiers equivalent to an ALT or CTRL key that requires the click of the tip on the screen to do anything? Or are they buttons in their own right? (hopefully the latter)

What I have:
Windows 10 tablet
two button pen

Background:
I give a lot of presentations to small groups of people, often the A/V kit in meetings rooms is broken / missing cables / no wifi / meeting rooms get double booked, so often we end up sat in a coffee shop without power sockets etc! I travel a lot, so don't want to carry additional kit around with me.

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: JoeWinograd and 76 guests