首页 > 其他分享 >调用 Magnification API 实现黑屏功能

调用 Magnification API 实现黑屏功能

时间:2024-05-16 18:29:37浏览次数:14  
标签:return UnmanagedType Magnification API static CallingConvention bool 黑屏

调用 Magnification API 实现 NVDA 屏幕阅读器的黑屏效果

[作者: 张赐荣]

前言

作为读屏软件的开发者,经常需要考虑如何帮助视力障碍者更好地使用计算机。一个常见需求是保护用户的屏幕隐私,避免在操作电脑期间被他人窥视。本文将详细讲解如何使用 Windows Magnification API 实现屏幕变暗功能,从而达到保护隐私的目的。

环境准备

首先,请确保你已经安装了 Visual Studio 或其他支持 C# 的开发环境。本教程将使用 C# 和 Windows Magnification API。

第一步:创建一个新的 Windows Forms 项目

  1. 打开 Visual Studio。
  2. 创建一个新的 Windows Forms 应用程序项目。

第二步:导入必要的命名空间和库

在项目中,我们需要导入一些命名空间和外部库以便使用 Windows Magnification API。

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

第三步:定义 Magnification API 的数据结构

Windows Magnification API 使用 MAGCOLOREFFECT 结构来定义颜色转换矩阵。我们需要在代码中定义这个结构。

[StructLayout(LayoutKind.Sequential)]
struct MAGCOLOREFFECT
{
// 将一个固定大小为25的数组按值进行封送。
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 25)]
    public float[] transform;
}

第四步:定义黑色转换效果

需要定义一个颜色转换矩阵,将所有颜色转换为黑色。

static MAGCOLOREFFECT TRANSFORM_BLACK = new MAGCOLOREFFECT()
{
    transform = new float[]
    {
        0, 0, 0, 0, 0,
        0, 0, 0, 0, 0,
        0, 0, 0, 0, 0,
        0, 0, 0, 1, 0,
        0, 0, 0, 0, 1
    }
};

第五步:导入 Magnification API 的函数

DllImport 属性导入 Magnification API 函数。

[DllImport("Magnification.dll", CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool MagInitialize();

[DllImport("Magnification.dll", CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool MagUninitialize();

[DllImport("Magnification.dll", CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool MagSetFullscreenColorEffect(ref MAGCOLOREFFECT pEffect);

[DllImport("Magnification.dll", CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool MagGetFullscreenColorEffect(out MAGCOLOREFFECT pEffect);

[DllImport("Magnification.dll", CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool MagShowSystemCursor([MarshalAs(UnmanagedType.Bool)] bool fShowCursor);

第六步:实现屏幕变暗功能

现在我们可以实现屏幕变暗功能了。以下是完整的 ScreenCurtain 类实现。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WinForms
{
	static class ScreenCurtain
	{
		[StructLayout(LayoutKind.Sequential)]
		struct MAGCOLOREFFECT
		{
			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 25)]
			public float[] transform;
		}

		static MAGCOLOREFFECT TRANSFORM_BLACK = new MAGCOLOREFFECT()
		{
			transform = new float[]
			{
				0, 0, 0, 0, 0,
				0, 0, 0, 0, 0,
				0, 0, 0, 0, 0,
				0, 0, 0, 1, 0,
				0, 0, 0, 0, 1
			}
		};

		[DllImport("Magnification.dll", CallingConvention = CallingConvention.StdCall)]
		[return: MarshalAs(UnmanagedType.Bool)] static extern bool MagInitialize();
		[DllImport("Magnification.dll", CallingConvention = CallingConvention.StdCall)]
		[return: MarshalAs(UnmanagedType.Bool)] static extern bool MagUninitialize();
		[DllImport("Magnification.dll", CallingConvention = CallingConvention.StdCall)]
		[return: MarshalAs(UnmanagedType.Bool)] static extern bool MagSetFullscreenColorEffect(ref MAGCOLOREFFECT pEffect);
		[DllImport("Magnification.dll", CallingConvention = CallingConvention.StdCall)]
		[return: MarshalAs(UnmanagedType.Bool)] static extern bool MagGetFullscreenColorEffect(out MAGCOLOREFFECT pEffect);
		[DllImport("Magnification.dll", CallingConvention = CallingConvention.StdCall)]
		[return: MarshalAs(UnmanagedType.Bool)] static extern bool MagShowSystemCursor([MarshalAs(UnmanagedType.Bool)] bool fShowCursor);

		public static bool Start()
		{
			if (!(MagInitialize() && MagSetFullscreenColorEffect(ref TRANSFORM_BLACK) && MagShowSystemCursor(false)))
			{
				MagUninitialize();
				return (false);
			}
			return (IsEnabled());
		}

		public static bool Stop()
		{
			return (MagUninitialize() && MagShowSystemCursor(true));
		}

		public static bool IsEnabled()
		{
			if (!MagInitialize())
			{
				throw new InvalidOperationException("Failed to initialize Magnification API.");
			}
			MagGetFullscreenColorEffect(out MAGCOLOREFFECT currentEffect);
			return AreEffectsEqual(currentEffect, TRANSFORM_BLACK);
		}

		private static bool AreEffectsEqual(MAGCOLOREFFECT effect1, MAGCOLOREFFECT effect2)
		{
			for (int i = 0; i < effect1.transform.Length; i++)
			{
				if (effect1.transform[i] != effect2.transform[i])
				{
					return false;
				}
			}
			return true;
		}
	}
}

第七步:测试屏幕变暗功能

在 Windows Forms 项目中,可以通过按钮或其他事件触发 ScreenCurtain.Start()ScreenCurtain.Stop() 方法,以测试屏幕变暗功能。例如:

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
    }

    private void btnStart_Click(object sender, EventArgs e)
    {
        if (ScreenCurtain.Start())
        {
            MessageBox.Show("屏幕遮罩已启用");
        }
        else
        {
            MessageBox.Show("屏幕遮罩启用失败");
        }
    }

    private void btnStop_Click(object sender, EventArgs e)
    {
        if (ScreenCurtain.Stop())
        {
            MessageBox.Show("屏幕遮罩已禁用");
        }
        else
        {
            MessageBox.Show("屏幕遮罩禁用失败");
        }
    }
}

在窗体上添加两个按钮,一个用于启动屏幕变暗功能,另一个用于停止屏幕变暗功能,并将其 Click 事件与上述方法关联。

参考资料

标签:return,UnmanagedType,Magnification,API,static,CallingConvention,bool,黑屏
From: https://www.cnblogs.com/netlog/p/18196472

相关文章

  • thusc&pkusc&apio游记
    thusc&pkusc&apio游记连打三场赛,真爽。明年可能就没这么爽了。5.10早上航班延误了,在家多睡了一会。我们学校有两个初二的去两个营,因为没有约。我是其中之一,因为我太菜了。syl要一次拿pku和thu的1=约了。飞机上看了下载的视频。下飞机后教练打车带我们去了酒店。然后下午太无......
  • 我发现了字节OpenApi接口的bug!
    本文记录我在对接字节旗下产品火山云旗下云游戏产品OpenApi接口文档时遇到的坑,希望能帮助大家(火山云旗下云游戏产品的文档坑很多,我算是从零到一都踩了一遍,特此记录,希望大家引以为鉴)。1.文档问题很经典的开局一张图,对接全靠问,这里给大家强调下,当要跟第三方产品对接时,一定要......
  • APIO 游记
    Day-3由于各种原因没报清北营,于是此时下午才坐绿皮火车出发。很久没做过绿皮火车了,有一种怀旧的感觉。但是车上旁边有人一直在打喷嚏,导致全程都不敢摘口罩,睡觉都戴着N95,一晚上没怎么睡。(可能也有原因是在脑子后面构造)吃饭也不敢在这吃,就溜到车厢连接处吃,很怕失手把饭盒翻了,......
  • nodejs学习07——API
    接口一、简介1.1接口是什么接口是前后端通信的桥梁简单理解:一个接口就是服务中的一个路由规则,根据请求响应结果接口的英文单词是API(ApplicationProgramInterface),所以有时也称之为API接口这里的接口指的是『数据接口』,与编程语言(Java,Go等)中的接口语法不同1.2......
  • 免费的天气接口api(腾讯)
    请求URL:https://wis.qq.com/weather/common请求方式:GET参数:参数名必选类型说明source是stringpcweather_type是stringobserveprovince是string省city是string市county是string县 请求示例https://wis.qq.com/weather/common?source=pc&weather_typ......
  • 使用Docker Desktop部署Apache APISIX
    使用DockerDesktop部署ApacheAPISIX说明测试系统:Windows11专业版23H2Docker:DockerDesktopv4.29.0+关于路径,“/e/Soft/conf/apisix/conf/config.yaml”代表windows系统下的文件“E:\Soft\conf\apisix\conf\config.yaml”Windows使用PowerShell运行Docker的Run......
  • apisix~authz-keycloak插件介绍
    参考:https://apisix.apache.org/docs/apisix/plugins/authz-keycloak/kc插件源码梳理及原理说明如果只是进行keycloak颁发的token进行校验(签名校验和有效期校验),那么我们可以使用jwt-auth这个插件实现,并且已经对这个插件进行二次开发,支持jwt内容解析与向下请求头的传递。作用......
  • 营业执照识别接口:通过API实现营业执照识别功能
      营业执照识别接口是一种通过API实现的功能,可以对不同版式的营业执照进行识别,提取其中的证件编号、社会信用代码、单位名称、地址、法人、类型、成立日期、有效日期、经营范围等关键字段。这个功能在很多场景下都可以发挥作用,比如在企业注册、信用查询、合作伙伴选择等方面......
  • 【Azure Developer】如何通过Azure Portal快速获取到对应操作的API并转换为Python代码
    问题描述对于Azure资源进行配置操作,门户上可以正常操作。但是想通过Python代码实现,这样可以批量处理。那么在没有SDK的情况下,是否有快速办法呢? 问题解答当然可以,AzurePortal上操作的所有资源都是通过RESTAPI来实现的,所以只要找到正确的API,就可以通过浏览器中抓取到的请求B......
  • 02快速上手drf、CBV源码分析、APIVIEW源码分析
    快速上手drf、CBV源码分析、APiview源码分析一、快速上手drf【1】安装drfpipinstalldjangorestframework注意:安装时不指定版本,默认下载最新版本每个版本有对应的解释器版本和django限制要求,下载时官网查看一下如果django版本是3以下,drf最新跟django3以下版本不兼容版......