-
Notifications
You must be signed in to change notification settings - Fork 165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
プロパティシートのコントロール表示のちらつき防止 #1424
プロパティシートのコントロール表示のちらつき防止 #1424
Conversation
✅ Build sakura 1.0.3141 completed (commit cec4c67bcc by @beru) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ほぼいちゃもんですが
::SendMessageAny
は使わないほうがよいと思います。
request changes な指摘はこれだけです。
PRの目的である「ちらつきを抑えたい」は、動かしてみてもちらつきが減ったかぼくには判断できないので、他の方にお任せします。
@@ -694,6 +695,8 @@ void CPropCustmenu::SetDataMenuList(HWND hwndDlg, int nIdx) | |||
::DlgItem_SetText( hwndDlg, IDC_EDIT_MENUNAME, m_Common.m_sCustomMenu.m_szCustMenuNameArr[nIdx] ); | |||
|
|||
CheckDlgButtonBool( hwndDlg, IDC_CHECK_SUBMENU, m_Common.m_sCustomMenu.m_bCustMenuPopupArr[nIdx] ); | |||
::SendMessageAny( hwndDlg, WM_SETREDRAW, TRUE, 0 ); | |||
::InvalidateRect( hwndDlg, NULL, FALSE ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ん?これは必要ですか・・・?
(たぶん、必要だから入れてると思いますが念のための確認です。)
window描画の仕組み
- 外部から WM_UPDATE を送る。
- WM_UPDATE を受け取ったウインドウは、クライアント領域に更新領域があれば自身に WM_PAINT を送る。
- WM_PAINT を受け取ったウインドウは、クライアント領域を描画する。
InvalidateRect(hwnd, NULL, FALSE)
は、クライアント領域の全域更新を指示する命令です。WM_SETREDRAW で再描画フラグを戻しただけだけだと更新されない仕様だと思うんですが、ここに要るなら他にもいるような気がして、何故ここだけ?と思いました。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
コントロールのウィンドウの変更に対して WM_SETREDRAW する場合は後で InvalidateRect を呼ばないでも表示が更新されてたんですが、親のダイアログの場合は呼ばないと表示が更新されませんでした。理屈は分かっていません。
//キーワード数を表示する。 | ||
DispKeywordCount( hwndDlg ); | ||
|
||
::SendMessageAny( hwndDlg, WM_SETREDRAW, TRUE, 0 ); | ||
InvalidateRect(hwndDlg, NULL, FALSE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ここにはありますね・・・
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ここも親ダイアログに対しての場合ですね。
@@ -1187,7 +1187,7 @@ BEGIN | |||
LTEXT "閉じるボタン(&X)", IDC_TextTabClose, 124, 116, 48, 8 | |||
COMBOBOX IDC_CHECK_DispTabClose, 173, 113, 46, 80, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP | |||
PUSHBUTTON "フォント(&F)...", IDC_BUTTON_TABFONT, 232, 113, 51, 14 | |||
RTEXT "Font", IDC_STATIC_TABFONT, 102, 127, 180, 17, SS_RIGHT | |||
RTEXT "Font", IDC_STATIC_TABFONT, 102, 127, 180, 12, SS_RIGHT |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
これは必要です? or NOT?
必要なら入れたらよいと思います。
右寄せラベルの高さが大きくなってるのを文字に合わせる変更に見えていて、ちらつき防止と関係あるようには思えないのですが・・・。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WS_EX_COMPOSITED を付けるとこの変更入れないと表示に問題がありました。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://docs.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles
の WS_EX_COMPOSITED
の解説ですが
Paints all descendants of a window in bottom-to-top painting order using double-buffering. Bottom-to-top painting order allows a descendent window to have translucency (alpha) and transparency (color-key) effects, but only if the descendent window also has the WS_EX_TRANSPARENT bit set. Double-buffering allows the window and its descendents to be painted without flicker. This cannot be used if the window has a class style of either CS_OWNDC or CS_CLASSDC.
Windows 2000: This style is not supported.
と書かれています。bottom-to-top painting order
というのが画面のXYのYの上下の事なのかZ-orderの上下の事なのかわかっていませんが(多分後者)この事が関わっていそうです。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bottom-to-top painting order
というのが画面のXYのYの上下の事なのかZ-orderの上下の事なのかわかっていませんが(多分後者)この事が関わっていそうです。
画面の下から上の順番でコントロールを描画していくってことでしょうね。
通常は上から下の順番で描画されていると考えると、下方向にはみ出したコントロールがこれまで問題にならず、拡張スタイルの追加でおかしくなった理由を説明できると思います。従来ははみ出した部分を下側にあるコントロールで上書きしていたから問題にならず、変更により描画済みのコントロールの上にはみ出して描画するようになったっちゅうことです。
これについてですが変更前と変更後でアプリを両方とも起動して交互に操作して見比べるのを繰り返さないとなかなか判断出来ないと思います。 |
✅ Build sakura 1.0.3142 completed (commit 2f6454c6c2 by @beru) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
コードで気になる点は解消したと思います。
変更したプロパティーシートでドロップダウンリストが表示できることも確認しました。
変更前の「ちらつく」について定量的な表現で事象を解説してもらえれば、改修確認のデータ取ってもよいです。目視チェックする能力はないので、目視がいい場合は他の人に頼んでください。
いつかHFR(ハイフレームレート) 撮影が出来るカメラを購入して撮影した動画を YouTube において確認出来るようにしようかと思います。 |
超スロー再生にしたときに問題のある瞬間のコマがどう見えるか、 |
百聞は一見にしかず、ということわざがあるぐらいなので言葉で説明してもきちんと伝わるか自信が無いですが書いてみます。 本来は表示する必要のない途中の絵が見えてしまうのがちらつきの原因です。例えばユーザーが操作をする前にリストボックスにアイテムがたくさん表示されているとして、操作後に下記の処理が行われるとします。
上記の処理の途中、例えばリストボックスのアイテムを全消去した後の内容が表示されると、そのコマの絵ではリストボックスのアイテムは空表示になります。上記の処理がすべて完了後にも描画が行われますが、そのコマではリストボックスにアイテムが入った状態の絵になります。
途中の 2 の絵は本来は表示する必要は無いもので、表示されるととても短い時間の間に 1 -> 2 -> 3 の3コマが表示されるのでその分画面の表示の切り替わりが頻繁になり、表示がちらついたような印象を受けます。 実際には3コマだけとも限らず、中間の状態のコマがもっとたくさん間に挟まって表示されてしまう事もあります。よく行われる対策としては、LB_ADDSTRING するループの前後で WM_SETREDRAW を送って再描画を抑制します。このPRでやっている事も基本的には同じです。 |
なんどやっても変更前 455a7ff の挙動を「ちらつく」と感じませんでした。 共通設定 ダイアログ 目視の範疇では 本当に目視で「ちらつき」を感じていますか? |
と書かれているので 「ちらつく」は科学的に説明できる現象で、C/C++特有の
よくある不具合なので対策手法の定石があります。 描画途中が見えてしまうことが問題ならば、見せなきゃよいのです。 修正内容は一定区間で発生する描画命令を抑制させるので、定石に照らして適切である、と予想できます。 問題は、実際の不具合事象を確認できていないのに理屈のみを以て approve してよいか? ということで、 |
上記のコメントに ScreenToGif でキャプチャして保存したアニメーションGIFファイルを貼り付けました。 下記のページでは同じ動画を 1/10 の速度で再生しています。 |
#1424 (comment) よく考えてみたらPRの事象確認には結構な描画性能を持つマシンを使っていて、他の端末での確認は行っていませんでした。 発生メカニズムからして「人の能力」ではなくて「マシンの能力」が影響する可能性に気付きました。 無駄な再描画(=クリアして描画し直し)を繰り返し行なう「不適切なコード」があったとして、 これをもって改善効果を確認できたとしてよいような気がしますがどうでしょう? |
マシンの能力も関係すると思います。ところで一般的にモニタのリフレッシュレートは 60Hzですが、240Hzのゲーミングモニターを使えば(マシンパワーが十分にあれば)中間のコマが更に表示される可能性は増えますね。無駄な中間のコマを表示すると計算量も増えてしまうので、リスト系のコントロールに大量にアイテムを登録する場合には WM_SETREDRAW を使って再描画を抑える事が推奨されています。 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
問題ないと思います。
レビューありがとうございます。Mergeします。 |
PR の目的
共通設定の画面において、主にリスト系のコントロールの内容を切り替える際にちらついて表示されるので、それがなるべく起きないようにするのが目的です。
カテゴリ
PR の背景
画面を操作していてコントロールの表示のちらつきが気になったので下記の対策を入れました。
WM_SETREDRAW
メッセージを送る事で表示更新のタイミングを制御InvalidateRect
を実行しないと画面の表示が更新されないので、そうするようにしました。WS_EX_COMPOSITED
を付けてダブルバッファリングされるようにしました。これをやらないでもちらつきが特に気にならないレベルまで解消される場合もありますが、そうでない場合もあります。メカニズムがいまいち不明なのと、動作環境によって挙動が変わるかもしれません。PR のメリット
表示のちらつきが減ります。
PR のデメリット (トレードオフとかあれば)
WS_EX_COMPOSITED
スタイルを付けてダブルバッファリングしているのでメモリ使用量が増えます。ただし最近のPCであれば問題になるような増加量では無い筈です。仕様・動作説明
テスト内容
画面表示を目視で確認しました。
リスト表示のちらつきが減ったかどうかの確認は、ドロップダウンリストの選択を切り替えるとリストの表示内容が切り替わるので、その際のちらつきが減ったかどうかを確認しました。
PR の影響範囲
下記の画面に手を入れました。
関連 issue, PR
参考資料
https://docs.microsoft.com/en-us/windows/win32/gdi/wm-setredraw
https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-invalidaterect
https://devblogs.microsoft.com/oldnewthing/20171018-00/?p=97245
https://devblogs.microsoft.com/oldnewthing/20110124-00/?p=11683