Выравнивание текста и столбца не было правильным в приложении при использовании clistctrl при обновлении VC++ 2015
Я обновляю проект приложения VC++6.0 32bit MFC до VC++2015 для развертывания в windows 7. Ниже приведен метод выравнивания текста.
Метод столбцов:
/**** "|" symbol are used as separators ****/ int CListCtrlEx::CreateColumns(LPCSTR fmt, ...) { ClearAll(); char* buffer = new char[strlen(fmt) + 256]; va_list args; va_start (args,fmt); vsprintf (buffer,fmt,args); va_end (args); CStringEx cols = buffer; int col; for( col = 0; col < cols.GetFieldCount("|"); col++ ) AddColumn(cols.GetField("|", col), col); delete [] buffer; delete [] m_arrayColumnClicks; m_arrayColumnClicks = NULL; m_arrayColumnClicks = new int[col]; int i; for( i = 0; i < col; i++) m_arrayColumnClicks[i] = 1; AutoSizeColumns(); return i; // return column count } int CListCtrlEx::AddColumn(LPCSTR desc, int col, LVCOLUMN* lvc) { if( lvc && lvc->pszText == NULL ) lvc->pszText = (char*)desc; LV_COLUMN t_lvc; t_lvc.mask = lvc ? lvc->mask : LVCF_FMT | LVCF_TEXT | LVCF_WIDTH; t_lvc.fmt = lvc ? lvc->fmt : LVCFMT_LEFT; t_lvc.cx = lvc ? lvc->cx : 75; // in pixels t_lvc.pszText = lvc ? lvc->pszText : (char*)desc; return InsertColumn(col, &t_lvc); } void CListCtrlEx::AutoSizeColumns(int col) { // SetRedraw(FALSE); int mincol = col < 0 ? 0 : col; int maxcol = GetColumnCount(); for( col = mincol; col < maxcol; col++) { SetColumnWidth(col, LVSCW_AUTOSIZE); int wc1 = GetColumnWidth(col); SetColumnWidth(col, LVSCW_AUTOSIZE_USEHEADER); int wc2 = GetColumnWidth(col); int wc = max(wc1, wc2); SetColumnWidth(col,wc); } Invalidate(); }
Приведенный выше код отлично работает с целевой ОС VC++ 6.0 windows xp. Но в VC++2015 он не нацелен на Windows 7.
Хуже всего то, что отладочная версия и версия выпуска показывают различные типы ошибок выравнивания в столбце и тексте.
Что я уже пробовал:
Похоже, это не проблема с кодом.
Есть ли какие-либо связанные с CListCtrl dll-файлы, которые не соответствуют последним версиям? Я включил "legacy_stdio_definitions. lib" в качестве мандата моего проекта ? ОПЕРАЦИОННАЯ
Может быть, переполнение буфера из-за размера бита не совпадает с ранее разработанным проектом в текущей версии ? ОПЕРАЦИОННАЯ
Какие-либо другие предварительные условия должны быть выполнены в настройках ?
Jochen Arndt
Что вы подразумеваете под"ошибкой выравнивания"?
Рендеринг элементов управления списком и шрифтов был изменен начиная с Windows XP, так что получение другого представления на экране является нормальным.
Member 12776813
Не могли бы вы подсказать мне, как исправить эти ошибки рендеринга?
Я должен сделать код мудрым, или добавление каких-либо внешних библиотек поможет.
*Я новичок в VS, не могли бы вы сообщить мне подробности?
Jochen Arndt
Я не могу этого сделать, не зная, как выглядят эти "ошибки".
Было бы также полезно увидеть код вашей функции AutoSizeColumns() и, возможно, код PlaceControls (), если он каким-то образом задействован.
Элемент управления списком рисуется системой. Единственный способ изменить внешний вид - это использовать предоставленные функции API или использовать список собственников (custom draw).
Member 12776813
Добавлены запрошенные функции.
Дисплей выглядит примерно так,
Ожидаемый:
Столбцы Полей
- оба в разных колонках
Актуально в отладочной версии:
Поле / Статус
В версии :
Поле Поле|
-в разных колонках
int CStringEx:: GetFieldCount( LPCTSTR delim )
{
LPTSTR lpsz, lpszRemainder = CA2T(CString:: GetString());
int lenDelim = lstrlen( delim );
int iCount = 1;
while ((lpsz = _tcsstr(lpszRemainder, delim))! = NULL )
{
lpszRemainder = lpsz + lenDelim;
людей icount++;
}
возвращение людей icount;
}
CStringEx CStringEx:: GetField( TCHAR delim, int fieldnum)
{
LPTSTR lpsz, lpszRemainder = CA2T(CString:: GetString ()), lpszret;
int retlen;
while (fieldnum-- >= 0 )
{
lpszret = lpszRemainder;
lpsz = _tcschr(lpszRemainder, (_TUCHAR)delim);
if (lpsz )
{
// Мы действительно нашли делим
retlen = lpsz - lpszRemainder;
lpszRemainder = lpsz + 1;
}
ещё
{
retlen = lstrlen( lpszRemainder );
lpszRemainder += retlen; / / изменить на пустую строку
}
}
return Mid( lpszret - CString:: GetString (), retlen );
}
Это функции, которые заботятся о разделениях строк.
Jochen Arndt
Сначала вы должны исправить свои преобразования ANSI / TCHAR. Опубликованный код даже не должен компилироваться для сборок Unicode:
Здесь вы проходите LPCSTR:
седла.GetFieldCount("|")
Но функция ожидает lpctstr:
int CStringEx:: GetFieldCount( LPCTSTR delim )
Проверить это:
LPTSTR lpszRemainder = CA2T(CString:: GetString());
При сборке Unicode GetString () возвращает LPCWSTR. Рассматривая это как ANSI, возвращает строку с одним символом!
Функция GetField() объявляется как
CStringEx CStringEx:: GetField( TCHAR delim, int fieldnum)
с разделителем TCHAR но вы передаете LPCSTR:
седла.Getfield у("|", коль)
В целом эти функции CStringEx могут быть реализованы гораздо лучше (и использовать один тип разделителя: символ или строку).
Не должно быть даже необходимости делать преобразования ANSI / Unicode внутри этих функций. Просто используйте функции-члены CString и библиотечные функции _tXXX.
Если вам нужно использовать строки ANSI со сборками Unicode, используйте версию ANSI cstringa явно и избегайте этих макросов преобразования ATL.
Member 12776813
Это действительно работает.
Я заменил все строковые типы на char TCHAR и LPTCSTR без преобразования CA2T. Теперь жала правильно выровнены.
Пожалуйста, дайте мне знать, если у вас есть какие-либо дополнительные предложения о том, какой тип предпочтительнее для этого случая.
Большое вам спасибо !!!
Jochen Arndt
Чтобы проверить основные функциональные возможности VC2015 и Win 7, Вы можете настроить проект VC 2015 на использование ANSI / MCBS (как используется VC6) вместо Unicode.
Если вы хотите использовать Unicode, вы должны преобразовать свой код souce, что может быть трудоемкой задачей (в зависимости от размера проекта).
Видишь https://msdn.microsoft.com/en-us/library/cc194801.aspx.