Этот вопрос затрагивался не так дано на этом форуме, но работающего решения предложено не было.
Итак, есть 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-приложения?
Здравствуйте, Аноним, Вы писали:
А>Этот вопрос затрагивался не так дано на этом форуме, но работающего решения предложено не было.
А>Итак, есть MFC-ное SDI-приложение. Его окно имеет цвет фона по умолчанию — белый. В некоторый момент надо изменить цвет фона. В MSDNе этот вопрос затрагивался в Q103786. Там рекомендовано для перегрузить функцию OnEraseBkgnd для потомков CWnd. Однако у меня это ничего не дает, — результат тот же самый. Я взял во этот код из заметки, но ожидаемого результата не получил:
Чтобы вызывался обработчик WM_ERASEBKGND, необходимо пари регистрации оконного класса указать поле hbrBackground структуры WNDCLASS равным NULL. MFC же, как я помню, заполняет его стандартной кистью. Я зааплоадил на сайт пример динамического изменения бэкграунда — скачать можно здесь.
Здравствуйте, 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? Можно попросить ваш примерчик?
Здравствуйте, <Аноним>, Вы писали:
K>>Кстати пример кода автора этой ветки у меня тоже нормально работает, что в принципе логично.
А>А у меня почему-то не работает . А>Кстати, для какого объекта надо переопределять OnEraseBkgnd — я пробовал для главного окна и дочернего view? А>Можно попросить ваш примерчик?
1. Создаю визардом MFC/SDI проект.
2. Переопределяю метод OnEraseBkgnd для моего класса представления производного от CView следующим образом:
Всё работает.
Попробуй сделать новый проект так же как я, посмотри будет ли работать.
... << 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 класса.
1. Создаю визардом MFC/SDI проект без поддержки Doc/View.
2. Переопределяю метод OnEraseBkgnd для моего класса CChildView производного от CWnd следующим образом:
Здравствуйте, <Аноним>, Вы писали:
А>Указанный подход действительно "работает" — нужный цвет на доли секунды мелькает на экране. Собственно, проблема в том, чтобы проделать такую же фишку для класса 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>
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.
Здравствуйте, <Аноним>, Вы писали:
А>При попытке привязать class wizard'ом сообщение WM_ERASEBKGND к функции CChildView::OnEraseBkgnd вижу, что оное сообщение отсутствует в списке доступных для привязывания. Что я делаю не так? У меня VS6SP5.
Установи фильтр сообщений для класса CChildView в значение Window.