我正在创建一个使用连接到几个不同DLL的主项目的应用程序.从一个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");
}
Run Code Online (Sandbox Code Playgroud)
Tim*_*ery 11
public static extern int FindWindow(string lpClassName, String lpWindowName);
Run Code Online (Sandbox Code Playgroud)
为了找到窗口,您需要窗口的类名.这里有些例子:
C#:
const string lpClassName = "Winamp v1.x";
IntPtr hwnd = FindWindow(lpClassName, null);
Run Code Online (Sandbox Code Playgroud)
我用VB编写的程序示例:
hParent = FindWindow("TfrmMain", vbNullString)
Run Code Online (Sandbox Code Playgroud)
为了获得窗口的类名,你需要一个名为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
Run Code Online (Sandbox Code Playgroud)
通过打开(Microsoft Visual Studio目录)/Common/Tools/WINAPI/winapi32.txt,可以使用API查看器(或简单的文本编辑器,如记事本)找到这些内容.
如果有必要,接下来的两个参数是某些细节.在按某些键时,它们将精确指定要按哪个特定键.
C#示例,使用WM_SETTEXT设置"windowHandle"的文本:
x = SendMessage(windowHandle, WM_SETTEXT, new IntPtr(0), m_strURL);
Run Code Online (Sandbox Code Playgroud)
我用VB编写的程序中的更多示例,设置程序的图标(ICONBIG是一个常量,可以在winapi32.txt中找到):
Call SendMessage(hParent, WM_SETICON, ICON_BIG, ByVal hIcon)
Run Code Online (Sandbox Code Playgroud)
VB的另一个例子,按空格键(VK_SPACE是一个常量,可以在winapi32.txt中找到):
Call SendMessage(button%, WM_KEYDOWN, VK_SPACE, 0)
Call SendMessage(button%, WM_KEYUP, VK_SPACE, 0)
Run Code Online (Sandbox Code Playgroud)
VB发送一个按钮点击(左键向下,然后向上):
Call SendMessage(button%, WM_LBUTTONDOWN, 0, 0&)
Call SendMessage(button%, WM_LBUTTONUP, 0, 0&)
Run Code Online (Sandbox Code Playgroud)
不知道如何在.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);
}
Run Code Online (Sandbox Code Playgroud)
然后在您的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);
}
}
Run Code Online (Sandbox Code Playgroud)
请记住,我还没有汇编以上任何内容,因此可能需要进行一些调整。还请记住,警告您远离的其他答案SendMessage也在现场。如今,这并不是模块间通信的首选方式,通常来说,覆盖WndProc和使用将SendMessage/PostMessage意味着对Win32消息基础结构的工作原理有很好的了解。
但是,如果您想/需要走这条路线,我认为以上内容将带您朝正确的方向前进。
| 归档时间: |
|
| 查看次数: |
95951 次 |
| 最近记录: |