お世話になっています。
次のような仕様のなアプリを作っています。
・アプリと同じディレクトリにファイルhoge.txtがあれば、アプリ起動直後にファイルの内容
を読み込む。
・ファイルが存在しなければ空のhoge.txtを作成する。
一応は以下のコードで期待通り動作したのですが、
なんかインチキくさいやり方のようで気に入りません。
もっとスマートな方法があればご教授ください。
BOOL CMyApp::InitInstance()
{
//前略
// DDE、file open など標準のシェル コマンドのコマンドラインを解析します。
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
cmdInfo.m_nShellCommand = CCommandLineInfo::FileOpen;
cmdInfo.m_strFileName = _T(hoge.txt);
CreateOrOpenDataFile();
// コマンドラインでディスパッチ コマンドを指定します。
if (!ProcessShellCommand(cmdInfo))
return FALSE;
//後略
}
void CMyApp::CreateOrOpenDataFile()
{
CFile file(_T(hoge.txt), CFile::modeCreate | CFile::modeNoTruncate);
}
開発環境は WinMe, VC++SP5 MFC(SDI)です。
少なくとも、
> ・ファイルが存在しなければ空のhoge.txtを作成する。
に関していえば、カミーユさんの手法でいいと思います。
ただ、MSDNによると、
> CFile( LPCTSTR lpszFileName, UINT nOpenFlags )
> nOpenFlags
> 共有モードとアクセス モードを指定します。ファイルを開くときの動作です。
> ビットごとの OR (|) 演算子を使って、次のオプションを組み合わせます。
> アクセス許可モードと共有モードは必ず 1 つずつ指定します。
とあるので、フラグ指定が不足していると思います。
Windows98/VC++6.0sp5pro/SDK-may2002/ATL3.0/WTL7.0
>ただ、MSDNによると、
>> CFile( LPCTSTR lpszFileName, UINT nOpenFlags )
>> nOpenFlags
>> 共有モードとアクセス モードを指定します。ファイルを開くときの動作です。
>> ビットごとの OR (|) 演算子を使って、次のオプションを組み合わせます。
>> アクセス許可モードと共有モードは必ず 1 つずつ指定します。
>とあるので、フラグ指定が不足していると思います。
CFile::shareDenyWriteあたりも付け加えるべきなんでしょうが、
CMyApp::CreateOrOpenDataFile()を抜けるときに
CFileのデストラクタでファイルがクローズされ
さらに先のステップのCDocument::OnOpenDocumentで
CFile::modeRead|CFile::shareDenyWriteと指定して
ファイルをオープンしているので結果的にうまく動いているようです。
ファイルを作るだけという機能はなさそうなので、
上記の通り開いてすぐ閉じるとするしかないでしょうね。
しかし、あらかじめファイルを作っておかなくても、
CDocument::OnOpenDocument()でのファイルオープン時に、
CFile::modeRead|CFile::shareDenyWrite|
CFile::modeCreate|CFile::modeNoTruncate
とまとめて指定しておけば問題なさそうですが。
それとも、「後から別のファイルを読もうとしたときには、
存在しないファイルは作らない」というような追加仕様があるのでしょうか。
一応MFCのSDIで開発してますが、
開くファイルはhoge.txtひとつで固定していて
ファイルの新規作成や別のファイルを開く機能はありません。
ですので、dairygoodsさんの言われるとおり
CDocument::OnOpenDocumentをオーバーライドしたほうが
よさそうですね。
問題はアプリ起動時にCDocument::OnNewDocument()ではなく
CDocument::OnOpenDocument()を呼び出したいんです。
現在は
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
cmdInfo.m_nShellCommand = CCommandLineInfo::FileOpen;
cmdInfo.m_strFileName = _T(hoge.txt);
としてますが、やはり本来はCWinApp::ParseCommandLineあたりを
オーバーライドするべきなんでしょうか?
> オーバーライドするべきなんでしょうか?
好みの問題のような気がしますが、
個人的には、起動時にあるファイルを自動的に開くというのは、
コマンドラインの解釈の仕組みを変更しているわけではないと思われるので、
CWinApp::ParseCommandLine()を上書きするのはヘンかなと思います。
>問題はアプリ起動時にCDocument::OnNewDocument()ではなく
>CDocument::OnOpenDocument()を呼び出したいんです。
最初に載せてあるソースの //前略 の部分でドキュメントテンプレートを生成して登録してい
ると思います。
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
// 略
AddDocTemplate(pDocTemplate);
この後で、
pDocTemplate->OpenDocumentFile(hoge.txt);
という処理を入れると、CDocument::OnOpenDocument()を呼んでくれますが、これでは駄目で
すか?
saraさんの方法を試してみました。
結果は期待通り動作しました。
あとよく考えたらParseCommandLineメソッドを呼ぶ必要はないですね。
CCommandLineInfoのメンバ変数がpublicで公開されてるので
CCommandLineInfo cmdInfo;
cmdInfo.m_nShellCommand = CCommandLineInfo::FileOpen;
cmdInfo.m_strFileName = _T(hoge.txt);
// コマンドラインでディスパッチ コマンドを指定します。
if (!ProcessShellCommand(cmdInfo))
return FALSE;
というコードでもいいかな?という気がします。
皆さんに教えてもらった方法を
いろいろと検討してみたいと思います。
ありがとうございました。