別スレッドからメインスレッドのテキストボックスに文字を表示させたい

このQ&Aのポイント
  • Visual C++ 2005 Express Editionを使用している初心者です。タイトルの方法がわからないので教えてください。
  • 質問者は、メインスレッドのテキストボックスに別のスレッドから文字を表示する方法を知りたいと述べています。
  • 質問者は、プログラムのコードの一部を共有し、その部分で表示したい文字列を記述しています。
回答を見る
  • ベストアンサー

別スレッドからメインスレッドのテキストボックスに文字を表示させたい

Visual C++ 2005 Express Editionを使用している初心者です。 タイトルの方法がどうしてもわからないので教えてください。 うまく説明できないので聞きたいところのコードを載せます。 //SAMPLE.cpp #include "stdafx.h" #include "Form1.h" using namespace SAMPLE; int main(array<System::String ^> ^args) { Application::EnableVisualStyles(); Application::SetCompatibleTextRenderingDefault(false); Application::Run(gcnew Form1()); } //Form1.h #include <process.h> #include <vcclr.h> namespace SAMPLE { unsigned __stdcall counter(void *arg); int thread_id1; unsigned dummy; using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; public ref class Form1 : public System::Windows::Forms::Form { public:Form1(void) { InitializeComponent(); //別スレッド起動 thread_id1=_beginthreadex(NULL,0,counter,(void *)1,0,&dummy); } private: System::Windows::Forms::TextBox^ textBox1; private: System::ComponentModel::Container ^components; void InitializeComponent(void) { this->textBox1 = (gcnew System::Windows::Forms::TextBox()); //省略(コンポーネント初期化) } private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) { } }; unsigned __stdcall counter(void *arg){ //別スレッド //ここで文字列を記述して上のtextBox1に表示したい return 0; } } 初歩的なことかもしれませんが、 よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • tea_sheep
  • ベストアンサー率53% (8/15)
回答No.1

フォームやコントロールを作成したスレッド以外のスレッドがフォームや コントロールを直接操作することはできません。 フォーム・コントロールが持つ Invoke メソッドなどを介して行います。 スレッド作成に _beginthreadex を使用しているようですが、 この関数はWindows APIが提供するスレッドハンドルを返すので、 明示的に CloseHandle でハンドルを閉じなければなりません。 System::Threading::Thread クラスを使ってはどうでしょう。

suzuki525
質問者

お礼

System::Threading::Threadを使って別スレッドをForm1クラスの中に入れ、実現することができました。 ありがとうございました。

関連するQ&A

  • フォームのテキストコントロールへの出力

    Cは分かりますが、C++初心者です。 よろしくお願いします。 namespace sample1 外にある関数から、フォームのコントロールにアクセスするには、 どうしたらいいのでしょうか? ========================================================== #pragma once void DspData( ReadData *readdata ); //コールバック関数宣言 namespace sample1 { using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; public __gc class Form1 : public System::Windows::Forms::Form { public: Form1(void) { InitializeComponent(); } protected: void Dispose(Boolean disposing) { if (disposing && components) { components->Dispose(); } __super::Dispose(disposing); } private: System::Windows::Forms::Label * label1; private: System::Windows::Forms::Button * start; private: System::Windows::Forms::Button * end; public: System::Windows::Forms::TextBox * textBox1; private: System::ComponentModel::Container * components; void InitializeComponent(void) { } private: System::Void start_Click(System::Object * sender, System::EventArgs * e) { } }; } //------------------------------------------------ // DspData //------------------------------------------------ void DspData( ReadData *readdata ) { //***↓ここでフォームのテキストボックスへの表示を行いたい。***** textBox1->set_text("ここで出力") return; } ==========================================================

  • VC2010プログラミング

    formの中に自作のクラスを定義して使用したいのですが、どこに定義すればよいのかわかりません。 #pragma once #include "XXX.h" namespace FileRename { 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 の概要 /// </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; XXX^ instance = gcnew XXX(); protected: private: /// <summary> /// 必要なデザイナー変数です。 /// </summary> System::ComponentModel::Container ^components;   ・   ・   ・ } XXXクラスはこの場所で定義するのは間違いなのでしょうか?

  • Windowsフォームの表示

    Visual C++ 2005(Express Edition)で、windowsフォームを3個作りました。 1個目をForm1.h、2個目をForm2.h、3個目をForm3.h、メインプロジェクトは、Sample.cpp, ファイルとします。 Form1にボタンbutton1を作成し、ボタンをクリックしたイベントが発生したとき、Form2を表示させます。 Form2には、ボタンbutton2があります。 Form1と同様に、Form2のボタンをクリックするとForm3の画面が表示されるようにします。 ところが、以下のソースファイルで書いたところ、Form2とForm3は、名前空間に存在しませんという意味のエラーが生じます。 Form2とForm3をインスタンス化し、Show()メッソドで、画面を表示させる方法です。 しかし、Form1とForm2だけのファイルですと、先のソースの書き方で上手くいきます。 何か、書き方が異なるのでしょうか?正しい書き方を教えてくださいますとありがたいです。 なお、C++/CLIの文法に沿った、ソースコードでお願いします。 <ソースファイル> ----Form1.h----------------------------- #pragma once #include "stdafx.h" #include "Form2.h" #include "Form3.h" namespace Sample { 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 { //button1を作成 //省略 #pragma endregion private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { Form2^ a = gcnew Form2(); a->Show(); } }; } [EOF] --------------------------------------- ----Form2.h---------------------------- #pragma once #include "Form1.h" #include "Form3.h" using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; namespace Sample { /// <summary> /// IsotopeInput の概要 /// /// 警告: このクラスの名前を変更する場合、このクラスが依存するすべての .resx ファイルに関連付けられた /// マネージ リソース コンパイラ ツールに対して 'Resource File Name' プロパティを /// 変更する必要があります。この変更を行わないと、 /// デザイナと、このフォームに関連付けられたローカライズ済みリソースとが、 /// 正しく相互に利用できなくなります。 /// </summary> public ref class Form2 : public System::Windows::Forms::Form { //button2を作成 //省略 } #pragma endregion private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) { Form3^ b = gcnew Form3(); b->Show(); } }; } [EOF] --------------------------------------- -------Form3.h-------------------------- #pragma once #include "stdafx.h" #include "Form1.h" #include "Form2.h" using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; namespace Sample { /// <summary> /// Result の概要 /// /// 警告: このクラスの名前を変更する場合、このクラスが依存するすべての .resx ファイルに関連付けられた /// マネージ リソース コンパイラ ツールに対して 'Resource File Name' プロパティを /// 変更する必要があります。この変更を行わないと、 /// デザイナと、このフォームに関連付けられたローカライズ済みリソースとが、 /// 正しく相互に利用できなくなります。 /// </summary> public ref class Form3 : public System::Windows::Forms::Form { //省略 } #pragma endregion }; } [EOF] --------------------------------------------------------- Sample.cpp----------------------------------------------- // Sample.cpp : メイン プロジェクト ファイルです。 #include "stdafx.h" #include "Form1.h" #include "Form2.h" #include "Form3.h" using namespace Sample; [STAThreadAttribute] int main(array<System::String ^> ^args) { // コントロールが作成される前に、Windows XP ビジュアル効果を有効にします Application::EnableVisualStyles(); Application::SetCompatibleTextRenderingDefault(false); // メイン ウィンドウを作成して、実行します Application::Run(gcnew Form1()); return 0; } [EOF] ------------------------------------------------------------

  • フォーム間のデータ受け渡し

    現在VIsual Studio 2005のフォームアプリケーションを使ってプログラミングしています。ボタンを押すことで新たな子フォームを作成し、親フォームから子フォームへグローバル関数で宣言しているbmp[],picture[],red[]などのデータを渡したいのですがどうすればいいのかわからず困っております。子フォームから親フォームへテキストボックスなどの値を渡す方法などはわかったのですが、それをどう応用していいのかもわからない状況です。最終的には親フォームのbmp[0]におけるred[0]が1(画像処理されている)なら子フォームでbmp[0]を表示させたいと思っています。わかる方がいましたらどうかご教授ください。よろしくお願いします。以下がプログラムとなっております。 *** 親フォーム *** #pragma once #include "pic2.h" namespace pic { using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; using namespace System::IO; // 省略 // public ref class Form1 : public System::Windows::Forms::Form { public: Form1(void) { InitializeComponent(); // //TODO: ここにコンストラクタ コードを追加します // bmp = nullptr; Array::Resize( bmp, 20 ); Array::Resize( picture, 20 ); Array::Resize( bmpr, 20 ); this->red = gcnew array<int>(20); } // 省略 // private: System::Windows::Forms::PictureBox^ pictureBox1; private:array< Bitmap^>^ bmp; // 原画像格納 // private:array< Bitmap^>^ bmpr; // 処理画像格納 // private:array< PictureBox^>^ picture; private:array< int>^ red; // 処理:1 不処理:0 // // 省略 // #pragma endregion private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) { bmp[0] = gcnew Bitmap("ファイル名",true); } private: System::Void button1_Click_1(System::Object^ sender, System::EventArgs^ e) { pic2 ^p2 = gcnew pic2(); p2->ShowDialog();     /* ボタンを押すことで新たなフォーム作成 */ } private: System::Void pictureBox1_Click(System::Object^ sender, System::EventArgs^ e) { int x,y; int w = bmpr[0]->Width; int h = bmpr[0]->Height; if(red[0] == 1){ bmp[0] = gcnew Bitmap("ファイル名",true); pictureBox1->Image = bmp[0]; red[0] = 0; return; } if(red[0] == 0){ // 画像処理 // pictureBox1->Image = bmpr[0]; red[0] = 1; } } }; *** 子フォーム *** #pragma once //#include "Form1.h" #include "pic3.h" using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; namespace pic { /// <summary> /// pic2 の概要 /// public ref class pic2 : public System::Windows::Forms::Form { public: pic2(void) { InitializeComponent(); // //TODO: ここにコンストラクタ コードを追加します // } // 省略 // } #pragma endregion private: System::Void pic2_Load(System::Object^ sender, System::EventArgs^ e) { if(親フォームのred[0]==1ならば){ pictureBox1->Image = bmp[0] } } private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {   // 新たな子フォームpic3作成 // } private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) { this->Close(); } }; }

  • [VC++]ヘッダファイルからの関数コール

    Formのボタンクリックイベント(Form.h)から 別ファイル(.cpp)の関数をコールしたいのですがうまくいきません、 どのようにすればよいでしょうか?ご教授お願いします。 1> : error C2144: 構文エラー : 'void' は ')' によって先行されなければなりません。 1> : error C2059: 構文エラー : ')' //----- main1.h #include <stdio.h> #include "Form1.h" namespace A { void main1(); } //----- main1.cpp #include <stdio.h> #include "main1.h" using namespace A; void main1() { //処理 } //----- Form1.h #include <stdio.h> #include "main1.h" void main1(void); namespace A { public ref class Form1 : public System::Windows::Forms::Form { public: private: System::Void btn_Click(System::Object^ sender, System::EventArgs^ e) { //★クリックイベントからmain1の関数コールしたい main1(void); } }; }

  • Visual c# スレッド

    プログラム初心者です。 Visual c#にてスレッド関数を使ったプログラムを見よう見まねで 作りました。 スタートボタンを押すとピクチャーボックスの位置が 左から右へ移動し、ストップボタンを押すと止まる。 ピクチャーボックスの位置をテキストボックスに表示する。 というプログラムのつもりです。 デバックの状態でスタートボタンを押すとエラーメッセージが出て テキストボックスに位置を書き込むの関数のところが緑色にハイライトされます。エラーの内容は「有効でないスレッド間の操作」とありますが、どうしたら良いのか分かりません。 エラーの直し方を教えてください。 プログラムコードは以下です。 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Threading; namespace bit_map_08._1._ { public partial class Form1 : Form { private Thread thread; static private int Position = 0; static private int i; static bool BtnOnFig; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { thread = new System.Threading.Thread(newSystem.Threading.ThreadStart(MainThread)); thread.Start(); } private void PointMove() { if (i < 300) { i = i + 1; Position = Position + i; textBox1.Text = Convert.ToString(Position); pictureBox1.Left = (Position); } if (i == 300) { i = 0; } } private void MainThread() { while( true ) { Thread.Sleep(100); if (BtnOnFig == true) { PointMove(); } } } private void button1_Click(object sender, EventArgs e) { BtnOnFig = true; } private void button2_Click(object sender, EventArgs e) { BtnOnFig = false; } } }

  • フォームを閉じる方法

    VC#2008ExpressEditionを使用して仕事で使う在庫管理ソフトを作成しています。 まず、ウェルカムページが開いて、その後認証ページが開くように作っていますが、認証ページが開いたのと同時にウェルカムページを閉じたいのですが、閉じることが出来ません。どなたか教えて下さい。 ウェルカムページのコーディング using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace zaiko { public partial class welcomeForm : Form { public welcomeForm() { InitializeComponent(); } private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { Form mainForm = new mainForm(); mainForm.Show(); } } } 認証ページのコーディング using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace zaiko { public partial class mainForm : Form { public mainForm() { InitializeComponent(); } private void mainForm_Load(object sender, EventArgs e) { Form welcomeForm = new Form(); welcomeForm.Close(); } } }

  • VC++メッセージの送受信について教えてください。

    VC++でソフトを作成しています。 初心者なのでわからないことだらけです。 どなたかご教授お願いします。 ■環境 Windows xp mode Visual Studio 2010 Professional VC++ フォームアプリケーション .net Framework4.0 ■相談内容 アプリ1のtextBoxに入力された文字列をアプリ2に送信して、アプリ2のtextBoxに表示させたいのですが、PostMessageを使用するとメッセージが送れません。 また、SendMessageを使用すると送れますが、共有メモリを使用すると文字列が途中で途切れてしまいます。 PostMessageと共有メモリの使用は指令なのではずせません。 理由は送信側のアプリがロックされるのを防ぐため、後に多数のアプリから送信した文字列を取得できるようにするためです。 下記にソースコードを記載しますので、どこが悪いのか、何が原因でそうなるのか、どうすれば正常に動作するようにできるのかを教えてください。 特に、ソースについてはどこをどのように直せば良いかを教えていただけるとありがたいです。 ~送信側ソース~ #pragma once #include<windows.h> #include<iostream> #include<fstream> #include<string> #include<msclr/marshal.h> #pragma comment(lib,"user32.lib") int s; using namespace std; using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; using namespace System::Runtime::InteropServices; using namespace msclr::interop; [DllImport("user32.dll") ] extern System::String^ FindWindow(String^ lpClassName, String^ lpWindowName); [DllImport("user32.dll")] extern System::String^ PostMessage(HWND hWnd, int Msg, int wParam, int lParam); public: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { System::String^ moji_textBox4; moji_textBox4=textBox4->Text; s=textBox4->Text->Length+1; COPYDATASTRUCT cd; HWND hWnd; char buffer[500]; sprintf_s(&buffer[0],5,"%s",moji_textBox4); cd.dwData=0; cd.cbData=s;//strlen(buffer)+1; cd.lpData=buffer; hWnd=::FindWindow(nullptr,L"アプリ2"); ::PostMessage((HWND)hWnd,WM_COPYDATA,0,(LPARAM)&cd); ~受信側ソース~ #pragma once #pragma comment(lib,"user32.lib") #include<ctype.h> #include<windows.h> #include<msclr/marshal.h> using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; using namespace System::Runtime::InteropServices; using namespace msclr::interop; public: virtual void WndProc(System::Windows::Forms::Message% msg) override { if(msg.Msg== WM_COPYDATA) { COPYDATASTRUCT *cd; cd=(COPYDATASTRUCT *)msg.LParam.ToInt32(); System::String^ str; str=gcnew System::String((char *)cd->lpData); pin_ptr<const wchar_t>pstr=PtrToStringChars(str); System::String^ ShareMemoryName1=L"Information"; HANDLE hmap; char *pmap; marshal_context^ context= gcnew marshal_context; LPCTSTR ShareMemoryName2 = context->marshal_as<LPCTSTR>(ShareMemoryName1); hmap=::CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE,0,2048, (LPCTSTR)ShareMemoryName2); pmap=(char *)::MapViewOfFile(hmap,FILE_MAP_ALL_ACCESS,0,0,1024); System::String^ pstr1= gcnew System::String(pstr); ZeroMemory(pmap,2048); memcpy_s(pmap,2048,pstr,sizeof(pstr)); System::String^ str1; str1= gcnew System::String((char *)pmap); textBox6->Text=str1; UnmapViewOfFile(pmap); CloseHandle(hmap); } Form::WndProc(msg); }

  • C#で処理中の状況をStatusLabelに表示

    C#で処理中の状況をStatusLabelに表示させたいのですが、どうやらマルチスレッドを使えば良いらしい事は分かったのですが、説明しているページを参考にいろいろやってみたのですがどうもうまくいきません。 例えば次のような場合、10秒後に”9”と表示されて終わってしまうのですが、どの様に書き直せばよろしいでしょうか? すみません、どなたかご存じの方教えていただけないでしょうか。 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Threading; namespace test_multithread3 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { for (int i = 0; i < 10; i++) { toolStripStatusLabel1.Text = i.ToString(); Thread.Sleep(1000); } } } }

  • C言語について質問・・・

    柴田望洋氏の著書である明解C言語(入門編)をもとに visual C++を使ってC言語の勉強をしているのですが まず最初に15+37の計算をしようと書いてあり、とりあえず わからない文法だらけだと思うが、下の通りそのまま入力してみよう と書いてあるのですが、その文章をそのまま入力してみたところ いきなりビルドエラーがでてきました。 ↓が実際の文章です。 /* 整数値15と37の和を表示する */ #include <stdio.h> int main(void) { printf("%d",15+37); /*整数値15と37の和を10進数で表示*/ return(0); } ※本書そのままを入力しており、全角半角のミスはないと思います。 しかし、実際新しいプロジェクトを作り立ち上げた瞬間に意味の分からない 文字の羅列が出てきてそのあとに上の文章を書いてあります。 ↓がその文章 #pragma once namespace lesson01 { 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 の概要 /// </summary> public ref class Form1 : public System::Windows::Forms::Form { public: Form1(void) { InitializeComponent(); // //TODO: ここにコンストラクター コードを追加します // } protected: /// <summary> /// 使用中のリソースをすべてクリーンアップします。 /// </summary> ~Form1() { if (components) { delete components; } } private: /// <summary> /// 必要なデザイナー変数です。 /// </summary> System::ComponentModel::Container ^components; #pragma region Windows Form Designer generated code /// <summary> /// デザイナー サポートに必要なメソッドです。このメソッドの内容を /// コード エディターで変更しないでください。 /// </summary> void InitializeComponent(void) { this->SuspendLayout(); // // Form1 // this->AutoScaleDimensions = System::Drawing::SizeF(6, 12); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; this->ClientSize = System::Drawing::Size(284, 262); this->Name = L"Form1"; this->Text = L"Form1"; this->Load += gcnew System::EventHandler(this, &Form1::Form1_Load); this->ResumeLayout(false); } #pragma endregion private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) { } }; } /* 整数値15と37の和を表示する */ #include <stdio.h> int main(void) { printf("%d",15+37); /*整数値15と37の和を10進数で表示*/ return(0); } となっております。 ※lesson01はプロジェクト名です。 ビルドエラーは 1>------ ビルド開始: プロジェクト: lesson01, 構成: Debug Win32 ------ 1> lesson01.cpp 1>lesson01.cpp(10): error C2731: 'main' : 関数はオーバーロードできません。 1> lesson01.cpp(9) : 'main' の宣言を確認してください。 ========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ========== 保存先はwindows フォームアプリケーションを選び保存しています

専門家に質問してみよう