Wednesday, November 29, 2006

Hacking the Microsoft Natural Ergonomic Keyboard 4000, redux

Earlier I wrote about hacking IntelliType's commands.xml file to enable the use of the "Zoom slider" as a "Scroll slider". Having recently repaved my computer, I found myself installing the latest version of Microsoft IntelliType Pro (version 6.02, a.k.a. 6.02.303.0) and trying to apply the patch I posted earlier:


C:\Program Files\Microsoft IntelliType Pro>patch -p0 < command.patch
patching file `commands.xml'
Hunk #1 FAILED at 1606.
Hunk #2 FAILED at 1694.
Hunk #3 FAILED at 2122.
Hunk #4 FAILED at 2134.
Hunk #5 FAILED at 2152.
Hunk #6 FAILED at 2182.
patch unexpectedly ends in middle of line
Hunk #7 FAILED at 2224.
7 out of 7 hunks FAILED -- saving rejects to commands.xml.rej


B'oh! Err... I mean: D'oh! Ok, time for plan B: Zoom2Scroll.xsl


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output method="xml" encoding="UTF-8" indent="yes" />

<!-- Pass-through (identity transform) template -->
<xsl:template match="* | @* | node()">
<xsl:copy>
<xsl:apply-templates select="* | @* | node()" />
</xsl:copy>
</xsl:template>

<xsl:template match="C319">
<C319 Type="6" Activator="ScrollUp" />
</xsl:template>

<xsl:template match="C320">
<C320 Type="6" Activator="ScrollDown" />
</xsl:template>

</xsl:stylesheet>


There. A quick trip to the command-line with my trusty xsl.exe:


C:\Program Files\Microsoft IntelliType Pro>xsl commands.old Zoom2Scroll.xsl commands.xml

C:\Program Files\Microsoft IntelliType Pro>


...and killing the IType.exe process, then re-launching that EXE again... it works! In your face, Larry Wall!

Oh, right. This post wouldn't be complete without the source code to xsl.exe. It's a JScript.NET program:


import System.Xml;
import System.Xml.Schema;

var src : String = System.Environment.GetCommandLineArgs()[1];

var transformer : System.Xml.Xsl.XslTransform = new System.Xml.Xsl.XslTransform ( );
var stylesheet : String = System.Environment.GetCommandLineArgs()[2];
transformer.Load ( stylesheet );

transformer.Transform ( src, System.Environment.GetCommandLineArgs()[3], null );


...which you can compile as follows:


C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322>jsc /nologo xsl.jsn


Thanks go out to the folks at Cute Overload for providing me with a [semi-]random web page to test the [new] scrolling capabilities of my "slider" in Internet Explorer.

25 comments:

Anonymous said...

Thanks man, good work.

Sean Chambers said...

awesome! very useful. thanks !!

Jeff Handley said...

This is absolutely awesome, thanks!!

Anonymous said...

useful! thanks for the hack

Unknown said...

You don't have to make an XSLT processor in .NET, I think the better way is to use the online one - http://xslt.sitesfree.com . There is also something from W3C but it didn't work for me. And thank you! It works well!

Anonymous said...

Adds a much-needed function to an otherwise solid product, thanks for posting!

Unknown said...

Thanks for a great hack!

I can add that it works with the 6.01.250.0 version as well :)

And maybe it's worth mentioning that there needs to exist a file called commands.old, otherwise it will give you a "File not found" error

Unknown said...

Here's a powershell script version of the transform code. Run it from a powershell prompt. You might need to adjust your execution policy using set-executionpolicy before it will run. Run get-help set-executionpolicy if you need help.


#Transform-Xml.ps1 by Steve Hiner
param (
[string]$inputfile = $(Read-Host "What XML file should I transform?")
, [string]$stylesheet = $(Read-Host "What XSL file should I use for the transform?")
, [string]$outputfile = $(Read-Host "Where should I put the transformed XML file?")
)
[System.Xml.Xsl.XslTransform]$transformer = New-Object System.Xml.Xsl.XslTransform
$transformer.Load($stylesheet)
$transformer.Transform($inputfile, $outputfile, $Null)

Troy Stauffer said...

Awesome, exactly what I was looking for!

It should be noted that when compiling xsl.jsn using the .NET framework v2.0, I had to add "import System.Data.SqlXml;" for it to compile.

Anonymous said...

I have a problem that I can not solve.

I want to replace "Ctrl Enter" with "Enter" and "Enter" with "Ctrl Enter" in Windows Live Messenger.

Now I've added:
<C28 Type="5" KeySeq="b" />

under :
<Application UniqueName="StandardSupport">

just to see if I can replace "Enter" with "b", saved, killed iType and started again. And nothing. :(

Can anyone help me?

Olivier Dagenais said...

@waldemar:

Try upgrading your IntelliType software: my commands.xml file contains these sections that might work better:

<Application UniqueName="MSBLClass" AppName="Windows/MSN Messenger">

and

<Application UniqueName="IMWindowClass" AppName="Windows/MSN Messenger">

...but then again, I don't know that this mechanism would allow you to trap Ctrl Enter (or even simply Enter), so you may be better off asking Microsoft for that feature/option or switching to a different instant messaging client, such as Trillian or Pidgin.

Anonymous said...

Thanks for the info.

moswald said...

Great hack, thanks. Do you know of any way to disable the FLock key (so that it's always on?)

Olivier Dagenais said...

@mos:

Unfortunately, I don't know how to make that setting permanent, as I also occasionally hit and wonder why all of the F-keys suddenly don't work.

In my opinion, that "F Lock" should have been a slide switch accessible from underneath the keyboard, just like the XT <-> AT switch under old keyboards.

If you do find a solution (a quick web search indicates people are simply working around the problem by remapping the keys, similar to how I remapped the "zoom scroller"), please post it here!

moswald said...

Well, I've *almost* got it working. Here's the xsl I wrote:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<!-- Pass-through (identity transform) template -->
<xsl:template match="* | @* | node()">
<xsl:copy>
<xsl:apply-templates select="* | @* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="C302">
<C302 Type="5" KeySeq="F1" />
</xsl:template>
<xsl:template match="C203">
<C203 Type="5" KeySeq="F2" />
</xsl:template>
<xsl:template match="C204">
<C204 Type="5" KeySeq="F3" />
</xsl:template>
<xsl:template match="C307">
<C307 Type="5" KeySeq="F4" />
</xsl:template>
<xsl:template match="C308">
<C308 Type="5" KeySeq="F5" />
</xsl:template>
<xsl:template match="C309">
<C309 Type="5" KeySeq="F6" />
</xsl:template>
<xsl:template match="C900">
<C900 Type="5" KeySeq="F7" />
</xsl:template>
<xsl:template match="C901">
<C901 Type="5" KeySeq="F8" />
</xsl:template>
<xsl:template match="C902">
<C902 Type="5" KeySeq="F9" />
</xsl:template>
<xsl:template match="C401">
<C401 Type="5" KeySeq="F10" />
</xsl:template>
<xsl:template match="C311">
<C311 Type="5" KeySeq="F11" />
</xsl:template>
<xsl:template match="C310">
<C310 Type="5" KeySeq="F12" />
</xsl:template>
</xsl:stylesheet>

However, it doesn't work for F7, F8, or F9 (and only those three). Do you see anything wrong with what I did? (I hope the HTML encoding worked out, there.)

Olivier Dagenais said...

@mos:

I'm not sure XSL is the best way to go here, since if there are no instances of C900, C901 or C902 elements in the original XML, the template will not add them for you.

Take a look at the Reprogramming Intellitype Pro Method; the only spot they have <C900> and "F7" is in the section they added. You might be able to do so with XSL like the following (warning: untested!):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" encoding="UTF-8" indent="yes" />
    <!-- Pass-through (identity transform) template -->
    <xsl:template match="* | @* | node()">
        <xsl:copy>
            <xsl:apply-templates select="* | @* | node()" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Application[@UniqueName='StandardSupport']">
        <C302 Type="5" KeySeq="F1" />
        <C203 Type="5" KeySeq="F2" />
        <C204 Type="5" KeySeq="F3" />
        <C307 Type="5" KeySeq="F4" />
        <C308 Type="5" KeySeq="F5" />
        <C309 Type="5" KeySeq="F6" />
        <C900 Type="5" KeySeq="F7" />
        <C901 Type="5" KeySeq="F8" />
        <C902 Type="5" KeySeq="F9" />
        <C401 Type="5" KeySeq="F10" />
        <C311 Type="5" KeySeq="F11" />
        <C310 Type="5" KeySeq="F12" />
    </xsl:template>
</xsl:stylesheet>

...as always, make a backup of the file before starting!

moswald said...

Oh, of course. My "All" section didn't contain entries for C900-C902. Duh.

For whatever reason, I couldn't get the Reprogramming Intellitype Pro method to work for me, which is why I went with the xsl route. Any time the F Lock key was off, pressing a function key would pop up an error dialog.

Anyhow, just adding the lines to the All section worked just fine.

Loch Ness said...

KTHXBYE

Unknown said...

Still works like a charm with Vista, thx!

Anonymous said...

Thanks for the heads up, I even wrote up my own blog entry about this with some additions to your information. Thanks.

http://www.pchenry.com/Home/tabid/36/EntryID/77/Default.aspx

Unknown said...

is it possible to make the Zoom become the (Previous & Next) buttons for playing music. this keyboard doesn't have it but i love the board.

Anonymous said...

Btw, you CAN assign any command to that so called "unassignable" "My Favorites" button....

You need to add this:

to the section MY_FAVORITES_LEGEND_EVENT of "ITypeDevices.xml" file...so it becomes like this:


MY_FAVORITES_LEGEND_EVENT
IDS_KN_MY_FAVORITES_LEGEND
IDI_FAVORITES_SETTINGS
MY_FAVORITES_LEGEND_COMMAND





Then you can add 83 (which is the code to My Favorites key) to Event Mapping in your registry and make it work however you like :)

To find Event Mapping section in your registry simply Google it...and it's a good idea to make backup of the ITypeDevices.xml

Greetings from Istanbul Turkey

Anonymous said...

hmm...blog commenting deleted section name...

here is what you need to add to ITypeDevices.xml file "Capability Name='CanRemap'/" put this sentence in "<" and ">"

Spider said...

I have 2.3.188.0 of Microsoft Mouse and Keyboard Center


MY_FAVORITES_LEGEND_EVENT
IDS_KN_MY_FAVORITES_LEGEND
MY_FAVORITES_LEGEND_COMMAND



I want to be able to change it so I can assign it to anything. I also want to change the zoom button to anything. I am fine with editing files but i'm a little confused by your post. Would it be possible for you to copy paste the lines of code I have to change for both these buttons.

jane holly said...

This professional hacker is absolutely reliable and I strongly recommend him for any type of hack you require. I know this because I have hired him severally for various hacks and he has never disappointed me nor any of my friends who have hired him too, he can help you with any of the following hacks:

-Phone hacks (remotely)
-Credit repair
-Bitcoin recovery (any cryptocurrency)
-Make money from home (USA only)
-Social media hacks
-Website hacks
-Erase criminal records (USA & Canada only)
-Grade change
-funds recovery

Email: onlineghosthacker247@ gmail .com