ライブラリ
DLL
使用するDLLのパスを指定する
- OSによっては.local/.manifest/.configファイルで指定可能。詳細はこちら。
互換性
- VC6で作ったDLLをVS2005で使うことは基本的に問題無い。
ただし、VC6とVS2005でリンクするライブラリ(CRTやMFC等)のバージョンが異なる場合、境界を越えるアクセスを行ってはいけない。情報元
DLLの選択
VC6のウィザードから作る場合。DLLでMFCを使わない場合
「Win32 Dynamic-Link Library」を選択。多言語対応でリソースのみをDLLに出したい時など。「空のDLLプロジェクト」を選択すると全くファイルが生成されないのでDllMainを書くことを忘れないこと。
DLLでMFCを使う場合
- レギュラーDLL
- 「MFCのスタティックライブラリを使用した標準DLL」
- コンパイラに_USRDLLが定義される。
- CWinAppの派生クラスがある。
- MFC と静的にリンクされるレギュラー DLL
- Cスタイルの関数しかエクスポートできない。もちろんDLL内部でクラスを使うのは問題無し。
- あらゆるWin32プログラムからロードする場合はこちらか、下の動的リンク版を使う。
- MFC自体を静的にリンクするのでMFCの再配布を考慮しなくてよい。もちろんサイズは大きくなる。
- 「MFCの共有DLLを使用」
- コンパイラに_USRDLLが定義される。
- CWinAppの派生クラスがある。
- MFC と動的にリンクされるレギュラー DLL
- Cスタイルの関数しかエクスポートできない。もちろんDLL内部でクラスを使うのは問題無し。
- あらゆるWin32プログラムからロードする場合はこちらか、上の静的リンク版を使う。
- MFCを動的にリンクするのでMFCの再配布を考慮する必要がある。本体の配布サイズは小さくできる。
- 「MFCのスタティックライブラリを使用した標準DLL」
- 拡張DLL
- 「MFCの拡張DLL(MFCの共有DLL使用)」
- コンパイラに_AFXEXTが定義される。
- DllMainがある。
- 関数だけでなくクラスをエクスポートできる。よって、MFCのクラスを拡張したクラスをDLLで定義しEXEで使ってもらう場合は拡張DLLでないといけない。
- 呼び出し側がMFCと動的にリンクされてないといけない。
- 「MFCの拡張DLL(MFCの共有DLL使用)」
DLLのロード
DllMainでやらない方がいいこと。
引用元・直接的または間接的な、LoadLibrary 関数、LoadLibraryEx 関数、または FreeLibrary 関数の呼び出し。あと、NyaRuRuさんのページにも情報有り。
・レジストリ関数の呼び出し。
・Kernel32.dll 内に存在しないインポートされた関数の呼び出し。
・他のスレッドまたはプロセスとの通信。
Loadに成功した直後Unloadされてしまう。
- エラーコードを見ると126(指定されたモジュールが見つかりません。)となっている。
- VCのDebugウィンドウには以下にように出力されている。
Loaded hoge.dll 〜DependencyWalkerで確認したところ、hoge.dllがさらにロードしているDLLの中に見つからないDLL(?マークとして表示される)があることがわかった。
Unloaded hoge.dll 〜
つまり、hoge.dllのロードに成功したとしても、さらに内部で呼び出そうとしているDLLが存在しない場合、126としてエラーが返るようだ。
DLLによるクラスのimport/export
- exportする側(AAA.dll,AAA.libとする)
- exportするクラスをヘッダファイル(AAA.h)に定義。
#ifdef AAA_EXPORTS
#define AAA __declspec(dllexport)
#else
#define AAA __declspec(dllimport)
#endif
class AAA
{
// 省略
}
- AAA_EXPORTSを#defineか「プロジェクトのプリプロセッサの定義」に加える。
- inportする側
- AAA.hを#includeする。
- AAA.libを#pragma comment(lib, "AAA.lib")で指定するか、「追加の依存ファイル」に加える。
プラットフォームSDK
マクロ
HANDLE
winnt.hで次のように定義されていた。typedef void *HANDLE;また、void型のポインタだとコンパイラは区別できないので、次のようなマクロで違いを区別できるようにしている。情報元
#define DECLARE_HANDLE(name) struct name## { int unused; }; typedef struct name## *name
エラーコードの取得
※必ずエラーを取得したいコードの直後に置くこと。じゃないと、すぐに書き換えられてしまう。DWORD winErr = ::GetLastError();
NetScheduleJobAdd
登録するAT_INFOのCommandのパスにスペースが含まれている場合、登録後のタスクのパスは"で括られている。→登録するCommandが"で括られているがスペースを含まない場合、登録後のCommandは"が取り除かれている。
ダブルクォート | スペース | 登録結果 | 注意 |
有り | 有り | ダブルクォート有り | 無し |
有り | 無し | ダブルクォート無し | ←"を勝手に取り除く |
無し | 有り | ダブルクォート無し | ←Commandにスペースが含まれるので実行時にエラー |
無し | 無し | ダブルクォート無し | 無し |
メモリ関連
- 物理ストレージにコミットしたサイズを最終的にRAMから確保しようとするので、VirtualAllocやCreateFileMappingを使おうがコミット時点でのサイズを小さくしないとRAMから確保できない場合がある。
VirtualAlloc
- 仮想アドレス空間の予約 → 物理ストレージのコミットという2段階が必要。
- 指定方法は第3引数に次のフラグを指定する。ORで指定することにより予約とコミットを同時に実施することも可能。
- 仮想アドレス空間の予約:MEM_RESERVE
- 物理ストレージのコミット:MEM_COMMIT
CreateFileMapping
シェルAPI
SHFileOperation
- ファイル名やパスとして使用できない文字「 \ / : ; * ? " < > | 」を指定した場合
→自動的に使用できない文字を取り除いて処理しようとする。
例:pTo="C:\\test\\////temp\0";だとpTo="C:\\test\\temp\0";として処理する。
※pToはSHFILEOPSTRUCTのメンバ。
よって、SHFileOperationを用いて「ファイル名には次の文字は使えません。」という例のダイアログを表示することはできない。たぶん(^^;SHFileOperationを呼び出す前に自前で処理しないといけないぽいなあ。
- FOF_RENAMEONCOLLISIONを指定して移動、コピー、名前の変更時に自動的に新しい名前をつけてもらう場合のファイル名の取得方法。
// shFileOpの設定は説明に必要な分だけ。動作させるには不足。 SHFILEOPSTRUCT shFileOp; shFileOp.fFlags = FOF_RENAMEONCOLLISION | FOF_WANTMAPPINGHANDLE; shFileOp.lpszProgressTitle = "Test"; shFileOp.fAnyOperationsAborted = FALSE; SHFileOperation(&shFileOp); struct TMPMAP{ int cnt; SHNAMEMAPPING *maps; }; CString csNewPath; if(shFileOp.hNameMappings){ TMPMAP *pTmpMap = (TMPMAP*)shFileOp.hNameMappings; for(int in = 0; in<pTmpMap->Indx; in++){ SHNAMEMAPPING *pMap = &pTmpMap->pMapping[in]; // ワイド文字前提だとこれでいいかな?実際に動かしてないので自身なし。 lstrcpy(csNewPath.GetBufferSetLength(pMap->cchNewPath) , pMap->pszNewPath); csNewPath.ReleaseBuffer(); //GetBufferSetLengthだと不要? TRACE("コピー後のファイル名 = %s\n", csNewPath); } } //この後WideCharToMultiByteする。情報元
http://www.codeguru.com/Cpp/W-P/files/shellapifunc...
http://yokohama.cool.ne.jp/chokuto/urawaza/struct/...
http://freezer.blog22.fc2.com/
WindowsForms
GroupBox
フォーム上にセパレータ(境界線)を引く
- プロパティで高さを2〜4あたりにする。
- MFCでやってた方法はうまくいかなかった。
- Static(WindowsFormsで言うLabel)は高さを10未満にできない。
- ピクチャー(WindowsFormsで言うPictureBox)は高さを小さくしても期待した表示にならない。
- MFCでやってた方法はうまくいかなかった。
DataGridView
値の変化を捕まえる
DataGridViewCheckBoxColumnとして追加したカラムのチェックボックスがON/OFFされたタイミングを捕まえる。注意しなければならないのはCellContentClickイベントの時点では値が確定していない。よって、dataGridView1.CurrentCell.Value等でアクセスしようとするとNullReferencEexceptionが発生する。そこで、代わりにEditedFormattedValueを使うことで値を取得することができる。ここではまった・・・。
情報元
ちなみに、情報元にあるように.CommitEditで値の変化をコミットさせた後、CellValueChangedイベントで新しい値を得るという方法もあるようだ。こちらは試していない。
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e) { MessageBox.Show(dataGridView1.CurrentCell.EditedFormattedValue.ToString()); }
MFC
一般
- MFCのソースで一番最初に呼ばれるのはCWinAppのInitInstance
バージョンの確認
#ifdef _DEBUG
CString ver;
ver.Format("%x",_MFC_VER);
afxDump << "_MFC_VER = " << ver << "\n";
#endif
サブクラス化
- ダイアログ上にのっけたコントロールでメッセージを処理したい場合に使用する。
Class Wizardでメンバ変数を割り当てることがサブクラス化と等価であることに注意
実際にメッセージを処理するコードはClass Viewの「メッセージハンドラの追加」から追加する。ここで「ハンドルするクラスまたはオブジェクト」でメッセージを処理させる対処を指定すればよい。
例えば、ダイアログ上にあるCTreeCtrlにNM_CLICKを処理させる指定をするとメッセージマップには次のようにハンドルする対象が指定された形式で追加される。
ON_NOTIFY(NM_CLICK, IDC_TREE_CTRL, nClickTreeCtrl)
幅(高さ)いろいろ
ペインのサイズを固定する必要があって調べた。ツールバーやステータスバーの表示/非表示、スクロールバーの表示/非表示を考慮して算出する必要がある。→ GetWindowRect()でうまくとれる?
※GetClientRect()から算出
※GetWindowRect()の結果がコントロールにより異なることにも注意。
ステータスバーはGetClientRect()==GetWindowRect()
ツールバーはGetClientRect()+4==GetWindowRect() 境界分?
- CSplitterWndの境界線(分割バー)の幅
7pixel WINSPLIT.CPP内のCSplitterWnd::CSplitterWnd()に記載有り。m_cxSplitter/m_cySplitterを参照すればよい。 - スクロールバー(CScrollBar)の幅
16pixel - ツールバー(CToolBar)の幅
25pixel - ステータスバー(CStatusBar)
19pixel
TRACE
- 連続して呼び出すと出力がスキップされることがある。
http://support.microsoft.com/default.aspx?scid=kb;...
_RPTとDebugViewで表示可能。
ただし、_RPTはデバッグモードでしか動作しないので、VC++から起動せずにexeを直接実行する必要がある。VC++から起動するとVC++のデバッグウィンドウに出力されてしまい、TRACEと同様に出力がスキップされてしまうため。
TRACEn系もOutputDebugStringを使っているとなっていたので同様にDebugViewに出力できるかと思ったが、試したところ出力されなかった。 - 512byte以上出力しようとするとassertion errorになる。
TRACEの実装に使われているバッファが"TCHAR szBuffer[512];"であるため。代わりに、afxDumpを使うとよい。
ただし、DEBUGビルドでしか定義されていないので#ifdef _DEBUGが必要。
int test = 100; #ifdef _DEBUG afxDump << "test = " << test << "\n"; #endif
CWnd
- コントロールの有効/無効を切り替えるにはEnableWindowを使用する。
- 表示位置を中央にしたい場合はCenterWindow();を使う。
CWnd::GetClientRect
- スクロールバーを含まない矩形を返す。
CView
- どのViewがアクティブになるかを調べたいときにはOnActivateViewをオーバーライドする。
複数ペインにViewを割り付ける場合等に使える。
CScrollView::SetScrollSizes
- 画像を表示する場合に設定するサイズは、基本的に表示する画像のサイズをそのまま設定すればよい。もちろん、拡大、縮小表示する場合は、拡大、縮小後のサイズを指定する。
で、実際の表示処理で表示したい矩形を表示すればその矩形のサイズに応じてスクロールバーが表示される。
CScrollView::GetTotalSize
- CScrollViewの持つビュー全体(SetScrollSizesで指定したサイズ)を返す。スクロールバーがあるときは、スクロールバーを含まないサイズ、のはず。
CScrollView::GetScrollPosition
- 取得できる値は描画するデータの左上を原点(0,0)とした論理座標。
- データを表示した後(どのAPIかは調べていない)に更新されるので、表示前に表示開始座標をこれで取得することはできない。前回表示時の値が取れるだけ。
CSplitterWnd
- 異なるドキュメントを表示するペインの表示/非表示を切り替えたい場合は、CSplitterWndを動的に生成/破棄しないといけない。つまり、常に表示するペインを作成しておいてもそれをちょいがえで切り替えれるようにはならない。
詳細はこちらを参照。
http://www.interq.or.jp/jazz/iijima/mfc/iijima/12d... - MainFrameのOnSizeの中でスプリッターウィンドウのサイズをGetClientRect()で取得する場合、フレームの拡大、縮小が反映された結果がスプリッターウィンドウのサイズとして取得されることに注意。
つまり、OnSize内で取得したスプリッターウィンドウのサイズはフレームのサイズを変更した後の値になっている。
→スプリッターウィンドウのサイズを固定表示かつ非表示も可能にするのに、ON_WM_MOUSEMOVE内でIsTracking()を使用し、IsTracking() == FALSEになった時点でペインのサイズを取得する方法を採用。
CDialog
- モーダルダイアログがフォーカスを失っているときはメッセージはとんでこない。
必死にフォーカスを失ったダイアログにドラッグ&ドロップしようとしてた(TT - メンバダイアログに親の情報を渡したい場合は、コンストラクタでポインタを渡してやるとよい。
- モードレスダイアログを終了する際(OKやキャンセルボタン押下時)には、各ボタンを処理するメソッド内(OnCancel等)でDestroyWindow()をcallすること。
DestroyWindow()を自前でcallした場合は親クラスのメンバ関数(CDialog::OnCancel()やCDialog::OnClose()等)のcallは不要。 - モードレスダイアログの親ウィンドウはCreateの第二引数で決まる。第二引数で指定したウィンドウより背面に回らなくなることに注意。
p_addDialog = new CAddDialog;
p_addDialog->Create(IDD_ADD_DIALOG, this); // ← モードレスダイアログを起動するウィンドウ
p_addDialog->Create(IDD_ADD_DIALOG, NULL); // ← 本体フレーム等
- モーダルダイアログはデフォルトではメインウィンドウの中央に表示される。
CPrintDialog
標準ダイアログのカスタマイズ
CPrintDialogの場合全てのドライバに共通の画面をカスタマイズすることになる。ドライバ別に画面を切り替えたい場合はCPrintDialogExを使用してシートの表示を切り替えることで可能??※注意:「部単位で印刷」のON/OFFで切り替わるアイコンが欠けることがある。これはリソースエディタで修正した際にVC++が勝手に.rcファイルの該当するICONの幅と高さを20x20に変更してしまうため。テキストエディタ等で開いて98x36(※言語によりサイズが異なる)に変更することで対応。←リソースエディタで修正すると勝手に書き換えることの対策にはなってないので、修正の際には常に手書きする必要がある。
- リソースをコピーしたい自分の環境(.dsw)をVCで開く。
- リソースをOSから自分の環境へコピーする
- 自分の環境を開いたVCから「インストールドライブ\WINNT\system32\COMDLG32.DLL」(Windows 2000の場合)を開く。
※この際「用途」は"リソース"を選択しておくこと。 - ダイアログから1538を選択し、自分のリソースにコピーする。
※この際Ctrlを押しながらドロップすること。 - コピーしたリソースのプロパティを開きIDを1538から変更する。IDD_CUSTOM_PRINT_DIALOG等。
- 自分の環境を開いたVCから「インストールドライブ\WINNT\system32\COMDLG32.DLL」(Windows 2000の場合)を開く。
- ダイアログに対応するクラスを作成する。
ここでは、CMyPrintDialogとする。- コンストラクタに以下を追加する。
m_pd.hInstance = AfxGetResourceHandle();
m_pd.Flags |= PD_ENABLEPRINTTEMPLATE;
m_pd.lpPrintTemplateName = MAKEINTRESOURCE(PRINTDLGORD);
- コンストラクタに以下を追加する。
- 追加したリソースをカスタマイズする。
CHeaderCtrl
- CListCtrlからGetHeaderCtrl()で取得したCHeaderCtrlに対してCHeaderCtrl::InsertItemを実施すると表示上カラムは増えているように見えるが、CListCtrl::InsertItemを実施してもアイテムが追加されない。カラムの追加はCListCtrl::InsertColumnでやればOK。
CHeaderCtrl::InsertItemって何に使うんだ?
CTreeCtrl
- TVIS_FOCUSEDはCommCtrl.hのバージョン 1.2以降削除されているようだ。
代替手段が何かある?それとも消すだけでいいのかな?
参照:http://support.microsoft.com/default.aspx?scid=kb%...
CListCtrl
- InsertItemする際は挿入位置を指定すること。指定しない場合は辞書順になる??
- GetItemする際のLVITEMにはiItemとiSubItemを指定すること。
1カラムしか無いからといってiItemだけを指定しても値を取得できない。でも、GetItem自体はエラーにならないんだよね・・・。 - プロパティの表示の設定によってInsertItemの動作が異なる
InsertItemでLVITEMのiItemにインデックスを指定してアイテムを挿入した場合表示設定によって追加される位置が異なった。
アイコン | 必ず最後尾に追加 |
小さいアイコン | 必ず最後尾に追加 |
リスト | 指定位置に追加 |
レポート | 表示されない(恐らくカラムを設定していないため→カラムにヘッダーをつけない(LVS_NOCOLUMNHEADER)を指定しても表示されず) カラムを追加したところリストと同様に指定位置に追加されるようになった。 |
→カラムを追加しレポート表示で正常に動作する状態でアイコン表示で試したところ症状変わらず。
結局InsertItemとDeleteItemで並び替えるのをあきらめてSortItemsで並び替えるようにした。
- DeleteItemで歯抜けになる場合はArrangeで再配置すること。
- ドロップターゲットとして強調表示するにはLVIS_DROPHILITEDを使用する。
※LVIS_SELECTEDやLVIS_FOCUSEDではないことに注意。
強調表示:GetListCtrl().SetItemState(index, LVIS_DROPHILITED, LVIS_DROPHILITED);
解除:GetListCtrl().SetItemState(index, ~LVIS_DROPHILITED, LVIS_DROPHILITED); - ラベルを編集可能にするにはLVS_EDITLABELSを指定する。
CListViewからの場合:GetListCtrl().ModifyStyle(0, LVS_EDITLABELS);
※ラベル編集状態にするにはマウスの左クリックを長押ししないといけないので、短く押してうまくいかないと勘違いしないように。 - ラベル変更時の動作
ラベルを変更した場合、表示順を更新せずフォーカスも移動しないのが一般的な動作。
表示順を変更する場合、フォーカスを追随するための工夫が必要。indexだけでは表示順が更新された時点で変更されてしまうのでダメ。 - フレームやスプリットバーのサイズ変更時にできるだけアイテムが表示されるように自動的に並び変えたい場合はLVS_AUTOARRANGEを指定する。
CToolBar
- CreateExの第二引数と第三引数でそれぞれ、TBSTYLE_TOOLTIPSとCBRS_TOOLTIPSの両方を指定すると、ボタン上にマウスを移動させて1個目のツールチップが表示された直後に、マウスをちょっとだけ移動させると再度ツールチップが表示され、二個表示されてしまう。
オプションの指定はどちらか片方でいい。
文字列操作
一般
- キャリッジリターン(CR)(\r)が末尾にあると、テキストとして表示してもついているのかどうか区別がつかない。
xyzzyの場合、CRの後にCRLFや別の文字があれば制御文字として表示されるが、末尾の場合だと^Mが表示されない。末尾だとCR単体かどうか区別がつかない?キャリッジリターンを末尾に含む文字列を扱う際は注意。
CStringT::FindOneOf
- 引数に指定した文字列に含まれている任意の一字に一致する最初の文字を検索する。
- SpanIncludingで途中の文字列を抜き出したいときに、Midと組み合わせて前方にある不要な文字列を除去するのに使える。
CStringT::SpanIncluding
- 引数に指定した文字で連続しているものを抽出する。ただし、先頭からスキャンして指定した文字が見つからなかった時点で終了。
つまり、文字列から数字を抜き出そうとして例(1)のようにしても、先頭からスキャンして数字ではない'a'が見つかった時点で終了してしまうので、結果は""となる。
例(1) CString str( "abc14736" ); CString res = str.SpanIncluding( "0123456789" ); ASSERT( res.IsEmpty() );
例(2) CString str( "14736abc94832" ); CString res = str.SpanIncluding( "0123456789" ); ASSERT( res == "14736" );
CStringT::SpanExcluding
- MFCの日本語訳が間違って(SpanIncludingと同じになって)いる。
- 引数に指定した文字が見つかるまでの文字を全て抽出する。
コレクション
- RemoveAtで複数の要素を削除する際は、直前のRemoveAtによってインデックスがずれていることに注意。
例:3,4,5を削除したい場合。
CStringArray sArray; RemoveAt(3); // RemoveAt(3); RemoveAt(3); // RemoveAt(4); ← 一瞬こう書きたくなるが間違い RemoveAt(3); // RemoveAt(5); ← 一瞬こう書きたくなるが間違い
ファイル操作
- 基本的な認識は以下でよいようだ。
もちろん、オプションにより変更可。
CFile | バイナリ |
CStdioFile | テキスト |
- 入出力の基本
引用元
Windowsのファイル入出力には「テキストモード」と「バイナリモード」があります。一方、UNIXではこのようなものはありません。テキストデータであっても、バイナリデータであっても、同じように入出力します。単純にメモリ上のデータをファイルに読み書きするだけです。この意味では、「バイナリモード」しかないとも言えます。 では、Windowsではなぜ2つのモードがあるのでしょうか。それは、改行コードの違いによるものです。Windowsでは、改行コードは「CR-LF(\r\n、0x0D,0x0A)」が使われます。 UNIXでは「LF(\n、0x0A)」が使われます。これは文字コードには依りません。 Windowsのテキストモードでは、ファイルに出力するときに、「\n」が「\r\n」に自動的に変換されます。また、ファイルから入力するときは、「\r\n」が「\n」に自動的に変換されます。ですので、テキストモードのファイル入出力を使うときは、プログラム上では改行コードは「\n」で扱わなければいけません。
CStdioFile::ReadString
- ReadString(LPTSTR,UINT);とReadString(CString&);の違い
LPTSTRバージョンだとCRLFを取り除かない。CStringバージョンだとCRLFが取り除かれる。
Open時のモードの指定typeTextとtypeBinaryと組み合わさると混乱しそうなので注意が必要。 - MSDNの表記がまずい?
以下引用を見ると、改行コードとして0x0A,0x0D(LFCR)の順番で書かれているが、CRLFが正しい。それとも「バイトペア」と表現していることから、順番は言っていなくて動かす環境によってはLFCRになることもあるとか?:
テキスト モードでは、キャリッジ リターンとライン フィードの組み合わせに対して特殊な処理を行います。テキスト モードの CStdioFile オブジェクトに改行文字 (0x0A) を書き込むと、バイトペア (0x0A, 0x0D) がファイルに送られます。また読み込みのときは、バイトペア (0x0A, 0x0D) が 1 バイトの 0x0A に変換されます。
通信
CAsyncSocket/CSocket
- OnAccept,OnReceive等のコールバック関数はメッセージループが無いとcallされない。あたりまえですね・・・。
特にコンソールアプリでCAsyncSocket/CSocketを利用する場合は注意。メッセージループがない場合は自前で用意する必要がある。
参考
http://www.ne.jp/asahi/yamashita/programming/tips/... - CAsyncSocket/CSocketはOnAccept,OnReceive等のコールバック関数を使わなくても通信ができるが、コールバック関数をオーバーライドしてその中から呼ばないと正常に動かない気がする。そういうcodeを見たことがあるが、どうも動きが怪しい・・・。
- CArchiveを利用する場合は「ほかのMFCアプリケーションとしか通信できない」ことに注意。
情報元
WinSock2.0プログラミング
WinSock
あくまでもWinSockの話。Unixと同名の関数があるが動作が異なるかもしれない。listen
- 第一引数に指定されたソケットを受信要求を待機用にする。
- 複数の接続要求を管理するためのもの。
- これをcallした時点でプロセスが停止したり待機することはない。
accept
- 第一引数に指定されたソケット(listenの第一引数と同じ)から受信要求を取り出し、接続を確立する。
- callした時点で受信要求が来るまでプロセスは停止し、待機する。
- 受信要求が来たら、クライアントと通信するための新たなソケットを生成する。
- ブロッキングを起こすかどうかはソケットのモード次第。
select
- 複数の受信要求を待機する。acceptの複数ソケット版みたいなもの?
- タイムアウトした場合は戻り値0。
- 必ずブロッキングを起こす。
- Winsock Programmer's FAQ 第7章: 論説記事: ザ・間違いリスト No.23によると「selectは使うな」というようなことが書いてある。
WSAAsyncSelect
- 第一引数で指定したソケットを非同期モードにする。
- GUIアプリ等で通信処理でブロッキングしてしまうと画面操作等ができなくなってしまうのを回避する場合に使用。
recv
- 受け取るデータがない場合、データが送られてくるまで待機する。 from WinSock2.0プログラミング p21
- 正常切断の場合0、データを受信した場合はバイト数、それ以外の場合はSOCKET_ERRORを返す。from MSDNライブラリ
正常切断って、送信側が全てのデータを送信し終わったってことだよなあ。なので、0が返れば受信終了とみなしてよさそう。まあ、受信側が全て受け取ったかどうかは別の話だと思うけど。←全て受け取ったって受信側で判断するのってどうだったけ?バイト数かなんか?または、TCPで保障されてたっけ?。
If no error occurs, recv returns the number of bytes received. If the connection has been gracefully closed, the return value is zero. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError.
- ブロッキングを起こすかどうかはソケットのモード次第。
sockaddr構造体
- sin_port =0;でポートの自動割り当て。
メッセージ
Windowsメッセージ
- WM_LBUTTONUPはマウスポインタを移動させない状態でシングルクリックしても発生しないようだ。
ダブルクリックやポインタを少しでも移動させた場合には発生した。 - IDCANCELを以下のような感じで無効にした場合、システムメニューの×ボタンも無効になることに注意。
::EnableWindow(::GetDlgItem(this->m_hWnd,IDCANCEL), FALSE);
- ポップアップメニューの表示にはWM_CONTEXTMENUを使う。
OnRclick等でも可能だがWM_CONTEXTMENUの方が名前の通り専用に用意されているのでよさそう。 - ClassWizardに表示されないメッセージでも手動でメッセージマップを追加すれば受け取れることがある。
この基準がよくわからない・・・。
ON_MESSAGE
本メッセージのハンドラはLRESULTを返すが、その値はユーザが好きに定義していいようだ。ダイアログのメンバクラスでClassWizardに表示されないメッセージを受ける
ダイアログにリストコントロール(CListCtrl)を貼り付け、それ上で行の入れ替えを実現するためマウスの左ボタンが離されたメッセージを取得しようとしたところ、ClassWizardのCListCtrlのメッセージのところには適当なメッセージ(WM_LBUTTONUP等)が見あたらなかった。そこで、いろいろ調べていくうちに「サブクラス化」に行き当たった。WM_LBUTTONUPをCListCtrlで処理させるために、メッセージマップとSubclassDlgItemの処理を追加したところ、SubclassDlgItemでAssertionエラー。wincore.cppのBOOL CWnd::Attach(HWND hWndNew)の先頭、
ASSERT(m_hWnd == NULL); // only attach once, detach on destroyで落ちていたことから、どうやら2回サブクラス化されている?なので、自分で追加したSubclassDlgItemを取り除いたところ動作するようになった。結果、CListCtrlにメッセージマップを追加しただけとなった。ClassWizardで追加したクラスって自動的にサブクラス化されている?それとも、CDialogもCListCtrlもCWndからの派生なので、マップだけで受け取れるってこと?
メッセージハンドラを追加したい場合は、クラスビューで追加したいクラスを選択し右クリックすると「Windowsメッセージハンドラの追加」があるので、そこからやった方がClassViewでやるよりか多数のメッセージが表示される気がする。ちなみに、ハンドラを追加できない場合は上記メニューは表示されない。
バージョン
昔のやつはウソかも。MFC | _MFC_VER | Visual C++ |
MFC Version 1.0 | 0x0100 | Microsoft C/C++ Version 7.0 |
MFC Version 2.0 | 0x0200 | Visual C++ Version 1.0 |
MFC Version 2.5 | 0x0250 | Visual C++ Version 1.5 |
MFC Version 3.0 | 0x0300 | Visual C++ Version 2.0 |
MFC Version 3.1 | 0x0310 | Visual C++ Version 2.1 |
MFC Version 3.2 | 0x0320 | Visual C++ Version 2.2 |
MFC Version 4.0 | 0x0400 | Visual C++ Version 4.0 |
MFC Version 4.1 | 0x0410 | Visual C++ Version 4.1 |
MFC Version 4.2 | 0x0420 | Visual C++ Version 4.2 |
MFC Version 4.21(従来どおり mfc42.dll) | 0x0421 | Visual C++ Version 5.0 |
MFC Version 6.0 (従来どおり mfc42.dll) | 0x0600 | Visual C++ Version 6.0 |
MFC Version 7.0 (mfc70.dll) | 0x0700 | Visual C++ .NET 2002 |
MFC Version 7.1 (mfc71.dll) | 0x0710 | Visual C++ .NET 2003 |
MFC Version 8.0 (mfc80.dll) | 0x0800 | Visual C++ .NET 2005 |
ATL
バージョン
昔のやつはウソかも。ATL | _ATL_VER | Visual C++ |
ATL Version 1.0 | 0x0100 | なし。Visual C++ 4.x のタイム フレームで Web にリリース |
ATL Version 1.1 | 0x0110 | なし。Visual C++ 4.x のタイム フレームで Web にリリース |
ATL Version 2.0 | 0x0200 | なし。Visual C++ 4.x のタイム フレームで Web にリリース |
ATL Version 2.1 | 0x0210 | Visual C++ Version 5.0 |
ATL Version 3.0 | 0x0300 | Visual C++ Version 6.0 |
ATL Version 7.0 | 0x0700 | Visual C++ .NET |
WTL
- サイト
- 日本語化
2007年12月10日(月) 21:13:25 Modified by n0gam0ga