And*_*eas 9 c windows winapi 2d
我的应用程序应该能够将32位图像(RGB + alpha通道)复制到剪贴板并从剪贴板粘贴这些图像.为此我打算使用,CF_DIBV5
因为BITMAPV5HEADER
结构有一个字段bV5AlphaMask
.
问题是,对于图像数据应该如何存储在剪贴板中似乎没有达成共识.在进行一些测试时,我发现应用程序之间存在一些差异,使得它几乎无法提出通用解决方案.
以下是我的观察:
当我将Alpha 2010通道图像从Word 2010或XnView复制到剪贴板时,它将被存储而不会预乘像素数据.
但是,当我使用Firefox或Chrome复制图像时,像素数据似乎被alpha通道预乘.
Firefox设置bV5AlphaMask
为0xff000000,而大多数其他应用程序根本不设置它,但保留0.这很奇怪,因为这些应用程序将DIB放到剪贴板上,实际上包含最高8位的alpha通道但仍然设置bV5AlphaMask
为0.必须假设如果位深度为32,即使bV5AlphaMask
为0 ,也存在alpha通道.
简而言之,我的基本问题是:是否有关于如何将Alpha通道数据存储在剪贴板上的官方信息?我特别想知道数据是否必须预乘.正如您在上面所看到的,Word 2010和XnView不会预先相互映射,而Firefox和Chrome则可以.但是,知道颜色通道是否应该预乘是至关重要的.
非常感谢您对此有所了解!
更新2 粘贴到Paint.NET现在工作正常.它是由我的代码中的一个错误引起的,如果alpha通道为0,则没有将颜色通道设置为0,即在这种情况下前导相应没有正确完成,这似乎混淆了Paint.NET.
仍未解决的问题是Internet Explorer 10.当将带有alpha通道的PNG复制到剪贴板时,IE 10只是将24位CF_DIBV5放在剪贴板上,但Paint.NET可以将此位图粘贴到alpha通道,因此必须有另一种格式IE 10暴露给剪贴板.也许它暴露了PNG使用CFSTR_FILECONTENTS和CFSTR_FILEDESCRIPTOR.
更新 我现在已经按照下面arx描述的方式实现了它,它运行得很好.然而,仍然有两件事令我困惑:
1)将我的应用程序中的alpha通道图像粘贴到Paint.NET中不会保留alpha通道.Paint.NET中的图像看起来不透明.但是,从Firefox和Chrome粘贴到Paint.NET完美地运行,alpha通道被保留了!我已经抛弃了完整的DIBV5并且它与我的应用程序完全相同,但它仍适用于FF和Chrome,但不适用于我的应用程序,因此必须有其他内容!Firefox和Chrome必须做一些我的应用不做的事情!?
2)对于Internet Explorer 10也是如此.将IE 10中的Alpha通道图像粘贴到我的应用程序根本不起作用...我得到的深度为24的DIB,即没有alpha通道所有.然而,当从IE 10粘贴到Paint.NET时,alpha通道就在那里!所以这里必须有更多东西......
arx*_*arx 17
我确信在CF_DIBV5中存储alpha的正确方法,但它确实没关系.应用程序已经不一致地处理它,因此如果您希望您的应用程序与其他应用程序很好地协作,则无法使用CF_DIBV5.
我刚刚研究过复制和粘贴透明位图.我的目标是成功将透明位图粘贴到两个版本的Office和GIMP中.我看了几种可能的格式:
CF_BITMAP
透明度始终被忽略.
CF_DIB
使用通常的0xAARRGGBB格式的32bpp BI_RGB.GIMP支持这一点,但没有别的.
CF_DIBV5
GIMP不支持这一点.
"PNG"
支持粘贴:GIMP,Word 2000,Excel 2000,Excel 2007和PowerPoint 2007.
粘贴不受支持:Word 2007和OneNote 2007.
如果复制位图,所有这些应用程序都会成功导出"PNG".
但是,Word和OneNote 2007 将粘贴从Explorer复制的PNG文件.所以我想出了以下内容:
复制解决方案
将透明位图转换为PNG格式.
宣传以下剪贴板格式:
"PNG" - 原始PNG数据.
CF_DIB - 用于不处理透明度的应用程序(如paint).
CFSTR_FILEDESCRIPTOR - 使PNG看起来像一个文件.文件描述符应该具有带有".png"扩展名的发明文件名.
CFSTR_FILECONTENTS - 内容必须作为IStream
; 只是使用一个HGLOBAL
似乎不起作用.该数据与"PNG"数据相同.
完成此操作后,我可以成功将透明位图粘贴到GIMP,Office 2000和Office 2007中.您还可以将PNG直接粘贴到Explorer文件夹中.
更新
我意识到我只回答了一半的问题.这非常适合复制,但如果要从仅复制CF_DIBV5(如Firefox)的应用程序中粘贴,则无用.
我建议您使用"PNG"(如果可用),否则回退到CF_DIBV5,将其视为预乘.这将正确处理Word 2010(导出"PNG"),Firefox和Chrome.XnView只导出非乘法CF_DIBV5,因此无法正常工作.我不确定你能做得更好.
lscf - 探索剪贴板格式的工具
这是用于显示可用剪贴板格式列表的工具的来源.它也可以写一个文件.我打电话给它lscf
.在Visual Studio中创建一个win32控制台应用程序,并将此源粘贴到主函数上.它有一个非常小的错误:如果您错误输入格式名称,它永远不会显示"未知格式"错误.
#include <Windows.h>
#include <stdio.h>
#include <tchar.h>
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
LPCTSTR cfNames[] = {
_T("CF_TEXT"),
_T("CF_BITMAP"),
_T("CF_METAFILEPICT"),
_T("CF_SYLK"),
_T("CF_DIF"),
_T("CF_TIFF"),
_T("CF_OEMTEXT"),
_T("CF_DIB"),
_T("CF_PALETTE"),
_T("CF_PENDATA"),
_T("CF_RIFF"),
_T("CF_WAVE"),
_T("CF_UNICODETEXT"),
_T("CF_ENHMETAFILE"),
_T("CF_HDROP"),
_T("CF_LOCALE"),
_T("CF_DIBV5")
};
int LookupFormat(LPCTSTR name)
{
for (int i = 0; i != ARRAY_SIZE(cfNames); ++i)
{
if (_tcscmp(cfNames[i], name) == 0)
return i + 1;
}
return RegisterClipboardFormat(name);
}
void PrintFormatName(int format)
{
if (!format)
return;
if ((format > 0) && (format <= ARRAY_SIZE(cfNames)))
{
_tprintf(_T("%s\n"), cfNames[format - 1]);
}
else
{
TCHAR buffer[100];
if (GetClipboardFormatName(format, buffer, ARRAY_SIZE(buffer)))
_tprintf(_T("%s\n"), buffer);
else
_tprintf(_T("#%i\n"), format);
}
}
void WriteFormats()
{
int count = 0;
int format = 0;
do
{
format = EnumClipboardFormats(format);
if (format)
{
++count;
PrintFormatName(format);
}
}
while (format != 0);
if (!count)
_tprintf(_T("Clipboard is empty!\n"));
}
void SaveFormat(int format, LPCTSTR filename)
{
HGLOBAL hData = (HGLOBAL)GetClipboardData(format);
LPVOID data = GlobalLock(hData);
HANDLE hFile = CreateFile(filename, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
DWORD bytesWritten;
WriteFile(hFile, data, GlobalSize(hData), &bytesWritten, 0);
CloseHandle(hFile);
}
GlobalUnlock(hData);
}
int _tmain(int argc, _TCHAR* argv[])
{
if (!OpenClipboard(0))
{
_tprintf(_T("Cannot open clipboard\n"));
return 1;
}
if (argc == 1)
{
WriteFormats();
}
else if (argc == 3)
{
int format = LookupFormat(argv[1]);
if (format == 0)
{
_tprintf(_T("Unknown format\n"));
return 1;
}
SaveFormat(format, argv[2]);
}
else
{
_tprintf(_T("lscf\n"));
_tprintf(_T("List available clipboard formats\n\n"));
_tprintf(_T("lscf CF_NAME filename\n"));
_tprintf(_T("Write format CF_NAME to file filename\n\n"));
}
CloseClipboard();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2928 次 |
最近记录: |