アカウント名:
パスワード:
高DPI対応とは名ばかりのクソアプリとか高DPIでレイアウトがめちゃくちゃになってもまったく対応する気のないアプリとかを、ようやく高DPI環境でまともに使えるようになった。
ちなみにSystem (Enhanced)は新機能だけど、Systemに相当する設定("DPIunaware" shim)は従来から存在していた。ただ従来は標準でUIがなかったので、アプリのmanifestを無理やり書き換えるとかApplication Compatibility Toolkitをインストールするとかする必要があったし、表示がぼやけるのでそこまでする気にもあまりなれなかった。
(以下、デスクトップアプリの開発者向けの情報)mmc.exeのmanifestによると、
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">false</dpiAware><gdiScaling xmlns="http://schemas.microsoft.com/SMI/2017/WindowsSettings">true</gdiScaling>
のような宣言をすることで、ユーザーに互換性オプションを設定させなくてもSystem (Enhanced)を設定したのと同等の状態にできるらしい。
テキストやGDIでの幾何学図形の描画は自動的に高DPIに対応できるし、アプリの改修が必要だけど高精細のビットマップも使える。たとえばDPIスケールが200%で描画領域の(96dpiでの)サイズが320×200なら、640×400のビットマップを用意してStretchBltなどで縮小コピーすればいい。
ビットマップのサイズを決めるには仮想化されていない本当のDPIを取得する必要があるが、プライマリモニターならGetDpiForWindow(GetDesktopWindow())すればいいし、プライマリ以外のモニターについてはEnumDisplayMonitorsのコールバックに渡されるhdcMonitorに対してWindowFromDCしてGetDpiForWindowで得られる。
WM_DPICHANGEDは受け取れないのでなんとかする(WM_DISPLAYCHANGE/WM_SIZING\WM_MOVINGで代用するとか描画のたびにGetDpiForWindowして変わっていたらビットマップを作り直すとか)。
スレッドを作成してSetThreadDpiAwarenessContextでスレッドをPer-monitor DPI awareに設定して、DPI取得専用のスレッドにするという手もある(WM_DPICHANGEDを受け取りたかったらこうするしかない)。
対応が面倒なら何もしなくても(ビットマップが荒いままになるだけで)とくに問題ない。Per-monitor DPI awareのアプリと違って、一気に全体を矛盾なく変更する必要がないしビットマップ以外は何もする必要がない。サードパーティー製のソースを持っていないDLLを読み込んでいるとか、改修が不可能な状況でも問題ない。というかmmcがまさにサードパーティー製のスナップインを使う可能性があるからこういう機能を追加したのだろう。なんで最初からこうしなかったってレベル。
> StretchBltなどで縮小コピーすればいい。
ちょっと訂正。CreateCompatibleDC/CreateCompatibleBitmapで作成したビットマップは、すでに内部的に指定サイズ*DPIスケールになっているみたい(GetObjectしてbmWidthBytesを見るとわかる)。だから縮小コピーするのはStretchDIBitsでDIBからコピーするところ。CreateDIBSectionで作成したビットマップは指定通りのサイズになるみたい。ビットマップへの直接アクセスが得られるから当たり前だけど。
より多くのコメントがこの議論にあるかもしれませんが、JavaScriptが有効ではない環境を使用している場合、クラシックなコメントシステム(D1)に設定を変更する必要があります。
犯人は巨人ファンでA型で眼鏡をかけている -- あるハッカー
DPIスケーリングの互換性オプション追加が最高 (スコア:2, 参考になる)
高DPI対応とは名ばかりのクソアプリとか高DPIでレイアウトがめちゃくちゃになってもまったく対応する気のないアプリとかを、ようやく高DPI環境でまともに使えるようになった。
ちなみにSystem (Enhanced)は新機能だけど、Systemに相当する設定("DPIunaware" shim)は従来から存在していた。ただ従来は標準でUIがなかったので、アプリのmanifestを無理やり書き換えるとかApplication Compatibility Toolkitをインストールするとかする必要があったし、表示がぼやけるのでそこまでする気にもあまりなれなかった。
(以下、デスクトップアプリの開発者向けの情報)
mmc.exeのmanifestによると、
のような宣言をすることで、ユーザーに互換性オプションを設定させなくてもSystem (Enhanced)を設定したのと同等の状態にできるらしい。
テキストやGDIでの幾何学図形の描画は自動的に高DPIに対応できるし、アプリの改修が必要だけど高精細のビットマップも使える。たとえばDPIスケールが200%で描画領域の(96dpiでの)サイズが320×200なら、640×400のビットマップを用意してStretchBltなどで縮小コピーすればいい。
ビットマップのサイズを決めるには仮想化されていない本当のDPIを取得する必要があるが、プライマリモニターならGetDpiForWindow(GetDesktopWindow())すればいいし、プライマリ以外のモニターについてはEnumDisplayMonitorsのコールバックに渡されるhdcMonitorに対してWindowFromDCしてGetDpiForWindowで得られる。
WM_DPICHANGEDは受け取れないのでなんとかする(WM_DISPLAYCHANGE/WM_SIZING\WM_MOVINGで代用するとか描画のたびにGetDpiForWindowして変わっていたらビットマップを作り直すとか)。
スレッドを作成してSetThreadDpiAwarenessContextでスレッドをPer-monitor DPI awareに設定して、DPI取得専用のスレッドにするという手もある(WM_DPICHANGEDを受け取りたかったらこうするしかない)。
対応が面倒なら何もしなくても(ビットマップが荒いままになるだけで)とくに問題ない。Per-monitor DPI awareのアプリと違って、一気に全体を矛盾なく変更する必要がないしビットマップ以外は何もする必要がない。サードパーティー製のソースを持っていないDLLを読み込んでいるとか、改修が不可能な状況でも問題ない。というかmmcがまさにサードパーティー製のスナップインを使う可能性があるからこういう機能を追加したのだろう。なんで最初からこうしなかったってレベル。
Re: (スコア:0)
> StretchBltなどで縮小コピーすればいい。
ちょっと訂正。CreateCompatibleDC/CreateCompatibleBitmapで作成したビットマップは、すでに内部的に指定サイズ*DPIスケールになっているみたい(GetObjectしてbmWidthBytesを見るとわかる)。だから縮小コピーするのはStretchDIBitsでDIBからコピーするところ。CreateDIBSectionで作成したビットマップは指定通りのサイズになるみたい。ビットマップへの直接アクセスが得られるから当たり前だけど。