Click here to Skip to main content
15,888,351 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
NOTE: I'm NOT using Notepad as the final application so PLEASE don't tell me how docking Notepad is a useless/bad idea!

Right now as a test app I have Notepad docked in my WinForm. Currently I'm sending commands into it by simply focusing the window and using SendKeys, but that requires focus which means I can't be doing anything else while the macro is running or else it would send the input to whatever is focused.

Is there a way that the program sends input only to itself or rather the docked exe inside of it without affecting the user?

For example I press a button and minimize the window and it would still type 5+5=10 in notepad then Ctrl+C -> Ctrl+V into another textbox all while I could be typing in another window.

What I have tried:

I have tried the SendKeys(), but that requires focus. I've read somewhere about PostMessage, but haven't been able to figure out how to use it properly.
Posted
Updated 31-Jul-16 23:47pm

1 solution

Have a look here, accepted answer: Problem with sendmessage in C#[^]

I made a short test on it and it does really work.
I hope it helps.

Edit Fast and dirty test code snippet
C#
public partial class FormMain : Form
{
    // Interop
    [DllImport("user32.dll")]
    public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

    [DllImport("user32.dll", SetLastError = true)]   
    static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);   

    [DllImport("user32.dll")]
    private static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, UInt32 wParam, UInt32 lParam);   

    // Notepad starter
    Process process = null;

    private void buttonStart_Click(object sender, EventArgs e)
    {
        if (process != null)
            return;
        process = new Process();
        try
        {
            string winpath = Environment.GetEnvironmentVariable("windir");
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.FileName = winpath + @"\system32\notepad.exe";
            process.Start();
            process.WaitForInputIdle();
            {
                Thread.Sleep(200);
                SetParent(process.MainWindowHandle, this.panelClient.Handle);
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }

    }

    private void buttonSendKeys_Click(object sender, EventArgs e)
    {
        if (process == null)
            return;

        // https://social.msdn.microsoft.com/Forums/en-US/eebaa35b-f22c-47b2-9fc9-2a5e876f0b79/problem-with-sendmessage-in-c?forum=csharplanguage
        UInt32 WM_KEYDOWN = 0x0100;
        UInt32 repeatCount = 13;
        UInt32 scanCode = 0x2D;
        UInt32 extended = 0;
        UInt32 context = 0;
        UInt32 previousState = 0;
        UInt32 transition = 0;

        // combine the parameters above according to the bit
        // fields described in the MSDN page for WM_KEYDOWN
        UInt32 lParam = repeatCount
            | (scanCode << 16)
            | (extended << 24)
            | (context << 29)
            | (previousState << 30)
            | (transition << 31);


        IntPtr editHandle = FindWindowEx(process.MainWindowHandle, IntPtr.Zero, "EDIT", null);

        PostMessage(editHandle, WM_KEYDOWN, 'A', lParam);  
    }
    //...
}
 
Share this answer
 
v3
Comments
[no name] 1-Aug-16 19:27pm    
This seems to work very well and the window does not need to be focused! This is meant specifically for notepad as it finds the EDIT field in the notepad. If it's another program would I be able to just put the p.MainWindowHandle as the first arg in the PostMessage() instead of the editHandle?

So if I want to send a string into the application I would have to do the PostMessage() for each individual character in that string?

Lastly to send Ctrl+C or Ctrl+V is there a special trick to it? Using the send key down then up for Ctrl+C didn't seem to work. I tried:

PostMessage(editHandle, WM_KEYDOWN, 0x11,
PostMessage(editHandle, WM_KEYDOWN, 'C',
PostMessage(editHandle, WM_KEYUP, 'C',
PostMessage(editHandle, WM_KEYUP, 0x11, 0);
[no name] 2-Aug-16 3:59am    
- How another app than Notepad reacts, I think you Need to test it individually.
- For sending a string you can use WM_SETTEXT.
- Ctrl+C or Ctrl+V you can't solve with WM_KEYUP :(

Finally I suggest you to have a look here: Windows Input Simulator &#40;C&#35; SendInput Wrapper - Simulate Keyboard and Mouse&#41; - Home[^]. This looks like it should solve your request. But most probably you Need to adapt it, at a first glance it Looks like it is not designed to send Inputs to other apps.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900