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

・環境
VisualStudio2008SP1+FeaturePack
Windows7 64bit

タブドキュメント形式でMDIアプリを作っているのですが、複数ドキュメントがある際にプログラムから任意のビューを安全にアクティブ化させる方法がわからずに困っております。CMainFrame::SetActiveViewメソッドを使用すると指定したビューがアクティブになり所望の動作になるのですが、この方法だとドキュメントをクローズするときに以下の例外が出て怒られます。SetActiveViewはビューのOnCreate内で実行しています。

 アクティブ化を解除しているアクティブ化コンテキストは、最近アクティブ化されたものではありません。

こういった状況に遭遇しない方法を探っているのですが使用するAPIと適切な使用タイミングがつかめず困っております。どなたかにご教授いただければ幸いです。

A 回答 (7件)

ちょっと今環境がないのでテストしていませんが


これでどうでしょうか?

http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng. …

この回答への補足

上記リンクは私もGoogleから検索してみておりましたが、そのあたりはクラスのメソッド名から予測していろいろ試し済みのところでもありまして、うまくもいきませんでした。

で、今回のケースではタブによるMDI子ウィンドウの切り替えを行っています。タブを交互にクリックするとCView::OnMDIActivate仮想関数が正しく呼ばれ、そこで所望の処理を記述し、たとえば複数のCView間でどうしても1つのリソースを共有しなければならない場合などに排他処理のフラグを立てたりします。今回問題なのは新規ドキュメント生成直後に「新規ドキュメント以外も」有効化状態のままになってしまうというところでして、新規ドキュメント作成後に新しいタブとともにそれに対応したビューが表示されるのですが、それだけを有効化されたビューにしたいのです。

新規のドキュメントが生成されたときにも既存のビューのOnMDIActivateは呼ばれるようなのですが、どうも既存のドキュメントのOnMDIActivateが「無効化フラグ」付きで実行されないようで、タブをクリックしてドキュメントを切り替えたときのような動作をしてくれません。 つまり上にも書いたとおりタブをクリックしたときは正常に有効化ならびに無効化状態がトグルされるので、その挙動をプログラマティックにやりたいのです。

補足日時:2011/08/15 22:41
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

お礼日時:2011/08/15 22:26

質問主です。


修正ですが、ドキュメントを閉じるときというよりは、複数のドキュメントを開いている状態で、前記した方法でアクティブ化を行い、「アプリケーション自体」をクローズボタンなどから終了したときに例外が出ます。
MDIアプリのスケルトンをタブドキュメントスタイルで作り、同様にやってみて同じ例外がアプリケーション終了時に出るので、他の実装の影響ではないようです。

ドキュメントが作成された時点でアクティブ化が一度行われるので本質的に必要のない目的のように思われますが、タブをクリックしたときのOnActivateViewの呼び出しタイミングをエミュレートしたいときにはプログラマティックに行えなければやはり不便かなと思います。
    • good
    • 0
この回答へのお礼

dummy

お礼日時:2011/08/16 13:10

質問者です。


アクティブ化がうまくいくのはMDIActivateではなくSetActiveView関数でした。度々の誤記申し訳ないです。
    • good
    • 0
この回答へのお礼

dummy

お礼日時:2011/08/16 01:03

質問者です。


とりあえず別の方針で所望の挙動を実装してみました。

1.ドキュメントテンプレートからドキュメントを列挙
2.各ドキュメントから対応するビューを取得
3.ビューに任意の排他制御処理を記述

という感じで回避できました。
もしMFCクラスが持っている関数などで対応できる解があった場合、ご回答いただければ幸いです。

この回答への補足

前記のとおりCMDIFrameWndが持つMDIActivateはビューを有効化するという目的だけは果たすのですが、ドキュメントクローズ時に例外が出てしまうので使うタイミングが難しいという感想です。
タブスタイルドキュメントを用いている場合に限る話ですが、どのタイミングでビューをプログラマティックに有効化すれば安全にドキュメントのクローズが出来るのかは知りたいところなので、もしご存知の方がおられましたら、ご回答いただければ幸いです。

補足日時:2011/08/16 00:59
    • good
    • 0
この回答へのお礼

dummy

お礼日時:2011/08/16 00:59

質問者です。

別アカで補足します。

前記補足でビューがアクティブかされたときにOnMDIActivateという仮想関数が呼ばれると記述したのですが誤りで、OnViewActivateでした。
    • good
    • 0
この回答へのお礼

dummy

お礼日時:2011/08/16 01:00

それってアクティブにするハンドルを間違っていませんか?

この回答への補足

CMainFrame::SetActiveView関数にはCWnd*を引数として渡すようになっていますがこのポインタの指しているインスタンスがCView派生のものではいけないということになるのでしょうか?その点もいろいろ試しまして、ビューの親ウィンドウなどを渡したりしてみたのですがうまくはいきませんでした。

補足日時:2011/08/14 21:43
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

お礼日時:2011/08/14 21:44

最近開発から離れていて、自宅に開発環境ないので曖昧だけど


SetActiveViewでなくSetFocusを使ってはいかがですか?
SetFocusとSetActiveViewはキー入力する場所になります。
正確にはちょっと違うけどどうでしょうか?


またはMFC使わずAPIを直接呼ぶとか。

あとなぜOnCreateで呼んでいるのかはわかりません。
他にタイミング(メッセージ)はないのですか?
昔OnDrawでアプリケーションかを作ったことがあります。

どういったアプリケーションを作ろうとしていて、どんなどんな
タイミングでアクティブにしたいのか教えてくれるとよりアドバイスしやすいですよ。

この回答への補足

実はOnCreate以外にもいろいろ試しました。そしてタイミングはつかめていません。タブドキュメントになっているので、タブをクリックすると対応するビューがアクティブ化されるので、この挙動と同じ処理をAPIから叩ければいいのかもしれませんがよくわかっておりません。
あとSetFocusも試したのですがアクティブ化がなされませんでした。

補足日時:2011/08/14 07:10
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

お礼日時:2011/08/14 08:04

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

このQ&Aを見た人はこんなQ&Aも見ています