[心得] 使用剪貼簿的方式將 ANSI 字串轉成 Unicode 字串

看板C_and_CPP作者 (小乖)時間14年前 (2009/09/24 16:13), 編輯推噓3(301)
留言4則, 4人參與, 最新討論串1/1
VC6.0 的 programmer 使用 Visual Studio 2005 常常會遇到 unicode 的問題, 尤其是將 C runtime library 與 win32 API 混用的情況。 C runtime library 接收的字串是使用 ANSI 字元集, 而 win32 API 接受的是 unicode。 解決方法很多種: 1. 在 visual studio 2005 的 compiler 選項中不定義 UNICODE (參考 http://mqjing.blogspot.com/2008/05/c-fprintf-unicode.html) 2. 利用 MultiByteToWideChar or WideCharToMultiByte 轉換 (這兩個函式有點複雜,我一直沒有弄懂過@@) 3. 使用一些高級的函式庫如: boost (還沒試過,不過聽說這個很好用...) 4. 使用 C 程式庫的寬字元版本 5. 剪貼簿 最近看到剪貼簿 (Clipboard) 的使用方式,看到了其中一段 "我有一些好消息,在處理您所想要的文字格式時,您只需要呼叫 SetClipboardData 和 GetClipboardData, Winodws 將處理剪貼簿中所有的文字轉換..." (by Programming Windows 中文版) 看到這一段時,我馬上跳了起來,想說利用剪貼簿做 ANSI 和 Unicode 的轉換應該是有 點搞頭!! 我利用以下的程式案例說明: 案例: 在 current 目錄下,新增一個文字檔,檔名由使用者輸入。 程式流程: 1. 取得目前目錄 path 2. 使用者輸入檔名 3. 將使用者檔名加入 path 4. 開啟檔案 檔案處理 關閉檔案 VC 6.0 ===================================================== #include <Windows.h> #include <stdio.h> int main() { //1. 取得目前目錄 path char pszBuffer[MAX_PATH]; ::GetCurrentDirectory(MAX_PATH,pszBuffer); //2. 使用者輸入檔名 printf("please input file name:\n"); char pszFileName[32]; scanf("%s",pszFileName); //3. 將使用者檔名加入 path sprintf(pszBuffer,"%s\\%s",pszBuffer,pszFileName); //4. 開啟檔案 檔案處理 關閉檔案 FILE *fptr = fopen(pszBuffer , "w"); fprintf(fptr,"我想要變身西裝\n"); fclose(fptr); } ======================================================= 此段 code 在 VC6.0 跑是沒問題 可是轉換成 visual studio 2005 的時候, 因為 win32 API 接受 unicode 所以要想辦法將 ANSI 字串轉成 unicode 字串。 以下利用剪貼簿來實作字串的轉換 Visual Studio 2005 ======================================================= #include <Windows.h> #include <stdio.h> int _tmain(int argc, _TCHAR* argv[]) { //1. 取得目前目錄 path TCHAR pszBuffer[MAX_PATH]; ::GetCurrentDirectory(MAX_PATH,pszBuffer); //2. 使用者輸入檔名 printf("please input file name:\n"); char pszFileName[32]; scanf("%s",pszFileName); //3. 將使用者檔名加入 path //把 ANSI 字串複製到剪貼簿 HGLOBAL hGlobal = GlobalAlloc (GHND | GMEM_SHARE, (strlen (pszFileName) + 1) * sizeof (char)) ; PTSTR pGlobal = (PTSTR)GlobalLock (hGlobal) ; strcpy ((char*)pGlobal, pszFileName) ; GlobalUnlock (hGlobal) ; OpenClipboard (NULL) ; EmptyClipboard () ; SetClipboardData (CF_TEXT, hGlobal) ; CloseClipboard () ; //從剪貼簿取得 Unicode 字串 OpenClipboard (NULL) ; hGlobal = GetClipboardData (CF_UNICODETEXT); pGlobal = (PTSTR)GlobalLock (hGlobal) ; TCHAR* pText = (TCHAR*)malloc (GlobalSize (hGlobal)) ; lstrcpy (pText, pGlobal) ; CloseClipboard () ; //將使用者檔名加入 path wsprintf(pszBuffer,TEXT("%s\\%s"),pszBuffer,pText); //4. 開啟檔案 檔案處理 關閉檔案 FILE *fptr = _tfopen(pszBuffer , L"w"); fprintf(fptr,"輪不到你\n"); fclose(fptr); return 0; } ================================================================== 其中最重要的兩段 //把 ANSI 字串送到剪貼簿 SetClipboardData (CF_TEXT, hGlobal) ; //從剪貼簿取得 Unicode 字串 hGlobal = GetClipboardData (CF_UNICODETEXT); 這種中間我並沒有作任何字串的轉換,因為 Windows 幫我做好了 XD 不過此方法我不知道會不會讓效能變差, 還有剪貼簿被別的 process 改掉可能會導致程式出錯。 這是我的一些心得,請各位大大給一些意見。 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 115.81.197.99

09/24 16:18, , 1F
先推再看
09/24 16:18, 1F

09/24 16:49, , 2F
User: 馬的為什麼我剪貼簿裡面的東西一直不見,中毒了嗎
09/24 16:49, 2F

09/24 16:54, , 3F
樓上推的這個反應好笑....XD
09/24 16:54, 3F

09/24 23:23, , 4F
可以先把剪貼簿存起來, 轉好再幫他還原
09/24 23:23, 4F
文章代碼(AID): #1AkoeEsF (C_and_CPP)