Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.19.27.178] |
|
Страницы: (2) [1] 2 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Хочу написать класс-оболочку для представления дисплея. Для этого собираюсь создать абстрактный базовый класс Display, в котором будут чисто вирт. ф-ции line(), circle() и пр. Далее мечтаю наследовать от него DisplayBuilder, DisplayVisuallCpp так, чтобы мою прогу, которая будет использовать этот класс дря рисования, можно было запросто перенести из Builder'а в Visuall Cpp (т.к. рисовать я буду через указатель на базовый класс проблем не будет, ведь остальной код не изменится). Так вот. Вопрос. Как мне объявить конструктор в Display? Ведь для DisplayBuilder переменной-членом будет CDC *m_cdc, а для DisplayVisuallCpp TCanvas *m_canvas. Пока у меня только одна идея Display( void *p ). Но это, по-моему, не очень модно. Вот и хочу узнать, что думают остальные по этому поводу.
Заранее спасибо. |
Сообщ.
#2
,
|
|
|
А если вспомнить, что Canvas и CDC работает через DC - контекст устройства в WinAPI, то начинает вырисовываться несколько другая архитектура.
|
Сообщ.
#3
,
|
|
|
Цитата Flex_Ferrum,9.01.04, 14:30 А если вспомнить, что Canvas и CDC работает через DC - контекст устройства в WinAPI, то начинает вырисовываться несколько другая архитектура. Нет. Позвольте. Вся прелесть-то в том, что в первом случае я смогу делать так m_canvas-> м далее вываливается список доступных ф-ций-членов. Во втором случае тоже понятно m_cdc и другой список ф-ций. Если я перейду на Win API, то проблемы бы этой не возникло. Поэтому всё же хочу узнать ваше мнение по поводу void *. |
Сообщ.
#4
,
|
|
|
А если сделать инерфейсныйкласс-прослойку?
ЗВ Надеюсь понятно выразился ЗЗЫ Ничего не знаяю о Canvas и его отличаях от CDC поэтому с реализацией помочь не могу |
Сообщ.
#5
,
|
|
|
Цитата dimedrol,9.01.04, 16:45 А если сделать инерфейсныйкласс-прослойку? ЗВ Надеюсь понятно выразился ЗЗЫ Ничего не знаяю о Canvas и его отличаях от CDC поэтому с реализацией помочь не могу Что такое инерфейсный класс-прослойка? Хочу детали. |
Сообщ.
#6
,
|
|
|
class CBaseDC { public: virtual ~CBaseDC(){} virtual InitDC()=0; virtual BeginPaint()=0; virtual EndPaint()=0; //остальные услуги, которые тебе требуються }; Класс обертка над DC/Canvas. Я просто не знаю как работать с Canvas и насколько он отличаеться от DC. |
Сообщ.
#7
,
|
|
|
Я бы тогда предложил бы условную компиляцию:
class Display { //... public: #ifdef __BORLANDC__ Display(TCanvas* canvas) {;} #else Display(CDC* dc) {;} #endif //... }; |
Сообщ.
#8
,
|
|
|
Цитата Flex_Ferrum @ 10.01.04, 16:50 Я бы тогда предложил бы условную компиляцию: А если вдруг понадобится какой-нибудь другой контекст. Добавить? Придется дописывать и перекомпелировать кучу кода Раз используеться ООП, то в том же стиле и надо писать. Наскоко я понямаю любые фокусы с макросами не приветствуються |
Сообщ.
#9
,
|
|
|
Цитата dimedrol, 11.01.04, 20:04 А если вдруг понадобится какой-нибудь другой контекст. Добавить? Придется дописывать и перекомпелировать кучу кода Раз используеться ООП, то в том же стиле и надо писать. Наскоко я понямаю любые фокусы с макросами не приветствуються Вот и попробуй ) В ряде случаев уж лучше макрос, чем void*. |
Сообщ.
#10
,
|
|
|
а почему нельзя использовать два конструктора ?
Display( CDC *cdc ); Display( TCanvas *canvas ); а вот выше использовать ifdef #ifdef __BORLANDC__ class CDC{ }; #else class TCanvas{ }; #endif |
Сообщ.
#11
,
|
|
|
Вопрос решил. Всё дело в том, что я забыл, что конструкторы не наследуются и, соответственно, проблема отпала. Правильный вариант:
/** * Абстрактный базовый класс, который предоставляет открытый * интерфейс для конкретных реализаций дисплея. */ class Display { public: /** * Рисует линию. * @param x1 абсцисса первой точки * @param y1 ордината первой точки * @param x2 абсцисса второй точки * @param y2 ордината второй точки */ virtual void line( int x1, int y1, int x2, int y2 ) = 0; }; // class Display /** * Дисплей для Builder'а. */ class DisplayBuilder: public Display { public: /** * Конструктор. * @param pCanvas указатель на объект класса TCanvas */ DisplayBuilder( TCanvas *pCanvas ) : m_canvas( pCanvas ) {} /** * Рисует линию. * @param x1 абсцисса первой точки * @param y1 ордината первой точки * @param x2 абсцисса второй точки * @param y2 ордината второй точки */ void line( int x1, int y1, int x2, int y2 ) { m_canvas->MoveTo( x1, y1 ); m_canvas->LineTo( x2, y2 ); } protected: /** * Указатель на объект класса TCanvas, * посредством которого будет осуществляться рисование. */ TCanvas *m_canvas; }; // class DisplayBuilder /** * Дисплей для Visual C++. */ class DisplayVisualCpp: public Display { public: /** * Конструктор. * @param pDC указатель на объект класса CDC */ DisplayVisualCpp( CDC *pDC ) : m_dc( pDC ) {} /** * Рисует линию. * @param x1 абсцисса первой точки * @param y1 ордината первой точки * @param x2 абсцисса второй точки * @param y2 ордината второй точки */ void line( int x1, int y1, int x2, int y2 ) { m_dc->MoveTo( x1, x2 ); m_dc->LineTo( x2, y2 ); } protected: /** * Указатель на объект класса CDC, * посредством которого будет осуществляться рисование. */ CDC *m_dc; }; // class DisplayVisualCpp Далее в программе: [/CODE] CWnd *pWnd = GetDlgItem( IDC_STATIC_CANVAS1 ); CDC *pCanvasDC = pWnd->GetDC(); /////////////////////////////////////////////// pWnd->Invalidate(); pWnd->UpdateWindow(); /////////////////////////////////////////////// DisplayVisualCpp disp1( pCanvasDC ); pWnd->ReleaseDC( pCanvasDC ); [/CODE] Добавлено в : Ё-моё лажанулся с [CODE] |
Сообщ.
#12
,
|
|
|
А можно было так:
class DisplayBase { public: Display(HDC hdc) : m_hDC(hdc) {;} void line(int x1, int y1, int x2, int y2) { POINT pnt; MoveToEx(m_hDC, x1, y1, &pnt); LineTo(m_hDC, x1, y2); } private: HDC m_hDC; }; class Display : public DisplayBase { public: #ifdef __BORLANDC__ Display(TCanvas* canvas) : DisplayBase(canvas->Handle) {;} #else Display(CDC* dc) : DislpayBase(dc->GetSaveHdc()) {;} #endif }; // Далее в программе CWnd *pWnd = GetDlgItem( IDC_STATIC_CANVAS1 ); CDC *pCanvasDC = pWnd->GetDC(); /////////////////////////////////////////////// pWnd->Invalidate(); pWnd->UpdateWindow(); /////////////////////////////////////////////// Display disp1( pCanvasDC ); pWnd->ReleaseDC( pCanvasDC ); |
Сообщ.
#13
,
|
|
|
Согласен, что можно. Только вот условная компиляция немного противоречит принципамм ООП. В этом плане полностью согласен с dimedrol.
Меня сейчас интересует другое. Не стоит ли GetDC() и ReleaseDC() засунуть внутрь DisplayVisualCpp? Параметром конструктора ведь вполне может быть и идентификатор static'а, на кототом собираюсь рисовать. Можно ли GetDC() и ReleaseDC() вызывать в конструкторе и деструкторе соответственно? Или же не стоит? Что-то слышал про несовсем обычную природу того указателя, что возвращает GetDC(). Его вроде бы нельзя надолго сохранять. Это так? Или я глючу. |
Сообщ.
#14
,
|
|
|
Цитата poi, 12.01.04, 14:32 Согласен, что можно. Только вот условная компиляция немного противоречит принципамм ООП. В этом плане полностью согласен с dimedrol. Но не тогда, когда тебе нужна кроссплатформенность. Я бы на твоем месте не стал приностить простоту класса и итогового дизайна в жертву этому принципу. Или тебе хочется писать вдвое больше кода? По поводу вопроса - можно. И это будет соответствовать принципу ООП "Объявление есть инциализация". |
Сообщ.
#15
,
|
|
|
Цитата Flex_Ferrum @ 12.01.04, 11:42 Но не тогда, когда тебе нужна кроссплатформенность. Я бы на твоем месте не стал приностить простоту класса и итогового дизайна в жертву этому принципу. Или тебе хочется писать вдвое больше кода? По поводу вопроса - можно. И это будет соответствовать принципу ООП "Объявление есть инциализация". Мне не нужна кроссплатформенность в её стандартном понимании! Всё это - исследовательская работа. И мне нужно именно ООП. А за ответ большое спасибо. |