目录
应用需求
我们在运行一些 Windows 应用程序的时候,需要将其运行在窗体置顶的模式(使其它应用窗体无法遮挡在置顶应用窗体之上),并且进入全屏状态。本文将介绍如何使用 C# 来实现 WinForm 的全屏置顶的基本功能。
基本功能主要实现以下几点:
(1)改变WinForm的一些外观属性,包括无边框、最大化和置顶属性。
(2)屏蔽一些键盘操作,以阻止关闭应用程序或切换到其它的应用程序。基本可以屏蔽左右WIN菜单键、关闭窗口组合键(Alt+F4)、切换窗口组合键(Alt+Tab)、开始菜单键(Ctrl+Esc)。
设计
设计 CraneofficeWinLock 类,该类可以实现一些方法,自动设置 WinForm 的一些属性、屏蔽一些键盘操作,其主要设计如下表:
| 序号 | 名称 | 成员类型 | 类型 | 说明 |
| 1 | form | 属性 | System.Windows.Forms | 指定要自动设置属性的窗体 |
| 2 | OnKeyPress | 方法 | void | 处理屏蔽键盘操作的方法 |
| 3 | Start | 方法 | void | 主入口方法,启动程序,需要传递OnKeyPress方法句柄 |
4 | Stop | 方法 | void | 停止所有屏蔽操作 |
---|
范例运行环境
操作系统: Windows 11、Windows 10 、Windows 2019 Server
.net版本: .netFramework4.7.2 或以上
开发工具:VS2019 C#
运行设备:Microsoft Surface Pro
实现代码
核心代码
代码如下:
cs
public class CraneofficeWinLock
{
private const int WH_KEYBOARD_LL = 13; //键盘
public Form form = null;
private delegate int HookHandle(int nCode, int wParam, IntPtr lParam);
public delegate void ProcessKeyHandle(HookStruct param, out bool handle);
private static int _hHookValue = 0;
private HookHandle _KeyBoardHookProcedure;
[StructLayout(LayoutKind.Sequential)]
public class HookStruct
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
[DllImport("user32.dll")]
private static extern int SetWindowsHookEx(int idHook, HookHandle lpfn, IntPtr hInstance, int threadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern bool UnhookWindowsHookEx(int idHook);
[DllImport("user32.dll")]
private static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
private static extern int GetCurrentThreadId();
[DllImport("kernel32.dll")]
private static extern IntPtr GetModuleHandle(string name);
private IntPtr _hookWindowPtr = IntPtr.Zero;
public CraneofficeWinLock() { }
private static ProcessKeyHandle _clientMethod = null;
public void Start(ProcessKeyHandle clientMethod)
{
if (form != null)
{
form.WindowState = FormWindowState.Maximized;
form.FormBorderStyle = FormBorderStyle.None;
form.TopMost = true;
}
_clientMethod = clientMethod;
if (_hHookValue == 0)
{
_KeyBoardHookProcedure = new HookHandle(OnHookProc);
_hookWindowPtr = GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
_hHookValue = SetWindowsHookEx(
WH_KEYBOARD_LL,
_KeyBoardHookProcedure,
_hookWindowPtr,
0);
//如果设置钩子失败.
if (_hHookValue == 0) Stop();
}
}
public void Stop()
{
if (_hHookValue != 0)
{
bool ret = UnhookWindowsHookEx(_hHookValue);
if (ret) _hHookValue = 0;
}
}
private static int OnHookProc(int nCode, int wParam, IntPtr lParam)
{
if (nCode >= 0)
{
HookStruct hookStruct = (HookStruct)Marshal.PtrToStructure(lParam, typeof(HookStruct));
if (_clientMethod != null)
{
bool handle = false;
_clientMethod(hookStruct, out handle);
if (handle) return 1; //1:表示键盘,return 退出
}
}
return CallNextHookEx(_hHookValue, nCode, wParam, lParam);
}
public void OnKeyPress(CraneofficeWinLock.HookStruct hookStruct, out bool handle)
{
handle = false;
if (hookStruct.vkCode == 91) // 左win(开始菜单键)
{
handle = true;
}
if (hookStruct.vkCode == 92)// 右win
{
handle = true;
}
if (hookStruct.vkCode == (int)Keys.Escape && (int)Control.ModifierKeys == (int)Keys.Control)
{
handle = true;
}
if (hookStruct.vkCode == (int)Keys.F4 && (int)Control.ModifierKeys == (int)Keys.Alt)
{
handle = true;
}
if (hookStruct.vkCode == (int)Keys.Tab && (int)Control.ModifierKeys == (int)Keys.Alt)
{
handle = true;
}
if (hookStruct.vkCode == (int)Keys.F1)
{
handle = true;
}
Keys key = (Keys)hookStruct.vkCode;
}
}
调用示例
示例代码如下:
cs
private CodnHBuilder.CraneofficeWinLock _winlock = null;
private void Form1_Load(object sender, EventArgs e)
{
_winlock = new CodnHBuilder.CraneofficeWinLock();
_winlock.form = this;
_winlock.Start(_winlock.OnKeyPress);
}
小结
我们可以在退出代码中停止屏蔽的操作,如下代码:
cs
if (_winlock != null) _winlock.Stop();
Application.Exit();
另外,为防止一些其它未考虑的情况,比较懒,写了一个计时器(时长1000毫秒)代码,实时激活窗体的状态,以保持窗体永远在最上层,如下代码:
cs
private void timer1_Tick(object sender, EventArgs e)
{
this.Activate();
}
以上代码我们提供了一些基本操作相关的方法,这里仅作参考,欢迎大家评论指教!