Control brightness in Windows at software Level - windows

It might be possible for a similar question to be already present on the site, but I have searched a lot and didn't find any relevant solution, so I'm posting it here.
I'm making a Night Light Application, which has two options-
Lessen the Brightness of the PC
Apply a Blue light filter mask over the screen.
I'm making this app cross platform, so I've already found a solution for Linux Systems, where I've been making use of xrandr utility to adjust the brightness and gamma at the software level, and my app works flawlessly.
The main problem is for Windows systems, where the brightness feature is only available for portable screens such as for a Laptop.
I cannot find any solution for this.
I made use of Qt5 for making a translucent app window which works good, but doesn't meet the requirement because the things displayed at kernel level are not masked like the cursor, taskbar, start menu, action center, and lots of other.
I searched a lot and lot, which included Microsoft Developer Network, where documentation included the Win32 API where brightness feature was present, but it didn't work for me, as I had a Desktop PC.
So my main problem is, How can I ajust the brightness of all Windows PC, including Laptops, Desktops n all others.
I'm working on Python with ctypes module.
I'm not that much familiar with VC+ and I cannot even afford to install it on my system as it is too much storage and resource intensive.
I primarily want to modify the output going to the physical monitor, that is to modify the Gamma values to get appropriate brightness and Yellow tincture.
I got something called gdi32.dll which deals with the outputs to screens, but I cannot find a way out as everything on the Internet is alongside C++.
Also, I cannot even provide my try code, as I'm not that much familiar to C type coding in Python.
Also, the thing I want to do, Intel Graphics Command Center already does it on my desktop.
If it can do it on at a software level, then I know its possible programmatically.
Can anyone tell is this possible what I'm thinking, and if yes, how can I achieve this?
I don't want the source code, I just want the way out for that.
Maybe GammaRamp from the Gdi32 API can be used, but I don't know how to begin.
This is a thread which actually asked this, but I didn't get my answer from here, and newbies are restricted from commenting, so I didn't have any choice than to post this question here.

I have found the way for the problem.
We can use GetDeviceGammaRamp and SetDeviceGammaRamp from the gdi32.dll library in Windows OS to set the brightness level.
To call these functions through Python, we can use ctypes module.
Below is the sample code that can set brightness of in Windows 10 via Python.
import ctypes
def displayGammaValues(lpRamp):
"""
Displays the GammaArray of 256 values of R,G,B individually
:param lpRamp: GammaArray
:return: None
"""
print("R values: ", end=' ')
for j in range(256):
print(lpRamp[0][j], end=' ')
print()
print("G values: ", end=' ')
for j in range(256):
print(lpRamp[0][j], end=' ')
print()
print("B values: ", end=' ')
for j in range(256):
print(lpRamp[0][j], end=' ')
print(), print()
def changeGammaValues(lpRamp, brightness):
"""
Modifies the Gamma Values array according to specified 'Brightness' value
To reset the gamma values to default, call this method with 'Brightness' as 128
:param lpRamp: GammaArray
:param brightness: Value of brightness between 0-255
:return: Modified GammaValue Array
"""
for i in range(256):
iValue = i * (brightness + 128)
if iValue > 65535: iValue = 65535
lpRamp[0][i] = lpRamp[1][i] = lpRamp[2][i] = iValue
return lpRamp
if __name__ == '__main__':
brightness = 100 # can be aby value in 0-255 (as per my system)
GetDC = ctypes.windll.user32.GetDC
ReleaseDC = ctypes.windll.user32.ReleaseDC
SetDeviceGammaRamp = ctypes.windll.gdi32.SetDeviceGammaRamp
GetDeviceGammaRamp = ctypes.windll.gdi32.GetDeviceGammaRamp
hdc = ctypes.wintypes.HDC(GetDC(None))
if hdc:
GammaArray = ((ctypes.wintypes.WORD * 256) * 3)()
if GetDeviceGammaRamp(hdc, ctypes.byref(GammaArray)):
print("Current Gamma Ramp Values are:")
displayGammaValues(GammaArray)
GammaArray = changeGammaValues(GammaArray, brightness)
print("New Current Gamma Ramp Values are:")
displayGammaValues(GammaArray)
if SetDeviceGammaRamp(hdc, ctypes.byref(GammaArray)): print("Values set successfully!")
else: print("Unable to set GammaRamp")
if ReleaseDC(hdc): print("HDC released")
else: print("HDC not found")
This sets the brightness value, that's between 0-255. Values may differ system-to-system, so preferable range for brightness is 0 - 128 where 128 is the default brightness.

FYI windows already has a monitor blue shade/color shift built in. Dimming external monitor outputs on a desktop is likely not possible.
You'll need to hook into the windows API somehow to control windows functions. There's some documentation about adjusting color temperature (making that warmer would essentially add a "blue light" filter to a screen on microsoft's website.
https://learn.microsoft.com/en-us/windows/win32/api/highlevelmonitorconfigurationapi/nf-highlevelmonitorconfigurationapi-setmonitorcolortemperature.
In terms of executing a small CPP script that actually can interface with windows, you can write a small CPP program, then compile it and execute from python using (slightly modified from this question)
import os
import subprocess
for filename in os.listdir(os.getcwd()):
proc = subprocess.Popen(["./prog", filename])
proc.wait()
However if you don't have the room to install visual studio compile tools, you won't be able to compile a small CPP script locally. There are a few online services that would be able to do that for you though.

Related

How to set a cursor of non-standard size in Windows 10?

I am attempting to change the cursor in Windows 10 (version 1703) to a custom made one (conditional on some event when a script activates), that is larger than the default 32 by 32 size. The MWE based on my Autohotkey script is the following:
ImagePath = %A_ScriptDir%\foo.cur
Cursor_ID := 32512 ; Standard arrow
Cursor_Size := 128
^0::
SetSystemCursor( ImagePath, Cursor_ID, Cursor_Size, Cursor_Size )
return
SetSystemCursor( path, id, sizeX, sizeY )
{
Cursor := DllCall( "LoadImage",
UInt,0, Str,path, UInt,0x2, Int,sizeX, Int,sizeY, UInt,0x00000010, Ptr)
DllCall( "SetSystemCursor", Ptr,Cursor, Int,id )
}
(My code is based off of that found at https://autohotkey.com/board/topic/32608-changing-the-system-cursor/.)
As far as I can tell from the documentation of LoadImage, the function SetSystemCursor(...) should load the image with dimensions (sizeX, sizeY) when those parameters are not 0 (since the flag LR_DEFAULTSIZE = 0x00000040 is not set), but instead I get the following behaviour: no matter what sizes I set, the image gets scaled to (sizeX, sizeY), and then down/upscaled to (32, 32). This is most obvious by setting, say Cursor_Size := 2, then I get an upscaled version of a 2 by 2 image.
After some searching around I have found both information suggesting that this should work, and also to the effect that the size of cursors is always dictated by getSystemMetrics(SM_CXCURSOR)
and getSystemMetrics(SM_CYCURSOR): The biggest size of Windows Cursor (see also GetSystemMetrics).
Additional tests/ideas I've tried:
I checked the dimensions of the image corresponding to the handle returned
by LoadImage, and it seems to be (sizeX, sizeY), just as it should be,
therefore the scaling to 32 most likely happens upon executing SetSystemCursor.
I wanted to see if an application-specific cursor could bypass the
apparent 32 by 32 restriction, so using Resource Hacker, I replaced one of
the resources in Paint. It was scaled down to size 32 in the same way.
Setting the values that are returned by
getSystemMetrics(SM_CXCURSOR) and getSystemMetrics(SM_CYCURSOR)
might be an option if these indeed restrict cursor sizes, but I
could not find an appropriate function. I checked
SystemParametersInfo, but the only remotely relevant option
I found was SPI_SETCURSORS, and that just reloads the cursors from
registry.
It might be possible to change a registry value, though it would not
be my preferred solution, as it would most likely require a reboot
to take effect. Additionally, I haven't been able to find the relevant key.
My question would therefore be the following:
Is there a way to add an image of arbitrary size as a cursor in Windows 10, preferably without the need to reboot the computer? If so, how? Do SM_CXCURSOR and SM_CYCURSOR absolutely restrict the cursor's size? If they do, can these values be changed somehow?
EDIT:
It has been pointed out that yes, the documentation of GetSystemMetrics states "the system cannot create cursors of other sizes" than SM_CXCURSOR and SM_CYCURSOR, but at the same time at some of the other webpages I linked, people seem to claim to be able to create arbitrary sized cursors. Hence my request for confirmation/clarification of the matter.
Apart from that, the question about changing these values, or the existence of any other possible workaround would still be important to me.

Matlab - signal after command completion

Is there a way to set matlab to come to the foreground of the windows when the command in complete? I can see it happening by executing a dos() but I'm unaware how window management works? Maybe there is a better way? Someone?
Two options. Neither exactly what you are asking for.
Option 1: Open a new figure.
figure();
imagesc(processingDoneSplashImage);
If you want to get fancy, put this in a script, with a timer, and flash the image between bright green, and bright red....
Option 2: My solution to your problem. (I find popping up windows extremely annoying.) I put this function call at the end of my long running scripts, and the computer tells me when it's done processing....
function [ ] = matSpeak( textToSpeak )
%matSpeak takes some text, and outputs onto the speaker the text,
% using the .Net SpeechSynthesizer.
% This only works on Windoze.
if ~exist('textToSpeak','var')
textToSpeak = 'Your processing has completed.';
end
NET.addAssembly('System.Speech');
speak = System.Speech.Synthesis.SpeechSynthesizer;
speak.Volume = 100;
speak.Speak(textToSpeak);
end
Why not just use Growl for your notification windows?
cmd = ['/usr/local/bin/growlnotify -m ' messagestr];
system(cmd);
Of course with Windows you need to fix the path to the growlnotify binary.
Source: http://www.mathworks.com/matlabcentral/newsreader/view_thread/259142
A wrapper with lots of features: Send a notification to Growl on MATLAB Exchange
Many more examples: https://www.google.com/search?q=growl+matlab

Need a fast programming language that can drive two printers [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 9 months ago.
Improve this question
I have a rather unusual application that isn't working the way I need, and I hope someone here will have some suggestions or at least a direction to investigate.
We have a museum exhibit that has a computer at the entrance driving two small receipt printers. There are two buttons on a console, wired to the left and right buttons of a disemboweled mouse. The two printers and associated buttons are for girls and boys, each button does a random selection from a database of names and prints a small ticket on the appropriate printer with a graphic image, a few words about the exhibit and the randomly chosen name.
Conceptually all is well, but it hangs quite often. I got the project at the last minute, because the original designer got bogged down and couldn't deliver, so the exhibit's author asked me the day before opening, whether I could write something that would work.
I did it in Word, since I am an experienced VBA programmer. Several other avenues I attempted first all lead to dead ends - one couldn't do graphics, another couldn't handle two printers, yet another couldn't change fonts and so on. The problem is that it simply isn't fast enough - Word can only drive one printer at a time and changing the active printer takes a long time. Not by office standards, where a second or two of delay before a printer starts working on your document is not an issue, but here I need more or less instant response. If kids press a button and nothing happens, they press it over and over until something does happen, resulting in maybe half a dozen commands being sent before the printer starts reacting. Sometimes it jams the program completely, since boys and girls will be pressing the two buttons simultaneously and Word locks up, and even when it doesn't jam, the printers then spit out a stream of tickets, making a mess. The kids start squabbling over which ticket is whose, pulling them out of the printers, snarling the paper tape, jamming the printer and generally making a mess of the whole affair, often necessitating the exhibit caretakers having to restart the computer and clear torn bits of paper out the printers.
What I need is some sort of fast programming language that can drive two printers *-simultaneously-*, not the MSOffice claptrap of having to switch the active printer, that can react to both left and right mouse button click events, can print a small graphic image and can print in different font sizes and styles and. I don't need many, but it's not all in one typeface.
Can anyone suggest what I might use for this? I don't even know if it's possible at all under Windows, whether the "single active printer" garbage is an Office artifact, or a Windows restriction. My little Commodore-64 twenty-five years ago had two printers attached to it and drove both simultaneously with no difficulties - it doesn't seem to me it should be such an impossible requirement today.
Being a Python programmer myself, I would use something like MSWinPrint.py, and render the documents directly using Python. It looks like it supports text and images, and you can easily select any printer in the system by name.
You would need to:
Install Python.
Install Python for Windows Extensions.
Install PIL.
Install MSWinPrint.
Then, you would need to write a program to do the printing. Something like the following.
#python
import sys
import Image, ImageWin
import MSWinPrint
# workaround for PIL namespace change
MSWinPrint.ImageWin = ImageWin
def print_name(name, printer_name):
doc = MSWinPrint.document(printer_name)
doc.begin_document('nametag for %s' % name)
# print the name at position 20,20
text_pos = 20, 20
doc.text(text_pos, name)
# add an image for this person
img_pos = 40, 40
img_size = 100, 100
doc.image(img_pos, get_image(), img_size)
doc.end_document()
def get_image():
image_filename = 'my image.jpg'
return Image.open(image_filename)
if __name__ == '__main__':
name, printer_name = sys.argv[1:]
print_name(name, printer_name)
If you save this as print_tag.py, then you can execute it with two command line arguments, the name to be printed and the image filename.
print_tag.py Sally "EPSON Artisan 810"
I ran this code and it worked great. I didn't know creating a custom print job could be so easy.
You can of course run the program as often as you like on as many printers as you would like. There's certainly more you can do to customize when an how the print job is run. You could customize the code to always run and interpret the mouse clicks (for that you might need wxPython), or you might have another program that just executes the script.
As other have said, the programming language isn't going to make much difference. However (and this is a BIG however), the print libraries built into most scripting languages, such as VBA and .NET, either only support printing to the system default printer (most common, and cannot be worked around by having two instances open simultaneously, as the system default printer is a global setting) or require you to configure a global variable to specify the active printer (this only affects one process, so could be worked around using two instances).
Instead, you will have to invoke the windows API directly. It most certainly allows printing directly to any printer on the system. Here is an example of how to use the default printer. Note that only one line of code (calling the GetDefaultPrinter function) ties this to the default printer. Supplying a different printer name to CreateDC gets you a different printer.
If you instead call the EnumPrinters function, you can find out ANY or ALL of the printer names, not just the default. Or have the administrator preconfigure the printer names to use in a registry setting or text file.
In any case, you can have device contexts for all printers open simultaneously. Of course, once you have the printer device context, you have to create a print job, send your content, and end the print job. There's a great deal of information available on MSDN.
All the examples are in C, which makes C++ the obvious language for printing to non-default printers, but as long as you know how to call WinAPI functions from your language, you can use it instead. In VBA, that'd require Declare Function XYZ Lib "gdi32" (params here)
This is not a problem with the programming language, its just a limitation of the printer stack you are using.
I am not sure if .NET would support it (or Windows for that matter) would support sending printing on a thread. You could put each printer in its own thread and block the UI from accepting more print requests.
You could also try to turn on print spooling for both printers. That will render it locally and return then print.
I wrote something a few years ago (in VB6 so could probably be ported to VBA easily) that bypassed the printer driver (a printer must be set up but the actual driver used was irrelevant) and sent raw commands to the printer. Depending on what sort of printer you are using this may or may not be an issue (some use complex escape sequences). If you want to print graphics, this could add another layer of complication - although it can be done if you know what commands the printer supports. I managed to get bitmaps printing on a dot matrix printer, but it wasn't a 5 minute task. If this is something you are interested in I can try and dig out the code?
The Code is as follows:
Public Type DOCINFO
pDocName As String
pOutputFile As String
pDatatype As String
End Type
Declare Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
Declare Function EndDocPrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
Declare Function EndPagePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, phPrinter As Long, ByVal pDefault As Long) As Long
Declare Function StartDocPrinter Lib "winspool.drv" Alias "StartDocPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, pDocInfo As DOCINFO) As Long
Declare Function StartPagePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
Declare Function WritePrinter Lib "winspool.drv" (ByVal hPrinter As Long, pBuf As Any, ByVal cdBuf As Long, pcWritten As Long) As Long
Public Function PrintRawData(ByVal sPrinter As String, ByVal sDocName As String, ByVal sData As String) As Boolean
On Error GoTo PrintErr:
Dim lhPrinter As Long, lReturn As Long, lpcWritten As Long
Dim lDoc As Long, sWrittenData As String
Dim MyDocInfo As DOCINFO
Dim pOutput As Printer
Dim p As Printer
For Each p In Printers
If p.DeviceName = sPrinter Then
Set pOutput = p
GoTo StartPrinting
End If
Next p
MsgBox "Unable to find the specified printer [" & sPrinter & _
"] in the list of currently installed printers" & vbCrLf & _
"Printing will be aborted", vbCritical
Exit Function
StartPrinting:
lReturn = OpenPrinter(pOutput.DeviceName, lhPrinter, 0)
If lReturn = 0 Then
MsgBox "Print was unsuccessful. Make sure there is a printer installed on the port you are trying to print to"
Exit Function
End If
MyDocInfo.pDocName = sDocName
MyDocInfo.pOutputFile = vbNullString
MyDocInfo.pDatatype = vbNullString
lDoc = StartDocPrinter(lhPrinter, 1, MyDocInfo)
Call StartPagePrinter(lhPrinter)
sWrittenData = sData
lReturn = WritePrinter(lhPrinter, ByVal sWrittenData, Len(sWrittenData), lpcWritten)
lReturn = EndPagePrinter(lhPrinter) 'need this??
lReturn = EndDocPrinter(lhPrinter)
lReturn = ClosePrinter(lhPrinter)
Exit Function
PrintErr:
MsgBox "Print was unsuccessful. Make sure there is a printer installed on the port you are trying to print to"
Exit Function
End Function
To use it you need to install a printer that uses the correct port using any driver (I generally use the Generic / text Only Driver) and then call it as follows replacing the Hello with the data you want to send to the printer including control characters etc:
PrintRawData "Generic / Text Only", "My Document", "Hello"
Updated and completely overhauled Answer :
Pete, have you considered an entirely different kind of printer? The setting, changing and sending PostSCript commands can take, indeed, a lot of time.
A strange solution you might call it, but our instant B/W laser Brother label printer prints out instantly on a press of the button. Their specialty rock solid in house developed P-Touch Editor 5.4 Software is created in such a way as to output to multiple printers simeltaneously(!!), each printing the same or different lables (for example different serial numbers or dates from a database).
Its snappy: when letting go of a return button, just when my finger has reached half a centimeter in the button already IIIIEEEUUUUUU (1 second after release of return key) the entire lable is out. Albeit in black and white.
Aside lables there are also paper lables without sticky backs 102mm wide rols by either original or third party brands makes.
Cost: 100$ ~ 400$ per unit incl software to design and customise connections with database.
I know that those instant printers use much less windows-based drivers and more embedded technologies, relieving the system from standardized print jobs.
Perhaps this solves your problem or brings you on a new idea.

API to get the graphics or video memory

I want to get the adpater RAM or graphics RAM which you can see in Display settings or Device manager using API. I am in C++ application.
I have tried seraching on net and as per my RnD I have come to conclusion that we can get the graphics memory info from
1. DirectX SDK structure called DXGI_ADAPTER_DESC. But what if I dont want to use DirectX API.
2. Win32_videocontroller : But this class does not always give you adapterRAM info if availability of video controller is offline. I have checked it on vista.
Is there any other way to get the graphics RAM?
There is NO way to directly get graphics RAM on windows, windows prevents you doing this as it maintains control over what is displayed.
You CAN, however, create a DirectX device. Get the back buffer surface and then lock it. After locking you can fill it with whatever you want and then unlock and call present. This is slow, though, as you have to copy the video memory back across the bus into main memory. Some cards also use "swizzled" formats that it has to un-swizzle as it copies. This adds further time to doing it and some cards will even ban you from doing it.
In general you want to avoid directly accessing the video card and letting windows/DirectX do the drawing for you. Under D3D1x Im' pretty sure you can do it via an IDXGIOutput though. It really is something to try and avoid though ...
You can write to a linear array via standard win32 (This example assumes C) but its quite involved.
First you need the linear array.
unsigned int* pBits = malloc( width * height );
Then you need to create a bitmap and select it to the DC.
HBITMAP hBitmap = ::CreateBitmap( width, height, 1, 32, NULL );
SelectObject( hDC, (HGDIOBJ)hBitmap );
You can then fill the pBits array as you please. When you've finished you can then set the bitmap's bits.
::SetBitmapBits( hBitmap, width * height * 4, (void*)pBits )
When you've finished using your bitmap don't forget to delete it (Using DeleteObject) AND free your linear array!
Edit: There is only one way to reliably get the video ram and that is to go through the DX Diag interfaces. Have a look at IDxDiagProvider and IDxDiagContainer in the DX SDK.
Win32_videocontroller is your best course to get the amount of gfx memory. That's how its done in Doom3 source.
You say "..availability of video controller is offline. I have checked it on vista." Under what circumstances would the video controller be offline?
Incidentally, you can find the Doom3 source here. The function you're looking for is called Sys_GetVideoRam and it's in a file called win_shared.cpp, although if you do a solution wide search it'll turn it up for you.
User mode threads cannot access memory regions and I/O mapped from hardware devices, including the framebuffer. Anyway, what you would want to do that? Suppose the case you can access the framebuffer directly: now you must handle a LOT of possible pixel formats in the framebuffer. You can assume a 32-bit RGBA or ARGB organization. There is the possibility of 15/16/24-bit displays (RGBA555, RGBA5551, RGBA4444, RGBA565, RGBA888...). That's if you don't want to also support the video-surface formats (overlays) such as YUV-based.
So let the display driver and/or the subjacent APIs to do that effort.
If you want to write to a display surface (which not equals exactly to framebuffer memory, altough it's conceptually almost the same) there are a lot of options. DX, Win32, or you may try the SDL library (libsdl).

How do you retrieve stylus pressure information on windows?

Is anyone aware of a sane way to get tablet/stylus pressure information on Windows?
It's possible to distinguish stylus from mouse with ::GetMessageExtraInfo, but you can't get any more information beyond that. I also found the WinTab API in a out of the way corner of the Wacom site, but that's not part of windows as far as i can tell, and has a completely distinct event/messaging system from the message queue.
Given all I want is the most basic pressure information surely there is a standard Win32/COM API, is anyone aware of what it might be?
The current way to do this is to handle WM_POINTERnnn msgs.
Note this is for Win 8 and later.
Note you will get these msgs for touch AND pen, so you'll need to know the pointerType in order to test for pen. The WPARAM received by a WNDPROC for WM_POINTERnnnn msgs such a WM_POINTERUPDATE and other msgs contains the pointer id which you will need in order to request more info. Empirically I found that WM_POINTERUPDATE results in info that contains pressure data whereas if the pointer flags indicate down/up there is no pressure info.
const WORD wid = GET_POINTERID_WPARAM(wParam);
POINTER_INFO piTemp = {NULL};
GetPointerInfo(wid, &piTemp);
if (piTemp.pointerType == PT_PEN
{
UINT32 entries = 0;
UINT32 pointers = 0;
GetPointerFramePenInfoHistory(wid, &entries, &pointers, NULL); // how many
// TODO, allocate space needed for the info, process the data in a loop to retrieve it, test pointerInfo.pointerFlags for down/up/update.
}
Once you know you are dealing with pen, you can get the pressure info from the POINTER_PEN_INFO struct.
This is similar to handling touch although for touch you'd want gesture recognition and inertia. There is a Microsoft sample illustrating using these functions.
It's part of a Build talk:
https://channel9.msdn.com/Events/Build/2013/4-022
You need to use the Tablet PC Pen/Ink API. The COM version of the API lives in InkObj.dll. Here is a starting point for documentation: http://msdn.microsoft.com/en-us/library/ms700664.aspx
If I remember correctly, InkObj.dll is available on Windows XP SP2 and all later Windows client OSes, regardless of whether the machine is a Tablet PC.
UPDATE:
It's been a number of years since I initially provided this answer, but wintab has become the de facto standard, and Ntrig more or less folded, eventually building a wrapper to allow for the wintab API to be accessed via this digitizer.
(http://www.tabletpcbuzz.com/showthread.php?37547-N-trig-Posts-WinTAB-Support-Driver)
This is a pretty late response, but recently my wife and I purchased a Dell XT tablet PC, which as it turns out actually uses NTrig, a suite of interfaces that utilize Ink, the accepted new windows API that shipped with Windows XP Tablet edition, then SP 2 and all versions thereafter.
A lot of Wacom tablets and others use the Wintab API, which is not currently open nor really permitted to use. From what I hear the folks who maintain it are pretty sue-happy.
So it depends on what type of tablet you're using, and the drivers you have installed for it. In my biased opinion, you should work with Ink, as it provides (or at least through NTrig and Windows 7 WILL provide) multi-touch capability and will likely be the new standard for tablet interfaces. But as of now, NTrig devices do not translate their pressure and angle information to common Wintab-based applications, such as Photoshop or Corel Painter. The applications tend to require at least some support for Microsoft's Tablet API in order to function properly.
If using UWP Windows Runtime then it's quite straightforward. The PointerEventArgs event seems to have all necessary data.
Modified Core App (C++/WinRT) template project snippet from Visual Studio 2019:
void OnPointerMoved(IInspectable const &, PointerEventArgs const &args)
{
if (m_selected)
{
float2 const point = args.CurrentPoint().Position();
m_selected.Offset(
{
point.x + m_offset.x,
point.y + m_offset.y,
0.0f
});
// (new!) Change sprite color based on pen pressure and tilt
auto sprite = m_selected.as<SpriteVisual>();
auto const props = args.CurrentPoint().Properties();
auto const pressure = props.Pressure();
auto const orientation = props.Orientation() / 360.0f;
auto const tiltx = (props.XTilt() + 90) / 180.0f;
auto const tilty = (props.YTilt() + 90) / 180.0f;
Compositor compositor = m_visuals.Compositor();
sprite.Brush(compositor.CreateColorBrush({
(uint8_t)(pressure * 0xFF),
(uint8_t)(tiltx * 0xFF),
(uint8_t)(tilty * 0xFF),
(uint8_t)(orientation * 0xFF)
}));
}
}
Similar code will likely work in C#, JavaScript, etc.

Resources