3 / 3 / 0
Регистрация: 03.05.2013
Сообщений: 23
1

Логические единицы системы координат в WinAPI

23.03.2015, 20:18. Показов 2283. Ответов 1
Метки нет (Все метки)

Здравствуйте, господа форумчане.
Возник вопрос касательно винапишных логических единиц.
Предыстория такова: при нажатии на кнопку в диалоговом родительском окне - в pop-up окошке рисуется график.
При рисовании применяю двойную буферизацию.
Вид системы координат и графика - на скрине. Для того, чтобы не использовать фиксированный отступ осей от границы экрана, было решено сделать отступ зависящим от ширины/высоты текста, соответствующего каждой метке. То есть, осью ОУ отступить от левой границы экрана, например, на длину текста "_-0.0e+007".
Для этого используется функция GetTextExtentPoint32(hdc, _TEXT("-0.0e+007"), _tcslen(_TEXT("-0.0e+007")), &textSize); - которая в структуру textSize пишет в логических единицах ширину и высоту заданного ей текста в соответствии с текущим шрифтом для данного окна.
Проблема состоит в том, что функция эта в структуру пишет для примера с "_-0.0e+007" значения: высота=19200, ширина=86400. В то время как SetWindowExtEx в окне я задаю размер в логических единицах 1200х1200. Естественно, сдвиг по осям при этом оказывается больше максимального размера самого окна - и вместо графиков белый экран.
Вопрос в том, как связать логические единицы, которые я устанавливаю через SetWindowExtEx для окна, с тем, что возвращает функция GetTextExtentPoint32 ?

Код: оконная процедура окошка с графиком:
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
const int scaleX = 6; //число меток на оси Х
const int scaleY = 6; //чисто меток на оси У
const int indent = 25; //отступ
const int GRAPHSIZE = 1200; //размер окна в логических единицах
const int GRAPHWIDTH = 1000; //размер рабочей области окна в лог.единицах
 
LRESULT CALLBACK WndGraph(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    PAINTSTRUCT ps;
    static HDC hdc; //display context
    static HDC hMemDC;//compatible context
    static int sx, sy;
    RECT rect;
    
    switch (message) {
        
    case WM_CREATE: {
        GetClientRect(hWnd, &rect);
        sx = rect.right;
        sy = rect.bottom;
    }
        break;
 
    case WM_ERASEBKGND:
        return TRUE;
 
    case WM_SIZING: 
    case WM_SIZE: {
        sx = LOWORD(lParam);
        sy = HIWORD(lParam);
        UpdateWindow(hWnd);
        } 
        break;
 
    case WM_PAINT: {
                
        hdc = BeginPaint(hWnd, &ps);
        GetClientRect(hWnd, &rect);
        hMemDC = CreateCompatibleDC(hdc);
 
        HBITMAP hScreen;
        HBITMAP oldBmp;
        hScreen = CreateCompatibleBitmap(hdc, sx, sy);
        oldBmp = (HBITMAP)SelectObject(hMemDC, hScreen);
        SelectObject(hMemDC, hScreen);
        SetGraphicsMode(hMemDC, GM_COMPATIBLE);
 
        //закраска фоновым цветом hMemDC
        LOGBRUSH br;
        br.lbStyle = BS_SOLID;
        br.lbColor = 0xCCCCFF;
        HBRUSH bkgrdbr = CreateBrushIndirect(&br);
        SelectObject(hMemDC, bkgrdbr); 
        FillRect(hMemDC, &rect, bkgrdbr);
        DeleteObject(bkgrdbr);
        ///////////////////////////////////////////////////////
/////////////устанавливаем режим отображения для hdc
        SetMapMode(hdc, MM_ANISOTROPIC); //разный масштаб по х и у
        SetWindowExtEx(hdc, GRAPHSIZE, -GRAPHSIZE, NULL); //window 1200x1200 logical units
        SetViewportExtEx(hdc, sx, sy, NULL); //sx x sy client area (in device units)
        SetViewportOrgEx(hdc, 0, sy, NULL); //function specifies which window point maps to the viewport origin (0,0). in device units
        
        DrawGraphics(hMemDC, points, quant, sx, sy, names); //функция которая рисует систему координат и график 
    
        //copy an image to the screen
        SetStretchBltMode(hdc, COLORONCOLOR);
        
        //conversion fron device units to logical units
        int ax = (int)(-((GRAPHSIZE/sx +0.5)*3*indent));
        int ay = (int)(-((GRAPHSIZE/sy +0.5)*indent));
        /////////////////////////////////////////////
 
        BitBlt(hdc, 0, 0, GRAPHSIZE, GRAPHSIZE, hMemDC, ax, ay, SRCCOPY);
        SelectObject(hMemDC, oldBmp);
        DeleteObject(hScreen);
        DeleteObject(oldBmp);
        DeleteDC(hMemDC);
 
        EndPaint(hWnd, &ps);
    } break;
 
    case WM_SYSCOMMAND: {
        if (wParam == SC_RESTORE) UpdateWindow(hWnd); //redraw if maximize/minimize window
    } break;
 
    case WM_DESTROY: {
        DeleteDC(hdc);
        if (!points.empty())points.resize(0); //clear points for plotting
        if (!names.empty()) names.resize(0); //clear names array
    } break;
    }
    return DefWindowProc(hWnd, message, wParam, lParam);
}
Одна из внутренних функций DrawGraphics, в которой и рисуются оси и подписи к ним:
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
void DrawGrid(HDC hdc, int sx, int sy, double max_x, double min_x, double max_y, double min_y, double hx, double hy) {
    HPEN pengrid_one, pengrid_two, pengrid_dash,oldpen;
    SIZE textSize;
    pengrid_one= CreatePen(PS_SOLID, 1, RGB(120, 30, 50));
    pengrid_two = CreatePen(PS_SOLID, 3, RGB(0, 0, 0));
    pengrid_dash = CreatePen(PS_DASH, 1, RGB(120, 30, 50));
    
    SetMapMode(hdc, MM_ANISOTROPIC);
    SetWindowExtEx(hdc, GRAPHSIZE, -GRAPHSIZE, NULL); //window 1200x1200 logical units
    GetTextExtentPoint32(hdc, _TEXT("-0.0e+007"), _tcslen(_TEXT("-0.0e+007")), &textSize);
    int width_intent = textSize.cx;
    int height_intent = textSize.cy;
    SetViewportExtEx(hdc, sx, sy, NULL); //sx x sy client area in device units
/////строка ниже соответствует тому, что на скрине/////////////////////////////////////////////////////////////////////////
//  SetViewportOrgEx(hdc, 3*indent,  sy-indent , NULL); //function specifies which window point maps to the viewport origin (0,0) in device units
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
    SetViewportOrgEx(hdc, textSize.cx, sy-textSize.cy , NULL); //function specifies which window point maps to the viewport origin (0,0) in device units
    SetTextAlign(hdc, TA_CENTER | TA_TOP);
    int x_gr, y_gr, i;
    TCHAR s[20];
    double grid_x, grid_y;
    //рисуем сетку///////////////////////////////////////////////////////////////////////////
    oldpen = (HPEN)SelectObject(hdc, pengrid_one);
    for (grid_x = min_x, i = 0; i <= 5 * scaleX; grid_x += hx / (5 * scaleX), i++) {
        x_gr = (int)((grid_x - min_x)*GRAPHWIDTH / (max_x - min_x) + 0.5);
        MoveToEx(hdc, x_gr, 0, NULL);
        LineTo(hdc, x_gr, GRAPHWIDTH);
    }
    for (grid_y = min_y, i = 0; i <= 5 * scaleY; grid_y += hy / (5 * scaleY), i++) {
        y_gr = (int)((grid_y - min_y)*GRAPHWIDTH / (max_y - min_y) + 0.5);
        MoveToEx(hdc, 0, y_gr, NULL);
        LineTo(hdc, GRAPHWIDTH, y_gr);
    }
    SelectObject(hdc, oldpen);
    
 //////////////////делаем насечки и подписи по осям/////////////////////////////////////////////////////
    for (grid_x = min_x, i = 0; i <= scaleX; grid_x += hx / scaleX, i++) {
        x_gr = (int)((grid_x - min_x)*GRAPHWIDTH / (max_x - min_x) + 0.5);
        _stprintf(s, _TEXT("%.1le"), grid_x);
        TextOut(hdc, x_gr, -5, s, _tcsclen(s));
        oldpen = (HPEN)SelectObject(hdc, pengrid_one);
        MoveToEx(hdc, x_gr, -10, NULL);
        LineTo(hdc, x_gr, 10);
        oldpen = (HPEN)SelectObject(hdc, pengrid_dash);
        LineTo(hdc, x_gr, GRAPHWIDTH);
    }
    oldpen = (HPEN)SelectObject(hdc, pengrid_two);
    MoveToEx(hdc, 0, 0, NULL);
    LineTo(hdc, GRAPHWIDTH, 0);
    SetTextAlign(hdc, TA_RIGHT | TA_BOTTOM);
    
    SelectObject(hdc, oldpen);
    for (grid_y = min_y+hy/scaleY, i = 0; i <= scaleY; grid_y += hy / scaleY, i++) {
        y_gr = (int)((grid_y - min_y)*GRAPHWIDTH / (max_y - min_y) + 0.5);
        _stprintf(s, _TEXT("%.1le"), grid_y);
        TextOut(hdc, -5, y_gr, s, _tcsclen(s));
        
        oldpen = (HPEN)SelectObject(hdc, pengrid_two);
        MoveToEx(hdc, -10, y_gr, NULL);
        LineTo(hdc, 10, y_gr);
        oldpen = (HPEN)SelectObject(hdc, pengrid_dash);
        LineTo(hdc, GRAPHWIDTH, y_gr);
    }
////////////////////////////////////////////////////////////////////////////////////////////////
    oldpen = (HPEN)SelectObject(hdc, pengrid_two);
    MoveToEx(hdc, 0, 0, NULL);
    LineTo(hdc, 0, GRAPHWIDTH);
    SelectObject(hdc, oldpen);
    DeleteObject(pengrid_two);
    DeleteObject(pengrid_one);
    DeleteObject(pengrid_dash);
 
}
Миниатюры
Логические единицы системы координат в WinAPI  
__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
23.03.2015, 20:18
Ответы с готовыми решениями:

Преобразование координат точки при повороте системы координат
Здравствуйте! Не могу понять, из чего получается формула преобразования координат точки при...

Переводить точки координат из декартовой системы координат и обратно
привет !! как написать процедуру чтобы она умела переводить точки координат из декартовой...

Единицы измерения линейных координат в 3D графике
Дорогие коллеги! Начинаю работать с 3D графикой и первый затык: совершенно непонятно в каких...

Система координат WinAPI
Всем привет! В данный момент изучаю систему координат ВинАПИ, но так и не смог понять как с ней...

1
902 / 423 / 159
Регистрация: 02.04.2014
Сообщений: 1,206
24.03.2015, 10:25 2
Связать очень просто, нужно полученные размеры разделить на величины, устанавливаемые в
C
1
SetWindowExtEx(hdc, GRAPHSIZE, -GRAPHSIZE, NULL);
(т.е. на 1200) потому что по умолчанию, диапазоны у контекста были (1,1)
А лучше передай последним параметром *SIZE и посмотри сам.
1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
24.03.2015, 10:25
Помогаю со студенческими работами здесь

Есть ли в winapi функция поворота оси координат?
Добрый день. Подскажите плиз есть ли в win api фия поворота оси координат...?

Решение однородной системы линейных уравнений c рангом порядка меньше единицы
Мужики выручайте весь интернет перерыл вообще нечего подробного не нашел.((( Вообще не понимаю как...

После восстановления системы мои логические диски сохранятся или все вернется как было прежде?
Добрый день. Если я сделал копию системы до разбивки жесткого диска, потом разбил его и мне вдруг...

Системы координат
Добрый вечер. Никак не могу разобраться в вопросе о системах координат в OpenGL. Просмотрел...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru