使用MFC和Unicode-Build
我想更改listctrl的colum-header-text并且这样做我必须将LPCTSTR转换为LPWSTR。我现在做的是
void CSPCListViewCtrl::SetHeaderText(long lCol, LPCTSTR lColText)
{
CListCtrl& ListCtrl = GetListCtrl();
LV_COLUMN lvc;
::ZeroMemory((void *)&lvc, sizeof(LVCOLUMN));
lvc.mask |= LVCF_TEXT;
ListCtrl.GetColumn(lCol, &lvc);
lvc.pszText = const_cast<LPWSTR>(lColText);
ListCtrl.SetColumn(lCol, &lvc);
}
它似乎工作,但const_cast看起来有些奇怪和错误,所以我尝试了类似
的东西USES_CONVERSION;
lvc.pszText = CT2W(lColText);
这似乎在release-build中工作,但在debug-build中产生垃圾,所以我想知道这样做的正确方法是什么?
答案 0 :(得分:2)
TL;DR:调用CListCtrl::SetColumn时,使用const_cast<LPTSTR>(lColText)
是安全的。
但是为什么LVCOLUMN structure的 pszText 成员声明为非const? LVCOLUMN
结构用于设置和检索信息。检索列的文本时,需要传入可修改的缓冲区(和长度参数)。另一方面,在设置列文本时,系统使用 pszText 成员并在内部存储副本。它不会尝试写入它。这也是documented,即使非常巧妙:
cchTextMax定义
pszText 成员指向的缓冲区的 TCHAR 中的大小。 如果结构未接收有关列的信息,则忽略此成员。
这是Windows API中的常见模式,其中相同的结构用作输入和输出参数。解决这个问题的唯一选择是为这些结构引入const
- ified版本。当Windows API在30年前发明时,这被认为是不必要或有用的。此外,它会使共同模式(读取 - 更新 - 写入)更加繁琐且容易出错,因为必须在不相关的类型之间手动复制数据。
const_cast
是安全的,您可能想知道,如果使用它是个好主意。这取决于许多因素,例如
// Totally safe, it's just that M$ sucks
的某些内容可能不会削减它。const_cast
s?const_cast
的误报?如果您发现无法满意地回答所有这些问题,您可以考虑实施(技术上不必要的)手动复制(并交换const_cast
进行异常处理):
void CSPCListViewCtrl::SetHeaderText(long lCol, LPCTSTR lColText) {
CListCtrl& ListCtrl = GetListCtrl();
LVCOLUMN lvc = {0};
lvc.mask |= LVCF_TEXT;
// Create modifiable copy of lColText
size_t colTextLength = _tcslen(lColText);
std::vector<TCHAR> buffer(colTextLength + 1);
std::copy(lColText, lColText + colTextLength + 1, buffer.data());
lvc.pszText = buffer.data();
ListCtrl.SetColumn(lCol, &lvc);
}
LPCWSTR
,并使用LVCOLUMNW
结构(如果您决定使用const_cast<LPWSTR>
[{"id":"1","title":"Test Event 1","description":"This is the first test event","location":"Acme Hall, Room 101","contact":"John Smith","url":"http:\/\/www.example.com","start":"2016-02-29 13:00:00","end":"2016-02-29 14:00:00"},
{"id":"2","title":"Test Event 2","description":"This is the second test event","location":"Venable Hall, Room 101","contact":"Jane Smith","url":"http:\/\/www.example.com","start":"2016-03-08 09:00:00","end":"2016-03-10 10:45:00"},
{"id":"3","title":"Test Event 3","description":"This is the third test event","location":"Sitterson Hall, Room 200","contact":"Jane Smith","url":"http:\/\/www.example.com","start":"2016-03-18 15:00:00","end":"2016-02-22 16:30:00"}]
路线)。不幸的是,在使用MFC时,在调用任何类成员时,您将不得不求助于使用泛型文本映射。但至少在字符编码不匹配的情况下会出现编译器错误。
答案 1 :(得分:1)
您可以使用CString::GetBuffer()
void SetHeaderText(long lCol, LPCTSTR lColText)
{
LV_COLUMN lvc;
::ZeroMemory((void *)&lvc, sizeof(LVCOLUMN));
lvc.mask |= LVCF_TEXT;
list.GetColumn(lCol, &lvc);
CString str = lColText;
lvc.pszText = str.GetBuffer();
list.SetColumn(lCol, &lvc);
str.ReleaseBuffer();
//ReleaseBuffer is option in this case because
//"str" is local variable and is destroyed before being used again*
}
SetHeaderText(0, L"text");
在UNICODE中,LPTSTR
只是LPWSTR
(或只是wchar_t*
)
如果由于某种原因您有ANSI文本,那么您可以使用CString
进行转换
CStringA ansi = "Text";
CStringW wide = CStringW(ansi);
SetHeaderText(0, wide);