開発Tips/VC++
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
|
ログイン
]
開始行:
#contents
*Windowsプログラミング [#aae2e34b]
**ダイアログボックス [#ca2af524]
***ダイアログの閉じ方と対応するイベントハンドラ [#h0086e95]
|操作|イベントハンドラ|h
|Enter|OnOK()|
|Esc|OnCancel()|
|Alt+F4|~|
***タブオーダの保存形式 [#t04332d2]
リソースファイル(*.rc)内でコントロールが定義される順番が...
***他のコントロールと連携が必要な場合の例 [#sa348c01]
異なるコントロールを連携させて使用する場合がある。連携さ...
-ラジオボタンのグループ化
~グループ化したいラジオボタンのタブオーダを連続させ、先頭...
-スピンコントロールのバディコントロール
~エディットボックスのタブオーダをスピンコントロールの直前...
この場合、値の取得やコントロールの操作は全てCSpinButtonCt...
***コントロールへのドラッグ&ドロップの優先順位 [#hc561ad0]
複数のコントロールが重なっている場合、タブオーダの小さい...
グループボックスコントロールを使用する際などは注意。
***クラスウィザードに表示されていないメッセージ [#v3678744]
クラスウィザードに目的のメッセージが表示されていない場合...
「詳細設定オプション」で「メッセージフィルタ」を変更する...
例)ダイアログクラスで初期状態ではフィルタリングされてい...
-WM_DROPFILES
~ファイルのドラッグ&ドロップ
-WM_ACTIVATE
~ウィンドウのアクティブ/非アクティブ
***コントロールのフォーカス移動 [#h004c8db]
CWnd::SetFocus() ではなく、CDialog::GotoDlgCtrl() を用い...
CWnd::SetFocus()を用いてもフォーカスは移動するが、画面描...
#code(c){{
// ボタンのコントロール変数が m_BtCtrl の場合
m_BtCtrl.SetFocus(); // ←×
GotoDlgCtrl(&m_BtCtrl); // ←○
}}
ダイアログ表示直後に指定コントロールへフォーカス設定する...
***リソースエディタ上でコントロールのフォントを指定した際...
コード上でフォントの設定をすると直ることがある。
***ツールバーを使用するには [#m55f34a1]
通常、ツールバーはSDIかMDIのアプリケーションにしか用意さ...
※ダイアログに配置するコントロールの位置は、ツールバーの範...
<ツールバーの作成>
+ツールバーのリソースを用意する。
+ダイアログクラスのメンバ変数として以下を定義しておく。
#code(c){{
CToolBar m_wndToolBar;
}}
+CXxxDlg::OnInitDialog()でツールバーを作成する。
#code(c){{
CRect rcClient;
CSize sizeToolBar;
// ツールバー作成
if(!m_wndToolBar.Create(this)){
return FALSE;
}
// ツールバーをリソースからロード
if(!m_wndToolBar.LoadToolBar(IDR_TOOLBAR)){
return FALSE;
}
// クライアント領域を取得
GetClientRect(rcClient);
// ツールバーのサイズを取得
sizeToolBar = m_wndToolBar.CalcFixedLayout(FALSE, TRUE);
// 作成時は大きさが0なので設定する必要がある
m_wndToolBar.MoveWindow(0, 0, rcClient.Width(), sizeTool...
}}
<ツールバーのボタン押下時のイベントハンドラ定義>
~クラスウィザードは対応していないため、自分で定義する必要...
+ダイアログクラスのヘッダのメッセージマップ部分に関数のプ...
#code(c){{{
// 生成されたメッセージ マップ関数
//{{AFX_MSG(CMStepEditorDlg)
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
//}}AFX_MSG
afx_msg void OnXxx(); // @TODO:ここに追加
DECLARE_MESSAGE_MAP()
}}}
+ダイアログクラスのソースに関数 OnXxx() を定義する。
+ダイアログクラスのソースのメッセージマップ部分に定義した...
#code(c){{{
BEGIN_MESSAGE_MAP(CMStepEditorDlg, CDialog)
//{{AFX_MSG_MAP(CMStepEditorDlg)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_COMMAND(ID_XXX, OnXxx) // @TODO:ここに追加
END_MESSAGE_MAP()
}}}
***イベントハンドラ活用 [#c7e6d076]
-複数の操作から同じイベントハンドラを呼び出す場合
~1つのイベントハンドラと対応する1つのリソースIDを用意し、...
--メニューの項目のID
--ツールバーのボタンのID
--アクセラレータのID
--ストリングテーブルのID
-別のIDを持つ操作から同じイベントハンドラを呼び出す場合
~1つのイベントハンドラに対して複数のIDをメッセージマップ...
例えば、2つのラジオボタンのどちらをクリックしたときも同じ...
***F1押下時のヘルプの無効化 [#na06dcc6]
アプリケーションクラスのメッセージ処理を修正することで、...
#code(c){{{
BEGIN_MESSAGE_MAP(CXxxApp, CWinApp)
//{{AFX_MSG_MAP(CXxxApp)
// メモ - ClassWizard はこの位置にマッピング用のマクロ...
// この位置に生成されるコードを編集しないでくだ...
//}}AFX_MSG
// ON_COMMAND(ID_HELP, CWinApp::OnHelp) // ※ここをコメン...
END_MESSAGE_MAP()
}}}
***ダイアログベースアプリケーションの終了コード [#r5c7907b]
アプリケーションのCWinAppを継承したクラスのExitInstance()...
***WM_INITDIALOGの戻り値 [#t9de6ed9]
通常、ウィンドウプロシージャやダイアログプロシージャの戻...
TRUE を返すと、タブオーダーが一番若いコントロールに自動的...
FALSE を返すと、何も行われない。(自分でフォーカスを当て...
~
ダイアログ生成時に明示的にあるコントロールにフォーカスを...
***CDialogBar派生クラスでOnInitDialog()を実装する方法 [#x...
CDialogBarクラスにはOnInitDialog()が用意されていないため...
~
参考:http://support.microsoft.com/kb/185672/ja
***MFCによりダイアログが自動的に中央に移動する [#ob241fd0]
MFCで作られたダイアログは、自動的に中央に移動する機能が組...
通常、OnInitDialog()でMoveWindow()等を呼び出し、明示的に...
例として、(0, 0)の位置に移動しようとしたときに現象が発生...
~
以下の条件のいずれかを満たしている場合は中央移動は行われ...
-画面の表示位置を(0, 0)以外にしている
-ダイアログテンプレート(リソース)のスタイル設定に DS_CENT...
-ダイアログテンプレート(リソース)のXY位置設定が(0, 0)では...
~
詳細は関連するMFCの関数を参照。~
-::_AfxPostInitDialog()
-CDialog::CheckAutoCenter()
**コントロール [#zd341b78]
***エディットボックス内の改行の注意点 [#p8b10388]
-複数行を許可していなくても、Ctrl+Enterで改行することがで...
-文字列取得の際、改行コードは"\r\n"として取得されるため、...
***コンボボックスのドロップダウンリストのサイズ変更 [#g26...
ダイアログエディタ上で、コンボボックスの右端の▼マークをク...
***リストビューコントロールのヘッダのソート記号 [#g161d5e1]
リストビューのヘッダに対して以下の定数を設定する。
|HDF_SORTUP|昇順(▲)|
|HDF_SORTDOWN|降順(▼)|
※この機能はXP以降の機能なので、VC6.0(1998年)時点では未対...
#code(c){{
// CListCtrl m_LcTest リストビューのコントロー...
// long lSubItem ヘッダの列インデックス
HDITEM hdItem; // ヘッダ設定情報
CHeaderCtrl* pHrCtrl; // リストビューのヘッダ
// 初期化
::ZeroMemory(&hdItem, sizeof(HDITEM));
// メンバ変数 HDITEM::fmt を有効にする
hdItem.mask = HDI_FORMAT;
// ヘッダコントロールをリストから取得
pHrCtrl = m_LcTest.GetHeaderCtrl();
// ヘッダの指定列の現在の設定状況を取得
pHrCtrl->GetItem(lSubItem, &hdItem);
// 例)昇順ソートマークを設定
hdItem.fmt &= ~HDF_SORTDOWN; // 降順マークを消す
hdItem.fmt |= HDF_SORTUP; // 昇順マークを設定
// ヘッダに設定
pHrCtrl->SetItem(lSubItem, &hdItem);
}}
***ツリービューの全展開 [#v4dc6172]
ツリービューコントロールを全展開する関数
#code(c){{
// ツリー全展開
// CTreeCtrl *pTreeCtrl 展開対象のツリーコントロ...
// HTREEITEM hParent 展開対象のノード (呼び出...
void ExpandAllTree(CTreeCtrl *pTreeCtrl, HTREEITEM hP...
HTREEITEM hChild;
// 初回呼び出し
if(hParent == NULL){
// ルートノード
if((hParent = pTreeCtrl->GetRootItem()) == NU...
// エラー
return;
}
}
// 子ノードが存在するなら
if(pTreeCtrl->ItemHasChildren(hParent) == TRUE){
// 展開
pTreeCtrl->Expand(hParent, TVE_EXPAND);
// 子ノードを順番に処理する
hChild = pTreeCtrl->GetChildItem(hParent);
while(hChild != NULL){
// 子ノードを展開する
ExpandAllTree(pTreeCtrl, hChild);
// 次の子ノード
hChild = pTreeCtrl->GetNextSiblingItem(hC...
}
}
}
}}
***スピンコントロールの値変更イベント [#m6c0c6c5]
スピンコントロールの値が変更された場合のイベントハンドラ...
しかし、スピンコントロールとエディットコントロールを自動...
対処策としては、自分でエディットコントロールにバディする...
***リッチエディットコントロール使用前の準備 [#leee484e]
リッチエディットコントロール(CRichEditCtrl)を使用する場合...
-コントロール自体の初期化~
リッチエディットコントロールを使用する前に、アプリケーシ...
呼び出すタイミングは、最初にリッチエディットコントロール...
-使用するイベントのマスク設定~
リッチエディットコントロールは、デフォルトでイベントマス...
ダイアログのOnInitDialog()で、明示的に使用するイベントの...
#code(c){{
// m_ReCtrl : リッチエディットコントロールのコントロール...
// EN_CHANGEイベント(内容が変更されたときのイベント)を使...
m_ReCtrl.SetEventMask(m_ReCtrl.GetEventMask() | ENM_CHAN...
}}
***エディット/リッチエディットコントロールのワード区切り ...
単語境界やワードラップ機能は、どのように文字列のワード区...
ワード区切りの方法を変更するには、以下のキーワードを調べ...
-EM_SETWORDBREAKPROC
-EditWordBreakProc
***コントロールの「通知」の有無 [#zfb7d171]
コントロールのプロパティの「通知」の有無の違いによって、...
(CWnd::Create()でコントロールを作成する場合は、「SS_NOTF...
-通知OFFの場合
++親ダイアログの PreTranslateMessage()
++親ダイアログの OnLButtonDown()
-通知ONの場合
++コントロールの PreTranslateMessage()
++親ダイアログの PreTranslateMessage()
++コントロールの OnLButtonDown()
++親ダイアログに追加したコントロールクリック時のイベント...
***ActiveXコントロールの登録状況の確認 [#g8d5ab8f]
ActiveXコントロールを使用したMFCアプリケーションを作成す...
それだと、なぜアプリケーションが起動しなかったのかが分か...
-チェック関数
#code(c){{
// clsid : 確認対象のActiveXコントロールのクラスID
BOOL IsControlRegister(CLSID clsid)
{
BOOL bRegistered = FALSE;
// クラスIDを文字列に変換
CString strClsid;
strClsid.Format("{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%0...
clsid.Data1,
clsid.Data2,
clsid.Data3,
clsid.Data4[0], clsid.Data4[1],
clsid.Data4[2], clsid.Data4[3], clsid.Data4[4], clsid.D...
);
// クラスIDを元にレジストリキーを作成
CString strKey;
strKey.Format("CLSID\\%s", strClsid);
// レジストリキーの存在確認
HKEY hKey = NULL;
if(::RegOpenKeyEx(HKEY_CLASSES_ROOT, strKey, 0, KEY_READ...
bRegistered = TRUE;
RegCloseKey(hKey);
}
return bRegistered;
}
}}
-使用例
#code(c){{
// AppクラスのInitInstance()で以下のコードを記述。(dlg...
// m_xxxx : dlgダイアログで使用しているOCXコントロール
// ウィザードによってGetClsid()メンバ関数が作成されてい...
if(!IsControlRegister(dlg.m_xxxx.GetClsid())){
::MessageBox(NULL, "XXXX ActiveX コントロールがインスト...
}
}}
**コントロールのサブクラス化 [#b1ba8fa2]
***サブクラス化の方法 [#ude717d6]
-動的サブクラス化
~親ダイアログクラスの初期処理で、CWnd::SubclassDlgItem()...
-静的サブクラス化
~ClassWizardを使用して派生クラスの型のコントロール変数を...
派生クラスのヘッダやソースファイルがクラスウィザードに登...
その場合は、直接ヘッダファイル内の変数定義の型名を編集す...
※サブクラス化とは、C++の「クラスの継承」のことではない。~
既存のウィンドウプロシージャを、独自のウィンドウプロシー...
***サブクラス化に用いた派生クラス内での初期処理 [#va683d55]
OnCreate()はコールされないため、初期処理を記述することは...
派生クラスでは、PreSubclassWindow()をオーバライドして、そ...
元のクラスが構築されて(OnCreate)、サブクラス化が行われる...
***MFCを継承した自作クラスへのイベントハンドラの追加 [#k7...
MFCを継承している場合は、クラスウィザードに派生クラスを認...
(認識されているかどうかは、クラスウィザードの「クラス名...
認識されていない場合は、以下の操作ができない。
-コントロールのメンバ変数追加時に、型の候補とする
-クラスビューからWindowsメッセージハンドラを追加する
プロジェクト内でクラスを作成した場合は自動的に認識される...
一度clwファイルを削除してクラスウィザードを作り直すときに...
※ちなみに、MFC継承クラスをさらに継承した場合は上記作業を...
**ウィンドウ [#b879af76]
***ウィンドウ操作関数一覧(一部) [#bc075974]
|>|操作|>|CENTER:Win32API|>|CENTER:MFC|h
|~|~|Set|Get|Set|Get|h
|>|ウィンドウ情報|-|::GetWindowInfo|-|CWnd::GetWindowInfo|
|>|親ウィンドウ|-|::GetParent|-|CWnd::GetParent|
|>|関連ウィンドウ|-|::GetWindow|-|CWnd::GetWindow|
|>|スタイル|::SetWindowLong|::GetWindowLong|CWnd::ModifyS...
|>|拡張スタイル|~|~|CWnd::ModifyStyleEx|CWnd::GetExStyle|
|>|インスタンスハンドル|~|~|-|-|
|>|ウィンドウプロシージャ|~|~|-|-|
|(特記)|使用可否|::EnableWindow|::IsWindowEnable|CWnd::En...
|~|表示状態|::ShowWindow|::IsWindowVisible|CWnd::ShowWind...
|>|ウィンドウクラス登録|::RegisterClassEx|-|-|-|
|>|ウィンドウクラス登録解除|::UnregisterClass|-|-|-|
|>|コントロールID|-|::GetDlgCtrlID|CWnd::SetDlgCtrlID|CWn...
|>|ドラッグ&ドロップ許可|::DragAcceptFiles|-|CWnd::DragA...
|>|アクティブ|::SetActiveWindow|::GetActiveWindow|CWnd::S...
|位置|スクリーン座標|::MoveWindow|::GetWindowRect|CWnd::M...
|~|クライアント座標|-|::GetClientRect|-|CWnd::GetClientRe...
|~|位置データ|::SetWindowPlacement|::GetWindowPlacement|C...
|~|Zレベル|::SetForegroundWindow|::GetForegroundWindow|CW...
|~|~|::SetWindowPos|-|CWnd::SetWindowPos|-|
|~|中央へ移動|-|-|CWnd::CenterWindow|-|
|>|キャプション|::SetWindowText|::GetWindowText|CWnd::Set...
|>|透明度|::SetLayeredWindowAttributes|::GetLayeredWindow...
|>|フォント|-|-|CWnd::SetFont|CWnd::GetFont|
|操作|閉じる|::DestroyWindow|-|CWnd::DestroyWindow|-|
|~|最大化|::ShowWindow|::IsZoomed|CWnd::ShowWindow|CWnd::...
|~|最小化|::ShowWindow&br;::CloseWindow|::IsIconic|CWnd::...
|~|メッセージ送信(同期)|::SendMessage|-|CWnd::SendMessage...
|~|メッセージ送信(非同期)|::PostMessage|-|CWnd::PostMessa...
|~|再描画|::UpdateWindow|-|CWnd::UpdateWindow|-|
***ウィンドウの中央表示 [#e4d8e618]
-''Win32API''
~ウィンドウの矩形を計算し、::MoveWindow() で移動する。
#code(c){{
// HWND hWnd 対象ウィンドウのハンドル
RECT rectDesktop; // デスクトップの領域矩形
RECT rectWnd; // ウィンドウの領域矩形
RECT rectCenter; // 中央表示の領域矩形
// デスクトップの領域を取得
SystemParametersInfo(SPI_GETWORKAREA, 0, &rectDesktop...
// ウィンドウの領域を取得
GetWindowRect(hWnd, &rectWnd);
// 中央表示の領域を計算
rectCenter.top = rectDesktop.bottom / 2 - (rectWnd.bo...
rectCenter.left = rectDesktop.right / 2 - (rectWnd.ri...
rectCenter.right = rectCenter.left + rectWnd.right;
rectCenter.bottom = rectCenter.top + rectWnd.bottom;
// ウィンドウを移動
MoveWindow( hWnd,
rectCenter.left,
rectCenter.top,
(rectCenter.right - rectCenter.left),
(rectCenter.bottom - rectCenter.top),
TRUE);
}}
-''MFC''
~CWnd::CenterWindow() を使用する。
#code(c){{
// デスクトップを基準に中央に表示する
CenterWindow(CWnd::GetDesktopWindow());
}}
***タイトルバーの高さの取得 [#ab66f67c]
OSの設定(フォントやテーマ等)に依存する。
#code(c){{
::GetSystemMetrics(SM_CYCAPTION) // タイトルバーの...
}}
***コンソールウィンドウの使用 [#w5bf5c30]
::AllocConsole(), ::FreeConsole()を用いる。~
コンソールへの入出力をするためには、標準入出力を割り当て...
#code(c){{
::AllocConsole(); // コンソール作成
// ①標準入出力を割り当てる方法
// printf()などの標準関数を使う場合
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
freopen("CONIN$", "r", stdin);
printf("test\n");
// ②コンソールハンドルを取得する方法
DWORD dwRet;
char *str = "test";
HANDLE hStdOut = ::GetStdHandle(STD_OUTPUT_HANDLE);
// コンソールへ書込み
::WriteConsole(hStdOut, str, strlen(str), &dwRet, NUL...
// アプリケーション終了時?などに::FreeConsole()でコ...
}}
***ウィンドウの描画更新の抑制 [#q420663c]
CWnd::LockWindowUpdate() と CWnd::UnlockWindowUpdate() で...
#code(c){{
LockWindowUpdate()
// 描画更新を抑制した状態で行う処理を記述
UnlockWindowUpdate()
}}
大きなツリービューへのアイテムの追加など、時間がかかる処...
***小さいアイコン(16x16)の設定 [#haeb34ab]
大きいアイコン(32x32)と小さいアイコン(16x16)の両方を用意...
その場合は、OnInitDialog() 等のアイコン設定処理で、小さい...
#code(c){{
SetIcon(m_hIcon, TRUE); // 大きいアイコンを設定
//SetIcon(m_hIcon, FALSE); // 小さいアイコンを設定
}}
※正式な修正方法ではないかも。
***メニューの項目の取得 [#e1529ac9]
取得の手順。
+メニューを持つウィンドウを識別
+メニューバーを取得
+必要があればサブメニューを取得していき、目的の項目を持つ...
+目的のメニュー項目の情報を取得(/設定)する
メニューの項目は、0から始まるインデックスで位置を指定する~
サブメニュー内は、それぞれで0から始まるインデックスを持つ。
#br
メニュー項目の取得は、MENUITEMINFO構造体を介して行う。~
MENUITEMINFO::cbSize に構造体のサイズを設定し、必要なメン...
#br
-''Win32API''
#code(c){{
// HWND hWnd メニューを持つウィンドウハン...
HMENU hMenu; // メニュー
HMENU hSubMenu; // サブメニュー
MENUITEMINFO menuItemInfo; // メニュー項目の情報
// メニューの取得
hMenu = ::GetMenu(hWnd);
// サブメニューの取得
hSubMenu = ::GetSubMenu(hMenu, 0); // メモ帳でいう「...
// MENUITEMINFO構造体を初期化
::ZeroMemory(&menuItemInfo, sizeof(MENUITEMINFO));
menuItemInfo.cbSize = sizeof(MENUITEMINFO); // お約束
menuItemInfo.fMask = MIIM_ID | MIIM_STATE; // メニュ...
// メニュー項目の情報を取得
::GetMenuItemInfo(
hSubMenu, // 対象のメニューハンドル
2, // メモ帳でいう「上書き保存」...
TRUE, // TRUEならメニューの位置、FA...
&menuItemInfo); // MENUITEMINFO構造体
// menuItemInfo.wID にメニュー項目IDが取得された
// menuItemInfo.fState にメニュー項目状態が取得された
}}
-''MFC''
#code(c){{
// CWnd *pWnd メニューを持つウィンドウクラス
CMenu *pSubMenu; // サブメニュークラス
MENUITEMINFO menuItemInfo; // メニュー項目の情報
// サブメニューを取得
pSubMenu = pWnd->GetMenu()->GetSubMenu(0); // メモ帳...
// MENUITEMINFO構造体を初期化
::ZeroMemory(&menuItemInfo, sizeof(MENUITEMINFO));
menuItemInfo.cbSize = sizeof(MENUITEMINFO); // お約束
menuItemInfo.fMask = MIIM_ID | MIIM_STATE; // メニュ...
// メニュー項目の情報を取得
pSubMenu->GetMenuItemInfo(
2, // メモ帳でいう「上書き保存」...
&menuItemInfo, // MENUITEMINFO構造体
TRUE); // TRUEならメニューの位置、FA...
// menuItemInfo.wID にメニュー項目IDが取得された
// menuItemInfo.fState にメニュー項目状態が取得された
}}
***メニューバーの描画更新 [#d24ac8ed]
メニュー項目に変更を行っても自動的に描画更新されないため...
-''Win32API''
~::DrawMenuBar()
-''MFC''
~CWnd::DrawMenuBar()
***指定ウィンドウの描画更新 [#l366c04f]
ウィンドウの描画更新を促すには、WM_PAINTを発行する必要が...
#code(c){{
// ウィンドウ全体を再描画する
pWnd->InvalidateRect(NULL); // 更新リージョンにウィンド...
pWnd->UpdateWindow(); // 更新リージョンが空でなければ...
}}
ウィンドウの一部だけを再描画させる場合は、CWnd::Invalidat...
***メッセージボックスの簡易的な最前面化 [#o379d572]
最前面ウィンドウを親に持つメッセージボックスを作成すれば...
親ウィンドウは非表示にしておけば、メッセージボックスのみ...
#code(c){{
CWnd *pDmyWnd;
TCHAR szClassName[256];
// ダミーウィンドウ生成 (非表示で最前面)
::GetClassName(this->GetSafeHwnd(), szClassName, 256);
pDmyWnd = new CWnd();
pDmyWnd->CreateEx(WS_EX_TOPMOST, szClassName, NULL, 0, C...
// ダミーウィンドウを親に持つメッセージボックス
::MessageBox(pDmyWnd->GetSafeHwnd(), "test", "test", MB_...
// ダミーウィンドウを破棄
pDmyWnd->DestroyWindow();
delete pDmyWnd;
}}
***ウィンドウの再表示 [#v91c4ad4]
ウィンドウの再表示を行う際、::ShowWindow()の第2引数に「SW...
以下のように場合分けをすることで解決できる。
#code(c){{
int nShowCmd;
// 表示コマンドを決定
if(::IsIconic(hWnd)){
// 最小化時:元の状態に戻す
nShowCmd = SW_RESTORE;
} else if(::IsZoomed(hWnd)){
// 最大化時:そのまま
nShowCmd = SW_SHOWMAXIMIZED;
} else {
// それ以外は単純に再表示
nShowCmd = SW_SHOW;
}
// ウィンドウを表示
::ShowWindow(hWnd, nShowCmd);
}}
***タイトルバーを常にアクティブ色にする [#qa874a77]
再描画のたびにウィンドウメッセージでアクティブ通知を行う。
#code(c){{
void CXxxDlg::OnPaint()
{
:
// キャプションを常にアクティブ色にする
PostMessage(WM_NCACTIVATE, TRUE);
:
}
}}
***メッセージ専用ウィンドウ [#i0849f40]
ウィンドウメッセージの処理を行いたいがウィンドウの実体は...
(ウィンドウ列挙等の対象からも外れる)
使用する場合は、予め下記の定数を設定しておく必要がある。
#define WINVER 0x0500 // 0x0500以上ならOK
-''Win32API''
#code(c){{
HWND hMsgWnd;
static const char* szWndClassName = "DUMMY_CLASS";
WNDCLASSEX wcx;
ZeroMemory(&wcx, sizeof(WNDCLASSEX));
wcx.cbSize = sizeof(WNDCLASSEX);
wcx.lpfnWndProc = DefWindowProc;
wcx.hInstance = hInst;
wcx.lpszClassName = szWndClassName;
BOOL bRegist = FALSE;
WNDCLASS wcx_dmy;
ZeroMemory(&wcx_dmy, sizeof(WNDCLASSEX));
// 既にクラスが登録されていたらRegisterClassEx()をコ...
if(!::GetClassInfo(wcx.hInstance, wcx.lpszClassName, ...
::CreateWindowEx(0, szWndClassName, "", 0, 0, 0, ...
}
}}
-''MFC''
#code(c){{
// CWnd *pWnd;
pWnd = new CWnd();
CString strWndClassName = ::AfxRegisterWndClass(NULL);
pWnd->CreateEx(0, strWndClassName, "", 0, 0, 0, 0, 0,...
}}
**ウィンドウメッセージ [#a73dc816]
***自作メッセージ [#n6691b3d]
自作のメッセージの定義は、以下の2通り。
-WM_USER + n~
プライベートなウィンドウに送る自作メッセージの定義。コモ...
-WM_APP + n~
自作アプリケーションから任意のウィンドウに送る自作メッセ...
***メッセージフック処理 [#x95361dc]
-''Win32API''
~自分でウィンドウプロシージャを定義する。
#code(c){{
LRESULT CALLBACK WinProc(HWND hWnd, UINT uMsg, WPARAM...
switch(uMsg) {
case WM_DESTROY :
PostQuitMessage(0);
return 0;
// 独自のメッセージフック
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}}
-''MFC''
~CWnd::PreTranslateMessage() をオーバーライドして、対応す...
MFCにデフォルトで定義されているメッセージ処理を行わせない...
#br
※PreTranslateMessage() は、Postされたメッセージしか処理で...
***アクティブウィンドウに対してキーメッセージを送信 [#ifd...
#code(c){{
// VK_xx に送信したい仮想キーを書く
keybd_event(VK_xx, 0, KEYEVENTF_EXTENDEDKEY, 0); ...
keybd_event(VK_xx, 0, KEYEVENTF_EXTENDEDKEY | KEYEVEN...
}}
「ALT+F」などのメッセージも、キー押下と解放のタイミングと...
***Windowsアプリケーションが終了する仕組み [#e28c5dda]
+ユーザが終了処理を行う(×を押すなど)
~↓ WM_CLOSE
+::DestroyWindow()
~↓ WM_DESTROY
+::PostQuitMessage()
~↓ WM_QUIT
+WinMain()やスレッド内で用いられている::GetMessage() が F...
***メッセージによるコマンドの実行 [#wab4d1b3]
ウィンドウにコマンドIDを付与した WM_COMMAND メッセージを...
#code(c){{
// HWND hWnd ウィンドウハンドル
// UINT nID コマンドID
// メニューコマンドを送信する場合
// ・第2引数のWPARAM
// 上位ワード : 0x0000 0
// 下位ワード : nID メニュー項目ID
::PostMessage(hWnd, WM_COMMAND, (WPARAM)MAKELONG((WOR...
// アクセラレータコマンドを送信する場合
// ・第2引数のWPARAM
// 上位ワード : 0x0001 1
// 下位ワード : nID アクセラレータキーID
::PostMessage(hWnd, WM_COMMAND, (WPARAM)MAKELONG((WOR...
}}
***アプリ間で使用する任意メッセージの受信 [#y9a866d6]
+グローバル変数として、メッセージIDを保持しておく
#code(c){{{
// ユニークなメッセージIDを取得
// ("TEST" はメッセージID登録用の任意の文字列。メッセージ...
static const UINT uiWmTest = ::RegisterWindowMessage("TES...
}}}
+ウィンドウクラスのヘッダに以下のようにイベントハンドラを...
#code(c){{{
// 生成されたメッセージ マップ関数
//{{AFX_MSG(CXxx)
:
//}}AFX_MSG
afx_msg LRESULT OnTest(WPARAM=0, LPARAM=0); // イベント...
DECLARE_MESSAGE_MAP()
}}}
+ウィンドウクラスのソースに以下のようにメッセージマップと...
#code(c){{{
BEGIN_MESSAGE_MAP(CXxx, CXxxParent)
//{{AFX_MSG_MAP(CXxx)
:
//}}AFX_MSG_MAP
ON_REGISTERED_MESSAGE(uiWmTest, OnTest) // メッセージ...
END_MESSAGE_MAP()
}}}
~
#code(c){{{
// イベントハンドラを実装
LRESULT CXxx::OnTest(WPARAM wParam/*=0*/, LPARAM lParam/*...
// 任意の処理
MessageBox("TEST");
return 0;
}
}}}
***ウィンドウサイズの制限(WM_GETMINMAXINFO) [#l9313add]
マウスドラッグやWin7のスナップ機能などによるウィンドウサ...
**コモンダイアログ [#e36b4d9a]
***ファイル選択(保存)ダイアログとカレントディレクトリ [#h...
-ファイル選択ダイアログを使用すると、カレントディレクトリ...
-OPENFILENAME::lpstrInitialDir (初期ディレクトリ) に無効...
***ファイル保存ダイアログの拡張子自動付与機能 [#dc09b3e1]
-OPENFILENAME::lpstrDefExt (デフォルト拡張子) よりも、OPE...
-OPENFILENAME::lpstrDefExt (デフォルト拡張子) にNULLを指...
※デフォルト拡張子は「.」を含まない。
***ファイル選択(保存)ダイアログ使用時にアプリケーションが...
ファイル選択ダイアログを使用していると、呼び出し元のアプ...
-発生条件
~AdobeReader7.0がインストールされていること。
-現象
~現象は、あるアプリケーションでファイル選択ダイアログを立...
一度ファイル選択ダイアログを閉じて再度同じ操作をすると、...
-対処法
~根本的な解決策は分かっていない。AdobeReader7.0が原因とい...
自作のアプリケーションであれば、ファイル選択ダイアログを...
既存のアプリケーション(メモ帳など)では、フォルダオプシ...
-原因
~本当に原因なのかは未確認だが、ネットに pdfshell.dll が原...
→ (AdobeReaderインストールフォルダ)\ActiveX~
→ C:\Program Files\Common Files\Adobe\Acrobat\ActiveX
**文字列処理 [#l9e19a41]
***マルチバイト文字とワイド文字のサンク機能 [#d510747d]
Wwindowsプログラミングをする上で、文字列を「マルチバイト...
-マルチバイト文字(MBCS)
~char型に格納して扱う。Asciiコードなどの半角英数字は1バイ...
-ワイド文字(Unicode)
~wchar_t型に格納して扱う。1文字を常に2バイト(1つの数値)で...
wchar_t型は、C言語では unsigned short に typedef されてお...
#br
~Win32APIやMFCには、これらの文字セットの切り替えを容易に...
-全般
||サンク|マルチバイト文字(MBCS)|ワイド文字(Unicode)|h
|文字&br;文字列|_T('~')&br;_T("~")|'~'&br;"~"|L'~'&b...
|変数型|TCHAR|CHAR&br;char|WCHAR&br;wchar_t|
|~|LPTSTR&br;TCHAR*|LPSTR&br;char*|LPWSTR&br;wchar_t*|
|~|LPCTSTR&br;const TCHAR*|LPCSTR&br;const char*|LPCWSTR&...
|Win32API 関数(例)|MessageBox()|MessageBoxA()|MessageBoxW...
|Win32API 構造体(例)|OPENFILENAME|OPENFILENAMEA|OPENFILEN...
|MFC クラス(例)|CString/&br;CStringT(※VC6.0では未対応)|CS...
-C標準関数(一部)
|分類|サンク|マルチバイト文字(MBCS)|ワイド文字(Unicode)|h
|文字列|_tcscat|strcat|wcscat|
|~|_tcschr|strchr|wcschr|
|~|_tcscmp|strcmp|wcscmp|
|~|_tcscpy|strcpy|wcscpy|
|~|_tcscspn|strcspn|wcscspn|
|~|_tcslen|strlen|wcslen|
|~|_tcsncat|strncat|wcsncat|
|~|_tcsncmp|strncmp|wcsncmp|
|~|_tcsncpy|strncpy|wcsncpy|
|~|_tcspbrk|strpbrk|wcspbrk|
|~|_tcsrchr|strrchr|wcsrchr|
|~|_tcsspn|strspn|wcsspn|
|~|_tcsstr|strstr|wcsstr|
|~|_tcstod|strtod|wcstod|
|~|_tcstok|strtok|wcstok|
|~|_tcstol|strtol|wcstol|
|~|_tcstoul|strtoul|wcstoul|
|~|_tcsicmp|_stricmp|_wcsicmp|
|~|_tcsnicmp|_strnicmp|_wcsnicmp|
|~|_tcslwr|_strlwr|_wcslwr|
|~|_tcsupr|_strupr|_wcsupr|
|入出力|_tprintf|printf|wprintf|
|~|_ftprintf|fprintf|fwprintf|
|~|_stprintf|sprintf|swprintf|
|~|_vtprintf|vprintf|vwprintf|
|~|_vftprintf|vfprintf|vfwprintf|
|~|_vstprintf|vsprintf|vswprintf|
|~|_tscanf|scanf|wscanf|
|~|_ftscanf|fscanf|fwscanf|
|~|_stscanf|sscanf|swscanf|
|~|_gettchar|getchar|getwchar|
|~|_fgettc|fgetc|fgetwc|
|~|_getts|gets|_getws|
|~|_fgetts|fgets|fgetws|
|~|_puttchar|putchar|putwchar|
|~|_fputtc|fputc|fputwc|
|~|_putts|puts|_putws|
|~|_fputts|fputs|fputws|
|変換|_ttoi|atoi|_wtoi|
|~|_ttol|atol|_wtol|
|~|_ttof|atof|_wtof|
|ファイル|_tmkdir|_mkdir|_wmkdir|
|~|_trmdir|_rmdir|_wrmdir|
|~|_tremove|remove|_wremove|
|~|_trename|rename|_wrename|
|~|_tfopen|fopen|_wfopen|
|~|_tpopen|_popen|_wpopen|
|~|_tfullpath|_fullpath|_wfullpath|
|~|_tmakepath|_makepath|_wmakepath|
|~|_tsplitpath|_splitpath|_wsplitpath|
|文字|_istalnum|isalnum|iswalnum|
|~|_istascii|isascii|iswascii|
|~|_istcntrl|iscntrl|iswcntrl|
|~|_istalpha|isalpha|iswalpha|
|~|_istdigit|isdigit|iswdigit|
|~|_istgraph|isgraph|iswgraph|
|~|_istlower|islower|iswlower|
|~|_istprint|isprint|iswprint|
|~|_istpunct|ispunct|iswpunct|
|~|_istspace|isspace|iswspace|
|~|_istupper|isupper|iswupper|
|~|_totupper|toupper|towupper|
|~|_totlower|tolower|towlower|
|その他|_tsystem|system|_wsystem|
***CStringオブジェクトの変換 [#t25669ac]
constな文字列型(LPCTSTR)への変換しか許されていない。~
それ以外は、変換関数が用意されていないため。
***文字列のコンバート (VBのStrConv()相当) [#i5b5ee29]
::LCMapString()で、ひらがな/カタカナ、半角/全角、大文字/...
***ファイルパス長関係のマクロの意味 [#d479626e]
これらは、「バイト数」ではなく「文字数」を定義したもの。~
マルチバイト文字を扱う場合は注意が必要。
|マクロ名|値|意味|h
|_MAX_PATH|260|フルパス|
|_MAX_DRIVE|3|ドライブ|
|_MAX_DIR|256|ディレクトリ|
|_MAX_FNAME|256|ファイル名(拡張子除く)|
|_MAX_EXT|256|拡張子(「.」含む)|
↑ <stdlib.h> に定義されている
***各種文字列型の相互変換 [#n70c2ccd]
|>||>|>|変換元 src|h
|>|~|char []|(STL) string|CString|h
|変換先&br;dst|char []||strcpy(dst, src.c_str());|strcpy(...
|~|(STL) string|dst = src;&br;dst = string(src);&br;strin...
|~|CString|dst = src;&br;dst = CString(src);&br;CString d...
|~|BSTR|dst = ::SysAllocString(src);&br;:&br;::SysFreeSt...
|~|CComBSTR|dst = src;&br;dst = CComBSTR(src);&br;CComBST...
~
|>||>|変換元 src|h
|>|~|BSTR|CComBSTR|h
|変換先&br;dst|char []|::WideCharToMultiByte(CP_ACP, 0, (...
|~|(STL) string|直接変換する方法はない|直接変換する方法は...
|~|CString|dst = src;&br;dst = CString(src);&br;CString d...
|~|BSTR||dst = src.Copy();&br;:&br;::SysFreeString(dst);|
|~|CComBSTR|dst = src;&br;dst = CComBSTR(src);&br;CComBST...
***マルチバイト文字の判定 [#bccb9a6f]
_ismbblead(),_ismbbtrail() を使用すると、「その文字がマル...
しかし、マルチバイト文字の第1バイトと第2バイトの取り得る...
例)「り」(0x82E8) の第2バイトである「0xE8」は、第1バイト...
その場合は、_ismbslead(), _ismbstrail() を使用し、文脈か...
ただし、指定した文字列全体のチェックを行うため、パフォー...
**ファイル処理 [#m33fb060]
***ファイル(ドライブ、ディレクトリ)の存在確認 [#c834cbdc]
-''Win32API''
~ファイル属性を取得する ::GetFileAttributes() で確認可能...
または、PathFileExists() や PathIsDirectory()。
-''C標準ライブラリ''
~access() や stat() 。
***ファイルのプロパティダイアログの表示 [#a2069ff1]
ファイルを右クリックして「プロパティ」を選択したときのダ...
***フォルダの属性変更 [#m8294ea4]
なぜかできない。CFile::SetStatus() だと例外が発生し、::Se...
**デバイスコンテキスト/画像処理 [#of44cd7a]
***用途別のデバイスコンテキスト [#f9290d55]
|MFCクラス|用途|備考|h
|CPaintDC|更新領域のみに対して描画する場合に使用する。|・...
|CClientDC|ウィンドウのクライアント領域全体に対して描画す...
|CWindowDC|ウィンドウの非クライアント領域(キャプションや...
***ダブルバッファリング [#q6be4fa4]
1つ1つの描画処理を行うたびに画面が更新されてしまうことに...
+ウィンドウ(ダイアログ)クラスのメンバ変数として以下を定義...
#code(c){{
// CStatic m_PcCtrl ピクチャコントロール
CDC m_memDC; // メモリデバイスコン...
CBitmap m_memBmp; // メモリデバイスコン...
CBitmap *m_pOldBmp; // メモリデバイスコン...
CRect m_PcRect; // キャンバスの矩形領域
}}
+アプリケーションの初期処理で、デバイスコンテキストと裏画...
#code(c){{
CDC *pDC; // デバイスコンテキスト
// コントロールの矩形領域の設定
m_PcCtrl.GetClientRect(&m_PcRect);
// ピクチャコントロールのデバイスコンテキストを取得
pDC = m_PcCtrl.GetDC();
// メモリデバイスコンテキストの作成
m_memDC.CreateCompatibleDC(pDC);
// メモリデバイスコンテキストの実体を作成して関連付ける
m_memBmp.CreateCompatibleBitmap(pDC, m_PcRect.Width()...
m_pOldBmp = m_memDC.SelectObject(&m_memBmp);
// デバイスコンテキスト解放
m_PcCtrl.ReleaseDC(pDC);
}}
+アプリケーションの終了処理で、デバイスコンテキストと裏画...
#code(c){{
// メモリデバイスコンテキストのビットマップを元に戻す
m_memDC.SelectObject(m_pOldBmp);
// 実体ビットマップを削除
m_memBmp.DeleteObject();
// メモリデバイスコンテキストを削除
m_memDC.DeleteDC();
}}
+CWnd::OnPaint() 等の再描画処理で、裏画面からの転送処理を...
#code(c){{
CPaintDC dc(this); // device context for painting
// TODO : ここにメッセージ ハンドラ コードを追加しま...
// 描画メッセージで CStatic::OnPaint() を呼び出さない...
// ピクチャコントロールにメモリデバイスコンテキストの...
dc.BitBlt(0, 0, m_PcRect.Width(), m_PcRect.Height(), ...
}}
+実際の描画処理。~
描画は裏画面に対して行い、最後にウィンドウの再描画を促す。
#code(c){{
// m_memDC に対して描画処理を行う
// 再描画
InvalidateRect(NULL, FALSE); // 領域を無効化
UpdateWindow(); // 領域を無効化して呼...
}}
***ウィンドウキャプチャ(ハードコピー) [#je77318f]
#code(c){{
// CWnd *pWnd キャプチャ対象のウィンドウクラス
CDC capDC; // ウィンドウキャプチャのDC
CBitmap capBmp; // ウィンドウキャプチャの...
CBitmap *pBmpOld; // 旧Bitmap
CRect wndRect; // ウィンドウの矩形
CWindowDC wndDC(pWnd); // ウィンドウDC
// ウィンドウの矩形を取得
pWnd->GetWindowRect(&wndRect);
// ウィンドウキャプチャのDCの作成
capDC.CreateCompatibleDC(NULL);
// 実体ビットマップの作成
capBmp.CreateBitmap(wndRect.Width(), wndRect.Height()...
// ウィンドウキャプチャのDCに実体を関連付ける
pBmpOld = capDC.SelectObject(&capBmp);
capDC.SetMapMode(MM_TEXT); // マップモードは1ピクセ...
// キャプチャ
capDC.BitBlt(0, 0, wndRect.Width(), wndRect.Height(),...
// capBmp にキャプチャされた画像が保持されている
// @TODO
// メモリデバイスコンテキストの実体を戻す
capDC.SelectObject(pBmpOld);
// メモリデバイスコンテキストを削除
capDC.DeleteDC();
// ビットマップを削除
capBmp.DeleteObject();
}}
***ビットマップのコピー [#e1e1dce3]
メモリ上のビットマップを複製する方法。
-''MFC''
#code(c){{
// CBitmap bmpSrc; // コピー元のビットマップ
CBitmap bmpDst; // コピー先のビットマップ
BITMAP bmpData; // コピー処理用のビットマップ...
BYTE *bmpBits; // コピー処理用のビットマップ...
// コピー元から、ビットマップ情報を取得する
if(bmpSrc.GetBitmap(&bmpData)){
// コピー元から、ビットマップデータを取得する
bmpBits = new BYTE[bmpData.bmWidthBytes * bmpData...
if(bmpSrc.GetBitmapBits(bmpData.bmWidthBytes * bm...
// コピー先へ設定する
bmpDst.CreateBitmapIndirect(&bmpData);
bmpDst.SetBitmapBits(bmpData.bmWidthBytes * b...
}
delete[] bmpBits;
}
}}
-''Win32API''
#code(c){{
// HBITMAP hBmpSrc; // コピー元のビットマップ
HBITMAP hBmpDst; // コピー先の新しいビットマップ
BITMAP bmpData; // コピー処理用のビットマップ...
BYTE *bmpBits; // コピー処理用のビットマップ...
// コピー元から、ビットマップ情報を取得する
if(::GetObject(hBmpSrc, sizeof(BITMAP), &bmpData) != ...
// コピー元から、ビットマップデータを取得する
bmpBits = new BYTE[bmpData.bmWidthBytes * bmpData...
if(::GetBitmapBits(hBmpSrc, bmpData.bmWidthBytes ...
// 新しいビットマップを作成
hBmpDst = CreateBitmapIndirect(&bmpData);
::SetBitmapBits(hBmpDst, bmpData.bmWidthBytes...
}
delete[] bmpBits;
}
}}
※SetBitmapBits()の替わりにSetDIBits()を使う必要があるらし...
***DCの内容をビットマップファイルとして保存 [#jb197919]
ビットマップファイルは次のような構造になっている。
+BITMAPFILEHEADER
+BITMAPINFOHEADER
+(カラーパレット)
+ピクセルデータ
上記の順番でバイナリデータをファイルに保存していくことで...
以下に、24bitフルカラーでのビットマップファイルの保存処理...
※フルカラーの場合、カラーパレットは格納しない。
#code(c){{
// LPCTSTR szFilePath 保存ファイルパス
// HBITMAP hBmp 保存対象のBitmapハンドル
// HDC hDC デバイスコンテキスト
DWORD dwFileAttr; // ファイル属性
HANDLE hFile; // Bitmapファ...
DWORD dwWritten; // ファイル書...
DWORD dwInfoHdrSize; // BITMAPINFO...
DWORD dwScanDataSize; // ピクセルデ...
BITMAPFILEHEADER bmpFileHeader; // BITMAPFILE...
BITMAPINFOHEADER *pBmpInfoHdr; // BITMAPINFO...
BYTE *pHeaderBuffer; // BITMAPINFO...
BYTE *pScanDataBuffer; // ピクセルデ...
BITMAP bmp; // Bitmap実体
BOOL bRet; // 戻り値
// ハンドルからBitmapの実体を取得
GetObject(hBmp, sizeof(BITMAP), &bmp);
//////// BITMAPINFOHEADER ////////
// BITMAPINFOHEADERのサイズを決定
dwInfoHdrSize = sizeof(BITMAPINFOHEADER) + sizeof(RGB...
// BITMAPINFOHEADERの実体を作成
pHeaderBuffer = new BYTE[dwInfoHdrSize];
memset(pHeaderBuffer, 0, dwInfoHdrSize);
pBmpInfoHdr = (BITMAPINFOHEADER*)pHeaderBuffer;
// 情報を格納
pBmpInfoHdr->biSize = sizeof(BITMAPINFOHEADER); /...
pBmpInfoHdr->biBitCount = 24; /...
pBmpInfoHdr->biWidth = bmp.bmWidth; /...
pBmpInfoHdr->biHeight = bmp.bmHeight; /...
pBmpInfoHdr->biPlanes = 1; /...
pBmpInfoHdr->biCompression = BI_RGB; /...
pBmpInfoHdr->biSizeImage = 0; /...
pBmpInfoHdr->biXPelsPerMeter = 0; /...
pBmpInfoHdr->biYPelsPerMeter = 0; /...
pBmpInfoHdr->biClrUsed = 0; /...
pBmpInfoHdr->biClrImportant = 0; /...
//////// ピクセルデータ ////////
// pBmpInfoHdr->biSizeImageを取得する
GetDIBits(hDC, hBmp, 0, bmp.bmHeight, NULL, (LPBITMAP...
// 取得した画像サイズでピクセルデータのバッファを用意...
dwScanDataSize = pBmpInfoHdr->biSizeImage;
pScanDataBuffer = new BYTE[dwScanDataSize];
// ピクセルデータを取得
GetDIBits(hDC, hBmp, 0, bmp.bmHeight, pScanDataBuffer...
//////// BITMAPFILEHEADER ////////
bmpFileHeader.bfType = 0x4d42; ...
bmpFileHeader.bfReserved1 = 0; ...
bmpFileHeader.bfReserved2 = 0; ...
bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + ...
bmpFileHeader.bfSize = dwScanDataSize + bmpFileHeader...
//////// Bitmapファイル作成 ////////
hFile = CreateFile(szFilePath, GENERIC_WRITE, FILE_SH...
if(hFile != INVALID_HANDLE_VALUE){
WriteFile(hFile, &bmpFileHeader, sizeof(BITMAPFIL...
WriteFile(hFile, pHeaderBuffer, dwInfoHdrSize, &d...
WriteFile(hFile, pScanDataBuffer, dwScanDataSize,...
CloseHandle(hFile);
}
// メモリ解放
delete[] pScanDataBuffer;
delete[] pHeaderBuffer;
}}
***描画時の兄弟ウィンドウのクリッピング [#d194e502]
WS_CLIPSIBLINGSスタイルを指定すると、OnPaint()やOnDraw()...
しかし、CClientDCでクライアント領域全体のデバイスコンテキ...
自作コントロールの描画処理を行う場合などは注意が必要。~
以下、兄弟ウィンドウをクリップする処理を自前で作成する場...
(※コントロール描画用のデバイスコンテキストとして CClient...
-コントロールの描画処理
#code(c){{
// WS_CLIPSIBLINGS スタイルが設定されている
if((this->GetStyle() & WS_CLIPSIBLINGS) != 0){
// 兄弟ウィンドウを列挙してクリップ
::EnumChildWindows(GetParent()->GetSafeHwnd(), ClipSibl...
}
// 描画処理
// 元に戻す
// WS_CLIPSIBLINGS スタイルが設定されている
if((this->GetStyle() & WS_CLIPSIBLINGS) != 0){
m_pDC->SelectClipRgn(NULL);
}
}}
-兄弟ウィンドウのクリッピング処理(static CALLBACK にして...
#code(c){{
BOOL CXxxCtrl::ClipSiblingsProc(HWND hwnd, LPARAM lParam)
{
CXxxCtrl *pThisWnd = (CXxxCtrl *)lParam;
CWnd *pWnd = CWnd::FromHandle(hwnd);
// 同階層の兄弟ウィンドウ かつ 描画対象のグリッドではな...
if( pThisWnd->GetParent() == pWnd->GetParent() && pThisW...
// 兄弟ウィンドウの矩形を取得する
CRect rect;
pWnd->GetWindowRect(&rect);
pThisWnd->ScreenToClient(&rect);
// 矩形領域を除外する
pThisWnd->m_pDC->ExcludeClipRect(&rect);
}
return TRUE;
}
}}
**フォント [#bf2344c3]
***フォントを変更する際の注意点 [#u289bbd2]
フォントの設定にCFontクラスのオブジェクトを用いる場合、メ...
ローカル変数だと、スコープを抜けたときに変数が自動的に破...
***単位系 [#ta347f7a]
コンピュータの世界でよく用いられる長さに関する単位。
|単位|説明|換算|h
|pixel|文字や画像を表示する際の最小要素。画素。&br;ディス...
|Twip|もとはVBでフォーム設計する際に用いられる長さの単位...
|point|フォントの大きさを表す|1point = 1/72inch|
|inch|一般的に使われる長さ。コンピュータの世界ではmmより...
|dpi|dot per inch。1inchあたりのdot数。&br;ディスプレイ上...
***セル高さと文字高さ [#f80f2072]
アクセント記号を含めた高さをセル高さ(Cell Height)、含めな...
(MSのサイトから抜粋 http://support.microsoft.com/kb/32667...
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _...
O O
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _...
/\
/ \
/ \
_ _ _ _ _ _ _ _ _ /______\ _ _ _ ___ _ _ _ _ _ _ _ _...
/ \ / \|
/ \ | |
_ _ _ _ _ _ _ _ /_ _ _ _ _ _ \ _ \___/| _ _ _ _ _ _ _ _...
|
|
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\___/_ _ _ _ _ _ _ _ _...
|
|-...
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_...
|
O O |-...
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_...
| /\
| / \
| / \
| /______\ _ _ _ ___ _ _ _ _ _ _ _ _...
Char Height -| / \ / \|
(Em) | / \ | |
| /_ _ _ _ _ _ \ _ \___/| _ _ _ _ _ _ _ _...
| |
| |
_ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _\___/_ _ _ _ _ _ _ _ _...
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _...
| ...
| O O ...
| ...
| /\ ...
| / \ ...
| / \ ...
Cell Height -| /______\ ___ ...
| / \ / \| ...
| / \ | | ...
| /_ _ _ _ _ _ \ _ \___/| _ _ _ _ _ _ _ _...
| | ...
| | ...
_ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _\___/_ _ _ _ _ _ _ _ _...
***LOGFONT構造体によるフォントサイズの指定 [#r782dcb2]
LOGFONT:lfHeightでフォントの高さ、LOGFONT:lfWidthでフォン...
-lfHeight~
0を指定すると、そのフォントのデフォルトサイズを指定したこ...
正数を指定すると、セル高さを指定したことになる。~
負数を指定すると、その絶対値を文字高さとして指定したこと...
実際には、そのフォントで使用できるサイズのうち、指定され...
~
指定する値の単位は論理単位(マッピングモード依存)。通常...
フォントのpoint数を用いて指定する場合は、以下の変換式を用...
#code(c){{
// pixel数 = (point数 * dpiY) / 72 ※dpiY : dot per in...
lfHeight = -::MulDiv(lPoint, GetDeviceCaps(hDC, LOGPIXEL...
}}
-lfWidth~
0を指定すると、フォントの種類と lfHeight から適切な値が自...
必ずしも lfHeight/2 となるわけではないことに注意。~
lfWidth に 0 を指定することで実際に幅がいくつになるかは、...
**DLL [#df7cb44a]
***リソースのみを含むDLL [#oe51089d]
ソースコード(エントリポイント)を持たないDLLを作るには、...
***DLL内での実行ファイルのパス取得 [#v9685502]
WIN32APIの ::GetModuleFileName() を使用することで、実行フ...
DLL内部のコードから ::GetModuleFileName() を使用した場合...
***DLLからモードレスダイアログを表示 [#w560662f]
DLLからモードレスダイアログを表示する場合、タブストップや...
モーダルダイアログのようにタブストップ等を処理させるには...
+グローバルな変数に、対象となるダイアログクラスオブジェク...
#code(c){{
CXxxDlg *g_pDlg;
}}
+ダイアログクラスのヘッダファイルで、フックハンドルとフッ...
#code(c){{
public:
// フックハンドル
HHOOK m_hHook;
private:
// メッセージ監視フックプロシージャ
static long CALLBACK GetMsgProc(int, WPARAM, LPARAM);
}}
+CXxxDlg::OnInitDialog() でフックプロシージャを登録する。
#code(c){{
// メッセージ監視フックプロシージャ
m_hHook = ::SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)CX...
}}
+CXxxDlg::OnDestroy() でフックプロシージャを破棄する。
#code(c){{
// フックプロシージャの破棄
::UnhookWindowsHookEx(m_hHook);
}}
+CXxxDlgクラスのソースで、フックプロシージャを実装する。
#code(c){{
// メッセージ監視フックプロシージャ
long CXxxDlg::GetMsgProc(int nCode, WPARAM wParam, LPARAM...
{
LPMSG lpMsg;
// メッセージを取得
lpMsg = (LPMSG)lParam;
// メッセージを処理する必要あり
if(nCode >= 0 && wParam == PM_REMOVE){
// キー関連メッセージ
if((lpMsg->message >= WM_KEYFIRST && lpMsg->message <= ...
// モードレスダイアログ用メッセージを処理させる
if(g_pDlg->IsDialogMessage(lpMsg)){
// 処理済みなら WM_NULL とする
lpMsg->message = WM_NULL;
lpMsg->lParam = 0;
lpMsg->wParam = 0;
}
}
}
// 次のフックプロシージャへ
return ::CallNextHookEx(g_pDlg->m_hHook, nCode, wParam, ...
}
}}
***DLL内でMFCリソースの使用 [#r709bcc8]
DLL内でダイアログを作成して表示するコードを用意して使用す...
#code(c){{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
}}
EXEからexportした関数が呼び出された状態では、リソースハン...
上記のコードによって、モジュール状態がDLL用のものに切り替...
***DLLのデバッグ方法 [#af846f08]
DLLは親となるプロセスにロードされるため、呼び出し側のEXE...
[注意点]~
-DLLはDebug版で用意しておく必要がある。
-DLLが動的リンクされている場合、::LoadLibrary()によってDL...
+呼び出し側EXEも含めてデバッグ~
呼び出し側EXEのソースが手元にある場合に有効。~
++呼び出し側EXEとデバッグ対象DLLのプロジェクトを1つのワー...
++呼び出し側EXEのデバッグを開始する。
++デバッグ対象DLL内のコードにブレークポイントを貼っておき...
+呼び出し側EXEを指定してデバッグ~
呼び出し側EXEが単純に起動できる場合に有効。~
++デバッグ対象DLLのプロジェクトを開き、プロジェクト設定の...
++デバッグ対象DLL内のコードにブレークポイントを貼っておき...
+呼び出し側EXEのプロセスにアタッチしてデバッグ~
呼び出し側EXEの起動タイミングを制御できない場合(常駐など...
++呼び出し側EXEが起動された状態にする。
++VisualStudioを新規に起動し、「プロセスにアタッチ」で呼...
++VisualStudioにデバッグ対象DLLのソースファイルをドラッグ...
**LIB [#z4a969ed]
***libファイルのリンク [#ed45b4e8]
プロジェクトにlibファイルをリンクするには以下の3つの方法...
+プロジェクトにlibファイルを追加する。コマンドラインでの...
+プロジェクトの設定でリンク指定する。
+プリプロセッサで指定する。
#code(c){{
#pragma comment(lib, "xxx.lib")
}}
***自作のスタティックライブラリ [#v57b8948]
自作クラスなどの汎用的なコードは、スタティックライブラリ...
+スタティックライブラリ側のプロジェクト
++スタティックライブラリのプロジェクトを作り、ヘッダとソ...
++ヘッダファイルの置き場所はあらかじめ決めておく。複数の...
++出力ファイルであるLibファイルもあらかじめ決めた場所に出...
+アプリケーション側のプロジェクト(Libファイルを使用する...
++プロジェクトの設定で、リンクするLIBファイルを設定する。...
++ワークスペースに使用するライブラリのプロジェクトを含め...
+VC++の設定
++ヘッダファイル、Libファイルを置いたパスをディレクトリ設...
**リソーススクリプト [#v66277bf]
-http://monado.dtiblog.com/blog-entry-52.html
-http://msdn.microsoft.com/en-us/library/aa380599(VS.85)....
**その他 [#w7ba403a]
***実行対象のWindowsバージョン [#y8998984]
Win32API等のOSの機能を使用する場合、OSのバージョンによっ...
つまり、アプリケーションを作成する場合、実行対象のWindows...
そこで、Windows用のヘッダファイルには以下のマクロが用意さ...
-WINVER~
実行対象のWindowsの最小バージョン
-_WIN32_WINNT~
実行対象のWindowsNTの最小バージョン
-_WIN32_IE~
実行対象の環境にインストールされているIEの最小バージョン
#br
-Windowsの最小バージョンの定義
|Windows|WINVER&br;_WIN32_WINNT|h
|Windows 95|0x0400|
|Windows 98|0x0410|
|Windows Me|0x0500|
|Windows NT 4.0|0x0400|
|Windows 2000|0x0500|
|Windows XP&br;Windows Server 2003|0x0501|
|Windows XP SP2&br;Windows Server 2003 SP1|0x0502|
|Windows Vista|0x0600|
|Windows 7|0x0601|
|Windows 8|0x0602|
-IEの最小バージョンの定義
|IE|_WIN32_IE|h
|Windows 95&br;Windows NT 4.0|0x0200|
|Internet Explorer 4.0|0x0400|
|Internet Explorer 4.01|0x0401|
|Internet Explorer 5.0, 5.0a, 5.0b|0x0500|
|Internet Explorer 5.01|0x0501|
|Internet Explorer 5.5|0x0550|
|Internet Explorer 6.0|0x0600|
|Internet Explorer 6.0 SP1|0x0601|
|Internet Explorer 6.0 SP2|0x0603|
|Internet Explorer 7.0|0x0700|
|Internet Explorer 8.0|0x0800|
|Internet Explorer 9.0|0x0900|
|Internet Explorer 10.0|0x0A00|
[[参考URL>http://msdn.microsoft.com/ja-jp/library/aa38374...
***コマンドライン引数 [#zc6d6927]
-''Win32API''
~::GetCommandLine()で取得可能。~
また、WinMain()で起動された場合は、__argv/__argc マクロを...
-''MFC''
~CWinApp::m_lpCmdLine に格納されている。
***二重起動防止 [#ud8cf73a]
CWinApp 派生クラスの InitInstance() で、ウィンドウ起動処...
#code(c){{
CString strExeName(m_pszExeName);
// 大文字化
strExeName.MakeUpper();
// アプリケーションの二重起動防止
CMutex mutex(FALSE, strExeName);
if(!mutex.Lock(0)) {
// 既に起動されているときの処理
// 起動しているアプリケーションのウィンドウをアクティブ...
HWND hWnd;
if((hWnd = ::FindWindow(NULL, "対象ウィドウのタイトル")...
// ウィンドウが最大化/最小化している場合は元に戻す
::ShowWindow(hWnd, SW_RESTORE);
// ウィンドウを最前面化する
::SetForegroundWindow(hWnd);
}
return FALSE;
}
// 正常時の起動処理
// :
// ミューテックスを解放
mutex.Unlock();
}}
※ <afxmt.h>をインクルードする必要がある。~
※ ミューテックス作成時に渡す文字列は大文字小文字を区別す...
***処理中の砂時計カーソル [#e2177ffb]
-''Win32API''
~::LoadIcon() であらかじめ用意されているカーソルから砂時...
#code(c){{
// HINSTANCE hInst アプリケーションのインスタン...
// 砂時計カーソル
::SetCursor(LoadCursor(NULL, IDC_WAIT));
// 任意の処理
// カーソルを元に戻す
::SetCursor(LoadCursor(NULL, IDC_ARROW));
}}
-''MFC''
~任意の処理の先頭で CWaitCursor型の変数を定義するのみ。~
CWaitCursorクラスのコンストラクタが砂時計カーソルを設定し...
#code(c){{
// 砂時計カーソル
CWaitCursor waitCursor;
// 任意の処理
// 何もしなくても、スコープを抜ければカーソルが元に戻る
}}
***カーソルの変更 [#n85c65d2]
-''MFC''
~CWnd::OnSetCursor() を実装する。~
引数の nHitTest でカーソル位置、message でマウス状態を判...
実際に設定するにはカーソルハンドルを指定する必要がある。O...
#br
例)
#code(c){{
BOOL CXxxDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, ...
{
// TODO: この位置にメッセージ ハンドラ用のコード...
HCURSOR hCursor; // カーソルハンドル
// カーソルがタイトルバーの上
if(nHitTest == HTCAPTION){
// 左クリック押下中
if(message == WM_LBUTTONDOWN){
// 全方向矢印
hCursor = ::LoadCursor(NULL, IDC_SIZEALL);
// カーソルを設定
SetCursor(hCursor);
// 独自にカーソルを設定した場合は、TRUEを...
return TRUE;
}
}
// カーソルを変更しない場合は親クラスに任せる
return CDialog::OnSetCursor(pWnd, nHitTest, messa...
}
}}
***外部プログラムの起動 [#i8452370]
-::CreateProcess()~
実行可能モジュールを新しいプロセスで起動する関数。~
基本的に第1引数は NULL にしておき、第2引数の文字列の1つ目...
理由は、第1引数に指定したコマンドは、フルパス指定かカレン...
-::ShellExecute()~
シェルにコマンドを実行させる関数。用途は実行ファイルの起...
関連付けられたアプリケーションでファイルを開くことも簡単...
***Win32APIやMFCのメンバ関数の戻り値 [#i3976e5f]
-BOOL型 (int型)
--エラーの詳細を知るためには、::GetLastError() を使用する...
--戻り値を TRUE(1)と比較してはいけない。条件が「真」であ...
-HRESULT型 (long型)
--成否の判定には、SUCCEEDED() / FAILED() マクロを用いる。~
(値の正負を判断しているだけ。つまり、HRESULT型は最上位ビ...
--戻り値からエラーの詳細を知ることができる。
--HRESULT型には、S_FALSE という、「エラーではないが失敗」...
***クリップボードの読み書き [#k28e4563]
-サンプルコード
--テキストの読み込み
#code(c){{
// char *pStr 読み込む文字列
// int nMaxCount 読み込む最大文字数
HGLOBAL hMem; // ヒープ上のメモリ領域
char *pMem; // ヒープ上のメモリ領域(文字列用)
// クリップボード内にテキストデータが存在するか
if(IsClipboardFormatAvailable(CF_TEXT)){
return;
}
// クリップボードのオープン
if(!::OpenClipboard(NULL)){
return;
}
// クリップボードから文字列を取得
if((hMem = (HGLOBAL)::GetClipboardData(CF_TEXT)) == N...
// クリップボードのクローズ
::CloseClipboard();
return;
}
// メモリをロック
pMem = (char *)::GlobalLock(hMem);
// 文字列をコピー
strncpy(pStr, pMem, nMaxCount);
pStr[nMaxCount] = '\0';
// メモリをロック解除
::GlobalUnlock(hMem);
// クリップボードのクローズ
::CloseClipboard();
}}
--テキストの書き込み
#code(c){{
// char *pStr 書き込む文字列
HGLOBAL hMem; // ヒープ上のメモリ領域
char *pMem; // ヒープ上のメモリ領域(文字列用)
// ヒープ上にメモリ領域を確保する
hMem = ::GlobalAlloc(GHND, strlen(pStr) + 1);
// メモリをロック
pMem = (char *)::GlobalLock(hMem);
// 文字列をヒープ上にコピー
strcpy(pMem, pStr);
// メモリをロック解除
::GlobalUnlock(hMem);
// クリップボードのオープン
if(::OpenClipboard(NULL)){
// クリップボードの中身を空にする
::EmptyClipboard();
// クリップボードへ文字列をコピー
::SetClipboardData(CF_TEXT, hMem);
// クリップボードのクローズ
::CloseClipboard();
// ※クリップボードへの書込みに成功したら、hMemは...
} else {
// メモリの解放
::GlobalFree(hMem);
}
}}
-クリップボードを閉じた後でのデータの変更~
クリップボードにはハンドル(グローバルな領域のアドレスを...
そのため、クリップボードを閉じた後であっても、データを変...
#code(c){{
// HBITMAP hBmpは、ビットマップデータのハンドル
// クリップボードを開く
if(::OpenClipboard(hWnd)){
// クリップボードをクリアして所有権を得る
if(::EmptyClipboard()){
// ビットマップをクリップボードに設定
::SetClipboardData(CF_BITMAP, hBmp);
}
// クリップボードを閉じる
::CloseClipboard();
}
// ここでhBmpの画像データを変更すると、クリップボードに...
}}
***アクセラレータ [#t171c798]
アプリケーションのショートカットキーを実現するアクセラレ...
+リソースにアクセラレータテーブルを追加する。(例:IDR_ACC...
+アクセラレータを関連付けるウィンドウ(ダイアログ)クラスの...
#code(c){{
BOOL CxxxxDlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: この位置に固有の処理を追加するか、または...
HACCEL hAccKey; // アクセラレータテーブルハ...
// アクセラレータテーブルハンドルを取得
hAccKey = ::LoadAccelerators(AfxGetInstanceHandle...
if (hAccKey != NULL){
// アクセラレータ処理
if (::TranslateAccelerator(this->m_hWnd, hAcc...
// アクセラレータとして処理された場合は、...
return TRUE;
}
}
return CDialog::PreTranslateMessage(pMsg);
}
}}
+アクセラレータテーブルにショートカットキーを登録する。(...
+クラスウィザードで、アクセラレータをウィンドウ(ダイアロ...
***タスクトレイ常駐 [#ga41bb66]
タスクトレイに常駐するアプリケーションの基本的な作成方法。
+リソースに、タスクトレイに表示するアイコンと、ポップアッ...
++アイコン~
アイコンを切り替える場合は、複数用意しておく。(例:IDR_M...
++ポップアップメニュー~
通常のメニューと同様に追加する。ポップアップ用メニューは...
+ポップアップメニューの項目のイベントハンドラを実装してお...
+ウィンドウ(ダイアログ)クラスのメンバ変数として以下を定義...
#code(c){{
NOTIFYICONDATA m_notifyIcon; // タスクトレイの...
}}
+タスクトレイのアイコンがクリックされた場合のユーザ定義メ...
#code(c){{
#define WM_USER_ACTION (WM_USER + 100)
}}
+アプリケーションの初期処理で、メインウィンドウを非表示し...
#code(c){{
// ウィンドウの表示を消す
ModifyStyleEx(WS_EX_APPWINDOW, WS_EX_TOOLWINDOW); ...
SetWindowPos(&wndTop, 0, 0, 0, 0, SWP_HIDEWINDOW); ...
// タスクトレイのアイコンデータを設定
memset(&m_notifyIcon, 0, sizeof(NOTIFYICONDATA));
m_notifyIcon.cbSize = sizeof(NOTIFYICONDATA); ...
m_notifyIcon.uID = 0; ...
m_notifyIcon.hWnd = m_hWnd; ...
m_notifyIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TI...
m_notifyIcon.hIcon = AfxGetApp()->LoadIcon(IDR_MAINFR...
m_notifyIcon.uCallbackMessage = WM_USER_ACTION; ...
lstrcpy(m_notifyIcon.szTip, "MAINモード"); ...
// アイコンをタスクトレイに格納する
::Shell_NotifyIcon(NIM_ADD, &m_notifyIcon);
}}
+CWnd::WindowProc() 等のウィンドウプロシージャにユーザ定...
#code(c){{
POINT pntCur; // マウスカーソルの位置
CMenu mainMenu; // メインメニュー
CMenu *pPopupMenu; // ポップアップメニュー
// メッセージ処理
switch(message){
// タスクトレイアイコンのユーザ定義メッセージ
case WM_USER_ACTION:
// wParam : m_notifyIcon.uIDの値
// lParam : マウスメッセージ
// カーソルの現在位置を取得
::GetCursorPos(&pntCur);
// 左クリック
if(lParam == WM_LBUTTONDOWN){
// メニューのロード
mainMenu.LoadMenu(IDR_MENU_POPUP);
// ポップアップメニューのロード
pPopupMenu = mainMenu.GetSubMenu(0);
if(pPopupMenu != NULL){
// メニュー項目のグレーアウト、チェックマ...
// タスクトレイのポップアップメニュー表示...
SetForegroundWindow();
// ポップアップメニュー表示
pPopupMenu->TrackPopupMenu(TPM_LEFTALIGN ...
// タスクトレイのポップアップメニュー表示...
PostMessage(WM_NULL);
}
// 右クリック
} else if(lParam == WM_RBUTTONDOWN){
//////// 以降、バルーンチップ関連 (※VC++6.0では非...
// バルーンが表示されたとき
} else if(lParam == NIN_BALLOONSHOW){
// バルーンがタイムアウトで消えたとき
} else if(lParam == NIN_BALLOONTIMEOUT){
// バルーンが通知領域のクリックにより消えたとき
} else if(lParam == NIN_BALLOONUSERCLICK){
// バルーンが×ボタンクリックにより消えたとき
} else if(lParam == NIN_BALLOONHIDE){
}
break;
}
}}
+アプリケーションの終了処理で、タスクトレイからアイコンを...
#code(c){{
// タスクトレイのアイコンを削除
::Shell_NotifyIcon(NIM_DELETE, &m_notifyIcon);
}}
+タスクトレイのアイコンに対する処理の例。
#code(c){{
//////// バルーンチップの例 (※VC++6.0では非対応) ////...
m_notifyIcon.uFlags |= NIF_INFO; // バ...
m_notifyIcon.uTimeout = 3000; // 表...
m_notifyIcon.dwInfoFlags = 0L; // バ...
lstrcpy(m_notifyIcon.szInfoTitle, "タイトル"); // バ...
wsprintf(m_notifyIcon.szInfo, "メッセージ"); // バ...
// ※...
// バルーンチップ表示
::Shell_NotifyIcon(NIM_MODIFY, &m_notifyIcon);
//////// タスクトレイアイコンの状態変更の例 ////////
m_notifyIcon.hIcon = AfxGetApp()->LoadIcon(IDR_SUBICO...
lstrcpy(m_notifyIcon.szTip, "SUBモード"); ...
// 変更を反映
::Shell_NotifyIcon(NIM_MODIFY, &m_notifyIcon);
}}
-注意
::Shell_NotifyIcon()は、時間がかかりすぎるとタイムアウト...
その場合、タスクトレイにアイコンが表示されなくなるので注...
参考:http://support.microsoft.com/kb/418138/JA/
***プロセス間共有メモリ [#e8896b6a]
通常、異なるアプリケーション間では別々のメモリ空間が使用...
そこで、OS側に仮想的なメモリ空間を作成してもらい、そのメ...
アプリAが共有メモリの内容を変更すると、それをマッピングし...
変更が即時反映されるファイルを複数プロセスで同時にオープ...
+共有ファイル作成に使用する変数等の定義
#code(c){{
#define FMAP_KEY "TEST_FMAP" // 共有メモリの識別名
#define FMAP_SIZE (sizeof(char) * 100) // サイズ:100バイト
HANDLE hFileMap; // 共有メモリのハンドル
char *pData; // 共有メモリのマッピング先アドレス
}}
+共有ファイルの使用開始
#code(c){{
// 共有メモリの実体を作成する
// ※既に実体が作成されている場合はオープンとなる。
// 明示的にオープンする場合は::OpenFileMapping()を使用...
hFileMap = ::CreateFileMapping(INVALID_HANDLE_VALUE, 0, ...
// 共有メモリのビューをメモリ空間にマッピングする
pData = (char*)::MapViewOfFile(hFileMap, FILE_MAP_ALL_AC...
}}
+共有ファイルの使用終了
#code(c){{
// 共有メモリのビューのマッピングを終了
::UnmapViewOfFile(pData);
pData = NULL;
// 共有メモリのハンドルを閉じる
::CloseHandle(hFileMap);
hFileMap = NULL;
}}
***アプリケーションのアイコン設定 [#b9dd2934]
-エクスプローラ上で表示されるexeファイルのアイコン~
アプリケーションのリソースファイル(*.rc)内で定義されてい...
コンソールアプリケーションのアイコンを変更したい場合も、...
-ウィンドウ左上のアイコン~
コード中で明示的にアイコンを設定する必要がある。~
コンソールアプリケーションの場合は変更不可。
--''Win32API''~
::RegisterClassEx() に指定するウィンドウクラス(WNDCLASS)...
--''MFC''~
CWnd::SetIcon() を使用してアイコンを設定する。
***アプリケーションのバージョン情報の取得 [#zeaf5ee0]
対象の実行ファイルのパスから、バージョン情報を取得できる。
#code(c){{
// char szPath[] モジュールのパス
// バージョン情報リソースのサイズを取得
DWORD dwZero = 0;
DWORD dwVerInfoSize;
dwVerInfoSize = ::GetFileVersionInfoSize(szPath, &dwZero);
if(dwVerInfoSize == 0) {
return FALSE;
}
// バージョン情報リソースを取得
BYTE *pVerInfo;
pVerInfo = new BYTE[dwVerInfoSize];
if(pVerInfo == NULL){
return FALSE;
}
::GetFileVersionInfo(szPath, dwZero, dwVerInfoSize, pVer...
// 各バージョン情報を取得
void *pvVersion;
UINT VersionLen;
// 以下の形式で取得するバージョン情報を指定する
// 「\StringFileInfo\[①言語識別子&コードページ識別子(16...
// ①は、日本語の場合"041104b0"となる
// FileVersionを取得
CString strFileVersion;
::VerQueryValue(pVerInfo, "\\StringFileInfo\\041104b0\\F...
strFileVersion = (LPCTSTR)pvVersion;
delete[] pVerInfo;
return TRUE;
}}
***CreateProcess()を使用する場合のリダイレクトの方法 [#if...
外部コマンドを起動して標準出力をリダイレクトする方法。(t...
#code(c){{
// HANDLE hFile // リダイレクト先のハンドル(テキストファ...
BOOL bRet;
DWORD dwEndCode;
PROCESS_INFORMATION pi;
STARTUPINFO si;
// 起動情報
ZeroMemory(&si, sizeof (si));
si.cb = sizeof(si);
si.dwFlags |= STARTF_USESTDHANDLES; // hStdOutputの使用...
si.hStdOutput = (HANDLE)hTxtFile; // リダイレクト先に指...
// プロセス起動 (第5引数をTRUEにする)
bRet = ::CreateProcess(NULL, "test.exe", NULL, NULL, TRU...
if(bRet){
// プロセスの終了を待つ
::WaitForSingleObject(pi.hProcess, INFINITE);
// プロセスの終了コードを取得
::GetExitCodeProcess(pi.hProcess, &dwEndCode);
}
}}
※標準出力のリダイレクトを追記させる場合は、予めファイルを...
同様の手順で、標準入力や標準エラー出力もリダイレクト可能。~
***ファイルのアイコン表示(エクスプローラと同じ表示) [#l2b...
-アイコンを単体で取得する場合
#code(c){{
SHFILEINFO sfi
// 小さいアイコン(16x16)
HICON hIconSmall;
hIconSmall = ::SHGetFileInfo(ファイルパス, 0, &sfi, size...
// 大きいアイコン(32x32)
HICON hIconLarge;
hIconLarge = ::SHGetFileInfo(ファイルパス, 0, &sfi, size...
}}
-アイコンをイメージリストとして取得する場合(システムイメ...
#code(c){{
SHFILEINFO sfi
// 小さいアイコン(16x16)
HIMAGELIST hImgListSmall;
hImgListSmall = (HIMAGELIST)SHGetFileInfo((LPCSTR)"C:\\"...
// 大きいアイコン(32x32)
HIMAGELIST hImgListLarge;
hImgListLarge = (HIMAGELIST)SHGetFileInfo((LPCSTR)"C:\\"...
}}
#code(c){{
// アイコンを使用するときのインデックス
SHFILEINFO sfi
SHGetFileInfo(ファイルパス, 0, &sfi, sizeof(SHFILEINFO),...
// sfi.iIcon にイメージリストのインデックスが取得される
}}
リストビュー、ツリービュー、タブなどのコントロールにアイ...
あらかじめ、CListCtrl::SetImageList()、ListView_SetImageL...
※コントロールにシステムイメージリストを使用する場合は、ウ...
***TCPサーバーの通信切断検知 [#mc9fe05c]
TCP通信を行っている際、LANケーブルが抜けるなどで通信切断...
この動作は、Keep-Aliveパケットを投げて通信が復帰しないこ...
|パラメータ|説明|デフォルト値(Linux)|h
|TCP_KEEPIDLE|Keep-Aliveを投げ始めるまでの待機時間(秒)|72...
|TCP_KEEPINTVL|Keep-Aliveを投げる間隔(秒)|75|
|TCP_KEEPCNT|Keep-Aliveを投げる回数|9|
デフォルトだと、7200 + 75 * 9 = 7875秒 待機してしまうこと...
#code(c){{
// sock : ソケットオブジェクト
int option = 1; // trueの意味
setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &option, size...
// 5 + 1 * 5 = 10秒 で切断検知する例
option = 5;
setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &option, siz...
option = 1;
setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &option, si...
option = 5;
setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &option, size...
}}
参考:https://iww.hateblo.jp/entry/20081030/setsockopt
***同期処理/排他制御 [#da47c13b]
|>||セマフォ|ミューテックス|クリティカルセクション|h
|>|同時に所有できる数|上限を設定可能|1つまで|1つまで|
|>|使用可能な範囲|プロセスをまたいで使用可能|プロセスをま...
|Win32API|オブジェクトの作成|CreateSemaphore|CreateMutex|...
|~|所有権の取得|>|WaitForSingleObject に代表される待機関...
|~|所有権の破棄|ReleaseSemaphore|ReleaseMutex|LeaveCritic...
*C/C++ネイティブ [#u9b2e1bf]
**C/C++共通 [#ccfc5367]
***定義済みプリプロセッサマクロ [#a736dd8d]
|カテゴリ|マクロ名|意味|h
|ANSI C&br;(C90)|__STDC__|標準規格のC言語であることを示す...
|~|__FILE__|ソースファイルパス|
|~|__LINE__|ソースの行番号|
|~|__TIMESTAMP__|コンパイル日時|
|~|__DATE__|コンパイル日|
|~|__TIME__|コンパイル時刻|
|C99|__func__|関数名|
|C++|__cplusplus|C++であることを示す&br;値が1とは限らない|
|文字セット&br;(どちらか一方)|_MBCS|マルチバイト文字セッ...
|~|_UNICODE|ワイド文字(Unicode)セットであることを示す|
|ビルド構成&br;(どちらか一方)|_DEBUG|Debug版|
|~|NDEBUG|Release版|
***const修飾子の効力 [#g654f90b]
ある関数Aでconst修飾された引数を、さらに関数Bの非constな...
コンパイラの警告レベルによっては、警告は出力される。
***CALLBACK関数の定義 [#oaa2d339]
CALLBACK関数は、グローバル関数やstaticメンバ関数などの静...
その他、関数ポインタを使用する仕組みも同様。~
クラスのメンバ関数はインスタンスが生成されるまでアドレス...
***ワイルドカード(*, ?)を用いた文字列検索 [#i6ddb4a0]
参考:http://katsura-kotonoha.sakura.ne.jp/prog/c/tip00003...
#code(c){{
// ワイルドカードを使用した文字列検索
// ※BOOLはintで代用可
BOOL strmatch(const char *ptn, const char *str)
{
BOOL bmatch = FALSE;
switch(*ptn){
// パターン文字列の末尾
case '\0':
// 検索対象文字列も末尾なら真
bmatch = (*str == '\0');
break;
// * : 0文字以上の任意の文字列
case '*':
// '*'が0文字とマッチしたと仮定して検索を継続
if(!(bmatch = strmatch(ptn+1, str))){
// '*'が1文字以上にマッチしていると仮定して検索を継続
if(*str != '\0'){
bmatch = strmatch(ptn, str+1);
}
}
break;
// ? : 任意の1文字
case '?':
// 次の文字から検索を継続
if(*str != '\0'){
bmatch = strmatch(ptn+1, str+1);
}
break;
// その他の文字
default:
// 今回の文字が一致するなら
if(*ptn == *str){
// 次の文字から検索を継続
if(*str != '\0'){
bmatch = strmatch(ptn+1, str+1);
}
}
break;
}
return bmatch;
}
}}
***関数シグニチャのマングルについて [#g5c5cfeb]
C++では、関数のオーバーロードを実現するために、関数シグネ...
このシンボル名を作成することをマングルと呼ぶ。~
マングルの方法は、コンパイラによって異なる。~
VC++を使用する場合はマイクロソフトの規約にしたがってマン...
逆に、シンボルを関数名に戻すことをデマングルと呼ぶ。~
VC++の場合、Win32APIの::UnDecorateSymbolName()を使用する...
参考URL:~
http://kone.vis.ne.jp/diary/diaryb13.html#080315~
http://www.kegel.com/mangle.html~
http://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B_Nam...
***構造化例外のキャッチ [#hdd334cf]
例えば、メモリアクセス違反(アクセスバイオレーション)な...
C++のtry-catch構文でキャッチするためにはコンパイルオプシ...
ただし、発生する例外はCException型ではないことに注意。以...
#code(c){{
try{
// アクセスバイオレーション発生
} catch(...) {
printf("例外発生\n");
}
}}
Visual Studio を使用している場合は、MS独自仕様の __try-__...
これはC言語のソースでも可能で、コンパイルオプションも不要...
#code(c){{
#include <excpt.h>
:
__try{
// アクセスバイオレーション発生
} __except(EXCEPTION_EXECUTE_HANDLER) {
printf("例外発生\n");
}
}}
**C++ [#pda30790]
***static関数/変数 [#lc012adb]
-staticなメンバ変数
~作成されるすべてのオブジェクト、派生クラスのオブジェクト...
-メンバ関数内のstaticなローカル変数
~staticなメンバ変数と同じ。(スコープはその関数内のみとい...
-staticなメンバ関数
~クラスのインスタンス生成無しで関数を呼び出せる。
#code(c){{
// 例
CSampleClass::sampleStaticMethod();
}}
***CPPファイルからCファイルに定義された関数を呼び出す [#x...
関数のシグネチャがCとCPPで異なるため、単純なextern宣言で...
#code(c){{
// グローバル関数 or グローバル変数
extern "C" ~~
// 複数のグローバル関数
extern "C"{
~~
~~
}
}}
***メンバ初期化子(:) [#hb253078]
クラスのメンバ変数を初期化する際、コンストラクタで初期値...
厳密に初期化を行う場合は、メンバ初期化子「:」を用いる。コ...
-コンストラクタでの「代入」
#code(c){{
class CChild
{
private:
int m_count;
int m_num;
// コンストラクタ
CChild()
{
// 代入
m_count = 0;
m_num = 100;
}
}
}}
-メンバ初期化子による「初期化」
#code(c){{
class CChild
{
private:
int m_count;
int m_num;
// コンストラクタ
CChild() : m_count(0), m_num(100)
{
}
}
}}
また、メンバ初期化子を用いることで基底クラスの初期化(と...
#code(c){{
class CChild : public CParent
{
private:
// コンストラクタ
CChild() : CParent(1) // メンバ初期化子による基...
{
}
}
}}
※メンバ初期化子で複数のメンバを初期化する際に実行される順...
***実行時型情報(RTTI) [#z042e38a]
typeid演算子によって、オブジェクトが何のクラスのインスタ...
使用するには、プロジェクトの設定で「ランタイムタイプ情報(...
***メンバアクセス演算子でprivateメンバにアクセス [#pba36e...
自身のクラス型のオブジェクトのprivateメンバは、たとえイン...
例)
#code(c, menu){{
class CSample
{
private:
int num;
void Test0()
{
printf("Test\n");
}
public:
void Test1(CSample &obj)
{
printf("%d\n", obj.num); // OK
}
void Test2(CSample *pObj)
{
pObj->Test0(); // OK
}
};
}}
*コーディングの慣例 [#k28c86ea]
**MFC派生クラスのヘッダファイル [#ye4679d4]
VC6で生成されるMFC派生クラスのヘッダファイルの例
#code(c){{{
// MFC派生クラス
class CSample : public CBase
{
DECLARE_DYNAMIC(CSample) // ①
// コンストラクション
public:
// ②
// アトリビュート
public:
// ③
// オペレーション
public:
// ④
// オーバーライド
// ClassWizard は仮想関数のオーバーライドを生成します。
//{{AFX_VIRTUAL(CAbc)
// ⑤
//}}AFX_VIRTUAL
// インプリメンテーション
public:
// ⑥
protected:
// ⑦
//{{AFX_MSG(CAbc)
// ⑧
//}}AFX_MSG
private:
// ⑨
};
}}}
''説明''~
||概要|説明|追加|h
|①|CObjectクラスの&br;機能の使用宣言 |全てのMFCクラスの...
|②|コンストラクション |コンストラクタやCWnd::Create(...
|③|アトリビュート |そのクラスの属性(プロパティ)を制...
|④|オペレーション |そのクラスのオブジェクトに対して...
|⑤|オーバーライド |MFC基底クラスの仮想関数のオーバ...
|⑥|インプリメンテーション&br;(公開メンバ) |そのクラスの...
|⑦|インプリメンテーション&br;(被保護メンバ) |そのクラスの...
|⑧|Window&br;メッセージハンドラ |Windowメッセージハン...
|⑨|インプリメンテーション&br;(非公開メンバ) |そのクラスの...
終了行:
#contents
*Windowsプログラミング [#aae2e34b]
**ダイアログボックス [#ca2af524]
***ダイアログの閉じ方と対応するイベントハンドラ [#h0086e95]
|操作|イベントハンドラ|h
|Enter|OnOK()|
|Esc|OnCancel()|
|Alt+F4|~|
***タブオーダの保存形式 [#t04332d2]
リソースファイル(*.rc)内でコントロールが定義される順番が...
***他のコントロールと連携が必要な場合の例 [#sa348c01]
異なるコントロールを連携させて使用する場合がある。連携さ...
-ラジオボタンのグループ化
~グループ化したいラジオボタンのタブオーダを連続させ、先頭...
-スピンコントロールのバディコントロール
~エディットボックスのタブオーダをスピンコントロールの直前...
この場合、値の取得やコントロールの操作は全てCSpinButtonCt...
***コントロールへのドラッグ&ドロップの優先順位 [#hc561ad0]
複数のコントロールが重なっている場合、タブオーダの小さい...
グループボックスコントロールを使用する際などは注意。
***クラスウィザードに表示されていないメッセージ [#v3678744]
クラスウィザードに目的のメッセージが表示されていない場合...
「詳細設定オプション」で「メッセージフィルタ」を変更する...
例)ダイアログクラスで初期状態ではフィルタリングされてい...
-WM_DROPFILES
~ファイルのドラッグ&ドロップ
-WM_ACTIVATE
~ウィンドウのアクティブ/非アクティブ
***コントロールのフォーカス移動 [#h004c8db]
CWnd::SetFocus() ではなく、CDialog::GotoDlgCtrl() を用い...
CWnd::SetFocus()を用いてもフォーカスは移動するが、画面描...
#code(c){{
// ボタンのコントロール変数が m_BtCtrl の場合
m_BtCtrl.SetFocus(); // ←×
GotoDlgCtrl(&m_BtCtrl); // ←○
}}
ダイアログ表示直後に指定コントロールへフォーカス設定する...
***リソースエディタ上でコントロールのフォントを指定した際...
コード上でフォントの設定をすると直ることがある。
***ツールバーを使用するには [#m55f34a1]
通常、ツールバーはSDIかMDIのアプリケーションにしか用意さ...
※ダイアログに配置するコントロールの位置は、ツールバーの範...
<ツールバーの作成>
+ツールバーのリソースを用意する。
+ダイアログクラスのメンバ変数として以下を定義しておく。
#code(c){{
CToolBar m_wndToolBar;
}}
+CXxxDlg::OnInitDialog()でツールバーを作成する。
#code(c){{
CRect rcClient;
CSize sizeToolBar;
// ツールバー作成
if(!m_wndToolBar.Create(this)){
return FALSE;
}
// ツールバーをリソースからロード
if(!m_wndToolBar.LoadToolBar(IDR_TOOLBAR)){
return FALSE;
}
// クライアント領域を取得
GetClientRect(rcClient);
// ツールバーのサイズを取得
sizeToolBar = m_wndToolBar.CalcFixedLayout(FALSE, TRUE);
// 作成時は大きさが0なので設定する必要がある
m_wndToolBar.MoveWindow(0, 0, rcClient.Width(), sizeTool...
}}
<ツールバーのボタン押下時のイベントハンドラ定義>
~クラスウィザードは対応していないため、自分で定義する必要...
+ダイアログクラスのヘッダのメッセージマップ部分に関数のプ...
#code(c){{{
// 生成されたメッセージ マップ関数
//{{AFX_MSG(CMStepEditorDlg)
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
//}}AFX_MSG
afx_msg void OnXxx(); // @TODO:ここに追加
DECLARE_MESSAGE_MAP()
}}}
+ダイアログクラスのソースに関数 OnXxx() を定義する。
+ダイアログクラスのソースのメッセージマップ部分に定義した...
#code(c){{{
BEGIN_MESSAGE_MAP(CMStepEditorDlg, CDialog)
//{{AFX_MSG_MAP(CMStepEditorDlg)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_COMMAND(ID_XXX, OnXxx) // @TODO:ここに追加
END_MESSAGE_MAP()
}}}
***イベントハンドラ活用 [#c7e6d076]
-複数の操作から同じイベントハンドラを呼び出す場合
~1つのイベントハンドラと対応する1つのリソースIDを用意し、...
--メニューの項目のID
--ツールバーのボタンのID
--アクセラレータのID
--ストリングテーブルのID
-別のIDを持つ操作から同じイベントハンドラを呼び出す場合
~1つのイベントハンドラに対して複数のIDをメッセージマップ...
例えば、2つのラジオボタンのどちらをクリックしたときも同じ...
***F1押下時のヘルプの無効化 [#na06dcc6]
アプリケーションクラスのメッセージ処理を修正することで、...
#code(c){{{
BEGIN_MESSAGE_MAP(CXxxApp, CWinApp)
//{{AFX_MSG_MAP(CXxxApp)
// メモ - ClassWizard はこの位置にマッピング用のマクロ...
// この位置に生成されるコードを編集しないでくだ...
//}}AFX_MSG
// ON_COMMAND(ID_HELP, CWinApp::OnHelp) // ※ここをコメン...
END_MESSAGE_MAP()
}}}
***ダイアログベースアプリケーションの終了コード [#r5c7907b]
アプリケーションのCWinAppを継承したクラスのExitInstance()...
***WM_INITDIALOGの戻り値 [#t9de6ed9]
通常、ウィンドウプロシージャやダイアログプロシージャの戻...
TRUE を返すと、タブオーダーが一番若いコントロールに自動的...
FALSE を返すと、何も行われない。(自分でフォーカスを当て...
~
ダイアログ生成時に明示的にあるコントロールにフォーカスを...
***CDialogBar派生クラスでOnInitDialog()を実装する方法 [#x...
CDialogBarクラスにはOnInitDialog()が用意されていないため...
~
参考:http://support.microsoft.com/kb/185672/ja
***MFCによりダイアログが自動的に中央に移動する [#ob241fd0]
MFCで作られたダイアログは、自動的に中央に移動する機能が組...
通常、OnInitDialog()でMoveWindow()等を呼び出し、明示的に...
例として、(0, 0)の位置に移動しようとしたときに現象が発生...
~
以下の条件のいずれかを満たしている場合は中央移動は行われ...
-画面の表示位置を(0, 0)以外にしている
-ダイアログテンプレート(リソース)のスタイル設定に DS_CENT...
-ダイアログテンプレート(リソース)のXY位置設定が(0, 0)では...
~
詳細は関連するMFCの関数を参照。~
-::_AfxPostInitDialog()
-CDialog::CheckAutoCenter()
**コントロール [#zd341b78]
***エディットボックス内の改行の注意点 [#p8b10388]
-複数行を許可していなくても、Ctrl+Enterで改行することがで...
-文字列取得の際、改行コードは"\r\n"として取得されるため、...
***コンボボックスのドロップダウンリストのサイズ変更 [#g26...
ダイアログエディタ上で、コンボボックスの右端の▼マークをク...
***リストビューコントロールのヘッダのソート記号 [#g161d5e1]
リストビューのヘッダに対して以下の定数を設定する。
|HDF_SORTUP|昇順(▲)|
|HDF_SORTDOWN|降順(▼)|
※この機能はXP以降の機能なので、VC6.0(1998年)時点では未対...
#code(c){{
// CListCtrl m_LcTest リストビューのコントロー...
// long lSubItem ヘッダの列インデックス
HDITEM hdItem; // ヘッダ設定情報
CHeaderCtrl* pHrCtrl; // リストビューのヘッダ
// 初期化
::ZeroMemory(&hdItem, sizeof(HDITEM));
// メンバ変数 HDITEM::fmt を有効にする
hdItem.mask = HDI_FORMAT;
// ヘッダコントロールをリストから取得
pHrCtrl = m_LcTest.GetHeaderCtrl();
// ヘッダの指定列の現在の設定状況を取得
pHrCtrl->GetItem(lSubItem, &hdItem);
// 例)昇順ソートマークを設定
hdItem.fmt &= ~HDF_SORTDOWN; // 降順マークを消す
hdItem.fmt |= HDF_SORTUP; // 昇順マークを設定
// ヘッダに設定
pHrCtrl->SetItem(lSubItem, &hdItem);
}}
***ツリービューの全展開 [#v4dc6172]
ツリービューコントロールを全展開する関数
#code(c){{
// ツリー全展開
// CTreeCtrl *pTreeCtrl 展開対象のツリーコントロ...
// HTREEITEM hParent 展開対象のノード (呼び出...
void ExpandAllTree(CTreeCtrl *pTreeCtrl, HTREEITEM hP...
HTREEITEM hChild;
// 初回呼び出し
if(hParent == NULL){
// ルートノード
if((hParent = pTreeCtrl->GetRootItem()) == NU...
// エラー
return;
}
}
// 子ノードが存在するなら
if(pTreeCtrl->ItemHasChildren(hParent) == TRUE){
// 展開
pTreeCtrl->Expand(hParent, TVE_EXPAND);
// 子ノードを順番に処理する
hChild = pTreeCtrl->GetChildItem(hParent);
while(hChild != NULL){
// 子ノードを展開する
ExpandAllTree(pTreeCtrl, hChild);
// 次の子ノード
hChild = pTreeCtrl->GetNextSiblingItem(hC...
}
}
}
}}
***スピンコントロールの値変更イベント [#m6c0c6c5]
スピンコントロールの値が変更された場合のイベントハンドラ...
しかし、スピンコントロールとエディットコントロールを自動...
対処策としては、自分でエディットコントロールにバディする...
***リッチエディットコントロール使用前の準備 [#leee484e]
リッチエディットコントロール(CRichEditCtrl)を使用する場合...
-コントロール自体の初期化~
リッチエディットコントロールを使用する前に、アプリケーシ...
呼び出すタイミングは、最初にリッチエディットコントロール...
-使用するイベントのマスク設定~
リッチエディットコントロールは、デフォルトでイベントマス...
ダイアログのOnInitDialog()で、明示的に使用するイベントの...
#code(c){{
// m_ReCtrl : リッチエディットコントロールのコントロール...
// EN_CHANGEイベント(内容が変更されたときのイベント)を使...
m_ReCtrl.SetEventMask(m_ReCtrl.GetEventMask() | ENM_CHAN...
}}
***エディット/リッチエディットコントロールのワード区切り ...
単語境界やワードラップ機能は、どのように文字列のワード区...
ワード区切りの方法を変更するには、以下のキーワードを調べ...
-EM_SETWORDBREAKPROC
-EditWordBreakProc
***コントロールの「通知」の有無 [#zfb7d171]
コントロールのプロパティの「通知」の有無の違いによって、...
(CWnd::Create()でコントロールを作成する場合は、「SS_NOTF...
-通知OFFの場合
++親ダイアログの PreTranslateMessage()
++親ダイアログの OnLButtonDown()
-通知ONの場合
++コントロールの PreTranslateMessage()
++親ダイアログの PreTranslateMessage()
++コントロールの OnLButtonDown()
++親ダイアログに追加したコントロールクリック時のイベント...
***ActiveXコントロールの登録状況の確認 [#g8d5ab8f]
ActiveXコントロールを使用したMFCアプリケーションを作成す...
それだと、なぜアプリケーションが起動しなかったのかが分か...
-チェック関数
#code(c){{
// clsid : 確認対象のActiveXコントロールのクラスID
BOOL IsControlRegister(CLSID clsid)
{
BOOL bRegistered = FALSE;
// クラスIDを文字列に変換
CString strClsid;
strClsid.Format("{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%0...
clsid.Data1,
clsid.Data2,
clsid.Data3,
clsid.Data4[0], clsid.Data4[1],
clsid.Data4[2], clsid.Data4[3], clsid.Data4[4], clsid.D...
);
// クラスIDを元にレジストリキーを作成
CString strKey;
strKey.Format("CLSID\\%s", strClsid);
// レジストリキーの存在確認
HKEY hKey = NULL;
if(::RegOpenKeyEx(HKEY_CLASSES_ROOT, strKey, 0, KEY_READ...
bRegistered = TRUE;
RegCloseKey(hKey);
}
return bRegistered;
}
}}
-使用例
#code(c){{
// AppクラスのInitInstance()で以下のコードを記述。(dlg...
// m_xxxx : dlgダイアログで使用しているOCXコントロール
// ウィザードによってGetClsid()メンバ関数が作成されてい...
if(!IsControlRegister(dlg.m_xxxx.GetClsid())){
::MessageBox(NULL, "XXXX ActiveX コントロールがインスト...
}
}}
**コントロールのサブクラス化 [#b1ba8fa2]
***サブクラス化の方法 [#ude717d6]
-動的サブクラス化
~親ダイアログクラスの初期処理で、CWnd::SubclassDlgItem()...
-静的サブクラス化
~ClassWizardを使用して派生クラスの型のコントロール変数を...
派生クラスのヘッダやソースファイルがクラスウィザードに登...
その場合は、直接ヘッダファイル内の変数定義の型名を編集す...
※サブクラス化とは、C++の「クラスの継承」のことではない。~
既存のウィンドウプロシージャを、独自のウィンドウプロシー...
***サブクラス化に用いた派生クラス内での初期処理 [#va683d55]
OnCreate()はコールされないため、初期処理を記述することは...
派生クラスでは、PreSubclassWindow()をオーバライドして、そ...
元のクラスが構築されて(OnCreate)、サブクラス化が行われる...
***MFCを継承した自作クラスへのイベントハンドラの追加 [#k7...
MFCを継承している場合は、クラスウィザードに派生クラスを認...
(認識されているかどうかは、クラスウィザードの「クラス名...
認識されていない場合は、以下の操作ができない。
-コントロールのメンバ変数追加時に、型の候補とする
-クラスビューからWindowsメッセージハンドラを追加する
プロジェクト内でクラスを作成した場合は自動的に認識される...
一度clwファイルを削除してクラスウィザードを作り直すときに...
※ちなみに、MFC継承クラスをさらに継承した場合は上記作業を...
**ウィンドウ [#b879af76]
***ウィンドウ操作関数一覧(一部) [#bc075974]
|>|操作|>|CENTER:Win32API|>|CENTER:MFC|h
|~|~|Set|Get|Set|Get|h
|>|ウィンドウ情報|-|::GetWindowInfo|-|CWnd::GetWindowInfo|
|>|親ウィンドウ|-|::GetParent|-|CWnd::GetParent|
|>|関連ウィンドウ|-|::GetWindow|-|CWnd::GetWindow|
|>|スタイル|::SetWindowLong|::GetWindowLong|CWnd::ModifyS...
|>|拡張スタイル|~|~|CWnd::ModifyStyleEx|CWnd::GetExStyle|
|>|インスタンスハンドル|~|~|-|-|
|>|ウィンドウプロシージャ|~|~|-|-|
|(特記)|使用可否|::EnableWindow|::IsWindowEnable|CWnd::En...
|~|表示状態|::ShowWindow|::IsWindowVisible|CWnd::ShowWind...
|>|ウィンドウクラス登録|::RegisterClassEx|-|-|-|
|>|ウィンドウクラス登録解除|::UnregisterClass|-|-|-|
|>|コントロールID|-|::GetDlgCtrlID|CWnd::SetDlgCtrlID|CWn...
|>|ドラッグ&ドロップ許可|::DragAcceptFiles|-|CWnd::DragA...
|>|アクティブ|::SetActiveWindow|::GetActiveWindow|CWnd::S...
|位置|スクリーン座標|::MoveWindow|::GetWindowRect|CWnd::M...
|~|クライアント座標|-|::GetClientRect|-|CWnd::GetClientRe...
|~|位置データ|::SetWindowPlacement|::GetWindowPlacement|C...
|~|Zレベル|::SetForegroundWindow|::GetForegroundWindow|CW...
|~|~|::SetWindowPos|-|CWnd::SetWindowPos|-|
|~|中央へ移動|-|-|CWnd::CenterWindow|-|
|>|キャプション|::SetWindowText|::GetWindowText|CWnd::Set...
|>|透明度|::SetLayeredWindowAttributes|::GetLayeredWindow...
|>|フォント|-|-|CWnd::SetFont|CWnd::GetFont|
|操作|閉じる|::DestroyWindow|-|CWnd::DestroyWindow|-|
|~|最大化|::ShowWindow|::IsZoomed|CWnd::ShowWindow|CWnd::...
|~|最小化|::ShowWindow&br;::CloseWindow|::IsIconic|CWnd::...
|~|メッセージ送信(同期)|::SendMessage|-|CWnd::SendMessage...
|~|メッセージ送信(非同期)|::PostMessage|-|CWnd::PostMessa...
|~|再描画|::UpdateWindow|-|CWnd::UpdateWindow|-|
***ウィンドウの中央表示 [#e4d8e618]
-''Win32API''
~ウィンドウの矩形を計算し、::MoveWindow() で移動する。
#code(c){{
// HWND hWnd 対象ウィンドウのハンドル
RECT rectDesktop; // デスクトップの領域矩形
RECT rectWnd; // ウィンドウの領域矩形
RECT rectCenter; // 中央表示の領域矩形
// デスクトップの領域を取得
SystemParametersInfo(SPI_GETWORKAREA, 0, &rectDesktop...
// ウィンドウの領域を取得
GetWindowRect(hWnd, &rectWnd);
// 中央表示の領域を計算
rectCenter.top = rectDesktop.bottom / 2 - (rectWnd.bo...
rectCenter.left = rectDesktop.right / 2 - (rectWnd.ri...
rectCenter.right = rectCenter.left + rectWnd.right;
rectCenter.bottom = rectCenter.top + rectWnd.bottom;
// ウィンドウを移動
MoveWindow( hWnd,
rectCenter.left,
rectCenter.top,
(rectCenter.right - rectCenter.left),
(rectCenter.bottom - rectCenter.top),
TRUE);
}}
-''MFC''
~CWnd::CenterWindow() を使用する。
#code(c){{
// デスクトップを基準に中央に表示する
CenterWindow(CWnd::GetDesktopWindow());
}}
***タイトルバーの高さの取得 [#ab66f67c]
OSの設定(フォントやテーマ等)に依存する。
#code(c){{
::GetSystemMetrics(SM_CYCAPTION) // タイトルバーの...
}}
***コンソールウィンドウの使用 [#w5bf5c30]
::AllocConsole(), ::FreeConsole()を用いる。~
コンソールへの入出力をするためには、標準入出力を割り当て...
#code(c){{
::AllocConsole(); // コンソール作成
// ①標準入出力を割り当てる方法
// printf()などの標準関数を使う場合
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
freopen("CONIN$", "r", stdin);
printf("test\n");
// ②コンソールハンドルを取得する方法
DWORD dwRet;
char *str = "test";
HANDLE hStdOut = ::GetStdHandle(STD_OUTPUT_HANDLE);
// コンソールへ書込み
::WriteConsole(hStdOut, str, strlen(str), &dwRet, NUL...
// アプリケーション終了時?などに::FreeConsole()でコ...
}}
***ウィンドウの描画更新の抑制 [#q420663c]
CWnd::LockWindowUpdate() と CWnd::UnlockWindowUpdate() で...
#code(c){{
LockWindowUpdate()
// 描画更新を抑制した状態で行う処理を記述
UnlockWindowUpdate()
}}
大きなツリービューへのアイテムの追加など、時間がかかる処...
***小さいアイコン(16x16)の設定 [#haeb34ab]
大きいアイコン(32x32)と小さいアイコン(16x16)の両方を用意...
その場合は、OnInitDialog() 等のアイコン設定処理で、小さい...
#code(c){{
SetIcon(m_hIcon, TRUE); // 大きいアイコンを設定
//SetIcon(m_hIcon, FALSE); // 小さいアイコンを設定
}}
※正式な修正方法ではないかも。
***メニューの項目の取得 [#e1529ac9]
取得の手順。
+メニューを持つウィンドウを識別
+メニューバーを取得
+必要があればサブメニューを取得していき、目的の項目を持つ...
+目的のメニュー項目の情報を取得(/設定)する
メニューの項目は、0から始まるインデックスで位置を指定する~
サブメニュー内は、それぞれで0から始まるインデックスを持つ。
#br
メニュー項目の取得は、MENUITEMINFO構造体を介して行う。~
MENUITEMINFO::cbSize に構造体のサイズを設定し、必要なメン...
#br
-''Win32API''
#code(c){{
// HWND hWnd メニューを持つウィンドウハン...
HMENU hMenu; // メニュー
HMENU hSubMenu; // サブメニュー
MENUITEMINFO menuItemInfo; // メニュー項目の情報
// メニューの取得
hMenu = ::GetMenu(hWnd);
// サブメニューの取得
hSubMenu = ::GetSubMenu(hMenu, 0); // メモ帳でいう「...
// MENUITEMINFO構造体を初期化
::ZeroMemory(&menuItemInfo, sizeof(MENUITEMINFO));
menuItemInfo.cbSize = sizeof(MENUITEMINFO); // お約束
menuItemInfo.fMask = MIIM_ID | MIIM_STATE; // メニュ...
// メニュー項目の情報を取得
::GetMenuItemInfo(
hSubMenu, // 対象のメニューハンドル
2, // メモ帳でいう「上書き保存」...
TRUE, // TRUEならメニューの位置、FA...
&menuItemInfo); // MENUITEMINFO構造体
// menuItemInfo.wID にメニュー項目IDが取得された
// menuItemInfo.fState にメニュー項目状態が取得された
}}
-''MFC''
#code(c){{
// CWnd *pWnd メニューを持つウィンドウクラス
CMenu *pSubMenu; // サブメニュークラス
MENUITEMINFO menuItemInfo; // メニュー項目の情報
// サブメニューを取得
pSubMenu = pWnd->GetMenu()->GetSubMenu(0); // メモ帳...
// MENUITEMINFO構造体を初期化
::ZeroMemory(&menuItemInfo, sizeof(MENUITEMINFO));
menuItemInfo.cbSize = sizeof(MENUITEMINFO); // お約束
menuItemInfo.fMask = MIIM_ID | MIIM_STATE; // メニュ...
// メニュー項目の情報を取得
pSubMenu->GetMenuItemInfo(
2, // メモ帳でいう「上書き保存」...
&menuItemInfo, // MENUITEMINFO構造体
TRUE); // TRUEならメニューの位置、FA...
// menuItemInfo.wID にメニュー項目IDが取得された
// menuItemInfo.fState にメニュー項目状態が取得された
}}
***メニューバーの描画更新 [#d24ac8ed]
メニュー項目に変更を行っても自動的に描画更新されないため...
-''Win32API''
~::DrawMenuBar()
-''MFC''
~CWnd::DrawMenuBar()
***指定ウィンドウの描画更新 [#l366c04f]
ウィンドウの描画更新を促すには、WM_PAINTを発行する必要が...
#code(c){{
// ウィンドウ全体を再描画する
pWnd->InvalidateRect(NULL); // 更新リージョンにウィンド...
pWnd->UpdateWindow(); // 更新リージョンが空でなければ...
}}
ウィンドウの一部だけを再描画させる場合は、CWnd::Invalidat...
***メッセージボックスの簡易的な最前面化 [#o379d572]
最前面ウィンドウを親に持つメッセージボックスを作成すれば...
親ウィンドウは非表示にしておけば、メッセージボックスのみ...
#code(c){{
CWnd *pDmyWnd;
TCHAR szClassName[256];
// ダミーウィンドウ生成 (非表示で最前面)
::GetClassName(this->GetSafeHwnd(), szClassName, 256);
pDmyWnd = new CWnd();
pDmyWnd->CreateEx(WS_EX_TOPMOST, szClassName, NULL, 0, C...
// ダミーウィンドウを親に持つメッセージボックス
::MessageBox(pDmyWnd->GetSafeHwnd(), "test", "test", MB_...
// ダミーウィンドウを破棄
pDmyWnd->DestroyWindow();
delete pDmyWnd;
}}
***ウィンドウの再表示 [#v91c4ad4]
ウィンドウの再表示を行う際、::ShowWindow()の第2引数に「SW...
以下のように場合分けをすることで解決できる。
#code(c){{
int nShowCmd;
// 表示コマンドを決定
if(::IsIconic(hWnd)){
// 最小化時:元の状態に戻す
nShowCmd = SW_RESTORE;
} else if(::IsZoomed(hWnd)){
// 最大化時:そのまま
nShowCmd = SW_SHOWMAXIMIZED;
} else {
// それ以外は単純に再表示
nShowCmd = SW_SHOW;
}
// ウィンドウを表示
::ShowWindow(hWnd, nShowCmd);
}}
***タイトルバーを常にアクティブ色にする [#qa874a77]
再描画のたびにウィンドウメッセージでアクティブ通知を行う。
#code(c){{
void CXxxDlg::OnPaint()
{
:
// キャプションを常にアクティブ色にする
PostMessage(WM_NCACTIVATE, TRUE);
:
}
}}
***メッセージ専用ウィンドウ [#i0849f40]
ウィンドウメッセージの処理を行いたいがウィンドウの実体は...
(ウィンドウ列挙等の対象からも外れる)
使用する場合は、予め下記の定数を設定しておく必要がある。
#define WINVER 0x0500 // 0x0500以上ならOK
-''Win32API''
#code(c){{
HWND hMsgWnd;
static const char* szWndClassName = "DUMMY_CLASS";
WNDCLASSEX wcx;
ZeroMemory(&wcx, sizeof(WNDCLASSEX));
wcx.cbSize = sizeof(WNDCLASSEX);
wcx.lpfnWndProc = DefWindowProc;
wcx.hInstance = hInst;
wcx.lpszClassName = szWndClassName;
BOOL bRegist = FALSE;
WNDCLASS wcx_dmy;
ZeroMemory(&wcx_dmy, sizeof(WNDCLASSEX));
// 既にクラスが登録されていたらRegisterClassEx()をコ...
if(!::GetClassInfo(wcx.hInstance, wcx.lpszClassName, ...
::CreateWindowEx(0, szWndClassName, "", 0, 0, 0, ...
}
}}
-''MFC''
#code(c){{
// CWnd *pWnd;
pWnd = new CWnd();
CString strWndClassName = ::AfxRegisterWndClass(NULL);
pWnd->CreateEx(0, strWndClassName, "", 0, 0, 0, 0, 0,...
}}
**ウィンドウメッセージ [#a73dc816]
***自作メッセージ [#n6691b3d]
自作のメッセージの定義は、以下の2通り。
-WM_USER + n~
プライベートなウィンドウに送る自作メッセージの定義。コモ...
-WM_APP + n~
自作アプリケーションから任意のウィンドウに送る自作メッセ...
***メッセージフック処理 [#x95361dc]
-''Win32API''
~自分でウィンドウプロシージャを定義する。
#code(c){{
LRESULT CALLBACK WinProc(HWND hWnd, UINT uMsg, WPARAM...
switch(uMsg) {
case WM_DESTROY :
PostQuitMessage(0);
return 0;
// 独自のメッセージフック
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}}
-''MFC''
~CWnd::PreTranslateMessage() をオーバーライドして、対応す...
MFCにデフォルトで定義されているメッセージ処理を行わせない...
#br
※PreTranslateMessage() は、Postされたメッセージしか処理で...
***アクティブウィンドウに対してキーメッセージを送信 [#ifd...
#code(c){{
// VK_xx に送信したい仮想キーを書く
keybd_event(VK_xx, 0, KEYEVENTF_EXTENDEDKEY, 0); ...
keybd_event(VK_xx, 0, KEYEVENTF_EXTENDEDKEY | KEYEVEN...
}}
「ALT+F」などのメッセージも、キー押下と解放のタイミングと...
***Windowsアプリケーションが終了する仕組み [#e28c5dda]
+ユーザが終了処理を行う(×を押すなど)
~↓ WM_CLOSE
+::DestroyWindow()
~↓ WM_DESTROY
+::PostQuitMessage()
~↓ WM_QUIT
+WinMain()やスレッド内で用いられている::GetMessage() が F...
***メッセージによるコマンドの実行 [#wab4d1b3]
ウィンドウにコマンドIDを付与した WM_COMMAND メッセージを...
#code(c){{
// HWND hWnd ウィンドウハンドル
// UINT nID コマンドID
// メニューコマンドを送信する場合
// ・第2引数のWPARAM
// 上位ワード : 0x0000 0
// 下位ワード : nID メニュー項目ID
::PostMessage(hWnd, WM_COMMAND, (WPARAM)MAKELONG((WOR...
// アクセラレータコマンドを送信する場合
// ・第2引数のWPARAM
// 上位ワード : 0x0001 1
// 下位ワード : nID アクセラレータキーID
::PostMessage(hWnd, WM_COMMAND, (WPARAM)MAKELONG((WOR...
}}
***アプリ間で使用する任意メッセージの受信 [#y9a866d6]
+グローバル変数として、メッセージIDを保持しておく
#code(c){{{
// ユニークなメッセージIDを取得
// ("TEST" はメッセージID登録用の任意の文字列。メッセージ...
static const UINT uiWmTest = ::RegisterWindowMessage("TES...
}}}
+ウィンドウクラスのヘッダに以下のようにイベントハンドラを...
#code(c){{{
// 生成されたメッセージ マップ関数
//{{AFX_MSG(CXxx)
:
//}}AFX_MSG
afx_msg LRESULT OnTest(WPARAM=0, LPARAM=0); // イベント...
DECLARE_MESSAGE_MAP()
}}}
+ウィンドウクラスのソースに以下のようにメッセージマップと...
#code(c){{{
BEGIN_MESSAGE_MAP(CXxx, CXxxParent)
//{{AFX_MSG_MAP(CXxx)
:
//}}AFX_MSG_MAP
ON_REGISTERED_MESSAGE(uiWmTest, OnTest) // メッセージ...
END_MESSAGE_MAP()
}}}
~
#code(c){{{
// イベントハンドラを実装
LRESULT CXxx::OnTest(WPARAM wParam/*=0*/, LPARAM lParam/*...
// 任意の処理
MessageBox("TEST");
return 0;
}
}}}
***ウィンドウサイズの制限(WM_GETMINMAXINFO) [#l9313add]
マウスドラッグやWin7のスナップ機能などによるウィンドウサ...
**コモンダイアログ [#e36b4d9a]
***ファイル選択(保存)ダイアログとカレントディレクトリ [#h...
-ファイル選択ダイアログを使用すると、カレントディレクトリ...
-OPENFILENAME::lpstrInitialDir (初期ディレクトリ) に無効...
***ファイル保存ダイアログの拡張子自動付与機能 [#dc09b3e1]
-OPENFILENAME::lpstrDefExt (デフォルト拡張子) よりも、OPE...
-OPENFILENAME::lpstrDefExt (デフォルト拡張子) にNULLを指...
※デフォルト拡張子は「.」を含まない。
***ファイル選択(保存)ダイアログ使用時にアプリケーションが...
ファイル選択ダイアログを使用していると、呼び出し元のアプ...
-発生条件
~AdobeReader7.0がインストールされていること。
-現象
~現象は、あるアプリケーションでファイル選択ダイアログを立...
一度ファイル選択ダイアログを閉じて再度同じ操作をすると、...
-対処法
~根本的な解決策は分かっていない。AdobeReader7.0が原因とい...
自作のアプリケーションであれば、ファイル選択ダイアログを...
既存のアプリケーション(メモ帳など)では、フォルダオプシ...
-原因
~本当に原因なのかは未確認だが、ネットに pdfshell.dll が原...
→ (AdobeReaderインストールフォルダ)\ActiveX~
→ C:\Program Files\Common Files\Adobe\Acrobat\ActiveX
**文字列処理 [#l9e19a41]
***マルチバイト文字とワイド文字のサンク機能 [#d510747d]
Wwindowsプログラミングをする上で、文字列を「マルチバイト...
-マルチバイト文字(MBCS)
~char型に格納して扱う。Asciiコードなどの半角英数字は1バイ...
-ワイド文字(Unicode)
~wchar_t型に格納して扱う。1文字を常に2バイト(1つの数値)で...
wchar_t型は、C言語では unsigned short に typedef されてお...
#br
~Win32APIやMFCには、これらの文字セットの切り替えを容易に...
-全般
||サンク|マルチバイト文字(MBCS)|ワイド文字(Unicode)|h
|文字&br;文字列|_T('~')&br;_T("~")|'~'&br;"~"|L'~'&b...
|変数型|TCHAR|CHAR&br;char|WCHAR&br;wchar_t|
|~|LPTSTR&br;TCHAR*|LPSTR&br;char*|LPWSTR&br;wchar_t*|
|~|LPCTSTR&br;const TCHAR*|LPCSTR&br;const char*|LPCWSTR&...
|Win32API 関数(例)|MessageBox()|MessageBoxA()|MessageBoxW...
|Win32API 構造体(例)|OPENFILENAME|OPENFILENAMEA|OPENFILEN...
|MFC クラス(例)|CString/&br;CStringT(※VC6.0では未対応)|CS...
-C標準関数(一部)
|分類|サンク|マルチバイト文字(MBCS)|ワイド文字(Unicode)|h
|文字列|_tcscat|strcat|wcscat|
|~|_tcschr|strchr|wcschr|
|~|_tcscmp|strcmp|wcscmp|
|~|_tcscpy|strcpy|wcscpy|
|~|_tcscspn|strcspn|wcscspn|
|~|_tcslen|strlen|wcslen|
|~|_tcsncat|strncat|wcsncat|
|~|_tcsncmp|strncmp|wcsncmp|
|~|_tcsncpy|strncpy|wcsncpy|
|~|_tcspbrk|strpbrk|wcspbrk|
|~|_tcsrchr|strrchr|wcsrchr|
|~|_tcsspn|strspn|wcsspn|
|~|_tcsstr|strstr|wcsstr|
|~|_tcstod|strtod|wcstod|
|~|_tcstok|strtok|wcstok|
|~|_tcstol|strtol|wcstol|
|~|_tcstoul|strtoul|wcstoul|
|~|_tcsicmp|_stricmp|_wcsicmp|
|~|_tcsnicmp|_strnicmp|_wcsnicmp|
|~|_tcslwr|_strlwr|_wcslwr|
|~|_tcsupr|_strupr|_wcsupr|
|入出力|_tprintf|printf|wprintf|
|~|_ftprintf|fprintf|fwprintf|
|~|_stprintf|sprintf|swprintf|
|~|_vtprintf|vprintf|vwprintf|
|~|_vftprintf|vfprintf|vfwprintf|
|~|_vstprintf|vsprintf|vswprintf|
|~|_tscanf|scanf|wscanf|
|~|_ftscanf|fscanf|fwscanf|
|~|_stscanf|sscanf|swscanf|
|~|_gettchar|getchar|getwchar|
|~|_fgettc|fgetc|fgetwc|
|~|_getts|gets|_getws|
|~|_fgetts|fgets|fgetws|
|~|_puttchar|putchar|putwchar|
|~|_fputtc|fputc|fputwc|
|~|_putts|puts|_putws|
|~|_fputts|fputs|fputws|
|変換|_ttoi|atoi|_wtoi|
|~|_ttol|atol|_wtol|
|~|_ttof|atof|_wtof|
|ファイル|_tmkdir|_mkdir|_wmkdir|
|~|_trmdir|_rmdir|_wrmdir|
|~|_tremove|remove|_wremove|
|~|_trename|rename|_wrename|
|~|_tfopen|fopen|_wfopen|
|~|_tpopen|_popen|_wpopen|
|~|_tfullpath|_fullpath|_wfullpath|
|~|_tmakepath|_makepath|_wmakepath|
|~|_tsplitpath|_splitpath|_wsplitpath|
|文字|_istalnum|isalnum|iswalnum|
|~|_istascii|isascii|iswascii|
|~|_istcntrl|iscntrl|iswcntrl|
|~|_istalpha|isalpha|iswalpha|
|~|_istdigit|isdigit|iswdigit|
|~|_istgraph|isgraph|iswgraph|
|~|_istlower|islower|iswlower|
|~|_istprint|isprint|iswprint|
|~|_istpunct|ispunct|iswpunct|
|~|_istspace|isspace|iswspace|
|~|_istupper|isupper|iswupper|
|~|_totupper|toupper|towupper|
|~|_totlower|tolower|towlower|
|その他|_tsystem|system|_wsystem|
***CStringオブジェクトの変換 [#t25669ac]
constな文字列型(LPCTSTR)への変換しか許されていない。~
それ以外は、変換関数が用意されていないため。
***文字列のコンバート (VBのStrConv()相当) [#i5b5ee29]
::LCMapString()で、ひらがな/カタカナ、半角/全角、大文字/...
***ファイルパス長関係のマクロの意味 [#d479626e]
これらは、「バイト数」ではなく「文字数」を定義したもの。~
マルチバイト文字を扱う場合は注意が必要。
|マクロ名|値|意味|h
|_MAX_PATH|260|フルパス|
|_MAX_DRIVE|3|ドライブ|
|_MAX_DIR|256|ディレクトリ|
|_MAX_FNAME|256|ファイル名(拡張子除く)|
|_MAX_EXT|256|拡張子(「.」含む)|
↑ <stdlib.h> に定義されている
***各種文字列型の相互変換 [#n70c2ccd]
|>||>|>|変換元 src|h
|>|~|char []|(STL) string|CString|h
|変換先&br;dst|char []||strcpy(dst, src.c_str());|strcpy(...
|~|(STL) string|dst = src;&br;dst = string(src);&br;strin...
|~|CString|dst = src;&br;dst = CString(src);&br;CString d...
|~|BSTR|dst = ::SysAllocString(src);&br;:&br;::SysFreeSt...
|~|CComBSTR|dst = src;&br;dst = CComBSTR(src);&br;CComBST...
~
|>||>|変換元 src|h
|>|~|BSTR|CComBSTR|h
|変換先&br;dst|char []|::WideCharToMultiByte(CP_ACP, 0, (...
|~|(STL) string|直接変換する方法はない|直接変換する方法は...
|~|CString|dst = src;&br;dst = CString(src);&br;CString d...
|~|BSTR||dst = src.Copy();&br;:&br;::SysFreeString(dst);|
|~|CComBSTR|dst = src;&br;dst = CComBSTR(src);&br;CComBST...
***マルチバイト文字の判定 [#bccb9a6f]
_ismbblead(),_ismbbtrail() を使用すると、「その文字がマル...
しかし、マルチバイト文字の第1バイトと第2バイトの取り得る...
例)「り」(0x82E8) の第2バイトである「0xE8」は、第1バイト...
その場合は、_ismbslead(), _ismbstrail() を使用し、文脈か...
ただし、指定した文字列全体のチェックを行うため、パフォー...
**ファイル処理 [#m33fb060]
***ファイル(ドライブ、ディレクトリ)の存在確認 [#c834cbdc]
-''Win32API''
~ファイル属性を取得する ::GetFileAttributes() で確認可能...
または、PathFileExists() や PathIsDirectory()。
-''C標準ライブラリ''
~access() や stat() 。
***ファイルのプロパティダイアログの表示 [#a2069ff1]
ファイルを右クリックして「プロパティ」を選択したときのダ...
***フォルダの属性変更 [#m8294ea4]
なぜかできない。CFile::SetStatus() だと例外が発生し、::Se...
**デバイスコンテキスト/画像処理 [#of44cd7a]
***用途別のデバイスコンテキスト [#f9290d55]
|MFCクラス|用途|備考|h
|CPaintDC|更新領域のみに対して描画する場合に使用する。|・...
|CClientDC|ウィンドウのクライアント領域全体に対して描画す...
|CWindowDC|ウィンドウの非クライアント領域(キャプションや...
***ダブルバッファリング [#q6be4fa4]
1つ1つの描画処理を行うたびに画面が更新されてしまうことに...
+ウィンドウ(ダイアログ)クラスのメンバ変数として以下を定義...
#code(c){{
// CStatic m_PcCtrl ピクチャコントロール
CDC m_memDC; // メモリデバイスコン...
CBitmap m_memBmp; // メモリデバイスコン...
CBitmap *m_pOldBmp; // メモリデバイスコン...
CRect m_PcRect; // キャンバスの矩形領域
}}
+アプリケーションの初期処理で、デバイスコンテキストと裏画...
#code(c){{
CDC *pDC; // デバイスコンテキスト
// コントロールの矩形領域の設定
m_PcCtrl.GetClientRect(&m_PcRect);
// ピクチャコントロールのデバイスコンテキストを取得
pDC = m_PcCtrl.GetDC();
// メモリデバイスコンテキストの作成
m_memDC.CreateCompatibleDC(pDC);
// メモリデバイスコンテキストの実体を作成して関連付ける
m_memBmp.CreateCompatibleBitmap(pDC, m_PcRect.Width()...
m_pOldBmp = m_memDC.SelectObject(&m_memBmp);
// デバイスコンテキスト解放
m_PcCtrl.ReleaseDC(pDC);
}}
+アプリケーションの終了処理で、デバイスコンテキストと裏画...
#code(c){{
// メモリデバイスコンテキストのビットマップを元に戻す
m_memDC.SelectObject(m_pOldBmp);
// 実体ビットマップを削除
m_memBmp.DeleteObject();
// メモリデバイスコンテキストを削除
m_memDC.DeleteDC();
}}
+CWnd::OnPaint() 等の再描画処理で、裏画面からの転送処理を...
#code(c){{
CPaintDC dc(this); // device context for painting
// TODO : ここにメッセージ ハンドラ コードを追加しま...
// 描画メッセージで CStatic::OnPaint() を呼び出さない...
// ピクチャコントロールにメモリデバイスコンテキストの...
dc.BitBlt(0, 0, m_PcRect.Width(), m_PcRect.Height(), ...
}}
+実際の描画処理。~
描画は裏画面に対して行い、最後にウィンドウの再描画を促す。
#code(c){{
// m_memDC に対して描画処理を行う
// 再描画
InvalidateRect(NULL, FALSE); // 領域を無効化
UpdateWindow(); // 領域を無効化して呼...
}}
***ウィンドウキャプチャ(ハードコピー) [#je77318f]
#code(c){{
// CWnd *pWnd キャプチャ対象のウィンドウクラス
CDC capDC; // ウィンドウキャプチャのDC
CBitmap capBmp; // ウィンドウキャプチャの...
CBitmap *pBmpOld; // 旧Bitmap
CRect wndRect; // ウィンドウの矩形
CWindowDC wndDC(pWnd); // ウィンドウDC
// ウィンドウの矩形を取得
pWnd->GetWindowRect(&wndRect);
// ウィンドウキャプチャのDCの作成
capDC.CreateCompatibleDC(NULL);
// 実体ビットマップの作成
capBmp.CreateBitmap(wndRect.Width(), wndRect.Height()...
// ウィンドウキャプチャのDCに実体を関連付ける
pBmpOld = capDC.SelectObject(&capBmp);
capDC.SetMapMode(MM_TEXT); // マップモードは1ピクセ...
// キャプチャ
capDC.BitBlt(0, 0, wndRect.Width(), wndRect.Height(),...
// capBmp にキャプチャされた画像が保持されている
// @TODO
// メモリデバイスコンテキストの実体を戻す
capDC.SelectObject(pBmpOld);
// メモリデバイスコンテキストを削除
capDC.DeleteDC();
// ビットマップを削除
capBmp.DeleteObject();
}}
***ビットマップのコピー [#e1e1dce3]
メモリ上のビットマップを複製する方法。
-''MFC''
#code(c){{
// CBitmap bmpSrc; // コピー元のビットマップ
CBitmap bmpDst; // コピー先のビットマップ
BITMAP bmpData; // コピー処理用のビットマップ...
BYTE *bmpBits; // コピー処理用のビットマップ...
// コピー元から、ビットマップ情報を取得する
if(bmpSrc.GetBitmap(&bmpData)){
// コピー元から、ビットマップデータを取得する
bmpBits = new BYTE[bmpData.bmWidthBytes * bmpData...
if(bmpSrc.GetBitmapBits(bmpData.bmWidthBytes * bm...
// コピー先へ設定する
bmpDst.CreateBitmapIndirect(&bmpData);
bmpDst.SetBitmapBits(bmpData.bmWidthBytes * b...
}
delete[] bmpBits;
}
}}
-''Win32API''
#code(c){{
// HBITMAP hBmpSrc; // コピー元のビットマップ
HBITMAP hBmpDst; // コピー先の新しいビットマップ
BITMAP bmpData; // コピー処理用のビットマップ...
BYTE *bmpBits; // コピー処理用のビットマップ...
// コピー元から、ビットマップ情報を取得する
if(::GetObject(hBmpSrc, sizeof(BITMAP), &bmpData) != ...
// コピー元から、ビットマップデータを取得する
bmpBits = new BYTE[bmpData.bmWidthBytes * bmpData...
if(::GetBitmapBits(hBmpSrc, bmpData.bmWidthBytes ...
// 新しいビットマップを作成
hBmpDst = CreateBitmapIndirect(&bmpData);
::SetBitmapBits(hBmpDst, bmpData.bmWidthBytes...
}
delete[] bmpBits;
}
}}
※SetBitmapBits()の替わりにSetDIBits()を使う必要があるらし...
***DCの内容をビットマップファイルとして保存 [#jb197919]
ビットマップファイルは次のような構造になっている。
+BITMAPFILEHEADER
+BITMAPINFOHEADER
+(カラーパレット)
+ピクセルデータ
上記の順番でバイナリデータをファイルに保存していくことで...
以下に、24bitフルカラーでのビットマップファイルの保存処理...
※フルカラーの場合、カラーパレットは格納しない。
#code(c){{
// LPCTSTR szFilePath 保存ファイルパス
// HBITMAP hBmp 保存対象のBitmapハンドル
// HDC hDC デバイスコンテキスト
DWORD dwFileAttr; // ファイル属性
HANDLE hFile; // Bitmapファ...
DWORD dwWritten; // ファイル書...
DWORD dwInfoHdrSize; // BITMAPINFO...
DWORD dwScanDataSize; // ピクセルデ...
BITMAPFILEHEADER bmpFileHeader; // BITMAPFILE...
BITMAPINFOHEADER *pBmpInfoHdr; // BITMAPINFO...
BYTE *pHeaderBuffer; // BITMAPINFO...
BYTE *pScanDataBuffer; // ピクセルデ...
BITMAP bmp; // Bitmap実体
BOOL bRet; // 戻り値
// ハンドルからBitmapの実体を取得
GetObject(hBmp, sizeof(BITMAP), &bmp);
//////// BITMAPINFOHEADER ////////
// BITMAPINFOHEADERのサイズを決定
dwInfoHdrSize = sizeof(BITMAPINFOHEADER) + sizeof(RGB...
// BITMAPINFOHEADERの実体を作成
pHeaderBuffer = new BYTE[dwInfoHdrSize];
memset(pHeaderBuffer, 0, dwInfoHdrSize);
pBmpInfoHdr = (BITMAPINFOHEADER*)pHeaderBuffer;
// 情報を格納
pBmpInfoHdr->biSize = sizeof(BITMAPINFOHEADER); /...
pBmpInfoHdr->biBitCount = 24; /...
pBmpInfoHdr->biWidth = bmp.bmWidth; /...
pBmpInfoHdr->biHeight = bmp.bmHeight; /...
pBmpInfoHdr->biPlanes = 1; /...
pBmpInfoHdr->biCompression = BI_RGB; /...
pBmpInfoHdr->biSizeImage = 0; /...
pBmpInfoHdr->biXPelsPerMeter = 0; /...
pBmpInfoHdr->biYPelsPerMeter = 0; /...
pBmpInfoHdr->biClrUsed = 0; /...
pBmpInfoHdr->biClrImportant = 0; /...
//////// ピクセルデータ ////////
// pBmpInfoHdr->biSizeImageを取得する
GetDIBits(hDC, hBmp, 0, bmp.bmHeight, NULL, (LPBITMAP...
// 取得した画像サイズでピクセルデータのバッファを用意...
dwScanDataSize = pBmpInfoHdr->biSizeImage;
pScanDataBuffer = new BYTE[dwScanDataSize];
// ピクセルデータを取得
GetDIBits(hDC, hBmp, 0, bmp.bmHeight, pScanDataBuffer...
//////// BITMAPFILEHEADER ////////
bmpFileHeader.bfType = 0x4d42; ...
bmpFileHeader.bfReserved1 = 0; ...
bmpFileHeader.bfReserved2 = 0; ...
bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + ...
bmpFileHeader.bfSize = dwScanDataSize + bmpFileHeader...
//////// Bitmapファイル作成 ////////
hFile = CreateFile(szFilePath, GENERIC_WRITE, FILE_SH...
if(hFile != INVALID_HANDLE_VALUE){
WriteFile(hFile, &bmpFileHeader, sizeof(BITMAPFIL...
WriteFile(hFile, pHeaderBuffer, dwInfoHdrSize, &d...
WriteFile(hFile, pScanDataBuffer, dwScanDataSize,...
CloseHandle(hFile);
}
// メモリ解放
delete[] pScanDataBuffer;
delete[] pHeaderBuffer;
}}
***描画時の兄弟ウィンドウのクリッピング [#d194e502]
WS_CLIPSIBLINGSスタイルを指定すると、OnPaint()やOnDraw()...
しかし、CClientDCでクライアント領域全体のデバイスコンテキ...
自作コントロールの描画処理を行う場合などは注意が必要。~
以下、兄弟ウィンドウをクリップする処理を自前で作成する場...
(※コントロール描画用のデバイスコンテキストとして CClient...
-コントロールの描画処理
#code(c){{
// WS_CLIPSIBLINGS スタイルが設定されている
if((this->GetStyle() & WS_CLIPSIBLINGS) != 0){
// 兄弟ウィンドウを列挙してクリップ
::EnumChildWindows(GetParent()->GetSafeHwnd(), ClipSibl...
}
// 描画処理
// 元に戻す
// WS_CLIPSIBLINGS スタイルが設定されている
if((this->GetStyle() & WS_CLIPSIBLINGS) != 0){
m_pDC->SelectClipRgn(NULL);
}
}}
-兄弟ウィンドウのクリッピング処理(static CALLBACK にして...
#code(c){{
BOOL CXxxCtrl::ClipSiblingsProc(HWND hwnd, LPARAM lParam)
{
CXxxCtrl *pThisWnd = (CXxxCtrl *)lParam;
CWnd *pWnd = CWnd::FromHandle(hwnd);
// 同階層の兄弟ウィンドウ かつ 描画対象のグリッドではな...
if( pThisWnd->GetParent() == pWnd->GetParent() && pThisW...
// 兄弟ウィンドウの矩形を取得する
CRect rect;
pWnd->GetWindowRect(&rect);
pThisWnd->ScreenToClient(&rect);
// 矩形領域を除外する
pThisWnd->m_pDC->ExcludeClipRect(&rect);
}
return TRUE;
}
}}
**フォント [#bf2344c3]
***フォントを変更する際の注意点 [#u289bbd2]
フォントの設定にCFontクラスのオブジェクトを用いる場合、メ...
ローカル変数だと、スコープを抜けたときに変数が自動的に破...
***単位系 [#ta347f7a]
コンピュータの世界でよく用いられる長さに関する単位。
|単位|説明|換算|h
|pixel|文字や画像を表示する際の最小要素。画素。&br;ディス...
|Twip|もとはVBでフォーム設計する際に用いられる長さの単位...
|point|フォントの大きさを表す|1point = 1/72inch|
|inch|一般的に使われる長さ。コンピュータの世界ではmmより...
|dpi|dot per inch。1inchあたりのdot数。&br;ディスプレイ上...
***セル高さと文字高さ [#f80f2072]
アクセント記号を含めた高さをセル高さ(Cell Height)、含めな...
(MSのサイトから抜粋 http://support.microsoft.com/kb/32667...
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _...
O O
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _...
/\
/ \
/ \
_ _ _ _ _ _ _ _ _ /______\ _ _ _ ___ _ _ _ _ _ _ _ _...
/ \ / \|
/ \ | |
_ _ _ _ _ _ _ _ /_ _ _ _ _ _ \ _ \___/| _ _ _ _ _ _ _ _...
|
|
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\___/_ _ _ _ _ _ _ _ _...
|
|-...
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_...
|
O O |-...
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_...
| /\
| / \
| / \
| /______\ _ _ _ ___ _ _ _ _ _ _ _ _...
Char Height -| / \ / \|
(Em) | / \ | |
| /_ _ _ _ _ _ \ _ \___/| _ _ _ _ _ _ _ _...
| |
| |
_ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _\___/_ _ _ _ _ _ _ _ _...
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _...
| ...
| O O ...
| ...
| /\ ...
| / \ ...
| / \ ...
Cell Height -| /______\ ___ ...
| / \ / \| ...
| / \ | | ...
| /_ _ _ _ _ _ \ _ \___/| _ _ _ _ _ _ _ _...
| | ...
| | ...
_ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _\___/_ _ _ _ _ _ _ _ _...
***LOGFONT構造体によるフォントサイズの指定 [#r782dcb2]
LOGFONT:lfHeightでフォントの高さ、LOGFONT:lfWidthでフォン...
-lfHeight~
0を指定すると、そのフォントのデフォルトサイズを指定したこ...
正数を指定すると、セル高さを指定したことになる。~
負数を指定すると、その絶対値を文字高さとして指定したこと...
実際には、そのフォントで使用できるサイズのうち、指定され...
~
指定する値の単位は論理単位(マッピングモード依存)。通常...
フォントのpoint数を用いて指定する場合は、以下の変換式を用...
#code(c){{
// pixel数 = (point数 * dpiY) / 72 ※dpiY : dot per in...
lfHeight = -::MulDiv(lPoint, GetDeviceCaps(hDC, LOGPIXEL...
}}
-lfWidth~
0を指定すると、フォントの種類と lfHeight から適切な値が自...
必ずしも lfHeight/2 となるわけではないことに注意。~
lfWidth に 0 を指定することで実際に幅がいくつになるかは、...
**DLL [#df7cb44a]
***リソースのみを含むDLL [#oe51089d]
ソースコード(エントリポイント)を持たないDLLを作るには、...
***DLL内での実行ファイルのパス取得 [#v9685502]
WIN32APIの ::GetModuleFileName() を使用することで、実行フ...
DLL内部のコードから ::GetModuleFileName() を使用した場合...
***DLLからモードレスダイアログを表示 [#w560662f]
DLLからモードレスダイアログを表示する場合、タブストップや...
モーダルダイアログのようにタブストップ等を処理させるには...
+グローバルな変数に、対象となるダイアログクラスオブジェク...
#code(c){{
CXxxDlg *g_pDlg;
}}
+ダイアログクラスのヘッダファイルで、フックハンドルとフッ...
#code(c){{
public:
// フックハンドル
HHOOK m_hHook;
private:
// メッセージ監視フックプロシージャ
static long CALLBACK GetMsgProc(int, WPARAM, LPARAM);
}}
+CXxxDlg::OnInitDialog() でフックプロシージャを登録する。
#code(c){{
// メッセージ監視フックプロシージャ
m_hHook = ::SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)CX...
}}
+CXxxDlg::OnDestroy() でフックプロシージャを破棄する。
#code(c){{
// フックプロシージャの破棄
::UnhookWindowsHookEx(m_hHook);
}}
+CXxxDlgクラスのソースで、フックプロシージャを実装する。
#code(c){{
// メッセージ監視フックプロシージャ
long CXxxDlg::GetMsgProc(int nCode, WPARAM wParam, LPARAM...
{
LPMSG lpMsg;
// メッセージを取得
lpMsg = (LPMSG)lParam;
// メッセージを処理する必要あり
if(nCode >= 0 && wParam == PM_REMOVE){
// キー関連メッセージ
if((lpMsg->message >= WM_KEYFIRST && lpMsg->message <= ...
// モードレスダイアログ用メッセージを処理させる
if(g_pDlg->IsDialogMessage(lpMsg)){
// 処理済みなら WM_NULL とする
lpMsg->message = WM_NULL;
lpMsg->lParam = 0;
lpMsg->wParam = 0;
}
}
}
// 次のフックプロシージャへ
return ::CallNextHookEx(g_pDlg->m_hHook, nCode, wParam, ...
}
}}
***DLL内でMFCリソースの使用 [#r709bcc8]
DLL内でダイアログを作成して表示するコードを用意して使用す...
#code(c){{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
}}
EXEからexportした関数が呼び出された状態では、リソースハン...
上記のコードによって、モジュール状態がDLL用のものに切り替...
***DLLのデバッグ方法 [#af846f08]
DLLは親となるプロセスにロードされるため、呼び出し側のEXE...
[注意点]~
-DLLはDebug版で用意しておく必要がある。
-DLLが動的リンクされている場合、::LoadLibrary()によってDL...
+呼び出し側EXEも含めてデバッグ~
呼び出し側EXEのソースが手元にある場合に有効。~
++呼び出し側EXEとデバッグ対象DLLのプロジェクトを1つのワー...
++呼び出し側EXEのデバッグを開始する。
++デバッグ対象DLL内のコードにブレークポイントを貼っておき...
+呼び出し側EXEを指定してデバッグ~
呼び出し側EXEが単純に起動できる場合に有効。~
++デバッグ対象DLLのプロジェクトを開き、プロジェクト設定の...
++デバッグ対象DLL内のコードにブレークポイントを貼っておき...
+呼び出し側EXEのプロセスにアタッチしてデバッグ~
呼び出し側EXEの起動タイミングを制御できない場合(常駐など...
++呼び出し側EXEが起動された状態にする。
++VisualStudioを新規に起動し、「プロセスにアタッチ」で呼...
++VisualStudioにデバッグ対象DLLのソースファイルをドラッグ...
**LIB [#z4a969ed]
***libファイルのリンク [#ed45b4e8]
プロジェクトにlibファイルをリンクするには以下の3つの方法...
+プロジェクトにlibファイルを追加する。コマンドラインでの...
+プロジェクトの設定でリンク指定する。
+プリプロセッサで指定する。
#code(c){{
#pragma comment(lib, "xxx.lib")
}}
***自作のスタティックライブラリ [#v57b8948]
自作クラスなどの汎用的なコードは、スタティックライブラリ...
+スタティックライブラリ側のプロジェクト
++スタティックライブラリのプロジェクトを作り、ヘッダとソ...
++ヘッダファイルの置き場所はあらかじめ決めておく。複数の...
++出力ファイルであるLibファイルもあらかじめ決めた場所に出...
+アプリケーション側のプロジェクト(Libファイルを使用する...
++プロジェクトの設定で、リンクするLIBファイルを設定する。...
++ワークスペースに使用するライブラリのプロジェクトを含め...
+VC++の設定
++ヘッダファイル、Libファイルを置いたパスをディレクトリ設...
**リソーススクリプト [#v66277bf]
-http://monado.dtiblog.com/blog-entry-52.html
-http://msdn.microsoft.com/en-us/library/aa380599(VS.85)....
**その他 [#w7ba403a]
***実行対象のWindowsバージョン [#y8998984]
Win32API等のOSの機能を使用する場合、OSのバージョンによっ...
つまり、アプリケーションを作成する場合、実行対象のWindows...
そこで、Windows用のヘッダファイルには以下のマクロが用意さ...
-WINVER~
実行対象のWindowsの最小バージョン
-_WIN32_WINNT~
実行対象のWindowsNTの最小バージョン
-_WIN32_IE~
実行対象の環境にインストールされているIEの最小バージョン
#br
-Windowsの最小バージョンの定義
|Windows|WINVER&br;_WIN32_WINNT|h
|Windows 95|0x0400|
|Windows 98|0x0410|
|Windows Me|0x0500|
|Windows NT 4.0|0x0400|
|Windows 2000|0x0500|
|Windows XP&br;Windows Server 2003|0x0501|
|Windows XP SP2&br;Windows Server 2003 SP1|0x0502|
|Windows Vista|0x0600|
|Windows 7|0x0601|
|Windows 8|0x0602|
-IEの最小バージョンの定義
|IE|_WIN32_IE|h
|Windows 95&br;Windows NT 4.0|0x0200|
|Internet Explorer 4.0|0x0400|
|Internet Explorer 4.01|0x0401|
|Internet Explorer 5.0, 5.0a, 5.0b|0x0500|
|Internet Explorer 5.01|0x0501|
|Internet Explorer 5.5|0x0550|
|Internet Explorer 6.0|0x0600|
|Internet Explorer 6.0 SP1|0x0601|
|Internet Explorer 6.0 SP2|0x0603|
|Internet Explorer 7.0|0x0700|
|Internet Explorer 8.0|0x0800|
|Internet Explorer 9.0|0x0900|
|Internet Explorer 10.0|0x0A00|
[[参考URL>http://msdn.microsoft.com/ja-jp/library/aa38374...
***コマンドライン引数 [#zc6d6927]
-''Win32API''
~::GetCommandLine()で取得可能。~
また、WinMain()で起動された場合は、__argv/__argc マクロを...
-''MFC''
~CWinApp::m_lpCmdLine に格納されている。
***二重起動防止 [#ud8cf73a]
CWinApp 派生クラスの InitInstance() で、ウィンドウ起動処...
#code(c){{
CString strExeName(m_pszExeName);
// 大文字化
strExeName.MakeUpper();
// アプリケーションの二重起動防止
CMutex mutex(FALSE, strExeName);
if(!mutex.Lock(0)) {
// 既に起動されているときの処理
// 起動しているアプリケーションのウィンドウをアクティブ...
HWND hWnd;
if((hWnd = ::FindWindow(NULL, "対象ウィドウのタイトル")...
// ウィンドウが最大化/最小化している場合は元に戻す
::ShowWindow(hWnd, SW_RESTORE);
// ウィンドウを最前面化する
::SetForegroundWindow(hWnd);
}
return FALSE;
}
// 正常時の起動処理
// :
// ミューテックスを解放
mutex.Unlock();
}}
※ <afxmt.h>をインクルードする必要がある。~
※ ミューテックス作成時に渡す文字列は大文字小文字を区別す...
***処理中の砂時計カーソル [#e2177ffb]
-''Win32API''
~::LoadIcon() であらかじめ用意されているカーソルから砂時...
#code(c){{
// HINSTANCE hInst アプリケーションのインスタン...
// 砂時計カーソル
::SetCursor(LoadCursor(NULL, IDC_WAIT));
// 任意の処理
// カーソルを元に戻す
::SetCursor(LoadCursor(NULL, IDC_ARROW));
}}
-''MFC''
~任意の処理の先頭で CWaitCursor型の変数を定義するのみ。~
CWaitCursorクラスのコンストラクタが砂時計カーソルを設定し...
#code(c){{
// 砂時計カーソル
CWaitCursor waitCursor;
// 任意の処理
// 何もしなくても、スコープを抜ければカーソルが元に戻る
}}
***カーソルの変更 [#n85c65d2]
-''MFC''
~CWnd::OnSetCursor() を実装する。~
引数の nHitTest でカーソル位置、message でマウス状態を判...
実際に設定するにはカーソルハンドルを指定する必要がある。O...
#br
例)
#code(c){{
BOOL CXxxDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, ...
{
// TODO: この位置にメッセージ ハンドラ用のコード...
HCURSOR hCursor; // カーソルハンドル
// カーソルがタイトルバーの上
if(nHitTest == HTCAPTION){
// 左クリック押下中
if(message == WM_LBUTTONDOWN){
// 全方向矢印
hCursor = ::LoadCursor(NULL, IDC_SIZEALL);
// カーソルを設定
SetCursor(hCursor);
// 独自にカーソルを設定した場合は、TRUEを...
return TRUE;
}
}
// カーソルを変更しない場合は親クラスに任せる
return CDialog::OnSetCursor(pWnd, nHitTest, messa...
}
}}
***外部プログラムの起動 [#i8452370]
-::CreateProcess()~
実行可能モジュールを新しいプロセスで起動する関数。~
基本的に第1引数は NULL にしておき、第2引数の文字列の1つ目...
理由は、第1引数に指定したコマンドは、フルパス指定かカレン...
-::ShellExecute()~
シェルにコマンドを実行させる関数。用途は実行ファイルの起...
関連付けられたアプリケーションでファイルを開くことも簡単...
***Win32APIやMFCのメンバ関数の戻り値 [#i3976e5f]
-BOOL型 (int型)
--エラーの詳細を知るためには、::GetLastError() を使用する...
--戻り値を TRUE(1)と比較してはいけない。条件が「真」であ...
-HRESULT型 (long型)
--成否の判定には、SUCCEEDED() / FAILED() マクロを用いる。~
(値の正負を判断しているだけ。つまり、HRESULT型は最上位ビ...
--戻り値からエラーの詳細を知ることができる。
--HRESULT型には、S_FALSE という、「エラーではないが失敗」...
***クリップボードの読み書き [#k28e4563]
-サンプルコード
--テキストの読み込み
#code(c){{
// char *pStr 読み込む文字列
// int nMaxCount 読み込む最大文字数
HGLOBAL hMem; // ヒープ上のメモリ領域
char *pMem; // ヒープ上のメモリ領域(文字列用)
// クリップボード内にテキストデータが存在するか
if(IsClipboardFormatAvailable(CF_TEXT)){
return;
}
// クリップボードのオープン
if(!::OpenClipboard(NULL)){
return;
}
// クリップボードから文字列を取得
if((hMem = (HGLOBAL)::GetClipboardData(CF_TEXT)) == N...
// クリップボードのクローズ
::CloseClipboard();
return;
}
// メモリをロック
pMem = (char *)::GlobalLock(hMem);
// 文字列をコピー
strncpy(pStr, pMem, nMaxCount);
pStr[nMaxCount] = '\0';
// メモリをロック解除
::GlobalUnlock(hMem);
// クリップボードのクローズ
::CloseClipboard();
}}
--テキストの書き込み
#code(c){{
// char *pStr 書き込む文字列
HGLOBAL hMem; // ヒープ上のメモリ領域
char *pMem; // ヒープ上のメモリ領域(文字列用)
// ヒープ上にメモリ領域を確保する
hMem = ::GlobalAlloc(GHND, strlen(pStr) + 1);
// メモリをロック
pMem = (char *)::GlobalLock(hMem);
// 文字列をヒープ上にコピー
strcpy(pMem, pStr);
// メモリをロック解除
::GlobalUnlock(hMem);
// クリップボードのオープン
if(::OpenClipboard(NULL)){
// クリップボードの中身を空にする
::EmptyClipboard();
// クリップボードへ文字列をコピー
::SetClipboardData(CF_TEXT, hMem);
// クリップボードのクローズ
::CloseClipboard();
// ※クリップボードへの書込みに成功したら、hMemは...
} else {
// メモリの解放
::GlobalFree(hMem);
}
}}
-クリップボードを閉じた後でのデータの変更~
クリップボードにはハンドル(グローバルな領域のアドレスを...
そのため、クリップボードを閉じた後であっても、データを変...
#code(c){{
// HBITMAP hBmpは、ビットマップデータのハンドル
// クリップボードを開く
if(::OpenClipboard(hWnd)){
// クリップボードをクリアして所有権を得る
if(::EmptyClipboard()){
// ビットマップをクリップボードに設定
::SetClipboardData(CF_BITMAP, hBmp);
}
// クリップボードを閉じる
::CloseClipboard();
}
// ここでhBmpの画像データを変更すると、クリップボードに...
}}
***アクセラレータ [#t171c798]
アプリケーションのショートカットキーを実現するアクセラレ...
+リソースにアクセラレータテーブルを追加する。(例:IDR_ACC...
+アクセラレータを関連付けるウィンドウ(ダイアログ)クラスの...
#code(c){{
BOOL CxxxxDlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: この位置に固有の処理を追加するか、または...
HACCEL hAccKey; // アクセラレータテーブルハ...
// アクセラレータテーブルハンドルを取得
hAccKey = ::LoadAccelerators(AfxGetInstanceHandle...
if (hAccKey != NULL){
// アクセラレータ処理
if (::TranslateAccelerator(this->m_hWnd, hAcc...
// アクセラレータとして処理された場合は、...
return TRUE;
}
}
return CDialog::PreTranslateMessage(pMsg);
}
}}
+アクセラレータテーブルにショートカットキーを登録する。(...
+クラスウィザードで、アクセラレータをウィンドウ(ダイアロ...
***タスクトレイ常駐 [#ga41bb66]
タスクトレイに常駐するアプリケーションの基本的な作成方法。
+リソースに、タスクトレイに表示するアイコンと、ポップアッ...
++アイコン~
アイコンを切り替える場合は、複数用意しておく。(例:IDR_M...
++ポップアップメニュー~
通常のメニューと同様に追加する。ポップアップ用メニューは...
+ポップアップメニューの項目のイベントハンドラを実装してお...
+ウィンドウ(ダイアログ)クラスのメンバ変数として以下を定義...
#code(c){{
NOTIFYICONDATA m_notifyIcon; // タスクトレイの...
}}
+タスクトレイのアイコンがクリックされた場合のユーザ定義メ...
#code(c){{
#define WM_USER_ACTION (WM_USER + 100)
}}
+アプリケーションの初期処理で、メインウィンドウを非表示し...
#code(c){{
// ウィンドウの表示を消す
ModifyStyleEx(WS_EX_APPWINDOW, WS_EX_TOOLWINDOW); ...
SetWindowPos(&wndTop, 0, 0, 0, 0, SWP_HIDEWINDOW); ...
// タスクトレイのアイコンデータを設定
memset(&m_notifyIcon, 0, sizeof(NOTIFYICONDATA));
m_notifyIcon.cbSize = sizeof(NOTIFYICONDATA); ...
m_notifyIcon.uID = 0; ...
m_notifyIcon.hWnd = m_hWnd; ...
m_notifyIcon.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TI...
m_notifyIcon.hIcon = AfxGetApp()->LoadIcon(IDR_MAINFR...
m_notifyIcon.uCallbackMessage = WM_USER_ACTION; ...
lstrcpy(m_notifyIcon.szTip, "MAINモード"); ...
// アイコンをタスクトレイに格納する
::Shell_NotifyIcon(NIM_ADD, &m_notifyIcon);
}}
+CWnd::WindowProc() 等のウィンドウプロシージャにユーザ定...
#code(c){{
POINT pntCur; // マウスカーソルの位置
CMenu mainMenu; // メインメニュー
CMenu *pPopupMenu; // ポップアップメニュー
// メッセージ処理
switch(message){
// タスクトレイアイコンのユーザ定義メッセージ
case WM_USER_ACTION:
// wParam : m_notifyIcon.uIDの値
// lParam : マウスメッセージ
// カーソルの現在位置を取得
::GetCursorPos(&pntCur);
// 左クリック
if(lParam == WM_LBUTTONDOWN){
// メニューのロード
mainMenu.LoadMenu(IDR_MENU_POPUP);
// ポップアップメニューのロード
pPopupMenu = mainMenu.GetSubMenu(0);
if(pPopupMenu != NULL){
// メニュー項目のグレーアウト、チェックマ...
// タスクトレイのポップアップメニュー表示...
SetForegroundWindow();
// ポップアップメニュー表示
pPopupMenu->TrackPopupMenu(TPM_LEFTALIGN ...
// タスクトレイのポップアップメニュー表示...
PostMessage(WM_NULL);
}
// 右クリック
} else if(lParam == WM_RBUTTONDOWN){
//////// 以降、バルーンチップ関連 (※VC++6.0では非...
// バルーンが表示されたとき
} else if(lParam == NIN_BALLOONSHOW){
// バルーンがタイムアウトで消えたとき
} else if(lParam == NIN_BALLOONTIMEOUT){
// バルーンが通知領域のクリックにより消えたとき
} else if(lParam == NIN_BALLOONUSERCLICK){
// バルーンが×ボタンクリックにより消えたとき
} else if(lParam == NIN_BALLOONHIDE){
}
break;
}
}}
+アプリケーションの終了処理で、タスクトレイからアイコンを...
#code(c){{
// タスクトレイのアイコンを削除
::Shell_NotifyIcon(NIM_DELETE, &m_notifyIcon);
}}
+タスクトレイのアイコンに対する処理の例。
#code(c){{
//////// バルーンチップの例 (※VC++6.0では非対応) ////...
m_notifyIcon.uFlags |= NIF_INFO; // バ...
m_notifyIcon.uTimeout = 3000; // 表...
m_notifyIcon.dwInfoFlags = 0L; // バ...
lstrcpy(m_notifyIcon.szInfoTitle, "タイトル"); // バ...
wsprintf(m_notifyIcon.szInfo, "メッセージ"); // バ...
// ※...
// バルーンチップ表示
::Shell_NotifyIcon(NIM_MODIFY, &m_notifyIcon);
//////// タスクトレイアイコンの状態変更の例 ////////
m_notifyIcon.hIcon = AfxGetApp()->LoadIcon(IDR_SUBICO...
lstrcpy(m_notifyIcon.szTip, "SUBモード"); ...
// 変更を反映
::Shell_NotifyIcon(NIM_MODIFY, &m_notifyIcon);
}}
-注意
::Shell_NotifyIcon()は、時間がかかりすぎるとタイムアウト...
その場合、タスクトレイにアイコンが表示されなくなるので注...
参考:http://support.microsoft.com/kb/418138/JA/
***プロセス間共有メモリ [#e8896b6a]
通常、異なるアプリケーション間では別々のメモリ空間が使用...
そこで、OS側に仮想的なメモリ空間を作成してもらい、そのメ...
アプリAが共有メモリの内容を変更すると、それをマッピングし...
変更が即時反映されるファイルを複数プロセスで同時にオープ...
+共有ファイル作成に使用する変数等の定義
#code(c){{
#define FMAP_KEY "TEST_FMAP" // 共有メモリの識別名
#define FMAP_SIZE (sizeof(char) * 100) // サイズ:100バイト
HANDLE hFileMap; // 共有メモリのハンドル
char *pData; // 共有メモリのマッピング先アドレス
}}
+共有ファイルの使用開始
#code(c){{
// 共有メモリの実体を作成する
// ※既に実体が作成されている場合はオープンとなる。
// 明示的にオープンする場合は::OpenFileMapping()を使用...
hFileMap = ::CreateFileMapping(INVALID_HANDLE_VALUE, 0, ...
// 共有メモリのビューをメモリ空間にマッピングする
pData = (char*)::MapViewOfFile(hFileMap, FILE_MAP_ALL_AC...
}}
+共有ファイルの使用終了
#code(c){{
// 共有メモリのビューのマッピングを終了
::UnmapViewOfFile(pData);
pData = NULL;
// 共有メモリのハンドルを閉じる
::CloseHandle(hFileMap);
hFileMap = NULL;
}}
***アプリケーションのアイコン設定 [#b9dd2934]
-エクスプローラ上で表示されるexeファイルのアイコン~
アプリケーションのリソースファイル(*.rc)内で定義されてい...
コンソールアプリケーションのアイコンを変更したい場合も、...
-ウィンドウ左上のアイコン~
コード中で明示的にアイコンを設定する必要がある。~
コンソールアプリケーションの場合は変更不可。
--''Win32API''~
::RegisterClassEx() に指定するウィンドウクラス(WNDCLASS)...
--''MFC''~
CWnd::SetIcon() を使用してアイコンを設定する。
***アプリケーションのバージョン情報の取得 [#zeaf5ee0]
対象の実行ファイルのパスから、バージョン情報を取得できる。
#code(c){{
// char szPath[] モジュールのパス
// バージョン情報リソースのサイズを取得
DWORD dwZero = 0;
DWORD dwVerInfoSize;
dwVerInfoSize = ::GetFileVersionInfoSize(szPath, &dwZero);
if(dwVerInfoSize == 0) {
return FALSE;
}
// バージョン情報リソースを取得
BYTE *pVerInfo;
pVerInfo = new BYTE[dwVerInfoSize];
if(pVerInfo == NULL){
return FALSE;
}
::GetFileVersionInfo(szPath, dwZero, dwVerInfoSize, pVer...
// 各バージョン情報を取得
void *pvVersion;
UINT VersionLen;
// 以下の形式で取得するバージョン情報を指定する
// 「\StringFileInfo\[①言語識別子&コードページ識別子(16...
// ①は、日本語の場合"041104b0"となる
// FileVersionを取得
CString strFileVersion;
::VerQueryValue(pVerInfo, "\\StringFileInfo\\041104b0\\F...
strFileVersion = (LPCTSTR)pvVersion;
delete[] pVerInfo;
return TRUE;
}}
***CreateProcess()を使用する場合のリダイレクトの方法 [#if...
外部コマンドを起動して標準出力をリダイレクトする方法。(t...
#code(c){{
// HANDLE hFile // リダイレクト先のハンドル(テキストファ...
BOOL bRet;
DWORD dwEndCode;
PROCESS_INFORMATION pi;
STARTUPINFO si;
// 起動情報
ZeroMemory(&si, sizeof (si));
si.cb = sizeof(si);
si.dwFlags |= STARTF_USESTDHANDLES; // hStdOutputの使用...
si.hStdOutput = (HANDLE)hTxtFile; // リダイレクト先に指...
// プロセス起動 (第5引数をTRUEにする)
bRet = ::CreateProcess(NULL, "test.exe", NULL, NULL, TRU...
if(bRet){
// プロセスの終了を待つ
::WaitForSingleObject(pi.hProcess, INFINITE);
// プロセスの終了コードを取得
::GetExitCodeProcess(pi.hProcess, &dwEndCode);
}
}}
※標準出力のリダイレクトを追記させる場合は、予めファイルを...
同様の手順で、標準入力や標準エラー出力もリダイレクト可能。~
***ファイルのアイコン表示(エクスプローラと同じ表示) [#l2b...
-アイコンを単体で取得する場合
#code(c){{
SHFILEINFO sfi
// 小さいアイコン(16x16)
HICON hIconSmall;
hIconSmall = ::SHGetFileInfo(ファイルパス, 0, &sfi, size...
// 大きいアイコン(32x32)
HICON hIconLarge;
hIconLarge = ::SHGetFileInfo(ファイルパス, 0, &sfi, size...
}}
-アイコンをイメージリストとして取得する場合(システムイメ...
#code(c){{
SHFILEINFO sfi
// 小さいアイコン(16x16)
HIMAGELIST hImgListSmall;
hImgListSmall = (HIMAGELIST)SHGetFileInfo((LPCSTR)"C:\\"...
// 大きいアイコン(32x32)
HIMAGELIST hImgListLarge;
hImgListLarge = (HIMAGELIST)SHGetFileInfo((LPCSTR)"C:\\"...
}}
#code(c){{
// アイコンを使用するときのインデックス
SHFILEINFO sfi
SHGetFileInfo(ファイルパス, 0, &sfi, sizeof(SHFILEINFO),...
// sfi.iIcon にイメージリストのインデックスが取得される
}}
リストビュー、ツリービュー、タブなどのコントロールにアイ...
あらかじめ、CListCtrl::SetImageList()、ListView_SetImageL...
※コントロールにシステムイメージリストを使用する場合は、ウ...
***TCPサーバーの通信切断検知 [#mc9fe05c]
TCP通信を行っている際、LANケーブルが抜けるなどで通信切断...
この動作は、Keep-Aliveパケットを投げて通信が復帰しないこ...
|パラメータ|説明|デフォルト値(Linux)|h
|TCP_KEEPIDLE|Keep-Aliveを投げ始めるまでの待機時間(秒)|72...
|TCP_KEEPINTVL|Keep-Aliveを投げる間隔(秒)|75|
|TCP_KEEPCNT|Keep-Aliveを投げる回数|9|
デフォルトだと、7200 + 75 * 9 = 7875秒 待機してしまうこと...
#code(c){{
// sock : ソケットオブジェクト
int option = 1; // trueの意味
setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &option, size...
// 5 + 1 * 5 = 10秒 で切断検知する例
option = 5;
setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &option, siz...
option = 1;
setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &option, si...
option = 5;
setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &option, size...
}}
参考:https://iww.hateblo.jp/entry/20081030/setsockopt
***同期処理/排他制御 [#da47c13b]
|>||セマフォ|ミューテックス|クリティカルセクション|h
|>|同時に所有できる数|上限を設定可能|1つまで|1つまで|
|>|使用可能な範囲|プロセスをまたいで使用可能|プロセスをま...
|Win32API|オブジェクトの作成|CreateSemaphore|CreateMutex|...
|~|所有権の取得|>|WaitForSingleObject に代表される待機関...
|~|所有権の破棄|ReleaseSemaphore|ReleaseMutex|LeaveCritic...
*C/C++ネイティブ [#u9b2e1bf]
**C/C++共通 [#ccfc5367]
***定義済みプリプロセッサマクロ [#a736dd8d]
|カテゴリ|マクロ名|意味|h
|ANSI C&br;(C90)|__STDC__|標準規格のC言語であることを示す...
|~|__FILE__|ソースファイルパス|
|~|__LINE__|ソースの行番号|
|~|__TIMESTAMP__|コンパイル日時|
|~|__DATE__|コンパイル日|
|~|__TIME__|コンパイル時刻|
|C99|__func__|関数名|
|C++|__cplusplus|C++であることを示す&br;値が1とは限らない|
|文字セット&br;(どちらか一方)|_MBCS|マルチバイト文字セッ...
|~|_UNICODE|ワイド文字(Unicode)セットであることを示す|
|ビルド構成&br;(どちらか一方)|_DEBUG|Debug版|
|~|NDEBUG|Release版|
***const修飾子の効力 [#g654f90b]
ある関数Aでconst修飾された引数を、さらに関数Bの非constな...
コンパイラの警告レベルによっては、警告は出力される。
***CALLBACK関数の定義 [#oaa2d339]
CALLBACK関数は、グローバル関数やstaticメンバ関数などの静...
その他、関数ポインタを使用する仕組みも同様。~
クラスのメンバ関数はインスタンスが生成されるまでアドレス...
***ワイルドカード(*, ?)を用いた文字列検索 [#i6ddb4a0]
参考:http://katsura-kotonoha.sakura.ne.jp/prog/c/tip00003...
#code(c){{
// ワイルドカードを使用した文字列検索
// ※BOOLはintで代用可
BOOL strmatch(const char *ptn, const char *str)
{
BOOL bmatch = FALSE;
switch(*ptn){
// パターン文字列の末尾
case '\0':
// 検索対象文字列も末尾なら真
bmatch = (*str == '\0');
break;
// * : 0文字以上の任意の文字列
case '*':
// '*'が0文字とマッチしたと仮定して検索を継続
if(!(bmatch = strmatch(ptn+1, str))){
// '*'が1文字以上にマッチしていると仮定して検索を継続
if(*str != '\0'){
bmatch = strmatch(ptn, str+1);
}
}
break;
// ? : 任意の1文字
case '?':
// 次の文字から検索を継続
if(*str != '\0'){
bmatch = strmatch(ptn+1, str+1);
}
break;
// その他の文字
default:
// 今回の文字が一致するなら
if(*ptn == *str){
// 次の文字から検索を継続
if(*str != '\0'){
bmatch = strmatch(ptn+1, str+1);
}
}
break;
}
return bmatch;
}
}}
***関数シグニチャのマングルについて [#g5c5cfeb]
C++では、関数のオーバーロードを実現するために、関数シグネ...
このシンボル名を作成することをマングルと呼ぶ。~
マングルの方法は、コンパイラによって異なる。~
VC++を使用する場合はマイクロソフトの規約にしたがってマン...
逆に、シンボルを関数名に戻すことをデマングルと呼ぶ。~
VC++の場合、Win32APIの::UnDecorateSymbolName()を使用する...
参考URL:~
http://kone.vis.ne.jp/diary/diaryb13.html#080315~
http://www.kegel.com/mangle.html~
http://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B_Nam...
***構造化例外のキャッチ [#hdd334cf]
例えば、メモリアクセス違反(アクセスバイオレーション)な...
C++のtry-catch構文でキャッチするためにはコンパイルオプシ...
ただし、発生する例外はCException型ではないことに注意。以...
#code(c){{
try{
// アクセスバイオレーション発生
} catch(...) {
printf("例外発生\n");
}
}}
Visual Studio を使用している場合は、MS独自仕様の __try-__...
これはC言語のソースでも可能で、コンパイルオプションも不要...
#code(c){{
#include <excpt.h>
:
__try{
// アクセスバイオレーション発生
} __except(EXCEPTION_EXECUTE_HANDLER) {
printf("例外発生\n");
}
}}
**C++ [#pda30790]
***static関数/変数 [#lc012adb]
-staticなメンバ変数
~作成されるすべてのオブジェクト、派生クラスのオブジェクト...
-メンバ関数内のstaticなローカル変数
~staticなメンバ変数と同じ。(スコープはその関数内のみとい...
-staticなメンバ関数
~クラスのインスタンス生成無しで関数を呼び出せる。
#code(c){{
// 例
CSampleClass::sampleStaticMethod();
}}
***CPPファイルからCファイルに定義された関数を呼び出す [#x...
関数のシグネチャがCとCPPで異なるため、単純なextern宣言で...
#code(c){{
// グローバル関数 or グローバル変数
extern "C" ~~
// 複数のグローバル関数
extern "C"{
~~
~~
}
}}
***メンバ初期化子(:) [#hb253078]
クラスのメンバ変数を初期化する際、コンストラクタで初期値...
厳密に初期化を行う場合は、メンバ初期化子「:」を用いる。コ...
-コンストラクタでの「代入」
#code(c){{
class CChild
{
private:
int m_count;
int m_num;
// コンストラクタ
CChild()
{
// 代入
m_count = 0;
m_num = 100;
}
}
}}
-メンバ初期化子による「初期化」
#code(c){{
class CChild
{
private:
int m_count;
int m_num;
// コンストラクタ
CChild() : m_count(0), m_num(100)
{
}
}
}}
また、メンバ初期化子を用いることで基底クラスの初期化(と...
#code(c){{
class CChild : public CParent
{
private:
// コンストラクタ
CChild() : CParent(1) // メンバ初期化子による基...
{
}
}
}}
※メンバ初期化子で複数のメンバを初期化する際に実行される順...
***実行時型情報(RTTI) [#z042e38a]
typeid演算子によって、オブジェクトが何のクラスのインスタ...
使用するには、プロジェクトの設定で「ランタイムタイプ情報(...
***メンバアクセス演算子でprivateメンバにアクセス [#pba36e...
自身のクラス型のオブジェクトのprivateメンバは、たとえイン...
例)
#code(c, menu){{
class CSample
{
private:
int num;
void Test0()
{
printf("Test\n");
}
public:
void Test1(CSample &obj)
{
printf("%d\n", obj.num); // OK
}
void Test2(CSample *pObj)
{
pObj->Test0(); // OK
}
};
}}
*コーディングの慣例 [#k28c86ea]
**MFC派生クラスのヘッダファイル [#ye4679d4]
VC6で生成されるMFC派生クラスのヘッダファイルの例
#code(c){{{
// MFC派生クラス
class CSample : public CBase
{
DECLARE_DYNAMIC(CSample) // ①
// コンストラクション
public:
// ②
// アトリビュート
public:
// ③
// オペレーション
public:
// ④
// オーバーライド
// ClassWizard は仮想関数のオーバーライドを生成します。
//{{AFX_VIRTUAL(CAbc)
// ⑤
//}}AFX_VIRTUAL
// インプリメンテーション
public:
// ⑥
protected:
// ⑦
//{{AFX_MSG(CAbc)
// ⑧
//}}AFX_MSG
private:
// ⑨
};
}}}
''説明''~
||概要|説明|追加|h
|①|CObjectクラスの&br;機能の使用宣言 |全てのMFCクラスの...
|②|コンストラクション |コンストラクタやCWnd::Create(...
|③|アトリビュート |そのクラスの属性(プロパティ)を制...
|④|オペレーション |そのクラスのオブジェクトに対して...
|⑤|オーバーライド |MFC基底クラスの仮想関数のオーバ...
|⑥|インプリメンテーション&br;(公開メンバ) |そのクラスの...
|⑦|インプリメンテーション&br;(被保護メンバ) |そのクラスの...
|⑧|Window&br;メッセージハンドラ |Windowメッセージハン...
|⑨|インプリメンテーション&br;(非公開メンバ) |そのクラスの...
ページ名: