• ベストアンサー

MFC SDIのDocからViewの関数を呼び出す方法

現在、センサから取得したデータを処理・および表示するMFC SDIベースのプログラムを作成しております。 今まではdialogベースで作っていたのですが、今回はセンサーデータをグラフにプロット表示するためにViewがあるSDIを選びました。 現在、2画面にスプリットして、左側がViewベース、右側がFormViewベースにし、センサーの取得開始などの制御ボタンを右側のFormViewへ、あたかもダイアログベースアプリのように開発しています。左側のViewへは取得されたセンサデータをプロットするようにしています。 さて、Docの中に独自スレッドを立てて、RS232C経由で定期的にセンサデータは取得できているのですが、その数値をFormViewに配置しているEditBoxに表示させたいと考えております。 Dialogベースで作っていたときは、dialog自体のポインタをAfxBeginThreadの2番目の引数(LPVOID pParam)で渡して、Thread内から該当のEditBoxの表示を切り替える関数(CEDITのSetWindowText)を呼び出していました。 今回Docの中にThreadが立っているので、FormViewのポインタをどうやって取得すべきかわかりません。FormView内では、GetDocument()でDocを取得できますが、その逆のパターンです。 CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd(); CXXXXView* pView = (CXXXXView*)pFrame->GetActiveView(); こんな感じで取得してみたのですが、Thread内からこのpViewを呼び出すとアクセス違反で落ちてしまいます。 FormViewクラス内にOnTimerを設けて、定期的にpDocに該当変数をチェックし変化があったらEditBoxに表示させるという”非同期”の方法だと実現できるのですが、なんかしっくりきません。 知識不足で根本から考え方が違うのかもしれませんが、ご教示いただければと思います。

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

  • ベストアンサー
  • titokani
  • ベストアンサー率19% (341/1726)
回答No.1

スレッドを作るときの引数として、表示させたいEditBoxのHWNDを渡すのはどうでしょうか? ちなみに、スレッド間で直接MFCオブジェクトをやりとりするのは危険です。 慎重に排他処理などを行えば可能ですが、この場合かえって面倒になるかと思います。

cortotbach
質問者

お礼

なるほど。ご指摘の通りHWNDなどを渡すことで実現することはできました。ありがとうございました。 後半のMFCオブジェクト渡しは確かに危険ですね。この点もありがとうございました。

その他の回答 (1)

回答No.2

せっかくDocumentとViewを分離しているのに、DocumentからViewを直接更新させたのでは意味がありません。 DocumentからはUpdateAllViewなどを使ってViewに対し更新が必要なことを知らせ、View側でDocumentの変更部分を描画に反映させるほうがいいと重います。

cortotbach
質問者

お礼

updateallviewにてviewに通知するのが本来のやり方ですよね。 onupdateなどをオーバーライドして実装してみます。これが一番普通にやり方ですかね。 大変参考になりました。

関連するQ&A

  • EPSON VIEW

    EPSON VIEWのデータのexportですが、EPSONVIEW上では5キロごとのデーターが表示されるのに、EXPORT するとトータル一つにまとめられてしまいます。 紙ベースと同じように詳細データーでEXPORT出来ないのでしょうか。 ※OKWAVEより補足:「EPSON社製品」についての質問です。

  • 複数のビュー表示について

    MFCプログラミングをしています。 AppWizardでMDI(SDI)アプリを作成しました。 今、1つのドキュメント(データ)に対して、 2つのビューを作らなくてはなりません。 (2つ目はOpenGL表示) フレームウィンドウを生成して Create関数のコーディングまでは、 何とか書けましたが、 実行すると、異常終了していまします。 というのも、 新しいウィンドウとドキュメント、ビューの 関連づけがされていないからだと思います。 ウィザードで作られる場合は、 フレームウィンドウとドキュメント、ビューの 関連づけはドキュメントテンプレートを 使っているようですが、 実行後に独自に作る場合は どのようにすれば良いか分からず、困り果てています。 どなたかご指導又はヒントをよろしくお願い致します。

  • MFC 分割ウィンドウのそれぞれ窓の描画に関して

    MFCプログラミング初心者ですが、宜しくお願いいたします。 ---------------プログラム環境--------------- WinXP2 Visula Studio 2005 Pro -------------------------------------------- 現在、上記の環境で、SDIプログラムを書いています。 ご教示していただきたいことは、分割ウィンドウにおけるそれぞれの窓の 表示内容を変えたいということです。TCP/IPのプログラムで、受信したMessageをstrstrなどで振り分けて、各々の窓に表示したいのですが、 どういう風にやればいいのですか?? なお、一つのViewに受信メッセージを表示させることは出来ました。 非常に困っています。 現在、CMainFrame::OnCreateClient(~~~)とMainFrame.cppに書き、 ウィンドウを3分割にしております。 m_wndSplitter.CreateStatic(this,1,2); m_wndSplitter.CreateStatic(&m_wndSplitter,2,1,WS_CHILD | WS_VISIBLE,WS_BORDER,m_wndSplitter.IdFromRowCol(0,1)); m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(??View)),~~ m_wndSplitter1.CreateView(0,0,RUNTIME_CLASS(??View)),~~ m_wndSplitter1.CreateView(1,0,RUNTIME_CLASS(??View)),~~ この用に記述しております。 説明しずらいのですが、??Viewの箇所にスケルトンの時にできていたView クラスを入れてやると、そのエリアに受信メッセージが表示されます。 初心者なので、まと外れかもしれませんが、新しいViewクラスを作成して なにかやれば、よいのでしょうか?? 現在3つのウィンドウにそれぞれの メッセージを表示させたいので、Viewクラスはそれぞれ3個なければ、いけないのでしょうか?? わかりずらい説明で申し訳ないですが、宜しくお願いいたします。

  • OnDestroy() について

    環境 WIN98 VC++6.0 MFC SDIにて アプリ起動と同時にダイアログを表示しています。 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { 略 dlg = new CInput(this); dlg->Create(IDD_DIALOG1); dlg->ShowWindow(SW_SHOW); return 0; } <質問1> このような場合に、CInputクラスに以下のようにOnDestroy()を追加しましたが、 ダイアログを閉じた時もアプリ終了時にもメッセージが飛んできません。 どうしてなのですか? void CInput::OnDestroy() { CDialog::OnDestroy(); AfxMessageBox("789"); } <質問2> 更に、以下のように新規にダイアログバーを追加したところ、メッセージが飛ぶようになりました。 どうしてなのでしょうか? int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { 略 if (!m_wndMyDialogBar.Create(this, CG_IDD_MYDIALOGBAR, WS_VISIBLE , CG_ID_VIEW_MYDIALOGBAR)) { TRACE0("Failed to create dialog bar m_wndMyDialogBar\n"); return -1; // 作成に失敗 } dlg = new CInput(this); dlg->Create(IDD_DIALOG1); dlg->ShowWindow(SW_SHOW); return 0; }

  • VC++、MFCでSDIでアプリ作成中

    現在、VC++、MFCでSDIでアプリ作成中です。 アイコン上にファイル(txtファイル)をドラッグ&ドロップしてメモ帳を起動したいです。 ただ、ドロップされたファイルはうまく読み込めるのですが、そのファイルを開く(表示)することができません。 ドロップされたファイルは、C○○View.cppで int C○○View::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; // TODO: この位置に固有の作成用コードを追加してください CStringArray argv; if( IsDropOnIcon( &argv, TRUE ) ){ int i; for( i = 0; i < argv.GetCount(); i++ ){ MessageBox( argv[ i ], "ドロップされたファイルは", MB_OK ); Read(argv[i]); } } } BOOL C○○View::IsDropOnIcon( CStringArray* argv, BOOL acceptFolder ) { CString cmdlin = ""; CString resToken; char* p; int startnum = 0; p = AfxGetApp()->m_lpCmdLine; if( strlen( p ) == 0 || p[ 0 ] == '-') return FALSE; cmdlin = p; resToken= cmdlin.Tokenize( "\"", startnum ); while( resToken != "" ){ if( resToken != " " && IsExist( resToken, acceptFolder ) ) argv->Add( resToken ); resToken= cmdlin.Tokenize( "\"", startnum ); }; return TRUE; } /* 引数で貰った文字列がファイルかどうかをチェック */ BOOL C○○View::IsExist( CString filepath, BOOL acceptFolder) { CFile fp; if( fp.Open( filepath, CFile::modeRead ) ){ fp.Close(); return TRUE; } return FALSE; } のargv[i]で取得しています。 これが、Read(arg[i])でうまく読み込めません。 ちなみにRead(CString filename)は正しく動くことは確認済みです。 Read(arg[i])を入れる場所がOnCreateがいけないとは思うのですが、どのタイミングで 読み込めばいいかがわかりません。 どなたか教えて頂けないでしょうか?

  • データシートビューからフォームビューへ切り替えられない。

    こんにちは。 以前、DexMachina様にご教授頂いたのですが 違うフォームを作っていたら データシートビューからフォームビューへ切り替えられないので教えてくださいませ。(アクセス2003) 前回質問:http://okwave.jp/qa4982081.html フォーム上(デザインビュー)にテーブルをドラッグしました。 (サブフォームのデフォルトのビューは、データシートビューになっていますが単票ビューに切り替えました。) 一度保存し、再度フォームを開くと、単票ビューで表示されるので その状態で、 Sub test() Forms("フォーム1").SetFocus Select Case Forms("フォーム1").Form.CurrentView Case 1 'フォームビューの場合 → データシートビューに切替 DoCmd.RunCommand acCmdSubformDatasheetView ' Forms("フォーム1").DefaultView = 2 Case 2 'データシートビューの場合 → ピボットテーブルに切替 DoCmd.RunCommand acCmdSubformPivotTableView End Select End Sub を実行すると、ちゃんとデータシートビューに切り替わります。 そしてデータシートビューからフォームビューへ切り替えようと思い 再度上記のコードを実行しても何も起こりません。 (エラーにもなりません) なぜでしょうか? ちなみに規定のビューをデータシートビューにして上記マクロを実行しても同様何も起こりません。データシートビューのままです。 MsgBox Forms("フォーム1").DefaultView で値を取得してみたら データシートビューでもフォームビューでも0が返って来ます。 何か原因がわかる方いらっしゃいましたら ご教授よろしくお願いします。

  • ダイアログボックスにリストビューを付けたが、リストが表示されない

    ダイアログボックスにリストビューを付けて、ダイアログボックスにデータの一覧を表示させたいのですが、うまく表示されません。  http://gurigumi.s349.xrea.com/programming/visualcpp/sdk_dialog_listview1.html を参考にして、プログラミングしました。 プログラムの大まかな処理としては、  1.InitCommonControls()をコール  2.GetDlgItem()で、ダイアログボックスに貼り付けられているウィンドウハンドルを取得  3.ListView_InsertColumn()をコールして、項目を追加  4.ListView_InsertItem()をコールして、1つ目の値を設定  5.ListView_SetItem()をコールして、2つ目以降の値を設定 だと思いますが、この手順で行っても、うまく表示されませんでした。 何か抜けている手順はあるのでしょうか? また、上記以外に、何かポイントにしなければならないことはあるのでしょうか? 申し訳ありませんが、ご返答くださいますよう、よろしくお願いいたします。

  • VC++ MFC CFrameWndって・・・

    こんにちわMFC初心者です MFCアプリケーションウィザードを利用してMFCの画面を作成するとCFrameWndを元にしたCMainFrameクラスが作成されますが、コレはプロジェクト起動時に一番最初にインスタンスが作成されるクラスと考えて良いのでしょうか? また、他のサンプルプログラムでCMainFrameクラス内のメンバとしてCWndクラスを元にしたCChildViewが定義されていますが、この場合はCChildViewはCMainFrameの子フォームになるのですかね? 更にCChildView内部でCImageクラスを元にしたimgOriginalが定義されていますが、これはCChildViewに設置するコントロールですかね?(VBでいうところのピクチャーコントロール見たいなモンですかね?) 目的として、特殊な画像形式を利用する為、CImageクラスを利用して画像表示が出来ないので、特殊な画像形式のファイルからピクセル単位のデータを取得して画像表示をしたいのですが、この時にCDCクラスを利用して画像表示したいのですが、上手く表示されません これは、自分のMFCに対する認識が間違っているのでは無いかと思い皆様に質問させて戴いた次第です 皆様、私の認識に間違いがないかどうか、コメントをお願い致します m(__)m

  • MFC VC++6.0 DestroyWindowの実装場所について

    [開発環境]:Visual C++ 6.0 現在、Visual C++ 6.0を使ったプログラミングの勉強をしています。 MFC AppWizard (exe)でSDIプログラムのtest1プロジェクト作成後、メインフレームにボタンを実装し、そのボタンを押下するとモードレスダイアログを表示するというアプリケーションを作っているのですが、ダイアログを終了させる時のDestroyWindowの実装場所と実装方法が分かりません。 ダイアログ用のクラスはCmyDialogとしていますが、ダイアログの終了ボタンを実装した場合、そのボタン処理の中すなわちCmyDialogクラスのなかの関数で行うべきなのでしょうか?それともダイアログの作成と同様にメインフレームがわの処理(CTest1Viewクラスでの処理?)として行うべきなのでしょうか?この場合にはどのような場所でどのようなタイミングで実装すればよいのか分かりません。 ご存じの方、これらについて御教授お願いします。 以下プログラムの一部を記載します。 -test1view.cppの一部-(ここでダイアログの作成と表示をしています) void CTest1View::OnButton1() { CmyDialog* myDLG = new CmyDialog; myDLG->Create(IDD_DIALOG1,this); myDLG->ShowWindow(SW_SHOW); }

  • 非表示のメインウィンドウを表示させるには?

    環境 WIN98 VC++6.0 MFC SDIにて タスクトレイに常駐するアプリにおいて 1.起動時にメインウィンドウを非表示にしています。 2.起動時と同時にダイアログを表示しています。 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { 略 dlg = new CInput(this); dlg->Create(IDD_DIALOG1); dlg->ShowWindow(SW_SHOW); return 0; } 3.このような場合に、ダイアログのボタン押し下げにて、メインウィンドウを表示させるには、どうすれば良いでしょうか? 以下のようにしてみましたが、不正な処理で落ちてしまいます。 void CInput::OnButton1() { CWnd* mywnd = (CWnd*)GetParent(); mywnd->ShowWindow(SW_SHOW); }