// サブスレッドサンプル // (C)2003 Yutaka Wada, AirparkLab // ユーザメッセージ定義 #define USER_MESSAGE_FROM_SUBTHREAD (WM_APP+100) // サブスレッドからのメッセージ #define SUBTHREAD_STATUS_CONTINUE 0 // サブスレッドステータス 実行中 #define SUBTHREAD_STATUS_DONE 1 // サブスレッドステータス 終了 #define SUBTHREAD_STATUS_CANCEL 2 // サブスレッドステータス キャンセル // サブスレッドコントロール構造体の定義と確保 struct SUBTHREAD_CTRL { BOOL bEnable; // サブスレッドの動作コントロールフラグ HWND ReceiveHandle; // サブスレッドからのメッセージを受け取るメインスレッドのウインドウハンドル } SubThreadCtrl; // サブスレッド関数プロトタイプ宣言 UINT SubThreadFunction( LPVOID pParam ); // サブスレッド関数定義 UINT SubThreadFunction( LPVOID pParam ) { char szMessage[MAX_PATH]; SUBTHREAD_CTRL *pCtrl = (SUBTHREAD_CTRL *)pParam; // サブスレッド処理のループ for( int i=0; i<1000; i++ ){ // メインスレッドからのキャンセル要求があれば処理中止 if( pCtrl->bEnable == FALSE ){ // キャンセルメッセージ送信 SendMessage( pCtrl->ReceiveHandle, USER_MESSAGE_FROM_SUBTHREAD, (WPARAM)SUBTHREAD_STATUS_CANCEL, (LPARAM)"キャンセル" ); // サブスレッドの動作中止 return( SUBTHREAD_STATUS_CANCEL ); } // サブスレッド処理中メッセージ送信 sprintf( szMessage, "サブスレッド処理中... [%d/1000]", i ); SendMessage( pCtrl->ReceiveHandle, USER_MESSAGE_FROM_SUBTHREAD, (WPARAM)SUBTHREAD_STATUS_CONTINUE, (LPARAM)szMessage ); // サブスレッドはメインスレッドとメモリ空間を共有し、かつ受信相手がメッセージを受信処理を終了するまで戻ってこないので、 // 上記ローカル変数のアドレスszMessageをSendMessageの引数に使うことができる。 } // サブスレッド処理終了メッセージ送信 sprintf( szMessage, "サブスレッド処理終了." ); SendMessage( pCtrl->ReceiveHandle, USER_MESSAGE_FROM_SUBTHREAD, (WPARAM)SUBTHREAD_STATUS_DONE, (LPARAM)szMessage ); // サブスレッド終了 return( SUBTHREAD_STATUS_DONE ); } ///////////////////////////////////////////////////////////////////////////// // サブスレッドを開始するボタン(コントロール変数m_Button)とサブスレッドからの // メッセージを表示するエディットボックス(コントロール変数m_Edit)を実装する。 // サブスレッド開始ボタン 押下ハンドラ void CTmpDlg::OnButton() { // サブスレッド実行中にこのボタンを押されたときはキャンセルする if( SubThreadCtrl.bEnable == TRUE ){ SubThreadCtrl.bEnable = FALSE; // サブスレッドにキャンセルを通知 m_Button.EnableWindow( FALSE ); // サブスレッドが完全に終了するまでこのボタンを無効にする return; } // サブスレッド停止中は再開処理を行う else { m_Button.SetWindowText( "キャンセル" ); // このボタンをキャンセルボタンにする SubThreadCtrl.bEnable = TRUE; // サブスレッドコントロールフラグをセット SubThreadCtrl.ReceiveHandle = this->GetSafeHwnd(); // メッセージ受信ハンドルをセット AfxBeginThread( (AFX_THREADPROC)SubThreadFunction, (LPVOID)&SubThreadCtrl ); // サブスレッド開始 } } // サブスレッドからのメッセージ受信ハンドラ LRESULT CTmpDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { // サブスレッドからのメッセージ if( message == USER_MESSAGE_FROM_SUBTHREAD ){ // 処理中メッセージの場合 if( wParam == SUBTHREAD_STATUS_CONTINUE ){ // エディットボックスにメッセージを表示 m_Edit.SetWindowText( (char *)lParam ); } // 処理終了またはキャンセルの場合 else if( wParam == SUBTHREAD_STATUS_DONE || wParam == SUBTHREAD_STATUS_CANCEL ){ // 次のファイルボタンのキャンセルを元に戻して有効にする m_Button.SetWindowText( "開始" ); m_Button.EnableWindow( TRUE ); // エディットボックスにメッセージを表示 m_Edit.SetWindowText( (char *)lParam ); // サブスレッドコントロールフラグをリセット SubThreadCtrl.bEnable = FALSE; } } return CDialog::WindowProc(message, wParam, lParam); }