わんくまT78 mfcを始めようとしてみた

61
わわわわわわ わわわわわ #78 MFC わわわわわわわわわわ わ わわ
  • Upload

    -
  • Category

    Documents

  • view

    1.235
  • download

    5

Transcript of わんくまT78 mfcを始めようとしてみた

Page 1: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

MFC を始めようとしてみた

暁 紫電

Page 2: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

自己紹介

• HN :暁 紫電• 本名: 伊藤 伸男• 職業: フリーランス・プログラ

マー使用言語  C++  C++/CLI  C#

Page 3: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

本日のアジェンダ

• MFC とは?• なんでいまさら MFC• MFC の利点/欠点• とりあえずプロジェクトを作ってみる• ダイアログベース• まとめ

Page 4: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

MFC とは

• マイクロソフトが Windows アプリ作成用のフレームワークとして開発したライブラリ。

• 環境としては、「 Visual C++ 1.0 」の前の「 C/C++ Compiler 7.0 」から付属している。

Page 5: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

なんでいまどき MFC?

• ロジックだけじゃなくて UI も C++ で書きたい。

• 受けれる仕事の幅を増やしたい。

Page 6: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

MFC( というよりネイティブ GUI) の利点

• .NET バージョンやラッパーの用意されていないネイティブライブラリを低コストで呼び出すことが出来る。

• ネイティブなので速いはず。• 実行時にネイティブに変換されるから速

度は変わらないという話もあるが、すくなくても ネイティブへの変換コストが掛からないはず。 (JIT コンパイル? )

Page 7: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

MFC の欠点

• MSDN に初心者向けチュートリアルがない– MFC 自体をある程度使える前提で

新し目の機能 ( リボンインターフェースなど )に対応というようなチュートリアルはある

– 初心者向けに 0 から作るようなチュートリアルがない。

– 各技術項目を読んで理解する必要がある。

Page 8: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

MFC の欠点

• リファレンスもない。パブリック クラス メンバーおよびプロテクト クラス メンバーは、アプリケーション プログラムや派生クラスでよく使われるものだけを取り上げています。 全クラス メンバーの一覧は、クラスのヘッダー ファイルを参照してください。

http://msdn.microsoft.com/ja-jp/library/d06h2x6e.aspx

ソース読め

Page 9: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

MFC の欠点 (by wikipedia)

• CDocument, CView 等の基本的なクラスの仕様が難解である。

• Windows メッセージ、コマンド等のWin32 API の基本を理解していることが前提。

• すべての構造体、クラスおよび列挙型などがグローバル名前空間に存在している。

• マクロが多用されているため、識別子の衝突、競合が発生しやすい。

Page 10: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

MFC の欠点 (by wikipedia)

• MFC が作られたのが C++ の標準化以前であるため、例外処理、実行時型情報などの機能がマクロを使用した独自実装となっているため、標準 C++ に慣れたユーザーは戸惑う

Page 11: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

最初から生の WinAPI にしておけば良かった

(´ ・ ω ・ `)

Page 12: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

でもセッションもう頼まれちゃったしがんばる。

( `・ ω ・ ´)

Page 13: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

とりあえずデフォルト設定でプロジェクトを作ってみる

Page 14: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

プロジェクトテンプレートからMFC アプリケーションを選択

Page 15: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

Page 16: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

Page 17: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

Page 18: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

Page 19: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

Page 20: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

Page 21: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

Page 22: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

Page 23: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

設定項目が多すぎてなにやら

ありがた迷惑臭が漂います

Page 24: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

デフォルトプロジェクト 設定

• アプリケーションの種類:マルチドキュメント

• ドキュメント/ビューアーキテクチャー• プロジェクト形式: VisualStudio• Visual スタイルと色 :Visual Studio 2008

Page 25: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

プロジェクトを作った状態

Page 26: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

デフォルトプロジェクト

• デザイナが開いていない• .cpp ファイル 11 個• .h ファイル 13 個• リソースファイル 27 個

Page 27: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

デフォルト設定にしては大き過ぎないか?

と思いつつコンパイル

Page 28: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

なにやら Visual Studio 的なものが完成

Page 29: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

とりあえずもう少しシンプルなものが作りた

Page 30: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

とりあえず、最初の画面だけシンプルなそうな設定にしてみる。

Page 31: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

Page 32: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

シンプル?プロジェクト 設定

• アプリケーションの種類:シングルドキュメント

• ドキュメント/ビューアーキテクチャー• プロジェクト形式: MFC 標準• Visual スタイルと色 :Windows ネイティ

ブ /既定

Page 33: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

シンプルプロジェクト

• 相変わらずデザイナなし• .cpp ファイル 5 個• .h ファイル 7 個• リソースファイル 7 個

Page 34: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

だいぶシンプルになったけど

Page 35: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

それでも色々付いてます。

Page 36: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

デザイナなし・まとめ

• ウィザードの最初の画面をいじるだけだと最小限のものは作れない。

• 本当に最小限のプロジェクトを作ろうとするとめんどくさそう

• そもそも最小限の状態から作り始めるものじゃないかもしれない。

• ウィザードで雛形を作ってそれを元にしてアプリケーションを作っていくべき?

Page 37: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

デフォルト設定じゃないけどちゃんとデザイナもあります。

Page 38: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

Page 39: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

デザイナはリソースビューから選択可能

Page 40: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

今回は割とシンプルなものが出来上がります

Page 41: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

最初からボタンが 2つ

クリックするとダイアログが閉じアプリケーションが終了します。DialogResult 的な物

Page 42: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

最初からボタンが 2つ

開発時にダブルクリックすると、 OnBnClickedOK(),OnBnClickedCancel() が作られる。内部で OnOK(), OnCancel(); を呼び出している

Page 43: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

• とりあえずコントロールを削除してみる• 削除しても Enter/Esc を押せば閉じてしまう。• OnBnClickedOk()/Cancel() で呼び出されている

CDialogEx::OnOK()/OnCancel() を削除すればキーを押しても閉じなくなる。

void CDialog1Dlg::OnBnClickedOk(){   // TODO: ここにコントロール通知ハンドラー コードを追加します。   CDialogEx::OnOK(); }

ダイアログが勝手に閉じないようにする。

←コレを消す

Page 44: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

ダイアログが勝手に閉じないようにする。( Cancel)

• OnCancel() の呼び出しを消してしまうとEsc ボタンだけじゃなくて閉じるボタンや Alt+F4 でもウィンドウが閉じられなくなってしまう

※(ウィンドウを閉じようとするとOnBnClickedCancel() が呼び出され、その中で閉じる処理 ( OnCancel() ) が行われるため

Page 45: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #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 をオーバーライドする必要がある。

Page 46: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

MFC の正しい使い方?

• デザイナなし (Doc-View 等 ) でアプリ本体を作って設定ダイアログ等をダイアログベースで作るのが MFC の正しい使い方っぽい?

• アプリの内容にもよるがダイアログベースで全部作ってしまう事のほうが多そうな気も……

Page 47: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

とりあえずなんか作る

• ボタンをクリックするとテキストボックスの中身がメッセージダイアログで表示される

• ダイアログボックスを閉じるとテキストコントロールにそのテキストボックスの中身を表示する。

• WinForms であればコントロールに対応する変数を操作すればすぐ出来る簡単なアプリ

Page 48: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

とりあえず、コントロールを配置

Page 49: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

コントロールに対応した変数が作られていない。

// CDialog1Dlg ダイアログclass CDialog1Dlg : public CDialogEx{   // ~略~public:   afx_msg void OnBnClickedOk();   afx_msg void OnBnClickedCancel();

   virtual BOOL PreTranslateMessage(MSG* pMsg);   afx_msg void OnBnClickedButton1();

};

Page 50: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

コントロールを選択して右クリック→変数の追加

Page 51: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

変数のカテゴリ

• Value

  主に表示している文字列に対応した変数   int,CString 等

• Control

  配置したコントロールに対応したクラス   CStatic,CButton,CEdit 等

Page 52: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #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 変数

};

Page 53: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #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系関数の呼び出しが追加される。

Page 54: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

DDX/DDV

• DDX: Dialog Data eXchange

 変数の内容を実際のコントロールに反映、 コントロールの内容を変数に反映させる。  

• DDV: Dialog data validation

 データの妥当性検査

Page 55: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

DoDataExchange(CDataExchange* pDX)

• pDx のメンバー m_bSaveAndValidate が TRUEの場合

 コントロールの内容を変数に反映する

• FALSE の場合 変数の内容をコントロールに転送する。

• CWnd::UpdateData(BOOL) で呼び出すことが出来る。

Page 56: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

なんとなく MVC系でいう中間層的な動作をしている気がす

る。

※厳密な意味ではないので適当に聞き流して下さい

Page 57: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

OnBnClickedButton1()

void CDialog1Dlg::OnBnClickedButton1(){   CString str;    //文字列変数の作成

   // テキストボックスの文字列を取得   TextBox1.GetWindowTextW(str);

   // メッセージボックに表示   AfxMessageBox(str,IDOK);

   // ラベルの文字列を更新   this->LabelText = str;

   UpdateData(FALSE);   // 反映}

Page 58: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

問題点

• 追加した変数すべての DDX/DDV がDoDataExchange() に含まれるのでひとつの変数に関してだけ更新したいときでもすべての変数に対して更新されてしまう。

• 変数が多くなると、更新したいわけではない変数に対する処理のせいで動作が重くなる可能性がある。

Page 59: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #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);}

Page 60: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

ダイアログベース・まとめ

• 基本的には設定ダイアログ等を作るためのもの

• アプリ自体の作成に使うなら、必要に応じてOnOK OnCancel が呼び出されないように修正。

• 変数の追加、DDX/DDV関数でコントロールを操作する。

• DoDataExChange() の肥大化が気になる場合は GetDlgItem() でコントロール対応クラスへのポインタを取得

Page 61: わんくまT78 mfcを始めようとしてみた

わんくま同盟 東京勉強会 #78

最後に

• ありがた迷惑設計だけど慣れればどうにかなりそう

• でも本格的に使うならフレームワーク的なものを作ったほうがいいかもしれない

• でもそれって自分で WinAPI を自分でラップして使うのとあまり変わりないのでは?