Win32 pen simulation not working with InjectTouchInput() - c#

Im using win32 touchinjection on windows 10 desktop.
I have been trying for two days to get pen simulation.
The code below works with PointerInputType.Touch but i need pressure and orientation, which don't seem to work.
GetLastError() returns 87 which means bad parameter but i have tried every pair of parameters i can think of.
InitializeTouchInjection();
pointer = new PointerTouchInfo();
pointer.PointerInfo.PointerId = 1;
pointer.PointerInfo.pointerType = PointerInputType.PEN;
pointer.TouchMasks = TouchMask.PRESSURE | TouchMask.ORIENTATION;
// pointer.TouchMasks = TouchMask.CONTACTAREA | TouchMask.ORIENTATION | TouchMask.PRESSURE;
pointer.Pressure = 1024;
pointer.Orientation = 90;
// pointer.PointerInfo.PtHimetricLocation.X = 50;
// pointer.PointerInfo.PtHimetricLocation.Y = 200;
pointer.PointerInfo.PtPixelLocation.X = 50;
pointer.PointerInfo.PtPixelLocation.Y = 200;
pointer.PointerInfo.PointerFlags = PointerFlags.INCONTACT |PointerFlags.INRANGE| PointerFlags.DOWN;
var a1=InjectTouchInput(1, new[] { pointer });
var b1 = GetLastError();
int errCode = Marshal.GetLastWin32Error();
Any information on how i could get this working or debug this further would be greatly appreciated.

There's a new InjectSyntheticPointerInput API very similar to InjectTouchInput which supports pen as well as touch. Can't help with C# or .NET but I imagine it can be exposed the same way. Only problem is it's only supported by Windows 10 1809 and above, so you'll need at least that version of the Windows SDK (which only supports Visual Studio 2017, not 2015, FYI).

Related

how to detect blobs in an image using emgu?

The older version of EMGU ( < 4.5.2) we could find blobs easily using the blobdetector and cvblobs methods like this :
Emgu.CV.Cvb.CvBlobs resultingImgBlobs = new Emgu.CV.Cvb.CvBlobs();
Emgu.CV.Cvb.CvBlobDetector bDetect = new Emgu.CV.Cvb.CvBlobDetector();
uint numWebcamBlobsFound = bDetect.Detect(greyThreshImg, resultingImgBlobs);
But in the latest version, there is no CVblobs and BlobDetector, there is a simpleblobdetector class but its useless.
Does anyone knows or can point me to some documentation on how to find blobs in the new version (4.5.5) ?
You can use the SimpleBlobDetector, it is what you are looking for.
You find it "useless" beacuase you didn't set it up correctly according to your usecase.
To set its parameters you need to use SimpleBlobDetectorParams.
Here is an example:
SimpleBlobDetector simpleBlobDetector = new SimpleBlobDetector(new SimpleBlobDetectorParams()
{
FilterByCircularity = true,
FilterByArea = true,
MinCircularity = 0.7f,
MaxCircularity = 1.0f,
MinArea = 500,
MaxArea = 10000
});
Here are just some parameters, you can find more about them in Emgu Documentation

Guide to use Yolo with gpu c#

I've been trying to find a tutorial or something on how to make yolo c# use gpu instead of cpu, I always find that it says that it works on both cpu and gpu but no one ever says how to use the gpu since it always uses cpu for me. Here's my code with yolo v5 c#. It doesn't really matter for me if it uses yolo v5 just that it uses gpu. Tutorial I found that tutorial but i can't even find the download for Nvidia cuDNN v7.6.3 for CUDA 10.1. It feels very unclear on how to use it with gpu please help me :D
var image = pictureBox1.Image;
var scorer = new YoloScorer<YoloCocoP5Model>("Assets/Weights/yolov5n.onnx");
List<YoloPrediction> predictions = scorer.Predict(image);
var graphics = Graphics.FromImage(image);
foreach (var prediction in predictions) // iterate predictions to draw results
{
using (MemoryStream ms = new MemoryStream())
{
pictureBox1.Image.Save(ms, ImageFormat.Png);
prediction.Label.Color = Color.FromArgb(255, 255, 0, 0);
double score = Math.Round(prediction.Score, 2);
graphics.DrawRectangles(new Pen(prediction.Label.Color, 1),
new[] { prediction.Rectangle });
var (x, y) = (prediction.Rectangle.X - 3, prediction.Rectangle.Y - 23);
graphics.DrawString($"{prediction.Label.Name} ({score})",
new Font("Consolas", 16, GraphicsUnit.Pixel), new SolidBrush(prediction.Label.Color),
new PointF(x, y));
pictureBox1.Image = image;
}
}
Before you are going to use scorer you need an option set.
//https://onnxruntime.ai/docs/execution-providers/CUDA-ExecutionProvider.html
bool initResult = false;
var cudaProviderOptions = new Microsoft.ML.OnnxRuntime.OrtCUDAProviderOptions(); // Dispose this finally
var providerOptionsDict = new Dictionary<string, string>();
providerOptionsDict["device_id"] = "0";
providerOptionsDict["gpu_mem_limit"] = "2147483648";
providerOptionsDict["arena_extend_strategy"] = "kSameAsRequested";
/*
cudnn_conv_algo_search
The type of search done for cuDNN convolution algorithms.
Value Description
EXHAUSTIVE (0) expensive exhaustive benchmarking using cudnnFindConvolutionForwardAlgorithmEx
HEURISTIC (1) lightweight heuristic based search using cudnnGetConvolutionForwardAlgorithm_v7
DEFAULT (2) default algorithm using CUDNN_CONVOLUTION_FWD_ALGO_IMPLICIT_PRECOMP_GEMM
Default value: EXHAUSTIVE
*/
providerOptionsDict["cudnn_conv_algo_search"] = "DEFAULT";
/*
do_copy_in_default_stream
Whether to do copies in the default stream or use separate streams. The recommended setting is true. If false, there are race conditions and possibly better performance.
Default value: true
*/
providerOptionsDict["do_copy_in_default_stream"] = "1";
/*
cudnn_conv_use_max_workspace
Check tuning performance for convolution heavy models for details on what this flag does. This flag is only supported from the V2 version of the provider options struct when used using the C API. The V2 provider options struct can be created using this and updated using this. Please take a look at the sample below for an example.
Default value: 0
*/
providerOptionsDict["cudnn_conv_use_max_workspace"] = "1";
/*
cudnn_conv1d_pad_to_nc1d
Check convolution input padding in the CUDA EP for details on what this flag does. This flag is only supported from the V2 version of the provider options struct when used using the C API. The V2 provider options struct can be created using this and updated using this. Please take a look at the sample below for an example.
Default value: 0
*/
providerOptionsDict["cudnn_conv1d_pad_to_nc1d"] = "1";
cudaProviderOptions.UpdateOptions(providerOptionsDict);
options = SessionOptions.MakeSessionOptionWithCudaProvider(cudaProviderOptions); // Dispose this finally
if (options != null)
{
// check yolo model file is accesible
if (File.Exists(yoloModelFile))
{
scorer = new YoloScorer<YoloCocoP5Model>(yoloModelFile, options);
initResult = true;
}
else
{
DebugMessage("Yolo model ONNX file (" + yoloModelFile + ") is missing!\r\n", 2);
}
}
else
DebugMessage("Yolo instance initializing error! Session options are empty!\r\n", 2);
}

Error when trying to capture desktop using DXGI and DirectX11 on intel 630 HD

I get the below error when trying to use DXGI to capture the builtin screen on my laptop that runs on an Intel 630 HD with the latest driver. The code works when I capture the external screen running on my GTX 1070.
SharpDX.SharpDXException
HResult=0x80070057
Message=HRESULT: [0x80070057], Module: [General], ApiCode: [E_INVALIDARG/Invalid Arguments], Message: The parameter is incorrect.
The code in my form:
desktopDuplicator = new DesktopDuplicatorD11(1,0, DesktopDuplicatorD11.VSyncLevel.None);
The section of the code that errors:
private bool RetrieveFrame()
{
if (desktopImageTexture == null)
desktopImageTexture = new Texture2D(mDevice, mTextureDescription);
frameInfo = new OutputDuplicateFrameInformation();
try
{
mDeskDuplication.AcquireNextFrame(500, out frameInfo, out desktopResource);
}
catch (SharpDXException ex)
{
if (ex.ResultCode.Code == SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code)
{
return true;
}
if (ex.ResultCode.Failure)
{
throw new DesktopDuplicationException("Failed to acquire next frame.");
}
}
using (var tempTexture = desktopResource.QueryInterface<Texture2D>())
{
mDevice.ImmediateContext.CopyResource(tempTexture, desktopImageTexture);
}
return false;
}
It errors specifically on the line:
desktopImageTexture = new Texture2D(mDevice, mTextureDescription);
What is causing the error when using the internal display and the intel 630?
Edit #1:
mTextureDescription creation:
this.mTextureDescription = new Texture2DDescription()
{
CpuAccessFlags = CpuAccessFlags.Read,
BindFlags = BindFlags.None,
Format = Format.B8G8R8A8_UNorm,
Width = this.mOutputDescription.DesktopBounds.Right,
Height = this.mOutputDescription.DesktopBounds.Bottom,
OptionFlags = ResourceOptionFlags.None,
MipLevels = 1,
ArraySize = 1,
SampleDescription = { Count = 1, Quality = 0 },
Usage = ResourceUsage.Staging
};
The whole Desktop Duplication process is done on the same thread.
Update #2:
On the intel 630 Width = this.mOutputDescription.DesktopBounds.Right, returns 0 where as on my 1070 it returns 1920.
The most simplest reason is usually the actual problem.
Intel's final WDDM 2.6 drivers do not work properly with switchable graphics, update to the DCH WDDM 2.7 driver.
First, to get hints from API about invalid argument (this is exactly what you have) you need to enable Direct3D Debug Layer. The article explains it for C++ and it is possible to do a similar trick with C# as well.
Second, important is what are effectively the arguments in the failing call, not just the code.
The code is about right but if coordinates in mOutputDescription are zero or invalid, the mentioned API call is going to fail as well. You need to set a break point and inspect the variable.

C# printer does print report in only about 1/6 of the page

Ever since I upgraded ActiveReports from version 7 to 11 the reports get printed at about 1/6 of the page and with weird layouting, only the pictures being printed correctly.
But apparently it only is when printing, not previewing it. As strange as it seems, I expect the problem to be the SystemPrinter object.
As far as my understanding goes this object is properly defined.
// get printer
if (systemPrinter == null)
{
systemPrinter = new SystemPrinter { PrinterName = systemPrinterName };
systemPrinter.StartJob("My-printjob");
}
// set paper source and size
SetPaper(systemPrinter, systemPrinterPaperSource);
// set draw size
var internalOffSetX = systemPrinter.PhysicalOffsetX / systemPrinter.Graphics.DpiX;
var internalOffSetY = systemPrinter.PhysicalOffsetY / systemPrinter.Graphics.DpiY;
internalOffSetX = internalOffSetX - (offSetX / 2.54f);
internalOffSetY = internalOffSetY - (offSetY / 2.54f);
var printWidth = (systemPrinter.PaperSize.Width / 100f) - internalOffSetX;
var printHight = (systemPrinter.PaperSize.Height / 100f) - internalOffSetY;
// Scale: A4 (printable)
var smlOut = RectangleF.FromLTRB(-internalOffSetX, -internalOffSetY, printWidth, printHight);
systemPrinter.Graphics.PageUnit = GraphicsUnit.Pixel;
//Important edit for StackOverflow: Just added this line and the pdf looks perfect
SaveDocumentAsPdf(#"C:\Temp\SaveAsPDF\mydocument.pdf", report);
foreach (Page page in report.Document.Pages)
{
systemPrinter.StartPage();
page.Draw(systemPrinter.Graphics, smlOut);
systemPrinter.EndPage();
}
With the PaperHeight being 11.69f and the PaperWidth being 8.27f, ClipBounds being {X = -699050.6 Y = -699050.6 Width = 1398101.25 Height = 1398101.25} System.Drawing.RectangleF
However I can't stress enough on the fact that I only changed the ActiveReports version to 11 (which now uses inches for messurement, but the preview still being ok. Output doesn't change when I print it on a phyiscal printer or a bullzip printer.
Does anyone have some insight on this?
Edit:
Just before printing the report by using a method that has already been written, the pdf looks perfect.
var pdfReportArchiv = new PdfExport();
pdfReportArchiv.Security.Encrypt = encrypt;
pdfReportArchiv.Security.Permissions = PdfPermissions.AllowPrint;
pdfReportArchiv.Security.Use128Bit = true;
pdfReportArchiv.Export(report.Document, pathAndName);
Apparantly with the change from 7 to 11 the line systemPrinter.Graphics.PageUnit = GraphicsUnit.Pixel;was no longer used and caused the problem.

Taking input from a joystick with C# .NET

I searched around on Google for this, but the only things I came up with were outdated and did not work.
Does anyone have any information on how to get joystick data using C# .NET?
Since this was the top hit I got on google while researching joystick / gamepad input in C#, I thought I should post a response for others to see.
The easiest way I found was to use SharpDX and DirectInput. You can install it via NuGet (SharpDX.DirectInput)
After that, it's simply a matter of calling a few methods:
Sample code from SharpDX
static void Main()
{
// Initialize DirectInput
var directInput = new DirectInput();
// Find a Joystick Guid
var joystickGuid = Guid.Empty;
foreach (var deviceInstance in directInput.GetDevices(DeviceType.Gamepad,
DeviceEnumerationFlags.AllDevices))
joystickGuid = deviceInstance.InstanceGuid;
// If Gamepad not found, look for a Joystick
if (joystickGuid == Guid.Empty)
foreach (var deviceInstance in directInput.GetDevices(DeviceType.Joystick,
DeviceEnumerationFlags.AllDevices))
joystickGuid = deviceInstance.InstanceGuid;
// If Joystick not found, throws an error
if (joystickGuid == Guid.Empty)
{
Console.WriteLine("No joystick/Gamepad found.");
Console.ReadKey();
Environment.Exit(1);
}
// Instantiate the joystick
var joystick = new Joystick(directInput, joystickGuid);
Console.WriteLine("Found Joystick/Gamepad with GUID: {0}", joystickGuid);
// Query all suported ForceFeedback effects
var allEffects = joystick.GetEffects();
foreach (var effectInfo in allEffects)
Console.WriteLine("Effect available {0}", effectInfo.Name);
// Set BufferSize in order to use buffered data.
joystick.Properties.BufferSize = 128;
// Acquire the joystick
joystick.Acquire();
// Poll events from joystick
while (true)
{
joystick.Poll();
var datas = joystick.GetBufferedData();
foreach (var state in datas)
Console.WriteLine(state);
}
}
I hope this helps.
I even got this to work with a DualShock3 and the MotioninJoy drivers.
One: use SlimDX.
Two: it looks something like this (where GamepadDevice is my own wrapper, and the code is slimmed down to just the relevant parts).
Find the joystick / pad GUIDs:
public virtual IList<GamepadDevice> Available()
{
IList<GamepadDevice> result = new List<GamepadDevice>();
DirectInput dinput = new DirectInput();
foreach (DeviceInstance di in dinput.GetDevices(DeviceClass.GameController, DeviceEnumerationFlags.AttachedOnly))
{
GamepadDevice dev = new GamepadDevice();
dev.Guid = di.InstanceGuid;
dev.Name = di.InstanceName;
result.Add(dev);
}
return result;
}
Once the user has selected from the list, acquire the gamepad:
private void acquire(System.Windows.Forms.Form parent)
{
DirectInput dinput = new DirectInput();
pad = new Joystick(dinput, this.Device.Guid);
foreach (DeviceObjectInstance doi in pad.GetObjects(ObjectDeviceType.Axis))
{
pad.GetObjectPropertiesById((int)doi.ObjectType).SetRange(-5000, 5000);
}
pad.Properties.AxisMode = DeviceAxisMode.Absolute;
pad.SetCooperativeLevel(parent, (CooperativeLevel.Nonexclusive | CooperativeLevel.Background));
pad.Acquire();
}
Polling the pad looks like this:
JoystickState state = new JoystickState();
if (pad.Poll().IsFailure)
{
result.Disconnect = true;
return result;
}
if (pad.GetCurrentState(ref state).IsFailure)
{
result.Disconnect = true;
return result;
}
result.X = state.X / 5000.0f;
result.Y = state.Y / 5000.0f;
int ispressed = 0;
bool[] buttons = state.GetButtons();
The bad news is that Microsoft seems to stop supporting their NET libraries for DirectX and focus on XNA instead. I don't work in GameDev so I don't need to use XNA but you may try it if you developing computer games. The good news is that there are other approaches. One is SlimDX the new framework to help you to wok with DirectX from C#. The other way is to directly add references of "Microsoft.DirectX.dll" and "Microsoft.DirectX.DirectInput.dll" to your project. you can find them "..\Windows\Microsoft.NET\DirectX for Managed Code\". if you you are going to use last approach here is a link to codeproject where you can read how to work with a joystick.
EDIT:
If your application is based on NET version newer then 2.0 the application may hang on. To fix this problem change config file and add this:
<startup useLegacyV2RuntimeActivationPolicy="true">
Google led me here and while not a requirement of this question, OpenTK is a good option for Windows and Linux (under mono) support.
From the OpenTK docs, this code works on Raspberry Pi + Raspbian + Mono 3.12.0:
for (int i = 0; i < 4; i++)
{
var state = Joystick.GetState(i);
if (state.IsConnected)
{
float x = state.GetAxis(JoystickAxis.Axis0);
float y = state.GetAxis(JoystickAxis.Axis1);
// Print the current state of the joystick
Console.WriteLine(state);
}
}
This question is old, but it seems to be active even to this day, so I'm posting anyway.
If you need to get input from XInput only, take a look at XInputium. This is a .NET library that is specialized in XInput controllers. It is pretty straightforward, and has many code samples you can look at.

Categories