I need to be able to control an external Qt application so that I can open a file in the application.
I have tried using Process to get the Window Handle and then via PInvoke using GetMenu, GetSubMenu and GetMenuItemID to get all the parameters for using SendMessage and "Click" on the open menu in the external application
This works perfectly if I try it with Notepad as the external app, but not with the actual application which is written using Qt.
I do get the Window handle but GetMenu returns 0.
I have this code
[DllImport("user32.dll")]
private static extern IntPtr GetMenu(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern IntPtr GetSubMenu(IntPtr hMenu, int nPos);
[DllImport("user32.dll")]
private static extern uint GetMenuItemID(IntPtr hMenu, int nPos);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
private void OpenButton_Click(object sender, EventArgs e)
{
OpenDocument("notepad", "test.doc");
}
public void OpenDocument(string windowTitle, string document)
{
IntPtr hWnd = GetWindow(windowTitle);
IntPtr hMenu = GetMenu(hWnd);
IntPtr hSubMenu = GetSubMenu(hMenu, 0); // File menu
uint menuItemId = GetMenuItemID(hSubMenu, 2); // Open
IntPtr ptr = SendMessage(hWnd, (uint)WM.COMMAND, (IntPtr)menuItemId, IntPtr.Zero);
}
private static IntPtr GetWindow(string windowTitle)
{
IntPtr hWnd = IntPtr.Zero;
Process[] processes = Process.GetProcesses();
foreach (Process p in processes)
{
if (p.MainWindowTitle.IndexOf(windowTitle, StringComparison.InvariantCultureIgnoreCase) > -1)
{
hWnd = p.MainWindowHandle;
break;
}
}
return hWnd;
}
How can I get the handles of the menu and submenu and the menuitemid from a Qt application?
// Anders
Related
I developed an add-on for SAP Business One, as a C# Windows Forms application.
In this add-on, using LoadLibraryEx, I load a native unmanaged DLL (correct me if I'm wrong) written in C++.
The add-on calls a method of the DLL, in this way:
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, LoadLibraryFlags dwFlags);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int _MyDllMethod();
//...
//load library
var handle = LoadLibraryEx(libPath, IntPtr.Zero, 0x00000008 /*LOAD_WITH_ALTERED_SEARCH_PATH*/);
//invoke method
Type delegateFunType = typeof(_MyDllMethod);
IntPtr funAddr = GetProcAddress(handle, delegateFunType.Name);
var fun = Convert.ChangeType(Marshal.GetDelegateForFunctionPointer(funAddr, delegateFunType), delegateFunType);
int result = fun.Invoke(); //now a window appears
This method opens a window with which the user interacts.
Everything working fine, except that such window starts minimized in the task bar, while I need it to appear in the forground as the active window. How can I acieve this?
Finally I found this hack: launching a parallel thread that looks for the window that will be opened by the DLL and bring it to the foreground with Windows API functions:
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, LoadLibraryFlags dwFlags);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int _MyDllMethod();
[DllImport("User32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(String lpClassName, String lpWindowName);
[DllImport("User32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("User32.dll")]
private static extern bool ShowWindow(IntPtr handle, int nCmdShow);
[DllImport("User32.dll")]
private static extern bool IsIconic(IntPtr handle);
[DllImport("User32.dll")]
private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);
private const int ALT = 0xA4;
private const int EXTENDEDKEY = 0x1;
private const int KEYUP = 0x2;
private const int SW_RESTORE = 9;
//...
//launch a parallel thread that looks for library window
//and brings it to the foreground
ThreadPool.QueueUserWorkItem(delegate {
bool windowFound = false;
int attempts = 0;
while (!windowFound && attempts < 10)
{
attempts++;
//check frequently
Thread.Sleep(200);
//look for the window using its class name
IntPtr handle = FindWindow("DllWindowClassName", null);
//check it is a running process
if (handle != IntPtr.Zero)
{
bool success = false;
//if window is minimized to icon
if (IsIconic(handle))
{
//then show it
success = ShowWindow(handle, SW_RESTORE);
}
//bring window to front
success = SetForegroundWindow(handle);
//once done, this thread can terminate
if (success)
{
windowFound = true;
}
else
{
//in case of failure, try this hack
//simulate a key press and release (hack for SetForegroundWindow to work)
keybd_event((byte)ALT, 0x45, EXTENDEDKEY | 0, 0);
keybd_event((byte)ALT, 0x45, EXTENDEDKEY | KEYUP, 0);
//bring window to front
success = SetForegroundWindow(handle);
//once done, this thread can terminate
if (success)
{
windowFound = true;
}
}
}
}
}, null);
//load library
var handle = LoadLibraryEx(libPath, IntPtr.Zero, 0x00000008 /*LOAD_WITH_ALTERED_SEARCH_PATH*/);
//invoke method
Type delegateFunType = typeof(_MyDllMethod);
IntPtr funAddr = GetProcAddress(handle, delegateFunType.Name);
var fun = Convert.ChangeType(Marshal.GetDelegateForFunctionPointer(funAddr, delegateFunType), delegateFunType);
int result = fun.Invoke(); //now a window appears
You can discover window class name using FindWindow, passing window title, and then with GetClassName. Class name is more reliable than the title, which can change with the language and in the time.
i'm trying to add a new MenuItem using DLL Fucntions imported of the user32.dll using DLLImort to a third party application out of my WPF app.
No I'd like to get the click event of the newly generated MenuItem. Any ideas?
Here's the code so far. I know there are functions of SetWindowHookEx or something else, but I'm stuck.
It's some test code and not bulletproofed..
public partial class MainWindow : Window
{
[DllImport("user32.dll")]
private static extern IntPtr GetMenu(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern IntPtr GetSubMenu(IntPtr hMenu, int nPos);
[DllImport("user32.dll")]
private static extern int GetMenuItemCount(IntPtr hMenu);
[DllImport("user32.dll")]
private static extern bool InsertMenuItem(IntPtr hMenu, uint uItem, bool
fByPosition, [In] ref MENUITEMINFO lpmii);
[DllImport("user32.dll")]
private static extern bool DrawMenuBar(IntPtr hWnd);
internal const UInt32 MIIM_FTYPE = 0x00000100;
internal const UInt32 MF_STRING = 0x00000000;
internal const UInt32 MF_OWNERDRAW = 0x00000100;
const uint MF_POPUP = 0x00000010;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern bool AppendMenu(IntPtr hMenu, MenuFlags uFlags, uint uIDNewItem, string lpNewItem);
[DllImport("user32.dll")]
static extern IntPtr CreatePopupMenu();
[Flags]
public enum MenuFlags : uint
{
MF_STRING = 0,
MF_BYPOSITION = 0x400,
MF_SEPARATOR = 0x800,
MF_REMOVE = 0x1000,
MF_POPUP = 0x00000010,
}
[StructLayout(LayoutKind.Sequential)]
struct MENUITEMINFO
{
public uint cbSize;
public uint fMask;
public uint fType;
public uint fState;
public uint wID;
public IntPtr hSubMenu;
public IntPtr hbmpChecked;
public IntPtr hbmpUnchecked;
public IntPtr dwItemData;
public string dwTypeData;
public uint cch;
public IntPtr hbmpItem;
// return the size of the structure
public static uint sizeOf
{
get { return (uint)Marshal.SizeOf(typeof(MENUITEMINFO)); }
}
}
public MainWindow()
{
InitializeComponent();
Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
createMenuEntry();
}
private void createMenuEntry()
{
Process[] proceses = Process.GetProcessesByName("spotify");
Process process = proceses.Where(e => e.MainWindowTitle == "Spotify").First();
IntPtr handle = process.MainWindowHandle;
IntPtr mainMenu = GetMenu(handle);
int mainMenuItemCount = GetMenuItemCount(mainMenu);
AppendMenu(mainMenu, MenuFlags.MF_STRING, 555, "TestEntry");
}
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
//HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
//source.AddHook(WndProc);
}
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
// Handle messages...
Debug.WriteLine((int)wParam);
if (((int)wParam == 555))
{
MessageBox.Show("Click");
}
return IntPtr.Zero;
}
}
Thanks for any ideas or suggestions in advance.
Your first step is to put down the C# and understand how the native menu API works. Start here: https://msdn.microsoft.com/en-us/library/windows/desktop/ms647553.aspx
I strongly recommend that you create a new C++ project and write a simple program to add a menu and respond to clicks.
The key information is found in the documentation I linked to, with my emphasis:
When the user chooses a command item, the system sends a command message to the window that owns the menu. If the command item is on the window menu, the system sends the WM_SYSCOMMAND message. Otherwise, it sends the WM_COMMAND message.
You need to intercept that message. I suspect that means to need to use a global WH_CALLWNDPROC hook. That's going to need an unmanaged DLL to implement the hook.
I am trying to use CoInternetSetFeatureEnabled API for blocking prompt dialog as it show below in application that hosts WebBrowser control, but it does not work. Updating registry does not work either, following MSDN - Internet Feature Controls (I..L). I am using IE9 on Win7 64 bit.
FEATURE_BLOCK_INPUT_PROMPTS Internet Explorer 7. Enable or disable the
pop-up blocker to show input prompt dialog boxes. Used pop-up blocker
to mitigate the risk of spoofing.
private const int FEATURE_BLOCK_INPUT_PROMPTS = 27;
[DllImport("urlmon.dll")]
[PreserveSig]
[return: MarshalAs(UnmanagedType.Error)]
public static extern int CoInternetSetFeatureEnabled(
int FeatureEntry,
[MarshalAs(UnmanagedType.U4)] int dwFlags,
bool fEnable);
public static int disableInputPrompts(bool state)
{
return CoInternetSetFeatureEnabled(
FEATURE_BLOCK_INPUT_PROMPTS, SET_FEATURE_ON_PROCESS, state);
}
Update Just have tried in WinXP with IE8 and this feature is working. Does it depends on something else?
Update According to msdn this feature is by default enabled in IE9 but it does not work. Clicking on "Try It" button in w3schools sample initiates the prompt dialog, is that a security bug?
By default, this feature is enabled for Internet Explorer and disabled for
applications hosting the WebBrowser Control.
Any working alternative on how to block prompt dialog in WebBrowser control?
Can this be done by implementing custom security manager IInternetSecurityManager?
The only option I have for now is to use SetWindowsHookEx, and is based on Suppressing Hosted WebBrowser Control Dialogs sample.
internal static class WindowsInterop
{
private const Int32 WM_COMMAND = 0x0111;
private const Int32 WM_INITDIALOG = 0x0110;
private const Int32 WM_SYSCOMMAND = 0x0112;
private const Int32 SC_CLOSE = 0xF060;
private static IntPtr _pWH_CALLWNDPROCRET = IntPtr.Zero;
private static HookProcedureDelegate _WH_CALLWNDPROCRET_PROC =
new HookProcedureDelegate(WindowsInterop.WH_CALLWNDPROCRET_PROC);
[DllImport("user32.dll")]
private static extern IntPtr SetWindowsHookEx(Int32 hooktype,
HookProcedureDelegate callback, IntPtr hMod, UInt32 dwThreadId);
[DllImport("user32.dll")]
private static extern IntPtr UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll")]
private static extern Int32 CallNextHookEx(IntPtr hhk, Int32 nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
private static extern Int32 GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern Int32 GetWindowText(IntPtr hWnd,
StringBuilder text, Int32 maxLength);
[DllImport("user32.dll", SetLastError = false)]
private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg,
IntPtr wParam, IntPtr lParam);
// Hook Types
private const Int32 WH_CALLWNDPROCRET = 12;
[StructLayout(LayoutKind.Sequential)]
private struct CWPRETSTRUCT
{
public IntPtr lResult;
public IntPtr lParam;
public IntPtr wParam;
public UInt32 message;
public IntPtr hwnd;
};
// Delegate for a WH_ hook procedure
private delegate Int32 HookProcedureDelegate(Int32 iCode,
IntPtr pWParam, IntPtr pLParam);
// Delegate for the EnumChildWindows method
private delegate Boolean EnumerateWindowDelegate(IntPtr pHwnd, IntPtr pParam);
// Add a Hook into the CALLWNDPROCRET notification chain
internal static void Hook()
{
if (WindowsInterop._pWH_CALLWNDPROCRET == IntPtr.Zero)
{
WindowsInterop._pWH_CALLWNDPROCRET = SetWindowsHookEx(
WH_CALLWNDPROCRET,
WindowsInterop._WH_CALLWNDPROCRET_PROC,
IntPtr.Zero,
(uint)AppDomain.GetCurrentThreadId());
}
}
// Remove the Hook into the CALLWNDPROCRET notification chain
internal static void Unhook()
{
if (WindowsInterop._pWH_CALLWNDPROCRET != IntPtr.Zero)
{
UnhookWindowsHookEx(WindowsInterop._pWH_CALLWNDPROCRET);
}
}
// Hook proceedure called by the OS when a message has been processed by the target Window
private static Int32 WH_CALLWNDPROCRET_PROC(Int32 iCode,
IntPtr pWParam, IntPtr pLParam)
{
if (iCode < 0)
return CallNextHookEx(WindowsInterop._pWH_CALLWNDPROCRET,
iCode, pWParam, pLParam);
CWPRETSTRUCT cwp = (CWPRETSTRUCT)
Marshal.PtrToStructure(pLParam, typeof(CWPRETSTRUCT));
Console.WriteLine(cwp.message);
if (cwp.message == WM_INITDIALOG)
{
// A dialog was initialised, find out what sort it was via it's Caption text
Int32 iLength = GetWindowTextLength(cwp.hwnd);
StringBuilder sb = new StringBuilder(iLength + 1);
GetWindowText(cwp.hwnd, sb, sb.Capacity);
var title = sb.ToString();
if (String.IsNullOrEmpty(title) == false &&
title.IndexOf("prompt", StringComparison.OrdinalIgnoreCase) >= 0)
{
// just close it
SendMessage(cwp.hwnd, WM_SYSCOMMAND, new IntPtr(SC_CLOSE), IntPtr.Zero);
return 1;
}
}
// Call the next hook in the chain
return CallNextHookEx(WindowsInterop._pWH_CALLWNDPROCRET, iCode, pWParam, pLParam);
}
}
How can I get the list of opened of folders, enumerate through it and minimize each folder programmatically?
At times some opened folders do steal focus from the tool when jumping from one form in the application to another. Preventing this is of high priority for our client. The customers are visually impaired people, so they access the machine only via screen readers. Minimizing other windows (folders) is not at all a problem, in fact a requirement.
I tried this:
foreach (Process p in Process.GetProcessesByName("explorer"))
{
p.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
}
As expected it did no good.
Update:
From the answers here, I tried this:
delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")]
static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);
static IEnumerable<IntPtr> EnumerateProcessWindowHandles(int processID)
{
List<IntPtr> handles = new List<IntPtr>();
EnumThreadDelegate addWindowHandle = delegate(IntPtr hWnd, IntPtr param)
{
handles.Add(hWnd);
return true;
};
foreach (ProcessThread thread in Process.GetProcessById(processID).Threads)
EnumThreadWindows(thread.Id, addWindowHandle, IntPtr.Zero);
return handles;
}
const int SW_MINIMIZED = 6;
[DllImport("user32.dll")]
static extern int ShowWindow(IntPtr hWnd, int nCmdShow);
private void button1_Click(object sender, EventArgs e)
{
foreach (IntPtr handle in EnumerateProcessWindowHandles(Process.GetProcessesByName("explorer")[0].Id))
ShowWindow(handle, SW_MINIMIZED);
}
This creates a whole lot of invisible explorer windows to be suddenly listed in the taksbar out of no where. I am bit noob in dealing with Windows API, so the code itself will actually help.
Please try this (the code is somewhat messy but for the purpose you should be able to go through it ;))
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Text;
using System.Globalization;
namespace WindowsFormsApplication20
{
static class Program
{
[STAThread]
static void Main()
{
foreach (IntPtr handle in EnumerateProcessWindowHandles(Process.GetProcessesByName("explorer")[0].Id))
{
SendMessage(handle, WM_SYSCOMMAND, SC_MINIMIZE, 0);
}
}
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
static string GetDaClassName(IntPtr hWnd)
{
int nRet;
StringBuilder ClassName = new StringBuilder(100);
//Get the window class name
nRet = GetClassName(hWnd, ClassName, ClassName.Capacity);
if (nRet != 0)
{
return ClassName.ToString();
}
else
{
return null;
}
}
delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")]
static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);
static IEnumerable<IntPtr> EnumerateProcessWindowHandles(int processID)
{
List<IntPtr> handles = new List<IntPtr>();
EnumThreadDelegate addWindowHandle = delegate(IntPtr hWnd, IntPtr param)
{
string className = GetDaClassName(hWnd);
switch (className)
{
case null:
break;
case "ExploreWClass":
handles.Add(hWnd);
break;
case "CabinetWClass":
handles.Add(hWnd);
break;
default:
break;
}
return true;
};
foreach (ProcessThread thread in Process.GetProcessById(processID).Threads)
EnumThreadWindows(thread.Id, addWindowHandle, IntPtr.Zero);
return handles;
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam);
const int WM_SYSCOMMAND = 274;
const int SC_MINIMIZE = 0xF020;
}
}
Best regards,
Żubrówka
//Create Instance Of Shell Class by referencing COM Library "Microsoft Shell Controls And Automation" -shell32.dll
Shell32.ShellClass objShell = new Shell32.ShellClass();
//Show Desktop
((Shell32.IShellDispatch4)objShell).ToggleDesktop();
Edit: to show your application (Activate or Maximize/Restore) after toggling actually turned out to be quite difficult:
I tried:
Application.DoEvents();
System.Threading.Thread.Sleep(5000);
Even overriding the WndProc didn't manage to capture the event:
private const Int32 WM_SYSCOMMAND = 0x112;
private const Int32 SC_MINIMIZE = 0xf020;
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_SYSCOMMAND)
{
if (m.WParam.ToInt32() == SC_MINIMIZE)
return;
}
base.WndProc(ref m);
}
So I suggest instead of Minimising all other windows, just stick yours on top during the operation, then once your finished turn off Always On Top:
[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
const UInt32 SWP_NOSIZE = 0x0001;
const UInt32 SWP_NOMOVE = 0x0002;
const UInt32 TOPMOST_FLAGS = SWP_NOMOVE | SWP_NOSIZE;
public static void MakeTopMost (IntPtr hWnd)
{
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS);
}
There is a less 'hacky' solution than the accepted answer available here: Minimize a folder
It's based on the Shell Objects for Scripting. Sample:
const int SW_SHOWMINNOACTIVE = 7;
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
static void MinimizeWindow(IntPtr handle)
{
ShowWindow(handle, SW_SHOWMINNOACTIVE);
}
//call it like:
foreach (IWebBrowser2 window in new Shell().Windows())
{
if (window.Name == "Windows Explorer")
MinimizeWindow((IntPtr)window.HWND);
}
The same thing can be achieved using the Internet Explorer Object Model
// add a reference to "Microsoft Internet Controls" COM component
// also add a 'using SHDocVw;'
foreach (IWebBrowser2 window in new ShellWindows())
{
if (window.Name == "Windows Explorer")
MinimizeWindow((IntPtr)window.HWND);
}
If you are willing to use p-invoke you can use EnumThreadWindows to enumerate all windows of a process. Then use ShowWindow to minimize them.
I know this is an old post, but here is a much shorter, simpler way in case people are still looking for a solution:
Using Windows API:
Declare a windows handle: (minimizes the calling executable)
HWND wHandle; //can be any scope - I use it in main
Call the following anywhere (depending on scope of wHandle):
wHandle = GetActiveWindow();
ShowWindow(wHandle, SW_SHOWMINNOACTIVE);
I'm trying to use SendMessage to Notepad, so that I can insert written text without making Notepad the active window.
I have done something like this in the past using SendText, but that required giving Notepad focus.
Now, first I'm retrieving the Windows handle:
Process[] processes = Process.GetProcessesByName("notepad");
Console.WriteLine(processes[0].MainWindowHandle.ToString());
I've confirmed it's the right handle for Notepad, the same shown within Windows Task Manager.
[DllImport("User32.dll", EntryPoint = "SendMessage")]
public static extern int SendMessage(int hWnd, int Msg, int wParam, int lParam);
From here, I haven't been able to get SendMessage to work in all my experimentation. Am I going in the wrong direction?
[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 button1_Click(object sender, EventArgs e)
{
Process [] notepads=Process.GetProcessesByName("notepad");
if(notepads.Length==0)return;
if (notepads[0] != null)
{
IntPtr child= FindWindowEx(notepads[0].MainWindowHandle, new IntPtr(0), "Edit", null);
SendMessage(child, 0x000C, 0, textBox1.Text);
}
}
WM_SETTEXT=0x000c
You first have to find the child window where the text is entered. You can do this by finding the child window with the window class "Edit".
Once you have that window handle, use WM_GETTEXT to get the text which is already entered, then modify that text (e.g., add your own), then use WM_SETTEXT to send the modified text back.
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);
}
}