Форум программистов, компьютерный форум, киберфорум
Visual C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.93/89: Рейтинг темы: голосов - 89, средняя оценка - 4.93
 Аватар для RetiF
9 / 9 / 1
Регистрация: 21.12.2008
Сообщений: 43

Создание классов геометрических фигур, рисование на GDI (MFC)

03.04.2009, 16:22. Показов 17250. Ответов 8
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Нужно создать класс Shape, как некий родительский класс геометрических фигур, от которого будут наследоваться последующие конкретные классы: треугольник, прямоугольник; и нарисовать их. Далее нужно будет реализовать возможность перемещать эти фигуры, но сейчас не до этого, надо разобраться с самими классами

Читал литературу на эту тему, более или менее разобрался, делаю это на GDI. Класс Shape унаследовал от CPaintDC (и скорее всего, это бред), а надо, насколько я понимаю, от CObject

Вот что у меня пока что получилось (код приведён не весь, только нужное):

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
#include "afxwin.h"   // MFC Основные и стандартные компоненты
 
class CMainWnd : public CFrameWnd
{
public:
    CMainWnd();
    afx_msg void OnPaint(); // функция рисования в окне
    ~CMainWnd();       
private:
    DECLARE_MESSAGE_MAP(); // таблица откликов на сообщения
};
 
BEGIN_MESSAGE_MAP(CMainWnd, CFrameWnd) 
    ON_WM_PAINT()   
END_MESSAGE_MAP()
 
class Shape : public CPaintDC // класс-родитель всех фигур
{
public:
    Shape(CWnd* pWnd);
    ~Shape();
    int x, y;
};
 
Shape::Shape(CWnd* pWnd):CPaintDC(pWnd) {}
Shape::~Shape() {}
 
class RectAngle : public Shape // прямоугольник, класс-потомок от Shape
{
public:
    RectAngle(CWnd* pWnd);
    int width, height;
    void DrawRectAngle(int x, int y, int width, int height);
    ~RectAngle();
};
 
class TriAngle : public Shape // треугольник, класс-потомок от Shape
{
public:
    TriAngle(CWnd* pWnd);
    int x2, y2, x3, y3;
    void DrawTriAngle(int x, int y, int x2, int y2, int x3, int y3);
    ~TriAngle();
};
 
void RectAngle::DrawRectAngle(int x, int y, int width, int height)
{
    MoveTo(x,y);
    LineTo(x+width,y);
    LineTo(x+width,y+height);
    LineTo(x,y+height);
    LineTo(x,y);
}
 
void TriAngle::DrawTriAngle(int x, int y, int x2, int y2, int x3, int y3)
{
    MoveTo(x,y);
    LineTo(x2,y2);
    LineTo(x3,y3);
    LineTo(x,y);
}
 
RectAngle::RectAngle(CWnd* pWnd):Shape(pWnd) {}
RectAngle::~RectAngle() {}
 
TriAngle::TriAngle(CWnd* pWnd):Shape(pWnd) {}
TriAngle::~TriAngle() {}
 
void CMainWnd::OnPaint()
{
    RectAngle dc(this);
    dc.DrawRectAngle(10,10,110,85);
}
 
CMainWnd::CMainWnd()
{
    Create(NULL,"Work",WS_OVERLAPPEDWINDOW,CRect(250,200,700,500),NULL,NULL);
}
 
CMainWnd::~CMainWnd() {}
Вот какие есть вопросы и проблемы:

1) Про сам класс Shape - правильно ли было наследовать его от CPaintDC? Скорее всего нет, это получается, что я создал ещё один класс рисования

2) И поэтому при рисовании в окне я могу нарисовать либо прямоугольник, либо треугольник, потому как только один из них может получить контекст устройства, чтобы рисовать в нём. Как быть?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
03.04.2009, 16:22
Ответы с готовыми решениями:

Рисование геометрических фигур
Доброго времени суток!!! Столкнулся с такой проблемой, сдаю сессию досрочно и нужно сдать летнюю...

Построить систему классов для описания плоских геометрических фигур
Построить систему классов для описания плоских геометрических фигур: круга, квадрата,...

Построить систему классов для описания плоских геометрических фигур
Здравствуйте. Прошу помощи) Вот сама задача Построить систему классов для описания плоских...

8
Эксперт С++
 Аватар для XuTPbIu_MuHTAu
2256 / 771 / 25
Регистрация: 27.05.2008
Сообщений: 1,496
03.04.2009, 16:48
Насколько я понял, в задании хотят независимый класс Shape. сделайте базовый класс и дайте ему вирутальный метод отрисовки,принимающий контекст GDI.Также всем фигурам свойственно иметь координаты (X,Y). Все остальное - свойство отдельных фигур. Унаследуйте классы треугольника,прямоугольника и т п от базового, переопределите метод отрисовки. После чего в главной программе можно будет создать,скажем, список или вектор Shape* и вызывать отрисовку для каждого в цикле. Поскольку функция вирутальная, вызываться будет отрисовка соответствующего объекта. Функцию отрисовки Shape можно определить чисто виртуальной,поможет при отладке.
0
 Аватар для RetiF
9 / 9 / 1
Регистрация: 21.12.2008
Сообщений: 43
04.04.2009, 02:07  [ТС]
сделайте базовый класс и дайте ему виртуальный метод отрисовки, принимающий контекст GDI
Я сразу потерялся, как это сделать?

C++
1
2
3
4
5
6
7
8
class Shape
{
public:
        int x, y; // координаты начальной точки фигуры
    Shape(int x, int y); // конструктор по умолчанию
    ~Shape(); // деструктор
       virtual void Draw(); // виртуальная функция рисования фигуры
};
Как передать контекст GDI? Рисоваться будет в CMainWnd, насколько я понимаю, значит и передавать надо его контекст? Нужно написать реализацию функции?

C++
1
2
3
4
virtual void Draw()
{
       // здесь происходит передача DC?
}
-------
Все остальное - свойство отдельных фигур. Унаследуйте классы треугольника, прямоугольника от базового
С этим понятно, у треугольника дополнительные точки, у прямоугольника ширина и высота, и так далее

-------
После чего в главной программе можно будет создать, скажем, список или вектор Shape* и вызывать отрисовку для каждого в цикле
Понимаю, что вопрос очень глупый, но расскажите подробнее, как это и что это?

Как я понимаю задачу и что я хочу сделать - у меня будут просто кнопки, например, Нарисовать треугольник, при нажатии которой будет отрисовываться объект класса TriAngle. То есть, для этого в событии OnLButtonDown кнопки будет вызываться конструктор класса и функция его прорисовки

Поправьте, если бред получился, а то я как в тёмной комнате
0
 Аватар для RetiF
9 / 9 / 1
Регистрация: 21.12.2008
Сообщений: 43
07.04.2009, 18:06  [ТС]
Вопрос и правда был глупый. Вот что получилось:

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
class Shape
{
public:
    int prp_x, prp_y;
    Shape(int x, int y);
    ~Shape();
    virtual void Draw();
};
 
class RectAngle : public Shape
{   
public:
    int prp_width, prp_height;
    RectAngle(int x, int y, int width, int height);
    virtual void Draw(CWnd* pWnd, int x, int y, int width, int height);
    ~RectAngle();
};
 
Shape::Shape(int x, int y)
{
    prp_x = y;
    prp_y = x;
}
Shape::~Shape() {}
 
RectAngle::RectAngle(int x, int y, int width, int height):Shape(x, y)
{
    prp_width = width;
    prp_height = height;
}
RectAngle::~RectAngle() {}
 
void Shape::Draw() {}
 
void RectAngle::Draw(CWnd* pWnd, int x, int y, int width, int height) 
{
    CClientDC dc(pWnd);
    dc.MoveTo(x, y);
    dc.LineTo(x+width, y);
    dc.LineTo(x+width, y+height);
    dc.LineTo(x, y+height);
    dc.LineTo(x, y);
}
 
void RectAngleButton::OnLButtonDown(UINT, CPoint)
{
    RectAngle RA(40, 5, 105, 70);
    RA.Draw(this, RA.prp_x, RA.prp_y, RA.prp_width, RA.prp_height);
}
Код не весь, оставил только принципиальное
В готовой программе две кнопки, по нажатию на одну рисуется прямоугольник, по нажатию на вторую - треугольник
Захотел сделать третью кнопку - по нажатию на которую всё нарисованное стирается. Не осилил передать ей контекст главного окна, у неё в собственных параметрах конструктора уже есть такой параметр, если я не путаю
Вот здесь застрял:

C++
1
2
3
4
5
void EraseButton::OnLButtonDown(UINT, CPoint)
{
    CClientDC dc();
    Invalidate();
}
Добавлено через 23 часа 35 минут 23 секунды
C++
1
2
3
4
5
void RectAngleButton::OnLButtonDown(UINT, CPoint)
{
        RectAngle RA(40, 5, 105, 70);
        RA.Draw(this, RA.prp_x, RA.prp_y, RA.prp_width, RA.prp_height);
}
Это я получаю контекст самой этой кнопки - RectAngleButton, а не главного окна, которое CMainWnd

У меня единственная проблема, я искал в книгах, искал в сети, не нашёл. Как передать его контекст? Ведь не &CMainWnd, это ересь вообще

Добавлено через 21 час 49 минут 59 секунд
Внезапно обнаружил - AfxGetApp()->m_pMainWnd
А ещё оказалось, что Invalidate ничего не стирает. Использовал FloodFill:
C++
1
2
3
4
5
6
void EraseButton::OnLButtonDown(UINT, CPoint) // обработчик нажатия кнопки
{
    CClientDC dc(AfxGetApp()->m_pMainWnd); // получить контекст Главного окна
    dc.FloodFill(0,0,NULL);                // заполнить его всё цветом фона (стереть всё)
 
}
1
 Аватар для RetiF
9 / 9 / 1
Регистрация: 21.12.2008
Сообщений: 43
12.04.2009, 17:07  [ТС]
А как теперь это сделать с OnPaint?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class CMainWnd : public CFrameWnd          
{
public:
        CMainWnd();
    afx_msg void OnPaint();
    ~CMainWnd();
private:
    DECLARE_MESSAGE_MAP();
};
 
BEGIN_MESSAGE_MAP(CMainWnd, CFrameWnd)
    ON_WM_PAINT()   
END_MESSAGE_MAP()
 
void CMainWnd::OnPaint()
{
        
}
По нажатию на кнопку должно передаваться сообщение, что нужно вызвать функцию рисования, насколько я понимаю. Как это реализовать?
0
 Аватар для RetiF
9 / 9 / 1
Регистрация: 21.12.2008
Сообщений: 43
17.04.2009, 21:07  [ТС]
На обработчики нажатия кнопок нужно было поставить изменение глобальных переменных, а в OnPaint при условии изменения переменной - вызов функции рисования

Оттакая штука получилась: http://img5.imageshost.ru/imgs... 59311a.png

Программу закончил, исходник приаттачил, вдруг кому-то понадобится
Вложения
Тип файла: zip work.zip (3.5 Кб, 3106 просмотров)
2
0 / 0 / 0
Регистрация: 14.02.2012
Сообщений: 6
14.02.2012, 01:28
class CMainWnd : public CFrameWnd
Честно говоря я не очен понял как оно у вас заработало? Мне выдает кучу ошибок. И хотелось бы узнать а где описание класса CFrameWnd?
0
 Аватар для RetiF
9 / 9 / 1
Регистрация: 21.12.2008
Сообщений: 43
14.02.2012, 09:12  [ТС]
Я не помню уже совершенно, сейчас посмотрел на своё творение и содрогнулся
Нашёл его в завалах, скомпиленный .exe запустился, хоть и криво работает, а компилить нету желания и Студии
А что, "class CMainWnd : public CFrameWnd" - это что-то плохое?
0
0 / 0 / 0
Регистрация: 14.02.2012
Сообщений: 6
15.02.2012, 22:05
"class CMainWnd : public CFrameWnd" нет это не плохое)))это как я понял создание окна. Между прочем у вас не плохо оформлен код. Хоть и криво как вы говорите. Прост класс CFrameWnd у меня пишет на студии что не найден. Но по мойму надо прописать:
#pragma comment(lib, "GdiPlus.lib")
и #include <windows.h>
в StdAfx.cpp. в Header Files
и #include <GdiPlus.h>
using namespace Gdiplus; в StdAfx.cpp.в Source Files.У меня VC2008
Но я еще не специалист только осваиваю.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
15.02.2012, 22:05
Помогаю со студенческими работами здесь

Построить систему классов для описания плоских геометрических фигур
Всем привет. Помогите пожалуйста сделать программу, ото совсем не получается и еще скоро курсовая. ...

Построить систему классов для описания плоских геометрических фигур
C++ Построить систему классов для описания плоских геометрических фигур: круга, квадрата,...

Построить систему классов для описания плоских геометрических фигур
Ребята смотрите дана така задача: Построить систему классов для описания плоских геометрических...

Многофайловая система классов для описания плоских геометрических фигур
Помогите пожалуйста составить по данной программе многофайловую систему,а то у меня не получается...

Иерархия классов для геометрических фигур
Здравствуйте, нужно Создать иерархию классов на примере геометрических фигур, которая должна...


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

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru