- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我试图捕获屏幕内容,直接修改捕获图像的位,然后将结果放在剪贴板上。 (实际上,我最终对剪贴板并不感兴趣,但是正在将其用作测试步骤。)
我从对this question的答案之一开始的示例。但是,它使用CreateCompatibleBitmap
,据我了解,无法直接访问使用该函数创建的位图的位,因此我尝试使用CreateDIBSection
。这是我到目前为止的内容:
void GetScreenShot(void)
{
int x1, y1, w, h;
// get screen dimensions
x1 = GetSystemMetrics(SM_XVIRTUALSCREEN);
y1 = GetSystemMetrics(SM_YVIRTUALSCREEN);
w = GetSystemMetrics(SM_CXVIRTUALSCREEN);
h = GetSystemMetrics(SM_CYVIRTUALSCREEN);
// copy screen to bitmap
HDC hScreen = GetDC(NULL);
HDC hDC = CreateCompatibleDC(hScreen);
if( !hDC )
throw 0;
// This works:
//HBITMAP hBitmap = CreateCompatibleBitmap(hScreen, w, h);
BITMAPINFO BitmapInfo;
BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
BitmapInfo.bmiHeader.biWidth = w;
BitmapInfo.bmiHeader.biHeight = h;
BitmapInfo.bmiHeader.biPlanes = 1;
BitmapInfo.bmiHeader.biBitCount = 24; // assumption; ok for our use case
BitmapInfo.bmiHeader.biCompression = BI_RGB;
BitmapInfo.bmiHeader.biSizeImage = ((w * 3 + 3) & ~3) * h;
BitmapInfo.bmiHeader.biXPelsPerMeter = (int)(GetDeviceCaps( hScreen, LOGPIXELSX ) * 39.3701 + 0.5);
BitmapInfo.bmiHeader.biYPelsPerMeter = (int)(GetDeviceCaps( hScreen, LOGPIXELSY ) * 39.3701 + 0.5);
BitmapInfo.bmiHeader.biClrUsed = 0;
BitmapInfo.bmiHeader.biClrImportant = 0;
BitmapInfo.bmiColors[0].rgbBlue = 0;
BitmapInfo.bmiColors[0].rgbGreen = 0;
BitmapInfo.bmiColors[0].rgbRed = 0;
BitmapInfo.bmiColors[0].rgbReserved = 0;
void *pBits;
// This does not work:
HBITMAP hBitmap = CreateDIBSection( hScreen, &BitmapInfo, DIB_RGB_COLORS, &pBits, NULL, 0 );
if( !hBitmap )
throw 0;
HGDIOBJ old_obj = SelectObject(hDC, hBitmap);
if( !old_obj )
throw 0;
if( !BitBlt(hDC, 0, 0, w, h, hScreen, x1, y1, SRCCOPY) )
throw 0;
if( !SelectObject(hDC, old_obj) )
throw 0;
if( !GdiFlush() )
throw 0;
// this is where we would modify the image
// save bitmap to clipboard
if( !OpenClipboard(NULL) )
throw 0;
if( !EmptyClipboard() )
throw 0;
if( !SetClipboardData( CF_BITMAP, hBitmap ) ) // CF_DIB causes the throw
throw 0;
if( !CloseClipboard() )
throw 0;
// clean up
DeleteDC(hDC);
ReleaseDC(NULL, hScreen);
DeleteObject(hBitmap);
}
pBits
之后,我可以在
BitBlt
上看到看起来像图像数据的图片,尽管这有点令人怀疑,因为第一堆值的R,G,B都相同,但是最下面的值屏幕的左上角实际上是蓝色。无论如何,即使实际的位错了,我也应该在剪贴板上得到一些图像,但是我没有。
CF_DIB
作为
SetClipboardData
的第一个参数,而不是
CF_BITMAP
,但是调用失败。
CreateDIBSection
的调用并取消注释对
CreateCompatibleBitmap
的调用,那么它可以工作,但是我没有机会直接修改图像位。
CreateCompatibleBitmap
,然后将DIB部分中的内容blit到“兼容位图”中,但是似乎没有任何明显的理由再次复制这些位。
SetClipboardData
?
最佳答案
最终,当我找到this时,找到了答案。 MSDN上的API文档对此相当含糊,可能是因为它本身可以追溯到很早,但是看起来剪贴板函数都使用Windows 3.x样式的内存分配系统(GlobalAlloc
等)。
对于系统剪贴板,将共享内存直接公开给应用程序是有意义的,而不是OS必须将数据复制到内部缓冲区中。但是剪贴板功能可以追溯到很远,以至于不存在基于较新页面文件的共享内存方案,因此它们必须使用GlobalAlloc
内存。当32位Windows出现时,仅模拟该机制而不是破坏现有的应用程序代码会更有意义。
我强烈怀疑,出于类似的原因,大多数GDI句柄实际上也实际上是GlobalAlloc
句柄,这就是为什么您可以将CreateCompatibleBitmap
的返回值传递给剪贴板。相比之下,CreateDIBSection
没有完全使用旧式分配,这很明显,因为您可以告诉它将位存储在文件映射中。 (我怀疑它返回的句柄仍来自GlobalAlloc
,但是如此分配的块又包含指向图像数据虚拟内存的直接指针,因此SetClipboardData
对此进行了测试,因为它显然是“陷阱”。)
因此,我只通过让CreateDIBSection
分配到所需的位置来固定所有内容,因为无论如何,都不可能将其交给SetClipboardData
,然后在我想发送到剪贴板时执行此操作:
void CScreenshot::SendToClipboard( void )
{
HGLOBAL hClipboardDib = GlobalAlloc( GMEM_MOVEABLE | GMEM_SHARE, cbDib );
if( !hClipboardDib )
throw 0;
void *pClipboardDib = GlobalLock( hClipboardDib );
memcpy( pClipboardDib, &BitmapInfo, sizeof(BITMAPINFOHEADER) );
memcpy( (BITMAPINFOHEADER*)pClipboardDib+1, pBits, BitmapInfo.bmiHeader.biSizeImage );
GlobalUnlock( hClipboardDib );
if( !OpenClipboard( NULL ) )
{
GlobalFree( hClipboardDib );
throw 0;
}
EmptyClipboard();
SetClipboardData( CF_DIB, hClipboardDib );
CloseClipboard();
}
CreateCompatibleBitmap
返回的句柄可以用于对
GlobalLock
的调用中,那么您就可以直接获得这些位,而无需在
CScreenshot::SendToClipboard
中生成副本,因为您可以将其直接传递给
SetClipboardData
。但是,我也强烈怀疑这是未记录的行为(如果我错了,请纠正我!),所以这是一个非常糟糕的主意。您还必须跟踪是否将其传递到剪贴板,如果没有,则不要在其上调用
DeleteObject
。但是我不确定。我还怀疑
SetClipboardData
无论如何都要复制它,因为它可能没有与
GMEM_SHARE
一起分配。
关于windows - 为什么不能在剪贴板上放置DIB部分?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50313607/
我正在我的应用程序中实现支付,但我的支付提供商 (DIBS) 在使用回调字符串连接到我的服务器时出现问题。我向他们的服务器发送了一个回调字符串,该字符串必须转发到我的服务器以确认付款已经完成。问题是支
我希望 1a 和 2a 成为一行,屏幕越薄,该行就越高 - 内容将包裹在每个单元格中。 我希望 1b 和 2b 成为占据屏幕剩余空间的一行。 1a + 1b 和 2a + 2b 是列。
我刚刚在论坛上讨论是否有替代 GDI 和 Direct X 的 Windows 图形库。有人提到了 WinDIB。遗憾的是,他没有对此进行更多解释。 现在我搜索了谷歌。 似乎没有关于 Windows
如果我使用 CreateDIBSection() 创建一个 DIB,我可以通过设置 的 biHeight 字段来指定它应该是自上而下还是自下而上>BITMAPINFOHEADER 结构为负值或正值。但
我正在使用一个捕获卡 dll,它导出一个函数,该函数提供一个包含 DIB 的 HGLOBAL 句柄。我想将此DIB写入文件。锁定资源并检索数据指针后,我请求大小,大约为 1mb。但是当我将它写入文件时
我有一个 DIB 句柄。如何将其转换为 TPNGObject保持其透明度? 编辑: 我在此解决方案中使用方法 2 Here 但即使我设置它的Transparent,结果位图也不透明标记为真 最佳答案
我正在开发一个剪贴板管理器(可以在这里看到:http://flamefusion.net/software/shapeshifter)。 但是,我目前遇到位图 (bmp) 问题,它无法真正正确地将自身
我需要做什么才能将 DIB 转换为 BMP? 最佳答案 位图 header 类型的文档位于 http://msdn.microsoft.com/en-us/library/dd183386%28VS.
我正在处理 Dibs 支付集成,但无法取得成功。所有东西在演示模式下都运行良好,但是当向它提供商家 ID 时,然后在打开卡详细信息表单之前它会给出错误“数据已被篡改。校验无效”。我不知道那是什么。在我
我正在用 Windows C++ 编程。我想知道在屏幕上绘制 DIB 的最快方法是什么。图片可能被拉伸(stretch)了。 比 StretchDIBits 快,比 SetDIBitsToDevice
我最近发现了这个 ( Win32 API Speed Issues )提高绘图速度,但似乎代码: pBits[(y * WIDTH) + x] = RGB(0, 0, 0xFF); 始终使图像翻转(从
我使用此代码将 DIB 转换为 TBitmap,那么我如何操作此代码以适合 PNG 图像(保留其透明度)?我厌倦了将透明属性设置为 true,但似乎代码是为 256 色位图编写的。 代码来源:Here
我最近才发现 GDI+ 中不同构造函数之间的区别。去: var bmp = new Bitmap(width, height, pixelFormat); 创建一个 DDB(设备相关位图)而: var
This question Jon 的回答让我意识到这甚至存在,所以我很好奇并启动了 Visual Studio。 我遵循了 MSDN 页面的一个示例,然后创建了自己的小示例。如下: public c
我正在尝试读取扫描图像并将其从内存中的 DIB 压缩为 TIF 文件。我正在使用 libtiff 库并在网上找到了几个示例,但没有一个真正按照我的需要进行操作。我需要从 DIB 中获取图像并将其转换为
我创建了一个可消耗的 COM 类库。 类库获取相机的图像。它的类型为图像/位图。 我在VB6中使用类库,我需要在VB6中显示这个图像。 如何将此 System.Drawing.Image 转换为 VB
我正在解码流中的视频帧,sws_scale 为我提供了解码后的 RGB 图像数据 (PIX_FMT_RGB24) 的缓冲区。我有一个现有的前端应用程序,需要输入 DIB。所以我需要知道如何将此缓冲区转
我试图通过对像素值数组进行硬编码来创建位图,将此像素数组转换为 DIB,然后将此 DIB 转换为 DDB。在网上找了两个转换CreateBitmapFromPixels和DIBToDDB的函数。我的问
我继承了一个老式的 MFC Windows CE 程序,我不得不对其进行一些修改。作为其中的一部分,我必须创建一个带有文本的单色图像,并将其显示在屏幕上,并将图像的每一行一次一个地发送到打印机。 我最
应为使用 GetDIBits 函数从 HBITMAP 接收的 DIB 数据分配多少内存? GetDIBits函数在MSDN中的描述如下: int GetDIBits( __in HDC h
我是一名优秀的程序员,十分优秀!