CUIからGUIへ(3)
ファイル選択ダイアログ
Windows風のファイル読み書きを体験してもらったところで、今度はコモンコントロールのファイル選択ダイアログを使ってみよう。
ファイル選択ダイアログについてはhttp://wisdom.sakura.ne.jp/system/winapi/common/common6.htmlこの辺が詳しいが、これはSDK用の説明。
今回はMFCを使うのでもっと簡単に実装できる。そちらの説明はこちらhttp://www.h6.dion.ne.jp/~shiimori/mfc/mfc05.htm
ではさっそく、ダイアログにボタンを一つ追加して、OnFileSelect()というような名前の関数を生成し、コードを記述してみよう。
void CD6Dlg::OnFileSelect() { char strPath[MAX_PATH]; CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY|OFN_FILEMUSTEXIST|OFN_NOCHANGEDIR, "テキストファイル(*.txt)|*.txt|全てのファイル(*.*)|*.*||", this); // ファイルダイアログの起動 if (dlg.DoModal() == IDOK) { // 選択ファイル名取得 strcpy(strPath, dlg.GetPathName()); MessageBox( TEXT(strPath) , TEXT("報告") , MB_OK ); } }
このコードでは既存ファイルを選択して、そのファイルのパスをメッセージボックスで出力する。
メッセージボックスでの出力というのはへちょいので、エディットボックスを一つ作り、そこに出力するように変更したのがこちら。
void CD6Dlg::OnFileSelect() { char strPath[MAX_PATH]; CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY|OFN_FILEMUSTEXIST|OFN_NOCHANGEDIR, "テキストファイル(*.txt)|*.txt|全てのファイル(*.*)|*.*||", this); // ファイルダイアログの起動 if (dlg.DoModal() == IDOK) { // 選択ファイル名取得 strcpy(strPath, dlg.GetPathName()); // エディットボックス(IDC_EDIT1)に得たパスをセット CEdit *pEdit = (CEdit *)GetDlgItem(IDC_EDIT1); pEdit->SetWindowText(strPath); } }
改行コード変換アルゴリズム
話を改行コード変換に戻そう。
まず手始めにMacやUNIXの文字コードからWindows用の文字コードに変換することを考える。
具体的には以下の三通りの処理を行う。
- \r -> \r\n
- \n -> \r\n
- other -> 変換しない
プログラムっぽく書けばこうなる。
int tmp = fgetc(fpIn); switch (tmp) { case '\r': case '\n': fputs("\r\n", fpOut); break; default: fputc(tmp, fpOut); }
これでMacとUnixからWindowsへの変換は成功したが、実は問題がある。Win->Winの変換がうまくいかないのだ。
\rと\nをそれぞれ\r\nに変換するため、Windowsの改行コードである\r\nを\r\n\r\nの改行二つに変換してしまう。
読み込んだ文字が\rだった場合は次の文字が\nであるかチェックして処理を分ける必要がある。直したコードがこちら。
int tmp = fgetc(fpIn); switch (tmp) { case '\r': if ((tmp = fgetc(fpIn)) == '\n') { fputs("\r\n", fpOut); } else { fputs("\r\n", fpOut); fputc(tmp); } break; case '\n': fputs("\r\n", fpOut); break; default: fputc(tmp, fpOut); }
最後に、前回のプログラムと組み合わせた完成版がこちら。
/* Windows改行コードへの変換プログラム */ #include <stdio.h> int sub(char *filename); int main(int argc, char *argv[]) { if (argc != 2) { printf("コマンド引数に対象ファイルを" "指定してください。\n"); getchar(); return 0; } sub(argv[1]); return 0; } int sub(char *filename) { // "r"で開くと改行コードが自動で変換されるので、 // バイナリモードで開く FILE *fp = fopen(filename, "rb"); if (fp == NULL) { printf("\"%s\"が見つかりません。\n", filename); return 1; } FILE *fpOut = fopen("out.txt", "wb"); if (fp == NULL) return 1; /* win \r\n unix \r mac \n */ int tmp; while ((tmp = fgetc(fp)) != EOF) { switch (tmp) { case '\r': if ((tmp = fgetc(fp)) == '\n') { fputs("\r\n", fpOut); } else { fputs("\r\n", fpOut); fputc(tmp, fpOut); } break; case '\n': fputs("\r\n", fpOut); break; default: fputc(tmp, fpOut); } } fclose(fpOut); fclose(fp); return 0; }