GetClipboardData (CF_UNICODETEXT);

Скажите пожалуйста, почему я получаю эти проблемы:

  • если в буфере обмена есть символы Unicode (например, русский), я получаю только первое выбранное слово. Первое слово перед символом «пробел».

  • если в буфере обмена нет символов 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);

5

Решение

CF_UNICODETEXT использует UTF-16. В Windows wchar_t элементы данных используются для UTF-16, но ваш код использует char вместо. CStringA не совместим с 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. конвертировать в / из 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;
    }
    

Другое решение заключается в использовании CString вместо того, чтобы CStringA или же CStringW, а затем использовать CF_TEXT или же CF_UNICODETEXT в зависимости от того TCHAR Анси или Юникод:

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

Другие решения

Они оба 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, …)

5