- 題名: セカンダリモニタのhDCを取得したい
- 日時: 2006/03/23 9:41:41
- ID: 14985
- この記事の返信元:
- (なし)
- この記事への返信:
- [14986] Re[1]: セカンダリモニタのhDCを取得したい2006/03/23 10:36:18
- [14997] Re[1]: セカンダリモニタのhDCを取得したい2006/03/23 19:39:12
- ツリーを表示
渋木宏明(ひどり)様,ありがとうございます。
> 第二2引数の解説が無いけど、hMonitor でいいのかなあ?
やってみました。すこし長いですけれど,リスト載せます。
結論を先に書きますが,ダメでした。やはりプライマリモニタにのみ描画されます。しかもセカンダリモニタの大きさにクリップされて。
ちなみに,g.Clear(Color.Black)とするとちゃんとセカンダリモニタが真っ黒に
なるんです。
う〜ん。もしかして.NETのバグ?
Option Strict On
Imports System.Runtime.InteropServices
Public Class Form1
<DllImport("user32.dll")> _
Private Shared Function GetDC( _
ByVal hWnd As IntPtr) _
As IntPtr
End Function
<DllImport("user32.dll")> _
Private Shared Function ReleaseDC( _
ByVal hWnd As IntPtr, _
ByVal hDC As IntPtr) _
As Integer
End Function
<DllImport("user32.dll")> _
Private Shared Function UpdateWindow( _
ByVal hWnd As IntPtr) _
As Boolean
End Function
<DllImport("user32.dll")> _
Private Shared Function RedrawWindow( _
ByVal hWnd As IntPtr, _
ByVal lprcUpdate As IntPtr, _
ByVal hrgnUpdate As IntPtr, _
ByVal flags As RDW) _
As Boolean
End Function
'RedrawWindow() flags
Private Enum RDW As Integer
INVALIDATE = &H1
INTERNALPAINT = &H2
[ERASE] = &H4
VALIDATE = &H8
NOINTERNALPAINT = &H10
NOERASE = &H20
NOCHILDREN = &H40
ALLCHILDREN = &H80
UPDATENOW = &H100
ERASENOW = &H200
FRAME = &H400
NOFRAME = &H800
End Enum
<DllImport("gdi32.dll")> _
Private Shared Function CreateDC( _
ByVal pszDriver As String, _
ByVal pszDevice As String, _
ByVal pszOutput As String, _
ByVal pInitData As IntPtr) _
As IntPtr
End Function
<DllImport("user32.dll")> _
Shared Function EnumDisplayMonitors( _
ByVal hdc As IntPtr, _
ByVal lprcClip As IntPtr, _
ByVal lpfnEnum As MonitorEnumProc, _
ByRef dwData As IntPtr) _
As Boolean
End Function
Delegate Function MonitorEnumProc( _
ByVal hMonitor As IntPtr, _
ByVal hdcMonitor As IntPtr, _
ByVal lprcMonitor As IntPtr, _
ByRef dwData As IntPtr) _
As Boolean
Dim WithEvents Timer As New Timer
Dim MonitorList As New List(Of IntPtr)
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
EnumDisplayMonitors(Nothing, Nothing, AddressOf EnumMonitors, IntPtr.Zero)
Me.Timer.Interval = 10
Me.Timer.Enabled = True
End Sub
Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
Me.Timer.Enabled = False
Me.RefreshDesktop()
End Sub
Private Function EnumMonitors(ByVal hMonitor As IntPtr, ByVal hdcMonitor As IntPtr, ByVal lprcMonitor As IntPtr, ByRef dwData As IntPtr) As Boolean
Me.MonitorList.Add(hMonitor)
Return True
End Function
Private Sub Timer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer.Tick
Select Case Control.MouseButtons
Case Windows.Forms.MouseButtons.Left
Dim hDC As IntPtr = CreateDC(Screen.AllScreens(1).DeviceName, Nothing, Nothing, IntPtr.Zero)
Using g As Graphics = Graphics.FromHdc(hDC, Me.MonitorList(1))
g.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality
g.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
Dim p As Point = Control.MousePosition
Const r As Integer = 5
g.FillEllipse(Brushes.Red, p.X - r, p.Y - r, r * 2, r * 2)
End Using
ReleaseDC(IntPtr.Zero, hDC)
Case Windows.Forms.MouseButtons.Right
Me.RefreshDesktop()
End Select
End Sub
Private Sub RefreshDesktop()
RedrawWindow(IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, RDW.ALLCHILDREN Or RDW.UPDATENOW Or RDW.ERASE Or RDW.INVALIDATE Or RDW.INTERNALPAINT)
UpdateWindow(IntPtr.Zero)
End Sub
End Class
分類:[.NET]
2006/03/23(Thu) 09:42:22 編集(投稿者)
たびたび似たようなスレッドをたてて申し訳ありません。
GetDC(IntPtr.Zero)でプライマリモニタのデバイスコンテキストハンドルが取得できることはわかったのですが,マルチディスプレイ環境でセカンダリモニタのデバイスコンテキストハンドルが取得できません。
Dim hDC As IntPtr = CreateDC("\\.\DISPLAY2", "\\.\DISPLAY2", Nothing, IntPtr.Zero)
とすると例外も発生せずハンドルが取得できるのですが,実際に描画しようとするとプライマリモニタに描画されます。それもセカンダリモニタの大きさにクリッピングされてです。(つまりプライマリが1600*1200,セカンダリが1024*768ならプライマリの1024*768に描画される)
座標はx:1200,y:0を原点にすると何も描かれず,x:0,y:0を原点にすると前述のようにプライマリの一部に描画されます。
GetDC(IntPtr.Zero)でプライマリモニタに描画するのと同じようにセカンダリモニタに描画する方法をご存じの方がいらっしゃいましたらご教授ください。