I'm using a Wacom Bamboo Pen tablet and I'd like to be able to get its pen pressure value in my application written in C#. How do I do that? Is there maybe an API that allows one to get pen values on Windows 7?
Wacom provides an extensive API to get data directly from the tablet.The API includes example code for detecting pressure, tilt and other interactions:
Tilt Test: Demonstrates pressure, use of the eraser and pen tilt properties
Pressure Test: Demonstrates how to detect and display pen pressure
These code samples are in C, but there are also examples that in c#.net that include code to handle pressure:
WintabDN: Interface, scribble and tablet control samples using Wintab .NET
Using this project as an example, you can get the pressure like this:
// Create a data object and hook a packetlistener to receive
// updatse by the tablet
m_wtData = new CWintabData();
m_wtData.SetWTPacketEventHandler(handler);
//Handles packet receive event
void handler(object sender,MessageReceivedEventArgs e)
{
//Get the packet id
uint pktID = (uint)eventArgs_I.Message.WParam;
//Get the data for that packet
WintabPacket pkt = m_wtData.GetDataPacket((uint)eventArgs_I.Message.LParam, pktID);
//Grab the pressure
var pressure = pk.pkNormalPressure.pkAbsoluteNormalPressure;
}
Next, here is a CodeProject that explains how to use the Wacom Tablet with the WPF InkCanvas
A good starting point for any tablet related development on windows is also the Ink API.
Can be a starting point
http://www.codeproject.com/Articles/46281/Digitizer-interface-in-C-using-VBTablet
Thats the right link to the project: http://sourceforge.net/projects/vbtablet/
Related
I have a quite specific problem regarding to a transformation matrix for transformations from the HoloLens 2 webcam space into the current Unity scene space in a Unity+MRTK+OpenXR app. The goal is to acquire the exact camera pose related to a camera frame, which was acquired through Windows.Media.Capture, in Unity space.
My environment:
Unity 2021.3.8.
MRTK v2.8.2
Mixed Reality OpenXR Plug-In v1.6.0
For obtaining the matrix, I first receive a Windows.Perception.Spatial.SpatialCoordinateSystem instance (unityReferenceCoordinateSystem) representing the Unity Space through the MR OpenXR Plug-In as described HERE:
using Windows.Perception.Spatial;
using Microsoft.MixedReality.OpenXR;
SpatialCoordinateSystem unityReferenceCoordinateSystem = PerceptionInterop.GetSceneCoordinateSystem(Pose.identity) as SpatialCoordinateSystem;
and I obtain the camera space (cameraCoordinateSystem) from the Windows.Media.Capture.Frames.MediaFrameReference camera frame instance acquired from a MediaFrameReader by
MediaFrameReference mediaFrame; // acquired camera frame
SpatialCoordinateSystem cameraCoordinateSystem = mediaFrame.CoordinateSystem;
Finally I obtain the required transformation matrix by using SpatialCoordinateSystem.TryGetTransformTo() as you can see in my complete method:
using Microsoft.MixedReality.Toolkit;
public bool TryGetCameraToUnityMatrix(out Matrix4x4 cameraToUnity)
{
// (obtain MediaFrameReader, acquire a camera frame and obtain
// unityReferenceCoordinateSystem and cameraCoordinateSystem as described above)
System.Numerics.Matrix4x4? camToUnitySysMatrix = cameraCoordinateSystem.TryGetTransformTo(unityReferenceCoordinateSystem);
if (!camToUnitySysMatrix.HasValue)
{
return false;
}
cameraToUnity = camToUnitySysMatrix.Value.ToUnity();
return true;
}
This works all fine so far - until I bring the HoloLens into another spatial environment, which is not connected to the environment, which was present when the app was started.
Describing the following scenario should make clear what I mean by that:
Start the app on HL2
Acquire the cameraToUnity matrix as described --> works fine
Set the HL to stand-by
Go to another room, for which the HL's spatial awareness does not know the connection between these two rooms
Wake up HL and open the (still running) app.
Acquire the cameraToUnity matrix. --> FAILS:
camToUnitySysMatrix.HasValue returns false (even though both arguments unityReferenceCoordinateSystem and cameraCoordinateSystem are not null.)
Set the HL to stand-by again
Go back to the initial environment where the app was originaly started
Wake up HL and open the (still running) app.
Acquire the cameraToUnity matrix as described --> works fine again! (camToUnitySysMatrix has valid value again)
I also made sure that unityReferenceCoordinateSystem = PerceptionInterop.GetSceneCoordinateSystem(Pose.identity) is re-called after I changed the environment and also the MediaFrameReader gets freshly instantiated origining from a new MediaCapture instance.
But obviously a transformation between the two SpatialCoordinateSystems seems to fail if it is attempted in the non-initial spatial environment.
Any ideas on how to solve this?
UPDATE
A minimal Unity sample project for reproducing this problem can be found here:
https://github.com/pjaydev/trygettransformto-so
Usually, users should wear the HoloLens device and keep it turned on while moving and operating, so that the device can fully understand the environment. And HoloLens also has some requirements on the size of the site used, if the room is too small, HoloLens may not work properly. If you have confusion about this issue or there is business impact, you can submit a ticket via aka.ms/HLSupport.
I know GDI+ is a bit antiquated, but I'm currently being forced to use it in in a WinForms app to draw complex CAD type models.
I encountered what I believe is the same issue as:
Why is my c# paint method running out of memory? as described by the currently accepted answer (https://stackoverflow.com/a/7501899/9300908) as well as some comments. I've ensured my brushes, pens, and fonts are disposed of as well as bitmaps and other gdi objects. I'm drawing 10s to 100s of thousands of arcs with the DrawArc() function and the same arc (1.13 degrees) each time is giving me trouble. I suspect I have encountered the small arc bug.
I'm planning to simply draw a line instead of an arc at whenever the conditions exceed a certain threshold, but I'm struggling to define the threshold. I'm trying to find a good source for what size is too small (I see references to < 1 degree, < 2 pixels, < 3.5 degrees) so that I don't need to rely on the exception handler especially when dealing with similarly small arcs.
The referenced answer as well as comments refer to a number of Microsoft Connect articles that are unavailable now that Microsoft Connect is now retired. I don't seem to have the magic sauce to find it in the visual studio developer community where I thought it might be moved to. Anyone have any reference material on the DrawArc bug or maybe an alternative workaround?
Connect references:
http://connect.microsoft.com/VisualStudio/feedback/details/121532/drawarc-out-of-memory-exception-on-small-arcs
http://connect.microsoft.com/VisualStudio/feedback/details/253886/graphics-drawarc-throws-outofmemoryexception-for-no-good-reason
Mentioned on msdn regarding DrawPath:
https://social.msdn.microsoft.com/Forums/vstudio/en-US/4c0aa2b2-6555-4c6f-85fc-8467e86bdf20/systemdrawinggraphicsdrawpath-throws-outofmemoryexception-when-drawing-a-very-small-cubic-bezier?forum=netfxbcl
https://connect.microsoft.com/VisualStudio/feedback/details/182774
Other forums I've found point back to the referenced question.
Update
Environment is x64, .NET 4.5.2
1.13 is the sweepAngle (see below for the effective values). It and the startAngle are both native floats.
I can recreate the exception with this sample code from a new WinForms app.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// g is a graphics object created from a 1920W x 1080H Bitmap:
using (Bitmap mBitmapModel = new Bitmap(1920, 1080))
{
using (Graphics g = Graphics.FromImage(mBitmapModel))
{
float lStartAngle = -0.00816029962F;
float lSweepAngle = 1.13203466F;
RectangleF lRect = new RectangleF(742.741333F, 157.927505F, 3.28945208F, 3.28945208F);
using (Pen lPen = new Pen(Color.Blue, 2F))
{
g.DrawArc(lPen, lRect, lStartAngle, lSweepAngle);
}
}
}
}
}
I am building a UI using pure Direct2D and C# with SharpDX.
This UI is meant to be user-friendly and good-looking, while being efficient.
For the sake of demonstration, I built a prototype using hacky undocumented APIs (see this question), but in no way I am going to production with this, being backward-compatibility the first and foremost reason:
var accent = new User32.AccentPolicy { AccentState = AccentState };
int accentStructSize = Marshal.SizeOf(accent);
// allocate space for the struct
IntPtr accentPtr = Marshal.AllocHGlobal(accentStructSize);
Marshal.StructureToPtr(accent, accentPtr, false);
// set composition data
var data = new User32.WindowCompositionAttributeData {
Attribute = User32.WindowCompositionAttribute.WCA_ACCENT_POLICY,
SizeOfData = accentStructSize,
Data = accentPtr
};
// change window composition attributes and release resources
User32.SetWindowCompositionAttribute(Handle, ref data);
Marshal.FreeHGlobal(accentPtr);
I know the instant response to this is to use WPF, but I'm fairly limited to raw Direct2D calls, as I'm intending to move all the UI logic to a DLL for injection in DirectX apps (which, albeit not being sure how I'm going to do this, is out of the scope of this question.)
On Windows 8.1, there is DirectComposition, which enables efficient alpha-blending on top of transparent windows.
But there's no such thing in Windows Vista and 7 (even with the Platform Update).
Is there a way I can use pure, non-hacky Direct2D/DirectX code to make this UI work across all Windows versions (preferably Vista SP2 upwards)?
I'm developing an application for a Windows Surface Pro. I need to gather the pen pressure on the screen and i figuret out to do.
After solving some issue due to Event (StylusDown, StylusUp and other Stylus event are never raised, bu only mouse event) i landed in a work around.
I will show you the code (taken from some microsoft guide)
Basically is a filter for raw event
class MyFilterPlugin : StylusPlugIn
{
protected override void OnStylusDown(RawStylusInput rawStylusInput)
{
// Call the base class before modifying the data.
base.OnStylusDown(rawStylusInput);
Console.WriteLine("Here");
// Restrict the stylus input.
Filter(rawStylusInput);
}
private void Filter(RawStylusInput rawStylusInput)
{
// Get the StylusPoints that have come in.
StylusPointCollection stylusPoints = rawStylusInput.GetStylusPoints();
// Modify the (X,Y) data to move the points
// inside the acceptable input area, if necessary.
for (int i = 0; i < stylusPoints.Count; i++)
{
Console.WriteLine("p: " + stylusPoints[i].PressureFactor);
StylusPoint sp = stylusPoints[i];
if (sp.X < 50) sp.X = 50;
if (sp.X > 250) sp.X = 250;
if (sp.Y < 50) sp.Y = 50;
if (sp.Y > 250) sp.Y = 250;
stylusPoints[i] = sp;
}
// Copy the modified StylusPoints back to the RawStylusInput.
rawStylusInput.SetStylusPoints(stylusPoints);
}
Added as Filter in StylusPlugin
StylusPlugIns.Add(new MyFilterPlugin());
While i run this, however, i always get 0.5 as PressureFactor (the default value) and inspecting more deep I still can see the evironment of Stylus is not properly set (his Id is 0 for example).
There is a way to gather StylusEvent correctly?
The main point is: i need to gather the pressure (how much pressure) of the pen on the screen.
Thanks a lot.
Some Info: i'm developing with visuals tudio 2012 Ultimate, on a win 7 Pc. I deploy the application in a Surface Pro with windows 8.1. I installed and configured the Surface SDK 2.0 and the Surface Runtime.
For completition i have solved this.
Stylus event (don't know how) conflicted with the Surface SDK. Once i removed the SDK reference from the project all went smooth and the problem i solved.
Now i can gather correctly the pressure of each pen touch and on pen move.
I post this only for community information.
I'm using a Wacom Bamboo Pen tablet and I'd like to be able to get its pen pressure value in my application written in C#. How do I do that? Is there maybe an API that allows one to get pen values on Windows 7?
Wacom provides an extensive API to get data directly from the tablet.The API includes example code for detecting pressure, tilt and other interactions:
Tilt Test: Demonstrates pressure, use of the eraser and pen tilt properties
Pressure Test: Demonstrates how to detect and display pen pressure
These code samples are in C, but there are also examples that in c#.net that include code to handle pressure:
WintabDN: Interface, scribble and tablet control samples using Wintab .NET
Using this project as an example, you can get the pressure like this:
// Create a data object and hook a packetlistener to receive
// updatse by the tablet
m_wtData = new CWintabData();
m_wtData.SetWTPacketEventHandler(handler);
//Handles packet receive event
void handler(object sender,MessageReceivedEventArgs e)
{
//Get the packet id
uint pktID = (uint)eventArgs_I.Message.WParam;
//Get the data for that packet
WintabPacket pkt = m_wtData.GetDataPacket((uint)eventArgs_I.Message.LParam, pktID);
//Grab the pressure
var pressure = pk.pkNormalPressure.pkAbsoluteNormalPressure;
}
Next, here is a CodeProject that explains how to use the Wacom Tablet with the WPF InkCanvas
A good starting point for any tablet related development on windows is also the Ink API.
Can be a starting point
http://www.codeproject.com/Articles/46281/Digitizer-interface-in-C-using-VBTablet
Thats the right link to the project: http://sourceforge.net/projects/vbtablet/