Send Message in C#

Send Message in C#

You don't need to send messages.

Add an event to the one form and an event handler to the other. Then you can use a third project which references the other two to attach the event handler to the event. The two DLLs don't need to reference each other for this to work.

How to send message from C# to C++ (MESSAGE ONLY WINDOW) using SendMessage (WM_COPYDATA)?

First of all, Process.Handle is the handle of the process instead of the window.

Secondly, since your main.exe is a console application and it only has a console window, you can only get the handle of the console window by using MainWindowHandle. However, the console does not belong to the main.exe, So you cannot use PeekMessage to handle the message sent to the console window. Console windows are owned by the console subsystem, csrss.exe(see https://stackoverflow.com/a/28248281/10611792). You should create your own window for your C++ app, or create a Message-Only window. Then, you can use FindWindow to get the window handle in C#:

public partial class Form1 : Form
{
[DllImport("user32.dll")]
static extern long SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

[DllImport("user32.dll",CharSet = CharSet.Unicode)]
static extern IntPtr FindWindow(string classname, string windowname);
...
private void Form1_Load(object sender, EventArgs e)
{
...
Thread.Sleep(3000);

string message = "This is a test";
IntPtr hWnd = FindWindow("MyClass", "MyTitle");
if (hWnd == IntPtr.Zero)
{
MessageBox.Show("couldn't find the process");
}
else
{
COPYDATASTRUCT cds;
cds.dwData = 1;
cds.cbData = message.Length + 1;
cds.lpData = Marshal.StringToHGlobalAnsi(message);
IntPtr cdsBuffer = IntPtrAlloc(cds);
SendMessage(hWnd, WM_COPYDATA, IntPtr.Zero, cdsBuffer);
IntPtrFree(cds.lpData);
IntPtrFree(cdsBuffer);
}

}
}

C++:

LRESULT CALLBACK WindProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
if (Msg == WM_COPYDATA)
{
PCOPYDATASTRUCT data = (PCOPYDATASTRUCT)lParam;
MessageBoxA(hWnd, (LPSTR)data->lpData, "info", 0); // The character set depends on the characters you send
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
int main() {

WNDCLASSEX wcx = { 0 };
wcx.cbSize = sizeof(WNDCLASSEX);
wcx.lpfnWndProc = WindProc;
wcx.hInstance = GetModuleHandle(NULL);
wcx.lpszClassName = TEXT("MyClass");
RegisterClassEx(&wcx);
HWND hWnd = CreateWindowEx(0, TEXT("MyClass"), TEXT("MyTitle"), 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);

MSG msg;
for (int i = 0; i < 1000; i++)
{
std::cout << "working" << std::endl;
Sleep(2 * 1000);
if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
break;
}
}

int x;
cout << "got it!";
cin >> x;
return 0;
}

Also Note that use SendMessage instead of PostMessage.

In addition, you can also choose other IPC methods.

SendMessage, Trying to send F4

The second parameter is the msg not the key, as: keyup (0x100) or keydown (0x101)

The third parameter is the key as 0x73 (F4)

SendMessage(whandle, 0x100, 0x73, IntPtr.Zero);
SendMessage(whandle, 0x101, 0x73, IntPtr.Zero);

SendMessage to Notepad++ in C#

You are running into a string encoding issue. Strings in .NET are UTF-16 little-endian strings. The string "Send" in UTF-16 is actually the bytes S{0}e{0}n{0}d{0}{0}{0}. Your declaration of SendMessage is using the ANSI string method. There are a number of ways to solve this. Here's one: Explicitly use the UTF-16 form by changing SendMessage to SendMessageW.

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

c# i'm unable to get SendMessage to send a message to a notepad window

Much credit to Remy. After some troubleshooting I ended up finding the code worked so it's a mystery why I was finding it didn't.

A good troubleshooting step is to try moving the window around with nircmd, so you know you have the handle.

To get the handle of the window, you can use nirsoft winlister, or winspector

You can use nircmd commands like nircmd win close handle 0x00230632 change that 0x00230632 to whatever you find the handle to be. Or better don't close it(otherwise you'll have to reopen it and the new window will have a new handle), so a command like nircmd win move handle 0x00B917AE 80 10 100 100 So you know the handle is right, regardless of any issue with the code.

Winspector also shows the child of the notepad window

Sample Image

Going back to the C# code, you can

skip the child and try writing into the parent, it should write into the title of the window

Try using SendMessage to specify a window directly. You write the handle in decimal rather than hex. e.g. if the handle is 3479948 then

e.g. SendMessage(new IntPtr(3479948), WM_SETTEXT, IntPtr.Zero, "abcdee");

You can also check that notepads[0].MainWindowHandle is picking up the correct value.. the handle shown in winspector.

You can look at the IntPtr child = FindWindowEx(...) line, make sure the 'child' is picking up the child handle.

You can try writing to that one directly with SendMessage. e.g. SendMessage(new IntPtr(1234567), WM_SETTEXT, IntPtr.Zero, "abcdee"); // (if winspector shows the child window to be that handle).



Related Topics



Leave a reply



Submit