TCustomForm::OnCreateでの注意点

フォーム作成時のエラー処理でちょっとハマったので、ほとんど覚え書き。アプリケーションの設定ファイルをアプリケーションと同じフォルダに置くことはよくあること*1だけど、設定ファイルが無い場合はデフォルト値で初期化するのではなく、アプリケーションを起動させないケース。

void __fastcall TForm1::FormCreate(TObject *Sender)
{
  UnicodeString ConfigFile = TPath::ChangeExtension(Application->ExeName, L".ini");
  if (!TFile::Exists(ConfigFile)) {
    throw Exception(L"設定ファイルがありません!");
  }
}

という感じで、フォームの作成時にエラーか何かが発生して、例外を投げても、何故か_tWinMainのtry〜catchブロックで例外をキャッチしてくれなく、そのままフォームが作成されてしまう。

#include <vcl.h>
#pragma hdrstop
#include <tchar.h>
//---------------------------------------------------------------------------
USEFORM("Unit1.cpp", Form1);
//---------------------------------------------------------------------------
WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
  try
  {
    Application->Initialize();
    Application->MainFormOnTaskBar = true;
    Application->CreateForm(__classid(TForm1), &Form1);
    Application->Run();
  }
  catch (Exception &exception)
  {
    Application->ShowException(&exception);
  }
  catch (...)
  {
    try
    {
      throw Exception("");
    }
    catch (Exception &exception)
    {
      Application->ShowException(&exception);
    }
  }
  return 0;
}

TCustomForm::OnCreateのヘルプによると、

フォームのコンストラクタとのやり取りが不良になる可能性があるので,C++ コードで OnCreate イベントを使用することはお勧めできません(OldCreateOrder 参照)。そのかわりに,フォームコンストラクタをオーバーライドすることをお勧めします。

とあるので、フォームの初期設定はOnCreateイベントで行うのではなく、フォームのコンストラクタで行うこと。

__fastcall TForm1::TForm1(TComponent* Owner)
  : TForm(Owner)
{
  UnicodeString ConfigFile = TPath::ChangeExtension(Application->ExeName, L".ini");
  if (!TFile::Exists(ConfigFile)) {
    throw Exception(L"設定ファイルがありません!");
  }
}

コンストラクタで例外を投げれば、_tWinMainのtry〜catchブロックで例外をキャッチしてくれる。

*1:Vista/7では推奨しないけど、滅多に変更しない場合は「あり」だと思う。