0

I know this question has already been answered. Here is my problem. I have a Windows Form with a button and a textbox. The user enters info into the textbox, and when the user clicks the button, an instance of notepad is launched and the text of the textbox is then loaded into the notepad.

Here is my code (which I got from a question on this site)

  [DllImport("user32.dll", EntryPoint = "FindWindowEx")]
        public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
        [DllImport("User32.dll")]
        public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, string lParam);

        private void btnCopyToNotepad_Click(object sender, EventArgs e)
        {
            StartNotepad();

            Process[] notepads = Process.GetProcessesByName("notepad");
            if (notepads.Length == 0) return;
            if (notepads[0] != null)
            {
                Clipboard.SetText(textBox1.Text);
                SendMessage(FindWindowEx(notepads[0].MainWindowHandle, new IntPtr(0), "Edit", null), 0x000C, 0, textBox1.Text);
            }
        }
        private static void StartNotepad() 
        {
            Process.Start("notepad.exe");
        }

When I run this code, stepping through debug, it runs fine, and the logic does what its intended to do (copy text to the instance of notepad). When I run it in release, nothing is copied to the instance of notepad. Any ideas why this is happening? No i'm not running multiple instances of notepad..

Mattaceten
  • 129
  • 2
  • 5
  • 14
  • Do you know what is not working or is failing? IS it finding the notepad process? Put some logging statements and see what is going on. You should be able to debug your code – dgorti Jan 13 '17 at 18:22
  • 1
    This rather begs the question of why you wouldn't just write out a text file and open it in notepad? – spender Jan 13 '17 at 18:22
  • I think this is a legit question, the issue lies within the SendMessage firing too quickly. I tried putting a Task.Delay in but it didn't help. – Muster Station Jan 13 '17 at 18:27
  • Why would I waste resources in writing out to a text file, when the code supplied works in debug, seems less efficent than what I am trying to accomplish. I don't know if the code is executing so fast that mainwindowhandle changes when its supposed to be sent, and that when in debug it has time to figure itself out. Just guessing here. – Mattaceten Jan 13 '17 at 18:28
  • Musters, I tried that as well. Thank you. – Mattaceten Jan 13 '17 at 18:29
  • dgorti, I stored the windowhandle into a intptr variable, and compared that variable with the one that is returned from findwindowex and they are the same in debug. when i finish stepping through the text is written to the notepad – Mattaceten Jan 13 '17 at 18:30
  • Check out: http://stackoverflow.com/questions/39756865/c-sharp-im-unable-to-get-sendmessage-to-send-a-message-to-a-notepad-window – Muster Station Jan 13 '17 at 18:39

3 Answers3

2

You need wait until the process is started, then send the text:

    [DllImport("user32.dll", EntryPoint = "FindWindowEx")]
    public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
    [DllImport("User32.dll")]
    public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, string lParam);

    private void btnCopyToNotepad_Click(object sender, EventArgs e)
    {
        StartNotepad();

        Process[] notepads = null;
        while (notepads == null || notepads.Length == 0)
        {
            notepads = Process.GetProcessesByName("notepad");   
            Thread.Sleep(500);
        }

        if (notepads.Length == 0) return;
        if (notepads[0] != null)
        {
            Clipboard.SetText(textBox1.Text);
            SendMessage(FindWindowEx(notepads[0].MainWindowHandle, new IntPtr(0), "Edit", null), 0x000C, 0, textBox1.Text);
        }
    }
    private static void StartNotepad() 
    {
        Process.Start("notepad.exe");
    }
  • 1
    It would be weird to say I love you, so thank you. This is the best answer I can find on this entire website. Thank you too Musters for the assistance. I didn't anticipate the millisecond timing being off from when the code executes to the instance of notepad. Hope you guys enjoy your weekend. – Mattaceten Jan 13 '17 at 19:12
  • just for the record (for future viewers), there are other ways to do this much more simple, like `StreamWriter file2 = new StreamWriter(@"c:\file.txt", true);` obv this doesnt use the "notepad instance", just creates a txt file or appends to it if it already exists. – Ricardo Olivo Poletti Jan 13 '17 at 19:20
2

Everton Santos' version can paste contents into a wrong instance of Notepad. This happens whenever user has other Notepad windows open. Pasting into a wrong Notepad instance overwrites all prior contents of that window. Undo doesn't work and leads to loss of user's own data.

Here's a version that holds pointer to the correct Notepad instance:

[DllImport("user32.dll", EntryPoint = "FindWindowEx")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, string lParam);

private void btnCopyToNotepad_Click(object sender, EventArgs e)
{
    var notepad = Process.Start("notepad.exe");
    notepad.WaitForInputIdle();
    Clipboard.SetText(textBox1.Text);
    SendMessage(FindWindowEx(notepad.MainWindowHandle, new IntPtr(0), "Edit", null), 0x000C, 0, textBox1.Text);
}
PatMunits
  • 31
  • 4
0

Something re-usable maybe? BTW, this opens a new instance of notepad each time.

using System.Diagnostics;
using System.Runtime.InteropServices;

static class Notepad
{
    #region Imports
    [DllImport("user32.dll")]
    public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

    [DllImport("User32.dll")]
    private static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, string lParam);

    //this is a constant indicating the window that we want to send a text message
    const int WM_SETTEXT = 0X000C;
    #endregion


    public static void SendText(string text)
    {
        Process notepad = Process.Start(@"notepad.exe");
        System.Threading.Thread.Sleep(50);
        IntPtr notepadTextbox = FindWindowEx(notepad.MainWindowHandle, IntPtr.Zero, "Edit", null);
        SendMessage(notepadTextbox, WM_SETTEXT, 0, text);
    }
}
Brian
  • 221
  • 2
  • 2