介绍 最近,我有理由
保存一个DIB到剪贴板。在四周的时间里,我尝试了许多方法,但都没有成功 他们工作(非常感谢Chris Losinger和Christian Graus,感谢他们愿意尝试并提供给我 指导,答案,或两者都有)。这篇文章描述了我是如何最终实现我的目标,但也正好属于 分类它不漂亮,但它工作。 考验和磨难 因为我需要这样做的原因超出了本文的范围,所以我只需要说我的 起始点是一个BITMAPINFOHEADER结构体和一个指向表示实际位图的位数组的指针 数据。位图为24位。 起初,我四处徘徊,试图创建一个位图句柄与我的信息。我确信我做得对 但是由于将位图移动到剪贴板的操作一次次失败,我(自然)认为我必须这样做 我真的把它搞砸了,所以我去寻求帮助,最后使用了Chris Maunder的CDIBSectionLite类。 Chris的类包含将我捕获的位图转换为DIBSection所需的所有代码,但它缺少这些代码 将DIB移动到剪贴板。这是一个很好的开始。然而,无论我怎样努力,我还是做不到 无法将位图导入剪贴板。 这一切是如何形成的 在花了一周的时间试图从我的代码(和CDIBSectionLite)中强制出所需的功能之后,我 打电话给微软软件开发者热线(使用我订阅的MSDN上两个可用的免费事件之一)。 微软的那个家伙带我看了一个示例,显然是wincap32编译器附带的。这个示例 程序将捕获所选窗口的内容并将其转换为DIB,并将其存储在剪贴板上。 完美的。 在更改了一个或两个#include语句并更改了文件的名称之后,我编译了我的代码,运行了 结果程序,并bingo - DIB在剪贴板! 我所做的 我做的第一件事是将这个函数添加到CDIBSectionLite类中(记住,它不漂亮,但它很漂亮 工作原理: 隐藏,收缩,复制Code
HANDLE CDIBSectionLite::PutOnClipboard() { HANDLE hResult = NULL; if (::OpenClipboard(NULL)) { ::EmptyClipboard(); ::GdiFlush(); // borrowed these variables from the sample app HDIB hDib = NULL; HBITMAP hBitmap = NULL; HPALETTE ghPal = NULL; if (m_hBitmap) { // call the function that converts the bitmap to a DIB hDib = BitmapToDIB(m_hBitmap, ghPal); if (hDib) { // ahhh, the sweet smell of success hResult = ::SetClipboardData(CF_DIB, hDib); if (hResult == NULL) { _ShowLastError(); } } else { MessageBeep(0); } } ::CloseClipboard(); } return hResult; }
从微软样例应用程序,我复制了以下文件到我的项目目录: 隐藏,复制Code
DIBUTIL.C DIBUTIL.H DIBAPI.H
然后我将DIBUTIL.C文件重命名为DIBUTIL.CPP。在此之后,我必须在该文件中进行以下更改 它会编译。示例应用程序是按原样编译的,但因为我包含了stdafx。h,编译器吐在某种类型上 不匹配,因此有以下变化: 隐藏,复制Code
Line 30: #include <span class="code-keyword"><windows.h></span> to: #include <span class="code-string">"stdafx.h"</span> Line 381: lpbi = GlobalLock(hDIB); to: lpbi = (LPSTR)GlobalLock(hDIB); Line 524: lpDIBHdr = GlobalLock(hDIB); to: lpDIBHdr = (LPSTR)GlobalLock(hDIB); Line 608: hPal = GetStockObject(DEFAULT_PALETTE); to: hPal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
最后,我使用了整个shebang如下: 隐藏,复制Code
// I needed to construct the BITMAPINFO structure to be passed to the // CDIBSectionLite object would be happy HBITMAP hBitmap; BITMAPINFO bmi; memset(&bmi, 0, sizeof(BITMAPINFO)); // use the BITMAPINFOHEADER structure that we captured bmi.bmiHeader = cb.bih; CDIBSectionLite dib; // use the BITMAPINFO struct that we created above and the bits we captured dib.SetBitmap(&bmi, cb.pBuffer); dib.PutOnClipboard();
最后 它的工作原理。我并不是真的对从我从文件中挑选出我需要的东西感兴趣 microsoftsample app,我打算把它都留在那里。这是我留给读者的一个练习。 本文附带的zip文件包含修改后的CDIBSectionLite类和修改后的示例应用程序 文件,以及整个示例应用程序源代码的本机形式。需要注意的是,如果按原样编译,则 示例应用程序项目创建(或提供)一个名为DIBAPI.DLL的DLL。这个DLL包含我链接的代码 直接进入我的程序(我不希望它在DLL形式)。 由于我捕获的位图的大小,我没有为CDIBSectionLite配备保存位图的能力 剪贴板除了DIB之外的任何东西。但是,请记住,有可能保存多个项 剪贴板,因此您可以同时(使用示例应用程序代码)在DIB中的剪贴板上放置位图 格式,设备依赖格式,和元文件格式,如果那是绊你的触发器。粘贴的任何应用 剪贴板将/应该拉出最适合它的要求的格式。 本文转载于:http://www.diyabc.com/frontweb/news353.html