BCC2ECCツールん最後は、メンバー関数の定義をまとめたBCC2ECCProc.hファイルです。
【BCC2ECCProc.h】
//////////////////////////////////////////
// BCC2ECCProc.h
// Copyright (c) 09/06/2022 by BCCSkelton
//////////////////////////////////////////
/////////////////////////////////
//主ウィンドウCMyWndの関数の定義
//ウィンドウメッセージ関数
/////////////////////////////////
bool CMyWnd::OnClose(WPARAM wParam, LPARAM lParam) {
if(MessageBox(m_hWnd, "終了しますか", "終了確認",
MB_YESNO | MB_ICONQUESTION) == IDYES)
//処理をするとDestroyWindow、PostQuitMessageが呼ばれる
return TRUE;
else
//そうでなければウィンドウではDefWindowProc関数をreturn、ダイアログではreturn FALSEとなる。
return FALSE;
}
//ダイアログベースの場合はこれが必要
bool CMyWnd::OnDestroy(WPARAM wPram, LPARAM lParam) {
PostQuitMessage(0);
return TRUE;
}
//(解説:以上はSkeltonWizard通りコードです。)
/////////////////////////////////
//主ウィンドウCMyWndの関数の定義
//メニュー項目、コントロール関数
/////////////////////////////////
bool CMyWnd::OnSel() {
char* fn = cmndlg.GetFileName(m_hWnd, "BDPファイル(*.bdp)\0*.bdp\0\0",
TRUE, "bdp", ".", "プロジェクトファイルを開く");
if(!fn) {
MessageBox(m_hWnd, "ファイルが選択されませんでした。", "エラー",
MB_OK | MB_ICONERROR);
return FALSE;
}
//(解説:ファイルを開くダイアログでbdpファイルを指定させます。)
else {
//フルパスプロジェクトファイル名を記録
lstrcpy(m_PathName, fn);
m_Ext = strstr(m_PathName, ".bdp"); //拡張子の位置を記録
//(解説:bdpファイルのフルパス名をg_PathNameに保存。拡張子の'.'の位置を記録します。)
//フルパスプロジェクトファイル名
char* cp = m_PathName;
while(cp < m_Ext) {
if(*cp == '\\')
fn = cp; //(最後の)'\\'の位置を記録
cp++;
}
++fn; //'\\'の次に進める
//(解説:最後の'\\'(\記号)fnに記録させ、それを一つ進めてパスを取り除きます。)
for(cp = fn; cp < m_Ext; cp++)
m_PrjtName[cp - fn] = *cp; //プロジェクト名の保存
SendItemMsg(IDC_EDIT, WM_SETTEXT, 0, (LPARAM)m_PrjtName);
//(解説:m_PrjtNameにはファイル名の内、「'.'拡張子」を外した文字列を保存し、IDC_EDITに表示ます。)
MessageBox(m_hWnd, "選択されたBCCSkeltonプロジェクトのrcファイル、"\
"cppフィル、hファイルおよびProc.hファイルを順に"\
"ECCSkelton用に変換します。\r\n但し、メインウィンドウで"\
"ないダイアログがあれば、コマンドテーブル(CMDTABLE)の"\
"クラス名とテーブルをマニュアルで修正する必要があります。",
"説明", MB_OK | MB_ICONINFORMATION);
//(解説:これからの処理と、ユーザーのマニュアル修正について説明しています。)
return TRUE;
}
}
bool CMyWnd::OnIdok() {
if(!*m_PathName) {
MessageBox(m_hWnd, "未だファイルが選択されていません。", "エラー" ,
MB_OK | MB_ICONERROR);
return FALSE;
//(解説:処理対象が指定されていない場合はエラーとなります。)
}
//チェックボックスをチェックする
if(SendItemMsg(IDC_OPTION, BM_GETCHECK, 0, (LPARAM)0) == BST_CHECKED)
m_Option = TRUE;
//(解説:オプションがチェックされていればmOptionフラグを真にします。)
//RCファイルの変更
lstrcpy(strstr(m_PathName, ".bdp"), ".rc");
ModifyRC();
//CPPファイルの変更
lstrcpy(strstr(m_PathName, ".rc"), ".cpp");
ModifyCPP();
//CPPファイルの変更
lstrcpy(strstr(m_PathName, ".cpp"), ".h");
ModifyH();
//CPPファイルの変更
lstrcpy(strstr(m_PathName, ".h"), "Proc.h");
ModifyProcH();
//(解説:rc、cpp、h、Proc.hの各ファイル毎の処理を行います。)
//再変換、再初期化、または終了する
int res = MessageBox(m_hWnd, "変換処理されたECCSkelton用ファイルは"\
"\"_ECC\"が付いたファイルになっています。\r\n内容を"\
"確認して再度変換する場合は「はい」を、再初期化する"\
"場合は「いいえ」を、終了する場合は「キャンセル」を"\
"押してください。",
"続行確認", MB_YESNOCANCEL | MB_ICONQUESTION);
if(res == IDNO)
Init();
else if(res == IDCANCEL)
OnIdno(); //終了します。
else
return TRUE;
}
bool CMyWnd::OnIdno() {
SendMsg(WM_CLOSE, 0, 0);
return TRUE;
}
////////////////////
//ユーザー関数定義
///////////////////
void CMyWnd::Init() {
*m_PathName = NULL;
m_Ext = NULL;
*m_PrjtName = NULL;
m_Option = FALSE;
//エディットボックスを空にする
SendItemMsg(IDC_EDIT, WM_SETTEXT, 0, (LPARAM)"");
//リストボックスを空にする
while(SendItemMsg(IDC_LISTBOX, LB_DELETESTRING, 0, 0));
//チェックボックスを未チェックにする
SendItemMsg(IDC_OPTION, BM_SETCHECK, BST_UNCHECKED, (LPARAM)0);
}
//(解説:メンバー変数とコントロールの初期化用の関数です。)
//(解説:以下各ファイルの変換ですが、何をどうしているかについては青字を読んでください。)
bool CMyWnd::ModifyRC() {
CSTR File, fn(m_PrjtName);
File.FromFile(m_PathName);
fn = fn + ".rc を処理します。";
SendItemMsg(IDC_LISTBOX, LB_ADDSTRING, 0, (LPARAM)fn.ToChar());
//共通
File.ReplaceAll(", \"", ", L\""); //[, "]→[, L"]
//ダイアログ
File.ReplaceAll("CAPTION \"", "CAPTION L\""); //[CAPTION "]→[CAPTION L"]
File.ReplaceAll("CONTROL \"", "CONTROL L\""); //[CONTROL "]→[CONTROL L"]
//メニュー
File.ReplaceAll("POPUP \"", "POPUP L\""); //[POPUP "]→[POPUP L"]
File.ReplaceAll("MENUITEM \"", "MENUITEM L\""); //[MENUITEM "]→[POPUP L"]
//(解説:以下は各ファイル共通の"\ECC.(拡張子)"保存処理です。)
*m_Ext = NULL;
fn = m_PathName;
*m_Ext = '.';
fn = fn + "_ECC.rc";
File.ToFile(fn.ToChar());
return TRUE;
}
bool CMyWnd::ModifyCPP() {
CSTR File, fn(m_PrjtName);
File.FromFile(m_PathName);
fn = fn + ".cpp を処理します。";
SendItemMsg(IDC_LISTBOX, LB_ADDSTRING, 0, (LPARAM)fn.ToChar());
File.ReplaceAll("BCCSkelton", "ECCSkelton");
File.ReplaceAll("WinMain(", "wWinMain("); //[WinMain(]→[wWinMain(]
File.ReplaceAll("LPSTR", "LPWSTR"); //[LPSTR]→[LPWSTR]
File.ReplaceAll(", SDIPROC", ""); //[, SDIPROC]→[]
File.ReplaceAll(", ModelessProc", ""); //[, ModelessProc]→[]
File.ReplaceAll("(\"", "(L\""); //[("]→[(L"]
File.ReplaceAll(" \"", " L\""); //[ "]→[ L"]
*m_Ext = NULL;
fn = m_PathName;
*m_Ext = '.';
fn = fn + "_ECC.cpp";
File.ToFile(fn.ToChar());
return TRUE;
}
bool CMyWnd::ModifyH() {
CSTR File, fn(m_PrjtName), work("ON_COMMAND(");
File.FromFile(m_PathName);
fn = fn + ".h を処理します。";
SendItemMsg(IDC_LISTBOX, LB_ADDSTRING, 0, (LPARAM)fn.ToChar());
//共通
File.ReplaceAll("BCCSkelton", "ECCSkelton");
//メッセージ、コマンドテーブル共通
work = work + m_PrjtName;
work = work + ", ";
File.ReplaceAll(work.ToChar(), "ON("); //[ON_COMMAND(]→[ON(]
File.ReplaceAll("ON_(", "//ON_("); //[ON_(Win message)]→[//ON_(Win message)]
File.ReplaceAll("ON_", "//ON_"); //[ON_]→[//ON_]
File.ReplaceAll("(\"", "(L\""); //[("]→[(L"]
File.ReplaceAll(" \"", " L\""); //[ "]→[ L"]
File.ReplaceAll("char", "WCHAR"); //[char]→[WCHAR]
//メインウィンドウのメンバー関数にCMDTABLEを追加
File.ReplaceAll("//ウィンドウメッセージ関連\r\n\tbool", "//ウィンドウメッセージ関連\r\n\tCMDTABLE\t\t//OnCommand()関数宣言\r\n\tbool");
//CSDIウィンドウの場合
File.ReplaceAll("BEGIN_SDIMSG(", "BEGIN_CMDTABLE(CMyWnd)\t//クラス名がCMyWndではない場合、クラス名、テーブルを適宜マニュアルで修正してください\r\n//BEGIN_SDIMSG(");
File.ReplaceAll("END_WNDMSG", "//END_WNDMSG\r\nEND_CMDTABLE");
//CDLGベースのモードレスダイアログの場合
File.ReplaceAll("BEGIN_MODELESSDLGMSG(", "BEGIN_CMDTABLE(CMyWnd)\t//クラス名がCMyWndではない場合、クラス名、テーブルを適宜マニュアルで修正してください\r\n//BEGIN_MODELESSDLGMSG(");
//CDLGベースのモーダルダイアログの場合
File.ReplaceAll("BEGIN_MODALDLGMSG(", "BEGIN_CMDTABLE(CMyWnd)\t//クラス名がCMyWndではない場合、クラス名、テーブルを適宜マニュアルで修正してください\r\n//BEGIN_MODALDLGMSG(");
File.ReplaceAll(" : public CDLG {\r\npublic:", " : public CDLG {\r\npublic:\r\n\tCMDTABLE\t\t//OnCommand()関数宣言");
//ダイアログ共通
File.ReplaceAll("END_DLGMSG", "//END_DLGMSG\r\nEND_CMDTABLE");
*m_Ext = NULL;
fn = m_PathName;
*m_Ext = '.';
fn = fn + "_ECC.h";
File.ToFile(fn.ToChar());
return TRUE;
}
bool CMyWnd::ModifyProcH() {
CSTR File, fn(m_PrjtName);
File.FromFile(m_PathName);
fn = fn + "Proc.h を処理します。";
SendItemMsg(IDC_LISTBOX, LB_ADDSTRING, 0, (LPARAM)fn.ToChar());
File.ReplaceAll("BCCSkelton", "ECCSkelton");
File.ReplaceAll(" \"", " L\""); //[ "]→[ L"]
File.ReplaceAll(" \'", " L\'"); //[ ']→[ L']
File.ReplaceAll("char", "WCHAR"); //[char]→[WCHAR]
File.ReplaceAll("LPSTR", "LPWSTR"); //[LPSTR]→[LPWSTR]
File.ReplaceAll("LPCSTR", "LPCWSTR"); //[LPCSTR]→[LPCWSTR]
///////////////////////////////////////////////////////////////////
//既にプログラムを書き始めている場合の為に以下オプションを用意した。
//多くのWin32API関数名はUNICODEが定義されていれば、ワイド文字にWを
//付けてくれる為、特に変換しなくてもよい。
//なお、自分用にもっと増やしたい場合は↓のリストに追加すればよい。
///////////////////////////////////////////////////////////////////
if(m_Option) {
//Win32 API関数
File.ReplaceAll("MessageBox", "MessageBoxW"); //[MessageBox]→[MessageBoxW]
File.ReplaceAll("SendMessage", "SendMessageW"); //[SendMessage]→[SendMessageW]
File.ReplaceAll("SendDlgItemMessage", "SendDlgItemMessageW"); //[SendDlgItemMessage]→[SendDlgItemMessageW]
File.ReplaceAll("lstrcmp", "lstrcmpW"); //[lstrcmp]→[lstrcmpW]
File.ReplaceAll("lstrcpy", "lstrcpyW"); //[lstrcpy]→[lstrcpyW]
File.ReplaceAll("lstrcat", "lstrcatW"); //[lstrcat]→[lstrcatW]
File.ReplaceAll("lstrlen", "lstrlenW"); //[lstrlen]→[lstrlenW]
File.ReplaceAll("wsprintf", "wsprintfW"); //[wsprintf]→[wsprintfW]
//C標準ライブラリ―
File.ReplaceAll("strstr", "StrStrW"); //[strstr]→[StrStrW] Shellの関数を優先した
//File.ReplaceAll("strstr", "wcsstr"); //[strstr]→[wcsstr]
File.ReplaceAll("strcmp", "wcscmp"); //[strcmp]→[wcscmp]
File.ReplaceAll("strcpy", "wcscpy"); //[strcpy]→[wcscpy]
File.ReplaceAll("strcat", "wcscat"); //[strcat]→[wcscat]
File.ReplaceAll("strlen", "wcslen"); //[strlen]→[wcslen]
//(解説:C標準ライブラリーはUNICODEフラグで勝手に変換してくれないと思うので、これらを使われ高た方は変換が必要です。なお、私はstrstrのワイド文字版はStrStrWというウィンドウズの関数を使う趣味なので、敢えてこうしています。)
}
*m_Ext = NULL;
fn = m_PathName;
*m_Ext = '.';
fn = fn + "Proc_ECC.h";
File.ToFile(fn.ToChar());
return TRUE;
}
と、拍子抜けする位簡単な処理でした。
SkeltonWizardで作ったばかりのファイルであればオプションを入れずに100%変換されます。なお、上記したように「メインウィンドウ以外のダイアログ」を使う場合については前々回に書いた以下注に注意してください。
注:RTWEditorがそうですが、SkeltonWizardは親ウィンドウをCMyWndクラスとしてコーディングしますので、親ウィンドウは自動で変換できますが、ユーザーが定義するその他のダイアログはそれぞれの任意のダイアログIDを基にクラス名が作られるので、これらはユーザーがマニュアルで対応する必要があります。
例:IDD_INPUT→INPUTDLGクラス、IDD_VERSION→VERSIONDLGクラス
但し、その場合も、
(1)テーブル開始行のクラス名の修正
例:BEGIN_CMDTABLE(CMyWnd)→BEGIN_CMDTABLE(VERSIONDLG)
(2)テーブルのコントロールコマンド修正
例:ON_COMMAND(versiondlg, IDC_VERTXT, OnVertxt())→ON(IDC_VERTXT, OnVertxt())
だけと、いたって簡便です。