Фон MFC CButton игнорируется Windows 7 - PullRequest
0 голосов
/ 14 ноября 2011

Чтобы изменить внешний вид (цвет фона и цвет текста текста) флажка MFC и радиокнопки, я использовал следующую реализацию, которая прекрасно работала в Windows 2000, наполовину в Windows XP, но не в Windows 7:

BEGIN_MESSAGE_MAP(mycheckbox, CButton)
  ...
  ON_WM_CTLCOLOR_REFLECT()
  ...
END_MESSAGE_MAP()

HBRUSH mycheckbox::CtlColor(CDC* pDC, UINT nCtlColor)
{
  pDC->SetBkColor( RGB( 255, 0, 0 ) );
  pDC->SetTextColor( RGB( 0, 255, 0 ) );
  return m_brush;
}

Это прекрасно работает, если используется тема Windows Classic.Однако при использовании другой темы:

  • Симптомы в Windows XP: SetBkColor работает, но SetTextColor игнорируется
  • Симптомы в Windows 7: и SetBkColor, и SetTextColor игнорируются

Я пытался OnEraseBkgnd залить фон пользовательским цветом (pDC->FillSolidRect), но даже это не дало эффекта.

Я хочу избежать использования ownerdrawn OnPaintпоэтому флажки и отметки радио продолжают следовать теме, которая активна в Windows.Как написано ранее, этот код используется в W2000, Windows Xp, Vista и Windows 7 ... Я просто хочу изменить цвет фона и цвет текста.

Ответы [ 4 ]

1 голос
/ 16 ноября 2011

Я написал CButton, который будет использовать ownerdraw, когда тематика активна в Windows (это не тот случай, когда используется Windows Classic), и будет делать это динамически.Этот пример кода не является полным, но он демонстрирует все необходимое для получения результатов.

Сложная часть заключается в том, что вам необходимо представлять выделенные и нажатые состояния, см. Параметры для DrawCheckBox.Я игнорирую их, поскольку они не будут полностью пропущены в моем приложении.

IMPLEMENT_DYNAMIC(mycheckbox, CButton)

mycheckbox::mycheckbox()
  : mv_bIsChecked( false )
{
  m_brush.CreateSolidBrush( RGB( 0,0,255) );
}

mycheckbox::~mycheckbox()
{
}

BEGIN_MESSAGE_MAP(mycheckbox, CButton)
  ON_WM_CTLCOLOR_REFLECT()
  ON_WM_PAINT()
  ON_CONTROL_REFLECT(BN_CLICKED, &mycheckbox::OnBnClicked)
END_MESSAGE_MAP()

HBRUSH mycheckbox::CtlColor(CDC* pDC, UINT nCtlColor)
{
  pDC->SetBkColor( RGB( 255, 0, 0 ) );   // text background color
  pDC->SetTextColor( RGB( 0, 255, 0 ) ); // text foreground color
  return m_brush;                        // control background
}

void mycheckbox::DrawItem(LPDRAWITEMSTRUCT)
{
}

void mycheckbox::OnPaint()
{
  if( ( GetStyle() & BS_OWNERDRAW ) == BS_OWNERDRAW )
  {
    CPaintDC dc( this );

    RECT rect;
    GetClientRect( & rect );
    rect.right = rect.left + 20;
    CMFCVisualManager::GetInstance()->DrawCheckBox(
                & dc
              , rect
              , false                               // highlighted
              , mv_bIsChecked ? 1 : 0 // state
              , true                                // enabled
              , false                               // pressed
              );

    // draw text next to the checkbox if you like
  }
  else
    __super::OnPaint();
}

  // when BS_OWNERDAW is active,
  // GetCheck() is reporting a wrong value
  // so we have to do a little bookkeeping ourselves
void mycheckbox::OnBnClicked()
{
  mv_bIsChecked = ! mv_bIsChecked;
}

BOOL mycheckbox::PreCreateWindow( CREATESTRUCT & cs )
{
  CString lv_szValue;
  CSettingsStore lv_Registry( FALSE, TRUE );
  lv_Registry.Open( _T("Software\\Microsoft\\Windows\\CurrentVersion\\ThemeManager") );
  lv_Registry.Read( _T("ThemeActive"), lv_szValue );
  lv_Registry.Close();
  if( lv_szValue == _T("1") )
    cs.style |= BS_OWNERDRAW;

  return CButton::PreCreateWindow(cs);
}

Я даже пробовал переключать темы во время выполнения, однако это дает нежелательный эффект при переключении с темы Windows 7 на Windows Classic (установите флажок тогдавыглядит как обычная кнопка).Так что я не пользуюсь этим, но, возможно, интересно поделиться:

void mycheckbox::OnNMThemeChanged( NMHDR * pNMHDR, LRESULT * pResult )
{
  CString lv_szValue;
  CSettingsStore lv_Registry( FALSE, TRUE );
  lv_Registry.Open( _T("Software\\Microsoft\\Windows\\CurrentVersion\\ThemeManager") );
  lv_Registry.Read( _T("ThemeActive"), lv_szValue );
  lv_Registry.Close();

  ModifyStyle( BS_OWNERDRAW, 0 ); // turn off
  if( lv_szValue == _T("1") )
    ModifyStyle( 0, BS_OWNERDRAW ); // turn on

  // This feature requires Windows XP or greater.
  // The symbol _WIN32_WINNT must be >= 0x0501.
  // TODO: Add your control notification handler code here
  *pResult = 0;
}
1 голос
/ 14 ноября 2011

CButton не делает ничего больше, чем вызывает процедуру окна Windows по умолчанию для рисования кнопки. Вы можете переопределить код OnPaint, чтобы сделать свое дело, но я могу понять, почему вы хотели бы избежать этого - очень много работы, чтобы правильно выглядело при любых обстоятельствах.

MFC предоставляет другой класс CMFCButton, который имеет переопределяемый метод OnFillBackground, посмотрите, работает ли он для вас.

0 голосов
/ 16 ноября 2011

Поверьте мне, лучшее решение здесь - иметь CStatic с текстом и CButton, содержащий только флажок. Начиная с Vista, изменение фона флажков является проблемой, если не сказать больше.

0 голосов
/ 15 ноября 2011

Согласно этой статье Microsoft :

Чтобы изменить цвет фона кнопки управления в Windows 3.0 и позже необходимо создать кнопку рисования владельца.

Если вы хотите, чтобы определенные элементы управления выглядели по-другому, я думаю, что лучше сделать это подклассом.

Эта статья будет полезна для понимания подклассов.

Здесь, чтобы изменить фон и цвет текста кнопки, вам потребуется получить новый класс из CButton скажем MyButton и переопределить его DrawItem функцию добавьте код для рисования этого конкретного элемента управления на вашем пути.

Примечание: вам нужно установить свойство draw владельца (BS_OWNERDRAW) для этих элементов управления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...