わずか30行のコードでPrintf可能なコンソールウィンドウをMFCアプリケーションに追加する方法 www.ysflight.com
 

はじめに

これまでにMFCアプリケーションを開発したことがある人ならば、デバッグのためにコンソールウィンドウがほしいと思ったことがあったのではないでしょうか?実際、僕は、printfデバッグが一番 効率的な方法だと思ってます。最近の若い人は(というと、おやじくさいですが)デバッガに頼る傾向がありますが、デバッガは悪いことが起きた瞬間、あるいは、プログラムを一時停止させたその一瞬しか見えません。単純な問題ならばそれで解決するでしょう。しかし、複雑な問題は、何か悪いことが起こるずっと手前で発生して、その結果としてプログラムがクラッシュしたり、予想しない結果が発生します。 ある瞬間を止めて見てもその原因はわかりません。printfでプログラムの経路を表示して行けば、どういう経過で悪いことが発生したかがわかるので、デバッガで追跡するよりも早く問題の本質を見つけることができます。さらに、コンソールがあると、プログラムの反応が止まったときTaskmgrを開くまでも無く、Ctrl+Cで止めることができたり、いろいろいいことがあります。

ところが、MFCのフレームワークはデフォルトではコンソールがついていないので、printfデバッグは使えません。が、わずか30行ほどのプログラムを追加して、オプションを少し変更するだけで、MFCアプリケーションにprintf可能なコンソールウィンドウを追加することができます。以下にその方法を解説します。

なお、なんでcoutじゃなくprintfなの?と思われた方もいるかもしれませんが、coutよりprintfの方が優れているから僕はcoutは使いません。coutはtype safeな代わりにprintfが簡単にできることをあまりにも犠牲にしすぎました。coutを含めC++のiostreamははっきり言って子供のおもちゃですね。用が足りません。

     
Visual Studio .NET (とそれ以降のバージョン) のMFCアプリケーションにコンソールウィンドウを追加する方法

以下の手順に従ってください。

(1) このリンク→ mfcconsole.cpp をマウスの右ボタンでクリックして、mfcconsole.cppという名前で保存してください。このファイルは、MFCアプリケーションのプロジェクトのソースファイルがあるディレクトリにコピーしてください。あるいは、以下のコードをカット&ペーストしてもokです。そして、"プロジェクト"メニューの"Add Existing Item"を選んで、"mfcconsole.cpp"をプロジェクトに追加してください。(日本語版のVisual Studio .NETだと、"Add Existing Item"は"既にあるアイテムを追加"とか翻訳されているのではないかと思います。)

#include "stdafx.h"

#include <stdio.h>
#include <windows.h>

extern "C"
{
int PASCAL WinMain(HINSTANCE inst,HINSTANCE dumb,LPSTR param,int show);
};


int main(int ac,char *av[])
{
    char buf[256];
    int i;
    HINSTANCE inst;

    inst=(HINSTANCE)GetModuleHandle(NULL);

    buf[0]=0;
    for(i=1; i<ac; i++)
    {
        strcat(buf,av[i]);
        strcat(buf," ");
    }

    return WinMain(inst,NULL,buf,SW_SHOWNORMAL);
}

ただ、なぜかときどきVisual Studio .NETはせっかく追加したファイルをコンパイル対象から除外してしまう癖があるようなので、そうなっていないことを確認する必要があります。"ソリューションエクスプローラ"で"mfcconsole.cpp"を右ボタンクリックして、"プロパティ"を開いてください。

次に、"Excluded from Build"(日本語版だと、"ビルドから除外"と訳されているのではないかと思います)が"No"になっていることを確認してください。"Yes"になっていたら"No"にしてください。

(2) "ソリューションエクスプローラ"でプロジェクト名(この例ではmfctest)を左ボタンで選んでください。

(3) "プロジェクト"メニューから"プロパティ"を選び、次にプロパティのダイアログで、"Linker" -> "System"を選び、"SubSystem"を"Console (/SUBSYSTEM:CONSOLE)"に切り替えてください。多分、日本語版のVisual Studio .NETだと、"リンカ"->"システム"とか訳してあるのではないかと思います。

以上で、コンソールウィンドウつきのMFCアプリケーションができます。

なお、コンソールを除去したい場合は、"SubSystem"を"Windows (/SUBSYSTEM:WINDOWS)"に戻すだけでできます。(その場合、mfcconsole.cppは自動的に無視されます。)

Visual Studio .NET (Visual C++ 6.0)で、MFCアプリケーションにコンソールウィンドウを追加

次の手順に従ってください。

(1) このリンク→mfcconsole.cppをマウスの右ボタンでクリックして、「保存」を選んで、mfcconsole.cppという名前で保存してください。なお、mfcconsole.cppは、MFCアプリケーションのプロジェクトのソースファイルがあるディレクトリにコピーしてください。あるいは、次のソースコードをカット&ペーストしてmfcconsole.cppという名前で保存してもokです。

続いて、"プロジェクト"メニュー→"Add to Project"(日本語版だと多分プロジェクトに追加とか訳してあると思う)→"Files"を選び、mfcconsole.cppをプロジェクトに追加してください。

#include "stdafx.h"

#include <stdio.h>
#include <windows.h>

extern "C"
{
int PASCAL WinMain(HINSTANCE inst,HINSTANCE dumb,LPSTR param,int show);
};


int main(int ac,char *av[])
{
    char buf[256];
    int i;
    HINSTANCE inst;

    inst=(HINSTANCE)GetModuleHandle(NULL);

    buf[0]=0;
    for(i=1; i<ac; i++)
    {
        strcat(buf,av[i]);
        strcat(buf," ");
    }

    return WinMain(inst,NULL,buf,SW_SHOWNORMAL);
}

たまにVisual Studioはせっかく追加したファイルをコンパイル対象から除外してしまうことがあるので、もしも、File Viewウィンドウ上でmfcconsole.cppのアイコンに下向き矢印がついていない場合(次の絵のような感じ)、ファイルをコンパイル対象から除外しないように設定してやる必要があります。

ファイルをコンパイル対象から除外しないようにするには、File Viewウィンドウ上で"mfcconsole.cpp"を右クリックして、"Setting"を選んでください(日本語版だと多分「設定」とかいう感じに訳してあると思う)。次に、ダイアログが開くので、"General"(日本語版だと多分「一般」とか訳してあると思う)タブで、"Exclude file from build"(日本語版だと多分、「ビルドからファイルを除外」とか訳してあると思う)のチェックボックスをオフにしてください。

  

(2) 次に"プロジェクト"メニューから"Setting"を選んでください。(日本語版だと多分「設定」とかなってると思う)

(3) リンクのオプションを開いて、オプション /subsystem:windows となっている箇所を下のように /subsystem:console と書き換えてください。

これで完了です。あとはプロジェクトをビルドすれば、コンソールウィンドウ付のMFCアプリケーションができます。

なお、コンソールウィンドウを除去するには、/subsystem:consoleを/subsystem:windowsに戻すだけでokです。その場合、mfcconsole.cppは自動的に無視されます。

なんでこれでコンソールウィンドウがつくの?

リンクオプションの "/subsystem:****"というのが、コンソール付プログラムか、コンソール無しプログラムかを決定します。/subsystemがconsoleの場合、コンソールウィンドウありで、プログラムはmain関数から始まります。これに対して、/subsystemがwindowsの場合、コンソールウィンドウなしで、プログラムはWinMain関数から始まります。ですが、MFCアプリケーションはフレームワーク(というか、MFCのライブラリ)内にWinMain関数が隠してあるので、普通は見えません。

ですので、コンソールウィンドウを追加しようと思ったら、/subsystemをコンソールに切り替えてやればいいのです。ですが、そうすると、main関数を追加しないと、プログラムの開始位置が無いというエラーが出ます。なので、mfcconsole.cppはmain関数を用意して、その中からWinMainを呼び出します。

また、/subsystemをwindowsに戻すと、コンソールウィンドウは消えて、main関数は呼び出されずに単純に無視されて、プログラムはWinMain(MFCフレームワーク内の)から始まります。なので、mfcconsole.cppを追加した後は、/subsystemオプションを切り替えるだけで、コンソールあり/なしを変更できます。

なお、同じテクニックはWin32アプリケーションでも利用可能です。

Comments are welcome.  Send E-Mail to:

RETURN TO TOP PAGE