A certain engineer "COMPLEX"

開発メモ その131 CSliderCtrlの背景色が変更されない

Introduction


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

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

ソースは下記になります

Sample source code for Demonstration, Experiment and Test - takuya-takeuchi/Demo

Resolution


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

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

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

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

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

I am working on a C++ MFC project and bumping in the following. I have a CSliderCtrl on my form which I call MFC_scKINECTANGLE. To make it the way I want it ...

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

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


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

コメントを残す

メールアドレスが公開されることはありません。

%d人のブロガーが「いいね」をつけました。