系统: windows XP先说明下要解决的问题:RichEdit控件(实现了一系列接口后能够导出RTF格式文本的),比如说系统的写字板。
你先用windows自带的画图程序打开任一幅JPEG图像,然后COPY。再打开系统自带的写字板,PASTE,你发现图像已粘到了写字板中。不过别高兴太早,你点保存后关闭文档,再打开--发现里面并没有图像。核实文档大小---图像确未被导出保存。
虽然上述现像仅是在特定条件下才会出现,但本着追求完美的愿望,我将其一个解决方法公布(应该还有更好办法)
我分析了剪贴板中数据类型,发现不管是由画图程序,还是其它程序送来的图像数据,都以CF_DIB类型为主。那即然都以此为主,为什么偏偏RichEdit就不导出画图程序送到剪贴板的数据呢? 我对图像格式及OLE这些东西并不了解。但猜测是不是有画蛇添足的东西,于是我将RichEdit控件窗口子类化,捕获CTRL+V,然后导出CF_DIB数据,再清空剪贴板,最后用先前导出的数据重设剪贴板。(剪贴板中原先有好几种数据类型呢) 哈哈,问题居然由此解决了!!
贴上相关代码:(本人是用API的)
//提供对windows剪贴板操作的支持 该函数应使用new方法来创建(别忘了delete)class CClipboard{public :CClipboard();
~CClipboard();
//失败返回0
UINT GetNextStyle(void);//头一次调用该函数O_buffer赋NULL,获取数据长度先
BOOL GetData(UINT I_style,PBYTE O_buffer,size_t & O_size);BOOL SetData(UINT I_style,PBYTE I_buffer,size_t I_size);//清空剪贴板
BOOL Empty(void);private :
UINT formatsStyle[16];
};//end class
CClipboard::CClipboard()
{
int n=0;
UINT iFormat=0; for(int i=0;i<16;++i)
{formatsStyle[i]=0;} if( OpenClipboard (NULL) )
{
while ( iFormat = EnumClipboardFormats (iFormat) )
{
formatsStyle[n] = iFormat; if( (++n)>15 )
break ;
}
}//end if}//end fun
CClipboard::~CClipboard()
{ CloseClipboard () ;}//end funUINT CClipboard::GetNextStyle(void)
{
static int i=0; if(i==16)
{i=0; return 0 ;} return ( formatsStyle[i++] );}//end fun
BOOL CClipboard::GetData(UINT I_style,PBYTE O_buffer,size_t & O_size)
{
GLOBALHANDLE hGlobal ;
LPVOID pGlobal ;
if( NULL == (hGlobal = (GLOBALHANDLE)GetClipboardData (I_style)) )
{
MessageBox(NULL,TEXT("GetClipboardData失败!"),TEXT("CClipboard::GetData"),MB_ICONSTOP);
return FALSE ;
} O_size=GlobalSize (hGlobal); if(O_buffer==NULL)
{return TRUE;} pGlobal = GlobalLock (hGlobal) ;
CopyMemory(O_buffer,(PBYTE)pGlobal,O_size); GlobalUnlock (hGlobal) ; return TRUE ;}//end fun
BOOL CClipboard::Empty(void)
{
return EmptyClipboard( ) ;}//end fun
BOOL CClipboard::SetData(UINT I_style,PBYTE I_buffer,size_t I_size)
{
GLOBALHANDLE hGlobal ;
LPVOID pGlobal ; if( NULL==(hGlobal = GlobalAlloc (GHND | GMEM_SHARE, I_size)) )
{
MessageBox(NULL,TEXT("分配内存失败!"),TEXT("CClipboard::SetData"),MB_ICONSTOP);
return FALSE ;
} pGlobal = GlobalLock (hGlobal) ; CopyMemory((PBYTE)pGlobal,I_buffer,I_size); GlobalUnlock (hGlobal) ; if ( NULL==SetClipboardData (I_style, hGlobal) )
{
MessageBox(NULL,TEXT("SetClipboardData失败!"),TEXT("CClipboard::SetData"),MB_ICONSTOP);
return FALSE ;
} return TRUE ;
}//end fun
////////////////////////////////////////////
//窗口子类化RichEdit
LRESULT CALLBACK EditProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
CClipboard * pClb = NULL ;
UINT style=0;
size_t size ;
PBYTE pb=NULL; if(message==WM_KEYDOWN)
{
//如果按下了CTRL+V
//目的是要修正剪贴薄中图像
if ( (wParam==86) && ((GetKeyState(VK_CONTROL) && 0x1000) == 1) )
{
pClb=new CClipboard();
while(style=pClb->GetNextStyle())
{
if(style==CF_DIBV5)//处理CF_DIB应该一样
{
pClb->GetData(style,NULL,size);
pb=(PBYTE)malloc(size+2);
if (! pClb->GetData(style,pb,size))
{break;} pClb->Empty(); pClb->SetData(style,pb,size);
}
} delete pClb ;
}// if ( (wParam==86)...
}//end if(message==WM_KEYUP) return CallWindowProc (edit.OldProc, hwnd, message, wParam, lParam) ;
}//end fun欢迎大家批抨指正!本人QQ 184263203
你先用windows自带的画图程序打开任一幅JPEG图像,然后COPY。再打开系统自带的写字板,PASTE,你发现图像已粘到了写字板中。不过别高兴太早,你点保存后关闭文档,再打开--发现里面并没有图像。核实文档大小---图像确未被导出保存。
虽然上述现像仅是在特定条件下才会出现,但本着追求完美的愿望,我将其一个解决方法公布(应该还有更好办法)
我分析了剪贴板中数据类型,发现不管是由画图程序,还是其它程序送来的图像数据,都以CF_DIB类型为主。那即然都以此为主,为什么偏偏RichEdit就不导出画图程序送到剪贴板的数据呢? 我对图像格式及OLE这些东西并不了解。但猜测是不是有画蛇添足的东西,于是我将RichEdit控件窗口子类化,捕获CTRL+V,然后导出CF_DIB数据,再清空剪贴板,最后用先前导出的数据重设剪贴板。(剪贴板中原先有好几种数据类型呢) 哈哈,问题居然由此解决了!!
贴上相关代码:(本人是用API的)
//提供对windows剪贴板操作的支持 该函数应使用new方法来创建(别忘了delete)class CClipboard{public :CClipboard();
~CClipboard();
//失败返回0
UINT GetNextStyle(void);//头一次调用该函数O_buffer赋NULL,获取数据长度先
BOOL GetData(UINT I_style,PBYTE O_buffer,size_t & O_size);BOOL SetData(UINT I_style,PBYTE I_buffer,size_t I_size);//清空剪贴板
BOOL Empty(void);private :
UINT formatsStyle[16];
};//end class
CClipboard::CClipboard()
{
int n=0;
UINT iFormat=0; for(int i=0;i<16;++i)
{formatsStyle[i]=0;} if( OpenClipboard (NULL) )
{
while ( iFormat = EnumClipboardFormats (iFormat) )
{
formatsStyle[n] = iFormat; if( (++n)>15 )
break ;
}
}//end if}//end fun
CClipboard::~CClipboard()
{ CloseClipboard () ;}//end funUINT CClipboard::GetNextStyle(void)
{
static int i=0; if(i==16)
{i=0; return 0 ;} return ( formatsStyle[i++] );}//end fun
BOOL CClipboard::GetData(UINT I_style,PBYTE O_buffer,size_t & O_size)
{
GLOBALHANDLE hGlobal ;
LPVOID pGlobal ;
if( NULL == (hGlobal = (GLOBALHANDLE)GetClipboardData (I_style)) )
{
MessageBox(NULL,TEXT("GetClipboardData失败!"),TEXT("CClipboard::GetData"),MB_ICONSTOP);
return FALSE ;
} O_size=GlobalSize (hGlobal); if(O_buffer==NULL)
{return TRUE;} pGlobal = GlobalLock (hGlobal) ;
CopyMemory(O_buffer,(PBYTE)pGlobal,O_size); GlobalUnlock (hGlobal) ; return TRUE ;}//end fun
BOOL CClipboard::Empty(void)
{
return EmptyClipboard( ) ;}//end fun
BOOL CClipboard::SetData(UINT I_style,PBYTE I_buffer,size_t I_size)
{
GLOBALHANDLE hGlobal ;
LPVOID pGlobal ; if( NULL==(hGlobal = GlobalAlloc (GHND | GMEM_SHARE, I_size)) )
{
MessageBox(NULL,TEXT("分配内存失败!"),TEXT("CClipboard::SetData"),MB_ICONSTOP);
return FALSE ;
} pGlobal = GlobalLock (hGlobal) ; CopyMemory((PBYTE)pGlobal,I_buffer,I_size); GlobalUnlock (hGlobal) ; if ( NULL==SetClipboardData (I_style, hGlobal) )
{
MessageBox(NULL,TEXT("SetClipboardData失败!"),TEXT("CClipboard::SetData"),MB_ICONSTOP);
return FALSE ;
} return TRUE ;
}//end fun
////////////////////////////////////////////
//窗口子类化RichEdit
LRESULT CALLBACK EditProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
CClipboard * pClb = NULL ;
UINT style=0;
size_t size ;
PBYTE pb=NULL; if(message==WM_KEYDOWN)
{
//如果按下了CTRL+V
//目的是要修正剪贴薄中图像
if ( (wParam==86) && ((GetKeyState(VK_CONTROL) && 0x1000) == 1) )
{
pClb=new CClipboard();
while(style=pClb->GetNextStyle())
{
if(style==CF_DIBV5)//处理CF_DIB应该一样
{
pClb->GetData(style,NULL,size);
pb=(PBYTE)malloc(size+2);
if (! pClb->GetData(style,pb,size))
{break;} pClb->Empty(); pClb->SetData(style,pb,size);
}
} delete pClb ;
}// if ( (wParam==86)...
}//end if(message==WM_KEYUP) return CallWindowProc (edit.OldProc, hwnd, message, wParam, lParam) ;
}//end fun欢迎大家批抨指正!本人QQ 184263203
if(style==CF_DIBV5)//原代码改为:
if( (style==CF_DIB)||(style==CF_DIBV5) ) 这样就OK了