How to simulate a shift press in C# code? - c#

I'm using thiis code to simulate key presses or key ups:
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo);
const uint KEYEVENTF_KEYUP = 0x0002;
const uint KEYEVENTF_EXTENDEDKEY = 0x0001;
// Key up
keybd_event((byte)Convert.ToInt32("A0"), 0, KEYEVENTF_KEYUP | 0, 0);
// Key down
keybd_event((byte)Convert.ToInt32("A0"), 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
According to this table, left-shift has the keycode A0.
For some reason the code above isn't working. Does anyone know why? Thanks a lot for the help! :)

If using keycode is not necessary then you can use Keys.LShiftKey from KEY enumeration of System.Windows.Forms Namespace.
Further using
keybd_event((byte)0xA0, 0x45, KEYEVENTF_KEYUP | 0, 0);
is not a bad idea.

I would use here for keys.
keybd_event(160, 0, KEYEVENTF_EXTENDEDKEY | 0, 0);

Related

How to make C# console application to always be in front?

How can I ensure my C# console application is always in front?
e.i. if a person clicks away from the console, how can I detect that the console has lost the focus an bring it back to front?
I have this C# console application that is waiting for users to scan bar codes, if for some reason someone clicks away from the console window then the barcode data will be "lost".
I took a look at this code posted on another thread;however, I can not seem to get this to work for me:
bring a console window to front in c#
This code thanks to #ILan keeps the console ontop of all windows, but it does not set the "focus" to keep capturing the incoming data.
class Program
{
[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hWnd,
IntPtr hWndInsertAfter,
int X,
int Y,
int cx,
int cy,
uint uFlags);
static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
const uint SWP_NOSIZE = 0x0001, SWP_NOMOVE = 0x0002, SWP_SHOWWINDOW = 0x0040;
[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();
static void Main()
{
IntPtr handle = GetConsoleWindow();
SetWindowPos(handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
Console.WriteLine($"Hello handle: {handle}");
Console.ReadLine();
}
}
The following will do the job if the application is the one that attached to the console.
For a complete answer how to get the handle in case that your application is not the one that attached to the console, see https://stackoverflow.com/a/28616832/2370138.
class Program
{
[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hWnd,
IntPtr hWndInsertAfter,
int X,
int Y,
int cx,
int cy,
uint uFlags);
static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
const uint SWP_NOSIZE = 0x0001, SWP_NOMOVE = 0x0002, SWP_SHOWWINDOW = 0x0040;
[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();
static void Main()
{
IntPtr handle = GetConsoleWindow();
SetWindowPos(handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
Console.WriteLine($"Hello handle: {handle}");
Console.ReadLine();
}
}
SetForegroundWindow has been limited since then (see Remarks in https://learn.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setforegroundwindow). It will not allow you to arbitrarily put windows in the foreground anymore, exactly to prevent you from doing what you're trying to do.
If you need other applications running on the system, you're out of luck. You'll just need to tell your users they need to have the window focused when scanning a barcode.

How to use Post/SendMessage (User32.dll) to make Alt+Space combitation/event

I need to make Post/SendMessage that will make Alt+Space that will open some tab that i need in windows aplication.I can't use SendKeys SendKeys.Send("% ") i have to use Post/SendMessage only.
This what i have tried so far
private const uint WM_KEYDOWN = 0x0100;
private const uint WM_KEYUP = 0x0101;
private const uint WM_SYSKEYDOWN = 0x0104;
private const uint WM_SYSKEYUP = 0x0105;
private const int VK_MENU = 0x12;
private const int VK_SPACE = 0x20;
PostMessage(Main, WM_SYSKEYDOWN, VK_MENU, 0);//
PostMessage(Main, WM_KEYDOWN, VK_SPACE, 0);
Thread.Sleep(1000);
PostMessage(Main, WM_KEYUP, VK_SPACE, 0);
PostMessage(Main, WM_SYSKEYUP, VK_MENU, 0);
Now i can see that Alt is pressed because tabs get under-lined(first letter)(it's happened in 99% winapp's),but the combination of Alt+Space not happened,and i don't know why.
Any one know what i am doing wrong?

SendKey.Send() Not working

I'm using WPF and I imported the System.Windows.Form reference. Here's my code:
Process[] process = Process.GetProcessesByName("wmplayer");
SetForegroundWindow(process[0].MainWindowHandle);
Thread.Sleep(200);
System.Windows.Forms.SendKeys.Send("^p");
The Windows Media Player do Focus, but no keystroke is Received. Why?
You can use WinAPI instead of SendKeys:
[DllImport("user32.dll", SetLastError = true)]
static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo);
public static void PressKey(Keys key, bool up) {
const int KEYEVENTF_EXTENDEDKEY = 0x1;
const int KEYEVENTF_KEYUP = 0x2;
if (up) {
keybd_event((byte) key, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, (UIntPtr) 0);
}
else {
keybd_event((byte) key, 0x45, KEYEVENTF_EXTENDEDKEY, (UIntPtr) 0);
}
}
void TestProc() {
PressKey(Keys.ControlKey, false);
PressKey(Keys.P, false);
PressKey(Keys.P, true);
PressKey(Keys.ControlKey, true);
}
In WPF applications you have to use SendKeys.SendWait() (English Documentation) instead.
Just doublechecked it, while Send() is working for WinForms application, WPF throws an InvalidOperationException although both target .net 4.0.
Check above link for more information.

C# -- PInvokeStackImbalance detected on a well documented function?

Here is my code for a ClickMouse() function:
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);
private const long MOUSEEVENTF_LEFTDOWN = 0x02;
private const long MOUSEEVENTF_LEFTUP = 0x04;
private const long MOUSEEVENTF_RIGHTDOWN = 0x08;
private const long MOUSEEVENTF_RIGHTUP = 0x10;
private void ClickMouse()
{
long X = Cursor.Position.X;
long Y = Cursor.Position.Y;
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, X, Y, 0, 0);
}
For some reason, when my program comes to this code, it throws this error message:
PInvokeStackImbalance was detected Message: A call to PInvoke function
'WindowsFormsApplication1!WindowsFormsApplication1.Form1::mouse_event'
has unbalanced the stack. This is likely because the managed PInvoke
signature does not match the unmanaged target signature. Check that
the calling convention and parameters of the PInvoke signature match
the target unmanaged signature.
Please help?
Looks like your DllImport declaration is wrong. In particular the use of Int64 (longs), instead of UInt32.
Here's some detail from the PInvoke reference:
http://www.pinvoke.net/default.aspx/user32.mouse_event
[DllImport("user32.dll")]
static extern void mouse_event(uint dwFlags, uint dx, uint dy,
uint dwData,UIntPtr dwExtraInfo);
I found this declaration
[DllImport("user32.dll")]
static extern void mouse_event(uint dwFlags,
uint dx,
uint dy,
uint dwData,
IntPtr dwExtraInfo);
I was using RealGetWindowClass using the following format.
[DllImport("User32", CallingConvention=CallingConvention.Cdecl)]
public static extern int RealGetWindowClass(IntPtr hwnd, StringBuilder pszType, int cchType);
and i was geting the 'PInvokeStackImbalance' exception/error. But when i changed the CallingConvention to
[DllImport("User32", CallingConvention=CallingConvention.StdCall)]
the error went away. I am using VS2010 on a 64 bit machine.
To fix PInvokeStackImbalance error:
Press: CTRL + ALT + E
Under "Managed Debugging Assistants" uncheck PInvokeStackImbalance
I changed "Cdecl" to "StdCall" but it didn't work.
As Scott Weinstein mentioned we should use int type.
[DllImport("user32.dll")]
static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
[Flags]
public enum MouseEventFlags
{
LEFTDOWN = 0x00000002,
LEFTUP = 0x00000004,
MIDDLEDOWN = 0x00000020,
MIDDLEUP = 0x00000040,
MOVE = 0x00000001,
ABSOLUTE = 0x00008000,
RIGHTDOWN = 0x00000008,
RIGHTUP = 0x00000010
}
public static void LeftClick(int x, int y)
{
Cursor.Position = new System.Drawing.Point(x, y);
mouse_event((int)(MouseEventFlags.LEFTDOWN), 0, 0, 0, 0);
mouse_event((int)(MouseEventFlags.LEFTUP), 0, 0, 0, 0);
}

Make a window topmost using a window handle

After launching an application using the Process class I'd like to make that window topmost. Currently, my app is the topmost window so when i launch the other app it doesn't display. One thing that came to mind is that I could set topmost = false for my application before launching the process, the problem with this is I want to give the process ample time to load up before displaying it to the user, so I'd like more control over when I switch the other application to the topmost.
You need to use P/Invoke with SetWindowPos to accopmlish this:
[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
const UInt32 SWP_NOSIZE = 0x0001;
const UInt32 SWP_NOMOVE = 0x0002;
const UInt32 SWP_SHOWWINDOW = 0x0040;
// Call this way:
SetWindowPos(theWindowHandle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);

Categories

Resources