Skip to content

Instantly share code, notes, and snippets.

@YSRKEN
Last active May 27, 2017 13:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save YSRKEN/0c804fb4633e27443d4a2776ac18483e to your computer and use it in GitHub Desktop.
Save YSRKEN/0c804fb4633e27443d4a2776ac18483e to your computer and use it in GitHub Desktop.
WPFアプリを高DPI対応にしよう! ref: http://qiita.com/YSRKEN/items/b8072f4816a88924605d
<DockPanel>
<DockPanel.LayoutTransform>
<ScaleTransform ScaleX="{Binding ScaleX}" ScaleY="{Binding ScaleY}"/>
</DockPanel.LayoutTransform>
<!-- ここにリサイズしたいオブジェクトを置く -->
</DockPanel>
// MonitorFromWindowが返したディスプレイの種類
public enum MonitorDefaultTo { Null, Primary, Nearest }
// GetDpiForMonitorが返したDPIの種類
enum MonitorDpiType { Effective, Angular, Raw, Default = Effective }
// NativeMethods
class NativeMethods {
// ウィンドウハンドルから、そのウィンドウが乗っているディスプレイハンドルを取得
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr MonitorFromWindow(IntPtr hwnd, MonitorDefaultTo dwFlags);
// ディスプレイハンドルからDPIを取得
[DllImport("SHCore.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
public static extern void GetDpiForMonitor(IntPtr hmonitor, MonitorDpiType dpiType, ref uint dpiX, ref uint dpiY);
}
// 現在のディスプレイにおけるDPIを取得する
Dpi GetDpi() {
// 当該ウィンドウののハンドルを取得する
var helper = new WindowInteropHelper(this);
var hwndSource = HwndSource.FromHwnd(helper.Handle);
// ウィンドウが乗っているディスプレイのハンドルを取得する
var hmonitor = NativeMethods.MonitorFromWindow(hwndSource.Handle, MonitorDefaultTo.Nearest);
// ディスプレイのDPIを取得する
uint dpiX = Dpi.Default.X;
uint dpiY = Dpi.Default.Y;
NativeMethods.GetDpiForMonitor(hmonitor, MonitorDpiType.Default, ref dpiX, ref dpiY);
return new Dpi(dpiX, dpiY);
}
// 初期化直後の処理
protected override void OnSourceInitialized(EventArgs e) {
base.OnSourceInitialized(e);
// 最初にDPIを取得する
ResizeWindowByDpi(GetDpi());
}
// DPI変更時に飛んでくるウィンドウメッセージ
enum WindowMessage { DpiChanged = 0x02E0 }
// フックするルーチン
protected override void OnSourceInitialized(EventArgs e) {
base.OnSourceInitialized(e);
// ウィンドウメッセージを取得する
var helper = new WindowInteropHelper(this);
var source = HwndSource.FromHwnd(helper.Handle);
source.AddHook(new HwndSourceHook(WndProc));
}
// ウィンドウプロシージャ
IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) {
if(msg == (int)WindowMessage.DpiChanged) {
// wParamの下位16bit・上位16bitがそれぞれX・Y方向のDPIを表している
var dpiX = (uint)wParam & 0xFFFF; //下位16bit
var dpiY = (uint)wParam >> 16; //上位16bit
ResizeWindowByDpi(new Dpi(dpiX, dpiY));
handled = true;
}
return IntPtr.Zero;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment