Форум программистов, компьютерный форум CyberForum.ru

класс холста - C++

Восстановить пароль Регистрация
 
antokarpo
0 / 0 / 0
Регистрация: 07.01.2013
Сообщений: 6
07.01.2013, 22:36     класс холста #1
Здравствуйте всем.
Пытаюсь реализовать класс "холста" или канвы. Задумывается это как объект в виде белого прямоугольника, внутри которого будут рисоваться все нужные примитивы (линии, круги, прямоугольники и т.п.). Так вот, не могу сообразить куда прикрутить контекст устройства для этого объекта. Каким образом заставить программу понять, что данный контекст устройства привязан не к экрану, не к окну, а именно к этому прямоугольнику?

Вот то, что у меня на данный момент есть по этому вопросу:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct Paires {int x, int y};
 
class GCanvas
{
    public:
        GCanvas(int,int);
        virtual ~GCanvas();
 
        void Draw(HDC, int, int);
        Paires MoveTo(int,int);
        Paires LineTo(int,int);
    protected:
    private:
        int height;
        int width;
        HDC handle;
        Paires PenPos;
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
GCanvas::GCanvas(int w=640,int h=480)
{
    height = h;
    width = w;
    PenPos.x = 0;
    PenPos.y = 0;
}
 
GCanvas::~GCanvas()
{
    //dtor
}
 
void GCanvas::Draw(HDC hdc, int x, int y)
{
    Rectangle(hdc,x,y,x+width,y+height);
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.01.2013, 22:36     класс холста
Посмотрите здесь:

C++ Создать Класс Coins (монеты). Класс сохраняет массив из 3 монет ...
C++ Класс домов и класс улиц для учета поступлений квартплаты. Массив
C++ С++ класс (создайте класс с именем Complex для выполнения в арифмитических операий с комплексными числами))
Реализовать класс Triangle (задание 25), опираясь на класс Angle из задания 26 для представления углов C++
C++ Разработать класс Tableware (посуда) и производный класс Dish (тарелка). Описать атрибуты
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
07.01.2013, 22:48     класс холста #2
тут речь идет о контексте, который создается в памяти и в который хочется рисовать? типа буфера вывода?
antokarpo
0 / 0 / 0
Регистрация: 07.01.2013
Сообщений: 6
08.01.2013, 14:01  [ТС]     класс холста #3
Эмм... Речь идет о контексте устройства (deviсe context) типа HDC. Я, конечно, не в курсе как этот класс устроен, но думаю, что да, как-нибудь так он, наверно, и работает.

А вообще-то я имел ввиду что-то вроде класса TCanvas в C++ Builder'е, но только для MSVC++.

Добавлено через 4 часа 42 минуты
Поправьте меня, если что не так понимаю...

Возможно, надо члену класса handle передать контекст функцией GetDC(). Хотя, по моему это не сработает. Не могу сообразить как это реализовать. Может, можно как-то проще сделать и я все усложняю?
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
08.01.2013, 14:08     класс холста #4
ну рас вы задумали заменить классом GCanvas виндовый HDC и набор апишных функций для рисования в этот HDC,
то в классе GCanvas нужно сделать мембер HDC m_hdc; Добавить конструктор, который будет принимать HDC и иницилизировать этот m_hdc.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
GCanvas::GCanvas(HDC hdc, int w=640,int h=480)
{
    m_hdc = hdc;
    height = h;
    width = w;
    PenPos.x = 0;
    PenPos.y = 0;
}
 
GCanvas::~GCanvas()
{
    //dtor
}
 
void GCanvas::Draw(int x, int y)
{
    Rectangle(m_hdc,x,y,x+width,y+height);
}
ну а вообще затея плохая.
antokarpo
0 / 0 / 0
Регистрация: 07.01.2013
Сообщений: 6
08.01.2013, 14:17  [ТС]     класс холста #5
Цитата Сообщение от DU Посмотреть сообщение
нужно сделать мембер HDC m_hdc;
Этот мембер у меня называется handle. Но не суть важно. Мне надо, чтобы можно было рисовать в HDC моего прямоугольника (холста), а не в HDC окна. Вот я и не могу додуматься как его туда прикрутить.

Добавлено через 1 минуту
Цитата Сообщение от DU Посмотреть сообщение
ну а вообще затея плохая.
Насчет плохой идеи я и сам понимаю. Посоветуй, как можно сделать это не заменяя HDC на GCanvas.
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
08.01.2013, 14:33     класс холста #6
я не совсем понимаю, что значит "hdc моего прямоугольника". в голову приходит только hdc, который создается в памяти и рисование идет сперва в него, а потом, в какой-то момент, нужно будет скопировать содержание этого hdc в окно (т.е. тут речь идет о буфере). если так, то вот, у меня завалялись старые файлики:

// common.h
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
#ifndef __COMMON_H__
#define __COMMON_H__
 
#include <windows.h>
 
typedef UINT64 UInt64;
typedef UINT16 UInt32;
typedef UINT16 UInt16;
 
typedef INT32 Int32;
 
// ...
 
struct Size
{
  UInt32 width;
  UInt32 height;
 
  Size()
    : width(0)
    , height(0)
  {
  }
 
  Size(UInt32 theWidth, UInt32 theHeight)
    : width(theWidth)
    , height(theHeight)
  {
  }
};
 
// ...
 
#endif
// mem_dc.h
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
#ifndef __MEM_DC_H__
#define __MEM_DC_H__
 
#include "common.h"
 
class MemDC
{
public:
  explicit MemDC(HWND hWnd = NULL);
  explicit MemDC(const Size& size, HWND hWnd = NULL);
  ~MemDC();
 
  HDC GetHDC() const;
 
  bool IsInited() const;
  Size GetSize() const;
  bool Resize(const Size& size);
  void Reset();
 
private:
  bool Init(const Size& size);
 
private:
  MemDC(const MemDC&);
  MemDC& operator = (const MemDC&);
 
private:
  HWND      m_hWnd;
  HDC       m_hMemDC;
  HBITMAP   m_hNativeBmp;
  HBITMAP   m_hBmp;
  Size      m_reservedSize;
  Size      m_size;
};
 
#endif
// mem_dc.cpp
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#include "mem_dc.h"
#include <cassert>
 
namespace
{
  class Cleanup
  {
  public:
    Cleanup(HDC& hDisplayDC,
            HDC& hMemDC,
            HBITMAP& hNativeBmp,
            HBITMAP& hBmp)
      : m_hDisplayDC(hDisplayDC)
      , m_hMemDC(hMemDC)
      , m_hNativeBmp(hNativeBmp)
      , m_hBmp(hBmp)
      , m_needCleanup(true)
    {
    }
 
    virtual ~Cleanup()
    {
      ReleaseDC(NULL, m_hDisplayDC);
      m_hDisplayDC = NULL;
      if (m_needCleanup)
      {
        SelectObject(m_hMemDC, m_hNativeBmp);
        DeleteObject(m_hBmp);
        DeleteDC(m_hMemDC);
        m_hMemDC = NULL;
        m_hNativeBmp = NULL;
        m_hBmp = NULL;
      }
    }
 
    void Cancel()
    {
      m_needCleanup = false;
    }
 
  private:
    Cleanup(const Cleanup&);
    Cleanup& operator = (const Cleanup&);
 
  private:
    HDC&      m_hDisplayDC;
    HDC&      m_hMemDC;
    HBITMAP&  m_hNativeBmp;
    HBITMAP&  m_hBmp;
    bool      m_needCleanup;
  };
 
} // namespace
 
MemDC::MemDC(HWND hWnd)
  : m_hWnd(hWnd)
  , m_hMemDC(NULL)
  , m_hNativeBmp(NULL)
  , m_hBmp(NULL)
{
}
 
MemDC::MemDC(const Size& size, HWND hWnd)
  : m_hWnd(hWnd)
  , m_hMemDC(NULL)
  , m_hNativeBmp(NULL)
  , m_hBmp(NULL)
{
  Resize(size);
}
 
MemDC::~MemDC()
{
  Reset();
}
 
HDC MemDC::GetHDC() const
{
  return m_hMemDC;
}
 
bool MemDC::IsInited() const
{
  return NULL != m_hMemDC;
}
 
Size MemDC::GetSize() const
{
  return m_size;
}
 
bool MemDC::Resize(const Size& size)
{
  return Init(size);
}
 
bool MemDC::Init(const Size& size)
{
  assert(size.width > 0 && size.height > 0 && "Invalid argument");
 
  const bool needJustResize = IsInited()
        && m_reservedSize.width >= size.width
        && m_reservedSize.height >= size.height
        ;
 
  if (needJustResize)
  {
    m_size = size;
    return true;
  }
 
  HDC hDisplayDC = NULL;
  HDC hMemDC = NULL;
  HBITMAP hNativeBmp = NULL;
  HBITMAP hBmp = NULL;
 
  Cleanup cleanup(hDisplayDC, hMemDC, hNativeBmp, hBmp);
 
  hDisplayDC = GetDC(m_hWnd);
  if (hDisplayDC == NULL)
  {
    return false;
  }
 
  hMemDC = CreateCompatibleDC(hDisplayDC);
  if (hMemDC == NULL)
  {
    return false;
  }
 
  hBmp = CreateCompatibleBitmap(hDisplayDC, size.width, size.height);
  if (hBmp == NULL)
  {
    return false;
  }
 
  hNativeBmp = static_cast<HBITMAP>(SelectObject(hMemDC, hBmp));
  if (hNativeBmp == NULL)
  {
    return false;
  }
 
  cleanup.Cancel();
 
  Reset();
 
  m_hMemDC       = hMemDC;
  m_hNativeBmp   = hNativeBmp;
  m_hBmp         = hBmp;
  m_reservedSize = size;
  m_size         = size;
 
  return true;
}
 
void MemDC::Reset()
{
  m_size = Size();
  m_reservedSize = Size();
 
  if (!IsInited())
  {
    return;
  }
 
  const HBITMAP hBmp = static_cast<HBITMAP>(SelectObject(m_hMemDC, m_hNativeBmp));
  m_hNativeBmp = NULL;
  if (hBmp != m_hBmp)
  {
    assert(!"Native and selected bitmap are not the same.");
    // do something
  }
 
  BOOL fSuccess = DeleteObject(m_hBmp);
  m_hBmp = NULL;
  if (!fSuccess)
  {
    assert(!"Failed to delete bitmap.");
    // do something
  }
 
  fSuccess = DeleteDC(m_hMemDC);
  m_hMemDC = NULL;
  if (FALSE == fSuccess)
  {
    assert(!"Failed to delete DC");
    // do something
  }
}

common.h - не обязателен и можно без него и того, что внутри него. это выдернуто из проекта и специально
удалять что-либо мне не хочется.

ну используется примерно так:

C++
1
2
3
4
5
6
7
8
9
MemDC memDC(GetDC(NULL), Size(100, 100)); // создание в памяти hdc
HDC hMemDC = memDC.getHDC();
Rectangle(hMemDC, 0, 0, 50, 50); // рисуем в hMemDC
... // тут тоже всякое рисование
 
HDC hWndDC = ...; // это мы откудато берем контекст для окна, чтобы вывести в него все то, что нарисовали в hMemDC
 
// копируем  в hWndDC то, что у нас в hMemDC
BitBlt(hWndDC, 0, 0, 100, 100, hMemDC, 0, 0);
antokarpo
0 / 0 / 0
Регистрация: 07.01.2013
Сообщений: 6
08.01.2013, 15:13  [ТС]     класс холста #7
Спасибо. Изучу, и подумаю, как это применить. Но, на всякий случай, объясню что мне нужно другими словами. Вот возьмем стандартный Paint. Там есть такая область для рисования белого цвета. Вот мне нужен такой объект. Может быть, это нужно делать и не через HDC, а как-то по другому. Но я хочу реализовать вот эту самую область для рисования. "Все" перерыл, не могу найти литературу на тему. А курсовик застрял на начальном этапе. В общем, с миру по нитке и, надеюсь, справлюсь с этой задачей. Вот и пришел на форум, ведь он для этого и нужен.

Добавлено через 3 минуты
Забыл написать. Тружусь над графическим редактором. Поэтому и начинаю с самого нужного класса - холст или область для рисования (ну, или как там оно еще может называться).
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
08.01.2013, 15:26     класс холста #8
c win api лучше не связыватся, если кто-то не поставил идиотского условия, что нужно пренепременно win api. используйте qt чтоли. там в разы все проще.
antokarpo
0 / 0 / 0
Регистрация: 07.01.2013
Сообщений: 6
08.01.2013, 15:30  [ТС]     класс холста #9
Да, я уже об этом слышал. Но, по Qt я мало литературы нашел (почти нисколько). Может, посоветуешь что-нибудь на русском? С Английским проблем нет, но переводить нет времени и не хочу.
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
08.01.2013, 15:40     класс холста #10
не посоветую, т.к. не значю что советовать. мне мануалов и примеров из сети хватает. и того и другого в сети полным полно.

Добавлено через 6 минут
вот в догонку постик:
Графический редактор на qt4
там в начале ссылка на исходники вроде.
короче юзайте поиск активнее.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
08.01.2013, 16:08     класс холста
Еще ссылки по теме:

C++ Класс Quadrangle (четырехугольник). Класс хранит Декартовы координаты четырех углов четырехугольника
Подробно прокомментировать класс PolarCoordinates, представляющий собой класс координат точки на плоскости C++
C++ Ошибка в выводе данных, класс выводит правильно, а класс в классе - нет

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

Или воспользуйтесь поиском по форуму:
antokarpo
0 / 0 / 0
Регистрация: 07.01.2013
Сообщений: 6
08.01.2013, 16:08  [ТС]     класс холста #11
ну, вот до чего я на данный момент додумал свой "проект". Объявление класса:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
struct Paires {int x; int y;};
 
class GCanvas
{
    public:
        GCanvas(HDC,int,int);
        virtual ~GCanvas();
 
        void Draw(int, int);
        void MoveTo(int,int);
        void GLineTo(int,int);
    protected:
    private:
        int startX;
        int startY;
        int height;
        int width;
        HDC handle;
        Paires PenPos;
};
Реализация:
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
GCanvas::GCanvas(HDC hdc,int w=640,int h=480)
{
    handle = hdc;
    height = h;
    width = w;
    PenPos.x = 0;
    PenPos.y = 0;
}
 
GCanvas::~GCanvas()
{
    //dtor
}
 
void GCanvas::Draw(int x, int y)
{
    startX = x;
    startY = y;
    Rectangle(handle,x,y,x+width,y+height);
}
 
void GCanvas::MoveTo(int xx,int yy)
{
    PenPos.x = xx+startX;
    PenPos.y = yy+startY;
}
 
void GCanvas::GLineTo(int xx,int yy)
{
    MoveToEx(handle,PenPos.x,PenPos.y,NULL);
    LineTo(handle,xx+startX,yy+startY);
    PenPos.x = xx+startX;
    PenPos.y = yy+startY;
}
По тупому, конечно, но на то я и начинающий, чтобы на таких тупостях учиться )))

Добавлено через 20 минут
Цитата Сообщение от DU Посмотреть сообщение
вот в догонку постик:
Графический редактор на qt4
там в начале ссылка на исходники вроде.
По той ссылке уже ничего нет ((( Может, сайт переехал, или страницу удалили. Печально.
Yandex
Объявления
08.01.2013, 16:08     класс холста
Ответ Создать тему
Опции темы

Текущее время: 08:17. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru