お世話になります。

VC 2005で開発しているC++で教えていただきたい事が有ります。

PictureboxBの上にPictureboxAを透過率50%位で重ねて表示したいのですが、
Pictureboxのプロパティ等で一括で指定できないでしょうか?
出来ない場合、画像を一括で透過処理する方法が有りましたら教えていただけないでしょうか
※ ググって、単色を透過するのは、色々見つけたのですが、画像全体を透過する方法を見つけることが出来ませんでした。

現状は単純にファイル(写真)を読み込んで、PictureboxのImageに格納しているだけです。
※将来的には、PictureboxAをドラッグで移動させたいので、背景画像(PictureboxB)との位相を取る方法以外でお願いいたします。

Bitmap^ PhotBMP = gcnew Bitmap(filename);
// この間にサイズ変更&位置合わせの処理が有りますが、記載を省略させていただいております。
PictureboxA->Image = PhotBMP;

このQ&Aに関連する最新のQ&A

A 回答 (2件)

// No.1 の続きです。

長くて申し訳ない

Bitmap^ back;
Graphics^ backGraphics;
void UpdateBuffer(){
if(back==nullptr){
back=gcnew Bitmap(Width,Height);
backGraphics=Graphics::FromImage(back);
}else if(back->Width!=Width||back->Height!=Height){
delete backGraphics;
delete back;
back=gcnew Bitmap(Width,Height);
backGraphics=Graphics::FromImage(back);
}
}

protected:
virtual void OnPaintBackground(PaintEventArgs^ e) override{
ContainerControl^ container=dynamic_cast<ContainerControl^>(Parent);
if(container!=nullptr){
this->UpdateBuffer();
backGraphics->Clear(BackColor);

Rectangle rect=e->ClipRectangle;
rect.Intersect(Rectangle(Point::Empty,this->Size));
if(!rect.IsEmpty){
this->DrawBackgroundControl(backGraphics,rect,container,Point(-Location.X,-Location.Y));

int i0=container->Controls->IndexOf(this);
if(i0>=0){
for(int i=container->Controls->Count;--i>i0;){
Control^ ctrl=container->Controls[i];
Point offset=Point(
ctrl->Location.X-this->Location.X,
ctrl->Location.Y-this->Location.Y);

Rectangle rect2=rect;
rect2.Intersect(Rectangle(offset,ctrl->Size));
if(!rect2.IsEmpty)
this->DrawBackgroundControl(backGraphics,rect2,ctrl,offset);
}
}
}
e->Graphics->DrawImageUnscaled(back,0,0);
}else{
this->PictureBox::OnPaintBackground(e);
}
}
};

//-------------------------------------
// 使用例

public ref class Form1:public Form{
public:
Form1(){
SetStyle(ControlStyles::SupportsTransparentBackColor,true);

SuspendLayout();

Image^ image=Image::FromFile("test1.png"); // 適当な画像

// ★PictureBox の代わりに上で定義したTransparentPictureBox を使う
TransparentPictureBox^ pictureBoxA=gcnew TransparentPictureBox;
pictureBoxA->Location=System::Drawing::Point(10,10);
pictureBoxA->Size=System::Drawing::Size(100,100);
pictureBoxA->SizeMode=PictureBoxSizeMode::StretchImage;
pictureBoxA->Image=image;
pictureBoxA->Opacity=0.3f; // ★プロパティ Opacity に不透明度 (0.0f = 完全に透明、1.0 = 完全に不透明) を指定。
Controls->Add(pictureBoxA);

PictureBox^ pictureBoxB=gcnew PictureBox;
pictureBoxB->Location=System::Drawing::Point(60,60);
pictureBoxB->Size=System::Drawing::Size(100,100);
pictureBoxB->SizeMode=PictureBoxSizeMode::StretchImage;
pictureBoxB->Image=(Image^)image->Clone();
Controls->Add(pictureBoxB);

this->Size=System::Drawing::Size(200,200);
BackColor=Color::FromArgb(0xFF,0xDD,0xDD,0xFF);

ResumeLayout();
}

public:
static void Main(){
Application::Run(gcnew Form1());
}
};

int main(){
Form1::Main();
return 0;
}
    • good
    • 0
この回答へのお礼

ありがとうございます。

サンプルを作成して動作確認までしていただけるなんて、
本当に助かりました。

お礼日時:2014/07/07 10:29

簡単にはできないみたいですね…。



(1) 画像を透過して半透明にするだけなら http://dobon.net/vb/dotnet/graphics/hadeinimage. … にあります。
しかし、これを PictureboxA->Image に指定しても pictureBoxA の背景色 (~灰色) が透けるだけです。
更に、コントロールの背景色を「透明」にする方法として http://msdn.microsoft.com/ja-jp/library/wk5b13s4(v=vs.110).aspx がありますが、これの実態は親コントロール (Form) の背景を自コントロールの背景として使用するというだけの物で、兄弟コントロール (PictureboxB) は映り込んでくれません。

(2) 強引に PictureboxA 自体を「透過」させるのを実装してみました (下のコード)。(実は他に綺麗で簡単な方法があるかも知れませんが。)

【説明】
PictureBox から派生クラスを作って PictureBox の振る舞いを一部変更しています。
前半部分は (1) で紹介した URL の方法で、指定した画像の半透明版を作成しています。
後半部分は背景を描き込む関数 PictureBox::OnPaintBackground を overload して、背景として無理矢理他のコントロールを描画しています。

一応動作する事は確かめましたが、適当に書いたので効率面で問題があります。バグも在るかも知れませんので、使うなら注意深く使って下さい…。

--------------------
#using "System.dll"
#using "System.Drawing.dll"
#using "System.Windows.Forms.dll"

using namespace System::Windows::Forms;
using namespace System::Drawing;

public ref class TransparentPictureBox:public PictureBox{
public:
TransparentPictureBox(){
this->InitializeBackground();
this->InitializeForeground();
}

protected:
~TransparentPictureBox(){
this->DeleteBackground();
this->DeleteForeground();
}

//-------------------------------------
// 前景を半透明にする部分
private:
void InitializeForeground(){
this->imageAttributes=gcnew System::Drawing::Imaging::ImageAttributes;
this->Opacity=1.0f;
}
void DeleteForeground(){
this->Image=nullptr;
}

float opacity;
System::Drawing::Imaging::ImageAttributes^ imageAttributes;
public:
property float Opacity{
void set(float value){
if(opacity==value)return;

System::Drawing::Imaging::ColorMatrix^ cm=gcnew System::Drawing::Imaging::ColorMatrix;
cm->Matrix00 = 1;
cm->Matrix11 = 1;
cm->Matrix22 = 1;
cm->Matrix33 = value;
cm->Matrix44 = 1;
imageAttributes->SetColorMatrix(cm);
opacity=value;
this->UpdateAlphaImage();
}
float get(){return opacity;}
}

private:
System::Drawing::Image^ original;
public:
property System::Drawing::Image^ Image{
void set(System::Drawing::Image^ value){
if(this->original==value)return;
this->original=value;
this->UpdateAlphaImage();
}
System::Drawing::Image^ get(){return this->original;}
}

private:
Bitmap^ alphaImage;
void UpdateAlphaImage(){
if(this->alphaImage!=nullptr){
delete alphaImage;
alphaImage=nullptr;
this->PictureBox::Image=nullptr;
}
if(original!=nullptr){
alphaImage=gcnew Bitmap(original->Width,original->Height);
{
Graphics^ g=Graphics::FromImage(alphaImage);
g->DrawImage(
original,Rectangle(Point::Empty,original->Size),
0,0,original->Width,original->Height,GraphicsUnit::Pixel,imageAttributes);
delete g;
}
this->PictureBox::Image=alphaImage;
}
}

//-------------------------------------
// 背景に他のコントロールを描き込む部分

System::Reflection::MethodInfo^ methodOnPaint;
System::Reflection::MethodInfo^ methodOnPaintBackground;
void InitializeBackground(){
System::Reflection::BindingFlags flags
=System::Reflection::BindingFlags::Instance
|System::Reflection::BindingFlags::Public
|System::Reflection::BindingFlags::NonPublic;
this->methodOnPaint=Control::typeid->GetMethod("OnPaint",flags);
this->methodOnPaintBackground=Control::typeid->GetMethod("OnPaintBackground",flags);
}
void DeleteBackground(){
delete backGraphics;
delete back;
}

void DrawBackgroundControl(Graphics^ g,Rectangle rect,Control^ control,Point offset){
g->SetClip(rect);
g->TranslateTransform(offset.X,offset.Y);
rect.Offset(-offset.X,-offset.Y);
try{
array<System::Object^>^ args=gcnew array<System::Object^>{gcnew PaintEventArgs(g,rect)};
this->methodOnPaintBackground->Invoke(control,args);
this->methodOnPaint->Invoke(control,args);
}catch(...){}
g->TranslateTransform(-offset.X,-offset.Y);
g->ResetClip();
}

// 続く…

参考URL:http://dobon.net/vb/dotnet/graphics/hadeinimage. …
    • good
    • 0

このQ&Aに関連する人気のQ&A

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

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QOpenDialog1->FileNameについて

C++ Builderでプログラミングしています。


OpenDialog1->FileName = Edit1->Text;

このようなテキストボックスに書かれたファイルパスをOpenDialog1->FileNameにいれてそこがNULLだった場合は、ファイルの読み込みを中止する処理をするようなことをやりたいと思っています。


if(OpenDialog1->FileName == NULL){



Edit1->Text;のなかに何も入っていない状態でNULLかどうかのif文に来たときに、NULLではないと判定されるのですが、この書き方に問題があるのでしょうか?


また、OpenDialog1->FileName に入っているパスが存在しない場合にファイル読み込みを中止させるような方法はありますでしょうか?

どうぞ、ご教授の程よろしくおねがい致します。

Aベストアンサー

>Edit1->Text;のなかに何も入っていない状態でNULLかどうかのif文に来たときに、NULLではないと判定されるのですが、この書き方に問題があるのでしょうか?

"" == NULLが真であれば、想定した動作になるハズです。
貴方のC++ Builderは""とNULLが等価であるとは判断していないのですよ。
# まぁ、当然ですが……。

NULLなら所謂ヌルポインタ(たいていは全Bitが0)ですが、""はどっかのアドレスを指しています。
そして、指している先には'\0'が入っています。
どこかのアドレスを指している以上、NULLにはなり得ません。
# 指している先が""だった場合にNULLを代入する処理を追加しないとならない…でしょうね。
# その処理が有用かどうかは…状況次第ですが。

OPENFILENAME構造体で、選択したファイル名を受け取るバッファへのポインタをNULLにしてAPIをコールして…正常に動作するかどうかは……どうなんでしょうかね?
# キャンセルされれば正常動作でしょうが、何らかのファイルを選択するとNULLポインタアクセスで「正常に吹っ飛ぶ」でしょうね。

>Edit1->Text;のなかに何も入っていない状態でNULLかどうかのif文に来たときに、NULLではないと判定されるのですが、この書き方に問題があるのでしょうか?

"" == NULLが真であれば、想定した動作になるハズです。
貴方のC++ Builderは""とNULLが等価であるとは判断していないのですよ。
# まぁ、当然ですが……。

NULLなら所謂ヌルポインタ(たいていは全Bitが0)ですが、""はどっかのアドレスを指しています。
そして、指している先には'\0'が入っています。
どこかのアドレスを指している以上、NULLにはなり得ま...続きを読む

QpictureBoxの画像の座標の色の出し方。

VC++で、pictureBoxで表示した画像を適当な場所をクリックするとその座標とRGBの色あいが表示するプログラムなんですが、エラーはしなかったんですが、デバックして画像表示して適当にクリックしてもなにも表示されませんでした。
プログラムに間違えでもあるのかみてください。

private: System::Void pictureBox1_MouseDown(System::Object^sender, System::Windows::Forms::MouseEventArgs^ e) {
String^fname = openFileDialog1->FileName;
Bitmap^fun = gcnew Bitmap(fname);
Point^ p = PointToClient( Point(e->X ,e->Y));
Color^col = fun->GetPixel(p->X,p->Y);
label1->Text = String::Format("..{0}", fun->GetPixel(p->X,p->Y));
}

VC++で、pictureBoxで表示した画像を適当な場所をクリックするとその座標とRGBの色あいが表示するプログラムなんですが、エラーはしなかったんですが、デバックして画像表示して適当にクリックしてもなにも表示されませんでした。
プログラムに間違えでもあるのかみてください。

private: System::Void pictureBox1_MouseDown(System::Object^sender, System::Windows::Forms::MouseEventArgs^ e) {
String^fname = openFileDialog1->FileName;
Bitmap^fun = gcnew Bitmap(fname);
Point^ p = Point...続きを読む

Aベストアンサー

PictureBoxのSizeModeは何でしょう? Normalなのでしょうか
NormalならPointToClientで変換する必要はありませんよ

StreatImageの場合は表示する画像ファイルの大きさ(高さ・幅)とPictureBoxの大きさの比率を考えてPointの換算をします

Zoomの場合は縦・横どちらが基準になっているのかを考えて換算します

CenterImageの場合は画像のどの部分が表示されているのかを考えてオフセットを考えましょう

MouseDownイベントで毎回イメージを選択するのは意図したことでしょうか
あらかじめPictureBoxにのImageプロパティに設定されているなら
Bitmap^ fun = gcnew Bitmap( pictureBox1->Image );
でイメージをBitmapオブジェクトに変換したほうがいいように思います

QTIFFを開いてBITMAPで保存する方法

■開発環境
VC++6.0,Windows2000 Pro,+ libtiff(TIFFを扱うライブラリ)

で以下のようなコードを書きました.

*************************************************
BOOL CTiff::OpenTiffAndSaveBMP(CString path)
{
HDIB hDIB;
hDIB = LoadTIFFinDIB(path);

BITMAPFILEHEADER BMPFILEHEADER;
LPBITMAPINFOHEADER BMPINFOHEADER;

if(!hDIB)
return FALSE;

CFile file;
path.Replace("tif", "bmp");
if( !file.Open( path, CFile::modeWrite|CFile::modeCreate) )
return FALSE;

BMPINFOHEADER = (LPBITMAPINFOHEADER)hDIB;

int nColors = 1 << BMPINFOHEADER->biBitCount;

// BITMAPFILEHEADERのフィールドを初期化
BMPFILEHEADER.bfType = ((WORD) ('M' << 8) | 'B'); // is always "BM"
BMPFILEHEADER.bfSize = GlobalSize (hDIB) + sizeof( BMPFILEHEADER );
BMPFILEHEADER.bfReserved1 = 0;
BMPFILEHEADER.bfReserved2 = 0;
BMPFILEHEADER.bfOffBits = (DWORD)(sizeof( BMPFILEHEADER ) +
BMPINFOHEADER->
biSize + nColors * sizeof(RGBQUAD));

// ファイルヘッダを書き込む
file.Write( &BMPFILEHEADER, sizeof(BMPFILEHEADER) );

// DIBのヘッダとビット列を書き込む
DWORD nSize = GlobalSize(hDIB);
file.Write( BMPINFOHEADER, nSize );
file.Close();
return TRUE;
}
************************************************

しかし,OpenTiffAndSaveBMP()の下から3行目の
>file.Write( BMPINFOHEADER, nSize );
でDebug Assertion Failed!なるエラーで止まってしまいます.
そこで「無視」ボタンを押すと「ファイルにアクセス中に不明なエラーが発生しまし
た」となります.

文字数の制限上LoadTIFFinDIB()のソースは無いのですが,
原因ならびに解決策の分かる方ご教授ください.

■開発環境
VC++6.0,Windows2000 Pro,+ libtiff(TIFFを扱うライブラリ)

で以下のようなコードを書きました.

*************************************************
BOOL CTiff::OpenTiffAndSaveBMP(CString path)
{
HDIB hDIB;
hDIB = LoadTIFFinDIB(path);

BITMAPFILEHEADER BMPFILEHEADER;
LPBITMAPINFOHEADER BMPINFOHEADER;

if(!hDIB)
return FALSE;

CFile file;
path.Replace("tif", "bmp");
if( !file.Open( path, CFile::modeWrite|CFile::modeCreate) )
return FALS...続きを読む

Aベストアンサー

GlobalSize(hDIB)としているならグローバルメモリなんでしょう。
hDIBがポインタとは限らないので、GlobalLock() でメモリブロックへのポインタを得てからキャストする。
BMPINFOHEADER = (LPBITMAPINFOHEADER)GlobalLock(hDIB);

QVisual C++でBitMapの移動

Visual C++ MFCをつかっていBitMapの移動をしたいのですがうまくいきません。参考になるHPがありましたら教えてください。

Aベストアンサー

ビットマップの移動はBitBlit()を使用しますが、MFCのメンバには無かったような気がします。

参考程度ですが、BitBlit()を使ったビットマップの移動方法にが掲載されているHPを紹介いたします。

マイクロソフト公式サイト
http://www.microsoft.com/japan/developer/winds/Sdk/Samples/SDKSample04.htm

ぷろぐらむ講座
http://www.ichigo-cafe.com/prog_tips/07_loadbmp/loadbmp.html

QC# pictureBox(a)

Visual C# 2008にて

int a = 3;
pictureBox(a).Image = Properties.Resources.Icon1_2;
みたいな代入の方法がどうしても解りません

Properties.Resources.Icon1_2は
リソースのIcon1_2.bmpです

過去のQ&A
QNo6332332を読んでも解りません。

pictureBoxを貼り付けてダブルクリック
Tagを1.などに設定

private void pictureBox1_Click(object sender, EventArgs e)
{
PictureBox pict = sender as PictureBox;
MessageBox.Show(pict.Name);
MessageBox.Show(pict.Tag.ToString());
int picb = int.Parse(pict.Tag.ToString());

pictureBox(picb).Image = Properties.Resources.Icon1_2;

}

上のようにしたい
アドバイスをお願いできませんでしょうか

Visual C# 2008にて

int a = 3;
pictureBox(a).Image = Properties.Resources.Icon1_2;
みたいな代入の方法がどうしても解りません

Properties.Resources.Icon1_2は
リソースのIcon1_2.bmpです

過去のQ&A
QNo6332332を読んでも解りません。

pictureBoxを貼り付けてダブルクリック
Tagを1.などに設定

private void pictureBox1_Click(object sender, EventArgs e)
{
PictureBox pict = sender as PictureBox;
MessageBox.Show(pict.Name);
MessageBox.Show(pict.Tag.ToString());
int picb = int.Parse(pict....続きを読む

Aベストアンサー

質問者様がTagを使用されるとのことですので、提示されたコードを用います。
(int picbは、pictureBox1の場合には、「1」とし、名称と一致するものとします。)

「pictureBox(picb).Image = Properties.Resources.Icon1_2;」を以下のように変更します。

Control c = this.Controls["pictureBox" + picb.ToString()];
((PictureBox)c).Image = Properties.Resources.Icon1_2;
(一度、Control型で定義し、PictureBox型にキャストした上で、アイコンを代入します。)

なお、本コードでは、対象となるpictureBoxが見つからなかった場合、エラーとなってしまいます。
try~catch~によるエラー処置が必要となります。


人気Q&Aランキング

おすすめ情報