DOBON.NET DOBON.NETプログラミング掲示板過去ログ

複数のコントロール上をまたぐように画像や線を描画する方法

環境/言語:[VB2010+.NetFramework各種]
分類:[.NET]

当方、VB2010+.NetFramework各種、OSはXPにて開発を行っております。
いろいろと調べてみましたがどうしても自力では実現できそうにないので
皆様のお知恵をお貸し頂ければと想います。

やりたいのは、通常のFrom上にいくつかコントロール(RichTextBoxやPictureBox
ListBoxなど様々です)を配置した上で、それらの「上」に重ねるように
画像を表示したいのです。

旧VBにあったImageやLine、Shapeのように……と言えばおわかり頂けるでしょうか?
これがどうしても自力では解決できません。

条件としては
・他Controlの上に画像や線を描画したい
・複数のControlをまたぐ(Button1中央からButton2中央まで矢印をひく、など)
・画像のない部分は透過し、「下のControlが見える」ようにしたい
・リアルタイムで操作が入るので、「他FormをTopMost、Oqpacy=0で配置」という手段は使えない(フォーカスがそちらに移ってしまうため)
となります。

DirectXのような手段でデスクトップというか、画面上に直接描画でもできればよいのですが……
どうかよろしくお願いします。
■No30004に返信(宝玉さんの記事)

Label + Regionの例

        Label1.BackColor = Color.Black
        Label1.Text = ""
        Dim path = New GraphicsPath({New Point(0, 0), New Point(Label1.Width, Label1.Height),
                                     New Point(Label1.Width + 10, Label1.Height + 10), New Point(10, 10)},
                                   New Byte() {CByte(PathPointType.Start), CByte(PathPointType.Line),
                                       CByte(PathPointType.Line), CByte(PathPointType.Line)})
        path.FillMode = FillMode.Alternate
        Label1.Region = New Region(path)
2012/03/01(Thu) 10:32:19 編集(投稿者)

■No30004に返信(宝玉さんの記事)
> やりたいのは、通常のFrom上にいくつかコントロール(RichTextBoxやPictureBox
> ListBoxなど様々です)を配置した上で、それらの「上」に重ねるように
> 画像を表示したいのです。
> 旧VBにあったImageやLine、Shapeのように……と言えばおわかり頂けるでしょうか?

旧 VB の場合でいうと、RichTextBox/PictureBox/ListBoxは
フォーム上層に配置されるコントロールであり、それに対して
Image/Line/Shape などは、中層に配置されるものですよね。

だとしたら、「上(手前方向)」ではなく「下(奥側)」になってしまいますが…。


> ・リアルタイムで操作が入るので、「他FormをTopMost、Oqpacy=0で配置」という手段は使えない
Oqpacy は Opacity のことだと読み替えますが、それを 0.0 にしてしまうと
何も見えなくなってしまいます。TransparencyKey のことでしょうか?

TransparencyKey での透過は、モニタが32bitカラー設定だと、
うまくいかなかったりもしますけれどね。
http://support.microsoft.com/kb/822495


> (フォーカスがそちらに移ってしまうため)
マウス操作を透過させるだけなら、こんな感じで。

Public Class Form2
    Protected Overrides ReadOnly Property CreateParams As CreateParams
        Get
            Dim p As CreateParams = MyBase.CreateParams
            If Not MyBase.DesignMode Then
                Const WS_EX_NOACTIVATE As Integer = &H8000000
                Const WS_EX_TRANSPARENT As Integer = &H20
                p.ExStyle = p.ExStyle Or WS_EX_NOACTIVATE Or WS_EX_TRANSPARENT
            End If
            Return p
        End Get
    End Property
End Class

関連情報として、このあたりも。
http://homepage1.nifty.com/yasunari/VB/VB2005/ScreenKeyBoardMaking.htm


> DirectXのような手段でデスクトップというか、画面上に直接描画でもできればよいのですが……
GetDC(IntPtr.Zero) API で取得したデバイスコンテキストハンドルを使う事で、
画面上に直接描画することができます。(最後に ReleaseDC も必要です)

ただしこの場合、Graphics クラス経由で描画できるのは、
プライマリモニターのみという制限が入ります。

もし、それ以外のモニターに対しても描画したいのであれば、
描画処理も API を利用して処理することになります。
shu 様

ありがとうございます。
Regionを使えば上に描画することは可能なようですね。
「またぐ」ことが可能かどうか、という問題は残りますが。
ありがとうございました。 参考にさせて頂きます。


魔界の仮面弁士 様
そうですね、Opacityでした。こちらでは完全に透明になってしまいますね。
TransparentKeyですが、やはり他フォームが上に来てしまうのは考え物です。
しかしスクリーンキーボードは参考になりそうです。ありがとうございます。

GetDCで取得、APIで描画ということはBitBltでしょうか。
VB2010で使えるんですね……。
サンプルコードがないか、探してみます。





お二方、情報ありがとうございました。
ただ、現状でまだ解決しきれていないので(描画できても他の問題があったり
位置がずれたり)、引き続き情報を求めております。
何かあればご教授頂ければ幸いです。
■No30023に返信(宝玉さんの記事)
> Regionを使えば上に描画することは可能なようですね。
> 「またぐ」ことが可能かどうか、という問題は残りますが。
直接跨げなくとも、それぞれのコントロールに描画するという手はありますね。
独自描画を加えにくいコントロールの扱いが悩みどころですが。

> しかしスクリーンキーボードは参考になりそうです。ありがとうございます。
関連情報として。
http://msdn.microsoft.com/ja-jp/library/cc440905.aspx


> GetDCで取得、APIで描画ということはBitBltでしょうか。
それでいけると思います。(再描画の仕組みも必要かな…)

あるいは、Graphics.FromHdc を経由で DrawImage メソッドを
呼び出す手もあります。先述したようにプライマリスクリーン限定ですが。

> ただ、現状でまだ解決しきれていないので(描画できても他の問題があったり
> 位置がずれたり)、引き続き情報を求めております。
位置ずれなどはコーディングミスな気もするのですが、それを指摘するには、
具体的にどんなコードを書いているのかが提示されていないといけません。
なので現時点では、具体的な情報提供は無理かも…。

> 何かあればご教授頂ければ幸いです。
http://www.tt.rim.or.jp/~rudyard/torii009.html
■No30023に返信(宝玉さんの記事)
> shu 様
>
> ありがとうございます。
> Regionを使えば上に描画することは可能なようですね。
> 「またぐ」ことが可能かどうか、という問題は残りますが。
> ありがとうございました。 参考にさせて頂きます。

PictureBox1:(10,10,100,100)
RichTextBox1:(200,150,100,100)
Label1:(50,50,170,180)=> 最前面
※(Left, Top, Width, Height)
とかすれば跨げるんじゃないかな?
違ってますか?

DOBON.NET | プログラミング道 | プログラミング掲示板