Re: Отключение custom-отрисовки в контролах
От: Master Yoda Великобритания  
Дата: 17.08.06 09:33
Оценка: 2 (1)
Здравствуйте, Yuri_Ch, Вы писали:

Y_C>1. Правильно ли следующее решение — завести глобальную переменную g_isNativeTheme, и проверять ее в каждом методе, имеющем отношеие к переопределению контрола.


К глобальным переменным вообще у многих людей отношение неоднозначное Я бы лучше создал метод например у объекта приложения:

class CMyApp: public CWinApp { /* ... * };

inline bool CMyApp::UseNativeTheme() {
    return m_bUseNativeTheme;
}


Но это конечно не принципиально.

<...>

Y_C>2. Вышеуказанное решение работает только при перезапуске приложения.


Да прям... Пробовал окно развернуть/свернуть?

Y_C>Когда я пытаюсь реализовать флажок Disable All Skins, примеро так:


<...>

Y_C>Но контролы не перерисовываются. Если идеи? Если моя ошибка очень грубая и очевидная, не бейте сильно по голове, ОК? Программист я пока очень начинающий


Попробуй

AfxGetMainWnd()->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_ALLCHILDREN);
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
Отключение custom-отрисовки в контролах
От: Yuri_Ch Россия  
Дата: 17.08.06 09:25
Оценка:
Исправлено форматирование текста. — SchweinDeBurg

Здравствуйте
Имеется следующая задача — есть несколько контролов (Button, Radio, Checkbox) с переопределенной отрисовкой (картинка берется из png-файла). Контролы писал не я. Необходимо реализовать функцию отключения custom-отрисовки, что-то типа переключения тем в Windows.
1. Правильно ли следующее решение — завести глобальную переменную g_isNativeTheme, и проверять ее в каждом методе, имеющем отношеие к переопределению контрола. В методах типа DrawItem(), OnMouseMove() я вызывал метод родитеьского класса, примерно так:

    if (g_isNativeTheme)
    {
        CButton::OnMouseMove(nFlags, point);
        return;
    }

Метода, характерные только для custom-контрола, превращаются в заглушки, например, OnTimer():

if (g_isNativeTheme) return;

2. Вышеуказанное решение работает только при перезапуске приложения. Когда я пытаюсь реализовать флажок Disable All Skins, примеро так:

void CSettingsGenDialog::OnBnClickedCheckSetgenDisskin()
{
    UpdateData(TRUE);    //считывает из checkbox
    g_isNativeTheme = m_disableTheme;//устанавливаем глобальную переменную
                                         //(здесь точно все работает!)
    InvalidateRect(NULL);//обновить окно настроек
    CWnd* w = AfxGetMainWnd();
    w->InvalidateRect(NULL);//обновить главное окно
}

Но контролы не перерисовываются. Если идеи? Если моя ошибка очень грубая и очевидная, не бейте сильно по голове, ОК? Программист я пока очень начинающий
Re[2]: Отключение custom-отрисовки в контролах
От: Yuri_Ch Россия  
Дата: 17.08.06 09:37
Оценка:
Сворачивать пробовал, не отрисовывается (странно, верно?)
Redraw сейчас попробую
Re[2]: Отключение custom-отрисовки в контролах
От: Yuri_Ch Россия  
Дата: 17.08.06 09:51
Оценка:
Ну, что-то прояснилось
Перерисовка при снятии флажка (используется custom-отрисовка) работает! Но обратно вместо контрола отображается пустое окно. Я посмотрел, там изначально во всех классах контролов в OnEraseBkgnd() была заглушка
return TRUE;

может, из-за этого? Только как работало непонятно

И еще, кроме окна настроек и главного окна есть еще окна, там перерисовка тоже не происходит.
Re[3]: Отключение custom-отрисовки в контролах
От: Master Yoda Великобритания  
Дата: 17.08.06 10:12
Оценка:
Здравствуйте, Yuri_Ch, Вы писали:

Y_C>Перерисовка при снятии флажка (используется custom-отрисовка) работает! Но обратно вместо контрола отображается пустое окно. Я посмотрел, там изначально во всех классах контролов в OnEraseBkgnd() была заглушка

Y_C>
Y_C>return TRUE;
Y_C>

Y_C>может, из-за этого? Только как работало непонятно

Это говорит о том, что прорисовка фона по умолчанию не используется (возможно для того чтобы избежать мерцания). Является ли это причиной глюка не знаю, но думаю что если не используется кастомная отрисовка (т.е. когда соответствующий флажок снят), лучше бы не возвращать из этого метода TRUE, а вызывать обработку базового класса:

BOOL CMyComboBox::OnEraseBkgnd(CDC* pDC) {
    CMyApp* pApp = static_cast<CMyApp*>(AfxGetApp());
    if(pApp->UseNativeTheme) {
        return CComboBox::OnEraseBkgnd(pDC);
    } else {
        return TRUE;
    }
}


Y_C>И еще, кроме окна настроек и главного окна есть еще окна, там перерисовка тоже не происходит.


Можно хранить где-нибудь список всех открытых окон приложения верхнего уровня и перерисовывать их при изменении настроек:

CTypedPtrList<CObList, CWnd*> topLevelWindows;

// ...

// изменили настройки
// ...
POSITION pos = topLevelWindows.GetHeadPosition();
while(NULL != pos) {
    CWnd* pWnd = topLevelWindows.GetNext(pos);
    pWnd->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_ALLCHILDREN);
}


Другой вариант, не требующий использования списка — использовать EnumWindows (перечисление всех окон верхнего уровня), GetWindowThreadProcessId() (для определения того ,что окно принадлжеит нашему приложению), IsWindowVisible() (нет смысла перерисовывать невидимые окна), CWnd::FromHandle (для получения указателя на объект CWnd), CWnd::RedrawWindow (собственно перерисовка)
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
Re[4]: Отключение custom-отрисовки в контролах
От: Yuri_Ch Россия  
Дата: 17.08.06 10:23
Оценка:
Спасибо
Сейчас попробую
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.