有了解 GetDIBits 函数的吧友吗?
vb吧
全部回复
仅看楼主
level 5
sdsxingyun 楼主
GetDIBits 如果调用本地BMP文件还可以处理,现在需要直接调用内存里面的图片,比如截屏后,获取RGB值,这个时候GetDIBits就不好使了。不知道内存里面的图像,GetDIBits要如何才能操作。有知道的吧友没,谢谢l
2024年09月25日 13点09分 1
level 13
方法一、借助PictureBox控件,作图后得到PictureBox的Image.Handle句柄作参数。
方法二、自己先创建hDC和内存位图,就有位图句柄hBmp,这样在作图后就可以用hBmp作参数
2024年09月25日 15点09分 2
真是哪方面都精通啊[大拇指]
2024年09月26日 03点09分
不知道为啥,用StretchBlt复制一下就好了; 方法一确实可行,但我截图都以秒为单位,中间中转一下太慢了; 感谢吧友回答[哈哈]
2024年09月26日 03点09分
@sdsxingyun PictureBox内置的hBmp是DDB设备相关位图,而CreateDibSection可以得到DIB设备无关位图,GetDIBits也是操作DIB的,你可以考虑用CreateDibSection创建hbmp,这样速度应该能提升不少
2024年09月26日 05点09分
@sdsxingyun StretchBlt不建议,这个是缩放的,一般截屏都是BitBlt,没有缩放功能,相对较快,当然看不同需求,如果要缩放就用StretchBlt
2024年09月26日 05点09分
level 5
sdsxingyun 楼主
@隨風缒夢: 我的笔记本是系统缩放150%的,这样子的话,截出来的图居然是100%的高清,没有缩放。所以得到的RGB值是对不上的;
而且扯到以前写的一个程序就是写了一个模拟QQ全屏截图的软件,也是同样的问题,如果不在系统里面设置强制关闭DPI的话,那截出来的屏就是半截;
不知道我说清楚没有,高手有办法解决吗? 就是我想屏幕显示是啥就是啥,屏幕高清就高清,缩放就缩放;
2024年09月27日 15点09分 3
level 13
将这个写入文本文件,保存成xxx.exe.manifest,和exe放在同目录。或者放入工程资源中(需要特殊处理,或借助第三方资源编辑器,主要VB不支持),这样可以嵌入在exe,不需要额外的附带文件。相关DPI的API函数也可以,不过有些要win8以上支持(具体我也没试)。
2024年09月28日 02点09分 4
这样BitBlt在高DPI(你说的150%)就会正常显示,不需要StretchBlt
2024年09月28日 02点09分
level 5
sdsxingyun 楼主
@隨風缒夢 : 我到微软的官网去查了技术资料,微软也建议用manifest,不过我把三个API也测试了一下,还是用manifest好一点;用MT整合的。
再次感谢;
2024年09月28日 08点09分 5
level 12
setProcessDPIAware
用这个试试
2024年09月28日 17点09分 6
最好不要用任何DPI设置的API,要用清单、清单、清单(重要的事情说三遍)。因为当你在调用SetProcessDPIAware这个API的时候,VB6的运行库已经在先初始化了(这样它内部记录的DPI在你用API设置之前的),你设置之后就会导致VB6的Form界面大小显示错误(甚至反而问题更严重)。
2025年01月24日 03点01分
@yjryym 用清单修改的是直接在整个进程启动阶段设置DPI模式(这样就在任何非系统代码执行之前),这样VB6运行库内部初始化的时候才能获取正确的DPI数据。
2025年01月24日 03点01分
@yjryym 确实还是清单可靠。
2025年01月25日 03点01分
level 9
@隨風缒夢
尴尬了。一样的BitBlt代码(其实就是2行),在我笔记本上全屏拷贝会放大(图1),在台式机上维持不变(图2)。图片里左上角是桌面,右下是截屏。操作系统都一样的Win11,笔记本175%自定义,台式机200%自定义。
使用楼上的manifest没有影响。
但是如果不是通过getDC(0)或者getDestWindows截桌面,而是拷贝其它Picture,大小都是不变的。
2024年09月29日 05点09分 7
level 13
@klimaa
这个DPI也是比较复杂的,VB6支持得不是很好(就算通过manifest,主要VB6的screen.TwipsPerPixelX是单精度型的,而VB6处理后都是按整数输出的,也就是说VB6在某些自定义高DPI下也是会出错的(比例不对,估计和VB6内部把小数部分割了按整数比例调整导致的)。还有系统DPI在vista到win8.1之前没有虚拟化DPI,到win10后引入了虚拟化DPI,可能需要针对不同系统版本进行DPI处理
VB自身的原因,和系统无关,所以GetDC(0)获取屏幕没有问题
2024年09月29日 08点09分 8
具体你得自己慢慢测试了,我搞DPI那会时发现VB有这个问题的(好像是DPI 200%下,记不清了),是不是和你的问题相关就不清楚,反正就是在不同DPI下测试
2024年09月29日 08点09分
level 11
可能是这项问题(应用程序调用此函数时,不得在设备上下文中选择 由 hbmp 参数标识的位图):
所以,操作你的内存中 DDB 位图时需要注意(如捕获屏幕),需要创建新的兼容 DC 和兼容位图进行使用。
另外一个可能不一致的原因是:捕获屏幕的位图是 32 位图,如果当作是 24 位位图处理将会与预期结果不一致。
下述例子演示了 VB6 使用 API 进行截图、以及使用 GetPixel 函数、GetDIBits 函数获取屏幕上 (0,0) 点的颜色值,以 16 进制表示
在例子中,使用了一个 PictureBox 控件用以便捷化保存截图,对象名为 picTmp
【第一部分】:声明 API、结构体和定义常量(略,参考 VB6 的 API 浏览器)
[ 函数声明 ]
BitBlt
CreateCompatibleBitmap
CreateCompatibleDC
GetCurrentObject
GetObject
GetObjectType
GetDIBits(注: lpBI As BITMAPINFO 改为 lpBI As Any)
GetDC
ReleaseD
SelectObject
DeleteObject
DeleteDC
GetPixel
SetPixel
CopyMemory
[ 结构体声明 ]
BITMAP
BITMAPINFOHEADER
RGBQUAD
BITMAPINFO
[ 常量定义 ]
OBJ_BITMAP
SRCCOPY
DIB_RGB_COLORS
BI_RGB
【第二部分】:实际函数
[ 窗体加载时对控件的调整 ]
[ 截图并保存到文件 ]
[ 获取 ( 0, 0 ) 点 RGB 颜色分量,以 16 进制表示 ]
[ 辅助函数 GetCR ,用以从指定位置获取指定颜色 ]
【演示】
将文件编译为 exe 后,先获取 ( 0, 0 ) 点 RGB 颜色分量,再进行截图
最后上传的图片就是截图的结果:
2024年10月01日 04点10分 9
你这个VB设置的颜色真的太nice了,喜欢,抄下了;
2024年10月06日 02点10分
level 1
’pic1 通过 屏幕截屏bit方式获得 并隐藏
Picture2.Width = Picture1.Width
Picture2.Height = Picture1.Height '不一致 画面混乱
With Picture1
GetObject .Image, Len(PicInfo), PicInfo
BytesPerPixel = PicInfo.bmBitsPixel \ 8
ReDim PicBits(0 To PicInfo.bmWidth * PicInfo.bmHeight * BytesPerPixel)
GetBitmapBits .Image, UBound(PicBits), PicBits(1)
For I = 0 To UBound(PicBits) \ BytesPerPixel - 1
B = PicBits(I * BytesPerPixel + 0)
G = PicBits(I * BytesPerPixel + 1)
R = PicBits(I * BytesPerPixel + 2)
‘ r=1-------255
PicBits(I * BytesPerPixel + 0) = B
PicBits(I * BytesPerPixel + 1) = G
PicBits(I * BytesPerPixel + 2) = R
Next I
SetBitmapBits Picture2.Image, UBound(PicBits), PicBits(1)
Picture2.Refresh
End With
2025年01月13日 12点01分 10
1