重要なお知らせ

「教えて! goo」は2025年9月17日(水)をもちまして、サービスを終了いたします。詳細はこちら>

【GOLF me!】初月無料お試し

お世話になります

PictureBoxを2枚使用して以下の様に現状はなっております。

PictureBox AAは背景となる画像を描画
AA->Image = bmpGazou;

PictureBox BBはAAのオーバーレイとして、文字や図形をGraphicsオブジェクトに描画したり編集したりしています。
主にg->FillEllipse等で円を描画しています
※文字や図形以外は透過

やりたいこと
保存用のBMPを作成して、そこにAAとBBを書き込んで、Jpeg保存したい

保存用BMPを定義して
Bitmap^ bmp = gcnew Bitmap(ixSize, iySize);
Graphics^ g = Graphics::FromImage(bmp);

そこにAAを書き込む
g->DrawImage(AA->Image,・・・

ここまでは正常にできたのですが、
BBのImageプロパティが未定義なので、g->DrawImageではBBを書き込めませんでした。
GraphicsオブジェクトをBMPに上書き(重ね書き)したいのですが、
どの様にすればよいのか教えていただけないでしょうか。

↓等も見てはいるのですが、前提条件のBBの使い方が違うので、やり方が判りませんでした。
http://dobon.net/vb/dotnet/graphics/pictureboxim …


※PCの画面上はAAの上にBBが表示され、背景のAA画像に文字や図形を重ねて描画できております。

A 回答 (2件)

あーと、自分の言いたかったことが伝わってないようですみません。

保存時に保存用 BMP を生成するという手順を変えろと言うつもりは全くありません。その手順にひと手間を追加してみたらどうかということです。

たとえば、
> 主にg->FillEllipse等で円を描画しています
というのであれば、その FillEllipse で使用したパラメータがあるはずです。
そのパラメータと、FillEllipse で描画したという事実を覚えておくということです。ここで保存用 BMP に描画はしませんし、そもそもこの時点では保存用 BMP は存在しないはずです。

そしていざ保存という時点で保存用 BMP を生成し AA をDrawImage したら、「そのパラメータと、FillEllipse で描画したという事実」を覚えていたので、続けて保存用 BMP に覚えていたパラメータで FillEllipse すれば、画面で見えている図と同じ絵の BMP ができるのではないか、というのが私の提案した代替手段です。

ええ、わかっています、描く円は一つだけじゃないし、そもそも描くのは円だけじゃないという事を。
ですから、複数回複数種類の描画を再現するには、
・何らかの描画を行ったという事を表す抽象クラスを作って、それを各描画方法ごとに派生させたクラスを作る。
・画像編集開始時に上記抽象クラスの List を生成する。
・何らかの画像編集を行うごとにそれに対応する派生クラスを生成し、上記 List に add する。
・画像保存時、保存用 BMP を生成し AA の画像を DrawImage した後で上記 List の順に行った描画を保存用 BMP に再現する。
ということを行えばできるはずです。
「これだけ変えたら現状の描画が変わるじゃないか」とお思いかもしれませんが、大丈夫です。最初のクラス追加は処理の流れには関係しませんし、2・3 番目は現行の処理を行っているメソッドに簡単な処理を追加するだけで、処理にかかる時間も「BB描画時にちらつき等」が出ることはまずないはずです。

確かに、目の前に描画した結果があるのに回りくどいことをしているように思うかもしれません。
しかし、上記の変更を行えば、現状では無理な画像編集の Undo/Redo もできるようになります。

この回答への補足

回答ありがとうございます。

実は、同時進行で、BMPへの直接描画も試みているのですが、
こちらはこちらで、別の問題が発生してしまい、
よろしければ、こちらの問題もアドバイスいただけますでしょうか。

【事象】
前記の質問の方法で作画した図形と以下の方法で作画した図形のスケールが異なってしまいます。
見た目で明らかに、下記方法の時の図形が、サイズ指定で大きくなるのではなく、
ズームしたように、荒く大きいので、Viewのサイズがおかしい様に見受けられます。

しかし、
AA,BBともに縦横(WidthとHeight)のサイズが同じで、ImageRectangleの縦横のサイズも同じ、
私の見逃しが無ければウォッチで比べたAA,BBの各クラスの値も同じだったんです。
※当然、アドレス系の値は異なっておりましたけど、直接数値の物とフラグ系は同じ値でした

※編集中は従来の方法で、編集終了時にバックグランドのイメージを入れ込んで、
そこに図形を上書きしております。

BB->Image = AA->Image;
Graphics^ g = Graphics::FromImage(BB->Image);
g->FillEllipse(gcnew SolidBrush(Color::White), posx, posy, d, d);


ちなみに
SizeModeはStretchImageにして、pictureboxのサイズも指定できるようにしております

補足日時:2014/06/25 09:38
    • good
    • 0
この回答へのお礼

たびたびスミマセン

その後、色々確認したところ、元々のGraphicsオブジェクトに描画した時の座標系は
PictureBoxのサイズが基準で、
今回の修正で変更した
Graphics^ gCorePrint = Graphics::FromImage(AA->Image);
ですと、Imageで定義されているピクセルが座標系となっているように見えます

お礼日時:2014/06/25 14:24

自分も軽く MSDN を確認してみたのですがわかりませんでした。


ただ、代替手段として、
> PictureBox BBはAAのオーバーレイとして、文字や図形をGraphicsオブジェクトに描画したり編集したりしています。
のときに、どのような文字や図形をどの位置に描画したかを覚えておいて、
> そこにAAを書き込む
> g->DrawImage(AA->Image,・・・
のあとでその g に上記で覚えておいた描画情報にしたがって描画する、というのであなたの希望通りの処理は可能と思います。

この回答への補足

回答ありがとうございます

私も最初は
g->DrawImage(AA->Image,・・・
の後に
g->DrawImage(BB->Image,・・・
と記載すれば良いと考えていたのですが。

PictureBox BBのImageプロパティには何も書き込んでいない為、
※書き込んでいるは、Graphicsオブジェクトに対しての書き込み

このため、実行すると
「'System,ArgumentNullException'のハンドルされていない例外がSystem,Drawing.dllで発生しました」
となってしまいます。

AA,BBのプロパティを確認すると
AAはImageが構造体となり、Bmpへのアドレスを始め各種情報が定義されていますが
BBは<未定義の値>となっております。
そりゃそうですよね、BBは元々オーバーレイとして、常に書き捨て前提で、
Graphicsオブジェクトのエリアにしか描画していないのですから。

つまり
BB->Graphicsに対して書き込んだ物を
保存用BMPに対して
AA->Image同様に書き込みたいんです。

BB描画時にちらつき等を気にしない仕様なら、BBの描画をImageプロパティに書けばよいのは判っているのですが、
できれば、現状の描画のまま解決策を見出したいと考えております

補足日時:2014/06/24 09:55
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!