C# WPF 实现鼠标固定在指定范围内运动
一.背景:
需要实现带有三个屏幕,三个屏幕分别显示窗体,但鼠标只能在主窗体中运动,不能移动到其他的两个附屏中。
二.实现:
具体实现使用的是user32.dll下的GetWindowRect(int hwnd, ref RECT lpRect)函数。
参考百度百科:https://baike.baidu.com/item/ClipCursor
ClipCursor,函数名。该函数把鼠标限制在屏幕上的一个矩形区域内,如果调用SetCursor或用鼠标设置的一个随后的鼠标位置在该矩形区域的外面,则系统自动调整该位置以保持鼠标在矩形区域之内。
函数原型
BOOL ClipCursor(CONST RECT * lpRect);
IpRect:指向RECT结构的指针,该结构包含限制矩形区域左上角和右下角的屏幕坐标,如果该指针为NULL(空),则鼠标可以在屏幕的任何区域移动。
返回值
如果成功,返回值非零;如果失败,返回值为零。若想获得更多错误信息,请调用GetLastError。
备注
1.光标是一个共享资源,如果一个应用控制了鼠标,在将控制转向另一个应用之前,必须要使用ClipCursor来释放鼠标,该调用过程必须具有对窗口的WINSTA_WRITEATTRIBUTES访问权。
2.此函数为api函数,调用时要函数声明:Private Declare Function ClipCursor Lib "user32" (lpRect As Any) As Long
速查:Windows NT:3.1及以上版本;Windows:95及以上版本;Windows CE:不支持;头文件:winuser.h;库文件;user32.lib。
三.代码
我主要实现的是限定屏幕,所以提供的接口直接和屏幕有关,其他的具体情况具体分析。
using System;
using System.Linq;
using System.Runtime.InteropServices;
namespace Tool.ClipCursor
{
class ClipCursorHelper
{
[DllImport("user32.dll")]
static extern bool ClipCursor(ref RECT lpRect);
[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "GetWindowRect")]
extern static int GetWindowRect(int hwnd, ref RECT lpRect);
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
public RECT(Int32 left, Int32 top, Int32 right, Int32 bottom)
{
Left = left;
Top = top;
Right = right;
Bottom = bottom;
}
}
/// <summary>
/// 设置鼠标显示在主屏范围内
/// </summary>
/// <returns></returns>
public static bool SetCursorInPrimaryScreen()
{
System.Windows.Forms.Screen screen = System.Windows.Forms.Screen.AllScreens.OrderBy(t => t.WorkingArea.X).First();
RECT rect = new RECT(screen.Bounds.X, screen.Bounds.Y, screen.Bounds.Right+screen.Bounds.X, screen.Bounds.Bottom);
return ClipCursor(ref rect);
}
/// <summary>
/// 恢复鼠标显示,可以所以屏幕的任何位置
/// </summary>
/// <returns></returns>
public static bool Default()
{
System.Windows.Forms.Screen screen = System.Windows.Forms.Screen.AllScreens.OrderByDescending(t => t.WorkingArea.X).First();
RECT rect = new RECT(0, 0, screen.Bounds.Right+ screen.Bounds.X, screen.Bounds.Bottom);
return ClipCursor(ref rect);
}
}
}
四.遇到的问题
1、在调试过程中发现每次窗体切换(如生成新的窗体),鼠标的范围又都返回到可以在任意位置使用,所以在每当生成窗体的时候都需要调一下上面的接口;
2、当使用Alt+Tab切换任务后,鼠标的限定范围也会不起作用,目前还无法解决;
但目前已经满足需要,网友知道如何避免上述两种问题的望交流学习。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
WPF C# 多屏情况下,实现窗体显示到指定的屏幕内
原文: WPF C# 多屏情况下,实现窗体显示到指定的屏幕内 针对于一个程序,需要在两个显示屏上显示不同的窗体,(亦或N个显示屏N个窗体),可以使用如下的方式实现。 主要涉及到的:System.Windows.Forms.Screen.AllScreens和WindowState属性 1、首先Window.WindowState属性,其类型是一个枚举,若想在指定的屏幕上显示WindowState属性不能为Maximized,当为Maximized时窗体会显示在主屏上。 namespaceSystem.Windows { //指定是最小化、最大化还是还原窗口 public enum WindowState { //还原窗口。 Normal = 0, //最小化窗口。 Minimized = 1, //最大化窗口。 Maximized = 2 } } 2、System.Windows.Forms.Screen.AllScreens属性提供获取获取系统上所有显示器的数组,因此我们通过此属性获取各个屏幕的参数,从而使用Window.Top和Window.Left设置偏移参数实现窗体显示...
- 下一篇
过期的对象引用
消除过期的对象引用 修正前 public class Stack { public Object[] elements; public int size = 0; private static final int DEALULT_VLAUE = 16; public Stack() { elements = new Object[DEALULT_VLAUE]; } public void push(Object e) { ensureCapacity(); elements[size++] = e; } public Object pop() { if (size == 0) { throw new RuntimeException(); } return elements[--size]; } private void ensureCapacity() { if (elements.length == size) { elements = Arrays.copyOf(elements, 2 * size + 1); } } } 这段程序中并没有很明显的错误.无论如何测试,它都会成功通...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Windows10,CentOS7,CentOS8安装Nodejs环境
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS8安装Docker,最新的服务器搭配容器使用
- 设置Eclipse缩进为4个空格,增强代码规范
- CentOS7安装Docker,走上虚拟化容器引擎之路