Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Вопрос по WinAPI: Device Contex'ы

1.9K
15 июня 2005 года
solovey
113 / / 25.07.2004
Доброго времени суток.

Возникла одна проблема при работе с графикой.

У меня есть класс Shape и класс MyWnd, у которого есть метод draw(Shape &). Вот реализация метода draw(Shape &):
Код:
void MyWnd::draw(Shape & figure)
{
       
    CDC * cDC = pWnd->GetDC();

    pen->CreatePen(PS_SOLID,figure.width,RGB(0,0,0));

    cDC->SelectObject(pen);
   
    figure.draw(this);

    cDC->DeleteDC();
}

В классе Shape есть переменная width, которая хранит в себе толщину линии, которой должна рисоваться фигура. В вышеприведенном методе мы сначала создаем кисть для рисования, потом делаем ее текущей, т.к. рисование фигур удет производиться стандартными средствами класса CDC, которые, согласно MSDN, должны использовать текущее перо.

Shape - абстрактый класс с чистовиртуальным методом draw(MyWnd *). Line:public Shape. Вот реализация метода Shape для Line:
Код:
void Line::draw(MyWnd * window)
{
    CDC * cDC = window->pWnd->GetDC();

    cDC->MoveTo(beg.x,beg.y);  
    cDC->LineTo(end.x,end.y);

    cDC->DeleteDC();

    window->pWnd->ShowWindow(SW_SHOW);
}


Вот тут проблема: линия рисуется все время толщиной в 1 пиксель, даже если в MyWnd::draw(Shape & figure) figure.width = 20. Пробовал использовать функции SaveDC(), RestoreDC(), но и они не помогли. Кто-нибудь может подсказать, что я делаю неправильно?
1.8K
16 июня 2005 года
_const_
229 / / 26.11.2003
Цитата:
Originally posted by solovey
Доброго времени суток.

Возникла одна проблема при работе с графикой.

У меня есть класс Shape и класс MyWnd, у которого есть метод draw(Shape &). Вот реализация метода draw(Shape &):
Код:
void MyWnd::draw(Shape & figure)
{
       
    CDC * cDC = pWnd->GetDC();

    pen->CreatePen(PS_SOLID,figure.width,RGB(0,0,0));

    cDC->SelectObject(pen);
   
    figure.draw(this);

    cDC->DeleteDC();
}

В классе Shape есть переменная width, которая хранит в себе толщину линии, которой должна рисоваться фигура. В вышеприведенном методе мы сначала создаем кисть для рисования, потом делаем ее текущей, т.к. рисование фигур удет производиться стандартными средствами класса CDC, которые, согласно MSDN, должны использовать текущее перо.

Shape - абстрактый класс с чистовиртуальным методом draw(MyWnd *). Line:public Shape. Вот реализация метода Shape для Line:
Код:
void Line::draw(MyWnd * window)
{
    CDC * cDC = window->pWnd->GetDC();

    cDC->MoveTo(beg.x,beg.y);  
    cDC->LineTo(end.x,end.y);

    cDC->DeleteDC();

    window->pWnd->ShowWindow(SW_SHOW);
}


Вот тут проблема: линия рисуется все время толщиной в 1 пиксель, даже если в MyWnd::draw(Shape & figure) figure.width = 20. Пробовал использовать функции SaveDC(), RestoreDC(), но и они не помогли. Кто-нибудь может подсказать, что я делаю неправильно?



Во-первых:
An application must not delete a device context whose handle was obtained by calling CWnd::GetDC. Instead, it must call CWnd::ReleaseDC to free the device context. The CClientDC and CWindowDC classes are provided to wrap this functionality.
The DeleteDC function is generally used to delete device contexts created with CreateDC, CreateIC, or CreateCompatibleDC.

Во-вторых: передавай в draw не окно, а DC.
В-третьих:
An application should not call DeleteDC if objects have been selected into the device context. Objects must first be selected out of the device context before it is deleted.

Т.е. где объявлен pen?

1.9K
16 июня 2005 года
solovey
113 / / 25.07.2004
Цитата:
Originally posted by _const_
Во-первых:
An application must not delete a device context whose handle was obtained by calling CWnd::GetDC. Instead, it must call CWnd::ReleaseDC to free the device context. The CClientDC and CWindowDC classes are provided to wrap this functionality.
The DeleteDC function is generally used to delete device contexts created with CreateDC, CreateIC, or CreateCompatibleDC.

В-третьих:
An application should not call DeleteDC if objects have been selected into the device context. Objects must first be selected out of the device context before it is deleted.

Т.е. где объявлен pen?


Код:
class MyWnd
{
    public:
        CWnd * pWnd;
        CPen * pen;
        MyWnd(CWnd * Wnd):pWnd(Wnd),pen(new CPen){};
                ~MyWnd();
        void draw(Shape & figure);
        Point current();
        Point current(Point p);
};


 
Код:
Во-вторых: передавай в draw не окно, а DC.

А чем это лучше? В моем варианте я могу нарисовать Shape на любом MyWnd, указатель на который у меня есть, просто передав в draw этот указатель. Какая разница, как я получаю DC: как параметр функции или через указатель на окно?
1.8K
16 июня 2005 года
_const_
229 / / 26.11.2003
Цитата:
Originally posted by solovey
Код:
class MyWnd
{
    public:
        CWnd * pWnd;
        CPen * pen;
        MyWnd(CWnd * Wnd):pWnd(Wnd),pen(new CPen){};
                ~MyWnd();
        void draw(Shape & figure);
        Point current();
        Point current(Point p);
};


 
Код:
Во-вторых: передавай в draw не окно, а DC.

А чем это лучше? В моем варианте я могу нарисовать Shape на любом MyWnd, указатель на который у меня есть, просто передав в draw этот указатель. Какая разница, как я получаю DC: как параметр функции или через указатель на окно?



Ну тогда примерно так:

Код:
void MyWnd::draw(Shape & figure)
{
 //лучше перенести куда-нибудь
 pen->CreatePen(PS_SOLID,figure.width,RGB(0,0,0));
 figure.draw(this);
 pen->DeleteObject();
}

void Line::draw(MyWnd * window)
{
 CDC *pDC = window->pWnd->GetDC();
 CPen *pDefPen;

 pDefPen = pDC->SelectObject(window->pen);
 pDC->MoveTo(beg.x,beg.y); 
 pDC->LineTo(end.x,end.y);
 pDC->SelectObject(pDefPen);

 pDC->ReleaseDC();

 window->pWnd->ShowWindow(SW_SHOW);
}


При этом надо быть уверенным в том, что pen
1. был корректно создан перед отрисовкой
2. был отсоединен от DC после отрисовки

Все дело в том, что повторный вызов GetDC делает все атрибуты равными по умолчанию. Вот цитата:
The GetDC function retrieves a common, class, or private DC depending on the class style of the specified window. For class and private DCs, GetDC leaves the previously assigned attributes unchanged. However, for common DCs, GetDC assigns default attributes to the DC each time it is retrieved.
1.9K
16 июня 2005 года
solovey
113 / / 25.07.2004
Цитата:
Originally posted by _const_
Ну тогда примерно так:
Код:
void MyWnd::draw(Shape & figure)
{
[color=#FF0000] //Вставил сюда, т.к. figure.width может меняться непосредственно перед прорисовкой[/color]
 pen->CreatePen(PS_SOLID,figure.width,RGB(0,0,0));
 figure.draw(this);
 pen->DeleteObject();
}

void Line::draw(MyWnd * window)
{
 CDC *pDC = window->pWnd->GetDC();
 CPen *pDefPen;

 pDefPen = pDC->SelectObject(window->pen);
 pDC->MoveTo(beg.x,beg.y); 
 pDC->LineTo(end.x,end.y);
 pDC->SelectObject(pDefPen);

 pDC->ReleaseDC();[color=#FF0000]//не метод CDC :)[/color]

 window->pWnd->ShowWindow(SW_SHOW);
}


При этом надо быть уверенным в том, что pen
1. был корректно создан перед отрисовкой
2. был отсоединен от DC после отрисовки

Все дело в том, что повторный вызов GetDC делает все атрибуты равными по умолчанию. Вот цитата:
The GetDC function retrieves a common, class, or private DC depending on the class style of the specified window. For class and private DCs, GetDC leaves the previously assigned attributes unchanged. However, for common DCs, GetDC assigns default attributes to the DC each time it is retrieved.


Собственно вопрос возник из-за того, что не хотелось в каждую функцию draw наследников класса Shape добавлять строку pDC->SelectObject(window->pen);
Спасибо за разъяснения.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог