I have an application with a WebBrowser Control.
I load a page to it with a button click.
Then I want to run a "Convert to Adobe PDF" action from the context menu of the web browser but... when I try to access the context menu by:
foreach (MenuItem vMenuItem in WebBrowser.ContextMenu.MenuItems)
{
if (vMenuItem.Text.Contains("onwert") && vMenuItem.Text.Contains("PDF"))
{
vMenuItem.PerformClick();
}
}
The IDE displays an error "Object reference not set to an instance of an object" on line with
foreach (MenuItem vMenuItem in WebBrowser.ContextMenu.MenuItems)
I didn't create my own context menu, I want the default context menu to show.
How can I access the WebBrowser's context menu and perform that action?
i'm having a similar problem to you. I have made a reference to your problem in my post here.
If you are still interested in this problem this is working solution that makes use of simulating clicks:
//Example of how to use the code:
Point controlLoc = this.PointToScreen(webbrowser1.Location);
controlLoc.X = controlLoc.X + webbrowser1.Document.GetElementById("sbvdcapimg").OffsetRectangle.Left+65;
controlLoc.Y = controlLoc.Y + webbrowser1.Document.GetElementById("sbvdcapimg").OffsetRectangle.Top+50;
Cursor.Position = controlLoc;
MouseSimulator.ClickRightMouseButton();
controlLoc.X = controlLoc.X + (webbrowser1.Document.GetElementById("sbvdcapimg").OffsetRectangle.Left + 95);
controlLoc.Y = controlLoc.Y + (webbrowser1.Document.GetElementById("sbvdcapimg").OffsetRectangle.Top + 45);
Cursor.Position = controlLoc;
MouseSimulator.ClickLeftMouseButton();
public class MouseSimulator
{
[DllImport("user32.dll", SetLastError = true)]
static extern uint SendInput(uint nInputs, ref INPUT pInputs, int cbSize);
[StructLayout(LayoutKind.Sequential)]
struct INPUT
{
public SendInputEventType type;
public MouseKeybdhardwareInputUnion mkhi;
}
[StructLayout(LayoutKind.Explicit)]
struct MouseKeybdhardwareInputUnion
{
[FieldOffset(0)]
public MouseInputData mi;
[FieldOffset(0)]
public KEYBDINPUT ki;
[FieldOffset(0)]
public HARDWAREINPUT hi;
}
[StructLayout(LayoutKind.Sequential)]
struct KEYBDINPUT
{
public ushort wVk;
public ushort wScan;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct HARDWAREINPUT
{
public int uMsg;
public short wParamL;
public short wParamH;
}
struct MouseInputData
{
public int dx;
public int dy;
public uint mouseData;
public MouseEventFlags dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[Flags]
enum MouseEventFlags : uint
{
MOUSEEVENTF_MOVE = 0x0001,
MOUSEEVENTF_LEFTDOWN = 0x0002,
MOUSEEVENTF_LEFTUP = 0x0004,
MOUSEEVENTF_RIGHTDOWN = 0x0008,
MOUSEEVENTF_RIGHTUP = 0x0010,
MOUSEEVENTF_MIDDLEDOWN = 0x0020,
MOUSEEVENTF_MIDDLEUP = 0x0040,
MOUSEEVENTF_XDOWN = 0x0080,
MOUSEEVENTF_XUP = 0x0100,
MOUSEEVENTF_WHEEL = 0x0800,
MOUSEEVENTF_VIRTUALDESK = 0x4000,
MOUSEEVENTF_ABSOLUTE = 0x8000
}
enum SendInputEventType : int
{
InputMouse,
InputKeyboard,
InputHardware
}
public static void ClickRightMouseButton()
{
INPUT mouseDownInput = new INPUT();
mouseDownInput.type = SendInputEventType.InputMouse;
mouseDownInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_RIGHTDOWN;
SendInput(1, ref mouseDownInput, Marshal.SizeOf(new INPUT()));
INPUT mouseUpInput = new INPUT();
mouseUpInput.type = SendInputEventType.InputMouse;
mouseUpInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_RIGHTUP;
SendInput(1, ref mouseUpInput, Marshal.SizeOf(new INPUT()));
}
public static void ClickLeftMouseButton()
{
INPUT mouseDownInput = new INPUT();
mouseDownInput.type = SendInputEventType.InputMouse;
mouseDownInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_LEFTDOWN;
SendInput(1, ref mouseDownInput, Marshal.SizeOf(new INPUT()));
INPUT mouseUpInput = new INPUT();
mouseUpInput.type = SendInputEventType.InputMouse;
mouseUpInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_LEFTUP;
SendInput(1, ref mouseUpInput, Marshal.SizeOf(new INPUT()));
}
Related
I'm looking for a way to rotate the display of one of my monitors programmatically.
I have two monitors set up on a desk mount, and I often use them in varying orientations when programming or using various other programs, and in order to change the orientation I jump into display settings and rotate it that way (so i can have one or both in portrait).
Call me lazy as i know thats hardly any hassle to do, but it would be nice to just have a quick little executable on my taskbar that i can run to instantly rotate one of the screens back and forth when i need to.
I've looked into it and found various explanations using DEVMODE structs etc, and it all seems like a really long winded process, is there really not an easier way to do this? Not a windows dll that has this functionailty already?
Thanks in advance.
it's not that hard to achieve this using the mentioned DEVMODE struct and native calls.
I've written a little wrapper that does this:
using System;
using System.Runtime.InteropServices;
public class Display
{
public enum Orientations
{
DEGREES_CW_0 = 0,
DEGREES_CW_90 = 3,
DEGREES_CW_180 = 2,
DEGREES_CW_270 = 1
}
public static bool Rotate(uint DisplayNumber, Orientations Orientation)
{
if(DisplayNumber == 0)
throw new ArgumentOutOfRangeException("DisplayNumber", DisplayNumber, "First display is 1.");
bool result = false;
DISPLAY_DEVICE d = new DISPLAY_DEVICE();
d.cb = Marshal.SizeOf(d);
DEVMODE dm = new DEVMODE();
if(!NativeMethods.EnumDisplayDevices(null, DisplayNumber-1, ref d, 0))
throw new ArgumentOutOfRangeException("DisplayNumber", DisplayNumber, "Number is greater than connected displays.");
if (0 != NativeMethods.EnumDisplaySettings(
d.DeviceName, NativeMethods.ENUM_CURRENT_SETTINGS, ref dm))
{
if ((dm.dmDisplayOrientation + (int)Orientation) % 2 == 1) // Need to swap height and width?
{
int temp = dm.dmPelsHeight;
dm.dmPelsHeight = dm.dmPelsWidth;
dm.dmPelsWidth = temp;
}
switch (Orientation)
{
case Orientations.DEGREES_CW_90:
dm.dmDisplayOrientation = NativeMethods.DMDO_270;
break;
case Orientations.DEGREES_CW_180:
dm.dmDisplayOrientation = NativeMethods.DMDO_180;
break;
case Orientations.DEGREES_CW_270:
dm.dmDisplayOrientation = NativeMethods.DMDO_90;
break;
case Orientations.DEGREES_CW_0:
dm.dmDisplayOrientation = NativeMethods.DMDO_DEFAULT;
break;
default:
break;
}
DISP_CHANGE ret = NativeMethods.ChangeDisplaySettingsEx(
d.DeviceName, ref dm, IntPtr.Zero,
DisplaySettingsFlags.CDS_UPDATEREGISTRY, IntPtr.Zero);
result = ret == 0;
}
return result;
}
public static void ResetAllRotations()
{
try
{
uint i = 0;
while (++i <= 64)
{
Rotate(i, Orientations.DEGREES_CW_0);
}
}
catch(ArgumentOutOfRangeException ex)
{
// Everything is fine, just reached the last display
}
}
}
internal class NativeMethods
{
[DllImport("user32.dll")]
internal static extern DISP_CHANGE ChangeDisplaySettingsEx(
string lpszDeviceName, ref DEVMODE lpDevMode, IntPtr hwnd,
DisplaySettingsFlags dwflags, IntPtr lParam);
[DllImport("user32.dll")]
internal static extern bool EnumDisplayDevices(
string lpDevice, uint iDevNum, ref DISPLAY_DEVICE lpDisplayDevice,
uint dwFlags);
[DllImport("user32.dll", CharSet = CharSet.Ansi)]
internal static extern int EnumDisplaySettings(
string lpszDeviceName, int iModeNum, ref DEVMODE lpDevMode);
public const int DMDO_DEFAULT = 0;
public const int DMDO_90 = 1;
public const int DMDO_180 = 2;
public const int DMDO_270 = 3;
public const int ENUM_CURRENT_SETTINGS = -1;
}
// See: https://msdn.microsoft.com/en-us/library/windows/desktop/dd183565(v=vs.85).aspx
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
internal struct DEVMODE
{
public const int CCHDEVICENAME = 32;
public const int CCHFORMNAME = 32;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
[System.Runtime.InteropServices.FieldOffset(0)]
public string dmDeviceName;
[System.Runtime.InteropServices.FieldOffset(32)]
public Int16 dmSpecVersion;
[System.Runtime.InteropServices.FieldOffset(34)]
public Int16 dmDriverVersion;
[System.Runtime.InteropServices.FieldOffset(36)]
public Int16 dmSize;
[System.Runtime.InteropServices.FieldOffset(38)]
public Int16 dmDriverExtra;
[System.Runtime.InteropServices.FieldOffset(40)]
public DM dmFields;
[System.Runtime.InteropServices.FieldOffset(44)]
Int16 dmOrientation;
[System.Runtime.InteropServices.FieldOffset(46)]
Int16 dmPaperSize;
[System.Runtime.InteropServices.FieldOffset(48)]
Int16 dmPaperLength;
[System.Runtime.InteropServices.FieldOffset(50)]
Int16 dmPaperWidth;
[System.Runtime.InteropServices.FieldOffset(52)]
Int16 dmScale;
[System.Runtime.InteropServices.FieldOffset(54)]
Int16 dmCopies;
[System.Runtime.InteropServices.FieldOffset(56)]
Int16 dmDefaultSource;
[System.Runtime.InteropServices.FieldOffset(58)]
Int16 dmPrintQuality;
[System.Runtime.InteropServices.FieldOffset(44)]
public POINTL dmPosition;
[System.Runtime.InteropServices.FieldOffset(52)]
public Int32 dmDisplayOrientation;
[System.Runtime.InteropServices.FieldOffset(56)]
public Int32 dmDisplayFixedOutput;
[System.Runtime.InteropServices.FieldOffset(60)]
public short dmColor;
[System.Runtime.InteropServices.FieldOffset(62)]
public short dmDuplex;
[System.Runtime.InteropServices.FieldOffset(64)]
public short dmYResolution;
[System.Runtime.InteropServices.FieldOffset(66)]
public short dmTTOption;
[System.Runtime.InteropServices.FieldOffset(68)]
public short dmCollate;
[System.Runtime.InteropServices.FieldOffset(72)]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHFORMNAME)]
public string dmFormName;
[System.Runtime.InteropServices.FieldOffset(102)]
public Int16 dmLogPixels;
[System.Runtime.InteropServices.FieldOffset(104)]
public Int32 dmBitsPerPel;
[System.Runtime.InteropServices.FieldOffset(108)]
public Int32 dmPelsWidth;
[System.Runtime.InteropServices.FieldOffset(112)]
public Int32 dmPelsHeight;
[System.Runtime.InteropServices.FieldOffset(116)]
public Int32 dmDisplayFlags;
[System.Runtime.InteropServices.FieldOffset(116)]
public Int32 dmNup;
[System.Runtime.InteropServices.FieldOffset(120)]
public Int32 dmDisplayFrequency;
}
// See: https://msdn.microsoft.com/en-us/library/windows/desktop/dd183569(v=vs.85).aspx
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
internal struct DISPLAY_DEVICE
{
[MarshalAs(UnmanagedType.U4)]
public int cb;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string DeviceName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceString;
[MarshalAs(UnmanagedType.U4)]
public DisplayDeviceStateFlags StateFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceKey;
}
// See: https://msdn.microsoft.com/de-de/library/windows/desktop/dd162807(v=vs.85).aspx
[StructLayout(LayoutKind.Sequential)]
internal struct POINTL
{
long x;
long y;
}
internal enum DISP_CHANGE : int
{
Successful = 0,
Restart = 1,
Failed = -1,
BadMode = -2,
NotUpdated = -3,
BadFlags = -4,
BadParam = -5,
BadDualView = -6
}
// http://www.pinvoke.net/default.aspx/Enums/DisplayDeviceStateFlags.html
[Flags()]
internal enum DisplayDeviceStateFlags : int
{
/// <summary>The device is part of the desktop.</summary>
AttachedToDesktop = 0x1,
MultiDriver = 0x2,
/// <summary>The device is part of the desktop.</summary>
PrimaryDevice = 0x4,
/// <summary>Represents a pseudo device used to mirror application drawing for remoting or other purposes.</summary>
MirroringDriver = 0x8,
/// <summary>The device is VGA compatible.</summary>
VGACompatible = 0x10,
/// <summary>The device is removable; it cannot be the primary display.</summary>
Removable = 0x20,
/// <summary>The device has more display modes than its output devices support.</summary>
ModesPruned = 0x8000000,
Remote = 0x4000000,
Disconnect = 0x2000000
}
// http://www.pinvoke.net/default.aspx/user32/ChangeDisplaySettingsFlags.html
[Flags()]
internal enum DisplaySettingsFlags : int
{
CDS_NONE = 0,
CDS_UPDATEREGISTRY = 0x00000001,
CDS_TEST = 0x00000002,
CDS_FULLSCREEN = 0x00000004,
CDS_GLOBAL = 0x00000008,
CDS_SET_PRIMARY = 0x00000010,
CDS_VIDEOPARAMETERS = 0x00000020,
CDS_ENABLE_UNSAFE_MODES = 0x00000100,
CDS_DISABLE_UNSAFE_MODES= 0x00000200,
CDS_RESET = 0x40000000,
CDS_RESET_EX = 0x20000000,
CDS_NORESET = 0x10000000
}
[Flags()]
internal enum DM : int
{
Orientation = 0x00000001,
PaperSize = 0x00000002,
PaperLength = 0x00000004,
PaperWidth = 0x00000008,
Scale = 0x00000010,
Position = 0x00000020,
NUP = 0x00000040,
DisplayOrientation = 0x00000080,
Copies = 0x00000100,
DefaultSource = 0x00000200,
PrintQuality = 0x00000400,
Color = 0x00000800,
Duplex = 0x00001000,
YResolution = 0x00002000,
TTOption = 0x00004000,
Collate = 0x00008000,
FormName = 0x00010000,
LogPixels = 0x00020000,
BitsPerPixel = 0x00040000,
PelsWidth = 0x00080000,
PelsHeight = 0x00100000,
DisplayFlags = 0x00200000,
DisplayFrequency = 0x00400000,
ICMMethod = 0x00800000,
ICMIntent = 0x01000000,
MediaType = 0x02000000,
DitherType = 0x04000000,
PanningWidth = 0x08000000,
PanningHeight = 0x10000000,
DisplayFixedOutput = 0x20000000
}
You can simply invoke the static Rotate-Function with the display number you want to rotate (Monitor 1=1, Monitor 2=2, etc.) and the degree you need.
Like this:
Display.Rotate(1, Display.Orientations.DEGREES_CW_180);
There is also a little short-hand function ResetAllRotations() to reset all displays.
Regards
I'm writing a helper for injecting touch in UI-tests using InjectTouchInput.
The injected touch works fine but injecting mouse input after touch does not work.
Mouse.Click(point); // works
Touch.Tap(point); // works
Mouse.Click(point); // does not work, mouse cursor no longer visible on screen.
Calling GetCursorInfo() reveals that cursor is CURSOR_SUPPRESSED and I have not found a way to restore it.
Moving the physical mouse brings back the cursor and clicking things work fine.
How can I restore things so that mouse works again here?
Use the API SendInput to Simulated mouse input.
PInvoke to SendInput – this is the official way to simulate input. It
pushes the input through all of the expected code paths, and is
indistinguishable from real input.
Here is the code sample:
public class MouseSimulator
{
[DllImport("user32.dll", SetLastError = true)]
static extern uint SendInput(uint nInputs, ref INPUT pInputs, int cbSize);
[StructLayout(LayoutKind.Sequential)]
struct INPUT
{
public SendInputEventType type;
public MouseKeybdhardwareInputUnion mkhi;
}
[StructLayout(LayoutKind.Explicit)]
struct MouseKeybdhardwareInputUnion
{
[FieldOffset(0)]
public MouseInputData mi;
[FieldOffset(0)]
public KEYBDINPUT ki;
[FieldOffset(0)]
public HARDWAREINPUT hi;
}
[StructLayout(LayoutKind.Sequential)]
struct KEYBDINPUT
{
public ushort wVk;
public ushort wScan;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct HARDWAREINPUT
{
public int uMsg;
public short wParamL;
public short wParamH;
}
struct MouseInputData
{
public int dx;
public int dy;
public uint mouseData;
public MouseEventFlags dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[Flags]
enum MouseEventFlags : uint
{
MOUSEEVENTF_MOVE = 0x0001,
MOUSEEVENTF_LEFTDOWN = 0x0002,
MOUSEEVENTF_LEFTUP = 0x0004,
MOUSEEVENTF_RIGHTDOWN = 0x0008,
MOUSEEVENTF_RIGHTUP = 0x0010,
MOUSEEVENTF_MIDDLEDOWN = 0x0020,
MOUSEEVENTF_MIDDLEUP = 0x0040,
MOUSEEVENTF_XDOWN = 0x0080,
MOUSEEVENTF_XUP = 0x0100,
MOUSEEVENTF_WHEEL = 0x0800,
MOUSEEVENTF_VIRTUALDESK = 0x4000,
MOUSEEVENTF_ABSOLUTE = 0x8000
}
enum SendInputEventType : int
{
InputMouse,
InputKeyboard,
InputHardware
}
public static void MoveMouseButton(int x, int y)
{
INPUT mouseMoveInput = new INPUT();
mouseMoveInput.type = SendInputEventType.InputMouse;
mouseMoveInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_MOVE| MouseEventFlags.MOUSEEVENTF_ABSOLUTE;
mouseMoveInput.mkhi.mi.dx = x;
mouseMoveInput.mkhi.mi.dy = y;
SendInput(1, ref mouseMoveInput, Marshal.SizeOf(new INPUT()));
}
}
I want to translate the Latin keyboard to another Keyboard like uyghur or something like. There is an uyghur keyboard, but the coding of keys are so complex that a normal PC User can't type uighur easily.
So my aim is that to create a software solution for this Problem, such as Chinese Input Systems. in that system you can input Chinese Characters from every kind of Keyboard. that is a kind of clever solution so that everyone can use it problem-less.
So my aim is that I want to write a Windows Service Application, which captures every KeyDown-Strike (only Alphabets) and translates the pressed Key to destination (Unicode) Alphabet and simulates again a Key strike with this translated Alphabet. As result the aimed Alphabet will be showed in the cursor-point. In the End my App discards/Stops the original key from the KEYDOWN pressing,
So that it will not be showed any more.
For example:
Press K.
Capturing the K and Translate it to Unicode like 0xFEBD then send back to cursor point.
Cancel or Discard the key down event of the K. This character should not be seen at the cursor point.
Until now the Step 1 and 2 works fine. My problem is that I can't discard/cancel/stop the last key down event for this key strike, after I capture the key down event.
I am not sure if my idea good/effective enough to realize what I am thinking. Now I am trying only. may be you have a better idea that you can suggest me. here is my code for that:
public class Simulate
{
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
static extern UInt32 SendInput(UInt32 numberOfInputs, INPUT[] input, Int32 sizeOfInputStructure);
[StructLayout(LayoutKind.Sequential, Size = 24)]
struct KEYBDINPUT
{
public UInt16 Vk;
public UInt16 Scan;
public UInt32 Flags;
public UInt32 Time;
public UInt32 ExtraInfo;
}
[StructLayout(LayoutKind.Explicit)]
private struct INPUT
{
[FieldOffset(0)]
public int Type;
[FieldOffset(4)]
public KEYBDINPUT ki;
}
public static void UnicodeInput(UInt16 unicode)
{
INPUT down = new INPUT();
down.Type = 1; //INPUT_KEYBOARD
down.ki.Vk = 0;
down.ki.Scan = unicode;
down.ki.Time = 0;
down.ki.Flags = 0x0004; //KEYEVENTF_UNICODE
down.ki.ExtraInfo = 0;
INPUT up = new INPUT();
up.Type = 1; //INPUT_KEYBOARD
up.ki.Vk = 0;
up.ki.Scan = unicode;
up.ki.Time = 0;
up.ki.Flags = 0x0004; //KEYEVENTF_UNICODE
up.ki.ExtraInfo = 0;
INPUT[] input = new INPUT[2];
input[0] = down;
input[1] = up;
SendInput(1, input, Marshal.SizeOf(typeof(INPUT)));
}
}
/// Capture any window key
///
public static class WinKeyCapture
{
private const int WH_KEYBOARD_LL = 13;
private const int WH_CALLWNDPROC = 4;
private const int WM_KEYDOWN = 0x0100;
private const int WM_CHAR = 0x0102;
const int VK_A = 0x08;// 0x41; //up key
const int VK_DOWN = 0x28; //down key
const int VK_LEFT = 0x25;
const int VK_RIGHT = 0x27;
const uint KEYEVENTF_KEYUP = 0x0002;
const uint KEYEVENTF_EXTENDEDKEY = 0x0001;
const uint KEYEVENTF_CTRL = 0x11;
const uint KEYEVENTF_ADD = 0x6B;
const uint VK_LWIN = 0x5b;
private static LowLevelKeyboardProc _proc = WinKeyCapture.HookCallback;
[DllImport("user32.dll")]
public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook,
LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("user32.dll", SetLastError = true)]
private static extern uint SendInput(uint numberOfInputs, INPUT[] inputs, int sizeOfInputStructure);
public static void SetHook()
{
SetHook(_proc);
}
public static void UnHook()
{
UnhookWindowsHookEx(_hookID);
}
private static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
}
}
private static IntPtr _hookID = IntPtr.Zero;
public static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
int vkCode = Marshal.ReadInt32(lParam);
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
// TODO: identify only Alphabets then fire
VKcode(vkCode);
}
//wParam |= 0x4000;
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
private static void VKcode(int code)
{
switch (code) // TODO: Complete all other Alphabet-Tranylations
{
case 0x4B:
Simulate.UnicodeInput(0xFEDB);
break;
case 0x54:
Simulate.UnicodeInput(0xFEAD);
break;
case 0x55:
Simulate.UnicodeInput(0xFBE7);
break;
case 0x56:
Simulate.UnicodeInput(0xFEE9);
break;
case 0x59:
Simulate.UnicodeInput(0xFEE1);
break;
case 0x5a:
break;
}
}
/// <summary>
/// simulate key press
/// </summary>
/// <param name="keyCode"></param>
public static void SendKeyPress(KeyCode keyCode)
{
INPUT input = new INPUT {
Type = 1
};
input.Data.Keyboard = new KEYBDINPUT() {
Vk = (ushort)keyCode,
Scan = 0,
Flags = 0,
Time = 0,
ExtraInfo = IntPtr.Zero,
};
INPUT input2 = new INPUT {
Type = 1
};
input2.Data.Keyboard = new KEYBDINPUT() {
Vk = (ushort)keyCode,
Scan = 0,
Flags = 2,
Time = 0,
ExtraInfo = IntPtr.Zero
};
INPUT[] inputs = new INPUT[] { input, input2 };
if (SendInput(2, inputs, Marshal.SizeOf(typeof(INPUT))) == 0)
throw new Exception();
}
/// <summary>
/// simulate key press
/// </summary>
/// <param name="keyCode"></param>
public static void SendUnicodePress(KeyCode keyCode)
{
INPUT input = new INPUT {
Type = 1
};
input.Data.Keyboard = new KEYBDINPUT() {
Vk = (ushort)keyCode,
Scan = 0,
Flags = 0,
Time = 0,
ExtraInfo = IntPtr.Zero,
};
INPUT input2 = new INPUT {
Type = 1
};
input2.Data.Keyboard = new KEYBDINPUT() {
Vk = (ushort)keyCode,
Scan = 0,
Flags = 2,
Time = 0,
ExtraInfo = IntPtr.Zero
};
INPUT[] inputs = new INPUT[] { input, input2 };
if (SendInput(2, inputs, Marshal.SizeOf(typeof(INPUT))) == 0)
throw new Exception();
}
[StructLayout(LayoutKind.Sequential)]
internal struct INPUT
{
public uint Type;
public MOUSEKEYBDHARDWAREINPUT Data;
}
[StructLayout(LayoutKind.Explicit)]
internal struct MOUSEKEYBDHARDWAREINPUT
{
[FieldOffset(0)]
public HARDWAREINPUT Hardware;
[FieldOffset(0)]
public KEYBDINPUT Keyboard;
[FieldOffset(0)]
public MOUSEINPUT Mouse;
}
[StructLayout(LayoutKind.Sequential)]
internal struct HARDWAREINPUT
{
public uint Msg;
public ushort ParamL;
public ushort ParamH;
}
[StructLayout(LayoutKind.Sequential)]
internal struct KEYBDINPUT
{
public ushort Vk;
public ushort Scan;
public uint Flags;
public uint Time;
public IntPtr ExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
internal struct MOUSEINPUT
{
public int X;
public int Y;
public uint MouseData;
public uint Flags;
public uint Time;
public IntPtr ExtraInfo;
}
}
I need to send mouse signals in C# so that other applications register them. To be exact, I need to simulate mouse buttons and the move of the mouse. Is there a way to do this in C#? (Windows)
The mouse's cursor position is a settable property - you can use it to move the mouse wherever you want.
You need to call the SendInput API function.
See here for P/Invoke defnitions.
As far as the buttonpresses go, you can do the following
[DllImport("user32.dll")]
public static extern uint SendInput(uint nInputs, ref Input pInputs, int cbSize);
const uint MOUSEEVENTF_LEFTDOWN = 0x0002;
const uint MOUSEEVENTF_LEFTUP = 0x0004;
const uint MOUSEEVENTF_RIGHTDOWN = 0x0008;
const uint MOUSEEVENTF_RIGHTUP = 0x0010;
public static void DoMouseClick()
{
var input =
new Input
{
type = 0,
mouseinput =
new Mouseinput
{
dx = Cursor.Position.X,
dy = Cursor.Position.Y,
dwFlags = MOUSEEVENTF_LEFTDOWN
}
};
SendInput(1, ref input, 28);
}
[StructLayout(LayoutKind.Explicit, Size = 28)]
public struct Input
{
[FieldOffset(0)]
public uint type;
[FieldOffset(4)]
public Mouseinput mouseinput;
};
[StructLayout(LayoutKind.Explicit, Size = 28)]
public struct Mouseinput
{
[FieldOffset(0)]
public int dx;
[FieldOffset(4)]
public int dy;
[FieldOffset(8)]
public uint mouseData;
[FieldOffset(12)]
public uint dwFlags;
[FieldOffset(16)]
public uint time;
[FieldOffset(20)]
public uint dwExtraInfo;
}
I'm trying to use the Windows API to set the primary monitor. It doesn't seem to work - my screen just flicks and nothing happens.
public const int DM_ORIENTATION = 0x00000001;
public const int DM_PAPERSIZE = 0x00000002;
public const int DM_PAPERLENGTH = 0x00000004;
public const int DM_PAPERWIDTH = 0x00000008;
public const int DM_SCALE = 0x00000010;
public const int DM_POSITION = 0x00000020;
public const int DM_NUP = 0x00000040;
public const int DM_DISPLAYORIENTATION = 0x00000080;
public const int DM_COPIES = 0x00000100;
public const int DM_DEFAULTSOURCE = 0x00000200;
public const int DM_PRINTQUALITY = 0x00000400;
public const int DM_COLOR = 0x00000800;
public const int DM_DUPLEX = 0x00001000;
public const int DM_YRESOLUTION = 0x00002000;
public const int DM_TTOPTION = 0x00004000;
public const int DM_COLLATE = 0x00008000;
public const int DM_FORMNAME = 0x00010000;
public const int DM_LOGPIXELS = 0x00020000;
public const int DM_BITSPERPEL = 0x00040000;
public const int DM_PELSWIDTH = 0x00080000;
public const int DM_PELSHEIGHT = 0x00100000;
public const int DM_DISPLAYFLAGS = 0x00200000;
public const int DM_DISPLAYFREQUENCY = 0x00400000;
public const int DM_ICMMETHOD = 0x00800000;
public const int DM_ICMINTENT = 0x01000000;
public const int DM_MEDIATYPE = 0x02000000;
public const int DM_DITHERTYPE = 0x04000000;
public const int DM_PANNINGWIDTH = 0x08000000;
public const int DM_PANNINGHEIGHT = 0x10000000;
public const int DM_DISPLAYFIXEDOUTPUT = 0x20000000;
public const int ENUM_CURRENT_SETTINGS = -1;
public const int CDS_UPDATEREGISTRY = 0x01;
public const int CDS_TEST = 0x02;
public const int CDS_SET_PRIMARY = 0x00000010;
public const long DISP_CHANGE_SUCCESSFUL = 0;
public const long DISP_CHANGE_RESTART = 1;
public const long DISP_CHANGE_FAILED = -1;
public const long DISP_CHANGE_BADMODE = -2;
public const long DISP_CHANGE_NOTUPDATED = -3;
public const long DISP_CHANGE_BADFLAGS = -4;
public const long DISP_CHANGE_BADPARAM = -5;
public const long DISP_CHANGE_BADDUALVIEW = -6;
public static void SetPrimary(Screen screen)
{
DISPLAY_DEVICE d = new DISPLAY_DEVICE();
DEVMODE dm = new DEVMODE();
d.cb = Marshal.SizeOf(d);
uint deviceID = 1;
User_32.EnumDisplayDevices(null, deviceID, ref d, 0); //
User_32.EnumDisplaySettings(d.DeviceName, 0, ref dm);
dm.dmPelsWidth = 2560;
dm.dmPelsHeight = 1600;
dm.dmPositionX = screen.Bounds.Right;
dm.dmFields = DM_POSITION | DM_PELSWIDTH | DM_PELSHEIGHT;
User_32.ChangeDisplaySettingsEx(d.DeviceName, ref dm, IntPtr.Zero, CDS_SET_PRIMARY, IntPtr.Zero);
}
I call the method like this:
SetPrimary(Screen.AllScreens[1])
Any ideas?
Here is the full code based on ADBailey's solution:
public class MonitorChanger
{
public static void SetAsPrimaryMonitor(uint id)
{
var device = new DISPLAY_DEVICE();
var deviceMode = new DEVMODE();
device.cb = Marshal.SizeOf(device);
NativeMethods.EnumDisplayDevices(null, id, ref device, 0);
NativeMethods.EnumDisplaySettings(device.DeviceName, -1, ref deviceMode);
var offsetx = deviceMode.dmPosition.x;
var offsety = deviceMode.dmPosition.y;
deviceMode.dmPosition.x = 0;
deviceMode.dmPosition.y = 0;
NativeMethods.ChangeDisplaySettingsEx(
device.DeviceName,
ref deviceMode,
(IntPtr)null,
(ChangeDisplaySettingsFlags.CDS_SET_PRIMARY | ChangeDisplaySettingsFlags.CDS_UPDATEREGISTRY | ChangeDisplaySettingsFlags.CDS_NORESET),
IntPtr.Zero);
device = new DISPLAY_DEVICE();
device.cb = Marshal.SizeOf(device);
// Update remaining devices
for (uint otherid = 0; NativeMethods.EnumDisplayDevices(null, otherid, ref device, 0); otherid++)
{
if (device.StateFlags.HasFlag(DisplayDeviceStateFlags.AttachedToDesktop) && otherid != id)
{
device.cb = Marshal.SizeOf(device);
var otherDeviceMode = new DEVMODE();
NativeMethods.EnumDisplaySettings(device.DeviceName, -1, ref otherDeviceMode);
otherDeviceMode.dmPosition.x -= offsetx;
otherDeviceMode.dmPosition.y -= offsety;
NativeMethods.ChangeDisplaySettingsEx(
device.DeviceName,
ref otherDeviceMode,
(IntPtr)null,
(ChangeDisplaySettingsFlags.CDS_UPDATEREGISTRY | ChangeDisplaySettingsFlags.CDS_NORESET),
IntPtr.Zero);
}
device.cb = Marshal.SizeOf(device);
}
// Apply settings
NativeMethods.ChangeDisplaySettingsEx(null, IntPtr.Zero, (IntPtr)null, ChangeDisplaySettingsFlags.CDS_NONE, (IntPtr)null);
}
}
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
public struct DEVMODE
{
public const int CCHDEVICENAME = 32;
public const int CCHFORMNAME = 32;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
[System.Runtime.InteropServices.FieldOffset(0)]
public string dmDeviceName;
[System.Runtime.InteropServices.FieldOffset(32)]
public Int16 dmSpecVersion;
[System.Runtime.InteropServices.FieldOffset(34)]
public Int16 dmDriverVersion;
[System.Runtime.InteropServices.FieldOffset(36)]
public Int16 dmSize;
[System.Runtime.InteropServices.FieldOffset(38)]
public Int16 dmDriverExtra;
[System.Runtime.InteropServices.FieldOffset(40)]
public UInt32 dmFields;
[System.Runtime.InteropServices.FieldOffset(44)]
Int16 dmOrientation;
[System.Runtime.InteropServices.FieldOffset(46)]
Int16 dmPaperSize;
[System.Runtime.InteropServices.FieldOffset(48)]
Int16 dmPaperLength;
[System.Runtime.InteropServices.FieldOffset(50)]
Int16 dmPaperWidth;
[System.Runtime.InteropServices.FieldOffset(52)]
Int16 dmScale;
[System.Runtime.InteropServices.FieldOffset(54)]
Int16 dmCopies;
[System.Runtime.InteropServices.FieldOffset(56)]
Int16 dmDefaultSource;
[System.Runtime.InteropServices.FieldOffset(58)]
Int16 dmPrintQuality;
[System.Runtime.InteropServices.FieldOffset(44)]
public POINTL dmPosition;
[System.Runtime.InteropServices.FieldOffset(52)]
public Int32 dmDisplayOrientation;
[System.Runtime.InteropServices.FieldOffset(56)]
public Int32 dmDisplayFixedOutput;
[System.Runtime.InteropServices.FieldOffset(60)]
public short dmColor; // See note below!
[System.Runtime.InteropServices.FieldOffset(62)]
public short dmDuplex; // See note below!
[System.Runtime.InteropServices.FieldOffset(64)]
public short dmYResolution;
[System.Runtime.InteropServices.FieldOffset(66)]
public short dmTTOption;
[System.Runtime.InteropServices.FieldOffset(68)]
public short dmCollate; // See note below!
[System.Runtime.InteropServices.FieldOffset(72)]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHFORMNAME)]
public string dmFormName;
[System.Runtime.InteropServices.FieldOffset(102)]
public Int16 dmLogPixels;
[System.Runtime.InteropServices.FieldOffset(104)]
public Int32 dmBitsPerPel;
[System.Runtime.InteropServices.FieldOffset(108)]
public Int32 dmPelsWidth;
[System.Runtime.InteropServices.FieldOffset(112)]
public Int32 dmPelsHeight;
[System.Runtime.InteropServices.FieldOffset(116)]
public Int32 dmDisplayFlags;
[System.Runtime.InteropServices.FieldOffset(116)]
public Int32 dmNup;
[System.Runtime.InteropServices.FieldOffset(120)]
public Int32 dmDisplayFrequency;
}
public enum DISP_CHANGE : int
{
Successful = 0,
Restart = 1,
Failed = -1,
BadMode = -2,
NotUpdated = -3,
BadFlags = -4,
BadParam = -5,
BadDualView = -6
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct DISPLAY_DEVICE
{
[MarshalAs(UnmanagedType.U4)]
public int cb;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string DeviceName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceString;
[MarshalAs(UnmanagedType.U4)]
public DisplayDeviceStateFlags StateFlags;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string DeviceKey;
}
[Flags()]
public enum DisplayDeviceStateFlags : int
{
/// <summary>The device is part of the desktop.</summary>
AttachedToDesktop = 0x1,
MultiDriver = 0x2,
/// <summary>The device is part of the desktop.</summary>
PrimaryDevice = 0x4,
/// <summary>Represents a pseudo device used to mirror application drawing for remoting or other purposes.</summary>
MirroringDriver = 0x8,
/// <summary>The device is VGA compatible.</summary>
VGACompatible = 0x10,
/// <summary>The device is removable; it cannot be the primary display.</summary>
Removable = 0x20,
/// <summary>The device has more display modes than its output devices support.</summary>
ModesPruned = 0x8000000,
Remote = 0x4000000,
Disconnect = 0x2000000,
}
[Flags()]
public enum ChangeDisplaySettingsFlags : uint
{
CDS_NONE = 0,
CDS_UPDATEREGISTRY = 0x00000001,
CDS_TEST = 0x00000002,
CDS_FULLSCREEN = 0x00000004,
CDS_GLOBAL = 0x00000008,
CDS_SET_PRIMARY = 0x00000010,
CDS_VIDEOPARAMETERS = 0x00000020,
CDS_ENABLE_UNSAFE_MODES = 0x00000100,
CDS_DISABLE_UNSAFE_MODES = 0x00000200,
CDS_RESET = 0x40000000,
CDS_RESET_EX = 0x20000000,
CDS_NORESET = 0x10000000
}
public class NativeMethods
{
[DllImport("user32.dll")]
public static extern DISP_CHANGE ChangeDisplaySettingsEx(string lpszDeviceName, ref DEVMODE lpDevMode, IntPtr hwnd, ChangeDisplaySettingsFlags dwflags, IntPtr lParam);
[DllImport("user32.dll")]
// A signature for ChangeDisplaySettingsEx with a DEVMODE struct as the second parameter won't allow you to pass in IntPtr.Zero, so create an overload
public static extern DISP_CHANGE ChangeDisplaySettingsEx(string lpszDeviceName, IntPtr lpDevMode, IntPtr hwnd, ChangeDisplaySettingsFlags dwflags, IntPtr lParam);
[DllImport("user32.dll")]
public static extern bool EnumDisplayDevices(string lpDevice, uint iDevNum, ref DISPLAY_DEVICE lpDisplayDevice, uint dwFlags);
[DllImport("user32.dll")]
public static extern bool EnumDisplaySettings(string deviceName, int modeNum, ref DEVMODE devMode);
}
[StructLayout(LayoutKind.Sequential)]
public struct POINTL
{
public int x;
public int y;
}
I ran into exactly the same problem, both from C# and after following the advice here to try it in C++. I eventually discovered that the thing the Microsoft documentation doesn't make clear is that the request to set the primary monitor will be ignored (but with the operation reported as successful!) unless you also set the position of the monitor to (0, 0) on the DEVMODE struct. Of course, this means that you also need to shift the positions of your other monitors so that they stay in the same place relative to the new primary monitor. Per the documentation (http://msdn.microsoft.com/en-us/library/windows/desktop/dd183413%28v=vs.85%29.aspx), call ChangeDisplaySettingsEx for each monitor with the CDS_NORESET flag and then make a final call with everything null.
The following code worked for me:
public static void SetAsPrimaryMonitor(uint id)
{
var device = new DISPLAY_DEVICE();
var deviceMode = new DEVMODE();
device.cb = Marshal.SizeOf(device);
NativeMethods.EnumDisplayDevices(null, id, ref device, 0);
NativeMethods.EnumDisplaySettings(device.DeviceName, -1, ref deviceMode);
var offsetx = deviceMode.dmPosition.x;
var offsety = deviceMode.dmPosition.y;
deviceMode.dmPosition.x = 0;
deviceMode.dmPosition.y = 0;
NativeMethods.ChangeDisplaySettingsEx(
device.DeviceName,
ref deviceMode,
(IntPtr)null,
(ChangeDisplaySettingsFlags.CDS_SET_PRIMARY | ChangeDisplaySettingsFlags.CDS_UPDATEREGISTRY | ChangeDisplaySettingsFlags.CDS_NORESET),
IntPtr.Zero);
device = new DISPLAY_DEVICE();
device.cb = Marshal.SizeOf(device);
// Update remaining devices
for (uint otherid = 0; NativeMethods.EnumDisplayDevices(null, otherid, ref device, 0); otherid++)
{
if (device.StateFlags.HasFlag(DisplayDeviceStateFlags.AttachedToDesktop) && otherid != id)
{
device.cb = Marshal.SizeOf(device);
var otherDeviceMode = new DEVMODE();
NativeMethods.EnumDisplaySettings(device.DeviceName, -1, ref otherDeviceMode);
otherDeviceMode.dmPosition.x -= offsetx;
otherDeviceMode.dmPosition.y -= offsety;
NativeMethods.ChangeDisplaySettingsEx(
device.DeviceName,
ref otherDeviceMode,
(IntPtr)null,
(ChangeDisplaySettingsFlags.CDS_UPDATEREGISTRY | ChangeDisplaySettingsFlags.CDS_NORESET),
IntPtr.Zero);
}
device.cb = Marshal.SizeOf(device);
}
// Apply settings
NativeMethods.ChangeDisplaySettingsEx(null, IntPtr.Zero, (IntPtr)null, ChangeDisplaySettingsFlags.CDS_NONE, (IntPtr)null);
}
Note that a signature for ChangeDisplaySettingsEx with a DEVMODE struct as the second parameter obviously won't allow you to pass in IntPtr.Zero. Create yourself two different signatures for the same extern call, i.e.
[DllImport("user32.dll")]
public static extern DISP_CHANGE ChangeDisplaySettingsEx(string lpszDeviceName, ref DEVMODE lpDevMode, IntPtr hwnd, ChangeDisplaySettingsFlags dwflags, IntPtr lParam);
[DllImport("user32.dll")]
public static extern DISP_CHANGE ChangeDisplaySettingsEx(string lpszDeviceName, IntPtr lpDevMode, IntPtr hwnd, ChangeDisplaySettingsFlags dwflags, IntPtr lParam);
I can't really help you with the winapi-stuff but if you are using a Nvidia card you may have a look at the NVcontrolPanel Api Documentation
Then you could make the secondary output your primary using rundll32.exe NvCpl.dll,dtcfg primary 2
Hope that will help you.
According to the documentation for ChangeDisplaySettingsEx, "the dmSize member must be initialized to the size, in bytes, of the DEVMODE structure." Furthermore, the EnumDisplaySettings documentation states, "Before calling EnumDisplaySettings, set the dmSize member to sizeof(DEVMODE), and set the dmDriverExtra member to indicate the size, in bytes, of the additional space available to receive private driver data". I don't see this happening in the code sample given in the question; that's one reason why it may be failing.
Additionally, you might have errors in the definitions of the DEVMODE and DISPLAY_DEVICE structs, which were not included in the question. Roger Lipscombe's suggestion to get it working from C/C++ first is an excellent way to rule out this type of problem.
Finally, check the return value from ChangeDisplaySettingsEx and see if that gives a clue as to why it might be failing.