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

PictureBox上に移動可能な枠を描きたい

環境/言語:[OS : Windows XP / 言語 : C# / .NET Framework : 3.5]
分類:[.NET]

【解決したい問題】

PictureBoxのPaintイベントでBitmapをDrawImageしています。その上にハンドル(マウスでつかむことの出来る小さな正方形)が四隅に付いた四辺形を描きたいのです。この四辺形は印刷領域を表すので、現在選択されている用紙のサイズや向きに応じます。また、マウスでハンドルをつかんでドラッグすることでPictureBox上を移動させますが、この時、描かれているBitmapが書き換わっては困ります。このBitmapを描く処理自体は少し重たくて1秒近くかかるため、四辺形を動かすたびに画面全体を書き換えることはしたくありません。

VB6時代にShapeを使って同じようなことをやったので、今回もRectangleShapeを使ってみましたが、マウスでつかんだときにRectangleShapeが選択状態になってしまって不自然でした。

そこで、この選択状態を解除する方法、または、RectangleShapeを使わない別の方法を探しています。

【解決するために何をしたか】

ControlPaintのFillReversibleRectangleとDrawReversibleFrameを使うことも考えたのですが、印刷領域枠がPictureBoxをはみ出したときのクリップ処理が難しそうで試していません。

よろしくお願いします。
■No28602に返信(ロートルさんの記事)

> PictureBoxのPaintイベントでBitmapをDrawImageしています。
これは1つのImageだけなのでしょうか?もし複数なのであればPictureBoxの
Graphicsに直接描画せず1枚のBitmapに描画するようにしてそれをPictureBoxの
Graphics上にDrawImageすることにより再描画にかかる時間を短縮できるのではないでしょうか?そのまま1イメージをDrawImageしているのであれば無理ですが。
■No28602に返信(ロートルさんの記事)
本題から外れて話を展開してしまいますが、

描画結果を Image に保存しておけば、Bitmapを描く処理の1秒は削れると思います。
http://dobon.net/vb/dotnet/graphics/pictureboximageanddrawimage.html
敢えて印刷領域の四辺形のみ Graphics で描くとか。
shuさん、コメントありがとうございます。

300×300ピクセルのBMPファイルを1セルとして、そのセルが縦横に数百枚並んだ巨大Bitmapがありまして、その一部を切り取ってPictureBoxに描画する仕様になっています。PictureBoxを窓としてそこから巨大Bitmapの一部を覗いているイメージです。余談ですが、そのPictureBoxは巨大Bitmap内を自由に動き回れないといけないのでこの部分の高速化も課題です。マウスで画面をつかんでスクロールさせようとしましたが、速度的に非実用的でした。ご指摘の方法も検討してみます。
るしぇさん、コメントありがとうございます。

> 描画結果を Image に保存しておけば、Bitmapを描く処理の1秒は削れると思います。
お二人から同じ方法のアドバイスがありましたので検討してみます。

> 敢えて印刷領域の四辺形のみ Graphics で描くとか。
印刷領域枠はマウスでつかんで動かしたいのでマウスイベントが拾えるShapeが簡単かなと思いました。実際にやってみるとコンテナやZオーダーを正しく指定しているにもかかわらずShapeがPictureBoxの下に隠れてしまう時があって頭を抱えています。背景を透過にしたLabelだとPictureBoxの下になることがないみたいなのでこいつを使ってみようかなと考えています。
■28607に返信(ロートルさんの記事)
> マウスで画面をつかんでスクロールさせようとしましたが、
> 速度的に非実用的でした。
たとえば下記は、TextureBrush を用いることで、数千ドット級の巨大画像を
高速にスクロールできていますが、このような対処はできないでしょうか。
http://dobon.net/vb/bbs/log3-39/23844.html


■No28608に返信(ロートルさんの記事)
> 印刷領域枠はマウスでつかんで動かしたいので

印刷領域枠を Form で表現してみるとか。枠線幅が邪魔かな…。


private Control draggableBox;
private void button1_Click(object sender, EventArgs e)
{
    Form f = new Form()
    {
        FormBorderStyle = FormBorderStyle.Sizable,
        BackgroundImageLayout = ImageLayout.Stretch,
        ControlBox = false,
        MinimizeBox = false,
        MaximizeBox = false,
        MinimumSize = new Size(1, 1),
        Size = new Size(100, 100),
    };
    f.BackgroundImage = bmp;
    f.TopLevel = false;
    pictureBox1.Controls.Add(draggableBox = f);
    f.Visible = true;
}
魔界の仮面弁士さん、コメントありがとうございます。

> たとえば下記は、TextureBrush を用いることで、数千ドット級の巨大画像を
> 高速にスクロールできていますが、このような対処はできないでしょうか。
> http://dobon.net/vb/bbs/log3-39/23844.html
この記事は参考にさせていただきました。DrawImageが想像以上に遅かったので考えてみようと思っています。

> 印刷領域枠を Form で表現してみるとか。枠線幅が邪魔かな…。
簡単にテストしてみましたが、背景を透明にしたFormをPictureBoxにのっけることができました。実は、この枠の中にLineをひきたかったのでLabelよりもこちらの方が適してるようです。目から鱗でした。

ということで、ひとまず解決です。コメントいただいた皆様、ありがとうございました。
解決済み!

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