Mouse move code snippet doesnt work with Kinect sdk2.0 - c#

Although am getting the values of cursorX, cursorY there is no movement of my mouse cursor. Am I missing anything?
Joint hand = helper.handRight;
CameraSpacePoint position = hand.Position;
DepthSpacePoint handPt = _sensor.CoordinateMapper.MapCameraPointToDepthSpace(position);
Point relativePoint = new Point(
handPt.X * (1920 / _sensor.DepthFrameSource.FrameDescription.Width),
handPt.Y * (1080 / _sensor.DepthFrameSource.FrameDescription.Height) );
cursorX = (int)relativePoint.X;
cursorY = (int)relativePoint.Y;
NativeMethods.SendMouseInput(cursorX, cursorY,
(int)SystemParameters.PrimaryScreenWidth,
(int)SystemParameters.PrimaryScreenHeight, leftClick);
public static class NativeMethods
{
public const int InputMouse = 0;
public const int MouseEventMove = 0x01;
public const int MouseEventLeftDown = 0x02;
public const int MouseEventLeftUp = 0x04;
public const int MouseEventRightDown = 0x08;
public const int MouseEventRightUp = 0x10;
public const int MouseEventMiddleDown = 0x0020;
public const int MouseEventMiddleUp = 0x0040;
public const int MouseEventAbsolute = 0x8000;
public const int MouseEventWheelScroll = 0x0800;
public const int MouseEventWheelHScroll = 0x1000;
private static bool lastLeftDown = false;
[DllImport("user32.dll", SetLastError = true)]
private static extern uint SendInput(uint numInputs, Input[] inputs, int size);
public static void SendMouseInput(int positionX, int positionY, int maxX, int maxY, bool leftDown)
{
if (positionX > int.MaxValue)
throw new ArgumentOutOfRangeException("positionX");
if (positionY > int.MaxValue)
throw new ArgumentOutOfRangeException("positionY");
Input[] i = new Input[4];
// move the mouse to the position specified
i[0] = new Input();
i[0].Type = InputMouse;
i[0].mouseInput.X = (positionX * 65535) / maxX;
i[0].mouseInput.Y = (positionY * 65535) / maxY;
i[0].mouseInput.Flags = MouseEventAbsolute | MouseEventMove;
// determine if we need to send a mouse down or mouse up event
if (!lastLeftDown && leftDown)
{
i[1] = new Input();
i[1].Type = InputMouse;
i[1].mouseInput.Flags = MouseEventLeftDown;
lastLeftDown = true;
}
else if (lastLeftDown && !leftDown)
{
i[1] = new Input();
i[1].Type = InputMouse;
i[1].mouseInput.Flags = MouseEventLeftUp;
lastLeftDown = false;
}
// send it off
uint result = SendInput(2, i, Marshal.SizeOf(i[0]));
if (result == 0)
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
}

Related

Scaling and Rotating together using wingdi function(SetWorldTransform)

I am using ExtTextOut wingdi function to draw text. Also, I am using SetWorldTransform for scaling text but now I want to rotate text(at all angles) too. How can I change/pass parameters to it so it will scale as well as rotate too?
Below is the sample code block, this code works perfect but now I want to introduce rotating text as well without impacting scaling.
var inputString = "Sample text";
var fontSize = 31f;
var font = new Font("Avenir Black", fontSize, new FontStyle());
var startX1 = 50;
var startY1 = 50;
LOGFONT lf = new LOGFONT();
font.ToLogFont(lf, e.Graphics);
IntPtr hPrinterDC = e.Graphics.GetHdc();
StringBuilder sbText = new StringBuilder(inputString);
if (hPrinterDC != IntPtr.Zero)
{
int nPrintHorzRes = GetDeviceCaps(hPrinterDC, HORZRES);
int nPrintVertRes = GetDeviceCaps(hPrinterDC, VERTRES);
int nPhysWidth = GetDeviceCaps(hPrinterDC, PHYSICALWIDTH);
int nPhysHeight = GetDeviceCaps(hPrinterDC, PHYSICALHEIGHT);
int nPhysOffsetX = GetDeviceCaps(hPrinterDC, PHYSICALOFFSETX);
int nPhysOffsetY = GetDeviceCaps(hPrinterDC, PHYSICALOFFSETY);
IntPtr hDCScreen = GetDC(IntPtr.Zero);
float nLogPixelsXScreen = GetDeviceCaps(hDCScreen, LOGPIXELSX);
float nLogPixelsYScreen = GetDeviceCaps(hDCScreen, LOGPIXELSY);
ReleaseDC(hDCScreen, IntPtr.Zero);
float nLogPixelsXPrinter = GetDeviceCaps(hPrinterDC, LOGPIXELSX);
float nLogPixelsYPrinter = GetDeviceCaps(hPrinterDC, LOGPIXELSY);
float nScaleX = Math.Max(nLogPixelsXScreen, nLogPixelsXPrinter) / Math.Min(nLogPixelsXScreen, nLogPixelsXPrinter);
float nScaleY = Math.Max(nLogPixelsYScreen, nLogPixelsYPrinter) / Math.Min(nLogPixelsYScreen, nLogPixelsYPrinter);
System.Drawing.Drawing2D.Matrix transform = new System.Drawing.Drawing2D.Matrix();
transform.Scale(nScaleX, nScaleY);
XFORM renderTransform = new XFORM();
var elements = transform.Elements;
var m11 = elements[0];
var m12 = elements[1];
var m21 = elements[2];
var m22 = elements[3];
var dx = elements[4];
var dy = elements[5];
renderTransform.eM11 = (float)m11;
renderTransform.eM12 = (float)m12;
renderTransform.eM21 = (float)m21;
renderTransform.eM22 = (float)m22;
int nOffsetX = 0;
int nOffsetY = 0;
renderTransform.eDx = (float)transform.OffsetX + nOffsetX;
renderTransform.eDy = (float)transform.OffsetY + nOffsetY;
SetGraphicsMode(hPrinterDC, GM_ADVANCED);
SetMapMode(hPrinterDC, MM_TEXT);
bool bRet = SetWorldTransform(hPrinterDC, ref renderTransform);
var startX2 = startX1;
var startY2 = startY1;
RECT rc = new RECT(startX2, startY2, nPhysWidth, nPhysHeight);
SetViewportOrgEx(hPrinterDC, -nPhysOffsetX, -nPhysOffsetY, IntPtr.Zero);
lf.lfHeight = (int)(lf.lfHeight / nScaleY);
IntPtr hFontNew = CreateFontIndirect(lf);
IntPtr hFontOld = SelectObject(hPrinterDC, hFontNew);
SetBkMode(hPrinterDC, TRANSPARENT);
SetTextColor(hPrinterDC, ColorTranslator.ToWin32(Color.Blue));
ExtTextOut(hPrinterDC, rc.left, rc.top, ETO_OPAQUE, IntPtr.Zero, sbText, (uint)sbText.Length, IntPtr.Zero);
rc.top += -lf.lfHeight;
SetTextColor(hPrinterDC, ColorTranslator.ToWin32(Color.Green));
ExtTextOut(hPrinterDC, rc.left, rc.top, ETO_OPAQUE, IntPtr.Zero, sbText, (uint)sbText.Length, IntPtr.Zero);
var nExtra = -10.0f / nScaleX;
SetTextCharacterExtra(hPrinterDC, (int)nExtra);
rc.top += -lf.lfHeight;
SetTextColor(hPrinterDC, ColorTranslator.ToWin32(Color.Red));
ExtTextOut(hPrinterDC, rc.left, rc.top, ETO_OPAQUE, IntPtr.Zero, sbText, (uint)sbText.Length, IntPtr.Zero);
SelectObject(hPrinterDC, hFontOld);
DeleteObject(hFontNew);
}
Here are pinvokes:
[DllImport("Gdi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool SetWorldTransform(IntPtr hdc, ref XFORM lpxf);
[StructLayout(LayoutKind.Sequential)]
public struct XFORM
{
public float eM11;
public float eM12;
public float eM21;
public float eM22;
public float eDx;
public float eDy;
}
[DllImport("Gdi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern int SetGraphicsMode(IntPtr hdc, int iMode);
public const int GM_COMPATIBLE = 1;
public const int GM_ADVANCED = 2;
public const int GM_LAST = 2;
[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
public const int TRANSPARENT = 1;
public const int OPAQUE = 2;
public const int BKMODE_LAST = 2;
[DllImport("Gdi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern int SetBkMode(IntPtr hdc, int mode);

Mouse Event - Mouse not moving as intended

I'm trying to move my cursor with Keyboard Arrow Keys. The result is that it will move, but only upwards and left.. towards the top left corner of the screen. It doesn't move downwards as intended.
Now, if I make my xSpeed and ySpeed greater than 3, it will work, but moving downwards and to the right will be slower. If I make the speed 10, then the result will be unnoticable, but that is way too fast for what I need this for.
[DllImport("User32.dll",EntryPoint = "mouse_event",CallingConvention = CallingConvention.Winapi)]
internal static extern void Mouse_Event(int dwFlags,int dx,int dy,int dwData,int dwExtraInfo);
[DllImport("User32.dll",EntryPoint = "GetSystemMetrics",CallingConvention = CallingConvention.Winapi)]
internal static extern int InternalGetSystemMetrics(int value);
private void UpdateLoop()
{
if (_hotKeys.Contains(Keys.Up))
MoveCursor(y: -YSpeed());
if (_hotKeys.Contains(Keys.Down))
MoveCursor(y: YSpeed());
if (_hotKeys.Contains(Keys.Left))
MoveCursor(x: -XSpeed());
if (_hotKeys.Contains(Keys.Right))
MoveCursor(x: XSpeed());
}
private void MoveCursor(int x = 0, int y = 0)
{
int to_x = MousePosition.X + x;
int to_y = MousePosition.Y + y;
int screenWidth = InternalGetSystemMetrics(0);
int screenHeight = InternalGetSystemMetrics(1);
int mic_x = (int)Math.Round(to_x * 65536.0 / screenWidth);
int mic_y = (int)Math.Round(to_y * 65536.0 / screenHeight);
Mouse_Event(0x0001 | 0x8000, mic_x, mic_y, 0, 0);
}
In this case, XSpeed and YSpeed are equal one.
public int XSpeed()
{
return int.Parse(tb_x.Text);
}
public int YSpeed()
{
return int.Parse(tb_y.Text);
}
Any help would be very appreciated!

InjectTouchInput Windows 8 C# not working (returns false)

I've just recently started playing with the InjectTouchInput for Windows 8 Consumer Preview. I've gone round and round in circles trying to get the darn thing to work but just can't seem to get it to actually interact. I'm working in c# and at the moment am only creating a metro interface with x and y coordinates in two text boxes and buttons which call the functions below to touch on the screen at those coordinates. Is this the right way to go about doing this?
protected unsafe class TouchDriver
{
public struct POINTER_TOUCH_INFO {
public POINTER_INFO pointerInfo; // An embedded POINTER_INFO header structure.
public TOUCH_FLAGS touchFlags; // Currently none.
public Rect rcContact; // Pointer contact area in pixel screen coordinates. By default, if the device does not report a contact area, this field defaults to a 0-by-0 rectangle centered around the pointer location.
public UInt32 orientation; // A pointer orientation, with a value between 0 and 359, where 0 indicates a touch pointer aligned with the x-axis and pointing from left to right; increasing values indicate degrees of rotation in the clockwise direction.
// This field defaults to 0 if the device does not report orientation.
public UInt32 pressure; // Pointer pressure normalized in a range of 0 to 256.
// This field defaults to 128 if the device does not report pressure.
// Question: Can this go from 0 to 1024 to match pen pressure?
}
public enum TOUCH_FLAGS
{
TOUCH_FLAGS_NONE = 0x00000000
}
public POINTER_TOUCH_INFO create_pointer_touch_info(POINTER_INFO pointerInfo, TOUCH_FLAGS touchFlags, RECT rcContact, UInt32 orientation, UInt32 pressure)
{
POINTER_TOUCH_INFO mi = new POINTER_TOUCH_INFO();
mi.pointerInfo = pointerInfo;
mi.touchFlags = touchFlags;
mi.rcContact = rcContact;
mi.orientation = orientation;
mi.pressure = pressure;
return mi;
}
public enum POINTER_INPUT_TYPE
{
PT_POINTER = 0x00000001,
PT_TOUCH = 0x00000002,
PT_PEN = 0x00000003,
PT_MOUSE = 0x00000004
}
public struct POINTER_INFO
{
public POINTER_INPUT_TYPE pointerType;
public UInt32 pointerId;
public UInt32 frameId;
public HANDLE sourceDevice;
public HWND hwndTarget;
public Point ptPixelLocation;
public Point ptHimetricLocation;
public Point ptPixelLocationPredicted;
public Point ptHimetricLocationPredicted;
public POINTER_FLAGS pointerFlags;
public DWORD dwTime;
public UInt32 historyCount;
// public UInt32 inputData;
public DWORD dwKeyStates;
public ULONGLONG Reserved;
}
public POINTER_INFO create_pointer_info(
POINTER_INPUT_TYPE pointerType,
UInt32 pointerId,
UInt32 frameId,
HANDLE sourceDevice,
HWND hwndTarget,
Point ptPixelLocation,
Point ptHimetricLocation,
Point ptPixelLocationPredicted,
Point ptHimetricLocationPredicted,
POINTER_FLAGS pointerFlags,
DWORD dwTime,
UInt32 historyCount,
// UInt32 inputData,
DWORD dwKeyStates,
ULONGLONG Reserved)
{
POINTER_INFO mi = new POINTER_INFO();
mi.pointerType = pointerType;
mi.pointerId = pointerId;
mi.frameId = frameId;
mi.sourceDevice = sourceDevice;
mi.hwndTarget = hwndTarget;
mi.ptPixelLocation = ptPixelLocation;
mi.ptHimetricLocation = ptHimetricLocation;
mi.ptPixelLocationPredicted = ptPixelLocationPredicted;
mi.ptHimetricLocationPredicted = ptHimetricLocationPredicted;
mi.pointerFlags = pointerFlags;
mi.dwTime = dwTime;
mi.historyCount = historyCount;
// mi.inputData = inputData;
mi.dwKeyStates = dwKeyStates;
mi.Reserved = Reserved;
return mi;
}
public enum POINTER_FLAGS
{
POINTER_FLAG_NONE = 0x00000000,
POINTER_FLAG_NEW = 0x00000001,
POINTER_FLAG_INRANGE = 0x00000002,
POINTER_FLAG_INCONTACT = 0x00000004,
POINTER_FLAG_FIRSTBUTTON = 0x00000010,
POINTER_FLAG_SECONDBUTTON = 0x00000020,
POINTER_FLAG_THIRDBUTTON = 0x00000040,
POINTER_FLAG_OTHERBUTTON = 0x00000080,
POINTER_FLAG_PRIMARY = 0x00000100,
POINTER_FLAG_CONFIDENCE = 0x00000200,
POINTER_FLAG_CANCELLED = 0x00000400,
POINTER_FLAG_DOWN = 0x00010000,
POINTER_FLAG_UPDATE = 0x00020000,
POINTER_FLAG_UP = 0x00040000,
POINTER_FLAG_WHEEL = 0x00080000,
POINTER_FLAG_HWHEEL = 0x00100000
}
[System.Runtime.InteropServices.DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
private static extern Boolean InjectTouchInput(UInt32 count, POINTER_TOUCH_INFO* pntTchInfo);
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern Boolean InitializeTouchInjection(UInt32 maxCount, DWORD dwMode);
private const UInt32 MAX_TOUCH_COUNT = 256; // Can be as high as 256
private const UInt32 TOUCH_FEEDBACK_DEFAULT = 0x1;
private const UInt32 TOUCH_FEEDBACK_INDIRECT = 0x2;
private const UInt32 TOUCH_FEEDBACK_NONE = 0x3;
public unsafe static void MouseTouch(int x, int y)
{
bool ret = false;
ret = InitializeTouchInjection(1, TOUCH_FEEDBACK_DEFAULT);
if (!ret)
{
throw new NotSupportedException();
}
Point point = new Point(x,y);
POINTER_INFO ptrInfo = new POINTER_INFO();
POINTER_TOUCH_INFO* ptrTchInfo;
ptrInfo.pointerType = POINTER_INPUT_TYPE.PT_TOUCH;
ptrInfo.pointerId = 1;
ptrInfo.ptPixelLocation = point;
ptrInfo.pointerFlags = POINTER_FLAGS.POINTER_FLAG_PRIMARY;
POINTER_TOUCH_INFO ptrTchInfobase = new POINTER_TOUCH_INFO();
ptrTchInfo = &ptrTchInfobase;
ptrTchInfo->pointerInfo = ptrInfo;
ptrTchInfo->touchFlags = TOUCH_FLAGS.TOUCH_FLAGS_NONE;
ptrTchInfo->rcContact.X = x - 2;
ptrTchInfo->rcContact.Y = y - 2;
ptrTchInfo->rcContact.Width = 4;
ptrTchInfo->rcContact.Height = 4;
ptrTchInfo->pressure = 128;
ptrTchInfo->orientation = 0;
ret = InjectTouchInput(1, ptrTchInfo);
if (!ret)
{
throw new NotImplementedException();
}
}
}
Almost all of that I've tried to lift from the InjectTouchInput API I found online. I can InitializeTouchInject fine, its the Inject bit thats returning false and I have no idea why.
I went ahead and create some custom functions in c++ based on the sample Microsoft provided and then went and imported that into C# using alot of the same definitions as before but without farting about with all the type checking, pointers and arguments that were causing headaches before.
The DLL file that I've used is TouchInjectionDriver.dll and can be found here:
http://www.mediafire.com/file/do2h6m04omjweb3/TouchInjectionDriver.zip
Below is the C# code I used to implement it.
public enum TOUCH_MASK : uint
{
TOUCH_MASK_NONE = 0x00000000,
TOUCH_MASK_CONTACTAREA = 0x00000001,
TOUCH_MASK_ORIENTATION = 0x00000002,
TOUCH_MASK_PRESSURE = 0x00000004
}
public enum POINTER_INPUT_TYPE : uint
{
PT_POINTER = 0x00000001,
PT_TOUCH = 0x00000002,
PT_PEN = 0x00000003,
PT_MOUSE = 0x00000004
}
public enum POINTER_FLAGS : uint
{
POINTER_FLAG_NONE = 0x00000000,
POINTER_FLAG_NEW = 0x00000001,
POINTER_FLAG_INRANGE = 0x00000002,
POINTER_FLAG_INCONTACT = 0x00000004,
POINTER_FLAG_FIRSTBUTTON = 0x00000010,
POINTER_FLAG_SECONDBUTTON = 0x00000020,
POINTER_FLAG_THIRDBUTTON = 0x00000040,
POINTER_FLAG_OTHERBUTTON = 0x00000080,
POINTER_FLAG_PRIMARY = 0x00000100,
POINTER_FLAG_CONFIDENCE = 0x00000200,
POINTER_FLAG_CANCELLED = 0x00000400,
POINTER_FLAG_DOWN = 0x00010000,
POINTER_FLAG_UPDATE = 0x00020000,
POINTER_FLAG_UP = 0x00040000,
POINTER_FLAG_WHEEL = 0x00080000,
POINTER_FLAG_HWHEEL = 0x00100000
}
public enum TOUCH_FEEDBACK : uint
{
TOUCH_FEEDBACK_DEFAULT = 0x1,
TOUCH_FEEDBACK_INDIRECT = 0x2,
TOUCH_FEEDBACK_NONE = 0x3
}
[DllImport("TouchInjectionDriver.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern bool InjectTouch(int x, int y, POINTER_INPUT_TYPE pt_input, int pressure, int orientation, int id, int rcContactTop, int rcContactBottom, int rcContactLeft, int rcContactRight, POINTER_FLAGS pointerFlags, TOUCH_MASK touchMask);
[DllImport("TouchInjectionDriver.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern void setTouchFeedback(TOUCH_FEEDBACK fb);
[DllImport("TouchInjectionDriver.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern void setDefaultRectSize(int size);
[DllImport("TouchInjectionDriver.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern void setDefaultPressure(int pres);
[DllImport("TouchInjectionDriver.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern void setDefaultOrientation(int or);
[DllImport("User32.dll")]
static extern Boolean MessageBeep(UInt32 beepType);
public static void mouseclick(int x, int y)
{
bool ret;
setTouchFeedback(TOUCH_FEEDBACK.TOUCH_FEEDBACK_INDIRECT);
ret = InjectTouch(x, y, POINTER_INPUT_TYPE.PT_TOUCH, 3200, 0, 0, x - 4, x + 4, y - 4, y + 4,POINTER_FLAGS.POINTER_FLAG_DOWN|POINTER_FLAGS.POINTER_FLAG_INCONTACT|POINTER_FLAGS.POINTER_FLAG_INRANGE,TOUCH_MASK.TOUCH_MASK_CONTACTAREA|TOUCH_MASK.TOUCH_MASK_ORIENTATION|TOUCH_MASK.TOUCH_MASK_PRESSURE);
if (ret)
{
ret = InjectTouch(x, y, POINTER_INPUT_TYPE.PT_TOUCH, 3200, 0, 0, x - 4, x + 4, y - 4, y + 4, POINTER_FLAGS.POINTER_FLAG_UP, TOUCH_MASK.TOUCH_MASK_CONTACTAREA | TOUCH_MASK.TOUCH_MASK_ORIENTATION | TOUCH_MASK.TOUCH_MASK_PRESSURE);
}
else
{
MessageBeep(0);
}
}

High CPU usage when getting color under cursor

I'm working on an app, moving the mouse in a certain area and clicking the mouse if something is not the color black.
However, I am getting a really high CPU usage while using this method too get the color below the cursor. After 5 completed runs from startY to endY - the application is lagging that much it takes around 5-10 sec. to get too the end of the area. With this part commented out, the application runs fine and each run doesn't increase in the too complete.
Here is my while loop:
private void moveMouse(int startX, int endX, int startY, int endY)
{
int newPosX = startX;
int newPosY = startY;
while (running)
{
Application.DoEvents();
//this.Cursor = new Cursor(Cursor.Current.Handle);
Cursor.Position = new Point(newPosX, newPosY);
Thread.Sleep(3);
if (colorCursor.Get(newPosX, newPosY))
{
MyMouse.sendClick();
countClicks++;
lblStatus.Text = "Klik: " + countClicks;
}
newPosX += 10;
if (newPosX > endX)
{
newPosY += 25;
newPosX = startX;
}
if (newPosY > endY)
{
newPosY = startY;
Thread.Sleep(1000);
}
}
}
Color below cursor:
public class ColorUnderCursor
{
[DllImport("gdi32")]
public static extern uint GetPixel(IntPtr hDC, int XPos, int YPos);
//[DllImport("user32.dll", CharSet = CharSet.Auto)]
//public static extern bool GetCursorPos(out POINT pt);
[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetWindowDC(IntPtr hWnd);
public bool Get(int x, int y)
{
IntPtr dc = GetWindowDC(IntPtr.Zero);
long color = GetPixel(dc, x, y);
Color underMouse = Color.FromArgb((int)color);
if(underMouse != Color.FromArgb(0, 0, 0, 0))
return true;
return false;
}
}
How I can minimize this heavy usage of the CPU.
Solution:
It was my method "Get" which was causing the problem. I solved it by this method below, and running the whole thing inside a backgroundworker.
public bool GetPixel(Point position)
{
using (var bitmap = new Bitmap(1, 1))
{
using (var graphics = Graphics.FromImage(bitmap))
{
graphics.CopyFromScreen(position, new Point(0, 0), new Size(1, 1));
}
if (bitmap.GetPixel(0, 0) != Color.FromArgb(255, 0, 0, 0) && bitmap.GetPixel(0, 0) != Color.FromArgb(255, 255, 255, 255))
return true;
return false;
}
}
Try to move logic into Invoke call like this
private void moveMouse(int startX, int endX, int startY, int endY)
{
this.BeginInvoke(new Action(() => { InvokeMouseMove(startX, endX, startY, endY)
}));
}
private void InvokeMouseMove(int startX, int endX, int startY, int endY)
{
int newPosX = startX;
int newPosY = startY;
while (running)
{
Application.DoEvents();
//this.Cursor = new Cursor(Cursor.Current.Handle);
Cursor.Position = new Point(newPosX, newPosY);
if (colorCursor.Get(newPosX, newPosY))
{
MyMouse.sendClick();
countClicks++;
lblStatus.Text = "Klik: " + countClicks;
}
newPosX += 10;
if (newPosX > endX)
{
newPosY += 25;
newPosX = startX;
}
if (newPosY > endY)
{
newPosY = startY;
}
}
}

Get image as Image Class with twain in c#

I can connect and get images from my device with twaindotnet. But I want to handle the images as Image class. When I try something like this:
...
ArrayList pics = tw.TransferPictures();
EndingScan();
tw.CloseSrc();
if(pics.Count > 0) {
IntPtr img = (IntPtr) pics[ 0 ];
PicForm newpic = new PicForm( img );
Image r = Image.FromHbitmap(img, this.Handle);
picturebox.Image = r;
}
...
I'm getting an error as "Error:Generic Error Occured in GDI+" on the line ,
Image r = Image.FromHbitmap(img, this.Handle);
So where am I wrong? How can I get as an Image the image?
I too found out that calling Image.FromHbitmap is not enough.
I had a look in the TwainDotNet library you mentioned and there I found the BitmapRenderer class.
Pulling out just the relevant bit it is easy enough to use that to create a simple static method that you can pass in the IntPtr you get from TWAIN (in your case your img variable) and convert it to a Bitmap. You, therefore, call it like so:
Image r = TwainBitmapConvertor.ToBitmap(img);
and here is the code (it only works on x86 and needs tidying but it does the job):
public static class TwainBitmapConvertor
{
[StructLayout(LayoutKind.Sequential, Pack = 2)]
private class BitmapInfoHeader
{
public int Size;
public int Width;
public int Height;
public short Planes;
public short BitCount;
public int Compression;
public int SizeImage;
public int XPelsPerMeter;
public int YPelsPerMeter;
public int ClrUsed;
public int ClrImportant;
}
[DllImport("gdi32.dll", ExactSpelling = true)]
private static extern int SetDIBitsToDevice(IntPtr hdc,
int xdst, int ydst, int width, int height, int xsrc,
int ysrc, int start, int lines, IntPtr bitsptr,
IntPtr bmiptr, int color);
[DllImport("kernel32.dll", ExactSpelling = true)]
private static extern IntPtr GlobalLock(IntPtr handle);
[DllImport("kernel32.dll", ExactSpelling = true)]
private static extern bool GlobalUnlock(IntPtr handle);
[DllImport("kernel32.dll", ExactSpelling = true)]
private static extern IntPtr GlobalFree(IntPtr handle);
public static Bitmap ToBitmap(IntPtr dibHandle)
{
var bitmapPointer = GlobalLock(dibHandle);
var bitmapInfo = new BitmapInfoHeader();
Marshal.PtrToStructure(bitmapPointer, bitmapInfo);
var rectangle = new Rectangle();
rectangle.X = rectangle.Y = 0;
rectangle.Width = bitmapInfo.Width;
rectangle.Height = bitmapInfo.Height;
if (bitmapInfo.SizeImage == 0)
{
bitmapInfo.SizeImage =
((((bitmapInfo.Width * bitmapInfo.BitCount) + 31) & ~31) >> 3)
* bitmapInfo.Height;
}
// The following code only works on x86
Debug.Assert(Marshal.SizeOf(typeof(IntPtr)) == 4);
int pixelInfoPointer = bitmapInfo.ClrUsed;
if ((pixelInfoPointer == 0) && (bitmapInfo.BitCount <= 8))
{
pixelInfoPointer = 1 << bitmapInfo.BitCount;
}
pixelInfoPointer = (pixelInfoPointer * 4) + bitmapInfo.Size
+ bitmapPointer.ToInt32();
IntPtr pixelInfoIntPointer = new IntPtr(pixelInfoPointer);
Bitmap bitmap = new Bitmap(rectangle.Width, rectangle.Height);
using (Graphics graphics = Graphics.FromImage(bitmap))
{
IntPtr hdc = graphics.GetHdc();
try
{
SetDIBitsToDevice(hdc,
0, 0, rectangle.Width, rectangle.Height, 0, 0, 0,
rectangle.Height, pixelInfoIntPointer, bitmapPointer, 0);
}
finally
{
graphics.ReleaseHdc(hdc);
}
}
bitmap.SetResolution(PpmToDpi(bitmapInfo.XPelsPerMeter),
PpmToDpi(bitmapInfo.YPelsPerMeter));
GlobalUnlock(dibHandle);
GlobalFree(dibHandle);
return bitmap;
}
private static float PpmToDpi(double pixelsPerMeter)
{
double pixelsPerMillimeter = (double)pixelsPerMeter / 1000.0;
double dotsPerInch = pixelsPerMillimeter * 25.4;
return (float)Math.Round(dotsPerInch, 2);
}
}
Assuming that tw.TransferPictures() returns an array of bitmap handles, then change Image r = ... to:
Image r = Image.FromHbitmap(img);
The second argument to FromHbitmap is a handle to a GDI palette, which I doubt you have.

Categories