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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
antokarpo
0 / 0 / 0
Регистрация: 07.01.2013
Сообщений: 6
#1

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

07.01.2013, 22:36. Просмотров 455. Ответов 10
Метки нет (Все метки)

Здравствуйте всем.
Пытаюсь реализовать класс "холста" или канвы. Задумывается это как объект в виде белого прямоугольника, внутри которого будут рисоваться все нужные примитивы (линии, круги, прямоугольники и т.п.). Так вот, не могу сообразить куда прикрутить контекст устройства для этого объекта. Каким образом заставить программу понять, что данный контекст устройства привязан не к экрану, не к окну, а именно к этому прямоугольнику?

Вот то, что у меня на данный момент есть по этому вопросу:
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++/CLI WinForms
Суть в том что при повороте изображения (осуществлён по пиксельно) изменяються размеры холста.Допустим если было избражение со сторонами...

Выравнивание Canvas-холста - HTML, CSS
Возможно ли оно? не нашел информации если оно не возможно, то можно ли инициализировать canvas по всей ширине экрана, причем если...

слишком частое обновление холста - C#
было необходимо нарисовать некоторые детали на холсте канвы с помощью Graphics G = drw.CreateGraphics(); drw -стандартный элемент-...

Как поменять цвет холста? - Delphi
Как поменять цвет холста? Или какой код цвета имеет стандартный холст в делфи? Очень нужно для графики.

Вывод TCanvas (холста) на принтер - C++ Builder
Может кто нибудь подскажет, как вывести график на принтер с TCanvas. Какой метод надо использовать, чтобы нажав на TButton отпечатать график

Изменение размеров холста в JavaFX - JavaFX
Начинаю кодировать на Java. Вроде бы простая задача - изменять размеры холста при изменении размеров окна. Вот код опуская некоторые...

Редактирование холста canvas несколькими людьми - JavaScript
У меня имеется свой маленький графический редактор на canvas + js там все простенько, обычная мазня карандашиком. Можно ли как то сделать...

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
DU
1481 / 1057 / 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
1481 / 1057 / 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
1481 / 1057 / 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
1481 / 1057 / 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
1481 / 1057 / 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     класс холста
Еще ссылки по теме:

Редактирование холста canvas несколькими людьми - HTML5 Canvas
У меня имеется свой маленький графический редактор на canvas + js там все простенько, обычная мазня карандашиком. Можно ли как то сделать...

Изменить размер холста для рисования - C++ Qt
Здравствуйте, суть программы - конструктор блок схем из элементов, которые создаются и отрисовываются на виджете, который похож на форму...

Как в центре Image(холста) построить квадрат? - Delphi
Как в центре поверхности рисования построить квадрат?

Выполнение скрипта после появлния канвас холста - HTML5 Canvas
В общем ребята столкнулся с такой проблемой что надо найти пиксели в кнопке при клике на нее, вот только код выполняется не с первого раза,...


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

Или воспользуйтесь поиском по форуму:
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     класс холста
Ответ Создать тему
Опции темы

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