日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > windows >内容正文

windows

windows剪切板暂存

發(fā)布時間:2024/6/14 windows 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 windows剪切板暂存 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

其實最初是因為在項目中使用了html網(wǎng)頁編輯器,通過ie的com組件和javascript通訊完成一些事情,其中有一個功能是插入表格,我們原本使用的range.pasteHTML(HTMLstr);根據(jù)用戶傳入的行和列等參數(shù)在javascript端創(chuàng)建好用戶想要的表格的html字串,然后的然后,測試人員就發(fā)現(xiàn)一個bug,因為這種pasterHTML會破壞TextArea原本的剪切板內(nèi)容,會直接導(dǎo)致無法撤銷到插入表格之前(包含插入表格)的狀態(tài)。

有一個同事想出一個方法,使用剪切板來代替pasterHTML這樣的操作,因為粘貼一個html有格式的內(nèi)容是可以撤銷的,這樣就又會涉及到一個問題,如果借用了剪切板的內(nèi)容就需要備份之前的內(nèi)容,并在使用完之后恢復(fù),不管原來是圖片、純文本、還是word、表格、帶格式的復(fù)雜的內(nèi)容。

首先在MSDN上找到這篇文章:http://msdn.microsoft.com/en-us/library/windows/desktop/ms649015%28v=vs.85%29.aspx

因為我需要加入的是一個html表格所以找來了它所需要的格式,并使用SetClipboardData進(jìn)行設(shè)置。

官方格式示例:

Version:0.9 StartHTML:71 EndHTML:170 StartFragment:140 EndFragment:160 StartSelection:140 EndSelection:160 <!DOCTYPE> <HTML> <HEAD> <TITLE> The HTML Clipboard</TITLE> <BASE HREF="http://sample/specs"> </HEAD> <BODY> <UL> <!--StartFragment --> <LI> The Fragment </LI> <!--EndFragment --> </UL> </BODY> </HTML> View Code

構(gòu)造header代碼:

1 int ClipboardHTMLHeader::size() const 2 { 3 const int numSpaces = 8; 4 int headerSIZE = 8/*strlen("Version:")*/ + strlen(version); 5 headerSIZE += 10/*strlen("StartHTML:")*/ + numSpaces; 6 headerSIZE += 8/*strlen("EndHTML:")*/ + numSpaces; 7 headerSIZE += 14/*strlen("StartFargment:")*/ + numSpaces; 8 headerSIZE += 12/*strlen("EndFargment:")*/ + numSpaces; 9 //headerSIZE += 15/*strlen("StartSelection:")*/ + numSpaces; 10 //headerSIZE += 13/*strlen("EndSelection:")*/ + numSpaces; 11 headerSIZE += 5/*fields*/ * 1; 12 return headerSIZE; 13 } 14 15 std::ostream& operator <<(std::ostream& os, const ClipboardHTMLHeader& header) 16 { 17 using namespace std; 18 const int numSpaces = 8; 19 const int headerSIZE = header.size(); 20 21 os << "Version:" << header.version << endl 22 << "StartHTML:" << setw(numSpaces) << setfill('0') << (header.StartHTML < 0 ? -1 : headerSIZE + header.StartHTML) << endl 23 << "EndHTML:" << setw(numSpaces) << setfill('0') << (header.EndHTML < 0 ? -1 : headerSIZE + header.EndHTML) << endl 24 << "StartFragment:" << setw(numSpaces) << setfill('0') << (header.StartFragment < 0 ? -1 : headerSIZE + header.StartFragment) << endl 25 << "EndFragment:" << setw(numSpaces) << setfill('0') << (header.EndFragment < 0 ? -1 : headerSIZE + header.EndFragment) << endl; 26 //<< "StartSelection:" << setw(numSpaces) << setfill('0') << (header.StartSelection < 0 ? -1 : headerSIZE + header.StartSelection) << endl 27 //<< "EndSelection:" << setw(numSpaces) << setfill('0') << (header.EndSelection < 0 ? -1 : headerSIZE + header.EndSelection) << endl; 28 return os; 29 } 30 31 bool CRichEditor::CopyHTMLToClipboard(LPCWSTR lpszWide) 32 { 33 using namespace std; 34 35 string html = "<!--StartFragment-->" + decode(lpszWide, CP_UTF8) + "<!--EndFragment-->"; 36 char docBegin[] = "<HTML><HEAD><TITLE>*</TITLE></HEAD><BODY>"; 37 char docEnd[]="</BODY></HTML>"; 38 39 ClipboardHTMLHeader h; 40 h.version = "0.9"; 41 h.StartHTML = 0; 42 h.EndHTML = sizeof(docBegin) + html.length() + sizeof(docEnd); 43 h.StartFragment = sizeof(docBegin); 44 h.EndFragment = sizeof(docBegin) + html.length(); 45 //h.StartSelection = h.StartFragment; 46 //h.EndSelection = h.EndFragment; 47 48 stringstream ss; 49 ss << h; 50 ss << docBegin; 51 ss << html; 52 ss << docEnd; 53 54 55 56 // Get clipboard id for HTML format... 57 static int cfid = 0; 58 cfid = RegisterClipboardFormat(L"HTML Format"); 59 // Open the clipboard... 60 if(::OpenClipboard(0)) { 61 EmptyClipboard(); 62 63 HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE/* |GMEM_DDESHARE*/, (int)ss.tellp() + 1); 64 char* buf = (char*)GlobalLock(hMem); 65 ss.read( buf, ss.tellp()); 66 buf[ss.tellp()] = 0; 67 GlobalUnlock(hMem); 68 69 ::SetClipboardData(cfid, hMem); 70 CloseClipboard(); 71 GlobalFree(hMem); 72 } 73 74 return false; 75 }

其中selection是可選的,重載了運(yùn)算符<<,且定義了很多int類型記錄它們的偏移量。

接下來需要在insert table的之前深拷貝剪切板的內(nèi)容到內(nèi)存中,在時候恢復(fù)內(nèi)存的數(shù)據(jù)到剪切板中,這其中對用戶都是不可知的并且速度也是相當(dāng)快的。

剛開始我們以為GlobalLock剪切板所獲得的內(nèi)存塊是安全的,所以寫了代碼在push的時候lock,然后在pop的時候unlock,誰知道調(diào)用EmptyClipboard后就照樣清空了,只能老老實實的拷貝全部的內(nèi)存數(shù)據(jù)了,我們采用了map來暫存剪切板中各種類型的數(shù)據(jù),針對不同的format的clipboard分別存到不同的map中。

1 std::map<UINT, HGLOBAL> _clipdata; 2 void CRichEditor::popClipboardData() 3 { 4 ::OpenClipboard(0); 5 ::EmptyClipboard(); 6 for (auto it = _clipdata.begin(); it != _clipdata.end(); ++it) 7 ::SetClipboardData(it->first, it->second); 8 ::CloseClipboard(); 9 10 for (auto it = _clipdata.begin(); it != _clipdata.end(); ++it) 11 ::GlobalFree(it->second); 12 13 _clipdata.clear(); 14 } 15 16 void CRichEditor::pushClipboardData() 17 { 18 ::OpenClipboard(0); 19 20 for (UINT next = ::EnumClipboardFormats(0); next != 0; next = ::EnumClipboardFormats(next)) 21 { 22 if(::IsClipboardFormatAvailable(next)) 23 { 24 HGLOBAL hmem = ::GetClipboardData(next); 25 void* src = ::GlobalLock(hmem); 26 SIZE_T bytes = ::GlobalSize(hmem); 27 28 _clipdata[next] = ::GlobalAlloc( GMEM_MOVEABLE, bytes ); 29 30 void* dst = ::GlobalLock( _clipdata[next] ); 31 memcpy(dst, src, bytes); 32 ::GlobalUnlock(_clipdata[next]); 33 34 ::GlobalUnlock(hmem); 35 } 36 } 37 38 ::EmptyClipboard(); 39 ::CloseClipboard(); 40 }

切記第10、11行必須這樣寫,必須在CloseClipboard之后來GlobalFree,否則就沒辦法恢復(fù)到備份clipboard之前的狀態(tài)了。

差不多到這里就是今天一天的奇遇的全部內(nèi)容了。。。

相信很多人碰到這個問題的時候最開始都受到

http://stackoverflow.com/questions/15962982/how-to-set-html-unicode-text-to-clipboard-in-vc

http://social.msdn.microsoft.com/Forums/es-ES/acc07c85-d0d3-4c4d-83e9-08f1a239758c/how-to-set-html-unicode-text-to-clipboard-in-vc?forum=vcgeneral

所誤導(dǎo),根本就不能用,問題是代碼寫的亂七八糟,怕是只有自己能看得懂。例如105這個數(shù)值是怎么來的?length+4又為什么?

希望祖國的花朵們不要再受到外國人的毒代碼摧殘了。。.今天就寫到這里,希望black早點(diǎn)回家~

轉(zhuǎn)載于:https://www.cnblogs.com/hyb1/p/3378065.html

總結(jié)

以上是生活随笔為你收集整理的windows剪切板暂存的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。