Как установить текст HTML Unicode в буфер обмена в VC ++?

Я новичок в C ++. Я хочу получить содержимое буфера обмена, которое может содержать символы Unicode, добавить тег div с некоторым содержимым, отформатированным в HTML, и вернуть его обратно в буфер обмена.

Я успешно добился получения и добавления контента. Но не мог установить его обратно в буфер обмена как текст HTML. Я достиг настройки как простой текст. Вот мой код:

#include <shlwapi.h>
#include <iostream>
#include <conio.h>
#include <stdio.h>

using namespace std;

wstring getClipboard(){
if (OpenClipboard(NULL)){
HANDLE clip = GetClipboardData(CF_UNICODETEXT);
WCHAR * c;
c = (WCHAR *)clip;
CloseClipboard();
return (WCHAR *)clip;
}
return L"";
}

bool setClipboard(wstring textToclipboard)
{
if (OpenClipboard(NULL)){
EmptyClipboard();
HGLOBAL hClipboardData;
size_t size = (textToclipboard.length()+1) * sizeof(WCHAR);
hClipboardData = GlobalAlloc(NULL, size);
WCHAR* pchData = (WCHAR*)GlobalLock(hClipboardData);
memcpy(pchData, textToclipboard.c_str(), size);
SetClipboardData(CF_UNICODETEXT, hClipboardData);
GlobalUnlock(hClipboardData);
CloseClipboard();
return true;
}
return false;
}

int main (int argc, char * argv[])
{
wstring  s =  getClipboard();
s += std::wstring(L"some extra text <b>hello</b>");
setClipboard(s);
getch();
return 0;
}

Я попробовал использовать описанный код Вот и читать документ Вот. Но я не мог заставить это работать. То, что я пытался сделать, могло быть совершенно неверным или совершенно неправильным.

Обновить: Приведенный ниже код является тем, что я пробовал после модификаций, предложенных Коди Грэем для исходного кода Вот:

bool CopyHTML2(WCHAR *html ){

wchar_t *buf = new wchar_t [400 + wcslen(html)];
if(!buf) return false;

static int cfid = 0;
if(!cfid) cfid = RegisterClipboardFormat("HTML Format");// Create a template string for the HTML header...
wcscpy(buf,
L"Version:0.9\r\n"L"StartHTML:00000000\r\n"L"EndHTML:00000000\r\n"L"StartFragment:00000000\r\n"L"EndFragment:00000000\r\n"L"<html><body>\r\n"L"<!--StartFragment -->\r\n");

// Append the HTML...
wcscat(buf, html);
wcscat(buf, L"\r\n");
// Finish up the HTML format...
wcscat(buf,
L"<!--EndFragment-->\r\n"L"</body>\r\n"L"</html>");

wchar_t *ptr = wcsstr(buf, L"StartHTML");
wsprintfW(ptr+10, L"%08u", wcsstr(buf, L"<html>") - buf);
*(ptr+10+8) = L'\r';

ptr = wcsstr(buf, L"EndHTML");
wsprintfW(ptr+8, L"%08u", wcslen(buf));
*(ptr+8+8) = '\r';

ptr = wcsstr(buf, L"StartFragment");
wsprintfW(ptr+14, L"%08u", wcsstr(buf, L"<!--StartFrag") - buf);
*(ptr+14+8) = '\r';

ptr = wcsstr(buf, L"EndFragment");
wsprintfW(ptr+12, L"%08u", wcsstr(buf, L"<!--EndFrag") - buf);
*(ptr+12+8) = '\r';

// Open the clipboard...
if(OpenClipboard(0)) {
EmptyClipboard();
HGLOBAL hText = GlobalAlloc(GMEM_MOVEABLE |GMEM_DDESHARE, wcslen(buf)+4);
wchar_t *ptr = (wchar_t *)GlobalLock(hText);
wcscpy(ptr, buf);
GlobalUnlock(hText);
SetClipboardData(cfid, hText);
CloseClipboard();
GlobalFree(hText);
}

// Clean up...
delete [] buf;
return true;
}

Этот код успешно компилируется, но я получаю следующую ошибку в SetClipboardData: HEAP[Project1.exe]: Heap block at 007A8530 modified at 007A860A past requested size of d2
Project1.exe has triggered a breakpoint.

Пожалуйста, объясните мне, как действовать дальше. Я использую Visual Studio Express 2012 на Windows 8. Спасибо.

2

Решение

Вы не соответствуете ANSI (узкие) и Unicode (широкие) строки.

в отличие от wcscpy функция, w в wsprintf функция не расшифровывается как «широкая», она обозначает «Windows». Это часть Win32 API, а не библиотека времени выполнения C. Все функции Win32 API, работающие со строками, имеют две версии, одна с суффиксом A который имеет дело со строками ANSI и другой с суффиксом W это имеет дело с широкими строками. Заголовки скрывают все это от вас с помощью макросов. Я объясню все это более подробно Вот— рекомендуемое чтение.

В любом случае, простое исправление здесь заключается в явном вызове широкого варианта этой функции, поскольку вы правильно используете широкие строки везде. Сделайте все звонки на wsprintf выглядеть так:

wchar_t *ptr = wcsstr(buf, L"StartHTML");
wsprintfW(ptr+10, L"%08u", wcsstr(buf, L"<html>") - buf);
*(ptr+10+8) = L'\r';

В качестве альтернативы, вы можете использовать swprintf функция, предоставляемая библиотекой времени выполнения C вместо версии Win32. Этот работает так же, как wcsstr а также wcscpy функции, которые вы используете в другом месте. w в названии означает «широкий». Документация для этой серии функций Вот.

Также обратите внимание, что когда вы используете символьные или строковые литералы, они также должны быть широкими символами. Вы достигаете этого, добавляя их L, Вы делаете это в одних местах, но скучаете по другим. Убедитесь, что вы делаете это последовательно.

Хотя компилятор должен предупредить вас обо всем этом. Вам просто нужно убедиться, что вы повысили уровень предупреждения и не игнорировать ни одно из предупреждений. Также убедитесь, что оба UNICODE а также _UNICODE Символы препроцессора определены глобально для вашего проекта. Это гарантирует, что вы всегда вызываете Unicode / широкие версии функций. Хотя это должно быть по умолчанию для всех новых проектов.

1

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

Это функция, которую я придумал с помощью Йохен Арндт на codeproject.com. Надеюсь, это кому-нибудь поможет. Вот полный рабочий код, если вы заинтересованы в проверке этого.

У него все еще есть одна проблема. То есть, когда он вставляется в один onenote, он вставляет тарабарщину после тега привязки. Это не происходит с Word, PowerPoint или Excel. И у него нет этой проблемы для обычных текстов на английском языке. Если у вас есть решение для этого, пожалуйста, дайте мне знать. Кажется, проблема в OneNote. Не с кодом.

bool setClipboard(LPCWSTR lpszWide){
int nUtf8Size = ::WideCharToMultiByte(CP_UTF8, 0, lpszWide, -1, NULL, 0, NULL, NULL);
if (nUtf8Size < 1) return false;

const int nDescLen = 105;
HGLOBAL hGlobal = ::GlobalAlloc(GMEM_MOVEABLE, nDescLen + nUtf8Size);
if (NULL != hGlobal)
{
bool bErr = false;
LPSTR lpszBuf = static_cast<LPSTR>(::GlobalLock(hGlobal));
LPSTR lpszUtf8 = lpszBuf + nDescLen;
if (::WideCharToMultiByte(CP_UTF8, 0, lpszWide, -1, lpszUtf8, nUtf8Size, NULL, NULL) <= 0)
{
bErr = true;
}
else
{
LPCSTR lpszStartFrag = strstr(lpszUtf8, "<!--StartFragment-->");
LPCSTR lpszEndFrag = strstr(lpszUtf8, "<!--EndFragment-->");
lpszStartFrag += strlen("<!--StartFragment-->") + 2;

int i = _snprintf(
lpszBuf, nDescLen,
"Version:1.0\r\nStartHTML:%010d\r\nEndHTML:%010d\r\nStartFragment:%010d\r\nEndFragment:%010d\r\n",
nDescLen,
nDescLen + nUtf8Size - 1,       // offset to next char behind string
nDescLen + static_cast<int>(lpszStartFrag - lpszUtf8),
nDescLen + static_cast<int>(lpszEndFrag - lpszUtf8));
}
::GlobalUnlock(hGlobal);
if (bErr)
{
::GlobalFree(hGlobal);
hGlobal = NULL;
}

// Get clipboard id for HTML format...
static int cfid = 0;
cfid = RegisterClipboardFormat("HTML Format");
// Open the clipboard...
if(OpenClipboard(0)) {
EmptyClipboard();
HGLOBAL hText = GlobalAlloc(GMEM_MOVEABLE |GMEM_DDESHARE, strlen(lpszBuf)+4);
char *ptr = (char *)GlobalLock(hText);
strcpy(ptr, lpszBuf);
GlobalUnlock(hText);
::SetClipboardData(cfid, hText);
CloseClipboard();
GlobalFree(hText);
}
}

return NULL != hGlobal;
}
0

По вопросам рекламы [email protected]