GetClipboardData(CF_UNICODETEXT);

时间:2013-03-12 13:40:56

标签: c++ unicode clipboard

请告诉我,为什么我会遇到这个问题:

  • 如果剪贴板包含unicode字符(e.q。俄语)我只得到第一个选中的单词。 “空间”字符前的第一个字。

  • 如果剪贴板不包含unicode字符(仅限英文)我会获得所选文本的第一个字符。

获取所选文字:

CStringA getClipboard()
{
     CStringA strData;

     if (OpenClipboard(NULL)){

         HANDLE hClipboardData = GetClipboardData(CF_UNICODETEXT);
         char *pchData = (char*)GlobalLock(hClipboardData);
         strData = pchData;
         GlobalUnlock(hClipboardData);
         CloseClipboard();

    }
    return strData;
}

设置文字:

bool setClipboard(CStringA textToclipboard)
{
    bool success = true;

    if (OpenClipboard(NULL)){

        EmptyClipboard();
        HGLOBAL hClipboardData;
        size_t size = (textToclipboard.GetLength()+1) * sizeof(TCHAR);
        hClipboardData = GlobalAlloc(NULL, size);
        TCHAR* pchData = (TCHAR*)GlobalLock(hClipboardData);
        memcpy(pchData, LPCTSTR(textToclipboard.GetString()), size);
        SetClipboardData(CF_UNICODETEXT, hClipboardData);
        GlobalUnlock(hClipboardData);
        CloseClipboard();
    }

    return success;

}

只需获取并设置剪贴板内容。

CStringA str = getClipboard();
setClipboard(str);

2 个答案:

答案 0 :(得分:9)

CF_UNICODETEXT使用UTF-16。在Windows上,wchar_t数据元素用于UTF-16,但您的代码使用的是charCStringA与UTF-16不兼容。您在两个函数中的数据不匹配,这就是您没有得到预期结果的原因。

一种解决方案是使用CStringW代替CStringA

CStringW getClipboard()
{
    CStringW strData;

    if (OpenClipboard(NULL))
    {
        HANDLE hClipboardData = GetClipboardData(CF_UNICODETEXT);
        if (hClipboardData)
        {
            WCHAR *pchData = (WCHAR*) GlobalLock(hClipboardData);
            if (pchData)
            {
                strData = pchData;
                GlobalUnlock(hClipboardData);
            }
        }
        CloseClipboard();
    }
    return strData;
}

bool setClipboard(CStringW textToclipboard)
{
    bool success = true;

    if (OpenClipboard(NULL))
    {
        EmptyClipboard();
        size_t size = (textToclipboard.GetLength()+1) * sizeof(WCHAR);
        HGLOBAL hClipboardData = GlobalAlloc(NULL, size);
        if (hClipboardData)
        {
            WCHAR* pchData = (WCHAR*) GlobalLock(hClipboardData);
            if (pchData)
            {
                memcpy(pchData, (WCHAR*) textToclipboard.GetString(), size);
                GlobalUnlock(hClipboardData);
                SetClipboardData(CF_UNICODETEXT, hClipboardData);
            }
        }
        CloseClipboard();
    }
    return success;
}

如果你需要坚持CStringA,那么:

  1. 使用CF_TEXT代替CF_UNICODETEXT,让剪贴板为您处理Ansi和Unicode之间的转换:

    CStringA getClipboard()
    {
        CStringA strData;
    
        if (OpenClipboard(NULL))
        {
            HANDLE hClipboardData = GetClipboardData(CF_TEXT);
            if (hClipboardData)
            {
                CHAR *pchData = (CHAR*) GlobalLock(hClipboardData);
                if (pchData)
                {
                    strData = pchData;
                    GlobalUnlock(hClipboardData);
                }
            }
            CloseClipboard();
        }
        return strData;
    }
    
    bool setClipboard(CStringA textToclipboard)
    {
        bool success = true;
    
        if (OpenClipboard(NULL))
        {
            EmptyClipboard();
            size_t size = (textToclipboard.GetLength()+1) * sizeof(CHAR);
            HGLOBAL hClipboardData = GlobalAlloc(NULL, size);
            if (hClipboardData)
            {
                CHAR* pchData = (CHAR*) GlobalLock(hClipboardData);
                if (pchData)
                {
                    memcpy(pchData, (CHAR*) textToclipboard.GetString(), size);
                    GlobalUnlock(hClipboardData);
                    SetClipboardData(CF_TEXT, hClipboardData);
                }
            }
            CloseClipboard();
        }
        return success;
    }
    
  2. 使用CF_UNICODETEXT时手动转换为UTF-16:

    CStringA getClipboard()
    {
        CStringW strData;
    
        if (OpenClipboard(NULL))
        {
            HANDLE hClipboardData = GetClipboardData(CF_UNICODETEXT);
            if (hClipboardData)
            {
                WCHAR *pchData = (WCHAR*) GlobalLock(hClipboardData);
                if (pchData)
                {
                    strData = pchData;
                    GlobalUnlock(hClipboardData);
                }
            }
            CloseClipboard();
        }
    
        return CStringA((WCHAR*)strData.GetString());
    }
    
    bool setClipboard(CStringA strData)
    {
        CStringW textToclipboard((CHAR*)strData.GetString());
        bool success = true;
    
        if (OpenClipboard(NULL))
        {
            EmptyClipboard();
            size_t size = (textToclipboard.GetLength()+1) * sizeof(WCHAR);
            HGLOBAL hClipboardData = GlobalAlloc(NULL, size);
            if (hClipboardData)
            {
                WCHAR* pchData = (WCHAR*) GlobalLock(hClipboardData);
                if (pchData)
                {
                    memcpy(pchData, (WCHAR*) textToclipboard.GetString(), size);
                    GlobalUnlock(hClipboardData);
                    SetClipboardData(CF_UNICODETEXT, hClipboardData);
                }
            }
            CloseClipboard();
        }
        return success;
    }
    
  3. 另一种解决方案是使用CString代替CStringACStringW,然后使用CF_TEXTCF_UNICODETEXT,具体取决于TCHAR是Ansi还是Unicode:

    #ifdef UNICODE
    #define CF_TEXT_T CF_UNICODETEXT
    #else
    #define CF_TEXT_T CF_TEXT
    #endif
    
    CString getClipboard()
    {
        CString strData;
    
        if (OpenClipboard(NULL))
        {
            HANDLE hClipboardData = GetClipboardData(CF_TEXT_T);
            if (hClipboardData)
            {
                TCHAR *pchData = (TCHAR*) GlobalLock(hClipboardData);
                if (pchData)
                {
                    strData = pchData;
                    GlobalUnlock(hClipboardData);
                }
            }
            CloseClipboard();
        }
        return strData;
    }
    
    bool setClipboard(CString textToclipboard)
    {
        bool success = true;
    
        if (OpenClipboard(NULL))
        {
            EmptyClipboard();
            size_t size = (textToclipboard.GetLength()+1) * sizeof(TCHAR);
            HGLOBAL hClipboardData = GlobalAlloc(NULL, size);
            if (hClipboardData)
            {
                TCHAR* pchData = (TCHAR*) GlobalLock(hClipboardData);
                if (pchData)
                {
                    memcpy(pchData, (TCHAR*) textToclipboard.GetString(), size);
                    GlobalUnlock(hClipboardData);
                    SetClipboardData(CF_TEXT_T, hClipboardData);
                }
            }
            CloseClipboard();
        }
        return success;
    }
    

答案 1 :(得分:5)

它们都是Unicode ......

但在Unicode中,更多的是一个字节代表一个字符。例如,可能有2个字节用于字符。因此:

当它是俄语时,字符串就像

                                                            '\0'
                                                            ----
0x04 0x3F 0x04 0x40 0x04 0x38 0x04 0x32 0x04 0x35 0x04 0x42 0x00 0x20
~~~~~~~~~ ~~~~~~~~~ ~~~~~~~~~ ~~~~~~~~~ ~~~~~~~~~ ~~~~~~~~~ ~~~~~~~~~
    п         р         и        в          е         т       space

它读到太空。

当它是英文时,字符串就像

'\0'
----
0x00 0x48 0x00 0x65 0x00 0x6C 0x00 0x6C 0x00 0x6F 0x00 0x20
~~~~~~~~~ ~~~~~~~~~ ~~~~~~~~~ ~~~~~~~~~ ~~~~~~~~~ ~~~~~~~~~
   H          e         l        l          o       space

它什么都没读。 (如果你先读,那是因为存储字节,LE或BE的顺序)

注意:也许我选择单词不精确(Unicode,UTF,...)