用C#发送消息

我正在创建一个使用连接到几个不同DLL的主项目的应用程序。 从一个DLL窗口我需要能够打开另一个窗口,但DLL不能互相引用。

有人建议我在第一个DLL中使用sendmessage函数,并在主程序中有一个监听器,它将该消息定向到相应的DLL以打开它的窗口。

但是我对sendmessagefunction一点都不熟悉,而且我正在从网上找到的信息中把很多东西拼凑起来。

如果有人能告诉我使用sendmessage函数的正确方法(如果有的话),也许还有一个听众如何捕获那些令人惊奇的消息。 这是我到目前为止所获得的一些代码,我不确定我是否正朝着正确的方向前进。

[DllImport("user32.dll")] public static extern int FindWindow(string lpClassName, String lpWindowName); [DllImport("user32.dll")] public static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam); public void button1_Click(object sender, EventArgs e) { int WindowToFind = FindWindow(null, "Form1"); } 

您不需要发送消息。

将事件添加到一个表单,将事件处理程序添加到另一个表单。 然后,您可以使用引用其他两个的第三个项目将事件处理程序附加到事件。 这两个DLL不需要相互引用就可以工作。

 public static extern int FindWindow(string lpClassName, String lpWindowName); 

为了找到窗口,您需要窗口的类名。 这里有些例子:

C#:

 const string lpClassName = "Winamp v1.x"; IntPtr hwnd = FindWindow(lpClassName, null); 

我用VB编写的程序示例:

 hParent = FindWindow("TfrmMain", vbNullString) 

为了获得窗口的类名,你需要一个名为Win Spy的东西

获得窗口句柄后,可以使用SendMessage(IntPtr hWnd,int wMsg,IntPtr wParam,IntPtr lParam)函数向其发送消息。

hWnd,这里是FindWindow函数的结果。 在上面的例子中,这将是hwnd和hParent。 它告诉SendMessage函数将消息发送到哪个窗口。

第二个参数wMsg是一个常量,表示您要发送的消息类型 。 消息可能是键击(例如,将“输入键”或“空格键”发送到窗口),但它也可能是关闭窗口的命令(WM_CLOSE),一个改变窗口的命令(隐藏它,显示它,最小化它,改变它的标题等),窗口内的信息请求(获取标题,在文本框中获取文本等),等等。 一些常见的例子包括:

 Public Const WM_CHAR = &H102 Public Const WM_SETTEXT = &HC Public Const WM_KEYDOWN = &H100 Public Const WM_KEYUP = &H101 Public Const WM_LBUTTONDOWN = &H201 Public Const WM_LBUTTONUP = &H202 Public Const WM_CLOSE = &H10 Public Const WM_COMMAND = &H111 Public Const WM_CLEAR = &H303 Public Const WM_DESTROY = &H2 Public Const WM_GETTEXT = &HD Public Const WM_GETTEXTLENGTH = &HE Public Const WM_LBUTTONDBLCLK = &H203 

通过打开(Microsoft Visual Studio目录)/Common/Tools/WINAPI/winapi32.txt,可以使用API​​查看器(或简单的文本编辑器,如记事本)找到它们。

如果必要,接下来的两个参数是某些细节。 在按某些键时,它们将精确指定要按哪个特定键。

C#示例,使用WM_SETTEXT设置“windowHandle”的文本:

 x = SendMessage(windowHandle, WM_SETTEXT, new IntPtr(0), m_strURL); 

我用VB编写的程序中的更多示例,设置程序的图标(ICONBIG是一个常量,可以在winapi32.txt中找到):

 Call SendMessage(hParent, WM_SETICON, ICON_BIG, ByVal hIcon) 

VB的另一个例子,按空格键(VK_SPACE是一个常量,可以在winapi32.txt中找到):

 Call SendMessage(button%, WM_KEYDOWN, VK_SPACE, 0) Call SendMessage(button%, WM_KEYUP, VK_SPACE, 0) 

VB发送一个按钮点击(左键向下,然后向上):

 Call SendMessage(button%, WM_LBUTTONDOWN, 0, 0&) Call SendMessage(button%, WM_LBUTTONUP, 0, 0&) 

不知道如何在.DLL中设置监听器,但这些示例应该有助于理解如何发送消息。

你快到了。 (注意FindWindow声明的返回值的变化)。 在这种情况下,我建议使用RegisterWindowMessage ,这样您就不必担心WM_USER的来龙去脉了。

 [DllImport("user32.dll")] public static extern IntPtr FindWindow(string lpClassName, String lpWindowName); [DllImport("user32.dll")] public static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)] static extern uint RegisterWindowMessage(string lpString); public void button1_Click(object sender, EventArgs e) { // this would likely go in a constructor because you only need to call it // once per process to get the id - multiple calls in the same instance // of a windows session return the same value for a given string uint id = RegisterWindowMessage("MyUniqueMessageIdentifier"); IntPtr WindowToFind = FindWindow(null, "Form1"); Debug.Assert(WindowToFind != IntPtr.Zero); SendMessage(WindowToFind, id, IntPtr.Zero, IntPtr.Zero); } 

然后在你的Form1类中:

 class Form1 : Form { [DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)] static extern uint RegisterWindowMessage(string lpString); private uint _messageId = RegisterWindowMessage("MyUniqueMessageIdentifier"); protected override void WndProc(ref Message m) { if (m.Msg == _messageId) { // do stuff } base.WndProc(ref m); } } 

请记住,我没有编译上面的任何内容,因此可能需要进行一些调整。 另外请记住,警告您远离SendMessage其他答案都是正确的。 它现在并不是模块间通信的首选方式,而且从根本上讲,覆盖WndProc并使用SendMessage/PostMessage意味着很好地理解Win32消息基础结构的工作原理。

但是如果你想要/需要走这条路线,我认为上面会让你朝着正确的方向前进。

使用发送消息听起来不是一个好主意。 我认为你应该尝试解决DLL无法互相引用的问题……

其他一些选择:

共同大会

创建另一个具有一些可由程序集实现的公共接口的程序集。

reflection

这有各种各样的警告和缺点,但您可以使用reflection来实例化/与表单通信。 这既慢又动态(在编译时没有对此代码进行静态检查)。

以Mark Byers为基础回答。

第三个项目可以是一个WCF项目,作为Windows服务托管。 如果所有程序都听取了该服务,则一个应用程序可以调用该服务。 该服务将消息传递给所有侦听客户端,如果合适,它们可以执行操作。

好的WCFvideo在这里 – http://msdn.microsoft.com/en-us/netframework/dd728059