2007年8月29日水曜日

伝票レイアウトセル(4) セル・ユーザーコントロール その2

セルに表示したいイメージのキャプチャーについて、というちゃんとやるなら深い話・・・。
なんだけど、そこまでのスキルも持っていないので今回利用した方法をってとこで。

まず目標としては、「ある状態のユーザーコントロールのキャプチャーを行って、それをセルに表示する」というところ。DataGridViewで提供されているセルでは全て自前で描写しているんだけど、今回はその手は使えない。
理由は簡単で、ユーザーコントロール上にどんなものが配置されるかもわからないから

なので単純にキャプチャしてしまいそれを表示しよう、という手段の方が楽だったってことなんだよねw
もちろん本当に単純にキャプチャできるわけはなかったんだけど。

今回使ったのはこんなやり方。
ユーザーコントロールのOnPainjtメソッドを利用してGraphicsクラスのインスタンスを取得する
これであればユーザーコントロール上に何を置かれても、原則はイメージを取得できる。DrawToBitmapメソッドのように特定コントロールで利用できないとかそういう問題はないしね。ただ、Graphicsを取得する際に気をつけないといけないのが一点だけある。

「Visible=TrueでなければGraphicsには描写されない」

という点。ただし、ここは勘違いしやすいポイントでもあるんだけど「目に見えている」必要はなく、ただ「VisibleプロパティがTrue」であるだけでGraphicsに描写はされるんだよね。ここに引っかからなければ解決も同然。イメージをキャプチャする際には、生成したユーザーコントロールを親フォームの可視領域外(マイナス座標とか)に配置してしまえばいいのだ。その時には、ダミーでフォーカスを移せるコントロールを一つ新たに作成し、そこにフォーカスを移した状態でキャプチャするとOK。そうでないとカーソルが残った状態がキャプチャされてしまう。テキストボックスとかでいいんじゃないかな?
それでは実際のロジックを。

Dim beforeControl As System.Windows.Forms.Control = Me.ActiveOwnerControl
'ダミーコントロールの追加
Dim dummyControl As New System.Windows.Forms.TextBox
With dummyControl
    .Name = "dummy"
    .Size = New System.Drawing.Size(0, 0)
End With
Me.Controls.Add(dummyControl)
dummyControl.Focus()
Me.Refresh()

'Graphicsを作成する
Dim targetControl As System.Windows.Forms.Control = Nothing
Dim targetGraphic As System.Drawing.Graphics = Nothing
targetControl = Me
targetGraphic = targetControl.CreateGraphics
Dim paintArgs As New System.Windows.Forms.PaintEventArgs(targetGraphic, targetControl.ClientRectangle)
Me.OnPaint(paintArgs)

'GraphicsオブジェクトよりBitmapオブジェクトのコピー
Using contGrap As System.Drawing.Graphics = targetGraphic
    Dim originalHdc As IntPtr = contGrap.GetHdc
    Using bmpGrap As System.Drawing.Graphics = System.Drawing.Graphics.FromImage(_controlImage)
        Dim targetHdc As IntPtr = bmpGrap.GetHdc
        MultiLayoutControl.BitBlt(targetHdc, 0, 0, targetControl.Width, targetControl.Height, _
                                  originalHdc, targetControl.Left, targetControl.Top, SRCCOPY)
        bmpGrap.ReleaseHdc(targetHdc)
    End Using
    contGrap.ReleaseHdc(originalHdc)
End Using
targetGraphic.Dispose()
targetControl = Nothing

If beforeControl IsNot Nothing Then beforeControl.Focus()
Me.Controls.Remove(dummyControl)

このソースは実際に利用しているものなので、独自に拡張した部分も混じってます。
ActiveOwnerControlは、ControlクラスにもActiveControlを追加したヤツです。実際のロジックはちょっと色々あるんだけど。MultiLayoutControlというのは、このユーザーコントロール自身のクラス名です。そして真ん中あたりのGraphicsからBitMapをコピーするのは、どこかのサイトでサンプルがあったので利用したんだけど・・・どこのサイトかが忘れてしまいました。

とりあえずはこの方法でキャプチャできたので、セル側ではこのイメージを描写してもらう事になりますな。
それはまた後で。

0 件のコメント:

コメントを投稿