将Vcl::Controls::TCaption(也称为System::UnicodeString)转换为const char *

3

我目前正在使用C++Builder创建一个应用程序,将文本复制到用户的剪贴板中。我放置了一个TMemo控件,并希望将其包含在const char *变量中,如下面的代码所示:

const char* output = TMemo1->Text;

当我编译程序时,它会抛出错误:

从“Vcl::Controls::TCaption”(又名“System::UnicodeString”)到“const char *”没有可行的转换

这是将文本复制到剪贴板的代码:

const char* output = TMemo1->Text; // Error here
const size_t len = strlen(output) + 1;
HGLOBAL hMem =  GlobalAlloc(GMEM_MOVEABLE, len);
memcpy(GlobalLock(hMem), output, len);
GlobalUnlock(hMem);
OpenClipboard(0);
EmptyClipboard();
SetClipboardData(CF_TEXT, hMem);
CloseClipboard();
1个回答

5

Text 属性返回的是一个 UnicodeString 对象,而不是一个 const char* 指针。同时,也没有从 UnicodeStringconst char* 的隐式转换(也不需要这样做)。因此,需要手动转换数据,例如使用 WideCharToMultiByte()(或类似函数),示例如下:

UnicodeString text = TMemo1->Text;
const size_t len = WideCharToMultiByte(CP_ACP, 0, text.c_str(), -1, NULL, 0, NULL, NULL);
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, len);
if (hMem)
{
    char *output = (char*) GlobalLock(hMem);
    WideCharToMultiByte(CP_ACP, 0, text.c_str(), -1, output, len, NULL, NULL);
    GlobalUnlock(hMem);
    if (OpenClipboard(0))
    {
        EmptyClipboard();
        if (SetClipboardData(CF_TEXT, hMem))
            hMem = NULL;
        CloseClipboard();
    }
    if (hMem)
        GlobalFree(hMem);
}

另外,您可以将 TMemo 的文本保存到 AnsiString 中,并让 RTL 为您处理转换,例如:

AnsiString output = TMemo1->Text; // <-- automatic conversion from UTF-16 to ANSI
const size_t len = (output.Length() + 1) * sizeof(System::AnsiChar);
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, len);
if (hMem)
{
    memcpy(GlobalLock(hMem), output.c_str(), len);
    GlobalUnlock(hMem);
    if (OpenClipboard(0))
    {
        EmptyClipboard();
        if (SetClipboardData(CF_TEXT, hMem))
            hMem = NULL;
        CloseClipboard();
    }
    if (hMem)
        GlobalFree(hMem);
}

然而,由于涉及到Unicode文本,您应该使用CF_UNICODETEXT格式而不是CF_TEXT。这样,您就不需要转换UnicodeString数据,只需将其原样存储(如果之后有人从剪贴板请求CF_TEXT剪贴板本身会为您转换文本),例如:
#include <System.SysUtils.hpp> // for ByteLength()

UnicodeString output = TMemo1->Text;
const size_t len = ByteLength(output) + sizeof(System::WideChar);
HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, len);
if (hMem)
{
    memcpy(GlobalLock(hMem), output.c_str(), len);
    GlobalUnlock(hMem);
    if (OpenClipboard(0))
    {
        EmptyClipboard();
        if (SetClipboardData(CF_UNICODETEXT, hMem))
            hMem = NULL;
        CloseClipboard();
    }
    if (hMem)
        GlobalFree(hMem);
}

话虽如此,您正在使自己的事情比必要的更加困难。 VCL有一个TClipboard类来处理这些细节,例如:

#include <Vcl.Clipbrd.hpp>

Clipboard()->AsText = TMemo1->Text;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接