Форум программистов, компьютерный форум, киберфорум
C++: WinAPI
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/11: Рейтинг темы: голосов - 11, средняя оценка - 5.00
0 / 0 / 0
Регистрация: 01.11.2013
Сообщений: 7
1

::TextOut выводит символ в позицию, смещенную влево

01.11.2013, 03:23. Показов 1958. Ответов 16
Метки нет (Все метки)

Есть окно. Есть hdc окна.(BeginPaint). Я беру шрифт с помощью ChooseFont(). Устанавливаю этот шрифт в этот hdc с помощью SelectObject(). В позицию 0 0 вывожу символ (выводятся по одному всегда, но да не суть). Он отрисуется почему то в позиции немного левее, чем должен быть. При взятии размера символа через GetExtendPoint32 это смещение также не учитывается. Я думал, что это особенность шрифта (дикая какая-то). Через GetTextMetrix нашел у шрифта lfOverhead. Он оказался равен нулю. Что делать, чтобы символы или выводились без смещения влево, или получить это смещение влево. Желательно без ответов "прибавляй 2 пикселя каждый раз")
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
01.11.2013, 03:23
Ответы с готовыми решениями:

Передвинуть элементы массива на 1 позицию влево
Написать программу на языке QBasic: найти для массива Cn S=1!С1+2!C2+…+n!Cn и передвинуть элементы...

Задание на сдвиг массива на одну позицию влеВо
Задание на сдвиг массива на одну позицию влеВо, uses Crt; Const N = 6; Var A: array of Integer;...

Циклическое перемещение символов строки на 1 позицию влево
Разработать программу циклического перемещения символов строки на 1 позицию влево(вправо). P.S....

Указатели: сдвинуть элементы циклически на 1 позицию влево
Условие задачи: Заполните случайным образом одномерный массив из n элементов и здвиньте элементы...

16
Эксперт С++
4974 / 3081 / 456
Регистрация: 10.11.2010
Сообщений: 11,160
Записей в блоге: 10
01.11.2013, 11:43 2
Покажи на примере. Гадать что ты там делаешь не очень хочется..
0
Модератор
Эксперт по электронике
8495 / 6321 / 855
Регистрация: 14.02.2011
Сообщений: 21,915
01.11.2013, 11:52 3
размер рамки окна???
0
Модератор
Эксперт С++
11130 / 9168 / 5506
Регистрация: 18.12.2011
Сообщений: 24,485
01.11.2013, 12:38 4
TextOut() выводит текст с выравниванием по некоторым признакам
(по центру, влево, по базовой линии и т.д.).
Изменяются они с помощью функции
SetTextAign(...).
Вот от нее и пляшите.
Или используйте DrawText(...)
Она впишет текст в указанный прямоугольник.
0
0 / 0 / 0
Регистрация: 01.11.2013
Сообщений: 7
01.11.2013, 16:19  [ТС] 5
SetTextAlign пробовал (LEFT, BASELINE), не помогло. DrawText(..) использовать не стоит (в контексте моей программы)

Добавлено через 37 минут
До ChooseFont() шрифт выбран (HFONT) GetStockObject(DEFAULT_GUI_FONT). Та же проблема
0
0 / 0 / 0
Регистрация: 01.11.2013
Сообщений: 7
03.11.2013, 00:32  [ТС] 6
Вот простейший пример
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;
    HFONT font =(HFONT) GetStockObject(DEFAULT_GUI_FONT);
    switch (message)
    {
    case WM_COMMAND:
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // Разобрать выбор в меню:
        switch (wmId)
        {
        case IDM_ABOUT:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break;
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        // TODO: добавьте любой код отрисовки...
        
        SelectObject(hdc,font);
        ::TextOut(hdc,0,0,L"fff",3);
        EndPaint(hWnd, &ps);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}
(первая буква f выведется без левой палочки(уйдет влево за предел области), и так происходит со всеми вызовами TextOut

Добавлено через 4 минуты
DrawText даст такой же результат(
0
Модератор
Эксперт по электронике
8495 / 6321 / 855
Регистрация: 14.02.2011
Сообщений: 21,915
03.11.2013, 00:40 7
LoserKiss,
я еще раз тебя спрашиваю, почему ты не учитываешь толщину рамки окна?
она обычно и бывает 2 пикселя, которые ты потерял
0
0 / 0 / 0
Регистрация: 01.11.2013
Сообщений: 7
03.11.2013, 00:44  [ТС] 8
Где мне ее учитывать? Отрисовка идет, начиная с активной области (безрамочной). Если бы ноль ноль было начало рамки, то первая буква вообще не видна бы была. Тем более я уже написал, что эта проблема происходит при каждом вызове TextOut (если вывод посимвольный со смещением на ширину символа,например). Тут дело не в рамке.
P.S. три препода с моего универа не знают, в чем проблема.
0
Модератор
Эксперт по электронике
8495 / 6321 / 855
Регистрация: 14.02.2011
Сообщений: 21,915
03.11.2013, 02:28 9
ладно, насчет рамки я не прав

сейчас скопировал твой листинг и запустил
есть такая бяка
дело в фонте
если вообще не выбирать нормальная отрисовка
если выбрать SYSTEM_FONT или DEVICE_DEFAULT_FONT, ANSI_FIXED_FONT,OEM_FIXED_FONTтоже все нормально
а если DEFAULT_GUI_FONT или ANSI_VAR_FONT то смещает
надо смотреть характеристики фонта
или поменяй если он тебе не принципиален
0
0 / 0 / 0
Регистрация: 01.11.2013
Сообщений: 7
03.11.2013, 02:36  [ТС] 10
Да, я знаю, что дело в фонте. Но в моей проге предусмотрен выбор любого возможного фонта из ChooseFont() и я бы хотел чтобы они все нормально работали. В характеристике фонта ничего такого не нашел (кроме lfOverhead, который равен нулю).
0
Модератор
Эксперт по электронике
8495 / 6321 / 855
Регистрация: 14.02.2011
Сообщений: 21,915
03.11.2013, 03:24 11
у шрифтов DEFAULT_GUI_FONT и ANSI_VAR_FONT
установлен tmInternalLeading как раз 2
но по определению
tmInternalLeading
Устанавливает величину междустрочного пространства (пробела) внутри границ, установленных членом tmHeight. В этой области могут встретиться знак ударения и другие диакритические символы .
как это влияет не смещение влево непонятно
или это просто совпадение

Добавлено через 5 минут
написал пока вот так
погоняй у себя
C++
1
2
::GetTextMetrics(hdc,&txtmtr1);
::TextOut(hdc,txtmtr1.tmInternalLeading,0,_T("fffrr"),5);
Добавлено через 13 минут
написал вот такой код
C++
1
2
3
4
5
 SetBkColor(hdc,RGB(255,255,0));
        ::TextOut(hdc,200,200,_T("fffrr"),5);
        for(int i=0;i<100;i++)
            for(int j=0;j<100;j++)
                SetPixel(hdc,100+i,100+j,GetPixel(hdc,(200+i/2),(200+j/2)));
вывожу по координатам 200,200 текст на желтом фоне
циклы это "линзочка", выводит увеличенное изображение по координатам 100,100
и видно текст смещен на 2 пикселя (линза его режет)
1
0 / 0 / 0
Регистрация: 01.11.2013
Сообщений: 7
03.11.2013, 04:33  [ТС] 12
Хм. Спасибо. tmInternalLeading неплохо помогает для всех шрифтов и размеров (хотя буквы начинают отрисовываться не очень плотно друг к другу, но все равно неплохо)

Добавлено через 9 минут
Но если найдете более правильное решение, напишите плиз)
0
Модератор
Эксперт по электронике
8495 / 6321 / 855
Регистрация: 14.02.2011
Сообщений: 21,915
03.11.2013, 10:36 13
Цитата Сообщение от LoserKiss Посмотреть сообщение
SelectObject(hdc,font);
::TextOut(hdc,0,0,L"fff",3);
EndPaint(hWnd, &ps);
у тебя здесь ошибка приводящая к утечке ресурсов, рано или поздно программа рухнет
необходимо возвращать старый фонт, а равно кисти перья, все что проходит через SelectObject
нужно делать примерно так
C++
1
2
3
4
HFONT fntOld=(HFONT)SelectObject(hdc,font);
....................................
// в конце отрисовки
SelectObject(hdc,fntOld);
0
Эксперт С++
4974 / 3081 / 456
Регистрация: 10.11.2010
Сообщений: 11,160
Записей в блоге: 10
03.11.2013, 11:18 14
Я один тут что-то недопонимаю...? О каком таком смешении идёт речь?
LoserKiss, скриншот своей проблемы покажи.
0
Модератор
Эксперт по электронике
8495 / 6321 / 855
Регистрация: 14.02.2011
Сообщений: 21,915
03.11.2013, 11:39 15
Цитата Сообщение от castaway Посмотреть сообщение
Я один тут что-то недопонимаю...? О каком таком смешении идёт речь?
шрифт типа DEFAULT_GUI_FONT печатается со смещением
т.е
C++
1
TextOut(hdc,0,0,_T("fffrr"),5);
начинает печатать не с 0 а, как будто, с -2 в результате съедается начало буквы
сам с таким первый раз столкнулся раньше не обращал внимания
Цитата Сообщение от castaway Посмотреть сообщение
скриншот своей проблемы покажи.
боюсь мало поможет
шрифт очень мелкий, не разглядишь
проще самому сэмулировать
ну вот кину тебе скриншотик
и заодно код

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;
 HFONT font1 =(HFONT) GetStockObject(OEM_FIXED_FONT );//DEFAULT_GUI_FONT);
  HFONT font2 =(HFONT) GetStockObject(DEFAULT_GUI_FONT);//ANSI_VAR_FONT);
 HFONT oldfnt;
 TEXTMETRIC txtmtr1;
 TEXTMETRIC txtmtr2;
    switch (message)
    {
    case WM_COMMAND:
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // Разобрать выбор в меню:
        switch (wmId)
        {
        case IDM_ABOUT:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break;
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
            oldfnt= (HFONT) SelectObject(hdc,font1);    
            ::GetTextMetrics(hdc,&txtmtr1);
        ::TextOut(hdc,txtmtr1.tmInternalLeading,0,_T("fffrr OEM_FIXED_FONT"),5+15);
        SelectObject(hdc,font2);    
            ::GetTextMetrics(hdc,&txtmtr2);
        //::TextOut(hdc,txtmtr2.tmInternalLeading,15,_T("fffrr"),5);
         ::TextOut(hdc,0,15,_T("fffrr DEFAULT_GUI_FONT"),5+16+1);
        SetBkColor(hdc,RGB(255,255,0));
        ::TextOut(hdc,200,200,_T("fffrr"),5);
        for(int i=0;i<100;i++)
            for(int j=0;j<100;j++)
                SetPixel(hdc,100+i,100+j,GetPixel(hdc,(200+i/8),(200+j/8))); 
           SelectObject(hdc,oldfnt);
        EndPaint(hWnd, &ps);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}
правда здесь накручено, накидано
просто эксперименты
1
Миниатюры
::TextOut выводит символ в позицию, смещенную влево  
Эксперт С++
4974 / 3081 / 456
Регистрация: 10.11.2010
Сообщений: 11,160
Записей в блоге: 10
03.11.2013, 12:07 16
Цитата Сообщение от ValeryS Посмотреть сообщение
боюсь мало поможет
шрифт очень мелкий, не разглядишь
На такие случаи я держу ярлык с экранной лупой на рабочем столе.
Так устроены шрифты, почитайте об этом.. да хотя бы вот здесь. В материале по ссылке это называется bearingX.
0
0 / 0 / 0
Регистрация: 01.11.2013
Сообщений: 7
04.11.2013, 20:21  [ТС] 17
Решено. Функция GetCharABCWidths(..) вернет ширину символа параметрами A,B,C. (до буквы, буква, после буквы). Так вот, у некоторых шрифтов параметр A может быть меньше нуля, и из-за этого всё и происходит.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
04.11.2013, 20:21

Передвинуть массив циклически влево на одну позицию
1.Вставить два нуля после минимального элемента в массиве. 2.Передвинуть массив циклически...

Сдвинуть элементы на одну позицию вправо\влево
Ребята помогите пожалуйста с решением задачи на с++ : Сдвинуть элементы на одну позицию...

Сдвинуть элементы массива циклически на одну позицию влево
Сдвинуть элементы массива циклически на одну позицию влево

Сдвинуть букву в слове на одну позицию влево/вправо
Здравствуйте. Как можно реализовать код, что бы допустим слово privet превращало в rpvite ?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.