以前の記事の続き。実際に顧客の端末に導入しに行った時に起きた悲劇について。
端的に言えば「高DPI時に画面レイアウトが崩れて撃沈」した。
こちらで同様の事例が紹介されている。
画像は上記リンク先より引用。文字がはみ出してレイアウトが崩れている。
WindowsのDPI設定を変更することでフォントサイズが大きくなり、コントロールのサイズからはみ出してしまったことが原因だろう。
画面レイアウト作成時には高DPI環境も想定なければならなかったのだが完全に失念していた。
コンピューター、プログラミング、モバイル、ガジェットなどエレクトロニクス分野を中心にネタを提供するウェブサイトです。最近は中国ネタにも注力中。かつてはHWD15向けのAndroidアプリ「HWD15 Status Notifier」を作ってたりしていました。
以前の記事の続き。実際に顧客の端末に導入しに行った時に起きた悲劇について。
端的に言えば「高DPI時に画面レイアウトが崩れて撃沈」した。
こちらで同様の事例が紹介されている。
画像は上記リンク先より引用。文字がはみ出してレイアウトが崩れている。
WindowsのDPI設定を変更することでフォントサイズが大きくなり、コントロールのサイズからはみ出してしまったことが原因だろう。
画面レイアウト作成時には高DPI環境も想定なければならなかったのだが完全に失念していた。
こちらのスライドに詳しく解説がある(一から読むことを推奨するがここでは割愛)
ここで知っておきたいのは、スケーリングの方法には「Windows XP形式」と「DPI仮想化」の2種類があるということ。
という特徴がある。
Windows7の場合、DPIの設定はコントロールパネルのディスプレイ設定から変更できる。
ここをクリックして、
「Windows XP 形式の DPI スケーリングを使用する」のチェックの有無で設定が変わる。デフォルトはオンだ。
上のチェックがオンだとどうなるかというと、初めの画像のようにレイアウトが崩れる。
逆にチェックを外せば「DPI仮想化」モードになり、ぼやけることを引き換えにレイアウト崩れを回避できる。
参考画像↓
百聞は一見に如かず、ということで参考サイトから引用。「DPI仮想化」の場合は単純に画像を引き延ばしているためぼやける。
アプリ側で対応する手間が不要なのでこれはこれでいいのだが、やるならとことんやりたい。ということでもうちょっと「Windows XP形式」の方を掘り下げてみる。
色々とググっていると「画面のスケーリングを無効化」する設定があるという。
EXEファイルを右クリック→「プロパティ」→「互換性」タブのこれだ。
確かにある。でもチェックを入れても崩れたままだ。
どうやらこれは強制的に「Windows XP形式」で表示する、というだけの設定らしい。それはもうディスプレイ設定で指定済みだ。ハズレ。
「app.manifestのdpiAwareをtrueにする」とか「app.configのDpiAwarenessをPerMonitorV2にする」ことで、このアプリケーションはDPI awareだと宣言ができるらしい。のだが、結局行きつく先は上の「高 DPI 設定では画面のスケーリングを無効にする」にチェックを入れるのと同じことらしいのでスルー。
次に見つけたのがFormのAutoScaleModeプロパティ。
画面開発時にFormプロパティのAutoScaleModeをDpiにすると、DPIに応じた画面レイアウトになるらしい。
確かに全く考慮しておらずNoneのままだった。これをDpiに変えると・・・レイアウトが戻った!!!WinForms終わってなかった!!!!
ひとまずレイアウトはうまく表示されたようだったが、よくよくテストしてみると一部のTextboxの高さが大きくなり過ぎていたり、DatagridViewのカラム幅がスケールされず横幅が足りない、といった問題があった。
こちらの掲示板でも
の高さが高くなりすぎる問題が取り上げられている。
また、こちらのサイトでは
が正しくスケーリングされない、という指摘がある。
私の環境で起きたDatagridViewのカラム幅がスケールされない問題はこちらでも指摘されている。
TextBoxの高さ問題については、Panelの中に入れてDock=Fillにすることで解決するようだ。
Panelは問題なくスケールされるため、その中にDock=FillにしたTextBoxを入れることでTextBoxのサイズがPanelに委ねられる、ということらしい。
少々厄介だったのがDataGridView。
コントロール自体やフォントサイズはスケーリングされるものの、幅が変わらないため表示できる文字数がかなり少なくなってしまう。
そこでプロパティを確認してみると、カラム幅を設定できる項目を発見。
AutoSizeColumnsModeをColumnHeaderに。これでカラム幅はヘッダ文字列によって決まるようになり、ヘッダ文字がスケールされたらされた分だけ横幅が大きくなってくれるようになった。強引なやり方なので高DPI環境では若干右側に余りが出来るが、実用に問題がないということで許してもらった。
高さも足りていなかったのでAutoSizeRowsModeをAllCellsに。これでフォントサイズに合わせて高さも調整されるようになった。
最後に、ヘッダの高さも調整するためにColumnHeadersHeightSizeModeをAutoSizeを設定。これでなんちゃって高DPI対応ができた。
一方でWPFやUWPは標準で高DPIに対応しており、作りも今どきで新しい環境に適した作りになっている。
かたやWinFormsはVBやMFCなどの「過去の遺産」を置き換える立ち位置でもある。MVCモデルにも対応していないし、全体的に古臭いのは否めない。
とはいえWinFormsが使い物にならないかといえばそうでもない。UIをさほど重要視しない業務用アプリケーションの場合、WinFormsを選んでも大きなデメリットは無いだろう。寧ろ既存の情報が多く出揃っている分だけ開発の工数が見積もりやすい側面もある。
MVCモデルはあくまでデザインパターンの一つなわけで、開発時に適切なデザイン設計がなされているのであればMVCモデルにこだわる必要は無い。
また、長期に渡って運用・保守を行う前提のシステムの場合は枯れた仕組みの方が歓迎される。
そこらへんの良し悪しは案件ごとに大きく変わるので、一方から見てオワコンと決めつけるのは早計だろう。
もちろんその逆もまた然りなので、常にWPF/UWPも考慮しなければいけない。んだけどUWPはやっぱり好かんなぁ...。
コメントする