Об изменении цвета фона окна "на лету".
От: Аноним  
Дата: 22.03.04 09:27
Оценка:
Этот вопрос затрагивался не так дано на этом форуме, но работающего решения предложено не было.

Итак, есть MFC-ное SDI-приложение. Его окно имеет цвет фона по умолчанию — белый. В некоторый момент надо изменить цвет фона. В MSDNе этот вопрос затрагивался в Q103786. Там рекомендовано для перегрузить функцию OnEraseBkgnd для потомков CWnd. Однако у меня это ничего не дает, — результат тот же самый. Я взял во этот код из заметки, но ожидаемого результата не получил:


BOOL CChildView::OnEraseBkgnd(CDC* pDC)
{
  // Set brush to desired background color
  CBrush backBrush(RGB(255, 128, 128));
  // Save old brush
  CBrush* pOldBrush = pDC->SelectObject(&backBrush);
  CRect rect;
  pDC->GetClipBox(&rect);     // Erase the area needed
  pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY);
  pDC->SelectObject(pOldBrush);
  return TRUE;
}


Что я делаю не так?

Аналогично не дали результатов и попытки перегрузить OnCtlColor — как советовали в одном из ответов в предыдущем обсуждении. Исследования показали, что перегруженные функции (в обоих случаях) никогда не вызывались. Попытка внаглую переопределить CWnd::OnEraseBkgnd также не дает результатов.

Таким образом, вопрос остается открытым — как программно менять цвет фона окна MFC/SDI-приложения?
Re: Об изменении цвета фона окна "на лету".
От: SchweinDeBurg Россия https://zarezky.spb.ru/
Дата: 22.03.04 09:51
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Этот вопрос затрагивался не так дано на этом форуме, но работающего решения предложено не было.


А>Итак, есть MFC-ное SDI-приложение. Его окно имеет цвет фона по умолчанию — белый. В некоторый момент надо изменить цвет фона. В MSDNе этот вопрос затрагивался в Q103786. Там рекомендовано для перегрузить функцию OnEraseBkgnd для потомков CWnd. Однако у меня это ничего не дает, — результат тот же самый. Я взял во этот код из заметки, но ожидаемого результата не получил:


Чтобы вызывался обработчик WM_ERASEBKGND, необходимо пари регистрации оконного класса указать поле hbrBackground структуры WNDCLASS равным NULL. MFC же, как я помню, заполняет его стандартной кистью. Я зааплоадил на сайт пример динамического изменения бэкграунда — скачать можно здесь.
- Искренне ваш, Поросенок Пафнутий
Re[2]: Об изменении цвета фона окна "на лету".
От: korzhik Россия  
Дата: 22.03.04 10:28
Оценка:
Здравствуйте, SchweinDeBurg, Вы писали:

SDB>Чтобы вызывался обработчик WM_ERASEBKGND, необходимо пари регистрации оконного класса указать поле hbrBackground структуры WNDCLASS равным NULL.

Не согласен с вами.
Обработчик WM_ERASEBKGND вызывается по любому.
Только вот если поле hbrBackground структуры WNDCLASS равно NULL,
то приложение обязано само рисовать фон.
Даже в вашем примере возьмите и приравняйте hbrBackground не к NULL, а к какой нибудь кисти,
всё равно будет вызываться ваш обработчик WM_ERASEBKGND.
Кстати пример кода автора этой ветки у меня тоже нормально работает, что в принципе логично.
... << RSDN@Home 1.1.3 stable >>
Re[3]: Об изменении цвета фона окна "на лету".
От: Аноним  
Дата: 22.03.04 10:54
Оценка:
Здравствуйте, korzhik, Вы писали:

K>Даже в вашем примере возьмите и приравняйте hbrBackground не к NULL, а к какой нибудь кисти,

K>всё равно будет вызываться ваш обработчик WM_ERASEBKGND.
K>Кстати пример кода автора этой ветки у меня тоже нормально работает, что в принципе логично.

А у меня почему-то не работает . Кстати, для какого объекта надо переопределять OnEraseBkgnd — я пробовал для главного окна и дочернего view? Можно попросить ваш примерчик?

Всего.
Re[4]: Об изменении цвета фона окна "на лету".
От: korzhik Россия  
Дата: 22.03.04 12:08
Оценка:
Здравствуйте, <Аноним>, Вы писали:

K>>Кстати пример кода автора этой ветки у меня тоже нормально работает, что в принципе логично.


А>А у меня почему-то не работает .

А>Кстати, для какого объекта надо переопределять OnEraseBkgnd — я пробовал для главного окна и дочернего view?
А>Можно попросить ваш примерчик?

1. Создаю визардом MFC/SDI проект.
2. Переопределяю метод OnEraseBkgnd для моего класса представления производного от CView следующим образом:
BOOL CTestView::OnEraseBkgnd(CDC* pDC)
{
  CBrush backBrush(RGB(0, 128, 128));
  CBrush* pOldBrush = pDC->SelectObject(&backBrush);
  CRect rect;
  pDC->GetClipBox(&rect);    
  pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY);
  pDC->SelectObject(pOldBrush);
  return TRUE;
}

Всё работает.
Попробуй сделать новый проект так же как я, посмотри будет ли работать.
... << RSDN@Home 1.1.3 stable >>
Re[5]: Об изменении цвета фона окна "на лету".
От: Аноним  
Дата: 22.03.04 12:58
Оценка:
Здравствуйте, korzhik, Вы писали:

K>1. Создаю визардом MFC/SDI проект.

Да. Простейший проект MFC/SDI без Doc/View.

K>2. Переопределяю метод OnEraseBkgnd для моего класса представления производного от CView следующим образом:

Я забыл сказать, что у меня Doc/View не используется. Соответсвенно, нет классов, производных от CView.

У меня есть следующие классы:
class CBgcolormfcApp : public CWinApp;
class CMainFrame : public CFrameWnd;
class CChildView : public CWnd;

В точности воспроизвожу заданный код. Кстати, classWizard позволяет мне добавить обработчик сообщения WM_ERASEBKGND только для CFrameWnd, и не позволяет для CChildView (производного от CWnd), хотя в Q103786 сказано следующее (там явно указан класс CWnd):


SUMMARY
To change the background color for a CView, CFrameWnd, or CWnd object, process the WM_ERASEBKGND message. The sample code below demonstrates how to do this.


Указанный подход действительно "работает" — нужный цвет на доли секунды мелькает на экране. Собственно, проблема в том, чтобы проделать такую же фишку для класса CChildView, производного от CWnd, но для него сообщения WM_ERASEBKGND не мапятся — class wizard не позволяет установить обработчик для этого сообщения. Так что указанный подход, вероятно, не работает.

K>Всё работает.

K>Попробуй сделать новый проект так же как я, посмотри будет ли работать.
Попробовал, для приложения в архитектуре Doc/View все действительно работает.

Таким образом, вопрос почти снят. Почти — потому что осталось сделать то же самое для приложения не Doc/View, или для произвольного производного от CWnd класса.

Всего.
Re[6]: Об изменении цвета фона окна "на лету".
От: korzhik Россия  
Дата: 22.03.04 14:40
Оценка:
Здравствуйте, <Аноним>, Вы писали:

1. Создаю визардом MFC/SDI проект без поддержки Doc/View.
2. Переопределяю метод OnEraseBkgnd для моего класса CChildView производного от CWnd следующим образом:
BOOL CChildView::OnEraseBkgnd(CDC* pDC)
{
  CBrush backBrush(RGB(0, 128, 128));
  CBrush* pOldBrush = pDC->SelectObject(&backBrush);
  CRect rect;
  pDC->GetClipBox(&rect);    
  pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY);
  pDC->SelectObject(pOldBrush);
  return TRUE;
}

Опять всё работает. Что опять же логично.
... << RSDN@Home 1.1.3 stable >>
Re[6]: Об изменении цвета фона окна "на лету".
От: korzhik Россия  
Дата: 22.03.04 14:40
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Указанный подход действительно "работает" — нужный цвет на доли секунды мелькает на экране. Собственно, проблема в том, чтобы проделать такую же фишку для класса CChildView, производного от CWnd, но для него сообщения WM_ERASEBKGND не мапятся — class wizard не позволяет установить обработчик для этого сообщения.

Ручками добавь метод, без ClassWizard.
В хедере:
public:
    afx_msg BOOL OnEraseBkgnd(CDC* pDC);
... << RSDN@Home 1.1.3 stable >>
Re[7]: Об изменении цвета фона окна "на лету".
От: Аноним  
Дата: 22.03.04 15:03
Оценка:
Здравствуйте, korzhik, Вы писали:

K>Здравствуйте, <Аноним>, Вы писали:


K>1. Создаю визардом MFC/SDI проект без поддержки Doc/View.

K>2. Переопределяю метод OnEraseBkgnd для моего класса CChildView производного от CWnd следующим образом:
K>
K>BOOL CChildView::OnEraseBkgnd(CDC* pDC)
K>{
K>  CBrush backBrush(RGB(0, 128, 128));
K>  CBrush* pOldBrush = pDC->SelectObject(&backBrush);
K>  CRect rect;
  pDC->>GetClipBox(&rect);    
  pDC->>PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY);
  pDC->>SelectObject(pOldBrush);
K>  return TRUE;
K>}
K>

K>Опять всё работает. Что опять же логично.
У меня не работает. Делаю вот так:

Вот мое определение класса CChildView


class CChildView : public CWnd
{
// Construction
public:
    CChildView();

// Attributes
public:

// Operations
public:

// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CChildView)
    protected:
    virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
    //}}AFX_VIRTUAL

// Implementation
public:
    virtual ~CChildView();


    // Generated message map functions
protected:
    //{{AFX_MSG(CChildView)
    afx_msg void OnPaint();
  afx_msg BOOL OnEraseBkgnd(CDC* pDC);
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};


Вот описание функции CChildView::OnEraseBkgnd:

BOOL CChildView::OnEraseBkgnd(CDC* pDC)
{
// Set brush to desired background color
  CBrush backBrush(RGB(0, 255, 255));

// Save old brush
  CBrush* pOldBrush = pDC->SelectObject(&backBrush);

  CRect rect;
  pDC->GetClipBox(&rect);     // Erase the area needed

  pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY);
  pDC->SelectObject(pOldBrush);
  return TRUE;
}


Не работает. Фон окна остается белым. При попытке привязать class wizard'ом сообщение WM_ERASEBKGND к функции CChildView::OnEraseBkgnd вижу, что оное сообщение отсутствует в списке доступных для привязывания. Что я делаю не так? У меня VS6SP5.

Всего.
Re[8]: Об изменении цвета фона окна "на лету".
От: Lone Беларусь  
Дата: 22.03.04 18:23
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>При попытке привязать class wizard'ом сообщение WM_ERASEBKGND к функции CChildView::OnEraseBkgnd вижу, что оное сообщение отсутствует в списке доступных для привязывания. Что я делаю не так? У меня VS6SP5.


Установи фильтр сообщений для класса CChildView в значение Window.
... << RSDN@Home 1.1.2 stable >>
Re: Об изменении цвета фона окна "на лету".
От: Fedor.P  
Дата: 22.03.04 20:26
Оценка:
Я в этом случае изменяю кисть класса, к которому принадлежит окно:

::SetClassLong(MainFrm.m_hWnd, GCL_BACKGROUND, ::CreateSolidBrush(RGB(239,235,206)));

— получается цвет фона как в XP
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.