Introduction

MFCなんかレガシーもいいところですが、仕事である以上使わざるを得ません。
そんな中、CSliderCtrlの背景色をCDialog::OnCtlColor経由で変更したところ、背景色が変わらない問題が発生。

CWnd::UpdateWindowCWnd::InvalidateRectを駆使しても効果が無い。
なぜ?とネットを彷徨った際の備忘録(今後使う可能性は低いが) ソースは下記になります

Resolution

CSliderCtrlは下記の、少し奇妙な関数を持っています。

  • CSliderCtrl::ClearSel
  • CSliderCtrl::ClearTics
  • CSliderCtrl::SetRange
  • CSliderCtrl::SetRangeMax
  • CSliderCtrl::SetRangeMin

これらの関数は最後の引数に BOOL bRedraw = FALSE をとります。
これらの関数にTRUEを渡すことで背景の更新が可能になります。

Spyで確認したのですが、これらの関数は内部で WM_PAINTを使っているようです。
そのため CWnd::UpdateWindow を使って同じ状況を作り出したにもかかわらず、CWnd::UpdateWindow は効果が無い。

この現象に言及した唯一の記事が下記。

上記の関数以外にも、CWnd::EnableWindowでも更新が可能だと言っています。
しかし、この関数を使う場合は、一度現在のEnable/Disableと反対の値を設定する必要があるため、著しくちらつく欠点があります。

ですので、最初に紹介した関数を使うことで、ちらつきを押さえて背景色を更新できます。
つまり、現在の設定と同じ値を使って更新するのです。

1
2
3
4
5
6
7
void CSliderSampleDlg::OnBnClickedButtonRedraw()
{
const auto max = this->m_slider.GetRangeMax();
const auto min = this->m_slider.GetRangeMin();
// Set same value to redraw
this->m_slider.SetRange(min, max, TRUE);
}

後は、SliderをGUIで操作して値を変更することでも背景が更新されますが、コードから変更しないと意味が無いので却下。
サンプルは下記のような感じです。

Source Code

https://github.com/takuya-takeuchi/Demo/tree/master/MFC1