В стандартных конфигурациях часто встречается кнопка Сформировать, причём шрифт таков, что мягкий знак не влезает, и получается слово "Сформироват". Надо проверить метрики используемых букв, и сузить одну из них (подозреваю, что `м` слишком широка).
В конфигурации Зарплата и Кадры в Журнале Ввод расчётов сотрудникам документ Ввод расчёта сотруднику есть кнопка "Исправит(ь)".
Я думаю, нужно взять функцию, возвращающую длину строки в точках, пробежаться по всем символам и получить ширину каждой буквы. Результат сравнить с виндой :)
В процессе написания теста возникла проблема - буфер, который должен получать ширину символов, не заполняется функциями Get*Width* WINGDIAPI BOOL WINAPI GetCharWidthA(HDC,UINT,UINT,LPINT); WINGDIAPI BOOL WINAPI GetCharWidthI(HDC,UINT,UINT,LPWORD,LPINT); WINGDIAPI BOOL WINAPI GetCharWidthW(HDC,UINT,UINT,LPINT); #define GetCharWidth WINELIB_NAME_AW(GetCharWidth) Интересно, что при таком объявлении в wingdi.h в dlls/gdi32/font.c отсутствуют функции GetCharWidthA и GetCharWidthW. При этом их можно вызвать из программы.
(In reply to comment #3) > В процессе написания теста возникла > проблема - буфер, который должен получать > ширину символов, не заполняется функциями > Get*Width* > > WINGDIAPI BOOL WINAPI GetCharWidthA(HDC,UINT,UINT,LPINT); > WINGDIAPI BOOL WINAPI GetCharWidthI(HDC,UINT,UINT,LPWORD,LPINT); > WINGDIAPI BOOL WINAPI GetCharWidthW(HDC,UINT,UINT,LPINT); > #define GetCharWidth WINELIB_NAME_AW(GetCharWidth) > > Интересно, что при таком объявлении в wingdi.h > в dlls/gdi32/font.c отсутствуют функции GetCharWidthA и > GetCharWidthW. При этом их можно вызвать из Использовать надо GetCharWidth32. Функции отсутствуют, потому что они опеределены через gdi32.spec: @ stdcall GetCharWidthA(long long long long) GetCharWidth32A
Ширина строки одинакова с виндовым и с вайновским шрифтами. Похоже, что дело в ширине создаваемой кнопки, куда не влезает слово "сформировать". Нужно проверить разницу в ширине кнопки в Windows и в WINE (нужны скриншоты).
Created attachment 931 [details] Кнопка в wine
Created attachment 932 [details] Кнопка в windows
Кнопки одинаковой ширины, и поля для текста в них тоже одинаковые. При выводе текста где-то неправильно считается область, в которую текст выводится.
До самой функции DrawTextExW всё правильно (кажется) считается. Значит, ошибка в выводе этой функцией или в одной из вложенных.
Исследуем всё в пределах DrawTextExW шаг 1. При трейсе сразу бросается в глаза такая картинка: DrawTextW L"С&формировать" ExtTextOutW L"Сформироват" ExtTextOutW L"Сформироват" ret (end) DrawTextW L"" ret (8) Функция ExtTextOutW получает длину буфера в 11 символов, хотя должна в 12 (символ & не учитывается) шаг 2. Ищем как формируется количество символов, которое попадает в ExtTextOutW (переменная len_seg, которая равна len) Находим, что это количество формируется в функции TEXT_NextLineW шаг 3. Смотрим, как формируется значение количества символов в TEXT_NextLineW. Там это значение формируется в переменной num_fit, которая инициализируется вызовом функции GetTextExtentExPointW шаг 4. Откуда в GetTextExtentExPointW берется значение 11? Оно накапливается инкрементом в переменной nFit при помощи цикла i = 0..(12 - 1) Инкремент выполняется в том случае, если правая граница символа (значение dxs[i]) не превышает некоторое значение maxExt -- очевидно, правая граница последнего символа, т. е. if (dxs[i] <= maxExt) ++nFit; на последней, 12-ой итерации, dxs[11] == 76, а maxExt == 75, поэтому инкремент ++nFit не выполнялся и к функции DrawTextExW приходило значение 11. шаг 5. проверяем, что, если заменить if (dxs[i] <= maxExt) ++nFit; на if (dxs[i] <= maxExt + 1) ++nFit; то бага решается шаг 6. Ищем, где формируется значение maxExt. Изначально оно формируется в начале функции DrawTextExW в переменной: int width = rect->right - rect->left; и расценивается как ширина, которая вычисляется не верно. т. е. вычислять надо так int width = rect->right - rect->left + 1; бага решается, если сделать такие изменения. в этом и будет состоять патч.
> > в этом и будет состоять патч. > патч http://lists.etersoft.ru/pipermail/wine-patches/2009-February/000290.html решает проблему