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

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

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

Re[4]: Graphicsを返すコード教えてください。。


(過去ログ 81 を表示中)

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

■47744 / inTopicNo.1)  Graphicsを返すコード教えてください。。
  
□投稿者/ lavender (1回)-(2010/03/12(Fri) 20:03:57)

分類:[VB.NET/VB2005 以降] 

初めて投稿させて頂きます。初心者です。
意味不明な言葉がありましたら申し訳ありません、ご容赦願います。。。

現在仕事でVB5.0をvb2008の移行作業をしており、5.0のプログラムそこら中にobjectでLineやらStringが描画されています。
そこでGraphicsをFunctionで返してあげれば、その場で描画出来ると安易に考えていたのですが...。
今現在のコードが下の状態です。

Public oj as Object 'ojがPictureBoxの場合とPrintDocmentがありえます。


Dim G as Graphics = AutoGra(oj)←問題のファンクションです。
G.Draw〜

Public Function AutoGra(ByVal oj As Object) As Graphics
If TypeOf oj Is PictureBox Then
Dim Pic As PictureBox = oj
If Pic.Image Is Nothing Then oj.Image = New Bitmap(Pic.Width, Pic.Height)
Return Graphics.FromImage(Pic.Image)
ElseIf TypeOf oj Is Printing.PrintDocument Then
Return ←@
End If
End Function

@の場所でPrintPageEventArgsのe.Graphicsを返したいのですが中々うまく出来ません。
そもそもこんなやり方ではダメなのでしょうか?
ojがPictureBoxの場合は問題ありません。
教えて頂けたら嬉しいです、宜しくお願いいたします。
引用返信 編集キー/
■47752 / inTopicNo.2)  Re[1]: Graphicsを返すコード教えてください。。
□投稿者/ やじゅ (1549回)-(2010/03/13(Sat) 00:46:29)
やじゅ さんの Web サイト
No47744 (lavender さん) に返信
> @の場所でPrintPageEventArgsのe.Graphicsを返したいのですが中々うまく出来ません。
> そもそもこんなやり方ではダメなのでしょうか?

発想を逆転するしかないんじゃない。
イベントでPrintPageEventArgsのe.Graphicsを取得した上で、
描画処理(G.Draw側)を外だしして、e.Graphicsを引数なりして渡す。

新しい印刷モデルの利用方法
http://www.fumikichan.net/prog/VB/se060301.jsp
引用返信 編集キー/
■47806 / inTopicNo.3)  Re[2]: Graphicsを返すコード教えてください。。
□投稿者/ lavender (2回)-(2010/03/15(Mon) 17:49:53)
No47752 (やじゅ さん) に返信
やじゅさん、返信ありがとうございます。

> イベントでPrintPageEventArgsのe.Graphicsを取得した上で、
> 描画処理(G.Draw側)を外だしして、e.Graphicsを引数なりして渡す。

そうですよね、結局PrintPageEventArgsが発生しないとe.Graphicsは取得できないんですもんね。。。
引数を返すのは100近くあるFormの1000以上あるSubに、その必要性を判断することは不可能に近いので、
いったんojを全てPictureBoxとして扱います。必要であればそのImageを出力することでエラーを回避します。
ありがとうございました!

ちなみに、このObjectがFormだった場合、FormをImage化することは可能ですか??
お手数ですが宜しくお願いします。
引用返信 編集キー/
■47810 / inTopicNo.4)  Re[1]: Graphicsを返すコード教えてください。。
□投稿者/ Jitta on the way (578回)-(2010/03/15(Mon) 20:23:36)
No47744 (lavender さん) に返信
> 初めて投稿させて頂きます。初心者です。
> 意味不明な言葉がありましたら申し訳ありません、ご容赦願います。。。
>
> 現在仕事でVB5.0をvb2008の移行作業をしており、5.0のプログラムそこら中にobjectでLineやらStringが描画されています。

さっそく意味不明です。「VB5のプログラムでは、そこら中でobjectにLineやらStringやらが描画されています」?こうだとしても、どこに描画しているのでしょう?



> そこでGraphicsをFunctionで返してあげれば、その場で描画出来ると安易に考えていたのですが...。
> 今現在のコードが下の状態です。
>
> Public oj as Object 'ojがPictureBoxの場合とPrintDocmentがありえます。
>
>
> Dim G as Graphics = AutoGra(oj)←問題のファンクションです。

問題はこのファンクションではなく、このファンクションを呼び出しているものは何か、だと思います。


> G.Draw〜
>
> Public Function AutoGra(ByVal oj As Object) As Graphics
> If TypeOf oj Is PictureBox Then
> Dim Pic As PictureBox = oj
> If Pic.Image Is Nothing Then oj.Image = New Bitmap(Pic.Width, Pic.Height)
> Return Graphics.FromImage(Pic.Image)
> ElseIf TypeOf oj Is Printing.PrintDocument Then
> Return ←@
> End If
> End Function
>
> @の場所でPrintPageEventArgsのe.Graphicsを返したいのですが中々うまく出来ません。

なぜ、急に「e.Graphics」が出てくるのでしょう?やはり、呼び出しもとが問題だと思います。


> そもそもこんなやり方ではダメなのでしょうか?
> ojがPictureBoxの場合は問題ありません。
> 教えて頂けたら嬉しいです、宜しくお願いいたします。
引用返信 編集キー/
■47811 / inTopicNo.5)  Re[2]: Graphicsを返すコード教えてください。。
□投稿者/ lavender (3回)-(2010/03/15(Mon) 20:47:43)
No47810 (Jitta on the way さん) に返信
Jitta on the way さん返信ありがとうございます。

> さっそく意味不明です。「VB5のプログラムでは、そこら中でobjectにLineやらStringやらが描画されています」?こうだとしても、どこに描画しているのでしょう?

説明不足ですみません、Objectは条件によってPictureBox、Form、Printerに描画するようになっています。


>> Public Function AutoGra(ByVal oj As Object) As Graphics
>> If TypeOf oj Is PictureBox Then
>> Dim Pic As PictureBox = oj
>> If Pic.Image Is Nothing Then oj.Image = New Bitmap(Pic.Width, Pic.Height)
>> Return Graphics.FromImage(Pic.Image)
>> ElseIf TypeOf oj Is Printing.PrintDocument Then
>> Return ←@
>> End If
>> End Function
>>
>>@の場所でPrintPageEventArgsのe.Graphicsを返したいのですが中々うまく出来ません。
>
> なぜ、急に「e.Graphics」が出てくるのでしょう?やはり、呼び出しもとが問題だと思います。

描画ルーチンが多岐に及び、その一つ一つを認識できていません。

Private Sub Make_Line(x as single,y as single)
oj.Line((x,y)-(x+10,y+10))
End Sub

↑こういった描画があちこちにあると言いたかったのです。
それを
Private Sub Make_Line(x as single,y as single)
 Dim G as Graphics
G.DrawLine(Pens.Black,x,y,x+10,y+10)
End Sub
に出来たらとっても楽ちんだな♪と安易に考えたのです。
でも今のObjectタイプが何か判断してからGraphicsをインスタンス化しないとダメですよね??
それをFunctionで書こうと思いました。

中々うまく伝えられなくて、説明できていないと思いますがどうぞ宜しくお願いします。。
引用返信 編集キー/
■47812 / inTopicNo.6)  Re[3]: Graphicsを返すコード教えてください。。
□投稿者/ Jitta on the way (579回)-(2010/03/15(Mon) 21:05:34)
No47811 (lavender さん) に返信

質問は、状況によって答えが変わります。質問するときは、「聞きたいこと」よりも、「今の状況」を伝えるようにすると、答えを早く得やすいです。


>
> Private Sub Make_Line(x as single,y as single)
> oj.Line((x,y)-(x+10,y+10))
> End Sub
>
> ↑こういった描画があちこちにあると言いたかったのです。

このコードでは、ojは、引数として渡していません。ということは、コードを順番に実行すると、どこかで設定していると思われます。ならば、設定しているところを適切に修正すれば良いのではないでしょうか。
しかしそれでは、オブジェクト指向としてのオブジェクトの在り方がくずれるかもしれません。それを正すのが目的でしょうか。
つまり、「VB5→VB9への移行」が主目的でしょうか。同時に「オブジェクトの再編成」もするのが目的でしょうか。
私は、まずは「VB2008で動くこと」を目的とし、その過程で「オブジェクトの関わり」や「処理の流れ」をメモし、今の処理のおかしなところがハッキリしてから、オブジェクトの再編成をする方が、結果的にコストが低いのではないかと思います。


> それを
> Private Sub Make_Line(x as single,y as single)
>  Dim G as Graphics
> G.DrawLine(Pens.Black,x,y,x+10,y+10)
> End Sub
> に出来たらとっても楽ちんだな♪と安易に考えたのです。
> でも今のObjectタイプが何か判断してからGraphicsをインスタンス化しないとダメですよね??

でも、呼び出しもとが渡せば、それで済むかもしれません。VB5であっても、描くことが出来ないオブジェクトに対して描くことは出来ないので、何処かでどうにかして、ojに描くことが出来るオブジェクトを設定しているはずです。


> それをFunctionで書こうと思いました。
>
> 中々うまく伝えられなくて、説明できていないと思いますがどうぞ宜しくお願いします。。

引用返信 編集キー/
■47864 / inTopicNo.7)  Re[4]: Graphicsを返すコード教えてください。。
□投稿者/ lavender (4回)-(2010/03/16(Tue) 20:01:32)
No47812 (Jitta on the way さん) に返信
Jitta on the wayさん返信ありがとうございます。

>>Private Sub Make_Line(x as single,y as single)
>> oj.Line((x,y)-(x+10,y+10))
>>End Sub
>>
>>↑こういった描画があちこちにあると言いたかったのです。
>
> このコードでは、ojは、引数として渡していません。ということは、コードを順番に実行すると、どこかで設定していると思われます。ならば、設定しているところを適切に修正すれば良いのではないでしょうか。

もちろん各Form内には以下の様なObject設定がされています。
Select Case 条件
Case 1
oj = Printer
Case 2
oj = Me
Case 3
oj = PictureBox1
Case 4
oj = PictureBox2
.
.
End Select
えと…ここを修正するのでしょうか??

> つまり、「VB5→VB9への移行」が主目的でしょうか。同時に「オブジェクトの再編成」もするのが目的でしょうか。
> 私は、まずは「VB2008で動くこと」を目的とし、その過程で「オブジェクトの関わり」や「処理の流れ」をメモし、今の処理のおかしなところがハッキリしてから、オブジェクトの再編成をする方が、結果的にコストが低いのではないかと思います。

おっしゃる通り、vb2008で動くことを目的にしています。とにかくデバッグして何とか動かしたいのです。

>>Private Sub Make_Line(x as single,y as single)
>> Dim G as Graphics
>> G.DrawLine(Pens.Black,x,y,x+10,y+10)
>>End Sub
>>に出来たらとっても楽ちんだな♪と安易に考えたのです。
>>でも今のObjectタイプが何か判断してからGraphicsをインスタンス化しないとダメですよね??
>
> でも、呼び出しもとが渡せば、それで済むかもしれません。VB5であっても、描くことが出来ないオブジェクトに対して描くことは出来ないので、何処かでどうにかして、ojに描くことが出来るオブジェクトを設定しているはずです。
>

呼び出し元をひとつひとつ追いかけていくことが至難の業です。PrivateSubだけでも一つのFormに100はあります。
順を追ってPaintEventを渡すことが不可能に近いのです。
そういう意味ではないでしょうか?わたし勘違いしていますか?? レベルが追い付いていなくて本当にすみません。。。
引用返信 編集キー/
■47868 / inTopicNo.8)  Re[5]: Graphicsを返すコード教えてください。。
□投稿者/ Jitta on the way (582回)-(2010/03/16(Tue) 20:42:56)
No47864 (lavender さん) に返信
>>このコードでは、ojは、引数として渡していません。ということは、コードを順番に実行すると、どこかで設定していると思われます。ならば、設定しているところを適切に修正すれば良いのではないでしょうか。
>
> もちろん各Form内には以下の様なObject設定がされています。
> Select Case 条件
> Case 1
> oj = Printer
> Case 2
> oj = Me
> Case 3
> oj = PictureBox1
> Case 4
> oj = PictureBox2
> .
> .
> End Select
> えと…ここを修正するのでしょうか??

この、現在のコードと、「VB9(VB2008)で動くことが先決」が、“説明すべき状況”です。
今、ojは、Objectと宣言されているのですね?これを“Graphics”に変更すると、このSwitch〜Case文の様なところはエラーになると思います。すると、設定しているところがわかります。これら、設定しているところで、適切なGraphicsオブジェクトを渡してはどうでしょうか。



> 呼び出し元をひとつひとつ追いかけていくことが至難の業です。PrivateSubだけでも一つのFormに100はあります。
> 順を追ってPaintEventを渡すことが不可能に近いのです。
> そういう意味ではないでしょうか?わたし勘違いしていますか?? レベルが追い付いていなくて本当にすみません。。。

レベルが追いついていないのではなく、切羽詰まって視野が狭くなっているのだと思います。
上記の様に、「コンパイルエラーになる状況」にしてやれば、探すことなくあぶり出せます。同じように、ソリューションから「oj =」を検索するという方法もあると思います。
描画するところがひとつで、いろいろな「描画可能なもの」に描画するなら、描画するところで判別するのもひとつかもしれません。しかし、PictureBoxやPrinter(の詳しい型はわかりませんがおそらく)に共通性はなく、無い情報を作り出すことは出来ません。作り出すことは出来ないから、わかるところが教えてあげるしかないと思います。
引用返信 編集キー/
■47872 / inTopicNo.9)  Re[3]: Graphicsを返すコード教えてください。。
□投稿者/ 魔界の仮面弁士 (1559回)-(2010/03/16(Tue) 22:04:34)
2010/03/16(Tue) 22:19:47 編集(投稿者)

No47811 (lavender さん) に返信
> Private Sub Make_Line(x as single,y as single)
> oj.Line((x,y)-(x+10,y+10))
> End Sub

それだと文法エラーになるはずなので、実際は
 oj.Line (x, y)-(x + 10, y + 10)
ですよね? (VB6 の描画系メソッドは構文が特殊なので)

どうしても、括弧を付けて Line メソッドを呼び出したいなら、
 With oj
  Call .Line(0, x, y, x + 10, y + 10, 0)
 End With
のように、With ブロックで囲むか、CallByName を使う必要があるはず…。


> に出来たらとっても楽ちんだな♪と安易に考えたのです。
> でも今のObjectタイプが何か判断してからGraphicsをインスタンス化しないとダメですよね??
その方向性では駄目だと思いますよ。
呼び出される側だけではなく、呼び出し側にも手を加えてください。


まず VB6 の場合、PictureBox/Form に対する描画処理は「Paint イベント」に記述することになっています。
このパターンで実装されたものに関しては、VB.NET でも『処理の流れ』は大して変わらないはずです。
VB.NET の場合も同様に、Paint イベントを使えば OK です。

 'VB6
 Private Sub Picture1_Paint()
  Picture1.ScaleMode = vbPixels
  Picture1.Line (0, 0)-(1000, 1000), vbRed
  Picture1.CurrentX = 32
  Picture1.CurrentY = 8
  Picture1.Print "サンプル"
 End Sub

ただし、PictureBox/Form のメソッドを使って描画するのではなく、
イベント引数 e.Graphics が持つ描画メソッドを利用する事になります。

 Private Sub PictureBox1_Paint(ByVal sender As PictureBox, ByVal e As PaintEventArgs) Handles PictureBox1.Paint
  e.Graphics.DrawLine(Pens.Red, 0, 0, 1000, 1000)
  e.Graphics.DrawString("サンプル", sender.Font, Brushes.Black, 32, 8)
 End Sub


そのため、先の
> Private Sub Make_Line(x as single,y as single)
が利用していた『変数 oj』に対しては、
「PictureBox」等ではなく「Graphics」を渡すことになります。



問題は、Paint イベントを使っていなかった場合ですね。
この場合は処理の手順が異なるため、VB.NET では基本的に作り直しが必要になります。


それでも、できるだけ修正の手間を省こうとするのであれば―――


まず、「AutoRedraw プロパティ = True」で描画していた場合については、
  'VB6
  Set oj = Picture1
  Make_Line oj, x1, y1 '描画メソッド
  Make_Line oj, x2, y2 '描画メソッド
の代わりに、
  'VB.NET
  Dim bmp As Bitmap = TryCast(PictureBox1.Image, Bitmap)
  If bmp Is Nothing Then
   bmp = New Bitmap(PictureBox1.ClientSize.Width, PictureBox1.ClientSize.Height)
  End If
  Using g As Graphics = Graphics.FromImage(bmp)
   Make_Line_dotNET(g, x1, y1) '描画メソッド
   Make_Line_dotNET(g, x2, y2) '描画メソッド
  End Using
  PictureBox1.Image = bmp
となるように修正していけば良いと思います。

描画メソッド自体はリメイクになりますし、呼び出し側にも修正が必要ですが、
呼び出す場所(イベント)を変更する手間は省けます。


また、「Paint イベントは使わないし、AutoRedraw も False のまま」という場合は、
  Dim g As Graphics = PictureBox1.CreateGraphics()
で得た Graphics クラスに対して描画していくこともできます。



続いて「Printer オブジェクト」の場合。

これについては、VB6 互換の Printer オブジェクトを使うという選択肢があります。
http://msdn.microsoft.com/ja-jp/library/microsoft.visualbasic.powerpacks.printing.compatibility.vb6.printer.aspx


たとえば
 'VB6
 Option Explicit
 Private Sub Command1_Click()
  Printer.ScaleMode = vbPixels
  Printer.Line (0, 0)-(1000, 1000), vbRed
  Printer.CurrentX = 32
  Printer.CurrentY = 8
  Printer.Print "サンプル"
  Printer.EndDoc
 End Sub
というコードについては、VB2008 では
 '参照設定に「Microsoft.VisualBasic.PowerPacks.Vs.dll」を加えておくこと
 Imports Microsoft.VisualBasic.PowerPacks.Printing.Compatibility.VB6
 Partial Public Class Form1
  Private Sub Button1_Click() Handles Button1.Click
   Dim p As New Printer()
   p.ScaleMode = vbPixels
   p.Line(0, 0, 1000, 1000)
   p.CurrentX = 32
   p.CurrentX = 8
   p.Print("サンプル")
   p.EndDoc()
  End Sub
 End Class
のように記述できます。

VB6 とほとんど同じコードが使えるため、この点に関して移植に悩む事は無いでしょう。

ただしこのクラスでは、描画処理に Graphics クラスを利用していません。そのため、
先述の PictureBox 等への描画処理とは、メソッドの扱いが異なってしまうのが難点です。


もし、プリンタへの出力に対しても Graphics クラスを利用して描画したいのであれば、
No47752 で紹介された、PrintDocument クラスを使った処理方法を使う必要があります。
この場合は処理の流れが大きく変わるため、プログラム全体を見直す事になるかと。

 'VB2008
 Imports System.Drawing.Printing
 Partial Public Class Form1
  Private Sub Button1_Click() Handles Button1.Click
   PrintDocument1.Print()
  End Sub

  Private Sub PrintDocument1_PrintPage(ByVal sender As PrintDocument, ByVal e As PrintPageEventArgs) Handles PrintDocument1.PrintPage
   e.Graphics.DrawLine(Pens.Red, 0, 0, 1000, 1000)
   e.Graphics.DrawString("サンプル", Me.Font, Brushes.Black, 32, 8)
   e.HasMorePages = False
  End Sub
 End Class
引用返信 編集キー/
■47897 / inTopicNo.10)  Re[4]: Graphicsを返すコード教えてください。。
□投稿者/ lavender (5回)-(2010/03/17(Wed) 16:21:05)
No47872 (魔界の仮面弁士 さん) に返信
魔界の仮面弁士さん、丁寧なご返信ありがとうございます!

それだと文法エラーになるはずなので、実際は
>  oj.Line (x, y)-(x + 10, y + 10)
> ですよね? (VB6 の描画系メソッドは構文が特殊なので)
>
はい、ごめんなさい。2008で起動した時にVB5から2008へアップグレードが走って、それが自動で変えちゃったみたいです。

>>に出来たらとっても楽ちんだな♪と安易に考えたのです。
>>でも今のObjectタイプが何か判断してからGraphicsをインスタンス化しないとダメですよね??
> その方向性では駄目だと思いますよ。
> 呼び出される側だけではなく、呼び出し側にも手を加えてください。

あぅぅ…ダメですか…。

>
> まず VB6 の場合、PictureBox/Form に対する描画処理は「Paint イベント」に記述することになっています。
> このパターンで実装されたものに関しては、VB.NET でも『処理の流れ』は大して変わらないはずです。
> VB.NET の場合も同様に、Paint イベントを使えば OK です。

正しくはvb5で、Paintイベントは使用していません。

> また、「Paint イベントは使わないし、AutoRedraw も False のまま」という場合は、
>   Dim g As Graphics = PictureBox1.CreateGraphics()
> で得た Graphics クラスに対して描画していくこともできます。

AutoRedrawはFalseですから、そっか!
CreateGraphicsで問題ないですね!あ〜目からうろこが落ちました。

>
>
> 続いて「Printer オブジェクト」の場合。
>
> これについては、VB6 互換の Printer オブジェクトを使うという選択肢があります。
> http://msdn.microsoft.com/ja-jp/library/microsoft.visualbasic.powerpacks.printing.compatibility.vb6.printer.aspx
>

当初はこれを利用しようと思いましたが、PictureBoxの描画処理とかなり違ってきますし、
何よりこんぱちって互換のためだけに残されたオブジェクトですよね?いつかはなくなるんじゃないかと。。。
そう思ってやめました。

> もし、プリンタへの出力に対しても Graphics クラスを利用して描画したいのであれば、
> No47752 で紹介された、PrintDocument クラスを使った処理方法を使う必要があります。
> この場合は処理の流れが大きく変わるため、プログラム全体を見直す事になるかと。

ささっと書いてみました。動作未確認ですけど、
Public Class Form1
Dim PictureBox1 As New PictureBox
Dim oj As Object
Dim Cnt As Integer
Public Pic As PictureBox
WithEvents Btn As Button
WithEvents PrintDoc As Printing.PrintDocument

Private Sub PBtn_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles PBtn.Click
Cnt = IIf(Cnt >= 2, 0, Cnt + 1)
SetObject()
Make_Line(100, 100)
If Cnt = 0 then PrintDoc.Print
End Sub
Private Sub SetObject()
Select Case Cnt
Case 0
oj = PrintDoc
Case 1
oj = PictureBox1
Case 2
oj = Me
End Select
End Sub
Private Sub Make_Line(ByVal X As Integer, ByVal Y As Integer)
Dim G As Graphics = AutoG(oj)
G.DrawLine(Pens.Black, 0, 0, X, Y)
End Sub
Public Function AutoG(ByVal Oj As Object) As Graphics
If TypeOf Oj Is PictureBox Then
Pic = Oj
Pic.Size = Oj.size
If Pic.Image Is Nothing Then Pic.Image = New Bitmap(Pic.Width, Pic.Height)
ElseIf TypeOf Oj Is Form Then
Dim Frm As Form = Oj
Frm.BackgroundImage = New Bitmap(Frm.ClientRectangle.Width, Frm.ClientRectangle.Height)
Return Graphics.FromImage(Frm.BackgroundImage)
ElseIf TypeOf Oj Is Printing.PrintDocument Then
Pic = New PictureBox
Pic.Size = New Size(1169, 827) 'A4
Pic.Image = New Bitmap(Pic.Size.Width, Pic.Size.Height)
End If
Return Graphics.FromImage(Pic.Image)
End Function

Private Sub PD_PrintPage(ByVal sender As Object, ByVal e As Printing.PrintPageEventArgs) Handles PrintDoc.PrintPage
e.Graphics.DrawImage(Pic.Image, 0, 0)
End Sub
End Class

あ、でもこれだとImage出力するからかなり荒くなってしまう問題がある。。。
やっぱり無理か(>_<)
どうしてもこの方法が諦めきれなくて、作りましたが別の方法をクライアントと相談してみます。。。
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -