別の C# アプリケーション (フォーム) が閉じようとしているときに、C# アプリケーションでイベントを受信したいと考えています。
どうすればこれを達成できますか? これはリフレクションで実行できますか?
編集:詳細な説明
私の元の質問はあまり具体的ではないことを認識しています。私の目標をより詳細に説明しようとします。
というわけで、応募は3件。Container、Placer、ToPlaceと名付けましょう。ContanerとPlacerを C# で開発しています。Placerは dll ですが、Containerは WinForm です。ToPlaceのソース コードにはアクセスできません。Containerには、 Placerから呼び出された SetParent を使用してToPlaceのメイン ウィンドウに配置するカスタム コントロールがあります。目標は、 Contanerアプリを閉じる前にToPlaceの親ウィンドウを復元するか、ToPlace に送信された WM_DESTROY メッセージ (またはその他のメッセージ) を除外することです。ToPlaceメイン ウィンドウ。最終的には、 Containerの終了時にToPlaceのメイン ウィンドウを破棄しないことが目標です。
Containerでカスタム コントロールの WndProc をオーバーライドしようとしましたが、子ウィンドウへのメッセージが親ウィンドウ経由で送信されません。
また、コンテナアプリにメッセージ フィルタをインストールしようとしましたが、これも成功しませんでした。
この質問を書く前の最後の試みは SetWindowsHookEx でしたが、フックを正常にインストールした後、フック プロシージャが呼び出されることはありません。おそらく、どこかで読んだところによると、フック関数はマネージ dll ではなく 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;
}
}
}