none
WinAppクラスからDocument側の処理を呼び出したい RRS feed

  • 質問

  • お世話になっております。arubi_momoと申します。

    現在、VisualStudio2010 MFCアプリケーションのシングルドキュメントで、開発を行っています。

    アプリケーションを起動すると、シングルドキュメントのメイン画面が表示されるようになっているのですが、このアプリケーションをコマンドラインから起動した場合は、メイン画面を表示させず、バッチ処理のように静かにファイルを読み込み印刷する、という機能をつけたいのです。

    WinAppクラスのInitInstance関数の中で、コマンドライン引数を受け取った場合は、Windowを表示しないというようにして、画面を起動させないようにはできたのですが、実際のファイル読み込み処理や印刷処理は、Document側に既にあるプログラムを使用して、読み込み・印刷を行いたいと考えています。

    ですが、WinAppクラスからDocumentを呼び出す方法がわかりません。m_pDocumentのアドレスを呼び出してそれを使えばよいのかと思ったのですが、WinAppクラスではm_pDocumentを認識してくれませんでした。WinAppクラスからDocument側の関数を使用する方法はありますでしょうか。

    ご存知の方がいらっしゃいましたら、ご教示いただけますようお願いいたします。

    

    2013年6月17日 1:26

回答

  • MFCはやや強引にメインフレームを表示しようとしますね。
    そして、気づきにくい罠的仕様もあります。例えば

     1.裏でこっそりレジストリからウインドウを再現してしまいます。
      ウインドウプレースメントですね。これを明示的に禁止しましょう。
      m_bLoadWindowPlacement = FALSE; // Placementをロードしない

     2.まあこいつもやっときましょう(不安だし)
      m_nCmdShow = SW_HIDE;

     3.CSingleDocTemplate::OpenDocumentFile( LPCTSTR, BOOL);
        のBOOLは bMakeVisible = TRUE とデフォルトの引数になってます。
      それとは気づかずに、表示することを自ら指定しまうように
      なっているのですね。これにFALSEを明示的に指定しなければなりません。
      Doc = pDocTemplate->OpenDocumentFile(「ファイル名」, FALSE);//表示しないでオープン

    これで、いけてますでしょうか(試してません)。

    2013年6月17日 9:52

すべての返信

  • MFC のDoc/View機構を使って、ということであれば、

    /p "%1" で、印刷ダイアログを表示して直接印刷

    /pt "%1" "%2" "%3" "%4" で、直接指定プリンタに印刷

    という機能が、MFCの拡張子関連付けサポート機能として標準実装されています。

    これをベースにしてみてはいかがでしょう?


    わんくま同盟,Microsoft MVP for Visual C++(Oct 2005-) http://blogs.wankuma.com/tocchann/

    2013年6月17日 3:16
  • 悩みどころがいまいち理解できないのですが、

    My_SDIApp::InitInstance()
    {
      :
      // 引数ファイル名称でDocをOpen
      My_SDIDoc * Doc
         =( My_SDIDoc *)pDocTemplate->OpenDocumentFile(
                     CmdOpenFileName);//RUNTIME_CLASSで渡したDocの派生クラスにキャスト
      Doc->MyTestFunc(); // テスト
      :
    }

    とかが、できないということでしょうか。
    My_SDIDoc.hをインクルードしていない・・・という落ちではないですよね。

    2013年6月17日 3:44
  • とっちゃん様

    いつもご教示いただきありがとうございます。

    標準機能があるのですね。現行のアプリケーションのつくりとして、設定ファイル・データファイル等を読み込み、描画・加工して画面に表示し、それを印刷する、という機能がすでに実装されていまして、それをそのまま(画面表示を除く)コマンドプロンプトから実行したいと考えています。なので、InitInstanceでDocument派生クラスの処理をキックできれば、それが一番よいかと考えておりました。

    一度、そのやり方を試してみて、無理そうでしたら標準機能をベースに考えてみようと思います。

    仲澤@失業者様

    いつもご教示いただきありがとうございます。そして説明下手で大変申し訳ありません。

    その通りです。Document派生クラスのアドレスを取得できずにつまずいていたのですが、それは仲澤@失業者様にいただいたサンプルを試して、取得することができました。ちなみに、My_SDIDoc.hはインクルードしてましたが、引数に指定すべきファイルが間違っていたようです。これは、実行するアプリケーションのexeを指定すればよいのでしょうか?それを指定したら取得できるようになりました。

    ただ、取得したDocument派生クラスの関数を呼び出すと、アクセス違反のエラーが発生してしまいます。これがDocumentの取得を間違えているためなのか、関数側の問題なのかがまだ切り分けできていません・・・。もう少し調べてみます。

    2013年6月17日 8:31
  • ドキュメント-ビューアーキテクチャは、その名の通り、

     1.データとウインドウ(メインフレームとチャイルドView)が必須

    ですね。
    ドキュメントをいぢると、メインフレームや、Viewにアクセスします。
    従って、ウインドウを表示したくない場合は、

     2.メインフレームを、作成しない・・・という選択は困難で、
      非表示にするか、デスクトップの外に移動させる方が簡単。

    このあたりの理解は大丈夫ですか。

    2013年6月17日 9:02
  • 仲澤@失業者様

    お世話になっております。

    アクセス違反のエラーはどうやら関数側の問題のようでした。単に値を返すだけの単純なサンプル関数でテストしてみたところ、受け取ることができました。お騒がせして申し訳ありません。

    ところで、新たに問題が出てしまったのですが、今、InitInstanceの中で、コマンドライン引数があればメイン画面を表示しない、という処理を入れています。ですが、OpenDocumentFile関数を使用したため、そのタイミングで一瞬メイン画面が表示されてしまいます。これを回避する方法はあるのでしょうか。

    2013年6月17日 9:12
  • MFCはやや強引にメインフレームを表示しようとしますね。
    そして、気づきにくい罠的仕様もあります。例えば

     1.裏でこっそりレジストリからウインドウを再現してしまいます。
      ウインドウプレースメントですね。これを明示的に禁止しましょう。
      m_bLoadWindowPlacement = FALSE; // Placementをロードしない

     2.まあこいつもやっときましょう(不安だし)
      m_nCmdShow = SW_HIDE;

     3.CSingleDocTemplate::OpenDocumentFile( LPCTSTR, BOOL);
        のBOOLは bMakeVisible = TRUE とデフォルトの引数になってます。
      それとは気づかずに、表示することを自ら指定しまうように
      なっているのですね。これにFALSEを明示的に指定しなければなりません。
      Doc = pDocTemplate->OpenDocumentFile(「ファイル名」, FALSE);//表示しないでオープン

    これで、いけてますでしょうか(試してません)。

    2013年6月17日 9:52
  • 仲澤@失業者様

    お世話になっております。ご返信が遅れて申し訳ありません。

    メインフレームは表示されなくなりました!ありがとうございます。

    パターンを試しましたが、1と3が必要のようです。2はなくても大丈夫でした。

    これで前に進めます。本当にありがとうございました。

    ちなみに、ひとつ前のご回答で、メインフレームを作成しないのは難しいため、非表示にするか、デスクトップの外へ表示するとおっしゃっていましたが、こちらの方法は、非表示にする方法ということですよね。デスクトップの外に表示、というのはあまり想像がついていないのですが、表示位置を指定するということなのでしょうか。

    2013年6月18日 0:15
  • >デスクトップの外に表示、というのはあまり想像がついていないのですが、表示位置を指定するということなのでしょうか。

    MainFrame->SetWindowsPos( NULL, -1000, -1000, 200, 200, ~

    等の様にデスクトップ外に移動させます。
    実質的にユーザーからは見えない点は、非表示にした場合と同様ですが、

     1.キーボードフォーカスが使用可能。
     2.起動中はタスクバーに表示される。

    などですね。
    ESCキーで処理中断とか、タスクバーからシステムメニューを選択させる
    などしたい場合でしょうか。
    完全にスティルス化する前のデバッグ時にも使えます(笑)。

    2013年6月18日 0:54
  • 仲澤@失業者様

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

    なるほど、用途によって使い分けるのですね。今回の場合は、完全にユーザから隠したいので、非表示の方法がよいですね。とても参考になりました!ありがとうございました。

    2013年6月18日 2:19