C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

仮想ディスプレイの座標を取得する方法 [1]

[トピック内 30 記事 (21 - 30 表示)]  << 0 | 1 >>

■98732 / inTopicNo.21)  Re[18]: 仮想ディスプレイの座標を取得する方法
  
□投稿者/ くま (83回)-(2021/12/18(Sat) 22:20:32)
次々違う質問をされると回答できませんよ。
> Clipboard.SetImage(PictureBox1.Image)
> だと、PictureBox1_Paint上に書いたラインなどが描画されません、
ラインの描写先が間違っていませんか?

        Dim objPen = New Pen(System.Drawing.Color.Blue, 2)
        Dim objFont = New Font("MS Pゴシック", 15)
        Dim objGrp As Graphics = Graphics.FromImage(PictureBox1.Image) 'ここポイント

        ' 直線を引く
        objGrp.DrawLine(objPen, 20, 20, 200, 200)
        ' 楕円を描く
        objGrp.DrawEllipse(objPen, 10, 10, 190, 190)
        ' 楕円を描く
        objGrp.DrawString("描画テスト", objFont, Brushes.Red, 80, 100)

        ' リソースを解放する
        objPen.Dispose()
        objFont.Dispose()
        objGrp.Dispose()

        Clipboard.SetImage(PictureBox1.Image)

これで書かれた線などもクリップボードに読み込まれます。
というかそうしないとフォーム最小化とか重なった後書いた線消えてるでしょ?

フォーム全体なら
        'コントロールの外観を描画するBitmapの作成
        Dim bmp As New Bitmap(Me.Width, Me.Height)
        'キャプチャする
        Me.DrawToBitmap(bmp, New Rectangle(0, 0, Me.Width, Me.Height))

        Clipboard.SetImage(bmp)

        bmp.Dispose()

> あと、Chart1に関してもクリップボードにコピーしたいのですが、
> これにはImageがないのでコピーすることができません。

コントロールだけなら
フォームやコントロールの外観をキャプチャする
https://dobon.net/vb/dotnet/graphics/invokepaint.html

        <System.Runtime.InteropServices.DllImport("User32.dll")> _
        Private Shared Function PrintWindow(ByVal hwnd As IntPtr, _
            ByVal hDC As IntPtr, ByVal nFlags As Integer) As Boolean
        End Function
        
        ''' <summary>
        ''' コントロールのイメージを取得する
        ''' </summary>
        ''' <param name="ctrl">キャプチャするコントロール</param>
        ''' <returns>取得できたイメージ</returns>
        Public Function CaptureControl(ByVal ctrl As Control) As Bitmap
            Dim img As New Bitmap(ctrl.Width, ctrl.Height)
            Dim memg As Graphics = Graphics.FromImage(img)
            Dim dc As IntPtr = memg.GetHdc()
            PrintWindow(ctrl.Handle, dc, 0)
            memg.ReleaseHdc(dc)
            memg.Dispose()
            Return img
        End Function

        Dim bmp As Bitmap = CaptureControl(Chart1)
	Clipboard.SetImage(bmp)
        bmp.Dispose()

引用返信 編集キー/
■98736 / inTopicNo.22)  Re[19]: 仮想ディスプレイの座標を取得する方法
□投稿者/ KOZ (193回)-(2021/12/19(Sun) 04:55:47)
No98732 (くま さん) に返信

PictureBox は
(1) BackColor で塗りつぶし
(2) セットされていれば BackgroundImage を描画
(3) セットされていれば Image を描画
(4) Paint イベントで、PaintEventArgs.Graphics へ描画
の順に描画されます。

つまり、Image プロパティにセットされた画像 = PictureBox に描画される内容、ではないです。
餃子さんは (4) で描画してるんでしょうね。

DrawToBitmap は、WM_PRINT メッセージをコントロールに送って Bitmap に描画するので、
コントロールの実装によっては画面に描画されたものと異なっている場合があります。
(PictureBox の場合は問題ありません。)
また、コントロールの上に別のコントロールがあったり、ウインドウの外にはみ出していても問題なく描画されます。

PrintWindow は、WM_PRINT メッセージがコントロールに送られますので DrawToBitmap と同等の動作になります。

ちなみに CreateGraphics で Graphics オブジェクトを作って描画すると反映されません。

引用返信 編集キー/
■98744 / inTopicNo.23)  Re[20]: 仮想ディスプレイの座標を取得する方法
□投稿者/ 餃子 (9回)-(2021/12/19(Sun) 12:34:13)
ありがとうございます。

これらの中のいずれかの方法でうまくいくと思います。

ところで、
> DrawToBitmap は、
> コントロールの実装によっては画面に描画されたものと異なっている場合があります。
これってどういう場合に起こりえますでしょうか?
いまやっている感じだとうまくいっているように思えます。

BitBltで取得すると、タイトルバーやフォームの形状がWindows7のものになってしまうので、
こちらの方がレイアウトが崩れやすいのではないかという気がしました。



引用返信 編集キー/
■98745 / inTopicNo.24)  Re[21]: 仮想ディスプレイの座標を取得する方法
□投稿者/ KOZ (194回)-(2021/12/19(Sun) 13:44:15)
No98744 (餃子 さん) に返信
>>DrawToBitmap は、
>>コントロールの実装によっては画面に描画されたものと異なっている場合があります。
> これってどういう場合に起こりえますでしょうか?

WM_PAINT のみ処理して見た目を変更しているケースです。
引用返信 編集キー/
■98746 / inTopicNo.25)  Re[22]: 仮想ディスプレイの座標を取得する方法
□投稿者/ 餃子 (11回)-(2021/12/19(Sun) 14:03:36)
ありがとうございます。

WM_PAINTで問題が出るのは
DrawToBitmapとPrintWindowだけで、

BitBltを使った場合には、
WM_PAINTであってもうまく取得できるということで合っていますか?

引用返信 編集キー/
■98747 / inTopicNo.26)  Re[23]: 仮想ディスプレイの座標を取得する方法
□投稿者/ KOZ (195回)-(2021/12/19(Sun) 15:05:51)
No98746 (餃子 さん) に返信

PictureBox の話をしていたのに、いつの間にか Form の話になってる・・・

Form についてはまた事情が異なります。
トップレベルのウインドウは DWM(デスクトップウインドウマネージャ)が外観を変更しているんですね。
MDI の子ウインドウは DWM の影響をうけないので、Windows7 ぽい外観になりますが、これが本来の姿です。
DrawToBitmap/PrintWindow は本来の姿を描画しています。

GetWindowDC → BitBlt は現在表示されているものをそのまま転送します。
Form をキャプチャするならこれが最適でしょう。
引用返信 編集キー/
■98749 / inTopicNo.27)  Re[24]: 仮想ディスプレイの座標を取得する方法
□投稿者/ 餃子 (12回)-(2021/12/19(Sun) 17:50:21)
重ね重ねありがとうございます。

GetWindowDC → BitBlt の方も調べてみましたが、

https://dobon.net/vb/dotnet/graphics/screencapture.html

このページを参考に

Public Shared Function CaptureActiveWindow() As Bitmap
    'アクティブなウィンドウのデバイスコンテキストを取得
    Dim hWnd As IntPtr = GetForegroundWindow()
    Dim winDC As IntPtr = GetWindowDC(hWnd)
    'ウィンドウの大きさを取得
    Dim winRect As New RECT
    GetWindowRect(hWnd, winRect)
    'Bitmapの作成
    Dim bmp As New Bitmap(winRect.right - winRect.left, _
        winRect.bottom - winRect.top)
    'Graphicsの作成
    Dim g As Graphics = Graphics.FromImage(bmp)
    'Graphicsのデバイスコンテキストを取得
    Dim hDC As IntPtr = g.GetHdc()
    'Bitmapに画像をコピーする
    BitBlt(hDC, 0, 0, bmp.Width, bmp.Height, winDC, 0, 0, SRCCOPY)
    '解放
    g.ReleaseHdc(hDC)
    g.Dispose()
    ReleaseDC(hWnd, winDC)

    Return bmp
End Function

というコードを試してみたところ
うまく取得することができました。

ただ、タイトルバーが真っ黒になってしまい表示されません。

これは仕様上仕方ないことでしょうか?


引用返信 編集キー/
■98750 / inTopicNo.28)  Re[25]: 仮想ディスプレイの座標を取得する方法
□投稿者/ 餃子 (13回)-(2021/12/19(Sun) 18:07:30)
すいません、

Dim hWnd As IntPtr = GetForegroundWindow()

のところを、
Dim hWnd As IntPtr = Me.Handle
にして使用していたのですが、
これを
Dim hWnd As IntPtr = Form1.Handle
に書き換えるとタイトルバーまで取得できるようになりました。

しかし、Windowsの設定でウインドウの枠線を細くして表示しているのですが、
ウインドウの外側の背景まで映り込んでしまいます。
これは仕様上仕方ないでしょうか?

引用返信 編集キー/
■98751 / inTopicNo.29)  Re[25]: 仮想ディスプレイの座標を取得する方法
□投稿者/ KOZ (196回)-(2021/12/19(Sun) 18:23:42)
No98749 (餃子 さん) に返信

まったく別の話題になっているので、別の質問にしてください。
その際には 〜を参考に、ではなく、APIの宣言、定数の宣言などもきちんと書いてください。

引用返信 編集キー/
■98834 / inTopicNo.30)  Re[26]: 仮想ディスプレイの座標を取得する方法
□投稿者/ 餃子 (14回)-(2021/12/26(Sun) 15:18:37)
No98751 (KOZ さん) に返信
ありがとうございます。
また新規に質問させていただきます。

解決済み
引用返信 編集キー/

このトピックをツリーで一括表示

<前の20件
トピック内ページ移動 / << 0 | 1 >>

このトピックに書きこむ