5

There is a utility on Windows 7 that allows you to do touch calibration, if you have a supported touch screen.

The executable is tabcal.exe and it's located in:

C:\Windows\System32

I'm look for a way to shell this exe myself from my kiosk application to:

  1. Reset calibration data
  2. Execute calibration mode screen

The exe supports some switches but they aren't documented. Once switch I found was this:

tabcal lincal novalidate XGridPts={coords} YGridPts={coords}

I'd like to know if anyone can help me find the command switches to reset calibration data, which would work the same as going to the Control Panel and going to Tablet PC Settings then clicking "Reset..."

1
  • I'm pretty sure all calibration data in Windows 7 is stored in the registry, under "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TabletPC\UserLinearityData". Delete that key and see if it 'resets' it in the way you expect, then come back and let us know. :) May 10, 2016 at 20:38

5 Answers 5

9

Short answer

tabcal.exe ClearCal DisplayID=\\.\DISPLAY1

Long answer

You won't find an official list of command-line parameters for tabcal.exe anywhere, but I hope this is of use to someone. This information is brought to you by Process Monitor (my go-to utility to understand what a process was told to do via command line arguments as well as what's it's doing to other processes, the file system, and registry) and liberal use of the Google.

Here's what I believe I've figured out:

ClearCal

              resets calibration data for a given device
              requires DisplayID

LinCal

              runs calibration
              (if ClearCal isn't specified, default function is LinCal)
              requires DisplayID if you have more than one device with pen and/or touch capabilities
              may require DeviceKind if you have both pen and touch digitizers on a single display

DisplayID=\\.\DISPLAY1

              one-based display index associated with the touch screen
              (If you have two displays it's 1 or 2; value matches multi-display identification number in Display Control Panel)

Quiet

              Suppresses message boxes
              E.g., if you do LinCal, your changes will be saved rather than being prompted if you'd like to save
              E.g., if you have an error with your command-line arguments, you won't receive a message indicating that

DeviceKind={touch,pen}

              Seemingly optional argument to ClearCal and LinCal to indicate the type of digitizer
              (I suspect it may be required if you have both on the same display but my digitizer supports only touch.)

{validate,novalidate}

              Optional argument to LinCal to prevent or accept registration of calibration marks that are way off from the crosshairs
              If unspecified, the default is validate

XGridPts=
YGridPts=

              Optional arguments (if used both required) to LinCal to specify X and Y coordinates of crosshairs for calibration.
              Values are a comma-delimited list without spaces of the zero-based pixel coordinates
              (e.g., for a 1920×1080, display X values 0-1919 and Y values 0-1079 are accepted; some examples are below)
              If unspecified, calibration points default to four unless previously specified (values are retrieved from HKLM:\SYSTEM\CurrentControlSet\Control\TabletPC\LinearityData)

Export

              Optional argument to LinCal to export calibration data to a file.
              Output file is in directory from which tabcal was called, named 'caldatan.txt', where n is a zero-based auto-incrementing number
              Contents of file are the name of the digitizer, a line break, and the same hex string written to the registry value in HKLM:\SYSTEM\CurrentControlSet\Control\TabletPC\LinearityData
              (I haven't found a corresponding Import function.)

Other stuff I've learned

There are three registry subkeys which contain calibration data:

  • HKLM:\SYSTEM\CurrentControlSet\Control\TabletPC\LinearityData
  • HKLM:\SYSTEM\CurrentControlSet\Control\TabletPC\UserLinearityData
  • HKLM:\SYSTEM\CurrentControlSet\Enum\HID\VID_xxxx&&PID_xxxx&Colxx\(non-deterministic)\Device Parameters

The first two may contain a binary value named vid_xxxxpid_xxxx&colxx containing the calibration data for that specific device as well as XGridPts and YGridPts values if you calibrated with more than 4 touch points.

The Enum\HID subkey that has the same VID/PID/Col values in its name as the LinearityData value will have a value named LinearityData with the same data as the above.

If you delete all of these registry values, you will have reset the calibration data, but the change doesn't take effect until that data is read back in by the system, either on the subsequent boot or when the wisptis.exe user process is restarted. (An orderly restart of the Tablet PC Input Service doesn't do it even though it stops and restarts the wisptis.exe processes. Go figure.)

A much easier way to do this is to run the following command (which requires elevation) which deletes those keys and effects the change immediately:

tabcal.exe ClearCal DeviceKind=touch DisplayID=\\.\DISPLAY1

This is the exact command that is run when a user selects "Reset..." from the Tablet PC Settings Control Panel on my test system. If you have a pen-input device or a different display configuration, your command may differ slightly. (If you have UAC enabled, before allowing the Reset action you can open the Details pane to see the full command-line to be executed. Alternatively, you could pull that info from Process Monitor.)

As you already determined, you can then re-calibrate the touchscreen using a derivative of one of the following commands depending on the size of your display and your specific requirements:

# Default touch calibration (4 points unless someone's previously specified XGridPts/YGridPts)
tabcal.exe lincal novalidate devicekind=touch
tabcal.exe lincal novalidate devicekind=pen

# Example 25-point touch calibration for 1920×1080 display
tabcal.exe lincal novalidate devicekind=touch XGridPts=10,485,960,1435,1910 YGridPts=10,275,540,805,1070

# Example 121-point pen calibration (from a Microsoft Surface forum)
tabcal.exe lincal novalidate devicekind=pen XGridPts=10,60,110,360,660,960,1260,1560,1810,1860,1910 YGridPts=10,60,110,200,330,490,650,810,970,1020,1070
3
  • Great answer. I've accepted your answer! One thing to note, we have a regular "User" that calibration won't work under because it's restricted so we require having to login as an Admin to do the calibration. It's a pain but works. Even executing the tabcal.exe under an Admin elevated CMD, it won't save the calibration as I'm guessing some sub-process is kicked off that doesn't have the permissions to save the data to the registry and do other saving routines.
    – ScottN
    Sep 13, 2019 at 14:50
  • Also, one more question: With Process Monitor, can you set it so a process that has exited (quickly) doesn't get removed from the list so you can still inspect what command line args it was executed with?
    – ScottN
    Sep 14, 2019 at 12:57
  • Interesting. Running tabcal.exe manually (from elevated context) should get the calibration data into HKLM but the user/session wisptis/dwm processes don’t automatically re-consult the registry for the update requiring them (or the user session entirely) to be restarted. Process Monitor is the best tool to tell if/why the registry writes had failed. As described in this answer, it’s a better tool for getting the arguments of fast-exiting process (filter on Operation=“Process Start”): superuser.com/a/1289465/614344
    – Dan
    Sep 14, 2019 at 16:19
4

I ran tabcal through strings. The list below may be possible switches. I do not know what they do.

LinCal
ShowCursor
Quiet
NoValidate
SaveFiles
Export
UserLinCal
ClearCal
NoDesktop
XInterval=
YInterval=
XGridPts=
YGridPts=
DeviceName=
DevicePath=
DisplayID=
DeviceKind=
UserSid=
UserSid=%s %s
RunAs
TabCalSingleInstance
1
  • Thanks for the list. Not sure why you got a downvote (I negated it). It's a decent start. I'll try a few of them out too.
    – ScottN
    Jun 28, 2016 at 15:06
4

Additional information:

On Windows 10, instead of restarting wisptis.exe, you have to kill DWM.exe (it restarts automatically) for the new values from the registry to take effect (if you don't use TabCal.exe).

Also of note, if you change the calibration data manually in the registry, you should emit the Windows message SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, NULL, "TabletPCDigitizerMappingChanged") as TabCal does to notify any client that calibration values have changed.

1
  • Very awesome information, your answer is the only google result for "TabletPCDigitizerMappingChanged" other then decombiler output. Would it be possible for you to give an example on how to send the Window Message using C#?
    – usbpc102
    Nov 26, 2022 at 14:30
1

Thank you so much for everyone's work in this thread! I was able to use this information to solve a y-axis inversion problem with a new touchscreen. I created the custom calibration test using the following code:

tabcal lincal novalidate DeviceKind=touch DisplayID=\\.\DISPLAY1 XGridPts=99,1265 YGridPts=99,667

This successfully inverted my y-axis points and allowed me to use the new touchscreen normally. This was used on a 1366 by 768 display so edit according to your display size.

1

I'd like to add my thanks for this info, it has been invaluable with our Win10 IOT Enterprise Touchscreen application. I really couldn't believe there is still very little information on the subject over 5 years on... Some of our custom Touchscreens have been bonded together with a slight offset - I thought it was going to be easy to adjust the touch position in our WPF kiosk app, however, Running tabcal.exe appears to be the only way. I thought there would be registry entries I could alter or maybe override the Touch positions before they bubble down into touch or mouse clicks, but couldn't find anything along those lines.

I finally managed to create a console app in VS which runs tabcal.exe with the necessary options. I can now use it to switch off UWF, reboot, run the app that calls tabcal.exe, calibrate the screen, switch UWF back on, reboot back into the kiosk app.

For anyone interested in overcoming the issues of "The System cannot find the file specified" when trying to run tabcal.exe from WPF/C#, this might help you:

    ProcessStartInfo processInfo = new ProcessStartInfo();
processInfo.FileName = @"C:\Windows\Sysnative\tabcal.exe";
processInfo.Arguments = @"clearcal DisplayID=\\.\DISPLAY1";
processInfo.WorkingDirectory = @"C:\Windows\Sysnative";

processInfo.ErrorDialog = true;
processInfo.UseShellExecute = false;
processInfo.RedirectStandardOutput = false;
processInfo.RedirectStandardError = false;
Process proc = Process.Start(processInfo);
proc.WaitForExit();

processInfo = new ProcessStartInfo();
processInfo.FileName = @"C:\Windows\Sysnative\tabcal.exe";
// these arguments give a 100px cal border on the 1280x800 Touchscreens
processInfo.Arguments = @"lincal novalidate DisplayID=\\.\DISPLAY1 DeviceKind=touch XGridPts=99,1179 YGridPts=99,699";
processInfo.WorkingDirectory = @"C:\Windows\Sysnative";

processInfo.ErrorDialog = true;
processInfo.UseShellExecute = false;
processInfo.RedirectStandardOutput = false;
processInfo.RedirectStandardError = false;
proc = Process.Start(processInfo);
proc.WaitForExit();

So, this will clear existing cal data and then run the calibration screen with 4 points. The key points being:

Set the app that is used to call tabcal.exe as 32 bit (not sure this is absolutely necessary)

Add app.manifest and set: <requestedExecutionLevel level="highestAvailable" uiAccess="false" />

Note the use of C:\Windows\Sysnative\ rather than C:\Windows\System32 apparently Windows thinks you should be using C:\Windows\SysWOW64 and changes the directory for you but then can't find tabcal.exe in that folder so bombs out.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .