プロが教えるわが家の防犯対策術!

プログラミングの初心者ですが、現在VC++2005のフォームアプリケーションでプログラムについて勉強しています。画像を連続表示するところで、わからなくなってしまったので、みなさんのご指導お願いいたします。
やりたい処理は、取り込んだ画像の色を変化させて、順番に表示したい
処理です。作成したプログラムは下記のようになります。

前略
for(n=0; n<256; n+=20){
for(y=0; y<480; y++){
for(x=0; y<640; x++){
bmp->Setpixel(x, y, Color::FromArgb(n, n, n));
}
}
pictureBox->Image = bmp;
Thread::Sleep(2000);
}
nの値をbmpに入れてから一回表示し、さらにnを足してからbmpに入れて表示するといった流れですが、Sleepを入れても何にも表示されません。
どういったところは不具合なのかをよくわかりません。
ご指導をいただければ感謝致します。どうぞよろしくお願い致します。

A 回答 (4件)

#3さんへ


別に君が書いたサンプルコードに対してコメントしたわけではありませんよ。
あなたもよく理解できていないようですが、質問者のコードでは、描画できません。
表に出てこないだけですが、Invalidate()をコールするとWM_PAINTのメッセージがアプリケーションに対して送られて描画される仕組みは、同じですよ。
    • good
    • 0

 こんにちは。

チョッと不足したので補足を。
 現状では真っ黒なビットマップをSetPixel()で着色しているだけなので、黒→白になるだけですので、ファイルから開いたビットマップの場合は、元の色彩を取って計算しないといけません。
 後、xボタンを押した時、スレッドが存在していれば止めるためにClosingイベントを追加しています。その他の細かい事は任意でお願いします。

・このコードでは、アプリケーションがWM_PAINTを処理できないので描画できません。
 描画出来ています。
 ピクチャボックスのImageプロパティにグラフィックをセットしてInvalidate()を呼ぶとピクチャボックスの表示が更新されます。
 
 通常、C++/CLIにWM_PAINTなんてものは出て来ません。
 WndProcメソッドをオーバーライドして、WM_PAINTを引っ掛ける事は出来る様に成っていますが、余程の理由でもない限り、行いません。
 処理する場合、PlatformSDK側のAPIや構造体を使用する為にwindows.hをインクルードしなければいけない必要性が発生する事がありますが、C++/CLIでは通常使用出来ない様に成っています。
 
 ピクチャボックスにグラフィックスをセットして反映させるだけなら、Paintイベントをオーバーライドする必要はありません。
 
・まず、Windowsにおける描画の仕組みを理解しましょう。
 揚げ足を取る前に、マネージドとアンマネージドの違い位は見抜きましょう。

#pragma once

namespace laylay {

using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;

/// <summary>
/// Form1 の概要
///
/// 警告: このクラスの名前を変更する場合、このクラスが依存するすべての .resx ファイルに関連付けられた
/// マネージ リソース コンパイラ ツールに対して 'Resource File Name' プロパティを
/// 変更する必要があります。この変更を行わないと、
/// デザイナと、このフォームに関連付けられたローカライズ済みリソースとが、
/// 正しく相互に利用できなくなります。
/// </summary>
public ref class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();
//
//TODO: ここにコンストラクタ コードを追加します
//
}

protected:
/// <summary>
/// 使用中のリソースをすべてクリーンアップします。
/// </summary>
~Form1()
{
if (components)
{
delete components;
}
}
private: System::Windows::Forms::Button^ button1;
protected:
private: System::Windows::Forms::PictureBox^ pictureBox1;

private:
/// <summary>
/// 必要なデザイナ変数です。
/// </summary>
System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
/// <summary>
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード エディタで変更しないでください。
/// </summary>
void InitializeComponent(void)
{
this->button1 = (gcnew System::Windows::Forms::Button());
this->pictureBox1 = (gcnew System::Windows::Forms::PictureBox());
(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->pictureBox1))->BeginInit();
this->SuspendLayout();
//
// button1
//
this->button1->Location = System::Drawing::Point(64, 238);
this->button1->Name = L"button1";
this->button1->Size = System::Drawing::Size(75, 23);
this->button1->TabIndex = 0;
this->button1->Text = L"button1";
this->button1->UseVisualStyleBackColor = true;
this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);
//
// pictureBox1
//
this->pictureBox1->Location = System::Drawing::Point(13, 13);
this->pictureBox1->Name = L"pictureBox1";
this->pictureBox1->Size = System::Drawing::Size(257, 179);
this->pictureBox1->TabIndex = 1;
this->pictureBox1->TabStop = false;
//
// Form1
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 12);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(292, 273);
this->Controls->Add(this->pictureBox1);
this->Controls->Add(this->button1);
this->Name = L"Form1";
this->Text = L"Form1";
this->Load += gcnew System::EventHandler(this, &Form1::Form1_Load);
(cli::safe_cast<System::ComponentModel::ISupportInitialize^ >(this->pictureBox1))->EndInit();
this->ResumeLayout(false);

}
#pragma endregion
//メンバ変数
private: delegate System::Void DelegateSetPixel(System::Int32 n);

private: DelegateSetPixel^ setPixel;
private: System::Threading::Thread^ thread;
private: System::Drawing::Bitmap^ bitmap;

//下ごしらえ
private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e)
{
//ファイルから読む
System::Drawing::Bitmap^ bmpFromFile = dynamic_cast<System::Drawing::Bitmap^>(gcnew System::Drawing::Bitmap("test.bmp"));
this->bitmap = dynamic_cast<System::Drawing::Bitmap^>(bmpFromFile->Clone());
delete bmpFromFile;

this->pictureBox1->Image = dynamic_cast<System::Drawing::Bitmap^>(this->bitmap->Clone());
this->setPixel = gcnew DelegateSetPixel(this, &Form1::DrawMethod);
this->button1->Tag = gcnew System::Boolean(false);

this->Closing += gcnew System::ComponentModel::CancelEventHandler(this, &Form1::Form1_Closing);
}
//閉じた時
private: System::Void Form1_Closing(System::Object^ sender, System::ComponentModel::CancelEventArgs^ e)
{
if(this->thread != nullptr)
this->thread->Abort();
}
//スレッド中
private: System::Void threadProc()
{
System::Int32 n = 0;
while(*static_cast<System::Boolean^>(this->button1->Tag))
{
this->thread->Sleep(33);
n = System::Math::Min(n + 20, 255);
this->setPixel->Invoke(n);
if(n == 255)n = 0;
}
}
//ボタンを押す
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
System::Boolean% rbRunning = *static_cast<System::Boolean^>(this->button1->Tag);
rbRunning ^= true;

if(rbRunning)
{
this->button1->Text = L"実行中";

this->thread = gcnew System::Threading::Thread(gcnew System::Threading::ThreadStart(this, &Form1::threadProc));
this->thread->Start();
}
else
{
this->button1->Text = L"レディ";
this->thread->Abort();
this->thread = nullptr;
}
this->button1->Update();
}
private: System::Void DrawMethod(System::Int32 n)
{
System::Drawing::Bitmap^ bmp = dynamic_cast<System::Drawing::Bitmap^>(this->bitmap->Clone());
for(System::Int32 y = 0; y < bmp->Height; y++)
{
for(System::Int32 x = 0; x < bmp->Width; x++)
{
Color color = bmp->GetPixel(x, y);
System::Int32 R = System::Math::Min(color.R + n, 255);
System::Int32 G = System::Math::Min(color.G + n, 255);
System::Int32 B = System::Math::Min(color.B + n, 255);
bmp->SetPixel(x, y, Color::FromArgb(R, G, B));
}
}
System::Drawing::Image^ image = this->pictureBox1->Image;
this->pictureBox1->Image = bmp;
delete image;
this->pictureBox1->Invalidate();
}
};
}
「BMP画像を画像処理して連続に表示したい」の回答画像3
    • good
    • 0

このコードでは、アプリケーションがWM_PAINTを処理できないので描画できません。


まず、Windowsにおける描画の仕組みを理解しましょう。
    • good
    • 0

 こんにちは。



 Thread::Sleep(2000);の2000が大きすぎて、止まっているのではないでしょうか。33位にしてみては如何でしょうか。
 後、SetPixel()は負担の大きいメソッドですので、640x480のイメージを処理するのは実に厳しいと思います。
 以下は320x240のイメージ変色をスレッドにて行っていますが、かなり重たいです。pictureBox1とbutton1が必要です。参考程度に。

//メンバ変数
private: delegate System::Void DelegateSetPixel(System::Int32 n);

private: DelegateSetPixel^ setPixel;
private: System::Threading::Thread^ thread;

//下ごしらえ
private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e)
{
//ファイルから読むなら
//System::Drawing::Bitmap^ bmpFromFile = dynamic_cast<System::Drawing::Bitmap^>(gcnew System::Drawing::Bitmap("test.bmp"));
//this->pictureBox1->Image = dynamic_cast<System::Drawing::Bitmap^>(bmpFromFile->Clone());
//delete bmpFromFile;

this->setPixel = gcnew DelegateSetPixel(this, &Form1::DrawMethod);
this->pictureBox1->Image = gcnew System::Drawing::Bitmap(320, 240, System::Drawing::Imaging::PixelFormat::Format24bppRgb);
this->button1->Tag = gcnew System::Boolean(false);
}
//スレッド中
private: System::Void threadProc()
{
System::Int32 n = 0;
while(*static_cast<System::Boolean^>(this->button1->Tag))
{
this->thread->Sleep(33);
n = System::Math::Min(n + 20, 255);
this->setPixel->Invoke(n);
if(n == 255)n = 0;
}
}
//ボタンを押す
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
System::Boolean% rbRunning = *static_cast<System::Boolean^>(this->button1->Tag);
rbRunning ^= true;

if(rbRunning)
{
this->button1->Text = L"実行中";

this->thread = gcnew System::Threading::Thread(gcnew System::Threading::ThreadStart(this, &Form1::threadProc));
this->thread->Start();
}
else
{
this->button1->Text = L"レディ";
}
this->button1->Update();
}
//色彩変化
private: System::Void DrawMethod(System::Int32 n)
{
//ピクチャボックスからイメージを複製
System::Drawing::Bitmap^ bitmap = dynamic_cast<System::Drawing::Bitmap^>(this->pictureBox1->Image->Clone());

//色彩変化
for(System::Int32 y = 0; y < bitmap->Height; y++)
{
for(System::Int32 x = 0; x < bitmap->Width; x++)
{
bitmap->SetPixel(x, y, Color::FromArgb(n, n, n));
}
}

//古いイメージと交換する
System::Drawing::Image^ image = this->pictureBox1->Image;
this->pictureBox1->Image = bitmap;
delete image;
this->pictureBox1->Invalidate();
}
    • good
    • 0

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