开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

楼主: z573277679
收起左侧

[易语言纯源码] 【开源】最强截图之WGC

[复制链接]
回帖奖励 167 枚 精币 回复本帖可获得 1 枚 精币奖励! 每人限 1 次
结帖率:91% (10/11)
发表于 昨天 16:11 | 显示全部楼层   河南省郑州市

回帖奖励 +1 枚 精币

谢谢分享!
回复 支持 反对

使用道具 举报

签到天数: 7 天

发表于 昨天 16:10 | 显示全部楼层   湖北省黄石市
z573277679 发表于 2026-7-6 15:30
这不是Bug,而是WGC引擎的底层机制决定的。仔细看我的源码,里面定义了 集_缓存_截图数据,当底层获取不 ...

好的增加 旧针判断,沿用缓存,或者重新构造
  
子程序名返回值类型公开备 注
WGC_截取图像字节集 【作者:白枫 (精易ID:*)】
参数名类 型参考可空数组备 注
参_目标句柄整数型
参_左整数型
参_顶整数型
参_宽整数型
参_高整数型
变量名类 型静态数组备 注
局_最新帧整数型 
局_临时帧整数型 
局_表面对象整数型 
局_接口访问整数型 
局_D3D纹理整数型 
局_函数_获取帧整数型 
局_函数_通用整数型 
局_目标行距整数型 
局_像素指针整数型 
局_源行距整数型 
局_需创建中转逻辑型 
局_最终宽整数型 
局_最终高整数型 
局_初始化宽整数型 
局_初始化高整数型 
局_描述指针整数型 
局_映射指针整数型 
i整数型 
如果真 (集_WGC_已初始化 = )
返回 ({  })

如果真 (集_状态_正在截图)
如果真 (取字节集长度 (集_缓存_截图数据) > 0)
返回 (集_缓存_截图数据)
返回 ({  })
集_状态_正在截图 = 真
如果 (参_左 > 0 参_顶 > 0)
局_初始化宽 = 0
局_初始化高 = 0
局_初始化宽 = 参_宽
局_初始化高 = 参_高

如果真 (集_WGC_会话 = 0 集_当前_句柄 ≠ 参_目标句柄 集_当前_宽 ≠ 局_初始化宽 集_当前_高 ≠ 局_初始化高)
如果真 (WGC_重建单例对象 (参_目标句柄, 局_初始化宽, 局_初始化高))
集_状态_正在截图 = 假
返回 ({  })


局_函数_获取帧 = Asm_取虚表函数 (集_WGC_帧池, 7)
如果真 (集_最新帧 = 0)
局_临时帧 = 0
判断循环首 (局_临时帧 = 0)
Asm_Call2P (局_函数_获取帧, 集_WGC_帧池, Asm_取整数指针 (局_临时帧))
Asm_微秒延时 (500)
判断循环尾 ()
集_最新帧 = 局_临时帧

Asm_Call2P (局_函数_获取帧, 集_WGC_帧池, Asm_取整数指针 (局_最新帧))
如果 (局_最新帧 ≠ 0)
Asm_COM释放对象 (集_最新帧)
集_最新帧 = 局_最新帧


沿用旧针 = 沿用旧针 + 1
如果真 (集_缓存_截图数据 ≠ {  })
集_状态_正在截图 = 假
返回 (集_缓存_截图数据)

局_最新帧 = 集_最新帧

. ' 计次循环首 (5, )
' 局_临时帧 = 0
' Asm_Call2P (局_函数_获取帧, 集_WGC_帧池, Asm_取整数指针 (局_临时帧))
. ' 如果真 (局_临时帧 = 0)
' 跳出循环 ()
' Asm_COM释放对象 (局_临时帧)
. ' 计次循环尾 ()
' Asm_微秒延时 (5000)
' 局_最新帧 = 0
. ' 判断循环首 (局_最新帧 = 0)
' Asm_Call2P (局_函数_获取帧, 集_WGC_帧池, Asm_取整数指针 (局_最新帧))
' Asm_微秒延时 (500)
. ' 判断循环尾 ()
如果真 (局_最新帧 ≠ 0)
局_表面对象 = 0
局_函数_通用 = Asm_取虚表函数 (局_最新帧, 6)
Asm_Call2P (局_函数_通用, 局_最新帧, Asm_取整数指针 (局_表面对象))
如果真 (局_表面对象 ≠ 0)
局_接口访问 = 0
Asm_调用_QueryInterface (局_表面对象, Asm_取字节集指针 (集_GUID_接口访问), Asm_取整数指针 (局_接口访问))
如果真 (局_接口访问 ≠ 0)
局_D3D纹理 = 0
COM_调用 (局_接口访问, 3, Asm_取字节集指针 (集_GUID_D3D11纹理), Asm_取整数指针 (局_D3D纹理))
Asm_COM释放对象 (局_接口访问)
如果真 (局_D3D纹理 ≠ 0)
局_描述指针 = Asm_取字节集指针 (集_缓存_纹理描述)
COM_调用 (局_D3D纹理, 10, 局_描述指针)
局_需创建中转 = 集_WGC_中转纹理 = 0
如果真 (局_需创建中转 = )
如果真 (Asm_读内存整数 (局_描述指针) ≠ 集_WGC_尺寸数组 [1] Asm_读内存整数 (局_描述指针 + 4) ≠ 集_WGC_尺寸数组 [2])
Asm_COM释放对象 (集_WGC_中转纹理)
局_需创建中转 = 真


如果真 (局_需创建中转)
集_WGC_尺寸数组 [1]Asm_读内存整数 (局_描述指针)
集_WGC_尺寸数组 [2]Asm_读内存整数 (局_描述指针 + 4)
Asm_写内存整数 (局_描述指针 + 28, 3)
Asm_写内存整数 (局_描述指针 + 32, 0)
Asm_写内存整数 (局_描述指针 + 36, 131072)
Asm_写内存整数 (局_描述指针 + 40, 0)
Asm_写内存整数 (局_描述指针 + 8, 1)
COM_调用 (集_D3D_设备指针, 5, 局_描述指针, 0, Asm_取整数指针 (集_WGC_中转纹理))

如果真 (集_WGC_中转纹理 ≠ 0)
COM_调用 (集_D3D_上下文指针, 47, 集_WGC_中转纹理, 局_D3D纹理)
局_映射指针 = Asm_取字节集指针 (集_缓存_映射数据)
如果真 (COM_调用 (集_D3D_上下文指针, 14, 集_WGC_中转纹理, 0, 1, 0, 局_映射指针) = 0)
局_像素指针 = Asm_读内存整数 (局_映射指针)
局_源行距 = Asm_读内存整数 (局_映射指针 + 4)
局_最终宽 = 参_宽
局_最终高 = 参_高
如果真 (局_最终宽 = 0)
局_最终宽 = 集_WGC_尺寸数组 [1] - 参_左
如果真 (局_最终高 = 0)
局_最终高 = 集_WGC_尺寸数组 [2] - 参_顶

如果真 (参_左 > 0 参_顶 > 0)
局_像素指针 = 局_像素指针 + 参_顶 × 局_源行距 + 参_左 × 4

局_目标行距 = 局_最终宽 × 3
如果真 (局_目标行距 % 4 ≠ 0)
局_目标行距 = 局_目标行距 + 4 - 局_目标行距 % 4

如果真 (取字节集长度 (集_缓存_截图数据) ≠ 54 + 局_目标行距 × 局_最终高)
集_缓存_截图数据 = 取空白字节集 (54 + 局_目标行距 × 局_最终高)

Asm_写入BMP头_24位 (Asm_取字节集指针 (集_缓存_截图数据), 局_最终宽, 局_最终高, 局_目标行距 × 局_最终高)
Asm_32位转24位_翻转 (局_像素指针, Asm_取字节集指针 (集_缓存_截图数据) + 54, 局_最终宽, 局_最终高, 局_源行距, 局_目标行距)
COM_调用 (集_D3D_上下文指针, 15, 集_WGC_中转纹理, 0)


Asm_COM释放对象 (局_D3D纹理)

Asm_COM释放对象 (局_表面对象)

如果真 (局_最新帧 ≠ 0)
' Asm_COM释放对象 (局_最新帧)

集_状态_正在截图 = 假
如果真 (取字节集长度 (集_缓存_截图数据) > 0)
返回 (集_缓存_截图数据)
返回 ({  })


沿用缓存数据

沿用缓存数据

重新构造

重新构造
回复 支持 反对

使用道具 举报

结帖率:100% (3/3)

签到天数: 7 天

 楼主| 发表于 昨天 15:49 | 显示全部楼层   重庆市重庆市
kmskik 发表于 2026-7-6 15:03
截屏为什么会有黄色的方框在窗口边缘

这个黄框是Windows操作系统(DWM)在底层强制加上去的。
这是微软在推出WGC技术时,特意引入的一项系统级隐私与安全机制。因为WGC的截屏能力太强(能无视遮挡、无视部分防截图),为了防止恶意木马或流氓软件在后台偷偷录屏、窃取用户隐私,微软强制要求在被捕获的窗口外围渲染一圈高亮的黄框,用来警示当前电脑用户:“这个窗口正在被截图/录制”。

为什么我不把它去掉?
当然这个黄框是能够去掉的。原因很简单,保留微软原生的安全行为。

回复 支持 反对

使用道具 举报

发表于 昨天 15:44 | 显示全部楼层   辽宁省沈阳市

回帖奖励 +1 枚 精币

感谢分享
回复 支持 反对

使用道具 举报

签到天数: 5 天

发表于 昨天 15:36 | 显示全部楼层   四川省乐山市

回帖奖励 +1 枚 精币

回复 支持 反对

使用道具 举报

结帖率:100% (3/3)

签到天数: 7 天

 楼主| 发表于 昨天 15:30 | 显示全部楼层   重庆市重庆市
斗战胜猴 发表于 2026-7-6 14:53
有个小bug,最新针时有时无。 不知道和dx11的区别在哪,都是拿底层的bgra颜色数据。再拼接bmp文件头,不知 ...

这不是Bug,而是WGC引擎的底层机制决定的。仔细看我的源码,里面定义了 集_缓存_截图数据,当底层获取不到新帧时,可以直接复用上一帧的缓存数据返回。这是微软官方推荐的做法。为什么这么设计?这里举两个例子。
获取太快:如果你的截图循环跑到了1000次/秒,但你的显示器是60Hz(每秒只刷新60次),那么多出来的940 次调用,系统根本没有生成新画面,TryGetNextFrame 就会直接返回 NULL。
画面静止: 如果目标窗口画面没有任何像素变动,DWM出于省电优化,可能不会投递新的帧。

另外DXGI显示器级别的捕获,不支持遮挡。
而WGC是复合管理器级别的捕获。它可以绑定某一个指定的窗口句柄,支持被遮挡的窗口。对硬件加速的窗口兼容性是目前微软官方API中最好的,不会黑屏。
回复 支持 反对

使用道具 举报

结帖率:50% (1/2)

签到天数: 3 天

发表于 昨天 15:25 | 显示全部楼层   江苏省盐城市

回帖奖励 +1 枚 精币

感谢分享,学习先
回复 支持 反对

使用道具 举报

签到天数: 2 天

发表于 昨天 15:18 | 显示全部楼层   北京市北京市
感谢楼主分享优质内容,希望继续努力!
回复 支持 反对

使用道具 举报

签到天数: 3 天

发表于 昨天 15:11 | 显示全部楼层   湖北省武汉市

回帖奖励 +1 枚 精币

感觉很强大
回复 支持 反对

使用道具 举报

结帖率:70% (14/20)

签到天数: 5 天

发表于 昨天 15:09 | 显示全部楼层   河南省郑州市

回帖奖励 +1 枚 精币

        感谢分享,很给力!~
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报QQ: 793400750,邮箱:wp@125.la
网站简介:精易论坛成立于2009年,是一个程序设计学习交流技术论坛,隶属于揭阳市揭东区精易科技有限公司所有。
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备2025452707号) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表