大家好,又见面了,我是你们的朋友全栈君。
背景
这周末闲来无事,整理了下虚拟显示器的源码,发现有几个项目都用到了,但是使用的功能不尽相同: (1)最简单的运用仅仅是需要显示器的拔插; (2)稍微复杂一点的是需要设置显示器的分辨率,包括标准的分辨率,如19201080,还包括非标准的分辨率,如1120900; (3)再复杂一点的需要设置显示器名称、刷新频率、获取虚拟显示器屏幕图像信息。 再观察我的那几个项目,都重复的导入了源码,每次发现一个bug,改了一个,另外一个忘记同步了,造成代码维护的不便,所以此次将虚拟显示器部分的代码进行提取,单独封装成一个SDK,只要项目中有用到都使用这个SDK即可。
SDK的导出函数
此次SDK,为win7虚拟显示器和win10虚拟显示器做了统一处理,导出同样的接口,也就是说用户在调用时不再需要关注当前系统是win7还是win10,初步导出函数如下:
代码语言:javascript复制#include <Windows.h>
enum
{
USB_DEVICE_ERROR_SUCC = 0,
USB_DEVICE_ERROR_FAILD,
USB_DEVICE_ERROR_DEV_NOT_READY,/* 虚拟显示器刚刚插入,还没准备好 */
USB_DEVICE_ERROR_INVALID_PARAMS/* 传入的参数不对 */
};
typedef struct _VMON_INFO
{
BOOL bExist;/* 虚拟显示器是否存在 */
BOOL bActive;/* 虚拟显示器是否处于激活状态 */
BOOL bIndependent;/* 虚拟显示器是否独立(不和其他显示器复制)*/
DISPLAYCONFIG_2DREGION m_currentResolution;/* 当前虚拟显示器分辨率 */
WCHAR szDisplayName[MAX_PATH];/* 虚拟显示器显示名称(可用于枚举分辨率列表)*/
}VMON_INFO;
typedef struct _MON_IMG_DATA
{
UINT width;
UINT height;
UINT stride;
PVOID pSurface;
}MON_IMG_DATA;
extern "C"
{
/*
* 创建MonitorDevice设备,用于对设备进行操作
* @return 失败返回false,成功返回true
* @remark 最后需要使用DestroyUsbDevice进行销毁
*/
__declspec(dllexport) HANDLE CreateMonitorDevice();
/*
* 插入虚拟显示器
* @param handle[in]:CreateMonitorDevice返回的设备句柄
* @return 见返回错误码
* @remark
*/
__declspec(dllexport) int PlugInMonitor(HANDLE handle);
/*
* 设置分辨率
* @param handle[in]:CreateMonitorDevice返回的设备句柄
* @param rsl[in]:需要设置的分辨率,宽度最小值为800,高度最小值为600
* @return 见返回错误码
* @remark 设置低于800*600的分辨率会返回失败
*/
__declspec(dllexport) int SetCustomSolution(HANDLE handle, DISPLAYCONFIG_2DREGION rsl);
/*
* 等待虚拟显示器屏幕数据,屏幕画面有更新才返回
* @param handle[in]:CreateMonitorDevice返回的设备句柄
* @return 见返回错误码
* @remark
*/
__declspec(dllexport) int WaitforMonitorImage(HANDLE handle, MON_IMG_DATA *imageData);
/*
* 取消等待屏幕图片,由于WaitMonitorImage是阻塞等待的,另一个线程可以取消等待,让WaitMonitorImage返回
* @param handle[in]:CreateMonitorDevice返回的设备句柄
* @return 见返回错误码
* @remark
*/
__declspec(dllexport) int CancelWaitMonitorImage(HANDLE handle);
/*
* 拔出虚拟显示器
* @param handle[in]:CreateMonitorDevice返回的设备句柄
* @return 见返回错误码
* @remark
*/
__declspec(dllexport) int PlugOutMonitor(HANDLE handle);
/*
* 销毁获取虚拟显示器信息
* @param handle[in]:CreateMonitorDevice返回的设备句柄
* ¶n pInfo[out]:返回的虚拟显示器信息
* @return 见返回错误码
* @remark
*/
__declspec(dllexport) int GetvMonitorInfo(HANDLE handle, VMON_INFO *pInfo);
/*
* 销毁MonitorDevice设备
* @param handle[in]:CreateMonitorDevice返回的设备句柄
* @return 见返回错误码
* @remark
*/
__declspec(dllexport) int DestroyMonitorDevice(HANDLE handle);
}
测试工具
SDK写完了需要验证SDK的功能是否完备,是否存在bug,所以写了个工具进行验证。 软件做成了托盘形式,运行后会在电脑右下角生成托盘,右击弹出菜单:
插入虚拟显示器
插入虚拟显示器后,我们到高级显示设置可以看到命名为DLJVMON的显示器(显示器名字可以自定义,也可以提供接口修改)。
拔出虚拟显示器
设置标准分辨率
设置自定义分辨率
后记
其他的一些接口有时间再补充测试,由于家里只有win10电脑,win7的暂时没有展现。 后续有时间再增加一些其他接口。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/171789.html原文链接:https://javaforall.cn