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

OvalShape コントロールなどを動的に形を変更したい

環境/言語:[Windows 7/Vista MS2010 C# Winアプリ]
分類:[.NET]

お世話になります。

OvalShape コントロールで円を表示する時、この表示する大きさや円の形を動的に変更したり、また場所を移動したりすることはできますか?

 実は、画像ファイルの上で、ある場所に○印を打ったり長円にして大きさを示したりしたいのですがどのようにしたらできますか?
 出来ればサンプルなどご提示頂けるとありがたいのですが、よろしくお願いします。
お世話になります。

自己レスです。こんなサンプル見つけました。

http://www.codeproject.com/Articles/8765/C-Rect-Tracker

これを利用すれば何とかいけるかも?です。


ただ、試していますが、実はこれを画像の上にUserControlで作成したコントロールを載せて「ここが、ポイント!」などと言った使い方をしようとしていました。


こんな感じです!

http://msdn.microsoft.com/ja-jp/library/cc440904.aspx

ですが、透過しないため下の画像がすけません。幾つか参考にしましたが、どうもうまくいきません。

表題の内容とかけ離れますがこのまま、アドバイス頂けないでしょうか?

プログラムは、pictureBoxにJPG画像を表示して、四角か○のもう一つの画像または、コントロールに描画(DrawEllipseなどで)したものを上から合わせる。と言いったことです。
bmp.MakeTransparent(SystemColors.Control);も試したのですが・・
うまくいかなかったです。

よろしくお願いします。
※OvalShape コントロールは俺の環境では使用できないのでそれ以外の部分で。


>ですが、透過しないため下の画像がすけません。幾つか参考にしましたが、どうもうまくいきません。
>
「透過=下の画像が透ける」のではなく「親コントロールの背景を表示」みたいです。
あと、ユーザーコントロールに配置したコントロールのBackColorでTransparentをサポートしている必要がありそうです。例えばTextBoxはサポートしていないので透過されない。


ユーザーコントロールの透過に関しては
> http://msdn.microsoft.com/ja-jp/library/cc440904.aspx
>
のコードをC#に直せばできますよ。(コンストラクタ部分参照)


pictureboxはコンテナにはならないので、ユーザーコントロールが透過できてもやりたいことはできないと思います。(コードでユーザーコントロールのParentをpictureBoxに切り替えればできるみたいですが、後々不具合が発生した場合対処できる気がしない。)
panelの背景としてJpegを読み込んで、ユーザーコントロールをpanelの子コントロールと操作したほうがいい気がします。
お世話になります。
>
> ユーザーコントロールの透過に関しては
>>http://msdn.microsoft.com/ja-jp/library/cc440904.aspx
>>
> のコードをC#に直せばできますよ。(コンストラクタ部分参照)
>

一応試してみているんですけど、うまくいきません。

コードは、そんなに長くないので載せます(UserControlのみ)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Camera
{
public partial class UserControlCircle : UserControl
{
private Color m_GraphicsBackColor = Color.Red;

public UserControlCircle()
{
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);

base.BackColor = Color.Transparent;

InitializeComponent();
}

private void UserControlCircle_Load(object sender, EventArgs e)
{

}

protected override void OnPaint(PaintEventArgs pe)
{
Brush GraphicsBKBrush = default(Brush);

GraphicsBKBrush = new SolidBrush(m_GraphicsBackColor);

int iPenWidth = 2;

int iInsetWidth = iPenWidth / 2 + iPenWidth % 2;

Rectangle rc = new Rectangle(iInsetWidth, iInsetWidth, this.Width - iInsetWidth * 2, this.Height - iInsetWidth * 2);

Size size = new Size(this.Width / 5, this.Height / 5);

FillRoundedRectangle(pe.Graphics, new Pen(m_GraphicsBackColor, iPenWidth), new SolidBrush(m_GraphicsBackColor), rc, size);
}

private void FillRoundedRectangle(Graphics g, Pen pen, Brush backBrush, Rectangle rect, Size size)
{
System.Drawing.Drawing2D.SmoothingMode sm = default(System.Drawing.Drawing2D.SmoothingMode);
System.Drawing.Drawing2D.PixelOffsetMode pom = default(System.Drawing.Drawing2D.PixelOffsetMode);
System.Drawing.Drawing2D.GraphicsPath graphicPath = default(System.Drawing.Drawing2D.GraphicsPath);

sm = g.SmoothingMode;
pom = g.PixelOffsetMode;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;


graphicPath = new System.Drawing.Drawing2D.GraphicsPath();
graphicPath.FillMode = System.Drawing.Drawing2D.FillMode.Winding;
graphicPath.AddArc(rect.Right - size.Width, rect.Top, size.Width, size.Height, 270, 90);
graphicPath.AddArc(rect.Right - size.Width, rect.Bottom - size.Height, size.Width, size.Height, 0, 90);
graphicPath.AddArc(rect.Left, rect.Bottom - size.Height, size.Width, size.Height, 90, 90);
graphicPath.AddArc(rect.Left, rect.Top, size.Width, size.Height, 180, 90);
graphicPath.AddArc(rect.Right - size.Width, rect.Top, size.Width, size.Height, 270, 90);
g.DrawPath(pen, graphicPath);

g.SmoothingMode = sm;
g.PixelOffsetMode = pom;
}
}
}
■No32060に返信(hiroさんの記事)
> 一応試してみているんですけど、うまくいきません。
>
「うまくいきません。」とはどのようになりますか?(白で表示される?グレー表示になる?他?)
白表示→base.BackColor = Color.Transparent;がきいてない?
グレー(Control色)表示→正常に透過されている可能性あり。フォームの背景色がきちんと表示されている。
      (Form.BackgroupndImageに適当な画像ファイルを設定して試してみて)

ユーザーコントロール上にコントロールは配置されていますか?
コントロールが配置されている場合、新規でユーザーコントロールを作って、コントロールを配置せずに試してもらえませんか?
ユーザーコントロールのビルド後、ユーザーコントロールを貼り直しても同じでしょうか?


> コードは、そんなに長くないので載せます(UserControlのみ)
>
俺も同じコード書いてます。
GraphicsBKBrush, sm, pom, graphicPath は後で値を入れているので、俺の方では宣言時に初期化してません(サンプルを直にC#にした形)でしたが、処理的には変わらないですね。
お世話になります。


> 「うまくいきません。」とはどのようになりますか?(白で表示される?グレー表示になる?他?)
> グレー(Control色)表示→正常に透過されている可能性あり。フォームの背景色がきちんと表示されている。
グレー表示になっています。


> Form.BackgroupndImageに適当な画像ファイルを設定して試してみて)
ここに適当な画像を貼ると、普通に表示してきます。OnPaint()で表示している枠も一緒に表示します。

>
> ユーザーコントロール上にコントロールは配置されていますか?
配置していません。


> ユーザーコントロールのビルド後、ユーザーコントロールを貼り直しても同じでしょうか?
やってみましたが結果、変わらず・・・・


> 俺も同じコード書いてます。
> GraphicsBKBrush, sm, pom, graphicPath は後で値を入れているので、俺の方では宣言時に初期化してません(サンプルを直にC#にした形)でしたが、処理的には変わらないですね。
同じコードでaさんはうまくいっているのですね。じゃ、どっか、「私とaさんのコードに相違点がある」ということですね。

なにか、プロパティか何か変更するのを忘れているのでしょうか?
■No32062に返信(hiroさんの記事)
>>Form.BackgroupndImageに適当な画像ファイルを設定して試してみて)
> ここに適当な画像を貼ると、普通に表示してきます。OnPaint()で表示している枠も一緒に表示します。
>
普通にというのはControl色で表示されるということですか?それともFormの背景が表示されるということですか?(ユーザーコントロールの背景部分)
Control色→コードにどこか違うとこがあるのかな?
Formの背景→透過の認識が違うのでは?(2014/01/14(Tue) 16:37:51の返信参照)

// Form側のテストコード(フォームロード時の処理)
// FormにpictureBoxとユーザーコントロールを配置。
// 変数名は適当に変更してください
// ユーザーコントロール部分が何色で表示されるか?(Color.Blueなら正常に透過できています。他の色になっているなら何かがおかしい?)
private void Form1_Load(object sender, EventArgs e)
{
// フォームの背景色を変更
this.BackColor = Color.Blue;

// PictureBoxの配置と背景色を変更
pictureBox1.Location = new System.Drawing.Point(25, 53);
pictureBox1.Size = new System.Drawing.Size(243, 188);
pictureBox1.BackColor = Color.Black;

// ユーザーコントロールの位置と背景色を変更
ucRectangle1.BackColor = System.Drawing.Color.Transparent;
ucRectangle1.Location = new System.Drawing.Point(61, 117);
ucRectangle1.Size = new System.Drawing.Size(158, 89);
}
お世話になります。


> // ユーザーコントロール部分が何色で表示されるか?(Color.Blueなら正常に透過できています。他の色になっているなら何かがおかしい?)
おっしゃる通りの青色になりました。ということは、このユーザーコントロールは、透過に対応した形で作成されている!?ということになるようですね。


・・・で自分なりに調査。
・・・フォーム画像を張り付け確認。
 フォームにPictureBox をはじめ」幾つかコントロールを配置しテスト!
 するとユーザコントロールには、フォームに或る画像が表示されました。
 トラッキングのテストなのでそのユーザコントロールを移動させても表示しています。
 じゃ、透過について完了?と思いきや、フォームに対しては上記のとおりOKのようですが、実際の画像を表示するのは、フォームでなくpictureBoxなのでpictureBoxに対する透過を実装する必要があるようです。

ユーザコントロールの定義で

public partial class UserControlCircle : PictureBox//UserControl
{

としてみましたが、それではうまくいかないようです。結果は、変更前と変わらず。

ユーザコントロールの親を透かせたいコントロールを親にすればいいんですよね!
■No32064に返信(hiroさんの記事)
> ユーザコントロールの定義で
>
> public partial class UserControlCircle : PictureBox//UserControl
> {
>
> としてみましたが、それではうまくいかないようです。結果は、変更前と変わらず。
>
基底クラスを変えてますね。やってることがずれています。
コンテナーについて調べてください。
2014/01/14(Tue) 16:37:51の返信について試行してますか?

別の案として
http://hisk2tmem.blog61.fc2.com/blog-entry-36.html
いう方法もあるみたいです。
お世話になります。

色々、試行錯誤しているうちに混同してましたね。

「透過=フォームの背景をコントロールに表示する」でしたね。透過という言葉に惑わされたり、変な方向に走ってみたりちょっと大変でした。

「フォームに表示するイメージを子コントロールに表示する」ことを抑えればなんとかなりそうな目途が立ちました。

a様、たいへんお世話になり感謝申し上げます。
解決済み!
2014/01/20(Mon) 10:41:51 編集(投稿者)

■No32079に返信(hiroさんの記事)
> 「透過=フォームの背景をコントロールに表示する」でしたね。透過という言葉に惑わされたり、変な方向に走ってみたりちょっと大変でした。
>
解決済みとなっていますが...
「フォームの背景〜」ではなく「親コントロールの背景〜」ですね。
必ずしも「フォーム=親コントロール」とはなりません。
panelなどのコンテナー機能を持った一部のコントロールは親コントロールになる可能性があるからです。

2014/1/20 10:41編集
 解決済みが外れていたので解決済みをチェック
解決済み!

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