わんくまT78 mfcを始めようとしてみた
Transcript of わんくまT78 mfcを始めようとしてみた
わんくま同盟 東京勉強会 #78
MFC を始めようとしてみた
暁 紫電
わんくま同盟 東京勉強会 #78
自己紹介
• HN :暁 紫電• 本名: 伊藤 伸男• 職業: フリーランス・プログラ
マー使用言語 C++ C++/CLI C#
わんくま同盟 東京勉強会 #78
本日のアジェンダ
• MFC とは?• なんでいまさら MFC• MFC の利点/欠点• とりあえずプロジェクトを作ってみる• ダイアログベース• まとめ
わんくま同盟 東京勉強会 #78
MFC とは
• マイクロソフトが Windows アプリ作成用のフレームワークとして開発したライブラリ。
• 環境としては、「 Visual C++ 1.0 」の前の「 C/C++ Compiler 7.0 」から付属している。
わんくま同盟 東京勉強会 #78
なんでいまどき MFC?
• ロジックだけじゃなくて UI も C++ で書きたい。
• 受けれる仕事の幅を増やしたい。
わんくま同盟 東京勉強会 #78
MFC( というよりネイティブ GUI) の利点
• .NET バージョンやラッパーの用意されていないネイティブライブラリを低コストで呼び出すことが出来る。
• ネイティブなので速いはず。• 実行時にネイティブに変換されるから速
度は変わらないという話もあるが、すくなくても ネイティブへの変換コストが掛からないはず。 (JIT コンパイル? )
わんくま同盟 東京勉強会 #78
MFC の欠点
• MSDN に初心者向けチュートリアルがない– MFC 自体をある程度使える前提で
新し目の機能 ( リボンインターフェースなど )に対応というようなチュートリアルはある
– 初心者向けに 0 から作るようなチュートリアルがない。
– 各技術項目を読んで理解する必要がある。
わんくま同盟 東京勉強会 #78
MFC の欠点
• リファレンスもない。パブリック クラス メンバーおよびプロテクト クラス メンバーは、アプリケーション プログラムや派生クラスでよく使われるものだけを取り上げています。 全クラス メンバーの一覧は、クラスのヘッダー ファイルを参照してください。
http://msdn.microsoft.com/ja-jp/library/d06h2x6e.aspx
ソース読め
わんくま同盟 東京勉強会 #78
MFC の欠点 (by wikipedia)
• CDocument, CView 等の基本的なクラスの仕様が難解である。
• Windows メッセージ、コマンド等のWin32 API の基本を理解していることが前提。
• すべての構造体、クラスおよび列挙型などがグローバル名前空間に存在している。
• マクロが多用されているため、識別子の衝突、競合が発生しやすい。
わんくま同盟 東京勉強会 #78
MFC の欠点 (by wikipedia)
• MFC が作られたのが C++ の標準化以前であるため、例外処理、実行時型情報などの機能がマクロを使用した独自実装となっているため、標準 C++ に慣れたユーザーは戸惑う
わんくま同盟 東京勉強会 #78
最初から生の WinAPI にしておけば良かった
(´ ・ ω ・ `)
わんくま同盟 東京勉強会 #78
でもセッションもう頼まれちゃったしがんばる。
( `・ ω ・ ´)
わんくま同盟 東京勉強会 #78
とりあえずデフォルト設定でプロジェクトを作ってみる
わんくま同盟 東京勉強会 #78
プロジェクトテンプレートからMFC アプリケーションを選択
わんくま同盟 東京勉強会 #78
わんくま同盟 東京勉強会 #78
わんくま同盟 東京勉強会 #78
わんくま同盟 東京勉強会 #78
わんくま同盟 東京勉強会 #78
わんくま同盟 東京勉強会 #78
わんくま同盟 東京勉強会 #78
わんくま同盟 東京勉強会 #78
わんくま同盟 東京勉強会 #78
設定項目が多すぎてなにやら
ありがた迷惑臭が漂います
わんくま同盟 東京勉強会 #78
デフォルトプロジェクト 設定
• アプリケーションの種類:マルチドキュメント
• ドキュメント/ビューアーキテクチャー• プロジェクト形式: VisualStudio• Visual スタイルと色 :Visual Studio 2008
わんくま同盟 東京勉強会 #78
プロジェクトを作った状態
わんくま同盟 東京勉強会 #78
デフォルトプロジェクト
• デザイナが開いていない• .cpp ファイル 11 個• .h ファイル 13 個• リソースファイル 27 個
わんくま同盟 東京勉強会 #78
デフォルト設定にしては大き過ぎないか?
と思いつつコンパイル
わんくま同盟 東京勉強会 #78
なにやら Visual Studio 的なものが完成
わんくま同盟 東京勉強会 #78
とりあえずもう少しシンプルなものが作りた
い
わんくま同盟 東京勉強会 #78
とりあえず、最初の画面だけシンプルなそうな設定にしてみる。
わんくま同盟 東京勉強会 #78
わんくま同盟 東京勉強会 #78
シンプル?プロジェクト 設定
• アプリケーションの種類:シングルドキュメント
• ドキュメント/ビューアーキテクチャー• プロジェクト形式: MFC 標準• Visual スタイルと色 :Windows ネイティ
ブ /既定
わんくま同盟 東京勉強会 #78
シンプルプロジェクト
• 相変わらずデザイナなし• .cpp ファイル 5 個• .h ファイル 7 個• リソースファイル 7 個
わんくま同盟 東京勉強会 #78
だいぶシンプルになったけど
わんくま同盟 東京勉強会 #78
それでも色々付いてます。
わんくま同盟 東京勉強会 #78
デザイナなし・まとめ
• ウィザードの最初の画面をいじるだけだと最小限のものは作れない。
• 本当に最小限のプロジェクトを作ろうとするとめんどくさそう
• そもそも最小限の状態から作り始めるものじゃないかもしれない。
• ウィザードで雛形を作ってそれを元にしてアプリケーションを作っていくべき?
わんくま同盟 東京勉強会 #78
デフォルト設定じゃないけどちゃんとデザイナもあります。
わんくま同盟 東京勉強会 #78
わんくま同盟 東京勉強会 #78
デザイナはリソースビューから選択可能
わんくま同盟 東京勉強会 #78
今回は割とシンプルなものが出来上がります
わんくま同盟 東京勉強会 #78
最初からボタンが 2つ
クリックするとダイアログが閉じアプリケーションが終了します。DialogResult 的な物
わんくま同盟 東京勉強会 #78
最初からボタンが 2つ
開発時にダブルクリックすると、 OnBnClickedOK(),OnBnClickedCancel() が作られる。内部で OnOK(), OnCancel(); を呼び出している
わんくま同盟 東京勉強会 #78
• とりあえずコントロールを削除してみる• 削除しても Enter/Esc を押せば閉じてしまう。• OnBnClickedOk()/Cancel() で呼び出されている
CDialogEx::OnOK()/OnCancel() を削除すればキーを押しても閉じなくなる。
void CDialog1Dlg::OnBnClickedOk(){ // TODO: ここにコントロール通知ハンドラー コードを追加します。 CDialogEx::OnOK(); }
ダイアログが勝手に閉じないようにする。
←コレを消す
わんくま同盟 東京勉強会 #78
ダイアログが勝手に閉じないようにする。( Cancel)
• OnCancel() の呼び出しを消してしまうとEsc ボタンだけじゃなくて閉じるボタンや Alt+F4 でもウィンドウが閉じられなくなってしまう
※(ウィンドウを閉じようとするとOnBnClickedCancel() が呼び出され、その中で閉じる処理 ( OnCancel() ) が行われるため
わんくま同盟 東京勉強会 #78
Esc キーでダイアログが閉じないようにする。
BOOL CDialog1Dlg::PreTranslateMessage(MSG* pMsg)
{
if( WM_KEYDOWN == pMsg->message )
{
if(pMsg->wParam == VK_ESCAPE)
{ return FALSE; }
}
return CDialogEx::PreTranslateMessage(pMsg);
}
Esc では閉じず他の手段では閉じるようにするためには、PreTranslateMessage をオーバーライドする必要がある。
わんくま同盟 東京勉強会 #78
MFC の正しい使い方?
• デザイナなし (Doc-View 等 ) でアプリ本体を作って設定ダイアログ等をダイアログベースで作るのが MFC の正しい使い方っぽい?
• アプリの内容にもよるがダイアログベースで全部作ってしまう事のほうが多そうな気も……
わんくま同盟 東京勉強会 #78
とりあえずなんか作る
• ボタンをクリックするとテキストボックスの中身がメッセージダイアログで表示される
• ダイアログボックスを閉じるとテキストコントロールにそのテキストボックスの中身を表示する。
• WinForms であればコントロールに対応する変数を操作すればすぐ出来る簡単なアプリ
わんくま同盟 東京勉強会 #78
とりあえず、コントロールを配置
わんくま同盟 東京勉強会 #78
コントロールに対応した変数が作られていない。
// CDialog1Dlg ダイアログclass CDialog1Dlg : public CDialogEx{ // ~略~public: afx_msg void OnBnClickedOk(); afx_msg void OnBnClickedCancel();
virtual BOOL PreTranslateMessage(MSG* pMsg); afx_msg void OnBnClickedButton1();
};
わんくま同盟 東京勉強会 #78
コントロールを選択して右クリック→変数の追加
わんくま同盟 東京勉強会 #78
変数のカテゴリ
• Value
主に表示している文字列に対応した変数 int,CString 等
• Control
配置したコントロールに対応したクラス CStatic,CButton,CEdit 等
わんくま同盟 東京勉強会 #78
変数の追加結果
// CDialog1Dlg ダイアログclass CDialog1Dlg : public CDialogEx{ // ~略~public: afx_msg void OnBnClickedOk(); afx_msg void OnBnClickedCancel();
virtual BOOL PreTranslateMessage(MSG* pMsg); afx_msg void OnBnClickedButton1();
CEdit TextBox1; // テキストボックスに対応した Controll変数 CString LabelText; // ラベルの文字列に対応した Value 変数
};
わんくま同盟 東京勉強会 #78
DDX/DDV
void CDialog1Dlg::DoDataExchange(CDataExchange* pDX){ CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT1, TextBox1); DDX_Text(pDX, IDC_RESULT, LabelText); DDV_MaxChars(pDX, LabelText, 10);}
• 変数を追加すると DoDataExchange() にDDX/DDV系関数の呼び出しが追加される。
わんくま同盟 東京勉強会 #78
DDX/DDV
• DDX: Dialog Data eXchange
変数の内容を実際のコントロールに反映、 コントロールの内容を変数に反映させる。
• DDV: Dialog data validation
データの妥当性検査
わんくま同盟 東京勉強会 #78
DoDataExchange(CDataExchange* pDX)
• pDx のメンバー m_bSaveAndValidate が TRUEの場合
コントロールの内容を変数に反映する
• FALSE の場合 変数の内容をコントロールに転送する。
• CWnd::UpdateData(BOOL) で呼び出すことが出来る。
わんくま同盟 東京勉強会 #78
なんとなく MVC系でいう中間層的な動作をしている気がす
る。
※厳密な意味ではないので適当に聞き流して下さい
わんくま同盟 東京勉強会 #78
OnBnClickedButton1()
void CDialog1Dlg::OnBnClickedButton1(){ CString str; //文字列変数の作成
// テキストボックスの文字列を取得 TextBox1.GetWindowTextW(str);
// メッセージボックに表示 AfxMessageBox(str,IDOK);
// ラベルの文字列を更新 this->LabelText = str;
UpdateData(FALSE); // 反映}
わんくま同盟 東京勉強会 #78
問題点
• 追加した変数すべての DDX/DDV がDoDataExchange() に含まれるのでひとつの変数に関してだけ更新したいときでもすべての変数に対して更新されてしまう。
• 変数が多くなると、更新したいわけではない変数に対する処理のせいで動作が重くなる可能性がある。
わんくま同盟 東京勉強会 #78
CWnd::GetDlgItem(int nID )
• CWnd::GetDlgItem を用いることで、DoDataExChange() を使わずに、コントロールと関連付けられた変数へのポインタを取得できる。
void CDialog1Dlg::OnBnClickedButton1(){ CEdit* pTextBox = (CEdit*)this->GetDlgItem(IDC_EDIT1); CStatic* pLabel = (CStatic*)this->GetDlgItem(IDC_LABEL);
CString str; pTextBox->GetWindowTextW(str); AfxMessageBox(str,IDOK); pLabel->SetWindowTextW(str);}
わんくま同盟 東京勉強会 #78
ダイアログベース・まとめ
• 基本的には設定ダイアログ等を作るためのもの
• アプリ自体の作成に使うなら、必要に応じてOnOK OnCancel が呼び出されないように修正。
• 変数の追加、DDX/DDV関数でコントロールを操作する。
• DoDataExChange() の肥大化が気になる場合は GetDlgItem() でコントロール対応クラスへのポインタを取得
わんくま同盟 東京勉強会 #78
最後に
• ありがた迷惑設計だけど慣れればどうにかなりそう
• でも本格的に使うならフレームワーク的なものを作ったほうがいいかもしれない
• でもそれって自分で WinAPI を自分でラップして使うのとあまり変わりないのでは?