DOBON.NETプログラミング道掲示板
(現在 過去ログ2 を表示中)

[ 最新記事及び返信フォームをトピックトップへ ]

■33691 / inTopicNo.1)  ディスプレイの認識番号を求めたい
  
□投稿者/ 東風 一般人(1回)-(2017/10/10(Tue) 13:00:32)
  • アイコン環境/言語:[VB.NET] 
    分類:[.NET] 

    初めて投稿させて頂きます

    VB.net/ VS2015 / Windows10 / NET Framework4.0 の環境で、ディスプレイ単位に画面イメージを取得して、bmpファイルに格納するプログラムを作成しています
    ネットの情報を参考に、System.Windows.Forms.Screen.AllScreensを使用して、ループの先頭から1台づつ画面イメージを取得し、取得した順にディスプレイ番号を付けたbmpファイルを作成したのですが、Windowsのディスプレイ認識番号とbmpファイルに付けた番号が一致しない場合がありました。

    そこで、Screen.AllScreensで取得できる座標などから、ディスプレイの認識番号を求めようと考えましたが、方法が見つかりませんでした。
    Screen.AllScreensで得られる情報か、別の方法でもかまいませんが、ディスプレイの認識番号を求める方法はありませんか?

    Dim s As System.Windows.Forms.Screen
    Dim DP_No As Integer
    DP_No = 0 'ディスプレイ番号初期化

    '接続されたすべてのディスプレイから、ディスプレイ単位にbmpファイルを出力する
    For Each s In System.Windows.Forms.Screen.AllScreens
    DP_No = DP_No + 1 'ディスプレイ番号更新

    'Bitmapの作成(ディスプレイサイズの領域を生成)
    Dim bmpd As New Bitmap(s.Bounds.Width, s.Bounds.Height)
    Dim g As Graphics = Graphics.FromImage(bmpd)

    '画面全体をコピーする
    g.CopyFromScreen(New Point(s.Bounds.X, s.Bounds.Y), New Point(0, 0), bmpd.Size)
    g.Dispose()

    'bmpイメージファイル出力(ファイル名にディスプレイ番号を付加する)
    bmpd.Save(IMGFILD & "\Disply_No" & DP_No & ".bmp", Imaging.ImageFormat.Bmp)
    bmpd.Dispose()
    Next

    Screen.AllScreensで取得した場合、画面イメージはWindowsの識別番号順に1番から取得できると思っていたのですが、3台接続時にDisply_No2.bmpとDisplay_No3の画面イメージが入れ替わっていました。メインディスプレイは1に設定しています。2と3のケーブルを差し替えて再起動しても状況は変わりませんでした。
    プログラムのバグか、Screen.AllScreensでは機能的に実現できないとか、何かヒントでも良いので、分かることがあればお願いします。

引用返信 削除キー/
■33692 / inTopicNo.2)  Re[1]: ディスプレイの認識番号を求めたい
□投稿者/ 魔界の仮面弁士 大御所(1086回)-(2017/10/10(Tue) 13:52:31)
  • アイコンNo33691に返信(東風さんの記事)
    > Windowsのディスプレイ認識番号とbmpファイルに付けた番号が一致しない場合がありました。
    不意に変わってしまうこともありますしね。
    https://answers.microsoft.com/ja-jp/windows/forum/windows_vista-desktop/*/0042a7dc-f710-4b12-97a4-1db6915f52c7

    メーカー製のドライバーですら、OS 上の識別番号とはずれる事があるようなので、
    なかなか根が深そうな問題です。
    https://oshiete.goo.ne.jp/qa/5952461.html


    > そこで、Screen.AllScreensで取得できる座標などから、
    そういえば、Screen.DeviceName プロパティもずれるでしょうか?
    ちなみにこの値は、GetMonitorInfo API を通じて、
    MONITORINFOEX.szDevice から得られる値に等しいです。

    なお、AllScreens は、内部的には EnumDisplayMonitors API を
    全引数 NULL 指定で呼び出して、MonitorEnumProc デリゲートを
    コールバックさせて拾う実装になっています。

    あるいはこれらのかわりに EnumDisplayDevices API を使って、
    DISPLAY_DEVICE 配列を得るのはどうでしょう。
    デバイス名を EnumDisplaySettings(Ex) に渡せば、解像度情報も得られるはず。
引用返信 削除キー/
■33693 / inTopicNo.3)  Re[2]: ディスプレイの認識番号を求めたい
□投稿者/ 東風 一般人(2回)-(2017/10/10(Tue) 16:55:33)
  • アイコンNo33692に返信(魔界の仮面弁士さんの記事)
    魔界の仮面弁士さん、回答ありがとうございます

    > 不意に変わってしまうこともありますしね
    ディスプレイ2台構成の状態で、もう1台ディスプレイを追加すると、追加したディスプレイが1番になってしまいました
    ディスプレイの性能差があるため、Windowsが最初に見つけたディスプレイを1番にしているのだと思います
    どのような順序でも、画面イメージを取り込むときに、Windowsの認識番号順に取り込めるのなら良いのですが、2番、3番の画面イメージが入れ替わってしまいます

    > そういえば、Screen.DeviceName プロパティもずれるでしょうか?
    Screen.DeviceNameは未確認ですが、座標などの情報は取得できているので問題ないと思います
    ディスプレイドライバの画面を見ると、デバイス名と認識番号はWindows側と一致しています
    Screen.AllScreensで取得できるデバイス名から、Windows側の認識番号が分かるのではと思いました

    > あるいはこれらのかわりに EnumDisplayDevices API を使って
    Screen.AllScreensを使わずに、EnumDisplayDevices API を使用するということでしょうか、APIの使い方を調べて試してみます
    DISPLAY_DEVICE 配列をScreen.AllScreensで取得したデバイス名で検索し、一致した順番を認識番号にしても良いかもしれません
    いろいろ試してみます、結果はこの掲示板でお知らせします

引用返信 削除キー/
■33695 / inTopicNo.4)  Re[3]: ディスプレイの認識番号を求めたい
□投稿者/ 東風 一般人(3回)-(2017/10/13(Fri) 13:58:51)
  • アイコン遅くなりましたが、教えていただいた情報をもとに、調べてみました

    > そういえば、Screen.DeviceName プロパティもずれるでしょうか?
    2台構成になりますが、Screen.AllSelect で取得した情報を表示すると以下の通りでした
    メインディスプレイは1番に設定しています

     デバイス名 "DISPLAY1" に対し座標は2の画面
     デバイス名 "DISPLAY2" に対し座標は1の画面

    PCをシャットダウンし、ケーブル差し替えると、デバイス名と座標が一致します
    ディスプレイの性能差やケーブルの接続順によっては、デバイス名と座標が一致しないのは、Screen.AllScreensの問題なんですかね

    デバイス名がWindowsの認識番号順に並んでいるのであれば、デバイス名から座標と解像度が得られると良いのですが、EnumDisplaySettings(Ex)だと、解像度しか得られないようです

    > なお、AllScreens は、内部的には EnumDisplayMonitors API を
    EnumDisplayMonitors APIを自分で呼び出せば、正しい座標が得られるか未確認ですが、他の方法がないか調査中です。

    最悪はディスプレイの認識順にケーブルを差し替えるとか、bmpファイルに保存した画像イメージに合わせてディスプレイに番号シールを貼る事も考えていますが、環境によっては再起動で番号が変わる可能性もあり、最大10台まで接続しようと思っているので難しいです
    できる事ならWindowの認識番号でbmpファイルを作成したいです

引用返信 削除キー/
■33698 / inTopicNo.5)  Re[4]: ディスプレイの認識番号を求めたい
□投稿者/ 魔界の仮面弁士 大御所(1088回)-(2017/10/16(Mon) 10:25:10)
  • アイコンNo33695に返信(東風さんの記事)
    >>そういえば、Screen.DeviceName プロパティもずれるでしょうか?
    > 2台構成になりますが、Screen.AllSelect で取得した情報を表示すると以下の通りでした
    Screen.AllSelect というのは
    Screen.AllScreens のことでしょうか。

    > メインディスプレイは1番に設定しています
    >  デバイス名 "DISPLAY1" に対し座標は2の画面
    >  デバイス名 "DISPLAY2" に対し座標は1の画面
    「2の画面」の「2」というのは、Screen から得た情報なのではなく、
    別の方法(たとえば画面のプロパティ)から得た情報だったりはしませんか?


    > デバイス名と座標が一致しないのは、Screen.AllScreensの問題なんですかね
    再起動等を行ったわけでも無いのに、実行するたびに
    DeviceName と GetBounds/GetWorkingArea の組み合わせが
    変わってしまうということですか?


    >>なお、AllScreens は、内部的には EnumDisplayMonitors API を
    > EnumDisplayMonitors APIを自分で呼び出せば、正しい座標が得られるか未確認ですが、他の方法がないか調査中です。

    別の方法(EnumDisplayDevices)は既に提示しませんでしたっけ。
    https://stackoverflow.com/questions/27042576/enumdisplaydevices-vs-enumdisplaymonitors
引用返信 削除キー/
■33700 / inTopicNo.6)  Re[5]: ディスプレイの認識番号を求めたい
□投稿者/ 魔界の仮面弁士 大御所(1089回)-(2017/10/16(Mon) 16:17:06)
  • アイコンNo33698に返信(魔界の仮面弁士さんの記事)
    > 別の方法(EnumDisplayDevices)は既に提示しませんでしたっけ。

    先に提示した方法を使った、3 種類の比較コードを書いてみました。

    下記を Windows Form に貼って起動すると、
    ListBoxとButton が 3 つずつ貼られた画面が表示されます。
    http://www.vb-user.net/junk/replySamples/2017.10.16.16.09/EnumDisplayDevices.txt
引用返信 削除キー/
■33705 / inTopicNo.7)  Re[6]: ディスプレイの認識番号を求めたい
□投稿者/ 東風 一般人(4回)-(2017/10/17(Tue) 17:28:12)
  • アイコン
    魔界の仮面弁士さん、お世話になります
    
    > Screen.AllScreens のことでしょうか。
    失礼しました、Screen.AllScreens です
    
    > 「2の画面」の「2」というのは、Screen から得た情報なのではなく、
    > 別の方法(たとえば画面のプロパティ)から得た情報だったりはしませんか?
    ディスプレイは2台ですが、左側に1番、右側に2番を配置しています
      [画面1][画面2]
    
    メインディスプレイは1番に設定しています
    この場合、1番の座標が X=0  Y=0 、2番の座標は X=1920 Y=0 になると思いますが
    Screen.AllScreens で取得した座標は、1番と2番が入れ替わっていました
    
    > 再起動等を行ったわけでも無いのに、実行するたびに
    > DeviceName と GetBounds/GetWorkingArea の組み合わせが
    > 変わってしまうということですか?
    プログラムを実行するたびに、位置関係が変わることはありません
    PCを止めて、ディスプレイケーブルを接続する位置を替えると、
    画面に表示される識別番号が変わってきますが、接続する順番次第では、
    それぞれ正しい座標で認識されます
    
    > 先に提示した方法を使った、3 種類の比較コードを書いてみました
    お手数おかけしました、ありがとうございます
    さっそく実行してみたところ、3種類の結果は、すべて同じ座標になりました
    どの方法でも、X,Y の座標が入れ替わっていました
    
    Screen.AllScreens 
     #0 DISPLAY1 X=1920 Y=0   W=1920 H=1080
     #1 SISPLAY2 X=0    Y=0   W=1920 H=1080
    
    EnumDisplayMonitors 
     #0 DISPLAY1 X=1920 Y=0   W=1920 H=1080
     #1 SISPLAY2 X=0    Y=0   W=1920 H=1080
    
    EnumDisplayDevices + EnumDisplaySettings
     #0 DISPLAY1 X=1920 Y=0   W=1920 H=1080
     #1 SISPLAY2 X=0    Y=0   W=1920 H=1080
    
    サイズを縮小しても、スクリーンショットが貼りつけられませんでした
    [画面1][画面2] の順で並び、メインディスプレイは1に設定しています
    
    

引用返信 削除キー/
■33711 / inTopicNo.8)  Re[7]: ディスプレイの認識番号を求めたい
□投稿者/ 東風 一般人(5回)-(2017/10/18(Wed) 13:14:25)
  • アイコンネットの情報を参考に、レジストリも確認してみました
    「HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\GraphicsDrivers\Configuration 」の
    「Position.cx 」、「 Position.cy」に位置情報が入っているということでしたが
    Configuration配下には数行の記載があり、ディスプレイ2台分の情報が保存されている箇所を確認すると
     [0] : X=1920 、Y=0
    [1] : X=0 、Y=0
    となっていたので、3種類の方法で取得した値は、レジストリに書かれている情報と一致していました

    実際に画面に表示されるディスプレイの識別番号を、どこから取得してるか不明ですが、
    レジストリレベルで違うのであれば、改修せずにプログラムが認識した番号に合わせて、
    ディスプレイに番号シールを貼ろうかと考え始めました

引用返信 削除キー/
■33719 / inTopicNo.9)  Re[8]: ディスプレイの認識番号を求めたい
□投稿者/ 東風 一般人(6回)-(2017/10/23(Mon) 13:33:08)
  • アイコンとりあえず、ディスプレイに番号シールでも貼る方法で対処し、後日、画面に表示される識別番号の取得方法を調べようと思います。
    解決には時間がかかりそうなので、この問題は、一旦、解決済みとさせていただきます。
    何か分かりましたら、ご報告します。
    魔界の仮面弁士さん、ご指導ありがとうございました。

    P.S
    レジストリには3台構成時の情報も残っていました
    新規にディスプレイを接続した際に、Windowsが認識する順番でレジストリが作成され、ケーブルなどを差し替えても順番は変わらないのではと思います。
    APIがレジストリから情報を取得しているのであれば、並び順だけでは識別番号を取得できない事になります。
    時間ができたらレジストリを手動で削除して、動作確認してみようと思います。

解決み!
引用返信 削除キー/



トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

Mode/  Pass/


- Child Tree -