Visual Basic 6.0 初級講座 |
第18回 2つ目のフォーム
いままでの解説はどれも最初から用意されているフォームの上にいろいろなコントロールを配置してプログラムするものでしたが、もちろん1つのプログラムには2つ以上のフォームがあっても構いません。
現に市販されているソフトのほとんどは2つ以上のフォームから構成されています。みなさんはInternet Explorerがいくつのフォームを使っているか知っていますか?
というわけで今回は2つ以上のフォームを使う方法を説明します。その過程で画像の色を反転するプログラムを作ります。
1.設計
具体的な話にはいる前に完成するプログラムの簡単な想像をします。まず、画像ファイルを選ぶとその画像がフォームに表示されるようにしましょう。そして、そのフォームにはボタンが付いていてボタンを押すともう一つのフォームが現れて今表示している画像を反転して表示するようにします。つまり、元の画像と反転した画像を横に並べて2つ同時に見れるようにするわけです。1つのフォーム上に2つPictureBox(ピクチャーボックス)を配置しても同様なことができそうですが、フォームを2つ使えばどちらかを最小化したりサイズを変えたりと言うことが容易にできます。
まぁ、元の画像と色を反転した画像を2つ並べてみるだけでは実用性はありませんが楽しんで作ることにしましょう。VBのレベルがあがれば反転以外にももっと複雑な画像処理ができるようになります。
2.1つ目のフォーム
フォームに画像を表示させるにはフォームのPictureプロパティを使います。次の例ではフォームにC:\Test.bmpという画像ファイルを表示させます。
Form1.Picture = LoadPicture("C:\Test.bmp")
しかし、ユーザが表示する画像を自由に選べるようにしたいですから少し工夫しましょう。この工夫については特別講義に解説がありますから参考にしてください。ここでは、解説は抜きにして完成した全コードだけを載せておきます。
Private Sub Command1_Click()
End Sub |
注:「特別講義1」では、4行目が Image1.Picture・・・ となっていますがここでは上記のように修正しました。
このコードを実行するにはコモンダイアログボックスを参照する必要があります。その手順は次の通りです。
@ メニューの[プロジェクト]から、[コンポーネント]を選択します。
A 一覧表が表示されるので Microsoft Common Dialog Control 6.0 を探してチェックします。(クリックしただけではチェックされません。左の四角をクリックしてください。)
B 「OK」をクリックします。そうすると、左のコントロールのアイコンの一番最後に新しいアイコンが追加されたでしょう。これがコモンダイアログのアイコンです。
Cふつうのコントロールと同じように、コモンダイアログを配置してください。場所は好きなところでいいです。
以上の手順を踏み、かつ上に掲げた6行のコードを打ち込み、さらにコマンドボタンを一つ配置していればプログラムは完成です。不安な人はこの時点で一度実行してみてください。コマンドボタンを押すとフォームに選んだ画像が表示されますね?
しかし、性能が悪いプログラムとなっています。一番の不満は、フォームの大きさが画像より小さいと全体が表示されない点です。そこで前にやったようにスクロールバーで画像全体が見られるようにしてもいいのですが今回はイメージ(Image)を使うことにします。
フォームにImageを一つ貼り付けてください。そして、フォームの大きさが変更されたらイメージの大きさも変更されるようにプログラムします。イメージの大きさは常にフォームの大きさと同じになるようにします。そのためのプログラムは次の通りです。
Private Sub Form_Resize()
End Sub |
Form_Resizeはフォームのサイズが変更されると自動的に呼び出されます。また、フォームがロードされた直後にも呼び出されます。Moveメソッドはコントロールの位置やサイズを1回で変更できる便利なメソッドです。引数は4つあって 左上の座標、右上の座標、横幅、たて幅 の順です。フォームの横幅とたて幅はそれぞれフォームのScaleWidthプロパティとScaleHeightプロパティで取得できます。
さて、選択された画像はフォームではなくこのイメージに表示されるようにします。それにはさっき打ち込んだ部分にちょっと手を加えるだけで済みます。以下では変更する部分を ピンク色にして示します。それ以外の場所は変更していませんから打ち直す必要はありません。
Private Sub Command1_Click()
End Sub |
これで、ImageのStretchプロパティをTrueにすれば作業完了です。実行してみてください。画像を読み込んでフォームのサイズを変えると、画像もフォームに従ってのびちぢみしますね。
ここまでの全コードと配置したコントロールを以下に示しておきます。
・配置したコントロール
1.CommonDialog1 (このコントロールを配置するためにはメニューの[プロジェクト]から、[コンポーネント]で Microsoft Common Dialog Control 6.0 をあらかじめ追加しておく必要がある。)
2.Command1
3.Image1 StretchプロパティをTrueにしておく
・全コード
Private Sub Command1_Click() CommonDialog1.Filter = "画像ファイル|*.bmp;*.gif;*.jpg;*.jpeg"
CommonDialog1.ShowOpen
Image1.Picture = LoadPicture ( CommonDialog1.FileName )
Form1.Caption = CommonDialog1.FileName
End Sub
Private Sub Form_Resize()
Image1.Move 0 , 0 , Form1.ScaleWidth , Form1.ScaleHeight
End Sub
3.2つ目のフォーム
以上で1つ目のフォームの主要な部分は終わりです。これから今回の本番である2つ目のフォームの制作に取りかかります。
まず、フォームを追加する方法から説明しましょう。メニューの[プロジェクト]から、[フォームモジュールの追加]を選択します。一覧のような物が表示されるのでその中から「フォームモジュール」を選んで「開く」ボタンをクリックします。
これでプログラムに2つ目のフォームが追加されました。このように1つのプログラムにはいくらでもフォームを追加できます。これらのフォームは1つのプログラムで制御されているわけです。このようなあつまりを「プロジェクト」と呼びます。この言葉を使うと今の作業は「プロジェクトに新しいフォームを追加した」と表現されるわけです。
さて、プロジェクトエクスプローラを見るとちゃんとフォームが2つ表示されていますね。最初のフォームをデザインしたいときはプロジェクトエクスプローラのForm1をダブルクリックします。2つ目のフォームをデザインしたい場合にはForm2をダブルクリックします。
このようにフォームが増えてくるとプロジェクトエクスプローラの役割も増えてきますからこのフォームの切り替え方も覚えて置いてください。
では、この状態でもう1度プログラムを実行してみましょう。フォームを追加する前と何一つ変わっていないのが分かるでしょう。フォームは追加しただけでは表示されないのです。「フォームを表示しろ」という命令が必要なのです。
そこで、From1にもう一つCommandButton(コマンドボタン)を配置してそのボタンを押したら2つ目のフォームが表示されるようにプログラムしてみましょう。
そのコードは次のようになります。
Private Sub Command2_Click()
End Sub |
これでこのボタンを押すと2つ目のフォームが表示されます。
ところで、我々は色を反転させた画像を表示させるために2つ目のフォームを用意したのですからその準備をしましょう。
2つ目のフォームにもイメージを一つ配置してください。そしてやはり2つ目のフォームのリサイズイベントに次のように記述します。(これはフォーム1とほとんど同じコードですね)。
Private Sub Form_Resize()
End Sub |
ImageのStretchプロパティをTrueにするのも忘れないでください。
これで準備が整いました。次はいよいよ画像の反転に挑戦です。
4.画像の色を反転して転送
1つ目のフォームの2つ目のコマンドボタンに先ほど次のようにプログラムしましたね。
Private Sub Command2_Click()
End Sub |
これはForm2を表示させるための処理だったわけですが今度はここにコードを追加します。ただ表示させるだけではなく、Form2のImageに色を反転させた画像を表示させるようにプログラムするわけです。
方法と手順は次の通りです。
1.Form1のImage1に表示されている画像をForm2のPicture1に送る(このとき反転して送るように命令する)。
2.Form2のPicture1は送られてきた画像をForm2のImage1に送る。
つまり、Form1のImage1 → Form2のPicture1 → Form2のImage1 という順に画像を送ります。
なんでわざわざ2回送るのかというと、まず、PictureBox(ピクチャーボックス)では画像のサイズ変更が簡単にできないのでフォームのサイズを変更すると画像のサイズも変わるというプログラムがやりにくいと言う点が挙げられます。それならば最初にForm1のImage1から直接Form2のImage1に画像を送ればいいじゃないかと思われるかも知れませんが、実はImageからImageに画像を送るときは画像を反転させて送ることができないのです。そこで画像を反転して受け取れるPicture1を間に挟んでいるというわけです。
という訳でForm2に画像転送用のピクチャーボックスを1つ配置してください。見えているとかっこわるいのでVisibleプロパティはFalseにしておきます。しかしながら、画像を受け取る必要があるのでAutoRedrawプロパティはTrueにしておいてください。
では、具体的に以上の方法を実現していきます。
転送を始める前にForm2のPicture1のサイズをあらかじめ画像のサイズと同じにしておく必要があります。そのためのコードは次の通りです。
Form2.Picture1.Move 0, 0, Image1.Picture.Width, Image1.Picture.Height |
頭に Form2. がついているのは「Form2の」と言う意味です。何もついていなければ「Form1の」という意味になります。これはこのコードをForm1に記述するからです。このことからたとえば Image1.Picture.Widthは「Form1のImage1の画像(Pictureプロパティ)の横幅」という意味になります。
サイズが調節できたら転送します。そのコードは次の通りです。
Form2.Picture1.PaintPicture Image1.Picture, 0, 0, Image1.Picture.Width, Image1.Picture.Height, , , , , vbNotSrcCopy |
長ったらしいコードですが、これが画像を反転させるからくりです。PaintPictureメソッドを使って画像を転送すれば簡単な画像処理を行うことができるのです。このPaintPictureメソッドは引数が多いので簡単に説明しておきましょう。
まず、Form2.Picture1.PaintPictureとなっている点に留意してください。つまり、「Form2のPicture1に画像を描け」という命令なのです。以下に引数でどの画像をどんな風に描くのかを指定るわけです。
第1引数は「どの画像を?」の部分です。ここではImage1のPictureを指定してます。第2引数から第5引数までは画像の部分を指定します。ここでの設定によっては1部分だけ描画するように指示することもできますがここでは全体を描画させたいので画像全体を指すように指定しています。具体的な引数の意味は順に、左上のx座標、左上のy座標、横幅、たて幅です。
第6引数から第9引数は指定した領域内(この場合はForm2.Picture1)のどこに描画するかを指定します。ここでは省略しているので、コピー元と同じ部分に描画されます。
第10引数では「どんな風に」描画するのかを指定できます。ここでの指定はVBの組み込み定数で行います。vbNotSrcCopyは「反転」を表します。この他にどんな指示があるかを一番下で表にまとめておきます。
少し話が横にそれましたが、最後はForm2のPicture1からForm2のImage1に画像を転送して終わりです。ここの転送は単純な転送なのでプロパティの受け渡しだけで事足ります。そのコードは次のようになります。
Form2.Image1.Picture = Form2.Picture1.Image |
右辺がPicture1のImageプロパティになっているのが気になるかも知れません。これはいずれ説明することになると思いますが簡単にいっておくとPaintPictureメソッドで画像を受け取った場合、その画像はPictureプロパティではなくImageプロパティに格納されるのです。そしてImageプロパティが予想通りに動作するためにあらかじめAutoRedrawプロパティをTrueにしておく必要があるのです。ためしにPicture1のAutoRedrawプロパティをFalseにして試してみてください。
以上で完成です。全コードと配置したコントロールを示しておきます。
・配置したコントロール
<Form1>
1.CommonDialog1 (このコントロールを配置するためにはメニューの[プロジェクト]から、[コンポーネント]で Microsoft Common Dialog Control 6.0 をあらかじめ追加しておく必要がある。)
2.Command1
3.Image1 StretchプロパティをTrueにしておく
4.Command2
<Form2>
1.Image1 StretchプロパティをTrueにしておく
2.Picture1 VisibleプロパティをFalse、AutoRedrawプロパティをTrueにしておく
・全コード
<Form1>
Private Sub Command1_Click() CommonDialog1.Filter = "画像ファイル|*.bmp;*.gif;*.jpg;*.jpeg"
CommonDialog1.ShowOpen
Image1.Picture = LoadPicture ( CommonDialog1.FileName )
Form1.Caption = CommonDialog1.FileName
End Sub
Private Sub Command2_Click()
Form2.Show
Form2.Picture1.Move 0, 0, Image1.Picture.Width, Image1.Picture.Height
Form2.Picture1.PaintPicture Image1.Picture, 0, 0, Image1.Picture.Width, Image1.Picture.Height, , , , , vbNotSrcCopy
Form2.Image1.Picture = Form2.Picture1.Image
End Sub
Private Sub Form_Resize()
Image1.Move 0 , 0 , Form1.ScaleWidth , Form1.ScaleHeight
End Sub
<Form2>
Private Sub Form_Resize() Image1.Move 0 , 0 , Form2.ScaleWidth , Form2.ScaleHeight
End Sub
5.まとめ
今回のテーマは「フォームを追加」することだったのですが画像を反転して転送する方が大変だったのでテーマが不明瞭になってしまいました。そこで少しこの点をまとめておきます。
・フォームを追加するにはメニューの[プロジェクト]から、[フォームモジュールの追加]を選択して、「フォームモジュール」を選ぶ。
・追加したフォームはプロジェクトエクスプローラに表示される。
・フォームを切り替えたいときはプロジェクトエクスプローラをダブルクリックする。
・フォームを表示するにはShowメソッドを使う。
例 Form2.Show
・別のフォームにあるコントロールを呼び出すときは頭にフォーム名をつける。
例 Form2.Image1.Visble = True
だいたいこんなところでしょう。
この他に重要なことを若干あげておきます。
・フォームを表示したくなくなったらHideメソッドで隠せる。
例 Form2.Hide
・Hideメソッドは一時的に隠すだけである。フォームをメモリ上から消去するにはUnloadステートメントを使用する。
例 Unload Form2
まだまだあるのですが続きはもっと高度なことをやるときに説明しましょう。それでは失礼します。
6.付録 PaintPictureメソッドの第10引数
定数名 |
意味 |
論理的な式 |
&H42 | 物理パレットのインデックス 0 に対応する色 (デフォルトは黒) で、コピー先の長方形を塗りつぶします。 | dest = BLACK |
vbDstInvert | コピー先長方形の色を反転します。 | dest = (NOT dest) |
vbMergeCopy | コピー元の色と、コピー先の色を、論理 AND 演算子で結合します。 | dest = (source AND pattern) |
vbMergePaint | コピー元の色を反転した色と、コピー先の色を、論理 OR 演算子で結合します。 | dest = (NOT source) OR dest |
vbNotSrcCopy | コピー元の色を反転して、コピー先にコピーします。 | dest = (NOT source) |
vbNotSrcErase | コピー元の色と、コピー先の色を、論理 OR 演算子で結合し、さらに反転します。 | dest = (NOT src) AND (NOT dest) |
vbPatCopy | 指定したパターンをコピー先にコピーします。 | dest = pattern |
vbPatInvert | 指定したパターンの色と、コピー先の色を、論理 XOR 演算子で結合します。 | dest = pattern XOR dest |
vbPatPaint | 指定したパターンの色と、コピー元の色を反転した色を、論理 OR 演算子で結合し、さらにその結果を、コピー先の色と論理 OR 演算子で結合します。 | dest = DPSnoo |
vbSrcAnd | コピー元の色と、コピー先の色を、論理 AND 演算子で結合します。 | dest = source AND dest |
vbSrcCopy | コピー元をコピー先にそのままコピーします。 | dest = source |
vbSrcErase | コピー先の色を反転した色と、コピー元の色を、論理 AND 演算子で結合します。 | dest = source AND (NOT dest ) |
vbSrcInvert | コピー元の色と、コピー先の色を、論理 XOR 演算子で結合します。 | dest = source XOR dest |
vbSrcPaint | コピー元の色と、コピー先の色を、論理 OR 演算子で結合します。 | dest = source OR dest |
&HFF0062 | 物理パレットのインデックス 1 に対応する色 (デフォルトは白) で、コピー先の長方形を塗りつぶします。 | dest = WHITE |
定数名の列にはVBのヘルプに記載されていない定数も載せておきました。
この表は、MSDN、オブジェクトブラウザ、Wingdi.hに記載されている内容を適当に写した物です。