I'm trying basically SendKey's to IE9 to change tabs. I have 3 tabs so I'd need to Send keys Ctrl+1, Ctrl+2, Ctrl+3 and also Ctrl+T to open a new tab.
I start by adding the import dlls and constants
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg,
IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg,
IntPtr wParam, IntPtr lParam);
const int WM_KEYDOWN = 0x100;
const int WM_KEYUP = 0x101;
I get the instance of Internet Explorer by opening a new process.
Process p = Process.Start("iexplorer.exe");
Use the process handle to PostMessage to IE9 instance
IntPtr handle = p.MainWindowHandle; //p.Handle (doesn't work either)
//Change to Tab2 using PostMessage
PostMessage(handle, WM_KEYDOWN, ((IntPtr)Keys.LControlKey), (IntPtr)0);
PostMessage(handle, WM_KEYDOWN, ((IntPtr)Keys.D2), (IntPtr)0);
PostMessage(handle, WM_KEYUP, ((IntPtr)Keys.D2), (IntPtr)0);
PostMessage(handle, WM_KEYUP, ((IntPtr)Keys.LControlKey), (IntPtr)0);
No response. I've also tried using SendMessage to no avail as well.
Am I doing anything obviously wrong?
How about SendKeys("^1");
as seen here
Related
[DllImport("user32.dll", EntryPoint = "SendMessageW", CharSet = CharSet.Unicode)]
public static extern int SendMessage(IntPtr hwnd, SendMessageFlags msg, IntPtr wParam, IntPtr lParam);
public static void SetByHwnd(IntPtr hwnd, string text)
{
IntPtr a = Marshal.StringToHGlobalUni(text);
SendMessage(hwnd, SendMessageFlags.WM_SETTEXT, IntPtr.Zero, a);
}
When i try to change any objects text to Japanese, Russian, Greek, Arabic etc.. text im changing my controls text to meaningless question marks.
There is no problem with the "a-Z" "0-9" but i need to use other languages alphabets too.
i need this to work SetByHwnd(hwnd, "कार्यकारी")
I tried to use SendMessageA and SendMessage, changed parameters like
SendMessage(IntPtr hwnd, SendMessageFlags msg, IntPtr wParam, StringBuilder strBuffer);
SendMessage(IntPtr hwnd, SendMessageFlags msg, IntPtr wParam, string lParam);
But didnt help. Always seeing the question marks "????" in my control.
Well, first off, what I'm trying to do is click a specific point inside a flash object, inside of a webbrowser control. I'm not sure why it isn't working, but I cannot seem to click any window, be it notepad, or the actual program.
Here is my code that I'm using.
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, IntPtr windowTitle);
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(String sClassName, String sAppName);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImport("user32.dll", SetLastError = true)]
static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
public IntPtr find()
{
return this.Handle;//FindWindow("", "Form1");
}
public enum WMessages : int
{
WM_LBUTTONDOWN = 0x201, //Left mousebutton down
WM_LBUTTONUP = 0x202, //Left mousebutton up
WM_LBUTTONDBLCLK = 0x203, //Left mousebutton doubleclick
WM_RBUTTONDOWN = 0x204, //Right mousebutton down
WM_RBUTTONUP = 0x205, //Right mousebutton up
WM_RBUTTONDBLCLK = 0x206, //Right mousebutton do
}
private int MAKELPARAM(int p, int p_2)
{
return ((p_2 << 16) | (p & 0xFFFF));
}
/** This is the non-working code **/
public void DoMouseLeftClick(IntPtr handle, Point x)
{
SendMessage(handle, (int)WMessages.WM_LBUTTONDOWN, 0, MAKELPARAM(x.X, x.Y));
SendMessage(handle, (int)WMessages.WM_LBUTTONUP, 0, MAKELPARAM(x.X, x.Y));
return;
//I have tried PostMessage, and SendMessage, and both of them at the same time, and neither works.
PostMessage(handle, (uint)WMessages.WM_LBUTTONDOWN, 0, MAKELPARAM(x.X, x.Y));
PostMessage(handle, (uint)WMessages.WM_LBUTTONUP, 0, MAKELPARAM(x.X, x.Y));
}
private void timer2_Tick(object sender, EventArgs e)
{
//I try hovering my mouse over a button I added to the form, and nothing happens.
DoMouseLeftClick(find(), Cursor.Position);
}
So, I have tried using PostMessage, and SendMessage, and neither of those seem to work.
All I need it to do is to click on a specific point.
Also, I need to mention that I can't use mouse_event, because from what I know, the window needs to be active, plus the cursor needs to be over the point you are clicking. I am making a bot that automatically does a process in a flash object, so that's why I can't use mouse_event.
Thanks for your help guys.
I had the same problem.
I tried to draw something in the MS Paint. It turned out that I was clicking on the main window but it turned out that MS Paint (and most of the applications) consist of many child windows and you actually want to click on the child. So I had to change my code from:
IntPtr handle = FindWindow(null, "Untitled - Paint");
PostMessage(handle, (uint)MOUSE_BUTTONS.LEFT_DOWN, 0, lparam);
to
IntPtr handle = FindWindow(null, "Untitled - Paint");
handle = FindWindowEx(handle, IntPtr.Zero, "MSPaintView", null);
canvasHandle = FindWindowEx(handle, IntPtr.Zero, "Afx:00007FF676DD0000:8", null);
PostMessage(canvasHandle, (uint)MOUSE_BUTTONS.LEFT_DOWN, 0, lparam);
You need to use tools like Spy++ for Windows that comes with C++ Visual Studio package if you want to debug these kind of things (even if you program in C#)
Hope it helps someone.
For the WM_LBUTTONDOWN, you may need to specify which button. Take reference for: https://msdn.microsoft.com/en-us/library/windows/desktop/ms645607(v=vs.85).aspx
I used:
SendMessage(hWnd, (int)WMessages.WM_RBUTTONDOWN, (int)KeyDownMessage.MK_LBUTTON, MAKELPARAM(x, y));
When I try to paste text in textbox another program, the text is inserted, but the program does not recognize it.
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
const uint WM_SETTEXT = 0x000C;
IntPtr text = Marshal.StringToCoTaskMemUni("100");
IntPtr thisWindow = FindWindow(null, "AnotherWindow");
IntPtr handle = FindWindowEx(thisWindow, IntPtr.Zero, "AnotherTextBox", null);
SendMessage(handle, WM_SETTEXT, IntPtr.Zero, text);
Marshal.FreeCoTaskMem(text);
Maybe I should send to the parent a message that the textbox is updated?
Like this:
//Wrong code, because I do not know how correctly send a message
SendMessage(handle, WM_COMMAND, EM_SETMODIFY, handle);
And again...help came from another site
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
//...
IntPtr boo = new IntPtr(1);
SendMessage(handle, EM_SETMODIFY, boo, IntPtr.Zero);
You'd be looking to do something like:
PostMessage(GetParent(handle), WM_COMMAND, MAKEWPARAM(GetWindowLong(handle, GWL_ID), EN_CHANGE), (LPARAM)handle);
some Textboxes have been set so that you can not set your text by WM_SETTEXT immediately, especially those which accept digits and perform calculation according these digits. I had similar problem and solved it by bellow code. I applied WM_PASTE, EM_REPLACESEL to conquer that.
SendMessage(child, WM_SETFOCUS,0 , IntPtr.Zero); // go to text box
System.Windows.Forms.Clipboard.SetText("1"); // set something in clipboard. it does not matter what it is.
SendMessage(child, WM_PASTE, 0, IntPtr.Zero); // paste to get control of text box
SendMessage(child, WM_SETTEXT, IntPtr.Zero, string.Empty); // clear textbox to insert your desired text.
SendMessage(child, EM_REPLACESEL, IntPtr.Zero, "your text"); // insert your desired text. i inserted digits as text.
you need to Import user32.dll file at first:
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
private static extern int SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, string lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
private static extern int SendMessage(IntPtr hWnd, uint msg,int wParam, IntPtr lParam);
I am writing a .NET wrapper around Win32 hooks which buffers WM_CHAR messages and allows events such as key presses, key releases, and accelerator keystrokes to be subscribed to. Everything is in working order except apparently my call to TranslateAccelerator. It returns true when I expect it to (when it finds an accelerator in the given table which I constructed earlier) but the WM_COMMAND messages don't seem to be showing up ever. Here is some relevant code.
[StructLayout(LayoutKind.Sequential)]
struct MSG {
IntPtr hWnd;
WindowsMessages message;
IntPtr wParam;
IntPtr lParam;
UInt32 time;
POINT pt;
}
delegate IntPtr HOOKPROC(HookCodes nCode, IntPtr wParam, ref MSG lParam);
[DllImport("user32.dll")]
extern IntPtr CallNextHookEx(IntPtr hhk, HookCodes nCode, IntPtr wParam, ref MSG lParam);
IntPtr HookProcedure(HookCodes nCode, IntPtr wParam, ref MSG lParam) {
IntPtr result = IntPtr.Zero;
if(nCode < HookCodes.ACTION) {
result = CallNextHookEx(hHook, nCode, wParam, ref lParam);
} else if(nCode == HookCodes.ACTION && (PeekMessageOptions)wParam == PeekMessageOptions.REMOVE) {
/*
* Under these conditions, each message will only be passed onto the switch below once.
*/
switch(lParam.message) {
case WindowsMessages.KEYDOWN:
//fire keydown events and call TranslateAccelerator/TranslateMessage
break;
case WindowsMessages.KEYUP:
//fire keyup events
break;
case WindowsMessages.COMMAND:
//fire accelerator events Ex: Ctrl+F, ALT+M, SHIFT+L
break;
case WindowsMessages.CHAR:
//place char in buffer
break;
default:
break;
}
}
return result; //Will be zero if action was taken on the message by this procedure.
}
}
In KeyPressed(MSG), messages are translated like so:
[DllImport("user32.dll")]
extern bool TranslateAccelerator(IntPtr hWnd, IntPtr hAccTable, ref MSG lpMsg);
[DllImport("user32.dll")]
extern bool TranslateMessage(ref MSG lpMsg);
if(!TranslateAccelerator(hWnd, hAccel, ref msg)){
TranslateMessage(ref msg);
}
The hook and accelerator table are created like this:
[StructLayout(LayoutKind.Sequential)]
struct ACCEL {
byte fVirt;
ushort key;
ushort cmd;
}
[DllImport("user32.dll")]
extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr lpdwProcessId);
[DllImport("user32.dll")]
extern IntPtr SetWindowsHookEx(WindowsHooks hook, HookProcedure lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll")]
extern IntPtr CreateAcceleratorTable(ACCEL[] lpaccl, int cEntries);
HOOKPROC proc = HookProcedure;
uint pid = GetWindowThreadProcessId(/*IntPtr*/hWnd, IntPtr.Zero);
IntPtr hHook = SetWindowsHookEx(WindowsHooks.GETMESSAGE, proc, IntPtr.Zero, pid);
IntPtr hAccel = CreateAcceleratorTable(/*ACCEL[]*/accelerators, accelerators.Length);
Everything works fine (such as attaching events to key-downs and buffering WM_CHAR messages) except I can't find WM_COMMAND or WM_SYSCOMMAND messages anywhere in the queue. They just don't seem to be visible to my hook procedure, even though TranslateAccelerator returns true when I expect it to. Note that I am really pretty clueless when it comes to Win32 so I'm probably missing something fairly obvious to the trained eye. But I am at my wits end. I've tried attaching the hook to an XNA window and a Windows Form without success.
You won't catch those WM_COMMAND messages with a GETMESSAGE hook.
TranslateAccelerator "sends the WM_COMMAND or WM_SYSCOMMAND message directly to the specified window procedure" (see the documentation) and hence bypasses the message queue.
You'll need a CALLWNDPROC hook instead.
I am using the following to mute/unmute the master audio on my computer. Now, I am looking for a way to determine the mute state. Is there a just as easy way to do this in C#?
private const int APPCOMMAND_VOLUME_MUTE = 0x80000;
private const int WM_APPCOMMAND = 0x319;
[DllImport("user32.dll")]
public static extern IntPtr SendMessageW(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
Hi just stumbled accross this old topic, but wa shaving the exact same issue.
I solved using the following:
using System.Runtime.InteropServices;
...
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
private const int APPCOMMAND_VOLUME_MUTE = 0x80000;
private const int APPCOMMAND_VOLUME_UP = 0xA0000;
private const int APPCOMMAND_VOLUME_DOWN = 0x90000;
private const int WM_APPCOMMAND = 0x319;
...
// mute (toggle)
SendMessage(this.Handle, WM_APPCOMMAND, this.Handle, (IntPtr)APPCOMMAND_VOLUME_MUTE);
// unmute
SendMessage(this.Handle, WM_APPCOMMAND, this.Handle, (IntPtr)APPCOMMAND_VOLUME_UP);
SendMessage(this.Handle, WM_APPCOMMAND, this.Handle, (IntPtr)APPCOMMAND_VOLUME_DOWN);
Mute will not always mute the audio, it's a toggle - but if you make sure to call "unmute" first you should be golden.
Best regards
Kurt
Checkout the following tutorial. I've never played with the Mixer in C# ( or any other language ) so I'm assuming they are correct in P/Invoking the Win32 APIs and that they aren't reinventing the wheel. You can download the example and I think the method GetMixer() will do what you want.
Credit to RRUZ in comments above. See stackoverflow.com/questions/294292. The only problem is that you need compatibility mode.