I'm using c#, Visual Studio 2010 for a Windows application.
I want to hold down the Ctrl key, then release it after a while.
I tried this but it didnt work.
[DllImport("user32.dll")]
static extern bool keybd_event(byte bVk, byte bScan, uint dwFlags,
UIntPtr dwExtraInfo);
public const uint KEYEVENTF_KEYUP = 0x02;
public const uint VK_CONTROL = 0x11;
// Press the Control key.
keybd_event(VK_CONTROL,0,0,0);
//release the control key
keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
But I get this error
The best overloaded method match for 'ImageR.Form1.keybd_event(byte, byte, uint, System.UIntPtr)
cannot convert from 'uint' to 'byte'
cannot convert from 'int' to 'System.UIntPtr'
I didn't find any good examples of do SendInput, the examples at http://www.pinvoke.net/default.aspx/user32.keybd_event didn't work for me.
The best solution to solve this was at http://inputsimulator.codeplex.com/
Now it's this simple:
//Press Ctrl
InputSimulator.SimulateKeyDown(VirtualKeyCode.CONTROL);
//Release Ctrl
InputSimulator.SimulateKeyUp(VirtualKeyCode.CONTROL);
Related
I'm using the below code to modify system volume programmatically. I would be honest with you that I got the same code from the internet from a lot of sources.
//private const int APPCOMMAND_VOLUME_UP = 0xA0000;
private const int APPCOMMAND_VOLUME_UP = 0xAFFFF;
private const int APPCOMMAND_VOLUME_DOWN = 0x90000;
private const int WM_APPCOMMAND = 0x319;
[DllImport("user32.dll")]
public static extern IntPtr SendMessageW(IntPtr hWnd, int Msg,
IntPtr wParam, IntPtr lParam);
private void btnVolumeUp_Click(object sender, RoutedEventArgs e)
{
SendMessageW(new WindowInteropHelper(this).Handle, WM_APPCOMMAND, new WindowInteropHelper(this).Handle,
(IntPtr)APPCOMMAND_VOLUME_UP);
}
I've observed that the values of the two variables APPCOMMAND_VOLUME_UP and APPCOMMAND_VOLUME_DOWN don't really matter as long as the up value starts with 0xA and the down value starts with 0x9. I have tried with many different values between 0000 and FFFF for both UP and DOWN scenarios. Is it really true that the values don't matter?
I don't have much knowledge about the interop calls. Can someone please explain the significance of those values?
Thank you in advance!
There is no "value". The LPARAM argument encodes three distinct properties:
The command, for example APPCOMMAND_VOLUME_UP is 10 (0x0A).
The device, indicates how the command was generated and can be key, mouse or oem.
The "keys", indicates which modifiers were in effect when the command was generated. Like shift/ctrl for a keyboard and the clicked mouse button for a mouse
These three properties are encoded the way bitfields work in the C language. The bit pattern in hex is 0xDCCCKKKK where C is command, D is device, K is keys.
Since you synthesize the message yourself, you have no meaningful way to report the device or the keys. Nor does it matter, you should simply use 0 (device = keyboard, no modifier keys). Do note that the value you use now is not correct, 0xAFFFF does not use a correct keys value and you are saying that the CTRL and SHIFT keys are down. Probably not enough to terminally confuse the shell, these modifier keys don't affect the way that particular command works.
So a sane implementation would look like:
public enum AppCommand {
VolumeDown = 9
VolumeUp = 10,
// etc..
}
private void SendAppCommand(AppCommand cmd) {
var hwnd = new WindowInteropHelper(this).Handle;
SendMessageW(hwnd, WM_APPCOMMAND, hwnd, (int)cmd << 16);
}
The erros seems pretty common, but here it is:
eCA1901 P/Invoke declarations should be portable As it is declared in your code, parameter 'dwExtraInfo' of P/Invoke 'NativeMethods.mouse_event(int, int, int, int, int)' will be 4 bytes wide on 64-bit platforms. This is not correct, as the actual native declaration of this API indicates it should be 8 bytes wide on 64-bit platforms. Consult the MSDN Platform SDK documentation for help determining what data type should be used instead of 'int'
Here is the line of code:
[System.Runtime.InteropServices.DllImport("user32.dll")]
internal static extern void mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);
Now i have tried changin to Uint or soemthing that is compatible with 64bit, or that can be used on both (Pint or something, can´t remember the name).
But if i change from Int to Uint or whatever, it breaks this code:
if (click == "Left")
{
NativeMethods.mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, MousePosition.X, MousePosition.Y, MousePosition.X, MousePosition.Y);
}
if (click == "Right")
{
NativeMethods.mouse_event(MOUSEEVENTF_RIGHTDOWN | MOUSEEVENTF_RIGHTUP, MousePosition.X, MousePosition.Y, MousePosition.X, MousePosition.Y);
}
if (down == "Left"+"True")
{
NativeMethods.mouse_event(MOUSEEVENTF_LEFTDOWN , MousePosition.X, MousePosition.Y, MousePosition.X, MousePosition.Y);
}
if (down == "Right"+"True")
{
NativeMethods.mouse_event(MOUSEEVENTF_RIGHTDOWN, MousePosition.X, MousePosition.Y, MousePosition.X, MousePosition.Y);
}
As it says (can´t convert from int...)
It seems to "work" if i use (uint) on everything there, but i don´t think that´s a very optimal way to do it.
here are the MouseEvent codes:
private const int MOUSEEVENTF_LEFTDOWN = 0x02;
private const int MOUSEEVENTF_LEFTUP = 0x04;
private const int MOUSEEVENTF_RIGHTDOWN = 0x08;
private const int MOUSEEVENTF_RIGHTUP = 0x10;
Also tried changing them to Uint.
Now why i am going on about Uint is because i read that i should change it to that.
I have no real clue what Uint is compared to Int.
So if there is a better way, or i am doing it wrong, please tell.
Original declaration:
VOID WINAPI mouse_event(
_In_ DWORD dwFlags,
_In_ DWORD dx,
_In_ DWORD dy,
_In_ DWORD dwData,
_In_ ULONG_PTR dwExtraInfo
);
Correct C# declaration (one of possible options):
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern void mouse_event(
int dwFlags, int dx, int dy, int dwData, IntPtr dwExtraInfo);
Why last parameter is declared as IntPtr:
Because it is a pointer type in original declaration and it will be 8 bytes in case of 64-bit process. IntPtr is 4 bytes for 32-bit process and 8 bytes for 64-bit processes, which means if you want to compile your assembly as AnyCPU or x64 your mouse_event code stays the same.
If you don't want to cast last parameter to (IntPtr) every time you use mouse_event, you can provide an overload which does that:
static void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo)
{
mouse_event(dwFlags, dx, dy, dwData, (IntPtr)dwExtraInfo);
}
Also, I don't think you are providing valid values for dwData & dwExtraInfo parameters. Make sure that you follow documentation: MSDN
Is there some way that I can send multimedia control commands like next song, pause, play, vol up, etc. to the operating system?
Commands that are sent when pressing Fn + some mapped ..key.
I am making a remote control for PC and sending those commands is essential.
You can use keybd_event to simulate keys presses, you have to simulate key down and then key up in order to recognize correctly
[DllImport("user32.dll", SetLastError = true)]
public static extern void keybd_event(byte virtualKey, byte scanCode, uint flags, IntPtr extraInfo);
public const int VK_MEDIA_NEXT_TRACK = 0xB0;
public const int VK_MEDIA_PLAY_PAUSE = 0xB3;
public const int VK_MEDIA_PREV_TRACK = 0xB1;
public const int KEYEVENTF_EXTENDEDKEY = 0x0001; //Key down flag
public const int KEYEVENTF_KEYUP = 0x0002; //Key up flag
private void ButtonClick(object sender, EventArgs e)
keybd_event(VK_MEDIA_PREV_TRACK, 0, KEYEVENTF_EXTENDEDKEY, IntPtr.Zero);
keybd_event(VK_MEDIA_PREV_TRACK, 0, KEYEVENTF_KEYUP, IntPtr.Zero);
}`
Actually, the answer of dxramax gives me erratic behavior. I'm posting this answer that gives me consistent behavior, and also has some more details.
To send multimedia keys, including Play/Pause, NextTrack, PrevTrack, etc, you can use keybd_event:
public class Program
{
public const int KEYEVENTF_EXTENTEDKEY = 1;
public const int KEYEVENTF_KEYUP = 0;
public const int VK_MEDIA_NEXT_TRACK = 0xB0;
public const int VK_MEDIA_PLAY_PAUSE = 0xB3;
public const int VK_MEDIA_PREV_TRACK = 0xB1;
[DllImport("user32.dll")]
public static extern void keybd_event(byte virtualKey, byte scanCode, uint flags, IntPtr extraInfo);
public static void Main(string[] args)
{
keybd_event(VK_MEDIA_PLAY_PAUSE, 0, KEYEVENTF_EXTENTEDKEY, IntPtr.Zero); // Play/Pause
//keybd_event(VK_MEDIA_PREV_TRACK, 0, KEYEVENTF_EXTENTEDKEY, IntPtr.Zero); // PrevTrack
//keybd_event(VK_MEDIA_NEXT_TRACK, 0, KEYEVENTF_EXTENTEDKEY, IntPtr.Zero); // NextTrack
}
Here is a list to the supported key codes that this windows api can handle:
https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
The SendKeys class is very nice, but it's also limited. The approach above sends the key command directly to Windows OS.
Unfortunately, in most cases, keys Fn can't be sent using Windows API and as a result - using .NET classes. It depends on how the manufacturer has done this functionality. Probably it is supported by additional driver or even go over operation system.
You can check if it's possible to send Fn commands from the code by trying to hook them using Windows API code or some application like AutoHotKey. For instance, on my laptop, I can't hook multimedia commands.
Otherwise, if you are lucky, use SendKeys as mentioned in the comments.
If anyone wonders on this page like me. All posts above do not work, you also need bScan which is second parameter, you can get it with MapVirutalKey(VKCode,0).
Ex:
int keyValue = VK_MEDIA_NEXT_TRACK;
keybd_event(keyValue, MapVirtualKey(keyValue, 0), KEYEVENTF_KEYUP, 0);
keybd_event(keyValue, MapVirtualKey(keyValue, 0), KEYEVENTF_KEYUP, 0);
I am trying to perform a mouse click through c#. I used the mouse_event function to do it.
private const int MOUSEEVENTF_LEFTDOWN = 0x02;
private const int MOUSEEVENTF_LEFTUP = 0x04;
[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);
I tried two methods :
Moving the mouse to the point and clicking it :
Cursor.Position = new Point(100, 100);
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, Cursor.Position.X, Cursor.Position.Y, 0, 0);
Passing the x, y of the desired click to the function :
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP,100, 100, 0, 0);
Either way, I'm this weird error :
Managed Debugging Assistant 'PInvokeStackImbalance' has detected a problem in 'C:\Users\or\Documents\Visual Studio 2010\Projects\ProjectName\ProjectName\bin\Debug\ProjectName.vshost.exe'.
Additional Information: A call to PInvoke function 'ProjectName!ProjectName.MainForm::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.
Any ideas on a solution?
I would suggest you use the following p/invoke signature
private const uint MOUSEEVENTF_LEFTDOWN = 0x02;
private const uint MOUSEEVENTF_LEFTUP = 0x04;
[DllImport("user32.dll")]
public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, IntPtr dwExtraInfo);
Note, that while mouse_event is convenient, it has been superseded by SendInput. You can find a reasonable p/invoke declaration for SendInput and the Input structure at the following URL.
http://www.pinvoke.net/default.aspx/user32.SendInput
You have obviously got this code from legacy VB6 code. long is 64-bit in .NET and C#, unlike VB6 where it is 32-bit.
Switch from long to int, and it should be okay.
edit: I was a little fast: dwExtraInfo should be of type IntPtr.
How could I programmatically trigger a left-click event on the mouse?
Thanks.
edit: the event is not triggered directly on a button. I'm aiming for the Windows platform.
To perform a mouse click:
[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 int MOUSEEVENTF_LEFTDOWN = 0x02;
private const int MOUSEEVENTF_LEFTUP = 0x04;
private const int MOUSEEVENTF_RIGHTDOWN = 0x08;
private const int MOUSEEVENTF_RIGHTUP = 0x10;
public static void DoMouseClick()
{
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
}
To move the cursor where you want:
[DllImport("user32.dll")]
static extern bool SetCursorPos(int X, int Y);
public static void MoveCursorToPoint(int x, int y)
{
SetCursorPos(x, y);
}
If it's right on a button, you can use
button1.PerformClick();
Otherwise, you can check out this MSDN article which discusses simulating mouse (and keyboard) input.
Additionally, this project may be able to help you out as well. Under the covers, it uses SendInput.
https://web.archive.org/web/20140214230712/http://www.pinvoke.net/default.aspx/user32.sendinput
Use the Win32 API to send input.
Update:
Since I no longer work with Win32 API, I will not update this answer to be correct when the platform changes or websites become unavailable. Since this answer doesn't even conform to Stackoverflow standards (does not contain the answer itself, but rather a link to an external, now defunct resource), there's no point giving it any points or spending any more time on it.
Instead, take a look at this question on Stackoverflow, which I think is a duplicate:
How to simulate Mouse Click in C#?