目次
/MT …… 静的リンク /MD …… 動的リンク /MTd …… 静的リンク (デバッグ版) /MDd …… 動的リンク (デバッグ版)
// undoPoint_ = -1; CCommand* pCommand = new CNoCommand(); addCommandHistory(pCommand);
// コマンド履歴追加 void CPictureDrawView::addCommandHistory(CCommand* pCommand) { // undo中なら、以降のコマンド履歴は必要なし while (m_pPimpl->undoPoint_ < (int)m_pPimpl->commandHistory_.size()-1) { delete m_pPimpl->commandHistory_[(int)m_pPimpl->commandHistory_.size()-1]; m_pPimpl->commandHistory_[(int)m_pPimpl->commandHistory_.size()-1] = 0; m_pPimpl->commandHistory_.pop_back(); } m_pPimpl->commandHistory_.push_back(pCommand); m_pPimpl->undoPoint_++; }
// リドゥ void onRedo() { if (m_pPimpl->undoPoint_ < (int)m_pPimpl->commandHistory_.size()-1) { m_pPimpl->undoPoint_++; m_pPimpl->commandHistory_[m_pPimpl->undoPoint_]->redo(); } }
// アンドゥ void onUndo() { if (m_pPimpl->undoPoint_ > 0) { m_pPimpl->commandHistory_[m_pPimpl->undoPoint_]->undo(); m_pPimpl->undoPoint_--; } }
ヘッダファイルの重複を防ぐディレクティブ
#include <direct.h> #include <errno.h> int iRet = _mkdir(mailPath.c_str()); // 成功なら 0、失敗なら-1 // errno == EEXISTなら既にフォルダが存在、errno == ENOENTならパスがおかしい
または派生クラスのメンバなどのCWinThreadオブジェクトのメンバデータを初期化する場合に使用。 初期化完了後にスレッドを実行するには、CWinThread::ResumeThreadを使用。 これを使用するまでスレッドは実行されない -0: 作成直後にスレッドを開始
// スレッドの作成と開始 m_pThread = ::AfxBeginThread(WatchFile, (LPVOID)this, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED, NULL); // WatchFileはスレッド関数 m_pThread->m_bAutoDelete = FALSE; m_pThread->ResumeThread();
// スレッド関数 UINT FootView::WatchFile(LPVOID pParam) { FootView* pFootView = (FootView*)pParam; int UpdateTime = 100; while (1) { pFootView->readFileLines(false); // ただの処理 // シグナル状態になるかタイムアウトになるまで待つ DWORD ret = ::WaitForSingleObject(pFootView->m_hEventStop, UpdateTime); switch (ret) { case WAIT_OBJECT_0: // シグナル状態 return 0; break; case WAIT_TIMEOUT: // タイムアウト break; case WAIT_FAILED: case WAIT_ABANDONED: default: break; } } return 0; }
sprintfのc++版
typdef boost::basic_format<TCHAR> TFormat #include <iostream> #include <boost/format.hpp> using namespace std; using namespace boost; using namespace boost::io; try { // printf的な使い方 cout << format("%d") % 10; // 文字列として取り出し string s; s = str(format ("数字 : %d 、文字 : %s") % 30 % "あああ"); } // Too much arguments catch (boost::io::too_many_args& ex) { cerr << ex.what() << endl; } // Too few arguments catch (boost::io::too_few_args& ex) { cerr << ex.what() << endl; }
#include <string> #include <boost/lexical_cast.hpp> try { TString str; int number = lexical_cast<int>(str); str = lexical_cast<TString>(number); } catch(boost::bad_lexical_cast & ex) { ::AfxMessageBox(_T("失敗")); }
#include <boost/share_ptr.hpp> // ppatを何度コピーしようとも、ppatが参照されなくなるまでdeleteされない typedef boost::shared_ptr<pattern> pattern_type pattern_type ppat = pattern_type(new pattern(...)); // 生のポインタ pattern* pat = ppat.get(); // 生成時はnull pattern_type pnull; // ローカル変数に使用すると、ブロック終了後にdeleteされるので注意 // 指す先を変更するには、 shared_ptr<Foo> p(new Foo(0)); p.reset(new Foo(1)); // このとき Foo(0)のデストラクタが走る
#include <boost/tokenizer.hpp> std::string str typedef boost::tokenizer<boost::char_separator<char>> tokenizer; boost::char_separator<char> sep("/"); tokenizer token(str, sep ); for (tokenizer::iterator it=token.begin(); it!=token.end(); ++it) { }
#include "boost/date_time/gregorian/gregorian.hpp" using namespace boost::gregorian; date d( Year, Month, Day ); // N日後 date d2 = d + date_duration(N); d.year() // 年 d.month() // 月 d.day() // 日 d.day_of_week() // 曜日 d.is_not_a_date() // 日付が存在しないならtrueを返す
// 初期化 BSTR var(::SysAllocString(L"")); // CString -> BSTR CString src(""); BSTR var(src.AllocSysString()); // BSTR ->CString BSTR var; CString src = CString(var); // 比較 strcmp(va1, var2)==0
Create (LPCTSTR lpszCaption, // ボタンコントロールのテキスト DWORD dwStyle, // ボタンコントロールのスタイル const RECT& rect, // ボタンコントロールのサイズと位置 CWnd* pParentWnd, // ボタンコンロールの親ウィンドウ。通常はCDialog UINT nID // ボタンコントロールのリソースID
CButton* pButton = new CButton(); pButton->Create(NULL, WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, CRect(0, 0, 0, 0), this, ID);
CClientDC dc(pWnd)
COLORREF Col; CColorDialog ColorDlg(RGB(0,0,0), 0x10, NULL); if (ColorDlg.DoModal() == IDOK) { Col = ColorDlg.GetColor(); int r, g, b; //r=Col&0xff;//赤情報取り出し r = GetRValue(col); //g=(Col>>8)&0xff;//緑情報取り出し g = GetGValue(col); //b=(Col>>16)&0xff;//青情報取り出し b = GetBValue(col); m_ForwardColor.Format("RGB(%d, %d, %d)", r, g, b);//CString文字列に変換 }
CComboBox m_MonthCtrl; TString Item = _T("項目"); m_MonthCtrl.AddString(Item.c_str()); // 項目の追加
// 日時のセット CDateTimeCtrl* pDate = (CDateTimeCtrl*)GetDlgItem(IDC_DATE); ASSERT(pDate); CTime tm(2007, 6, 6, 1, 2, 3); // 2007/06/06 01:02:03 pDate->SetTime(&tm);
// ダイアログの呼出 CMyDlg dlg(this); dlg.DoModal(); // モーダルダイアログボックスの起動。OKなどが押されるまで親の操作は不可
// 初期化処理 BOOL OnInitDialog() { // クラスビューから該当クラスを探し、そのプロパティのオーバーライドから作成 if (!__super::OnInitDialog()) { FALSE } }
// ダイアログの貼り付け CRect rect; GetClientRect(&rect); CDialog* pDialog = new CDialog(); pDialog->Create(IDD_DIGEST_DIALOG, this); pDialog->MoveWindow(rect.left, rect.top, rect.right, rect.bottom); pDialog->ShowWindow(SW_SHOW);
// ダイアログの終了 EndDialog(IDOK);
// サイズ変更 リソースの設定で、「ダイアログ枠」から「サイズ変更枠」に変更する
改行位置には\r\nが必要
LONG pointSize = -MulDiv(Font.Size, GetDeviceCaps(GetDC()->GetSafeHdc(), LOGPIXELSY), 72); CFontDialog dlg; dlg.m_cf.Flags |= CF_NOSCRIPTSEL | CF_INITTOLOGFONTSTRUCT; dlg.m_cf.Flags &= ~CF_EFFECTS | CF_USESTYLE; strcpy_s(dlg.m_cf.lpLogFont->lfFaceName, Font.Name); if (Font.Style.Compare(_T("標準"))==0) dlg.m_cf.lpLogFont->lfWeight = FW_NORMAL; else if (Font.Style.Compare(_T("斜体"))==0) dlg.m_cf.lpLogFont->lfItalic = true; if (Font.Style.Compare(_T("太字"))==0) dlg.m_cf.lpLogFont->lfWeight = FW_BOLD; if (Font.Style.Compare(_T("太字 斜体"))==0) { dlg.m_cf.lpLogFont->lfWeight = FW_BOLD; dlg.m_cf.lpLogFont->lfItalic = true; } dlg.m_cf.lpLogFont->lfHeight = pointSize; if (dlg.DoModal() == IDOK) { Font.Name = dlg.GetFaceName(); bool IsBold = dlg.IsBold(); bool IsItalic = dlg.IsItalic(); if (IsBold) { if (IsItalic) Font.Style = "太字 斜体"; else Font.Style = "太字"; } else if (IsItalic) Font.Style = "斜体"; else Font.Style = "標準"; Font.Size = dlg.GetSize() / 10; }
複数選択させないためには、Single Selectionをtrueに。
//選択されている項目のindexを取得 index=-1; while ((index = GetNextItem(index, LVNI_ALL|LVNI_SELECTED))!=-1) // 選択されている項目のindexのとき
// 1行選択モード&グリッドにするには以下の記述が必要 CListCtrl* pList = (CListCtrl*)GetDlgItem(IDC_LOGINFO_LIST); ASSERT(pList); DWORD dRet = pList->SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
// 見出しの追加 CListCtrl* pList = (CListCtrl*)GetDlgItem(IDC_LIST_KEYWORD); ASSERT(pList); int iRet(-1); if (pList->GetSafeHwnd()) { iRet = pList->InsertColumn( 0, "キーワード", LVCFMT_LEFT, 125, -1); ASSERT(iRet!=-1); iRet = pList->InsertColumn( 1, "前景色", LVCFMT_LEFT, 125, -1); ASSERT(iRet!=-1); iRet = pList->InsertColumn( 2, "背景色", LVCFMT_LEFT, 125, -1); ASSERT(iRet!=-1); }
// 項目の追加 // No Column Headerをtrueにしている場合も、項目を追加する必要あり! CListCtrl* pList = (CListCtrl*)GetDlgItem(IDC_LIST_KEYWORD); ASSERT(pList); bool bRet(false); for (int i=0; i<(int)SettingList.size(); ++i) { int nItem = m_KeywordList.InsertItem( i, SettingList[i].Keyword, 0); bRet = pList->SetItem( nItem, 1, LVIF_TEXT, SettingList[i].ForwardColor, 0, 0, 0, 0); ASSERT(bRet); bRet = pList->SetItem( nItem, 2, LVIF_TEXT, SettingList[i].BackColor, 0, 0, 0, 0); // チェックをつける bRet = pList->SetCheck(nItem, SettingList[i].Check); ASSERT(bRet); }
// チェックボックスのチェック void ColorSettingDlg::OnLvnItemchangedListKeyword(NMHDR *pNMHDR, LRESULT *pResult) { LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR); // TODO: ここにコントロール通知ハンドラ コードを追加します。 UINT newimage; if ((newimage = pNMLV->uNewState & LVIS_STATEIMAGEMASK) !=(pNMLV->uOldState & LVIS_STATEIMAGEMASK)) { if (newimage == INDEXTOSTATEIMAGEMASK(2)) { // チェックが押された } else if (newimage == INDEXTOSTATEIMAGEMASK(1)) { // チェックが外された } } *pResult = 0; }
// 表示内容の取得 CString GetItemText(int nItem, int nSubItem)
// 選択アイテムの取得(単一選択) void CModifyDialog::OnLvnItemchangedList(NMHDR *pNMHDR, LRESULT *pResult) { LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR); // TODO: ここにコントロール通知ハンドラ コードを追加します。 UINT NewState = pNMLV->uNewState; if (NewState==3) { // 選択された! int nItem = pNMLV->iItem; UINT state = m_DrLst.GetItemState( nItem, LVIS_SELECTED ); if( state == LVIS_SELECTED ) { UINT index = m_DrLst.GetSelectedColumn(); m_ID = m_DrLst.GetItemText(index, 0); m_Name = m_DrLst.GetItemText(index, 1); m_Weekday = m_DrLst.GetItemText(index, 2); m_Max = m_DrLst.GetItemText(index, 3); UpdateData(false); } } }
戻り値: BOOL
オープンしているカーネルオブジェクトのハンドルをクローズ。オブジェクトのハンドルの参照カウンタを1つ減らす。参照カウンタが0になった時点で、そのオブジェクトはメモリから開放される
COLORREF Col; Col = ColorDlg.GetColor(); int r, g, b; r = Col&0xff; g = (Col>>8)0xff; b = (Col>>16)0xff; Format("%d, %d, %d", r, g, b);
CPaintオブジェクトを構築し、塗りつぶす対象となるアプリケーションウィンドウを用意
CPaintDC dc(pWnd)
引数: lpEventAttributes: セキュリティ記述子 bManualReset: FALSEにすると、WaitForSingleObjectが制御を戻したとき、自動的に非シグナル状態に bInitialState: 初期状態 TRUE:シグナル状態 FALSE:非シグナル状態 lpName: オブジェクトの名前
HANDLE m_hEventStop = ::CreateEvent(NULL, TRUE, FALSE, NULL);
//各辺を中心から外側に向かって移動させることで CRect を拡大 InflateRect(int x, int y) InflateRect(int l, int t, int r, int b) // Rectをコピー CopyRect(CRect rect) // 戻り値のメンバである cx と cy が CRect の高さと幅を持つ Size() //四角形がフォーカスを持つことを示すために使われるスタイルで四角形を描画 DrawFocusRect(LPCRECT lpRect); //lpRect で指定された四角形の周囲に境界線を描く FrameRect(LPCRECT lpRect, CBrush* pBrush)
ユーザがテキストを入力し編集できるウィンドウ
ReplaceSel: オブジェクト内の現在の選択を指定されたテキストに置き換え
CHARFORMAT2 cf; TString FontName; ::memset(&cf, 0, sizeof(CHARFORMAT2)); cf.cbSize = sizeof(CHARFORMAT2); cf.cbSize = sizeof(cf); cf.dwMask = CFM_COLOR | CFM_BACKCOLOR | CFM_ITALIC | CFMBOLD | CFM_SIZE | CFM_FACE | CFM_SPACING; ::_tcscpy_s(cf.szFaceName, LF_FACESIZE, FontName); cf.sSpacing = 0; cf.dwEffects = CFE_ITALIC | CME_BOLD | UNDERLOINE | STRIKEOUT; cf.yHeight = 300; cf.crTextColor = RGB(255, 0, 0); cf.crBackColor = RGB(0, 255, 0);
// ダブルクリックで単語選択 // 自動垂直スクロール // 常に選択状態 // 読取専用 editCtrl.SetOptions(ECOOP_SET, ECO_AUTOWORDSELECTION | ECO_AUTOVSCROLL | ECO_NOHIDESEL | ECO_READONLY);
// 右端で折り返す SendMessage(EM_SETTARGETDEVICE, NULL, 0); // 右端で折り返さない SendMessage(EM_SETTARGETDEVICE, NULL, 1);
CSpinButtonCtrl m_YearCtrl; CEdit* pYear= (CEdit*)GetDlgItem(IDC_EDIT_YEAR2); ASSERT(pYear); m_YearCtrl.SetBuddy(pYear); // pYearと対に m_YearCtrl.SetRange(0, 9999);
void CCalendarDlg::OnDeltaposSpinYear(NMHDR *pNMHDR, LRESULT *pResult) { LPNMUPDOWN pNMUpDown = reinterpret_cast<LPNMUPDOWN>(pNMHDR); // TODO: ここにコントロール通知ハンドラ コードを追加します。 if (pNMUpDown->iDelta > 0) { // 上が押された } else { // 下が押された } *pResult = 0; }
|modeCreate|ファイルがない場合には作成し、そんざいする場合には内容長を0にする| |modeNoTruncate|modeCretateとともに使用し、存在する場合には内容はそのままで開く| |modeRead|読み込み専用として開く| |modeReadWrite|読み込み/書き込み両用で開く| |modeWrite|書き込み専用として開く| |modeNoInherit|子プロセスにファイルを継承しない| |shareDenyNone|読み込み/書き込みとも他のプロセスと共有する| |shareDenyRead|書き込みのみ他のプロセスと共有する| |shareDenyWrite|読み込みのみ他のプロセスと共有する| |shareExclusive|他のプロセスとファイルを共有しない|
|CFile::begin|ファイルの最初| |CFile::current|現在位置| |CFile::end|ファイルの終わり|
戻り値: bool
x1: 楕円に外接する四角形の、左上隅の論理 x 座標。 y1: 楕円に外接する四角形の、左上隅の論理 y 座標。 x2: 楕円に外接する四角形の、右下隅の論理 x 座標。 y2: 楕円に外接する四角形の、右下隅の論理 x 座標。
メニューの項目を無効に
ウィンドウのマウス入力とキーボードを有効/無効にする
// ウィンドウの点滅を行う // 成功するとtrue、失敗するとfalseを返す BOOL FlashWindow(HWND hWnd, BOOL bInvert); // binvert: ウィンドウ(のタイトルバー)を反転させるのか(true)、正常な状態に戻するのか(false)を指定。
戻り値: BOOL
クライアント領域の座標を取得する
戻り値: BOOL
ウィンドウの境界線の寸法を取得する
ウィンドウズにメッセージをポスト。現在実行中のハンドラや先にポストされていたメッセージに対応するハンドラの実行終了を待つ。WM_PAINTメッセージは関数を抜けてから
CRect myRect; myRect.SetRect(0, 0, 200, 200); InvalidateRect(&myRect); myRectだけ再描画
std::map<int, char> var; // keyを整数型,valueを文字型とする連想配列を作成 var.insert(std::make_pair(3, 'a')); // keyが3,valueが'a'の要素を追加
std::map<int, char>::iterator i = var.find(4); // iはkeyが4の要素を指す反復子 std::map<int, char>::iterator j = var.end(); // jはvarの終端を指す反復子 if (i==j) { // 要素が見つからなかった場合,findの返り値は終端を指す反復子になります。 // 見つからなかった… } else { // 見つかった!!!! int key = i->first; // 当然keyの値は4 char value = i->second; // valueは'c' // ちなみに i->first = 10; // NG!!!! keyは書き換えられない。 i->second = 'x'; // OK!!!! valueは書き換えられる。 }
// 設定されたサウンドを鳴らす。ビープ音の発生に成功するとtrue、失敗するとfalse BOOL MessageBeep(UINT soundType)
MB_OK | 一般の警告音 |
MB_ICONHAND | システムエラー |
MB_ICONEXCLAMATION | メッセージ(警告) |
MB_ICONQUESTION | メッセージ(問合せ) |
MB_ICONASTERISK | メッセージ(情報) |
0xFFFFFFFF | 単純なビープ音 |
typedef std::ofstream TOFStream;
#include <fstream> int main() { std::ofstream ofs( "test.txt", ios::out | ios::app); ofs << "testmessage" << 123 << std::endl; return 0; } // ファイルはデストラクタによって自動的に閉じられる
フラグ | 説明 |
out | 書き込み専用に開く。デフォルト。 |
app | 追記用に開く。 |
ate | ファイルを開くと、自動的に末尾に移動する。 |
trunc | ファイルを開くと、以前の内容を全て削除する。 |
binary | 特殊な文字を置換しない。 |
id1: 連続するコマンドIDの先頭コマンドID id2: 連続するコマンドIDの末尾コマンドID memberFxn: コマンドが割り当てられるメッセージハンドラ関数 このマクロを使って連続する範囲のコマンドIDを1つのメッセージハンドラ関数に割り当てる。 OnmemberFxn(UINT nID): nIDを使える
// ヘッダに afx_msg void OnCalDay(UINT id); // メッセージマップに ON_COMMAND_RANGE(id1, id2, OnCalDay) // 本体 void OnCalDay(UINT id) { // idを使って処理 }
HBRUSH CCalendarDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); if (pWnd->GetSafeHwnd() == m_CalLastMonth.GetButton(i)->GetSafeHwnd()) pDC->SetTextColor(RGB(255, 0, 0)); switch (pWnd->GetDlgCtrlID()) { case IDC_STATIC_SUN: break; default: break; }
// TODO: 既定値を使用したくない場合は別のブラシを返します。 return hbr; }
Exceptional C++ 4章
struct Pimpl; Pimpl* m_pPimpl;
C++ Coding Standards 22
BOOL DigestInfoView::PreTranslateMessage(MSG* pMsg) { if (WM_LBUTTONDBLCLK == pMsg->message) { m_pCmdTarget->SendMessage(WndMsg::WM_DIGEST_DOUBLE_CLICK, reinterpret_cast<WPARAM>(&m_carteID)); // メッセージの処理をさせたくなければtrueを返す return TRUE; } return CHtmlView::PreTranslateMessage(pMsg); }
CButton* pRadio = (CButton*)GetDlgItem(IDC_RADIO_3MONTH); ASSERT(pRadio); pRadio->SetCheck(1); // ボタンチェック
戻り値: bool
x1: 四角形の左上隅の x 座標を指定します (論理単位)。 y1: 四角形の左上隅の y 座標を指定します (論理単位)。 x2: 四角形の右下隅の x 座標を指定します (論理単位)。 y2: 四角形の右下隅の y 座標を指定します (論理単位)。
reinterpret_cast<変換後><変換前>
戻り値: BOOL
オブジェクトを非シグナル状態に
戻り値: BOOL
スクリーン座標をクライアント座標に変換する
ウィンドウにメッセージを送信する。
この関数は、指定したウィンドウのウィンドウプロシージャが処理を終了するまで制御を返さない
引数: HWND hWnd, // ウィンドウハンドル UINT Msg, // メッセージコード WPARAM wParam, // wParamパラメータ LPARAM lParam // lParamパラメータ
// 呼出側 // 変数宣言 CWnd* m_pCmdTarget; // 関数宣言 void SetCmdTarget(CWnd* pWnd) { m_pCmdTarget = pWnd; } // ウィンドウメッセージWM_CAL_SELECTを送る TString Date = _T("2006/01/01"); m_pCmdTarget->SendMessage(WndMsg::WM_CAL_SELECT, reinterpret_cast<WPARAM>(&Date));
// 受取側 // ヘッダに afx_msg LRESULT onCalSelect(WPARAM wParam, LPARAM lParam); // メッセージマップに ON_MESSAGE(WndMsg::WM_CAL_SELECT, &GairaiViewHeader::onCalSelect) // ユーザー定義メッセージは、通常、WM_USER から 0x7FFF までの範囲で定義 // どこかで 呼出側ポインタ->SetCmdTarget(this); // 本体 LRESULT GairaiViewHeader::onCalSelect(WPARAM wParam, LPARAM /* lParam */) { TString* Date = reinterpret_cast<TString*>(wParam); // 2006/01/01が抜き出せる return 0; }
戻り値: BOOL
オブジェクトをシグナル状態に
スレッドの終了処理
bool bRet = ::SetEvent(m_hEventStop); if (!bbRet) { ::AfxMessageBox(_T("終了イベントのセットに失敗しました")); return; }
if (m_pThread != NULL) { // スレッド実行中 // スレッドの終了を待つ ::WaitForSingleObject(m_pThread->m_hThread, INFINITE); // スレッドオブジェクト破棄 delete m_pThread; m_pThread = 0; }
// 終了イベントクリア bool bRet = ::ResetEvent(m_hEventStop); if (!bRet) { ::AfxMessageBox(_T("終了イベントのクリアに失敗しました")); return; }
std::vector<int> a;
// テンポラリファイル用のファイル名を取得する。 // テンポラリファイルを作成し、そのファイルへのファイルポインタを返す。 // 作成に失敗した場合には、NULLが返される。 CStdioFile *myFile = new CStdioFile(fp);
// テンポラリファイル用のファイル名を取得する。 //ファイル名は最大TMP_MAX個まで取得可能で、ファイル名の長さは最大L_tmpnamバイトになる。 // ファイル名の取得に失敗するとNULLを返す char *tmpnam(char *string)
char tmpfilename[L_tmpnam]; if (tmpnam(tmpfilename)==NULL) { // エラー処理 } try { CFile aFile(_T(tmpfilename), CFile::modeCreate|CFile::modeWrite|CFile::shareExclusive); } catch (CFileException *e) { e->Delete(); }
typedef std::basic_string<TCHAR> TString
CString c; TString t; t = (LPCTSTR)c; // CSTring -> TString c = t.c_str(); // TString -> CString
#include <boost/format.hpp> #include <boost/lexical_cast.hpp> // TString から Int を得る int GetIntFromTString(TString src) { int dst; try { dst = lexical_cast<int>(src); } catch(boost::bad_lexical_cast & ex) { ::AfxMessageBox(_T("失敗")); const TString msg = io::str(TFormat(Msg::ERR_LEXICAL_CAST_FAILURE) % ex.what()); theApp.getLogger()->writeLog(LogType::LT_ERROR, msg); return -1; } return dst; }
// int から TString を得る TString GetTStringFromInt(int src) { TString dst; try { dst = lexical_cast<TString>(src); } catch(boost::bad_lexical_cast & ex) { ::AfxMessageBox(_T("失敗")); const TString msg = io::str(TFormat(Msg::ERR_LEXICAL_CAST_FAILURE) % ex.what()); theApp.getLogger()->writeLog(LogType::LT_ERROR, msg); return _T(""); } return dst; }
// \ を \\ に変換 TString filePath = "c:\temp\" TString result = _T(""); TString searchString = _T("\\"); string::size_type findPos = 0; string::size_type searchPos = 0; while (findPos != string::npos) { findPos = filePath.find(searchString, searchPos); if (findPos != string::npos) { result += filePath.substr(searchPos, findPos-searchPos) + "\\\\"; searchPos = findPos + searchString.length(); } } findPos = filePath.find_last_of(searchString); TString file = result + filePath.substr(findPos+searchString.length()); // file = "c:\\temp\\"
デバッグ出力に表示、デバッグモードでのみ実行される。
Dialogの値をそのメンバ関数に取り込む時 -> 引数をtrueにする
メンバ変数の値をそのDialogに返す時 -> 引数をfalseにする
ドキュメントの変更をビューに通知する
pSender: ドキュメントを変更したビューへのポインタ。すべてのビューを更新する場合は、NULL を指定します。 lHint: 変更に関する情報を指定します。 pHint: 変更に関する情報が格納されているオブジェクトへのポインタ。
親ウィンドウを移動してもOnMove、OnMovingなどは呼ばれない。処理させたいときはMainfrmなどから呼ぶ。
C++では値渡しが基本。参照渡しにしたい場合は、
void swap(int& x, int& y) { int tmp = x; int x = y; int x = tmp; }
アプリケーションのキーをバイパスして、直接WM_PAINTメッセージを送る
CView *MyView = (CView *)RUNTIME_CLASS(CCanvas)->CreateObject(); MyView->Create(NULL, NULL, WS_CHILD|WS_VISIBLE, rect, this, IDC_CANVAS_VIEW);
hHANDLE: オヴジェクトのハンドル dwMilliseconds: タイムアウト時間
指定されたカーネルオブジェクトがシグナル状態になるか、指定された時間が経過するまでスレッドをスリープ。 0を指定するとオブジェクトがシグナル状態かどうかを調べてすぐに制御を返す。 INFINITEを指定すると、オブジェクトがシグナル状態になるまで待ち続ける
WAIT_OBJECT_0: オブジェクトがシグナル状態 WAIT_TIMEOUT: タイムアウト時間が経過
スレッドが終了する = シグナル状態になる
nCount: スレッドの個数 lpHandles: スレッドのハンドルを配列で fWaitAll: true(すべてのスレッドがシグナル状態)、 false(どれか1つのスレッドがシグナル状態) dwMilliseconds: タイムアウト時間 WAIT_OBJECT_ + 0: スレッド0がシグナル状態
特定のビットを反転するのに用いる
char fullpath[_MAX_PATH], drive[_MAX_DRIVE], dir[_MAX_PATH], fname[_MAX_FNAME], ext[_MAX_EXT]; //起動パスの取得 GetModuleFileName(NULL, fullpath, sizeof(fullpath)); _splitpath(fullpath, drive, dir, fname, ext);
// InitInstanceで free((void*)m_pszAppName); m_pszAppName=_tcsdup(_T("読影医別依頼状況表示ツール"));
「マウスが押された」、「ウィンドウサイズが変更された」などウィンドウに関連するイベントはウィンドウメッセージによって通知される。
CDC m_MemDC; CBitmap* m_pOldBitmap; CBitmap* m_pBitmap; // デストラクタでの処理を忘れずに!
void CFamilyHistoryView::OnInitialUpdate() { CDC *pDC;//通常のデバイスコンテキストを格納するポインタ CRect cClient;//クライアント領域 CBrush cBrush;//ブラシ CBrush *pOldBrush;//ブラシのストック変数 // ビットマップオブジェクトの動的確保 m_pBitmap = new CBitmap(); // クライアント領域の取得 GetClientRect(&cClient); // 現在のDCのポインタを取得 pDC=GetDC(); // 通常のDCとメモリDCに互換性をつける m_MemDC.CreateCompatibleDC(pDC); // 通常のDCの互換性のあるビットマップをメモリ上に作成 m_pBitmap->CreateCompatibleBitmap(pDC,cClient.Width(),cClient.Height()); //ビットマップとメモリDCの関連付け m_pOldBitmap = m_MemDC.SelectObject(m_pBitmap); //白のBrushを作成 cBrush.CreateSolidBrush(RGB(255,255,255)); //現在のbrushのポインタをpOldBrushとして残しておく pOldBrush=m_MemDC.SelectObject(&cBrush); // クライアント領域でbitmapをコピー m_MemDC.PatBlt(0,0,cClient.Width(),cClient.Height(),PATCOPY); //昔のBrushに戻す m_MemDC.SelectObject(pOldBrush); //DCを解放 ReleaseDC(pDC); }
void CFamilyHistoryView::OnDraw(CDC* pDC) { CFamilyHistoryDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; // ここに図形描画 CRect rect; GetClientRect(&rect); pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &m_MemDC, 0, 0, SRCCOPY); }
void CFamilyHistoryView::OnDestroy() { // TODO: ここにメッセージ ハンドラ コードを追加します。 // ストックしておいたビットマップを割り当てる m_MemDC.SelectObject(m_pOldBitmap); // ビットマップオブジェクトを削除する m_pBitmap->DeleteObject(); // メモリデバイスコンテキストの削除 m_MemDC.DeleteDC(); // 正規のOnDestroyを実行する CView::OnDestroy(); }
void CFamilyHistoryView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy);
// TODO: ここにメッセージ ハンドラ コードを追加します。 // OnInitialUpdate()でやってる処理と同じ ViewBackgroundScreen();
// 表示されてたものをすべて表示 AllView(); CRect rect; GetClientRect(rect); m_MemDC.BitBlt(0, 0, rect.Width(), rect.Height(), &m_MemDC, 0, 0, SRCCOPY); }
参考:http://www.geocities.jp/chiakifujimon/makesoft2/proc3.html
オーバロードされる可能性のあるメンバ関数には、virtualキーワードをつけて仮想関数にする。
基本クラスへのポインタを使って仮想関数を実行したとき、適切なバージョンの関数が実行される(基本型への回帰の回避)
#include <iostream> #include <boost/date_time/gregorian/gregorian.hpp> #include <boost/date_time/posix_time/posix_time.hpp> using namespace boost::gregorian; using namespace boost::posix_time; const ptime now(second_clock::local_time()); const date d(now.date()); const time_duration time(now.time_of_day()); TFormat("%4d/%2d/%2d/ %2d:%2d:%2d") % d.year() % d.month() % d.day() % time.hours() % time.minutes() % time.seconds()
クラスのコピー用。普通のコンストラクタに初期値を設定したり、代入をしても参照渡しなのでダメ(メンバ変数にポインタ等を使ってなければ大丈夫だけど)。
class CSample { public: CSample(const CSample& obj); // コピーコンストラクタ }; CSample::CSample(const CSample& obj) { }
メニューやボタンのクリックはコマンドとしてコマンドターゲット(CCmdTargetクラス)に送られる
(expression1, expression2) 左から順に実行される 優先度が低いので括弧づけしておく コンマ演算子全体の値は最右端の演算の値
スレッドオブジェクトが持つ待機と実行を制御するカウンタ
カウンタが0のとき実行し、そうでなければ待機
カウンタをインクリメント: SuspendThread
カウンタをデクリメント: ResumeThread
(式1) ? 式2 : 式3
virtural void show()=0のように「=0」をつける。
抽象クラス(純粋仮想関数を持つクラス)は、その派生クラスを統一的に管理するために存在する。純粋仮想関数を利用することで、実行ファイルサイズを小さくすることができる。
// メインフレームウィンドウのポインタを取得します CFrameWnd* pWnd = (CFrameWnd*)AfxGetApp()->m_pMainWnd; // ステータスバーのポインタを取得します CStatusBar* pStatusBar = (CStatusBar*)pWnd->GetMessageBar(); // それぞれのペインに文字を出力します pStatusBar->SetPaneText(0, _T("Pane 0"));
C++ Coding Standards 24
// .hppに #ifndef INCLUDE_UTIL_HPP #define INCLUDE_UTIL_HPP // 何かしらの処理 #endif
afxdb.hが必要
CDatabaseオブジェクトを構築。その後、OpenExを呼出して接続。 OpenEx(LPCTSTR, DWORD) -LPCTSTR: "DSN=SQLSERVER_SOURCE;UID=SA;PWD=abc123" -接続に失敗するとCDBExceptionをスロー close() -データベースへの接続を解除。ただし、オブジェクトは破棄されないので再利用可 IsOpen() CDatabaseオブジェクトがデータソースに現在接続されているかどうか調べる
CRecordSetオブジェクトを構築。その後、データベースからの読み込み IsEOF() -レコードセットにレコードが存在しない場合、または最終レコードより後にスクロールした場合は0以外の値を返す GetFieldValue(LPCTSTR, CDBVariant&, short) -LPCTSTR: インデックスorフィールドの名前 -CDBVariant: フィールドの値を保持 MoveNext() -現在のレコードを次の行セットの先頭レコードに位置づける GetODBCFieldCount() レコードセットオブジェクト内のフィールドの合計数を取得 GetODBCFieldInfo(nIndex, CODBCFieldInfo&) -nIndex: 0から始まるフィールドのインデックス -CDBCFieldInfo&: CDBCFieldInfo構造体への参照 --CString m_strName: フィールド名 --SWORD m_nSQLType: フィールドのSQLデータ型 --UDWORD m_nPrecision: フィールドの最大有効桁数 --SWORD m_nScazle: フィールドのスケール --SWORD m_nNullability: フィールドにNULL値を仕様できるかどうか示す
ディスプレイやプリンタなどの表示デバイスを出力する際に必要な描画情報を保持するメモリ領域
関数の引数にデフォルト値を設定できる
// プロトタイプ宣言 void hoge(int i=0;) // 実装 void hoge::hoge(int i /* =0 */)
try { // 「名前をつけて保存」ダイアログの作成 CFileDialog dlg(FALSE, _T("*.*"), _T("default.csv"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, _T("csv (*.csv)|*.csv|すべて (*.*)|*.*||"), this); dlg.m_ofn.lpstrInitialDir = _T("c:\")
// 「ファイルを開く」ダイアログの作成 CFileDialog dlg(TRUE, _T("*.*"), _T("default.csv"), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, _T("csv (*.csv)|*.csv|すべて (*.*)|*.*||"), this);
OFN_ALLOWMULTISELECT | 複数ファイルの選択を可能にする |
OFN_FILEMUSTEXIST | 存在しないファイル名を指定した場合、警告を表示し、ダイアログを終了しない。このフラグを指定するとOFN_PATHNUSTEXISTも有効になる |
OFN_PATHMUSTEXIST | 存在しないパスを指定した場合、警告を表示し、ダイアログを終了しない |
OFN_NODEREFERENCELINKS | ショートカットを選択したとき、直接そのファイル名を返す。指定しないと、ショートカットが指すファイル名を返す |
OFN_NONETWORKBUTTON | [ネットワーク]ボタンを表示しない |
OFN_SHOWHELP | [ヘルプ]ボタンを表示する |
OFN_OVERWRITEPROMPT | 選択されたファイルがすでに存在するなら、 ファイルに上書きするべきかどうか確認する |
OFN_CREATEPROMPT | 指定ファイルが存在しない時、新規作成するかどうかを確認します。 |
OFN_READONLY | 読み取り専用ファイルとして開く(R)を最初からオンに選択させます。 |
OFN_HIDEREADONLY | 読み取り専用ファイルとして開く(R)をオンに選択させません |
// 指定されたファイルのフルパス名を取得 CFileDialog::GetPathName(); // 選択されたファイルのファイル名を返す CFileDialog::GetFileName(); // 選択されたファイルの拡張子を返す CFileDialog::GetFileExt(); // 選択されたファイルのタイトルを返す CFileDialog::GetFileTitle();
// ファイルの複数選択 POSITION pos = dialog.GetStartPosition(); while (pos != NULL) AfxMessageBox(dialog.GetNextPathName(pos)); // ファイルリスト中の最初のファイル名の位置を取得。1つもファイル名が選択されていない場合はNULL CFileDialog::GetStartPosition // ファイル名を1つずつ取得する。ファイル名が残されていない場合にはNULLを返す。フルパス名を返す CFileDialog::GetNextPathName(POSITION& pos);
// 「ファイルを開く」ダイアログを開く if( dlg.DoModal() == IDOK) { // 選択されたファイルパス名を表示 TString FileName = dlg.GetPathName(); TString Item = _T("\"病院コード\",\"病院グループコード\",\"病院名\",\"依頼科\",\"読影医名\","); CStdioFile TxtFile; // オープン時のモードの設定により、エラーが発生するので注意! BOOL FileOpened = TxtFile.Open(FileName.c_str(), CFile::modeCreate | CFile::modeWrite); if(FileOpened) { TxtFile.WriteString(Item.c_str()); TxtFile.WriteString(results.c_str()); TxtFile.Close(); } } else { ::AfxMessageBox( Msg::ERR_OPEN_FILE ); return; } } catch( CFileException& ex ) { string msg = io::str( format( Msg::ERR_OPEN_FILE_DIALOG ) % ex.m_cause ); theApp.GetLogger()->writeLog( Logger::L_ERROR, msg ); ::AfxMessageBox( msg.c_str() ); }
// Cドライブのすべてのファイルを検索 SearchFile(_T("C:"));
void SearchFile(CString strFolder) { CFileFind FileFind; // すべてのファイルを検索 CString strSearchFile = strFolder + _T("\\*.*"); if(!FileFind.FindFile(strSearchFile)) return; BOOL bContinue = TRUE; while(bContinue){ bContinue = FileFind.FindNextFile(); // ドット("." , "..")の場合 無視 if(FileFind.IsDots()) continue; // ディレクトリの場合、そのディレクトリ内を検索するため再起呼び出し if(FileFind.IsDirectory()) SearchFile(FileFind.GetFilePath()); else // ファイルの場合 TRACE("%s\n",FileFind.GetFilePath()); }; }
void CFamilyHistoryView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { // TODO: ここにメッセージ ハンドラ コードを追加するか、既定の処理を呼び出します。 if (nChar != VK_CONTROL) { // Ctrl- if(::GetKeyState(VK_CONTROL)<0) { // c if (nChar == 0x43) { } // v if (nChar == 0x56) { } // x if (nChar == 0x58) { } // z if (nChar == 0x5a) { } } } CView::OnKeyDown(nChar, nRepCnt, nFlags);
}
HFONT hFont; int fontsize = lexical_cast<int>(m_fontSize); hFont = CreateFont(fontsize, 0, 0, 0, FALSE, FALSE, FALSE, 0, SHIFTJIS_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, m_fontName.c_str()); SendDlgItemMessage(IDC_EDIT_SAMPLE, WM_SETFONT, (WPARAM)hFont, 0L );
m_ToolTip1.Create(this, TTS_ALWAYSTIP | TTS_BALLOON ); // ダイアログ上のボタンを指定 m_ToolTip1.AddTool((CButton *)GetDlgItem(IDC_BTN1),_T("あいうえお"));
BOOL CTheDlg::PreTranslateMessage(MSG* pMsg) { switch(pMsg->message){ case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_MOUSEMOVE: m_ToolTip1.RelayEvent(pMsg); m_ToolTip2.RelayEvent(pMsg); }
return CDialog::PreTranslateMessage(pMsg); }
d = floor(d+0.5);
template <class T> void swap(T& x, T& y) { T tmp = x; x = y; y = tmp; };
CMenu* pMenu = GetSystemMenu(FALSE); ASSERT(pMenu); pMenu->EnableMenuItem(SC_CLOSE, MF_GRAYED);
// ViewからDocへの参照 CXXXDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); pDoc->YYY
// DocからViewへの参照 POSITION pos = GetFirstViewPosition(); CXXXView* pView = (CXXXView*)this->GetNextView(pos); pView->YYY
// DocとViewの関連づけ CXXXDoc->AddView(CXXXView);
// 存在しているならtrue bool DoesFileExist( TString FileName ) { bool bRet = false; WIN32_FIND_DATA FindData; HANDLE hFile = FindFirstFile( FileName.c_str(), &FindData ); if ( hFile != INVALID_HANDLE_VALUE ) bRet = true; FindClose( hFile ); return bRet; }
CFont *pFont; LOGFONT logFont; pFont = GetFont(); pFont->GetLogFont(&logFont); // フォントをポイントサイズで取得 // マッピングモードがMM_TEXTの場合 int pointSize = -MulDiv(logFont.lfHeight, GetDeviceCaps(GetDC()->GetSafeHdc(), LOGPIXELSY), 72);
参考URL: http://support.microsoft.com/kb/74299/ja http://72.14.235.104/search?q=cache:fubrRw54nm0J:www2.ocn.ne.jp/~mizu/api/c/c0002-2.htm+lfHeight+-11&hl=ja&ct=clnk&cd=7&gl=jp&lr=lang_ja&client=firefox
LOGBRUSH logBrush; logBrush.lbColor = color; logBrush.lbHatch = 0; logBrush.lbStyle = BS_SOLID; // 点線 CPen pen(PS_DASH | PS_GEOMETRIC | PS_ENDCAP_FLAT, width, &logBrush); CPen* pOldPen = pDC->SelectObject(&pen); pDC->SelectObject(&pen);
C++ Coding Standards 19 変数は必ず初期化しよう Exceptional C++ 項目42 変数の初期化 T t(u); // T T=u;の代わりに
void DigestSelectBtn::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { // TODO: 指定された項目を描画するためのコードを追加してください。 CRect rect; rect.CopyRect(&lpDrawItemStruct->rcItem); CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC); UINT nState = lpDrawItemStruct->itemState; HBITMAP hBitmap = (HBITMAP)::LoadImage(NULL, _T("res\\Erase.bmp"),IMAGE_BITMAP,0,0,LR_LOADFROMFILE ); CBitmap* pBitmap = CBitmap::FromHandle(hBitmap);
CDC OB; CBitmap *pOld; OB.CreateCompatibleDC( pDC ); pOld = OB.SelectObject( pBitmap ); BITMAP bm; pBitmap->GetBitmap(&bm);
/* bitmapの貼り付け */ pDC->SetStretchBltMode(HALFTONE); pDC->StretchBlt(rect.left, rect.top, rect.Width(), rect.Height(), &OB, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
/* 縁の描画 */ if (nState & ODS_SELECTED) { pDC->DrawEdge(rect,EDGE_SUNKEN,BF_RECT); } else { pDC->DrawEdge(rect,EDGE_RAISED,BF_RECT); }
// メニュー押下に対するメッセージ関数を用意しておかないと、表示が無効になったままになるので注意!!! void CFamilyHistoryView::OnContextMenu(CWnd *pWnd, CPoint pos) { CMenu Menu; CMenu* pMenu; // 右クリックメニューの追加 Menu.LoadMenu(IDR_RIGHT_MENU); ASSERT(Menu); pMenu = Menu.GetSubMenu(0); ASSERT(pMenu); pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, pos.x, pos.y, AfxGetMainWnd()); }
// メニュー項目を有効に pCmdUI->Enable(); // メニュー項目のチェック if (自分のメニューなら) pCmdUI->SetCheck(1); else pCmdUI->SetCheck(0);
// .cpp // include文より後ろに挿入 #ifdef _DEBUG #define new DEBUG_NEW #endif
// プログラムの先頭に; _CrtSetBreakAlloc(1329)
CWnd* m_pParent; int m_nID;
m_pParent = pParent; m_nID = CDlg1::IDD;
return CDialog::Create( m_nID, m_pParent);
Dlg* pDlg = new Dlg(this); pDlg->Create(); pDlg->ShowWindow(SW_SHOW);
CPoint startPos, endPos; startPos.x = m_rect.left; startPos.y = m_rect.top; endPos.x = m_rect.right; endPos.y = m_rect.bottom; pDC->MoveTo(startPos); pDC->LineTo(endPos);
double x, y; x = endPos.x - startPos.x; y = endPos.y - startPos.y; double r = atan2(y, x);
POINT arrowHead[2], newArrowHead[2]; arrowHead[0].x = -wingLength; arrowHead[0].y = -wingLength; arrowHead[1].x = -wingLength; arrowHead[1].y = wingLength; for(int j = 0; j < 2; j++) { newArrowHead[j].x = (int)(arrowHead[j].x * cos(r) - arrowHead[j].y * sin(r)); newArrowHead[j].y = (int)(arrowHead[j].x * sin(r) + arrowHead[j].y * cos(r)); }
pDC->MoveTo(endPos); pDC->LineTo(endPos + newArrowHead[0]); pDC->MoveTo(endPos); pDC->LineTo(endPos + newArrowHead[1]);
ラジオボタンをグループ化するためには、