上面代码没有生效
时间: 2023-08-08 19:09:46 浏览: 58
非常抱歉,我的回答有误。在WinForm中,如果你想在点击窗体外面的任何地方时关闭模式窗体,你可以利用Win32 API的`SetWindowsHookEx`函数来实现。
以下是示例代码:
```csharp
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace WinFormDemo
{
public partial class MainForm : Form
{
private const int WH_MOUSE_LL = 14;
private const int WM_LBUTTONDOWN = 0x201;
private IntPtr _hookId = IntPtr.Zero;
private Action _hookAction;
public MainForm()
{
InitializeComponent();
this.Load += MainForm_Load;
this.FormClosing += MainForm_FormClosing;
}
private void MainForm_Load(object sender, EventArgs e)
{
// 注册全局鼠标钩子
_hookAction = () =>
{
if (NativeMethods.GetMessage(out NativeMethods.MSG msg, IntPtr.Zero, 0, 0) > 0)
{
if (msg.message == WM_LBUTTONDOWN)
{
IntPtr hWnd = NativeMethods.WindowFromPoint(msg.pt);
if (hWnd != IntPtr.Zero && hWnd != this.Handle && !NativeMethods.IsChild(this.Handle, hWnd))
{
this.Close();
}
}
NativeMethods.TranslateMessage(ref msg);
NativeMethods.DispatchMessage(ref msg);
}
};
_hookId = NativeMethods.SetWindowsHookEx(WH_MOUSE_LL, HookProc, IntPtr.Zero, 0);
}
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
// 卸载全局鼠标钩子
NativeMethods.UnhookWindowsHookEx(_hookId);
}
private IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0)
{
_hookAction();
}
return NativeMethods.CallNextHookEx(_hookId, nCode, wParam, lParam);
}
private static class NativeMethods
{
public const int HC_ACTION = 0;
public const int WM_MOUSEFIRST = 0x200;
public const int WM_MOUSELAST = 0x20A;
public struct POINT
{
public int x;
public int y;
}
public struct MSG
{
public IntPtr hwnd;
public uint message;
public IntPtr wParam;
public IntPtr lParam;
public uint time;
public POINT pt;
}
public delegate IntPtr HookProcDelegate(int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(int idHook, HookProcDelegate lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
public static extern int GetMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool TranslateMessage([In] ref MSG lpMsg);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr DispatchMessage([In] ref MSG lpmsg);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr WindowFromPoint(POINT Point);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool IsChild(IntPtr hWndParent, IntPtr hWnd);
}
}
}
```
在上述代码中,我们创建了一个`MainForm`类,并在其`Load`事件中注册全局鼠标钩子,以便在用户点击鼠标时能够检查是否需要关闭模式窗体。在`FormClosing`事件中,我们卸载全局鼠标钩子。
在`HookProc`方法中,我们调用了`_hookAction`来处理全局鼠标钩子事件。在该方法中,我们利用了`WindowFromPoint`函数来获取鼠标所在窗体的句柄,然后判断该句柄是否为当前模式窗体的句柄或其子窗体的句柄。如果不是,则关闭模式窗体。
由于我们在代码中使用了一些Win32 API函数,需要进行一些DllImport声明。