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.
Related
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'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/
I'm using the ArcGIS Runtime SDK 100.1.0 for .NET. I have a mobile map package (.mmpk) vector map and want to limit the maximum and minimum zoom in the MapView. I tried to track the MapScale property and set it:
((INotifyPropertyChanged)MyMapView).PropertyChanged += (sender, args) =>
{
args.PropertyName;
var s = MyMapView.MapScale;
if(s < 500)
MyMapView.SetViewpointScaleAsync(700);
if (s > 16500000)
MyMapView.SetViewpointScaleAsync(16500000);
};
This works, but map jerks at low/high zoom levels because it tries to smooth zoom and I can't figure out how to stop the active zooming task. What is the right way to do this?
The easy way
If you just want to set a minimum scale and a maximum scale, the Map class has MinScale and MaxScale properties. Replace your code with the following:
MyMapView.Map.MaxScale = 700;
MyMapView.Map.MinScale = 16500000;
The hard way
You probably don't need this! Use the easy way listed above unless you have a good reason to do something more complicated!
If instead for some reason you really want to track scale changes and then change the scale yourself, you should do it in a different way. Currently you're listening for PropertyChanged, which is way too broad. One effect is that when the scale changes, your event handler runs, which performs an asynchronous zoom, which generates a scale change before it's finished, which calls your event handler, which performs an asynchronous zoom, which generates a scale change before it's finished, which calls your event handler, which...I could go on and on. Literally. And so will your program, unless you make some changes.
Here's one way to do it:
// Save a variable so you can invoke the EventHandler elsewhere
EventHandler navigationCompletedHandler = (sender, args) =>
{
var s = MyMapView.MapScale;
if (s < 500)
MyMapView.SetViewpointScaleAsync(700);
if (s > 16500000)
MyMapView.SetViewpointScaleAsync(16500000);
};
MyMapView.NavigationCompleted += navigationCompletedHandler;
// Invoke the above handler one time when the map first loads
EventHandler firstViewpointChangeHandler = null;
firstViewpointChangeHandler = (sender, args) =>
{
if (!double.IsNaN(MyMapView.MapScale))
{
MyMapView.ViewpointChanged -= firstViewpointChangeHandler;
navigationCompletedHandler.Invoke(null, null);
}
};
MyMapView.ViewpointChanged += firstViewpointChangeHandler;
You can just set the zoom levels to whatever intervals you want in ArcMap for your map file, when you build your map package / publish it to a service ArcMap seems to honour it (does for me at least).
Map Scale Drop Down -> Customize This List -> Standard Scales -> Tick the box "Only display these scales when zooming"
Saves having to write a custom mapscale event handler.
As a side note, this question has nothing to do with SharpDX, it is purely a Kinect 2.0 SDK question.
I am migrating a completed Kinect 1.8 project to the Kinect 2.0 SDK. In this program I have a WPF front end, but 99% of the code is written in SharpDX for C#. The program hides the KinectRegions cursor and uses the cursor location and grip data as the input to the SharpDX code. With this new version of the Kinect SDK however, I can't find any way to get the relative cursor data (hand position relative to the user). I tried using skeleton data to extrapolate the cursor location, just a simple primary shoulder location - primary hand location. This has the issue of when the hand occludes the shoulder, the cursor would shoot around. If I switch shoulders by reflecting across the spine when the occlusion occurs, I get a momentary jump. I can think of a way to get this to work but it will take quite a bit of code. I want to make sure there is no other way before I dive into that. Thanks in advance for any help!
You should check out Mike Taulty's blog. He utilizes the KinectCoreWindow to grab the pointer movement. One note of caution though: this event gets raised for both hands even if they're not "active." I mitigated this by utilizing the body frame to set which hand was higher (y) to denote that that hand was "active."
...
var window = KinectCoreWindow.GetForCurrentThread();
window.PointerMoved += window_PointerMoved;
...
void window_PointerMoved(object sender, KinectPointerEventArgs e)
{
if ((!rightHand && e.CurrentPoint.Properties.HandType == HandType.LEFT) ||
(rightHand && e.CurrentPoint.Properties.HandType == HandType.RIGHT))
{
//do something with this hand pointer's location
}
}
void _bodyReader_FrameArrived(object sender, BodyFrameArrivedEventArgs e)
{
//get and check frame
//...
using (frame)
{
frame.GetAndRefreshBodyData(_bodies);
foreach(Body body in _bodies)
{
if(body.IsTracked)
{
CameraSpacePoint left = body.Joints[JointType.HandLeft].Position;
CameraSpacePoint right = body.Joints[JointType.HandRight].Position;
if (left.Y > right.Y)
rightHand = false;
else
rightHand = true;
break; //for this example I'm just looking at the first
//tracked body - other handling is required if you
//want to keep track of more than one body's hands
}
}
}
}
The other part is that your previous application could hide the KinectRegion cursor; I have not as of yet found out how to do that with the Kinect v2 (which is what brought me to this question actually lol).
In my opinion the MS Office Smooth Typing is a very innovative feature in the Office Suite, and I'd like to know if this feature is available for programmers in the .NET Framework, specifically in the C# language.
If so, could you please post in your answer a usage example and link to the documentation?
Thanks.
By "smooth typing" I'm referring to the typing animation, that makes the cursor slide during typing.
I don't own Office, so I can't look at the feature, but I needed to fiddle around with the caret in RichTextBoxes a while ago and decided that it wasn't worth the effort. Basically you are on your own. No helper functions from .NET, but everything is handled by the backing Win32 control. You will have a hard time defeating what already happens under the hood. And probably ending up intercepting window messages and lots of ugly code.
So my basic advice is: Don't do it. At least for basic form controls like the TextBox or RichTextBox. You may have more luck trying to remote access an running office from within .NET, but that is a totally different can of worms.
If you really insist on going the SetCaretPos - route, here is some code to get you up and running with a basic version where you can improve upon:
// import the functions (which are part of Win32 API - not .NET)
[DllImport("user32.dll")] static extern bool SetCaretPos(int x, int y);
[DllImport("user32.dll")] static extern Point GetCaretPos(out Point point);
public Form1()
{
InitializeComponent();
// target position to animate towards
Point targetCaretPos; GetCaretPos(out targetCaretPos);
// richTextBox1 is some RichTextBox that I dragged on the form in the Designer
richTextBox1.TextChanged += (s, e) =>
{
// we need to capture the new position and restore to the old one
Point temp;
GetCaretPos(out temp);
SetCaretPos(targetCaretPos.X, targetCaretPos.Y);
targetCaretPos = temp;
};
// Spawn a new thread that animates toward the new target position.
Thread t = new Thread(() =>
{
Point current = targetCaretPos; // current is the actual position within the current animation
while (true)
{
if (current != targetCaretPos)
{
// The "30" is just some number to have a boundary when not animating
// (e.g. when pressing enter). You can experiment with your own distances..
if (Math.Abs(current.X - targetCaretPos.X) + Math.Abs(current.Y - targetCaretPos.Y) > 30)
current = targetCaretPos; // target too far. Just move there immediately
else
{
current.X += Math.Sign(targetCaretPos.X - current.X);
current.Y += Math.Sign(targetCaretPos.Y - current.Y);
}
// you need to invoke SetCaretPos on the thread which created the control!
richTextBox1.Invoke((Action)(() => SetCaretPos(current.X, current.Y)));
}
// 7 is just some number I liked. The more, the slower.
Thread.Sleep(7);
}
});
t.IsBackground = true; // The animation thread won't prevent the application from exiting.
t.Start();
}
Use SetCaretPos with your own animation timing function. Create a new thread that interpolates the caret's position based on the previous location and the new desired location.