C# スレッドから親ウィンドウへの通知の方法は?

このQ&Aのポイント
  • C#のスレッドから親ウィンドウへの通知方法について知りたいです。
  • PostMessageの代替方法としてBeginInvokeを使用する方法について詳しく教えてください。
  • 具体的な例を交えて、BeginInvokeを使用した子クラスの状態を親ウィンドウへ通知する方法について教えてください。
回答を見る
  • ベストアンサー

C# PostMessage BeginInvok

お世話になります。 「C# スレッドから親ウィンドウへの通知の方法は?」というタイトルで、 PostMessageの代替方法について質問させていただいた者です。 その後ウェブにていろいろと調べて見ると、 「C++ の PostMessage、C# では BeginInvoke」のような記述を所々で見かけます。 しかし、どのようにすれば、BeginInvoke を PostMessage の代わりに使えるのか、 よく分かりませんでした。 ご存知の方、具体的な例をご提示願えませんでしょうか。 どうかよろしくお願いします。 以下は自分なりに、こんなカンジ?と作ってみたものです。 これでも子クラスの状態を親ウィンドウへ通知できるのですが...。 namespace DeviceControler {   delegate void InformState(int msg);   public partial class MainForm : Form ---(A)   {     InformState InformChildState {get; set;}     DTLink DtLink {get; set;}     public MainForm()     {       InformChildState = new InformState(ChildStateChanged); ---(B)       DtLink = null;     }     private void MainForm_Load(object sender, EventArgs e)     {       DtLink = new DTLink(); ---(C)       DtLink.InformChildState = InformChildState; ---(D)       DtLink.Start(); ---(E)     }     private void ChildStateChanged(int msg) ---(F)     {              // (G)から状態値が渡されるので、値に応じて処理を行う       switch (msg) {       case ...              }     }   }   class DTLink  ---(G) == (C)の本体   {     public InformState InformChildState;     public void Start(int activeFAPanel = FAPanel.main)     {       InformChildState.BeginInvoke(状態値, null, null); ---(H)     }   } } (A) はウィンドウフォームです (B) で (F) の delegate を作り、 (C) で 子クラスを作り、 (D)で (C) のクラスに (B) を渡し、 (E) で (C) の中身を起動し(処理は省略です)、 (H) で (F) を呼び出しています。 これにより、(G)の状態を、(A)に通知しています。 (H) はここだけでなく、(G) のクラスの中で様々な処理を行う度に、必要に応じ て呼び出します。

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

  • ベストアンサー
noname#251971
noname#251971
回答No.3

昔に比べてムツカシとのことですが、、、、、 自分もMFCを利用していた時もありましたし、フレームワークを使わずにネイティブなC言語/Win32API環境でコードを書いていた時もありましたが、それらに比べてC#でのマルチスレッドの実現はかなり簡単になっていると思っています。 きっちりしたアプリを作る場合には、だいたいは非同期処理の部分に進捗表示と処理のキャンセルのUIを持たせる必要が出てくると思います。(PostMessageによるメッセージング機構を引き合いに出されていたのもそういう関連からかと思います) No.2の回答でBackgroundWorkerを推したのは、MSDNのリファレンスページでも書かれていますがBackgroundWorkerがUI連携を前提とした設計のクラスですので、そこから入るのが良いかと思ってのことです。 話が広がり過ぎるかと思い書きませんでしたが、C#で非同期処理を実現する方法は多数の選択肢があって、シンプルに作るならばたとえば以下のような形もあります。これは結構書きやすいと思います。 (1つのスレッドだけの例ですが、複数あっても大したことは無いと思います。) PostMessageは通知とUIスレッド側へのコンテキストスイッチの2つの機能を備えたものと言えると思いますが、別に1操作でそれを行えないと実現できないことがあると言うわけでもありませんので、スレッドではイベントを単に通知して、利用側(UI操作が必要な側)が自分の都合でUIにコンテキストを移すという感じです。 こう分離しておくと、非同期処理側がUIを全く意識しなくてよくて、UIフレームワークを別のものに変えたとしても非同期処理に変更の必要がないというような利点もありますね。 class AsyncWorker { public event Action Started; public event Action Finished; public void Start() { ThreadPool.QueueUserWorkItem(_ => run()); } private void run() { this.Started(); // 何かの処理 this.Finished(); } } private void button_click() { // 非同期処理クラスをのイベントをハンドルして非同期処理開始。 // 利用側でUIへ処理委譲 var asyncWork = new AsyncWorker(); asyncWork.Started += () => this.BeginInvoke(new MethodInvoker(beginAsync)); asyncWork.Finished += () => this.BeginInvoke(new MethodInvoker(beginAsync)); asyncWork.Start(); } private void beginAsync() { // 開始時UI変更など } private void endAsync() { // 終了時UI変更など } 非同期処理の終了待機については、(ここでは途中の進捗通知やキャンセルサポートなをとりあえず置いておくとして)以下のようにすることも出来ますね。 private void Start() { ThreadPool.QueueUserWorkItem(_ => { // 複数の非同期処理を開始して全部が終了するのを待つ var exitEvents = Enumerable.Range(0, 3).Select(n => new ManualResetEvent(false)).ToArray(); foreach (var evt in exitEvents) { ThreadPool.QueueUserWorkItem(__ => { // なんらかの非同期処理 // 終了フラグのイベントをシグナル化 evt.Set(); }); } WaitHandle.WaitAll(exitEvents); this.BeginInvoke(new MethodInvoker(onEnd)); }); } private void onEnd() { // 全部終わった後の処理 } もっとも、これはC#としては少々古い書き方で、現在であれば並列処理ライブラリなどが充実しているのでたとえば上記の複数実行&待機と同じことが以下で出来ますが。 Parallel.For(0, 2, (num) => { // なんらかの非同期処理 }); 他にも一部のデータ処理の一部だけ並列化したい場合はPLINQで以下のような形とか。 // URLのリストがあるとして var urlList = new List<Uri>(); // 同時に最大10個までを非同期ダウンロードして var downloadData = urlList.AsParallel() .WithDegreeOfParallelism(10) .Select(url => { using (var webClient = new WebClient()) { return webClient.DownloadString(url); } }); // ダウンロード出来たものから何らかの処理をする、など。 foreach (var data in downloadData) { // データを処理 } 手段はいろいろありますので順に全てを学んで、C#のガベージコレクションやラムダ式によるクロージャなんかは非同期処理とも相性が良いので、そのあたりも組み合わせて必要な所に必要なものを利用するようにすれば、結構簡単に目的を実現できたりすると思います。 (私のの場合は、簡単なツールを作るぐらいの場合であればNo.2の回答に示したURL先にも書いたように、1メソッド内で開始のUI変更と終了のUI変更を閉じ込めてしまうさらっとした書き方をよくしますね。)

seekh0n875
質問者

お礼

toras9000 さん 再度回答をくださってありがとうございます。 書いてくださったコードを真剣に読みました。 大変々々勉強になりました。 昔MFCをかじっていた頃は、並行処理の開始は beginthread、排他はセマフォ、これだけでした。 (単に私が他の手法を知らなかっただけだとは思いますが。) それに比べると、今はマルチタスクの実現方法が多様で、 また、C#のVer.が上がる毎に新しい機能が追加されたりもするので、 普段から開発業務に携わっているわけではない者にとっては、 たまの機会で目的に応じた手法を選択して学習するのがなかなか大変です。 しかし、前の質問でのBackgroundWorkerもそうなのですが、 こうやって教えていただいて、知らないことを理解するのはとても楽しいことに感じます。 今回もとても参考になりました。 やりたいことが実現できそうです。 どうもありがとうございました。

その他の回答 (2)

noname#251971
noname#251971
回答No.2

まずこの質問項目に対する回答事項ですが、 「BeginInvoke」メソッドは複数クラスが持っており、どちらも非同期でのメソッド実行を行う目的のものではありますが、デリゲートが持つものとControlクラス(およびその派生クラス。Formクラスなども)が持つものとで意味が異なります。 デリゲートが持つものは単に別スレッドからデリゲートを呼び出すもので、動作としては以下のコードとほとんど同じです。 (BeginInvokeをしたら、EndInvokeで非同期呼び出しの待機&完了を行わなければならないという違いはありますが)  ThreadPool.QueueUserWorkItem(state => InformChildState(状態)); Controlクラスが持つものは指定した処理がControlを作成したスレッド(通常はメインスレッド)にキューイングされて実行されるということになります。 これはまさしくPostMessageと同じ動作であり、Windowsの場合は内部実装的にもPostMessageを利用しているはずです。 こちらは、主な目的としてはControl派生クラスのUI要素類がスレッドセーフでは無いので、別スレッドからUI更新が必要な場合にUIスレッド側に処理を委譲するために利用します。 定義したメソッドを引数にするほか、ラムダ式を使ってインスタントな処理を書くことも可能です。 # 単純な1本の非同期処理を行う場合であれば、こちらなども参考にどうぞ。 # http://okwave.jp/qa/q8331278.html ただ、以前に投稿された質問にある複数のスレッドからの通知のようなものの場合、 各スレッドから直接BeginInvokeを利用するというよりは、 前の質問の回答者さんが書かれているBackgroundWorkerの対応がほぼ完璧な回答かと思いますので その方向の対応方法を学んでいくのが良いかと思います。 # プログラミングのプラットフォームが変われば、手法も変わってきますので、 # 無理にほかのプラットフォームでのやり方を再現するような必要は無いかとおもいます。

seekh0n875
質問者

お礼

詳しい内容をありがとうございます。 マルチスレッドの実現が、昔に比べてムツカシくなったなあ、という感想です。 まあ、正直、昔も「かじった」程度ではあったのですが...。 前に回答いただいた内容を勉強してみます。 ありがとうございました。

回答No.1

「C# デリゲート」で検索してください。 例えば http://ufcpp.net/study/csharp/sp_delegate.html デリゲートを使って子スレッドから親スレッドにイベントを渡します。

seekh0n875
質問者

お礼

回答をありがとうございます。   リンク先拝見しました。 このサイト、別のページですが、時々見てました。   経験不足で読解力に自信がないのですが、 なんとなく私の理解(サンプルとして載せたもの)で、 まあまあ合っていそうな...。 (だとすると、それはそれでまた疑問もあるのですが。)   もう少し理解に努めます。 ありがとうございました。

関連するQ&A

  • C# 子->親の通知にBeginInvokeすると

    親クラスウィンドウのボタンを押すと子クラスを作成して実行し、 子クラスは処理の経過や結果を親クラスに通知する、 というような処理をするために、下のようなコードを書きました。 (主要な部分のみの抜粋です。) 子クラスでは、親クラスへの通知後も引き続いて処理できるよう、 親クラスに対して非同期で通知したいため、 BeginInvoke を使用することにしました。 実行すると、「★A★」で親クラスに通知を実行した際、 ・「★B★」は本来モーダルのはずが裏に回ってしまう ・「★C★」ではクロススレッド呼び出し方法の例外が発生 という問題が生じます。 BeginInvokeするとUIスレッドとは別のスレッドとしてChildEnventReceivedが呼ばれるためと解釈しています。(ほんとかな。) こういったことをしたい場合、どうするのが普通でしょう? 下のコード自体はだいたい合っていて、 コントロールの操作は例えば「★C★」ではbtn.Invoke()するのが普通でしょうか? とすると、そのためのdelegateやメッソドを定義しなければならず、 煩雑になりますね。 C++のPostMessageのようなことがやりたいだけなのですが。 C#は最近取り組み始めたばかりで、勉強中です。 普通はこうする、というような処理をご教授いただければ幸いです。 よろしくお願いします。 ================================================ // 子クラスからの通知イベント delegate void EventHandler(); public Parent {   EventHandler handler;   private void btn_Click(object sender, EventArgs e)   {     btn.Enabled = false;     handler = new EventHandler(ChildEventReceived);     Child child = new Child();     child.SendEvent += hander;     child.Exec();   }   void ChildEnventReceived();     MessageBox.Show("Child State Received");     ★B★このメッセージボックスが裏に隠れてしまう★B★     btn.Enabled = true;     ★C★この操作は「有効でないスレッド間の操作」となる★C★   } } class Child {   public event EventHandler SendEvent;   public void Exec()   {     ★A★ここで親に対して通知する★A★     SendEvent.BeginInvoke(null, null);   } } ================================================

  • 下記のc言語のプログラム(LU分解を用いた連立一次方程式)を起動させた

    下記のc言語のプログラム(LU分解を用いた連立一次方程式)を起動させたいのですがエラーがでてしまいます。 どのようにしたら動作しますか? #include <stdio.h> #include <stdlib.h> #include <float.h> #define MAX_DIM 10 #define MIN_DIM 1 int get_dimension(int, int); double *get_matrix( int ); double *get_vector( int ); void set_matrix( int, double* ); void set_vector( int, double* ); void LU( int, double*, double*, double* ); void L_equ( int, double*, double*, double* ); void U_equ( int, double*, double*, double* ); void pr_vector( int, double* ); void matrixcpy( int, double*, double* ); void make_I( int, double* ); void main( void ) { int n , i ; double *A, *b ; double *L, *U ; double *c, *x ; n = get_dimension( MAX_DIM, MIN_DIM ); if( ( A = get_matrix( n ) ) == (double *) NULL || ( L = get_matrix( n ) ) == (double *) NULL || ( U = get_matrix( n ) ) == (double *) NULL || ( b = get_vector( n ) ) == (double *) NULL || ( c = get_vector( n ) ) == (double *) NULL || ( x = get_vector( n ) ) == (double *) NULL ) { fprintf( stderr, "メモリ所得エラーです!!\n" ); } else { set_matrix( n, A ); set_vector( n, b ); LU( n, A, L, U ); L_equ( n, L, c, b ); U_equ( n, U, x, c ); printf( "解は、" ) ; pr_vector( n, x ) ; } }

  • C++ GUIのメッセージループ。

    初心者です。 よろしくお願いします。 とても重く時間の掛かる処理を色んなサイトを参考にスレッドにしてみたんですけど、書き方が悪いのか、再描写がワンテンポ遅れたり、アプリケーションを複数起動したりするとフリーズしてしまったりします。 原因はメッセージループにあるような気がしてるんですが、この書き方はおかしいですか?? どのサイトから引用したのかわからなくなってしまいました。 気付いたことなどあったら何でもいいので教えて貰えたら嬉しいです!よろしくお願いします!! thread01に重い処理が書かれてます。 int thread_call() {   unsigned int dwThreadId[1];   HANDLE hThread[0] = (HANDLE)_beginthreadex(     NULL,     0,     ( unsigned int (__stdcall*)(void*) )thread01,     NULL,     0,     &dwThreadId[0] );   MSG msg;   DWORD dwRet = WAIT_TIMEOUT;   while ( 1 ) {     dwRet = ::MsgWaitForMultipleObjects( sL, hThread, FALSE, INFINITE, QS_ALLEVENTS );     if ( dwRet == WAIT_OBJECT_0 + sL ) {       if ( ::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) {         ::TranslateMessage( &msg );         ::DispatchMessage( &msg );       }     } else if ( dwRet >= WAIT_OBJECT_0 && dwRet < WAIT_OBJECT_0 + sL )       break;   }   CloseHandle( hThread[0] );   hThread[0] = NULL; }

  • C フォームから受け取った知をクッキーで発行 2

    前回 http://okwave.jp/qa/q7765400.html からあれこれしてフォームの値をクッキーに保存できるようになったのですが、バグが出てきました。 一、クッキーが存在しないとエラーが出る ニ、Deta1関数を使って文字列の分解を試みるもうまく分解されない この2つのバグを解決するにはどうしたら直せますか? ---以下ソース--- #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> char *nameset[2],*valueset[2]; char *nameset2[2],*valueset2[2]; int Deta1(char *a,int b); int Dcd(char *set,int a); void get_Form(void); void get_cookie(void); void set_cookie(void); int hen(char *buf, char *mae, char *ato); void Page(int mode); int main(void) { char *nameset[2],*valueset[2]; char *nameset2[2],*valueset2[2]; printf("Content-type: text/html\n"); get_Form(); set_cookie(); get_cookie(); printf("\n"); Page(0); } int Deta1(char *a,int b){ int i=0,cn=0; if(a[0]==NULL){ return(-1); } nameset[0]=a; while((a[++i]!=NULL)&&(i<b)){ /* 項目の分解 */ if(a[i]=='='){ a[i]=NULL; valueset[cn]=a+i+1; } /* データ項目で分解 */ else if(a[i]=='&'){ a[i]=NULL; cn++; nameset[cn]=a+i+1; } } return cn+1; } int Dcd(char *set,int a){ int i,j; char buf,*tmp; if(a==0){ return -1; } tmp=(char*)malloc(a); for(i=0,j=0;i<a;i++,j++){ if(set[i]=='+'){tmp[j]=' ';continue;} if(set[i]!='%'){tmp[j]=set[i];continue;} if(set[++i]>='A'){buf=set[i]-'A'+10;} else{buf=set[i]-'0';} buf*=16; if(set[++i]>='A'){buf+=set[i]-'A'+10;} else{buf+=set[i]-'0';} tmp[j]=buf; } for(i=0;i<j;i++){ set[i]=tmp[i]; } set[i]='\0'; free(tmp); return 0; } void get_Form(void){ int a=0; int i=0; char *chr=NULL; if ( getenv("CONTENT_LENGTH")!=NULL ){ a = atoi( getenv("CONTENT_LENGTH") ); } chr=(char *)malloc(a+1); scanf("%s",chr); chr[a] = '\0'; if (a==0){ return ; } int deta1=Deta1(chr,a); } void get_cookie(void){ int i=0,cn=0; int a=NULL; char *b; if( (getenv("HTTP_COOKIE"))!=NULL){ a=strlen(getenv("HTTP_COOKIE")); } if(a==NULL){ } b=getenv("HTTP_COOKIE"); while((b[++i]!=NULL)&&(i<a)){ if(b[i]=='='){ b[i]=NULL; nameset2[0]=b+i+1; } /* 項目の分解*/ if(b[i]=='-'){ b[i]=NULL; valueset2[cn]=b+i+1; } /*データ項目で分解*/ else if(b[i]=='&'){ b[i]=NULL; cn++; nameset2[cn]=b+i+1; } } for(i=0;i<cn+1;i++){ Dcd(nameset2[i],strlen(nameset2[i])); Dcd(valueset2[i],strlen(valueset2[i])); } } void set_cookie(void) { time_t timer; struct tm *tset; char expires[256]; char *name="sskchat"; int kikan=86400*90; char *set[2]; int i; for(i=0;i<2;i++){ set[i]=NULL; } for(i=0;i<2;i++){ set[i]=valueset[i]; } for(i=0;i<2;i++){ if(set[i]==NULL){ set[i]="no"; } } timer = time(NULL); timer += kikan; tset = gmtime(&timer); strftime(expires, 255, "%a, %d-%b-%Y %H:%M:%S GMT", tset); printf("Set-Cookie:%s=name-%s&mail-%s; expires=%s;\n",name,set[0],set[1],expires); } void Page(int mode){ FILE *fp; char *f1="!name!",*h1; char *f2="!mail!",*h2; if(valueset2[0]==NULL||strcmp("!name!",valueset2[0])==0){ h1=""; } else{ h1=valueset2[0]; } if(valueset2[1]==NULL||strcmp("!mail!",valueset2[1])==0){ h2=""; } else{ h2=valueset2[1]; } char buf[200]; char set[200]; fp = fopen("ren.html", "r+"); while( fgets( set, 200, fp ) != NULL ){ strcpy(buf,set); while(hen(buf, f1, h1)); while(hen(buf, f2, h2)); printf("%s", buf); } fclose(fp); } int hen(char *buf, char *mae, char *ato){ char *nw; size_t zen,go; zen = strlen(mae); go = strlen(ato); if(zen == 0 || (nw = strstr(buf, mae)) == NULL){ return 0; } memmove(nw + go, nw + zen, strlen(buf) - (nw + zen - buf ) + 1); memcpy(nw, ato, go); return 1; } ---ソースここまで--- ---ren.htmlの内容--- <form action="first.exe" method="post"> 名前:<input type="text" name="name" size="100" value="!name!"><br><br> メール:<input type="text" name="mail" size="100" value="!mail!"><br><br> 本文:<textarea name="text" cols="70" rows="10"></textarea><br><br> <input type="submit" value=" 送 信 "><br> </form>

    • ベストアンサー
    • CGI
  • C#クラスについて教えてください

    下記通りクラスを作成した場合、プロパティaを配列にできますか? class Class1 { public string a { set; get; } public int b { set; get; } public int c { set; get; } } イメージとしては下記通りにしたいのですが、なかなかうまく行きません。 class Class1 { public Class1(int x) { } public string a[x] { set; get; } public int b { set; get; } public int c { set; get; } } private void Form1_Load(object sender, EventArgs e) { Class1 f = new Class1(2); f.a[0] = "asdf"; f.a[1] = "asdfa"; f.a[2] = "asdfasd"; f.b = 1; f.c = 2; } 初心者なんで、やさしく教えてください。お願いします。

  • cではよくてc++ではダメな理由

    #include <stdio.h> #include <stdlib.h> int main(void) { int *x; x = calloc(1, sizeof(int)); if (x == NULL) puts("記憶域の確保に失敗しました。"); else{ *x = 57; printf("*x = %d\n", *x); free(x); } return 0; } 上のソースなのですがcallocの戻り値がvoidなのでintにはキャストしてくれみたいなことを コンパイラに言われます。 cではコンパイルできてc++ではコンパイルできないのはなぜでしょう。

  • C# プロパティのスコープ/寿命について

    たびたびすみません。 いつもありがとうございます。 C#でウィンドウアプリケーションを作成しています。 今回下のような TestClass クラスを作りました。 TestClass クラスの中に Paths プロパティを持っているのですが、 このプロパティは、コンストラクタの一番下に到達した時点で開放されています。 プロパティのスコープってそういうものでしょうか。 この TestClass クラスは上位で new されてインスタンスが作成されていますが、 このインスタンスが存在する間はデータが保持されると思っていたのです。 逆に、インスタンスが存在する間、そのクラス内で値を保持するには、どうするのでしょうか? よろしくお願い致します。 public partial class MainForm : Form {   // プロパティ   TestClass Test {get; set;}   private void MainForm_Load(object sender, EventArgs e)   {     Test = new TestClass();   } } class TestClass() {   // プロパティ   string[] Paths {get; set;}   // コンストラクタ   // Dirクラスには、複数のディレクトリ情報が格納されている   public TestClass(Dir[] dirs)   {     try {       string[] TagPaths = new string[Const.MaxNum.tag];       // Dirクラスのディレクトリ情報のうち、パスを取り出す       for (int i = 0; i < n; i++) {         Paths[i] = dirs[i].Path;       }       // 某処理       ActiveFAPanel = SetupXXX(Paths);     }     catch(Exception ex)     {     }   } ←●●●● ここに来た時点でPathsはnullとなっている }

  • [Visual C++ 6.0] コンパイル(ビルド)エラー

    ※参考までに『3週間完全マスターVisual C++ 6.0 』という本の「5日目」の部分を進めていて詰まってしまいました。 ビルドすると、下記のDialogsDlg.h中の「CMsgDlg m_dMsgDlg;」の辺りに対して error C2146: 構文エラー : ';' が、識別子 'm_dMsgDlg' の前に必要です。 error C2501: 'CMsgDlg' : 識別名を宣言するのに、型が指定されていません。 error C2501: 'm_dMsgDlg' : 識別名を宣言するのに、型が指定されていません。 というエラーが出てしまいます。CMsgDlgというクラスはちゃんと作っていますし、構文的にも間違ってはいないと思うのですが、何がいけないのでしょうか? 説明が足りなければ補足します(見づらくてスミマセン)。 // DialogsDlg.h : #if !defined(AFX_DIALOGSDLG_H__4772C7E5_F2C9_4E57_99B8_EF1D44426473__INCLUDED_) #define AFX_DIALOGSDLG_H__4772C7E5_F2C9_4E57_99B8_EF1D44426473__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif class CDialogsDlg : public CDialog { public: CDialogsDlg(CWnd* pParent = NULL); enum { IDD = IDD_DIALOGS_DIALOG }; CButton m_cWhichOption; CString m_sResults; protected: virtual void DoDataExchange(CDataExchange* pDX); protected: HICON m_hIcon; //{{AFX_MSG(CDialogsDlg) virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); afx_msg void OnExit(); afx_msg void OnYesnocancel(); afx_msg void OnAbortretryignore(); afx_msg void OnFileopen(); afx_msg void OnBcustomdialog(); afx_msg void OnBwhichoption(); //}}AFX_MSG DECLARE_MESSAGE_MAP() private: CMsgDlg m_dMsgDlg; }; #endif

  • コンソールアプリケーションでのWIN32 APIメッセージ処理

    コンソールアプリケーションでのWIN32 APIメッセージ処理 VisualStdio.NET 2005のC++で作成しているコンソールアプリケーションで、 PostMessageでメッセージを送信しているのに、PeekMessageで検出できません。 下のプログラムに誤った点があるのでしょうか? 尚、ウィンドウハンドルの確認部分はパスしますが、 PostMessageとPeekMessageの引数hWndをNULLに置き換えるとメッセージの検出はできるので、 やはり、ウィンドウハンドルに問題があるのかもしれません。 #include <windows.h> #include <stdio.h> void main( void ) {   char OldTitle[1024], NewTitle[1024];   char WindowText[1024], ConsoleTitle[1024];   HWND hWnd;   MSG Msg;   /*** ウィンドウハンドルの取得 ***/   GetConsoleTitle( OldTitle, 1024 );   wsprintf( NewTitle, "%d/%d", GetTickCount(), GetCurrentProcessId());   SetConsoleTitle( NewTitle );   Sleep(40);   hWnd = FindWindow( NULL, NewTitle );   SetConsoleTitle( OldTitle );   /*** ウィンドウハンドルの確認 ***/   GetWindowText( hWnd, WindowText, 1024 );   GetConsoleTitle( ConsoleTitle, 1024 );   if ( strcmp( WindowText, ConsoleTitle ) != 0 ){     printf( "ウィンドウハンドルが不正です" );     return;   }   /*** メッセージの送信と検出 ***/   PostMessage( hWnd, 1050, 0, 0 );   do{     while ( PeekMessage( &Msg, hWnd, 0, 0, PM_REMOVE )){       printf( "メッセージを検出しました" );       return;     }   } while( 1 ); }

  • クラスのファイル分割について

    こんにちは。JavaをやっていましたがC++が必要になってC++を勉強している者です。 クラスを別のファイルに分割する際の書き方についてなのですが、 --Graph.h-- struct edge{ int to, cost; edge(int to,int cost){ this->to = to; this->cost = cost; } } class dijkstra{ public: vector<edge> *G;  ~~~  void set_graph(int N); void add_edge(int a, int b, int cost); ~~~ } ---- --Dijkstra.cpp-- void dijkstra::set_graph(int N){ G = new vector<edge>[N]; } void dijkstra::add_edge(int a,int b,int cost){ G[a].push_back(edge(b,cost)); } ---- としたとき、当方の開発環境のEclipseは「push_backの引数と合わない」といった旨のエラーを出しています。何が悪いのでしょうか。ご教授お願いします。

専門家に質問してみよう