当另一个 C# 应用程序(表单)即将关闭时,我想在我的 C# 应用程序中接收一个事件。
我怎样才能做到这一点?这可以用反射来完成吗?
编辑:详细说明
我意识到我最初的问题不是很具体。我将尝试更详细地描述我的目标。
所以我有3个应用程序。让我们将它们命名为Container、Placer和ToPlace。我正在用 C# 开发Contaner和Placer,Placer是一个 dll,而Container是一个 WinForm。我无权访问ToPlace的源代码。在Container中,我有一个自定义控件,我在ToPlace的主窗口中放置了从Placer调用的 SetParent 。目标是在关闭Contaner应用程序之前恢复ToPlace的父窗口,或者过滤掉发送到ToPlace主窗口。最终目标是在Container退出时不破坏ToPlace的主窗口。
我试图覆盖Container中自定义控件的 WndProc ,但是没有通过父窗口发送到子窗口的消息。
我还尝试在Container应用程序上安装消息过滤器,但这也没有成功。
我在写这个问题之前的最后一次尝试是 SetWindowsHookEx,但是在成功安装钩子后,钩子程序永远不会被调用。也许是因为,我在某处读到,钩子函数必须在 win32 dll 中,而不是在托管的。下一个尝试是使用 SetWinEventHook,我读到了这个,它更容易从 C# 中工作。
我尝试使用 SetWindowsHookEx 的代码如下,也许在 C# 互操作方面更有经验的人会看到一个错误并且可以让它工作:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace AppMonitor
{
public class AppMonitor
{
private const int WH_GETMESSAGE = 3;
private const int HC_ACTION = 0;
private const int PM_NOREMOVE = 0x0000;
private const int PM_REMOVE = 0x0001;
private const int WM_QUIT = 0x0012;
[DllImport("user32.dll")]
private static extern int SetWindowsHookEx(int idHook, GetMsgProcDelegate lpfn, int hMod, int dwThreadId);
[DllImport("user32.dll")]
private static extern bool UnhookWindowsHookEx(int hhk);
[DllImport("user32.dll")]
private unsafe static extern int CallNextHookEx(int hhk, int nCode, int wParam, void* lParam);
[DllImport("user32.dll")]
private static extern int GetWindowThreadProcessId(int hWnd, out int lpdwProcessId);
[DllImport("kernel32.dll")]
private static extern int GetLastError();
private struct Msg {
public int hwnd;
public int message;
public int wParam;
public int lParam;
public int time;
public int pt;
};
[DllImport("kernel32.dll")]
public static extern int LoadLibrary(string dllToLoad);
public AppMonitor()
{
}
private int hHook;
private int hMod;
public event EventHandler AppClosing;
private unsafe delegate int GetMsgProcDelegate(int code, int wParam, void* lParam);
private unsafe GetMsgProcDelegate m_dlgt;
private unsafe int GetMsgProc(int code, int wParam, void* lParam)
{
if (code != HC_ACTION || wParam != PM_REMOVE)
return CallNextHookEx(this.hHook, code, wParam, lParam);
Msg* msg = (Msg*)lParam;
//if (msg.message == WM_QUIT)
// OnAppClosing(new EventArgs());
return CallNextHookEx(this.hHook, code, wParam, lParam);
}
protected virtual void OnAppClosing(EventArgs e)
{
EventHandler h = AppClosing;
if (h != null)
{
h(this, e);
}
}
public unsafe bool setHook(int hWnd)
{
hMod = LoadLibrary("AppMonitor.dll"); //this dll
int procId = 0;
int threadId = GetWindowThreadProcessId(hWnd, out procId);
if (threadId == 0)
throw new System.Exception("Invalid thread Id");
m_dlgt = GetMsgProc;
this.hHook = SetWindowsHookEx(WH_GETMESSAGE, m_dlgt, hMod, threadId);
if (this.hHook == 0)
throw new System.Exception("Hook not successfull! Error code: " + GetLastError());
return this.hHook != 0;
}
public bool unSetHook()
{
bool result = false;
if (hHook != 0)
result = UnhookWindowsHookEx(hHook);
return result;
}
}
}