用 C# 发送消息
我正在创建一个应用程序,该应用程序使用连接到多个不同 DLL 的主项目。我需要能够从一个 DLL 窗口打开另一个窗口中的窗口,但 DLL 无法相互引用。
有人建议我在第一个 DLL 中使用 sendmessage 函数,并在主程序中设置一个侦听器,将该消息定向到适当的 DLL 以打开它的窗口。
然而,我对 sendmessage 函数根本不熟悉,并且很难从网上找到的信息将内容拼凑在一起。
如果有人可以请告诉我使用 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");
}
I'm creating an application that uses a main project that is connected to several different DLLs. From one DLL window I need to be able to open a window in another but the DLL's can't reference each other.
It was suggested to me to use the sendmessage function in the first DLL and have a listener in the main program that directs that message to the appropriate DLL to open it's window.
However I'm not familiar at all with the sendmessage function and am having a lot of diffculty piecing things together from information I'm finding online.
If someone could please show me the correct way (if there is any) to use the sendmessage function and maybe how a listener captures that message that would be amazing. Here is some of the code I've got so far I'm not sure if I'm heading in the right direction.
[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");
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
为了找到窗口,您需要窗口的类名。以下是一些示例:
C#:
我用 VB 编写的程序示例:
为了获取窗口的类名,您需要名为 Win Spy
获得窗口句柄后,您可以使用
SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam) 向其发送消息)
函数。这里的
hWnd
是FindWindow
函数的结果。在上面的示例中,这将是hwnd
和hParent
。它告诉SendMessage
函数将消息发送到哪个窗口。第二个参数
wMsg
是一个常量,表示您要发送的消息的TYPE。该消息可能是击键(例如,向窗口发送“回车键”或“空格键”),但也可能是关闭窗口的命令(WM_CLOSE
)、更改窗口(隐藏窗口、显示窗口、最小化窗口、更改标题等)、请求窗口内的信息(获取标题、获取文本框中的文本等),等等。一些常见示例如下:可以使用 API 查看器(或简单的文本编辑器,例如记事本)打开
(Microsoft Visual Studio Directory)/Common/Tools/WINAPI/winapi32.txt
。接下来的两个参数是某些细节(如果需要的话)。在按下某些键时,它们会准确指定要按下哪个特定键。
C# 示例,使用
WM_SETTEXT
设置windowHandle
的文本:来自我用 VB 编写的程序的更多示例,设置程序的图标 (
ICON_BIG 是一个常量,可以在
winapi32.txt
中找到):另一个来自 VB 的例子,按空格键(
VK_SPACE
是一个常量,可以在winapi32.txt
):VB 发送按钮单击(左键按下,然后向上):
不知道如何在 .DLL 中设置侦听器,但这些示例应该有助于理解如何发送消息。
In order to find the window, you need the class name of the window. Here are some examples:
C#:
Example from a program that I made, written in VB:
In order to get the class name of a window, you'll need something called Win Spy
Once you have the handle of the window, you can send messages to it using the
SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam)
function.hWnd
, here, is the result of theFindWindow
function. In the above examples, this will behwnd
andhParent
. It tells theSendMessage
function which window to send the message to.The second parameter,
wMsg
, is a constant that signifies the TYPE of message that you are sending. The message might be a keystroke (e.g. send "the enter key" or "the space bar" to a window), but it might also be a command to close the window (WM_CLOSE
), a command to alter the window (hide it, show it, minimize it, alter its title, etc.), a request for information within the window (getting the title, getting text within a text box, etc.), and so on. Some common examples include the following:These can be found with an API viewer (or a simple text editor, such as notepad) by opening
(Microsoft Visual Studio Directory)/Common/Tools/WINAPI/winapi32.txt
.The next two parameters are certain details, if they are necessary. In terms of pressing certain keys, they will specify exactly which specific key is to be pressed.
C# example, setting the text of
windowHandle
withWM_SETTEXT
:More examples from a program that I made, written in VB, setting a program's icon (
ICON_BIG
is a constant which can be found inwinapi32.txt
):Another example from VB, pressing the space key (
VK_SPACE
is a constant which can be found inwinapi32.txt
):VB sending a button click (a left button down, and then up):
No idea how to set up the listener within a .DLL, but these examples should help in understanding how to send the message.
你快到了。 (注意 FindWindow 声明的返回值的变化)。我建议在此使用 RegisterWindowMessage这样您就不必担心 WM_USER。
然后在您的 Form1 类中:
请记住,我还没有编译上述任何内容,因此可能需要进行一些调整。
另请记住,警告您远离
SendMessage
的其他答案是正确的。这不是当今模块间通信的首选方式,一般来说,覆盖WndProc
并使用SendMessage/PostMessage
意味着很好地理解 Win32 消息基础结构 有效。但如果你想/需要走这条路,我认为上述内容会让你朝着正确的方向前进。
You are almost there. (note change in the return value of FindWindow declaration). I'd recommend using RegisterWindowMessage in this case so you don't have to worry about the ins and outs of WM_USER.
And then in your Form1 class:
Bear in mind I haven't compiled any of the above so some tweaking may be necessary.
Also bear in mind that other answers warning you away from
SendMessage
are spot on. It's not the preferred way of inter module communication nowadays and genrally speaking overriding theWndProc
and usingSendMessage/PostMessage
implies a good understanding of how the Win32 message infrastructure works.But if you want/need to go this route I think the above will get you going in the right direction.
您不需要发送消息。
将事件添加到一个表单和一个事件处理程序到另一个。然后,您可以使用引用其他两个项目的第三个项目将事件处理程序附加到事件。这两个 DLL 不需要互相引用即可工作。
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.
其他一些选项:
通用程序集
创建另一个程序集,该程序集具有一些可由程序集实现的通用接口。
反射
这有各种警告和缺点,但您可以使用反射来实例化表单/与表单进行通信。这既慢又运行时动态(在编译时没有静态检查此代码)。
Some other options:
Common Assembly
Create another assembly that has some common interfaces that can be implemented by the assemblies.
Reflection
This has all sorts of warnings and drawbacks, but you could use reflection to instantiate / communicate with the forms. This is both slow and runtime dynamic (no static checking of this code at compile time).
以马克·拜尔斯的回答为基础。
第三个项目可能是一个 WCF 项目,作为 Windows 服务托管。如果所有程序都侦听该服务,则一个应用程序可以调用该服务。该服务将消息传递给所有侦听客户端,并且它们可以在合适的情况下执行操作。
这里有精彩的 WCF 视频 - http://msdn.microsoft.com/en-us/netframework /dd728059
Building on Mark Byers's answer.
The 3rd project could be a WCF project, hosted as a Windows Service. If all programs listened to that service, one application could call the service. The service passes the message on to all listening clients and they can perform an action if suitable.
Good WCF videos here - http://msdn.microsoft.com/en-us/netframework/dd728059