6

教えてください、なぜ私がこの問題を抱えているのですか?

  • クリップボードにUnicode文字(eq russian)が含まれている場合、最初に選択した単語のみを取得します。「スペース」文字の前の最初の単語。

  • クリップボードに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);
4

2 に答える 2

11

CF_UNICODETEXTUTF-16 を使用します。Windows では、wchar_tデータ要素は UTF-16 に使用されますが、コードではchar代わりに使用されています。 CStringAUTF-16 には対応していません。両方の関数でデータが一致していないため、期待する結果が得られません。

CStringW1 つの解決策は、代わりに使用することです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. を使用する場合は、手動で UTF-16 に/から変換しCF_UNICODETEXTます。

    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;
    }
    

もう 1 つの解決策は、 orCStringの代わりに使用し、 Ansi か Unicodeかに応じてCStringAorCStringWを使用することです。CF_TEXTCF_UNICODETEXTTCHAR

#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;
}
于 2013-03-13T05:59:30.123 に答える
5

どちらもユニコード...

しかし、Unicode では、1 バイトを超える文字が文字を表します。たとえば、文字には 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 など)。

于 2013-03-12T13:52:10.913 に答える