「私はド素人、内容には全く自身を持てません」状態からヨチヨチ歩き程度に上達できたと思う今日この頃なので、一旦内容を整理した。


VC++ ver.6 を使用中。

*VS 2003 に浮気してみる [#b7513908]
-「ファイルを開く」際、「開く」ボタンの右からプルダウンを出してアプリケーションを指示すると、リソーススクリプトがテキストエディタで開ける!

**MFCとWM_INITDIALOG [#e7ed879d]
.net 2003 で、例えばダイアログのイベントハンドラを追加する場合は、プロパティから「メッセージ」のアイコンを選んでゴニョゴニョすれば良いが、ここにWM_INITDIALOGが無かったので腹が立った。

原因は、これはオーバーライドするハンドラだからなのであった。これを表示するにはクラスビューを表示させた状態(フロートにすると良い)でプロパティを選ぶ。すると直方体の「オーバーライド」ボタンが登場するので、ここからOnInitDialogを選択してゴニョゴニョすると良い。このあたりはプロパティウィンドウをフロートにしてF1でヘルプを呼ぶと書いてある。でも、ここまで気づくのは相当難しいのではないのか。

-[[MFCを使ったダイアログの初期化で・・・:http://forums.belution.com/ja/vc/000/176/44s.shtml]]


**MFCのアプリケーションウィザードのActiveXコントロールのチェックボックスの役目 [#l1768d41]
ヘルプからの抜粋:

「このオプションを選択せず、後で ActiveX コントロールをプロジェクトに追加する必要が生じた場合には、アプリケーションのメンバ関数 InitInstance に AfxEnableControlContainer の呼び出しを追加する必要があります。 」


*Win32API [#m7786998]

いわゆるSDKプログラミング。これを知らねばはじまらない
**link [#we9c2ad9]
-[[WisdomSoft:http://wisdom.sakura.ne.jp/]] WinAPIはもとより、各言語が広範に渡り解説されている。
-[[Win32 プログラミング入門:http://www7.plala.or.jp/keny01/windows/win32/]]
-[[猫でもわかるプログラミング(biglobe):http://www2m.biglobe.ne.jp/~yasutaka/]] 定番。MFCもあり
-[[VC++ programming tips:http://win32lab.com/tips/]]

**メモ [#ya71b298]
-MapVirtualKeyによって、仮想キーコードからスキャンコードに変換ができる。
-リストビューまわりをAPIの直叩きだけでなんとかするのは結構つらい。でもListView_から始まる一連のマクロが定義されており、これらを使うと多少楽になる。例えば「一行まるまる選択」するためのオプションは LVS_EX_FULLROWSELECT だが、これは ListView_GetExtendedListViewStyle で取得できる。
-1行表示のエディットコントロールで、表示しきれない量のテキストをWM_SETTEXTした後に、末尾のほうを優先して見たいので最後(右端)までスクロールさせたいなあと思った。

 SendMessage(hEdit,EM_SETSEL,0,-1); //全選択
 SendMessage(hEdit,EM_SETSEL,-1,-1); //解除

でうまくいった。[[エディットコントロールについて。:http://forums.belution.com/ja/vc/000/125/61s.shtml]]
-プリコンパイル済ヘッダを使用する際には、各実装ファイルについて適切にヘッダ(stdafx.h)をインクルードしないとC1010エラーで怒られてしまう。外部からもってきたソースコードなんかでインクルードディレクトリをいじりたくないなんて場合は、FileViewから設定を選び、C/C++タブの「プリコンパイル済みヘッダー」カテゴリから、「使用しない」を選択すればよい。
-アイコンはウィンドウクラス登録時に wc.hIcon = LoadIcon (NULL, MAKEINTRESOURCE(IDI_MYICON)); として指定。
-外部プロセス起動はWinExec
-Windowsは、各プロセスに固有のインスタンスハンドルを割当てる
-ウィンドウプロシージャはWindowClassで定義。戻り値は多分重要でない。デフォルトの挙動は DefWindowProc で実現されるので、望むメッセージ処理の後にこれを入れると良い。CALLBACK修飾子が宣言されねばならない。
-別なプログラムのウィンドウハンドル取得するには FindWindow、WindowFromPointあたりを使う。FindWindowExで子ウィンドウも検索できる。[[プログラムのウィンドウハンドルの取得:http://www14.big.or.jp/~ken1/tech/tech8.html]]も参照。
-ダイアログボックスと(グローバル変数を使わずに)データのやりとりをするには、DialogBoxParamを使う。やりとりしたいデータを構造体にしておいて、最後の引数にそこへのポインタを指定すると良い。
-コモンコントロールについては[[猫でもわかるプログラミング(biglobe):http://www2m.biglobe.ne.jp/~yasutaka/]]より[[第111章 ツリービューの基礎:http://www2m.biglobe.ne.jp/~yasutaka/sdk2/sdk_111.htm]]を見よ
-ファイルの存在の有無の確認は _access が良さそうである(CFile::GetStatus()でもOK)。参考:[[「CFILEしかないですかね?」:http://forums.belution.com/ja/vc/000/186/39s.shtml]]
-ダイアログで、バツを押しても(WM_CLOSEの後に)IDCANCELが飛んでくる(あれば)。[[Win32API(C言語)編 第5章 メッセージボックス:http://www.geocities.jp/ky_webid/win32c/005.html]]
-VS6で警告レベルを上げたら、次の様な警告が出るようになった。
 d:\program files\microsoft visual studio\vc98\include\rpcasync.h(45) : warning C4115: '_RPC_ASYNC_STATE' : 関数の仮引数リストで構造体、共用体、列挙型の定義に使われました。
件のヘッダを覗いてみたが、大元で正しく前方参照されていないのが原因のようだ。個々のファイルで
 #pragma warning(disable : 4115)
してもいいが、やはり前方参照
 struct _RPC_ASYNC_STATE;
を大元のヘッダに埋めこんでしまうのが根本的な解決なのだろう。ベンダ提供のヘッダを書換えるのはヤな感じだが、しかたがない。

-win32apiの中にはCランタイム関数互換のものも沢山ある。Cランタイムはwin32apiによって実装されてるそうなので、apiを呼び出したほうが何かと良いのかも。lstrlen、lstrcpy、CopyMemoryとか。see - http://www.biwa.ne.jp/~chu2/laboratory/win32api.html

-ウィンドウを作る時は、ウィンドウのサイズを指定するわけであって、クライアント領域の大きさを指定できるわけではない。クライアント領域の大きさを指定することで、ウィンドウのサイズを求めるには AdjustWindowRect を用いる。

-ウィンドウのスタイルなどは、定数をor演算子で結合して複数の属性を与える。あらかじめ幾つか混じった定数が用意されている場合もあるが、「この属性を取り除きたい」と思った場合は以下のようにする。
 WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME

-リソースエディタで、「このサイズのアイコンを消したい」と思ったら、メニューから「イメージ ==> デバイスイメージの削除」とする。


**サブクラス化 [#eeb1b25e]
コントロールのウィンドウプロシージャとして、自前の関数を登録することができる。

 WNDPROC PrevWndProc; 
 
 LRESULT CALLBACK MyWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
   if(uMsg == WM_LBUTTONDBLCLK){
     MessageBox(GetParent(hWnd), TEXT("double-click hello"), TEXT(""), MB_OK);
     return 0;
   }
   return CallWindowProc(PrevWndProc, hWnd, uMsg, wParam, lParam);
 }
 
 void some_initialization_func(){
   // ...
   HWND hwndTargetCtrl = GetDlgItem(hWndDlg, IDC_TARGET_CONTROL);
   PrevWndProc = (WNDPROC)GetWindowLong(hwndTargetCtrl, GWL_WNDPROC);
   SetWindowLong(hwndTargetCtrl, GWL_WNDPROC, (LONG)MyWndProc);
   // ...
 }

などとする。上の例では、コントロールにおけるダブルクリックはメッセージボックスに置き換わる。CallWindowProc してやればデフォルトの処理が実行されるので、記述するのは自分の欲しい機能だけでOK。

**フルパスからファイル名を取得する。 [#a7a46d8c]
_splitpath() あるいは http://www3.ocn.ne.jp/~liquidz/tips/tips_cpp000.htm

**フォルダ選択ダイアログ [#afb633ca]
全て http://homepage2.nifty.com/DSS/VCPP/API/SHBrowseForFolder.htm にて学んだこと。
 #include <shlobj.h>
 static bool ChooseDirectory(LPSTR NewDir, HWND hwndOwner = NULL){
 
     // see http://homepage2.nifty.com/DSS/VCPP/API/SHBrowserForFolder.htm
     BROWSEINFO bi;
     LPSTR lpBuffer;
     LPITEMIDLIST pidlBrowse;
     LPMALLOC lpMalloc = NULL;
 
     HRESULT hr = SHGetMalloc(&lpMalloc);
     if(FAILED(hr)) return false;
 
     if((lpBuffer = (LPSTR)lpMalloc->Alloc(_MAX_PATH)) == NULL) return false;
     bi.hwndOwner = hwndOwner;
     bi.pidlRoot = 0;    // desktop is the root
     bi.pszDisplayName = lpBuffer;
     bi.lpszTitle = TEXT("Choose your favourite directory...");
     bi.ulFlags = 0x0040; //BIF_NEWDIALOGSTYLE
     bi.lpfn = 0;
     bi.lParam = 0;
     pidlBrowse = SHBrowseForFolder(&bi);
     bool copied = false;
     if(pidlBrowse != NULL){    // not canceled
         if(SHGetPathFromIDList(pidlBrowse, lpBuffer)){
             lstrcpy(NewDir, lpBuffer);
             copied =  true;
         }
         lpMalloc->Free(pidlBrowse);
     }
     lpMalloc->Free(lpBuffer);
     lpMalloc->Release();
     return copied;
 }


**ダイアログとWM_KEYDOWN [#z66a7966]
標準では、ダイアログプロシージャでWM_KEYDOWNは拾えないようだ。
-[[ダイアログボックス上でWM_KEYDOWNを捕まえる:http://hpcgi1.nifty.com/MADIA/Vcbbs/wwwlng.cgi?print+200411/04110065.txt]]
-[[ダイアログボックスでのWM_KEYDOWNメッセージの取得方法?:http://forums.belution.com/ja/vc/000/056/63s.shtml]]


**スレッド [#y72188d5]
わけのわからないバグは大抵スレッドに絡んでいるが、この前遭遇したわかりにくいバグ(私にとっては。多分初歩のミス)もやっぱりスレッドまわりだったのでメモ。

::WaitForSingleObject という関数があるが、これはカーネルオブジェクトでキッチリ同期をとってくれるスグレモノであるが、キッチリwaitしてくれたおかげでメッセージループも回らなくなり、これが原因でよくわからないバグになっていた。メッセージループ(ウィンドウ)を持つスレッドの場合は、代わりに::MsgWaitForMultipleObjectsExを用いて、カーネルオブジェクトを待ちつつメッセージを処理するべきである。よく見たらそのようにMSDNにも書いてあった。

ここで、CoInitializeなんかは間接的にウィンドウを作るので、明示的にウィンドウを作らないがCoInitializeを呼ぶスレッドなんかも、同様の理由で::WaitForSingleObjectを使うべきではないようだ。


**メッセージクラッカー [#l47095ac]
ウィンドウプロシージャは大抵飛んでくるメッセージをさばくのにswitch文を使う。処理すべきメッセージなんてのは大抵沢山あるので、巨大なswitch文になりがちだが、これがまた美しくない。そこで、メッセージクラッカーと呼ばれているwindowsx.hで定義されている一連のマクロを使うと比較的すっきりとメッセージ処理が記述できる。直接APIを叩いてアプリケーションを作る場合にとても重宝する。

・・・と、Jeffrey RichterのAdvanced Windowsに書いてあった。試してみたが、ダイアログプロシージャを以下の様にすっきりと記述できて満足。

 BOOL CALLBACK DialogProc(HWND hwnd, UINT uMsg, WPARAM wp, LPARAM lp){
 	switch(uMsg){
 		hiHANDLE_DLGMSG(hwnd,	WM_INITDIALOG,	Dlg_OnInitDialog);
 		hiHANDLE_DLGMSG(hwnd,	WM_CLOSE,		Dlg_OnClose);
 		hiHANDLE_DLGMSG(hwnd,	WM_COMMAND,		Dlg_OnCommand);
 		hiHANDLE_DLGMSG(hwnd,	WM_COPYDATA,	Dlg_OnCopyData);
 	}
 	return FALSE;
 }

正しくは(ダイアログプロシージャの場合)、以下のようなマクロを前もって定義しておく必要がある。
 /////////////////////////////////////////////////////////////////////
 // The macro (message cracker) is almost same as that of Jeffrey Richter's "CmnHdr.h".
 // Just the names of the variables are different from the original ones.
 #define hiHANDLE_DLGMSG(hwnd, message, fn)			\
 	case(message): return (SetDlgMsgResult(hwnd, uMsg,	\
 		HANDLE_##message((hwnd),(wp),(lp),(fn))))
 /////////////////////////////////////////////////////////////////////




Dlg_OnInitDialogなどとあるのがハンドラの関数名である。これらのプロトタイプはwindowsx.hに与えられている。でもWM_COPYDATAのが書いてない。これは以下のようになる。
 BOOL Dlg_OncopyData(HWND hwnd, HWND hwndFrom, PCOPYDATASTRUCT pcds)

ただし、SetDlgMsgResultはあんまり賢くないみたいで、キャスト関連でC4244の警告が出る。
-http://www.codeguru.com/forum/showthread.php?threadid=279743

[[メッセージクラッカー・ビューア:http://www.vector.co.jp/soft/dl/win95/prog/se161043.html]]なるものを作ってらっしゃる方もおられた。


**ファイルの列挙 [#nbcf8241]
-[[ディレクトリのファイルを列挙する:http://www.geocities.jp/monalipse/c/api/396.html]]
-[[サブフォルダ(サブディレクトリ)も含めてファイルを検索するには?:http://techtips.belution.com/ja/vc/0083/]]

FindFirstFileとFindNextFileを駆使する。例えばファイル数が知りたければ以下のようにする。ファイル名はWIN32_FIND_DATAのcFileNameでわかる。

 int count_files(const TCHAR* mask){
   WIN32_FIND_DATA w32fd;
   HANDLE hfind = FindFirstFile(mask, &w32fd);
   int i = 0;
   if (hfind != INVALID_HANDLE_VALUE) {
     do {
       i++;
     } while(FindNextFile(hfind, &w32fd));
   }
   return i;
 }



**クリップボード [#xb3ea56a]
-[[[mfc 33455] Re: クリップボードのデータを直接保存:http://search.acty-net.ne.jp/mfc_search/archive/2001-2/msg00922.html]]
-[[第5回 クリップボード その2:http://home.h07.itscom.net/buruturi/VCTIPS_005.html]]
-[[「きっちり!テキスト行末揃え」 (クリップボード操作編):http://home.a03.itscom.net/tsuzu/programing/tips43/]]
-[[第95章 クリップボード その2:http://www.kumei.ne.jp/c_lang/sdk/sdk_95.htm]]

**DoEvents [#qe3a68ea]
VB6でいうところのDoEventsは以下(なのだそうだ。出典は失念)
 MSG msg;
 if(::PeekMessage(&msg,NULL,0,0,PM_REMOVE)){
     ::TranslateMessage(&msg);
     ::DispatchMessage(&msg);
 }


**DLLを使う [#s54fcce6]
インポートライブラリを使ってビルド時に関数を参照する方法と、実行中に動的に関数を参照する方法とがある。

以前A社の計測装置を購入した際、USBによる操作用にDLLが添付されてきたことがあった(実はそれがお目当て)。しかし、言語のサポートとしてはVisual Basic用の標準モジュールのみで、インポートライブラリはもちろんCのヘッダもなかった。その時標準モジュールを参考にヘッダを書き、何とか動的呼び出しにまでこじつけたのが勉強したきっかけ。

-[[ダイナミックリンク:http://wisdom.sakura.ne.jp/system/winapi/win32/win149.html]]
-[[DLLの動的呼出:http://www10.plala.or.jp/yaoshi/masa/comp/prog/dll.html]]

お目当ての関数ポインタには、ちゃんと自ら型(引数、戻り値)を指定してやる。
-[[[00021443](SET)] 実引数が多すぎます:http://forums.belution.com/ja/vc/000/214/43s.shtml]]

DLLと .def ファイルがあればインポートライブラリが作れるみたいだ!? 中身は全く理解していないが
 lib /def:my_def_file.def
とすれば .libができるみたい。実際にできた。[[The Code Project - CppSQLite - C++ Wrapper for SQLite - Database:http://www.codeproject.com/database/CppSQLite.asp]]を参考にした。


*IDEの操作 [#hc7c1a0f]
ジワジワと操作を覚え、ジワジワと便利になってゆくもの
**メモ [#ze396a69]
-プロジェクト >> プロジェクトへ追加 >> 新規作成 としてファイルを追加。
-デバッグ・リリースビルドは、ビルド >> アクティブな構成の設定 から選択。
-選択範囲にインデントを適用したい場合、編集 >> 高度な操作 >> 選択範囲の書式自動設定
-インテリセンスが出なくなって困ったら*.ncbと*.optを削除してワークスペースを開きなおせば良いということを、[[http://search.acty-net.ne.jp/mfc_search/archive/2001-1/msg03130.html]] にて学んだ。

**ライブラリ [#j6aef7a0]
ある関数に必要なヘッダとライブラリはヘルプに記載されている。ヘッダは include すれば良い。ライブラリは
-プロジェクト >> プロジェクトへ追加 >> ファイル
-プロジェクト >> 設定 >> リンク >> オブジェクト/ライブラリ モジュール

のいずれかで追加する(両者はどう違うのだ?)

-pragmaでライブラリが追加できる。超便利。
 #pragma comment(lib,"msxml2")

だけどインクルードパスの追加はできないみたい。




*全般的なこと [#z5f81526]

**link [#f5ec93c8]
-[[VC++超初心者のホームページ:http://www.mtakahashi.com/]]
-[[Object Pascal, C/C++, VBのデータ型:http://homepage1.nifty.com/susho/windoze/datatype.html]]

**メモ [#f96ee3cf]
-ウィンドウのサイズ関連の話題については[[「ボタンによって、ウインドウスタイルを変更するには?」:http://homepage1.nifty.com/MADIA/vc/vc_bbs/200310_03100031.html]]が勉強になった。
-GetCurrentDirectoryなるAPIでは、MAX_PATH というマクロが活躍するっぽい。



**同種のコントロールたちを、例えばVBのコントロール配列の様にして一括して処理したい [#zb7b0798]
-[[同種複数のメッセージをひとつのハンドラで処理する-2. コントロール編 + DDX 変数の配列:http://www.interq.or.jp/jazz/iijima/mfc/iijima/05range2.html]]

以下[[VC++超初心者のホームページ:http://www.mtakahashi.com/]]から。

-[[A7592 コントロール配列と同じことは?:http://www.mtakahashi.com/old/a7600.html#A7592]]
-[[A7371 ボタンを配列化したい:http://www.mtakahashi.com/old/a7375.html#A7371]]
-[[A3610 VBのコントロール配列の様な使い方:http://www.mtakahashi.com/old/a3625.html#A3610]]
-[[A3283 VBでいうコントロール配列をVCでするには:http://www.mtakahashi.com/old/a3300.html#A3283]]

自分で適当に配列を作って、コントロールIDを格納するのが(実装と理解の観点で)一番お手軽


**グラフ [#xc5a4a94]
SDKに限った話ではないが、VCでグラフを実現するのはそう簡単なことではなさそうだ。自分で描画することはできるが面倒くさいのでパス。そこで既存のものを使いたくなるわけだが、標準でついてくるのはMSChartくらい。VBから使うのは簡単だが、VCから使うにはかなりのクセモノである上に文書も少ない。定番がどれなのかもよくわからない。[[CodeGuru:http://www.codeguru.com/]]でも乱立してるみたいだ。
-[[CodeGuru より Other Controls:http://www.codeguru.com/Cpp/controls/controls/]]

-[[株式会社インターフェース:http://www.interface.co.jp/]]に10,000円の市販ActiveXがある(試用版あり)。

**インストーラ [#p7f8959d]
[[National Instruments:http://www.ni.com]]の[[Measurement Studio:http://www.ni.com/mstudio/]]を使って、計測制御用のプログラムが使い慣れた言語でラクラク書けてとても幸せだが、成果物の配布にあたっては「インストーラを作りなさい」とのことであった。そういえばインストーラについては全く知らなかったのでWeb上の文書をひととおり調べた結果が以下。

-[[Windows Installer:http://www.cocky.to/Wininst/tools.html]]
-[[Visual Studio Installer:http://www.microsoft.com/japan/msdn/vstudio/downloads/vsi/]]
-[[love unstable: フリーなWindowsのインストーラ作成ツール:http://kumiki.c.u-tokyo.ac.jp/~ichiyama/mt/archives/000029.html]]
-[[Advanced Installer:http://www.advancedinstaller.com/]]
-[[Inno Setup:http://www.jrsoftware.org/isinfo.php]]
-[[NSIS:http://nsis.sourceforge.net/]]
-[[VBに適したインストーラを探そう:http://dobon.net/vb/installer/index.html]]
-[[のぶきちのホームページ:http://www5a.biglobe.ne.jp/~nobukich/index_j.htm]]
-[[かいちょのどうぐばこ:http://homepage1.nifty.com/BXW01421/]]

**Spy++とWinspector [#e467797a]
VC++付属のSpy++は色々調べるのに便利だが、フリーソフトの[[Winspector:http://www.windows-spy.com/]]はその機能を凌駕する。

*WTL [#v84678ad]
非常に大雑把にいうと「手動MFC亜種」。実行ファイルが軽いという利点がある。MFC、ClassWizardの動作を見つめなおすきっかけにもなる。

**link [#s62aa2ce]
-[[Roy.'s Homepage:http://homepage1.nifty.com/Roy_/index.htm]]より[[WTL研究所:http://homepage1.nifty.com/Roy_/Software/WTL/WTL.htm]]
-[[The So-Software Studio:http://home.att.ne.jp/banana/akatsuki/]]より[[ATL/WTLによるWindowsプログラミング:http://home.att.ne.jp/banana/akatsuki/doc/atlwtl/index.html]]
-[[Virtual Truth Lab.:http://lamoo.s53.xrea.com/]]より[[Develop:http://lamoo.s53.xrea.com/develop/index.html]]の項。GDI+の話題なども。
-[[かっとしの記録場所:http://www.mars.dti.ne.jp/~kattoshi/]]より[[Windows Template Library:http://www.mars.dti.ne.jp/~kattoshi/Program/]]
-[[The Code Project:http://www.codeproject.com/]]から[[WTL:http://www.codeproject.com/wtl/]]

**メモ [#edb2f589]
-DDX_TEXTでCStringを使おうとしたが、「この変換を実行可能なユーザー定義変換演算子がないか、または演算子を呼び出せません」と言われて怒られた。原因は面倒なので調べてないが、atlmisc.h を atlddx.h よりあとにincludeしていたのが原因のようであった。



*MFC [#hbf7de34]
業界標準のフレームワークだが、全くのWindowsプログラミング初学者が手を染めるべきではないと思う。(とりあえずは動作しても、何が何だかわからない状態になると思われる)

**link [#vd4dac63]
-[[Masayuki Tanaka's Home Page:http://www-kobayashi.ctrl.titech.ac.jp/~mtanaka/]]より[[Visual C++講座:http://www-kobayashi.ctrl.titech.ac.jp/~mtanaka/vc/]]
-[[VisualC++でソフトを作ろう:http://www.geocities.jp/chiakifujimon/]]
-[[MFC 実践プログラミング ヒント集:http://www.hi-ho.ne.jp/hawk/mfc0401.html]]

**メモ [#j68bf0c3]
-ラジオボタンは、プロパティでグループにチェックしておかなければ、ClassWizardのメンバ変数の覧に登場してくれないようである。
-MFCでプリコンパイル済みヘッダを利用している際には、全てのcppファイルについてstdafx.hをインクルードしておかなくてはいけない。([[MFCの森:http://www.page.sannet.ne.jp/t1533/program/tips.html]]における記述の抜粋にすぎません)
-AppWizardでオートメーションを選択すると、もれなくAfxOleInit()なる記述が追加される。これは内部でOleInitializeを呼び出しているとは聞いていたが、VC98/MFC/SRC/OLEINIT.CPP で実装を見ることができて、確かにOleInitializeがあった。
-印刷の際、紙の向きのデフォルトを変えたいなと思っていたら[[こちらの文書:http://www.hey-to.net/ML-archive/vcppML/2000/msg00084.html]]を見つけた。目的達成。
-[[MFC MDIアプリケーションで初期子ウインドウを開かないようにするには:http://homepage1.nifty.com/MADIA/vc/vc_bbs/200403_04030017.html]]
-[[タイトルにファイル名を出させない!:http://www.athomejp.com/goldfish/mfc/window/nonfilename.asp]]
-コントロールを動的にCreateする時に、どうやってuniqueなコントロールIDを割り振ればいいのだろう?uniqueでなくとも動作はするみたいだが、GetDlgItemが使えなくなる。(参考:[[コントロール動的Create時のIDのつけ方:http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200503/05030060.txt]])
-[[CDialogにCViewを貼り付ける:http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200408/04080002.txt]]
-[[ListViewで一行全体を選択:http://hp.vector.co.jp/authors/VA016117/listview.html]]
-[[オーナードローリストビュー:http://www.alpha-net.ne.jp/users2/uk413/vc/VCT_LVowner.html]]
-[[CFileDialogでの初期表示フォルダ:http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200207/02070028.txt]]

**消してもよいファイル [#v97adef1]
 *.aps;*.bsc;*.dll;*.exe;*.exp;*.idb;*.ilk;*.lib;*.ncb;*.obj;
 *.ocx;*.pch;*.pdb;*.plg;*.res;*.sbr;*.tlb;*.tlh;*.tli;*.trg
は消してもよいのだそうだ。http://www.mtakahashi.com/old/a2725.html での A2705「もろ」氏。まあ、「ビルドの際に自動で生成されるから」という理由だから、よそから引っ張ってきたdll、exe、lib、tlh、tliなどなどは当然消したらダメ。


**SDIウィンドウの作成 [#qe7f189e]
最初にAppWizardさんが作ってくれるが、後から自分で作りたい場合はどうすればよいか?
-[[「Kirikaの非人間的生活」より2005年7月26日:http://d.hatena.ne.jp/Kirika/20050726#1122409707]]
-[[子ウィンドウ作成:http://homepage2.nifty.com/DSS/VCPP/MFC/SDI/SDICreateChild.htm]]

に記述が見つかった。指定するリソースIDのメニューを前もって作っておかねばうまくいかなかった。

**CEditView [#df71b7b6]
-OnDrawの描画はすぐに消されてしまうそうだ[[mfc_ビュ-・CTRL(エディタに描画):http://www.page.sannet.ne.jp/mtoga/lang/cv/bih-m_71.htm]]。自由に描画するためにはWM_PAINTを捕まえるとよい。
-キャレットを消したいと思った。HideCaret()がどうもうまくいかないなあと思って2回連続でHideCaret()したら消えた。原因は不明だけとよしとする。(ひょっとしたらとんでもない間違いをしてるかも・・・)

**CHtmlView [#ec0c1936]
-CHtmlViewでイベントを拾うにはPreTranslateMessageをいじるのがbestのようである。[[2ch ■ VisualC++(MFC限定)相談室 5■ の465さん以下の議論より:http://pc3.2ch.net/tech/kako/1028/10285/1028553308.html]]
-[[CHtmlViewにメモリ上のHTMLテキストを表示するには:http://forums.belution.com/ja/vc/000/045/72s.shtml]]
-[[QHTM:http://www.gipsysoft.com/qhtm/]]の方がいいかも。


***COM絡み [#zcedc64c]
-[[CHtmlViewやWebBrowserに表示されたページ上に画像をのせる:http://mfc.acty-net.ne.jp/ml/mfc/logTop/logAll/00017202.shtml]]
-[[IEコンポーネントの使い方 [VC++の使い方]:http://www.nitoyon.com/vc/tips/ie_component.htm]]
-[[Loading HTML content from a Stream (Internet Explorer - WebBrowser):http://msdn.microsoft.com/workshop/browser/webbrowser/tutorials/webocstream.asp]]

**フォント [#u66d83fa]
フォントまわりは奥が深い。CreateFontの引数には泣きそうになる。よって、とりあえず動いたやつをメモとして貼る。CFontのメンバ関数とグローバルなAPIが同名だが、引数は同じっぽい。
 CreateFont(20, 0, 0, 0, FW_NORMAL, FALSE, FALSE, 0, SHIFTJIS_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, _T("MS ゴシック"));
CFontなら以下のようなお手軽設定も可能。
 hFont.CreatePointFont(15*10, _T("MS ゴシック"));
設定させるにはWM_SETFONTのwParamにHFONTをのせてやってメッセージを送る
 HFONT hFont;
 ...
 ::SendMessage(hWnd, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE,0));
か、CWndのSetFontメンバを使って
 SetFont(&hFont,TRUE); // CFont hFont;
とする。しかしCFontオブジェクトがローカル変数だとこれは失敗するので、CWndのメンバにしておくとよし。([[ナレッジウェア Tips3 - SetFont:http://www.kwi.co.jp/tips3.htm]])


**リストビュー [#m5fb3a72]
使用する際には、stdafx.hに Afxcview.h をインクルードしておくこと。リストビュー(CListView)は正体がリストコントロール(CListCtrl)なビュークラスだそうだ。ダイアログ等にリストコントロールを直接貼り付ける時と違い、スタイルはリソースから指定できない。「レポート」にするにはPreCreateWindow内で
 cs.style &= ~LVS_TYPEMASK;
 cs.style |= LVS_REPORT;
とする。その他SetExtendedStyleまわりはOnInitialUpdateに記述するとよし。(以上は[[ClistViewの表示がうまくいかない・・・。:http://www.mtakahashi.com/old/12000.html]]における記述を引用)

***オーナードロー、カスタムドロー [#r899ac49]
-[[Custom Draw items inside a ListView Control:http://www.codeguru.com/Cpp/controls/listview/article.php/c921]]
-[[カスタムドロー(NM_CUSTOMDRAW)を使用する:http://www24.cds.ne.jp/~neg/pro/piyo1/clc/custom.html]]


**ダイアログベースでEnter [#v834b7db]
[[「MFCでEnterキーが反応してしまう」:http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200408/04080061.txt]]のやりとりを参考にしました。

ダイアログのデフォルト動作では、Enterによって終了してしまう。これを変えるには例えば以下のようにする。
 BOOL CxxxDlg::PreTranslateMessage(MSG* pMsg)
 {
     if(pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN)
         return TRUE;
     return CDialog::PreTranslateMessage(pMsg);
 }


**ユーザー定義メッセージ [#fb6d6cb2]
MFCではメッセージマップをClassWizardで楽々記述できるのが大変らくちんなのだが、ユーザー定義メッセージを扱う際には手動でなくてはいけない。

-[[ユーザーメッセージ:http://homepage2.nifty.com/DSS/VCPP/API/UserMessage.htm]]


**エディットボックスの表示更新のタイミングについて [#rfe25aa8]
調べようと思ってとりあえず以下の文書を見つけたが、詳しい検証はしていない。

-[[http://search.acty-net.ne.jp/mfc_search/archive/2004-2/msg00085.html]]

**スレッド [#y9f3b3ae]
-AfxBeginThread でワーカスレッド作って、そこでもとのウィンドウのUpdateData呼出すとDebug Assertion Failedとなる件について、[[■ VisualC++(MFC限定)相談室 MFC7.dll■:http://pc2.2ch.net/tech/kako/1047/10479/1047949606.html]]の174,176,177さんがやりとりされていた。

-[[クラス関数をスレッドにする:http://homepage2.nifty.com/DSS/VCPP/MFC/Thread/ThreadClass.htm]]
-[[AfxBeginThreadを終了させたい:http://forums.belution.com/ja/vc/000/125/88s.shtml]]
-[[ワーカースレッドを呼び出し元から終了させたい:http://search.acty-net.ne.jp/mfc_search/archive/2001-1/msg03424.html]]

**'s'の初期化が'default'ラベルによって行われませんでした [#u05b3f1d]
switch文を使っていたら上記のようなエラー(C2361)に遭遇した。あるcaseのみで使う変数をそこで宣言した場合に、残りのcaseでもスコープが残っているけどいいのか、というニュアンスなのだそうだ。こんな時は変数を宣言・使用している箇所をブロックの中に閉じ込めてしまえばよい。

・・・という内容を http://frog.raindrop.jp/knowledge/archives/000223.html にて学びました。

**右クリックメニュー [#p7389b4f]
[[右クリックでポップアップメニューを出す方法:http://www.ne.jp/asahi/hishidama/home/tech/vcpp/popmenu.html]]を見て学んだ。このページに記述されていることではあるが、念のためこちらにも書く。何か処理をする(ハンドラを書く)ためにはメニューIDとハンドラとの対応をとってやらないといけない。このあたりはClassWizardにやらせるとラクだが、メニューIDを直接ソースに書くとClassWizardはそれに気づいてくれない。そこで、(実際にはどこにも使われないけど)メニューリソースをひとつ用意し、そこで適当な
メニューIDを登録しておけばよい。するとClassWizardはそれを認識してくれるので、同じメニューIDを用いれば右クリックメニューのハンドラが楽に実装できる。

*SDK雛型 [#k6883f62]
**シングルウィンドウ [#c29cbab0]
-[[WisdomSoft:http://wisdom.sakura.ne.jp/]]より[[終了処理:http://wisdom.sakura.ne.jp/system/winapi/win32/win11.html]]がベース。

 #include<windows.h>
 const char lpClassName[]="SDKTemplate";    // window class
 
 LRESULT CALLBACK WndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
     switch (msg) {
         case WM_COMMAND:
         switch(LOWORD(wp)) {
             //case BUTTON:
             //break;
             }
         break;
         case WM_DESTROY:
             PostQuitMessage(0);
             return 0;
         }
         return DefWindowProc(hwnd , msg , wp , lp);
 }
 
 int WINAPI WinMain(HINSTANCE hInst , HINSTANCE hPrevInstance , PSTR lpCmdLine , int nCmdShow ) {
     HWND hwnd;
     MSG msg;
     WNDCLASS winc;
 
     winc.style	= CS_HREDRAW | CS_VREDRAW;
     winc.lpfnWndProc = WndProc;
     winc.cbClsExtra = 0;
     winc.cbWndExtra = 0;
     winc.hInstance = hInst;
     winc.hIcon	= LoadIcon(NULL , IDI_APPLICATION);
     winc.hCursor = LoadCursor(NULL , IDC_ARROW);
     winc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
     winc.lpszMenuName = NULL;
     winc.lpszClassName = lpClassName;
 
     if (!RegisterClass(&winc)) return 0;
 
     hwnd = CreateWindow(
         lpClassName ,    // class name
         TEXT("My SDK") , // window name
         WS_OVERLAPPEDWINDOW | WS_VISIBLE ,
         100 , 100 , // horizontal, vertical position
         200 , 200 , // width and height
         NULL ,	// parent window
         NULL ,	// menu
         hInst , // application instance
         NULL // window-creation data
     );
 
     if (hwnd == NULL) return 0;
 
     while (GetMessage(&msg , NULL , 0 , 0)) DispatchMessage(&msg);
     return msg.wParam;
 }

**ダイアログベース [#z1ef9dde]

-[[初歩のVC++Programming Tips Win32SDK篇--ダイアログベースアプリケーションの作り方:http://win32lab.com/tips/tips11.html]]
-[[ダイアログウィンドウ:http://wisdom.sakura.ne.jp/system/winapi/win32/win89.html]]([[WisdomSoft:http://wisdom.sakura.ne.jp/]])
-[[skamachi's factory:http://skamachi.gotdns.com/index.html]]より[[ダイアログベース アプリケーション:http://skamachi.gotdns.com/sdk0.html]]
-[[u1271055のページ:http://home.hiroshima-u.ac.jp/u1271055/]]の[[SDK Programming Samples:http://home.hiroshima-u.ac.jp/u1271055/sdk/]]
-Jeffrey Richter "Advanced Windows"

以上を参考に作成しました。


 #include<windows.h>
 #include"resource.h"
 
 INT_PTR CALLBACK DialogProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
 {
   switch(msg){
   case WM_INITDIALOG:
     // initialize
     return TRUE;
   case WM_COMMAND:
     switch(LOWORD(wp)){
     case IDOK:
       EndDialog(hDlg,LOWORD(wp));
       return TRUE;
     case IDCANCEL:
       EndDialog(hDlg,LOWORD(wp));
       return TRUE;
     }
     break;
   case WM_CLOSE:
     PostQuitMessage(0);
     break;
   }
   return FALSE;
 }
 
 
 int WINAPI WinMain(HINSTANCE hinst, HINSTANCE, PTSTR pCmdLine, int nCmdShow)
 {
   DialogBox(hinst, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogProc);
   return 0;
 }

こちらはメッセージクラッカーを使用するもの。

 #include<windows.h>
 #include <windowsx.h>
 #include"resource.h"
 
 
 /////////////////////////////////////////////////////////////////////
 // The macro (message cracker) is almost same as that of Jeffrey Richter's "CmnHdr.h".
 // Just the names of the variables are different from the original ones.
 #define hiHANDLE_DLGMSG(hwnd, message, fn)      \
   case(message): return (SetDlgMsgResult(hwnd, uMsg,  \
     HANDLE_##message((hwnd),(wp),(lp),(fn))))
 /////////////////////////////////////////////////////////////////////
 
 
 void Dlg_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify){
   switch(id){
     case IDCANCEL:
       EndDialog(hwnd, id);
       break;
     case IDOK:
       // do something
       break;
   }
 }
 
 BOOL Dlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lp){
   // initialization code
   return TRUE;
 }
 
 void Dlg_OnClose(HWND hwnd){
   EndDialog(hwnd, 0);
 }
 
 
 INT_PTR CALLBACK DialogProc(HWND hwnd, UINT uMsg, WPARAM wp, LPARAM lp){
   switch(uMsg){
     hiHANDLE_DLGMSG(hwnd,  WM_INITDIALOG,  Dlg_OnInitDialog);
     hiHANDLE_DLGMSG(hwnd,  WM_CLOSE,    Dlg_OnClose);
     hiHANDLE_DLGMSG(hwnd,  WM_COMMAND,    Dlg_OnCommand);
   }
   return FALSE;
 }
 
 int WINAPI WinMain(HINSTANCE hinst, HINSTANCE, PTSTR pCmdLine, int nCmdShow)
 {
   DialogBox(hinst, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogProc);
   return 0;
 }




*組込みスクリプトエンジン [#c803cfb4]
調べ中。

-[[The pawn Language:http://www.compuphase.com/pawn/pawn.htm]]
-[[The ICI Programming Language:http://ici.sourceforge.net/]]
-[[The Programming Language Lua:http://www.lua.org/]]
-[[「コンパイラ・スクリプトエンジン」相談室のまとめサイト:http://www6.atwiki.jp/compilerandscriptengine/]]
-[[Lua言語の紹介:http://staff.aist.go.jp/yutaka.ueno/lua/docsjp.html]]

WindowsのScripting Hostも魅力的な機能

-[[SAMPLE: MFCAxs.exe Implements an Active Script Host Using MFC(MSDN):http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q168214&]]
-[[Say Goodbye to Macro Envy with Active Scripting:http://www.microsoft.com/mind/0297/activescripting.asp]]
-[[ Microsoft Windows Script Technologies:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/script56/html/1c457e66-a6b2-4545-b2dd-33a59d8661e8.asp]]
-[[CodeGuru: ActiveX Programming:http://www.codeguru.com/cpp/com-tech/activex/]]
-[[The Code Project - COM, DCOM and COM+ articles:http://www.codeproject.com/com/]]
-[[僻地のプログラマkmt-tの日記 - 今日は雨で憂鬱 - 何故かあまり利用されないVBScript/JScriptのいいとことろをだらだと書いてみる:http://d.hatena.ne.jp/kmt-t/20040611#p3]]
-[[ The Axsh.exe sample is a sample that demonstrates how to implement an ActiveX Scripting host.:http://www.kbalertz.com/kb_Q183698.aspx]]
-[[WSH - HOWTO: Run a JAvaScript inside a C++ program.:http://www.codecomments.com/archive300-2005-1-375438.html]]