質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

2回答

6901閲覧

ディスプレイの最高解像度または、ディスプレイのスケーリングを取得したい

cancat

総合スコア313

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

1クリップ

投稿2017/09/14 02:52

こんにちは。
Windows10でC#のアプリケーションを開発しています。
Visual Studio 2017 Communityを使っています。

###前提・実現したいこと
ディスプレイの最高解像度または、ディスプレイのスケーリング(IsScalingかMaxWidth)を取得する方法を知りたいです。

###該当のソースコード

C#

1private System.Windows.Forms.Screen[] Screens = System.Windows.Forms.Screen.AllScreens;

###試したこと
Screen.Boundsにいろいろ値は入っているのですが、それはWidth=3840、Height=2160のような「現在表示している解像度」です。
スケーリングで150%にしていると、このディスプレイの場合取得できる値はWidth=2560、Height=1440となります。

###発生している問題・エラーメッセージ
これだと、3840/2560で計算すると、1.5(150%)を取得できますが、3840という値は知っているから知っているだけで、ほんとうにそうであるかどうかはわかりません。

たとえばWidth=2560、Height=1440のディスプレイと、スケーリングで150%にした4K(Width=3840、Height=2160)ディスプレイをつないでいる場合、2560という値を見ただけではそのディスプレイが4Kのディスプレイなのか、2.5Kのディスプレイなのかは区別できません。

なので、ディスプレイの最高解像度または、ディスプレイのスケーリング(IsScalingかMaxWidth)を取得する方法を知りたいです。

###補足情報(言語/FW/ツール等のバージョンなど)
Microsoft Visual Studio Community 2017
Version 15.0.26228.9 D15RTWSVC
Microsoft .NET Framework
Version 4.6.01586

です。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

Windows10では高DPI対応の一環で、過去の高DPI非対応アプリのレイアウトを崩さずに表示させるための「アプリ内では96dpiとみなしてそれでうまく表示されるようにスケーリングする」モードが追加されています。これにより、高解像度ディスプレイなどでテキストサイズを125%(120dpi)以上にしていると、アプリによっては引き延ばされた残念な表示になってしまうことがあります。

作成したアプリ(exeファイル)のショートカットをどこかに作って、そのプロパティを開いて「互換性」タブにある「高いDPIスケールの動作を上書きします」にチェックを入れてみてください。前述のモードを無効化できます。それで実行するとちょっと様子が変わると思います(表示が小さくなってレイアウトが崩れます)。ただ、画面解像度は正しく取得できるはずです。

残念ながら、C#で普通にフォームアプリを作ると、既定では高DPI非対応アプリになってしまいます。おそらく互換性のためにそうしているのだと思いますが、当然のことながら高DPI対応のアプリも作成可能です。
以下、高DPI対応にするための手順です。

  1. app.manifestファイルの追加

プロジェクトに新しい項目の追加で「全般」の中にある「アプリケーション マニフェスト ファイル」を選択すると自動で作成されます。

  1. app.manifestファイルを編集し、高DPI対応部分のコメントを外す

xml

1 <!-- アプリケーションが DPI 対応であり、それ以上の DPI で Windows によって自動的にスケーリングされないことを 2 示します。Windows Presentation Foundation (WPF) アプリケーションは自動的に DPI に対応し、オプトインする必要は 3 ありません。さらに、この設定にオプトインする .NET Framework 4.6 を対象とする Windows Forms アプリケーションは、 4 app.config ファイルで 'EnableWindowsFormsHighDpiAutoResizing' 設定を 'true' に設定する必要があります。--> 5 <!-- 6 <application xmlns="urn:schemas-microsoft-com:asm.v3"> 7 <windowsSettings> 8 <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware> 9 </windowsSettings> 10 </application> 11 --> 12```作成されたファイルには上記のような記述がありますので、コメントを外して<application>タグを有効化します。 13 14これで高DPI対応アプリになり、実際の画面解像度が取得できるようになります。 15※app.configファイルもいじるようなことがコメントに書かれていますが、とりあえず情報取得についてはいじらなくても問題ありません。

投稿2017/09/14 11:18

catsforepaw

総合スコア5938

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cancat

2017/09/14 11:33

コメントありがとうございます。 じつはその方法で、すでにapp.manifest(とapp.config)を変更してみましたが、その場合でも、ディスプレイが複数あり二つ目のみをスケーリングしている場合には、ふたつめのディスプレイの解像度は取得できない模様です。
catsforepaw

2017/09/14 12:50

マルチディスプレイ環境でしたか。その旨書いておいてほしかったのですが……。 私のところではディスプレイが1個しかないので試せないのですが、<dpiAware>タグの`true`を`per monitor`に変更すればマルチディスプレイ対応になるそうです。
cancat

2017/09/14 13:36

すみません。連続して別の質問をしていて、それでできなかったので、別の方法を考えてそれがこちらの質問でした。独立した質問になるようにすべきでした。
hmmm

2017/09/14 14:53

@cancat dpiAwareをTrue/PMにした?
cancat

2017/09/18 13:11

app.manifestを追加し、true/PMにしてもダメでした。
catsforepaw

2017/09/19 04:01

これ以外の方法は私は思いつきません。もし差し障りがなければ、試してみたapp.manifestの内容を貼り付けてもらえないでしょうか。記述ミスなどあるのかもしれませんし。
cancat

2017/09/19 07:26

ほぼ空のapp.manifestを新規に作成してTrue/PMとしただけです。夜に貼りますね。
cancat

2017/09/19 22:57

遅くなりました。下記のとおりです。 <?xml version="1.0" encoding="utf-8"?> <assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/> <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> <security> <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"> <!-- UAC マニフェスト オプション Windows のユーザー アカウント制御のレベルを変更するには、 requestedExecutionLevel ノードを以下のいずれかで置換します。 <requestedExecutionLevel level="asInvoker" uiAccess="false" /> <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> <requestedExecutionLevel level="highestAvailable" uiAccess="false" /> requestedExecutionLevel 要素を指定すると、ファイルおよびレジストリの仮想化が無効にされます。 アプリケーションが下位互換性を保つためにこの仮想化を要求する場合、この要素を 削除します。 --> <requestedExecutionLevel level="asInvoker" uiAccess="false" /> </requestedPrivileges> </security> </trustInfo> <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> <application> <!-- このアプリケーションがテストされ、協働するようテストされた Windows バージョンの 一覧。適切な要素をコメント解除すると、最も互換性のある環境を Windows が 自動的に選択します。--> <!-- Windows Vista --> <!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />--> <!-- Windows 7 --> <!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />--> <!-- Windows 8 --> <!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />--> <!-- Windows 8.1 --> <!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />--> <!-- Windows 10 --> <!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />--> </application> </compatibility> <!-- アプリケーションが DPI 対応であり、それ以上の DPI で Windows によって自動的にスケーリングされないことを 示します。Windows Presentation Foundation (WPF) アプリケーションは自動的に DPI に対応し、オプトインする必要は ありません。さらに、この設定にオプトインする .NET Framework 4.6 を対象とする Windows Forms アプリケーションは、 app.config ファイルで 'EnableWindowsFormsHighDpiAutoResizing' 設定を 'true' に設定する必要があります。--> <application xmlns="urn:schemas-microsoft-com:asm.v3"> <windowsSettings> <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware> </windowsSettings> </application> <!-- Windows のコモン コントロールとダイアログのテーマを有効にします (Windows XP 以降) --> <!-- <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*" /> </dependentAssembly> </dependency> --> </assembly>
catsforepaw

2017/09/19 23:58

記述が間違っていますね。 <dpiAware>タグの設定は、私が最初のコメントで書いた「per monitor」です。「true/PM」ではありません。
catsforepaw

2017/09/20 00:14

すみません。念のため確認してみましたが、ちょっと認識が違っていました。「per monitor」「true/PM」どちらでも受け付けるようです。
catsforepaw

2017/09/20 00:21

となると、それでも本来の解像度が取得できないのは、ちょっとおかしいですね。どこに原因があるのかすぐには思いつきません。 とりあえず、今開発中のとは別にテスト用に解像度を取得するだけの単純なアプリを作って、それで試してみてください。うまくできたらそれを開発中のアプリに反映させるようにしてみてはどうでしょうか。
cancat

2017/09/20 01:03

ありがとうございます。 別のキャプチャープログラムでは、同様のtrue/PMでスケーリングしたディスプレイを含む複数のディスプレイの解像度に応じてキャプチャーできているので、どこか別のところに原因があるのだとは思います。 だいぶ試行錯誤してコードめちゃくちゃなので、すこし時間をおいてからとりかかってみます。 ありがとうございました。
guest

0

Win32APIを使ってはどうでしょうか?

C

1SetProcessDPIAware(); 2GetDeviceCaps(dc, HORZRES);

で、実際の解像度を取得できます。

投稿2017/09/14 05:15

koguma98

総合スコア288

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問