VC++関係[詳細] (最終更新日は '00.2.23 です。)
CFileDialogのカスタマイズを行う。
[New'98.12.18]
1.追加するダイアログリソースを定義する。 このとき、必ず子ウィンドウで、3D・コントロール・兄弟ウィンドウをクリップを指定する。 IDD_FILE_C_RANGE DIALOG DISCARDABLE 13, 28, 171, 22 STYLE DS_3DLOOK | DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS FONT 9, "MS Pゴシック" BEGIN CTEXT "開始位置",IDC_STATIC,5,9,28,8 EDITTEXT IDC_STARTSEC,42,5,37,12,ES_AUTOHSCROLL CTEXT "終了位置",IDC_STATIC,89,9,28,8 EDITTEXT IDC_ENDSEC,129,5,37,12,ES_AUTOHSCROLL END 2.CFileDialogの派生クラスを作成する。(例えばCFileRangeDialog) 3.コントロールに対応したメンバ変数を定義し、対応つける。 4.OnFileNameOK()を定義し、その中で、OnOK()を呼び出す。 CFileRangeDialog::CFileRangeDialog(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName, DWORD dwFlags, LPCTSTR lpszFilter, CWnd* pParentWnd) : CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, pParentWnd) { m_sEndSec = _T(""); m_sStartSec = _T(""); } void CFileRangeDialog::DoDataExchange(CDataExchange* pDX) { CFileDialog::DoDataExchange(pDX); DDX_Text(pDX, IDC_ENDSEC, m_sEndSec); DDV_MaxChars(pDX, m_sEndSec, 8); DDX_Text(pDX, IDC_STARTSEC, m_sStartSec); DDV_MaxChars(pDX, m_sStartSec, 8); } BEGIN_MESSAGE_MAP(CFileRangeDialog, CFileDialog) //{{AFX_MSG_MAP(CFileRangeDialog) //}}AFX_MSG_MAP END_MESSAGE_MAP() BOOL CFileRangeDialog::OnInitDialog() { CFileDialog::OnInitDialog(); // TODO: この位置に初期化の補足処理を追加してください //IDC_STARTSEC //IDC_ENDSEC return TRUE; // コントロールにフォーカスを設定しないとき、戻り値は TRUE となります // 例外: OCX プロパティ ページの戻り値は FALSE となります } void CFileRangeDialog::OnOK() { CFileDialog::OnOK(); } BOOL CFileRangeDialog::OnFileNameOK() { OnOK(); return CFileDialog::OnFileNameOK(); } 5.CFileDialogの派生クラスを使用する。 CString strDefExt((LPCSTR)IDS_DEFFILTER); CString strExtType((LPCSTR)IDS_FILTER); CFileRangeDialog FileOpen( FALSE, //* [ファイル名を付けて保存] を構築 strDefExt, //* デフォルト拡張子 NULL, //* 初期値 OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY | OFN_PATHMUSTEXIST|OFN_ENABLETEMPLATE/*|OFN_ENABLEHOOK*/, strExtType, //* フィルタ AfxGetMainWnd( ) ); //* 親ウィンドウ //* CHILDの追加 // FileOpen.m_ofn.hInstance = AfxGetInstanceHandle( ); CString strTipText=_T("部分保存"); //タイトル FileOpen.m_ofn.lpstrTitle=strTipText; FileOpen.m_ofn.nMaxFileTitle=strTipText.GetLength(); FileOpen.m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_FILE_C_RANGE); //* カスタマイズリソース int ret = FileOpen.DoModal();
65535以上の範囲のスクロールバー表示
[New'98.11.13]
1.範囲指定&初期位置 SCROLLINFO scrollinfo; scrollinfo.cbSize=sizeof(scrollinfo); scrollinfo.fMask=SIF_POS|SIF_RANGE; //位置とスクロール範囲指定 scrollinfo.nMin=0; //最小値 scrollinfo.nMax=m_dwOffsetMax; //最大値 scrollinfo.nPos=m_dwOffset; //位置 SetScrollInfo(SB_VERT,&scrollinfo,TRUE); 2.位置指定 SCROLLINFO scrollinfo; scrollinfo.cbSize=sizeof(scrollinfo); scrollinfo.fMask=SIF_POS; //位置指定 scrollinfo.nPos=m_dwOffset; //位置 SetScrollInfo(SB_VERT,&scrollinfo,TRUE); 3.位置取得(OnVScroll()などで) SCROLLINFO scrollinfo; DWORD nPos; scrollinfo.cbSize=sizeof(scrollinfo); GetScrollInfo(SB_VERT,&scrollinfo,SIF_POS|SIF_TRACKPOS );//位置を取得 nPos=scrollinfo.nPos; //位置 if (nSBCode==SB_THUMBTRACK) { //スライダードラッグ中 nPos=scrollinfo.nTrackPos; //スライダードラッグ時の位置 }
メッセージへのファイル名などの埋め込み
[New'98.11.13]
1.AfxFormatString1()またはAfxFormatString2()を使用する。 リソースファイル IDS_ERR_SAVE_AS "ファイル'%1'の保存でエラーが発生しました。" コーディング CString strFileName; //ファイル名 CString strWk; AfxFormatString1( strWk, IDS_ERR_SAVE_AS, strFileName); AfxMessageBox(strWk); 2.CString::Format()を使用する。 リソースファイル IDS_ERR_COMMON_DLG "エラーコード:%d" コーディング DWORD dret; //リターンコード CString sMsg; sMsg.Format(IDS_ERR_COMMON_DLG,dret); AfxMessageBox(sMsg);
CFontDialogのカスタマイズを行う。
[New'98.7.11]
1.includeディレクトリ(mfcなどではなくSDKレベル)にある、font.dlgをコピーする。 2.resource.hの最後の行に #include<Dlgs.h> を追加する。 3.font.dlgの内容をxxxx.rc(xxxはプロジェクト名)に追加する。場所は、ダイアログの定義部分の最後に追加する。 (font.dlgをxxx.rcにincludeしても良いが、編集が面倒になります。) この場合シンボル、値は変更不可。 4.フォントをMS Pゴシック 9ポイントに変更する。 5.文字列を日本語に変更する。 6.CFontDialogの派生クラスを作成し、下記の手順で表示する。 CCustomFontDialog FontDlg(&m_logfont); //CCustomFontDialogはCFontDialogの派生クラス FontDlg.m_cf.Flags |= CF_ENABLEHOOK | CF_ENABLETEMPLATE; //* フラグ設定 FontDlg.m_cf.hInstance = AfxGetInstanceHandle( ); FontDlg.m_cf.lpTemplateName = MAKEINTRESOURCE(FORMATDLGORD31); //* カスタマイズリソース //ダイアログリソースは、必要な項目を含んでいる必要がある。 int iret=FontDlg.DoModal(); 7.通常のダイアログが出ることを確認したら、FORMATDLGORD31ダイアログに項目を追加、変更する。 8.OnInitDialogで追加した項目の初期化を行う。 9.必要に応じて、処理を追加する。 注意:もとのリソースが英語のため、日本語の選択コンボボックスは付かないようです。
アプリケーションのポインタを取得する
[New'98.3.24]
AfxGetApp()で通常アプリケーションへのポインタが取得できます。
CXXXApp *pWnd=(CXXXApp *)AfxGetApp();
メインウィンドウのポインタを取得する
[New'98.3.24]
AfxGetMainWnd()で通常CMainFrameへのポインタが取得できます。
CMainFrame *pWnd=(CMainFrame *)AfxGetMainWnd();
表示のちらつきをなくす
[New'98.3.24]
OnEraseBkgnd()をオーバライドして、背景の消去を抑止する。
CXXWnd::OnEraseBkgnd(CDC *pDC) { return 1; }
CImageListで256色のbitmapリソースを扱う
[New'97.11.5]
CImageListのCreate時にbitmapリソースIDを指定すると、16色になってしまうため、
CImageListを色のbit数を指定してCreateしてからbitmapリソースをAddする。
//Create CImageList m_imgList; int index=-1; #define MASK_COLOR RGB(255,0,255) //例えば紫色を透過色とする場合 BOOL bret=m_imgList.Create(cx,cy,ILC_COLOR8|ILC_MASK,0,1); if (bret) { CBitmap bmp; bret=bmp.LoadBitmap(IDB_XXXX); //IDB_XXXXはbitmapリソーシID if (bret) { index=m_imgList.Add(bmp,MASK_COLOR); } } //表示 //CDC dc; //CPOint pt; BOOL bret=m_imgList.Draw(&dc,index,pt,ILD_NORMAL);
ダイアログでキャンセルボタンがないとき、ESCを効かなくする。
[New'97.10.20]
OnCancel()をオーバライドし、なにも動作しないようにする。
コントロールバーの状態を保存・回復する。
[New'97.10.13]
CDockStateを使用する。
[保存] CDockState dockstate; GetDockState(dockstate); //CFrameWnd:: dockstate.SaveState(_T("xxxx")); //xxxx:エントリ名 [回復] CDockState dockstate; dockstate.LoadState(_T("xxxx")); //xxxx:エントリ名 SetDockState(dockstate); //CFrameWnd::
起動時にスプラッシュウィンドウ(ロゴ)を表示する。
[New'97.10.9]
1.コンポーネントギャラリーでスプラッシュ スクリーンを指定して挿入を行う。
2.bitmapリソース IDB_SPLASHを編集する。
3.画面の表示が遅い場合は、CMainFrame::OnCreate()で自動挿入されたコードをCMainFrame::OnCreate()内のCFrameWnd::OnCreate()の直後へ移動する。
bitmapリソースを透過色を指定して表示する。
[New'97.10.3]
CImageList m_imglist; cx=16; //bitmapの横幅 nGrow=0; crMask=RGB(255,0,255);//紫を透過色とする場合 m_imglist.Create( IDB_XXXX, cx, nGrow, crMask );//bitmapリソースを登録 CDC *pdc; //DC int nImage=0; //先頭のbitmap CPoint pt; //表示座標 UINT nStyle=ILD_NORMAL; pdc=&dc; pt=CPoint(100,100); m_imglist.Draw(pdc, nImage, pt, nStyle);//bitmapを表示する。
座標が特定の矩形領域内にあるか判断する。
[New'97.10.3]
CRect::PtInRect()を使用して判定する。
書式を付けて文字列を操作する。
[New'97.10.3]
CString::Format()を使用する。
ドライブ名、ディレクトリ、ファイル名、拡張子からパス名を得る
[New'97.9.29]
_tmakepath()[ASCII/SJISだけなら_makepath()]を使用する。
これで、ドライブ名、ディレクトリ、ファイル名、拡張子からパス名を得ることができます。
絶対パスからファイル名等を取り出す。
[New'97.9.29]
_tsplitpath()[ASCII/SJISだけなら_splitpath()]を使用する。
これで、ドライブ名、ディレクトリ、ファイル名、拡張子を得ることができます。
非ビューウィンドウでOLE Drag&Dropを可能とする。
[New'97.9.23]
1.COleDropTargetの派生クラスを作る。
2.Dropを可能としたいウィンドウにCOleDropTargetの派生クラスのメンバ変数(m_DropTarget等)を定義する。
3.OnCreate()で、 m_DropTarget.Register(this) を追加する。
4.COleDropTargetの派生クラスでOnDragEnter(),OnDragLeave(),OnDragOver(),OnDrop(),OnScrollBy()をオーバーライドする。
5.OnDragEnter(),OnDragOver()で通常は、リターン値にDROPEFFECT_COPY か DROPEFFECT_MOVEを指定することで、カーソルがDrop可能表示となる。
6.OnDropでドロップされた内容を取得して、独自の処理を行う。
7.ウィンドウの一部だけをDrop可能とする場合は、OnDragEnter(),OnDragOver()で引数で渡ってくるpointをチェックし、NGの場合はDROPEFFECT_NONEを返す。
また、OnDrop()ではFALSEを返す。
Visual Studio Service Pack 1/Service Pack 2をインストールした後にビルドするとツールチップが表示されなくなる。
[New'97.9.18]
Visual Studio (VC++ 5.0) Service Pack 1のバグのためです。
Article ID: Q172276FIX: CToolTipCtrl Not Displaying Text After VS SP1, SP2 Install
を参考にして、ツールヒントを出したいボタン等の親ウィンドウのクラスにOnToolHitTest()をvirtualでオーバーライドすることで、回避できます。
文書ファイルに関連付いているアイコンを取得する。
[New'97.9.17]
::SHGetFileInfo()を使用する。
タイトルバーのフォントを取得する。
[New'97.9.16]
::SystemParametersInfo()でLOGFONTを取得し、これからCFontを作成する。
nNONCLIENTMETRICS nonclientmetrics; nonclientmetrics.cbSize=sizeof(NONCLIENTMETRICS); BOOL bret=::SystemParametersInfo(SPI_GETNONCLIENTMETRICS,nonclientmetrics.cbSize,&nonclientmetrics,0); //nonclientmetrics.lfCaptionFont //通常のタイトルバーのLOGFONT //nonclientmetrics.lfSmCaptionFont //ツールバー等のタイトルバーのLOGFONT CFont font; bret=font.CreateFontIndirect(&nonclientmetrics.lfCaptionFont);
オーナードローのチェックボタン・ラジオボタンの作成
[Update'04.1.21]
1.CButtonの派生クラスを作成する。(Create時にBS_OWNERDRAW|BS_PUSHBUTTONを指定する。)
2.SetCheck(),GetCheck()をvirtualでオーバーライドする。またチェック状態をメンバ変数に設定する。
3.BM_SETCHECKメッセージをON_MESSAGEでメッセージをマップし、メンバ変数を更新する。
4.DrawItem()をオーバーライドし、メンバ変数の状態で表示内容を切り替える。
プロセスの終了を監視する方法
[New'97.8.28]
16bitのとき
(1)Windows APIのGetModuleUsageでプロセスが無くなったか監視する。
(2)Windows APIのFindWindowでプロセスのWindowが無くなったか監視する。
(3)Windows APIのtoolhelp系のNotifyRegisterで終了通知を受ける。
(4)Windows APIのtoolhelp系のタスクを検索するAPIで検索する。
(Windows95/NTのWOWで、32bitの終了を監視する場合に有用)
32bitのとき
(1)Windows APIのFindWindowでプロセスのWindowが無くなったか監視する。
(2)Windows APIのOpenProcessとGetExitCodeProcessを使用する。
(3)Windows APIのCreateProcessでプロセスを起動して、WaitForInputIdle
で起動完了までアイドルして、WaitForSingleObjectで監視
(4)Windows95であれば、toolhelp32を使用する。
(5)Windows APIのCreateProcessでプロセスをデバッグモードで起動して、終了通知を受ける。
(監視スレッドを作り、CreateProcessはそのスレッドで実行し、デバッグメッセージ
を逐次処理する)ただし、16bitの起動はできません。
プロセスに所属するウィンドウを取得する。(WindowsNT以外)
[Update'98.7.22]
Windows3.1ならEnumTaskWindows,win32ならEnumThreadWindowsを使用する。
1.Windows 3.1の時
HWND hWndwk[(予定するhWnd数)] //共通変数 int wndCnt; xxxxxx(xxxx,xxxx) { HANDLE hThreadSnap = NULL; THREADENTRY32 te32 = {0}; ・・・ wndCnt=0; //hTaskからWindow検索 ret=EnumTaskWindows(hTask,EnumWndProc,0L); //wndCntで個数,hWndwkでhWndを取得 ・・・ } BOOL CALLBACK EnumWndProc(hWnd,lParam) { hWndwk[wndCnt]=hWnd; wndCnt++; return TRUE; } 2.Win32のとき #include <tlhelp32.h> // Required for ToolHelp32 functions typedef BOOL (WINAPI *MODULEWALK)(HANDLE hSnapshot, LPMODULEENTRY32 lpme); typedef BOOL (WINAPI *THREADWALK)(HANDLE hSnapshot, LPTHREADENTRY32 lpte); typedef BOOL (WINAPI *PROCESSWALK)(HANDLE hSnapshot, LPPROCESSENTRY32 lppe); typedef HANDLE (WINAPI *CREATESNAPSHOT)(DWORD dwFlags, DWORD th32ProcessID); HWND hWndwk[(予定するhWnd数)] //共通変数 CREATESNAPSHOT pCreateToolhelp32Snapshot = NULL; THREADWALK pThread32First = NULL; THREADWALK pThread32Next = NULL; xxxxxx(xxxx,xxxx) { HANDLE hThreadSnap = NULL; THREADENTRY32 te32 = {0}; ・・・ wndCnt=0; //toolhelp32でプロセスID(dwPID)からthreadIDを検索してWindow検索 hKernel = GetModuleHandle("KERNEL32.DLL"); if (hKernel) { pCreateToolhelp32Snapshot = (CREATESNAPSHOT)GetProcAddress(hKernel, "CreateToolhelp32Snapshot"); pThread32First = (THREADWALK)GetProcAddress(hKernel, "Thread32First"); pThread32Next = (THREADWALK)GetProcAddress(hKernel, "Thread32Next"); } else { //Error } hThreadSnap = pCreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); if (hThreadSnap == (HANDLE)-1) { //Erro } te32.dwSize = sizeof(THREADENTRY32); if (pThread32First(hThreadSnap, &te32)) { do { if (te32.th32OwnerProcessID == dwPID) { ret=EnumThreadWindows(te32.th32ThreadID,EnumWndProc,0L); } } while (pThread32Next(hThreadSnap, &te32)); } else { //Error } CloseHandle (hThreadSnap); FreeLibrary(hKernel); //wndCntで個数,hWndwkでhWndを取得 ・・・ } BOOL CALLBACK EnumWndProc(hWnd,lParam) { hWndwk[wndCnt]=hWnd; wndCnt++; return TRUE; }
16bit APから32bit DLLを呼び出す。
[New'97.8.28]
MSJ No.33(MSDN MSJ Vol.9 No.6 Test Drive Win32 ...)に記述があります。
また、MSDNの「Calling a Win32 DLL from a Win16 Application Under WOW」
に簡単な呼び方が記述されています。
1.LoadLibraryEx32W/GetProcAddress32W/CallProc32W/GetVDMPointer32W/
FreeLibrary32Wをkernelからインポートする。
2.32bit DLLを16bitAPでロードする。
DWORD FAR PASCAL LoadLibraryEx32W( LPCSTR, DWORD, DWORD);
3.32bit DLLのexportされた関数のアドレスを取得する。
DWORD FAR PASCAL GetProcAddress32W( DWORD, LPCSTR );
4.32bit DLLの関数をコールする。
DWORD FAR PASCAL CallProc32W( DWORD, ..., LPVOID, DWORD, DWORD );
5.32bitアドレスへの変換
DWORD FAR PASCAL GetVDMPointer32W( LPVOID, UINT );
6.32bit DLLを開放する。
BOOL FAR PASCAL FreeLibrary32W( DWORD );
OSの種類(95、NT)を判定する方法
[New'97.8.28]
1.Win32のとき
BOOL GetVersionEx(LPOSVERSIONINFO lpVersionInformation )で取得できます。
2.16bitのとき
GetWinFlagsの戻り値で判断できます。
GetWinFlagsの追加定義
#define WF_WINNT 0x4000 //GetWinFlagsでこの値でandを取って判断する。
詳細は、MSDNの「How to Determine If a VB App is Running Under Windows NT 3.x」,
「Determining System Version from a Windows-Based Application」を参考にして下さい。
経過時間を取得する。
[New'97.8.28]
BOOL QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCounter)で可能です。
ちなみに、タイマーの解像度は、QueryPerformanceFrequency()で調べられます。
Windows 3.1でドライブがCD-ROMかを判断する。
[New'97.8.23]
MSDNのCDで「Knowledge Base How to Determine Drive Types in Windows」を参照する。
REPORT表示のCListCtrlの行の高さを変える
[New'97.8.23]
SetImageListで指定したい高さ分のアイコンを指定する。
文字列リソースからツールチップの文字列を取得する。
[New'97.8.23]
MFC内部の関数を使用する。
int nID; //文字列のリソースID
TCHAR szFullText[256];
CString strTipText;
AfxLoadString(nID, szFullText);
// this is the command id, not the button index
AfxExtractSubString(strTipText, szFullText, 1, '\n');
ツールチップの内容を条件により変更する。
[Update'97.10.18]
(1)::SetWindowLong(m_hWnd,GWL_ID ,nID)でツールチップを変えたいウィンドウのIDを変更したあとのツールチップに対応するIDに書き換える。
(2)OnToolHitTest()をオーバーライドし、UpdateTipText()でツールチップを更新する。
OnToolHitTest()の戻り値はドキュメントと異なり、ヒットしたコントロールのIDが帰ってくるので、これを基に判断する。
メニューの表示文字列を条件により変更する。
[Update'97.8.21]
OnUpdateXXXでSetText()でメニューの文字列を変更する。
メニューに対するガイダンスを条件により変更する。
[Update'97.10.18]
(1)OnUpdateXXXでpCmdUI->m_nIDを変更したあとのガイダンスに対応するIDに書き換える。
(2)CFrameWnd::OnMenuSelect()でSetMessageText()でガイダンスを更新する。
システムメニューの内容を元に戻す。
[New'97.8.18]
GetSystemMenu(TRUE)を実行する。
ダイアログバーをリサイズ可能にする。
[Update'97.8.13]
1.ダイアログバーのCreate時にCBRS_SIZE_DYNAMICを指定する。
2.ダイアログバーの派生クラスで、CalcFixedLayout(),CalcDynamicLayout()にサイズ計算処理を入れる。
3.CMainFrameでEnableDocking()をオーバーライドし、MFCのソースの内容を一部変更する。
リサイズしたい位置のCDockBarのCreate時にWS_THICKFRAME|CBRS_BORDER_3D|CBRS_BORDER_XXXを追加指定する。指定した所がリサイズ可能となる。
4.CDockBarの派生クラスのOnSize処理でダイアログバーの再配置を行う。
*CDockBarクラスはテクニカルノートに少し記述があります。実態は、CFrameWndの子ウィンドウでコントロールバーのドッキング時の親ウィンドウになるようです。
コントロールバーがフロート時は親ウィンドウはCMiniFrameWndのようです。
ウィンドウの背景色を変更する。
[New'97.8.9]
PreCreateWindowで背景色を指定したクラスを登録して、ウィンドウを生成する。
例:CMainFrameの場合
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { BOOL bret=m_brsh.CreateSolidBrush(RGB(242,242,242));//メンバ変数に宣言 cs.lpszClass = AfxRegisterWndClass(CS_DBLCLKS, AfxGetApp()->LoadStandardCursor(IDC_ARROW), m_brsh, AfxGetApp()->LoadIcon(IDR_MAINFRAME)); return TRUE; }
ドッキングしているコントロールバーの配置順序を変える。
[New'97.8.9]
コントロールバーのZオーダーを入れ替えたあと、再度位置計算を行う。
//CControlBar m_cbar;既に作成してドッキングしたコントロールバー CWnd *pWnd=m_cbar.GetParent();//ステータスバー以外は親を求める pWnd->SetWindowPos(&wndTop,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);//Zオーダーを先頭にする AfxGetMainWnd()->RecalcLayout();
Windows95,WindowsNT 4.0でユーザーのログイン・ログオフを知る。
[New'97.8.7]
WM_USERCHANGEDメッセージを処理する。
ダイアログの背景色、コントロールの色を変える。
[New'97.7.31]
(1)CWinApp::SetDialogBkColor()を使用する。
(2)ダイアログの親ウィンドウでOnCtlColor()をオーバライドし、色を指定する。
WindowsNT 3.51でCButtonでビットマップが表示されない。
[New'97.7.29]
WindowNT 3.51ではBS_ICON と BS_BITMAPが支援されていないため。
MSDNで「PRB: CButton SetIcon and SetBitmap Work Only Under Windows 95」参照のこと。
ダイアログバー上のボタンにツールヒントを表示する。
[New'97.7.29]
ボタンのリソースIDを対応するメニューのリソースIDと同一にする。
ステータスバーに座標を表示する。
[New'97.7.29]
コンポーネントギャラリーでステータスバーを挿入後、挿入された内容(時間表示)を修正すると簡単です。
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) ON_WM_INITMENUPOPUP() ON_WM_MENUSELECT() ON_UPDATE_COMMAND_UI(ID_INDICATOR_XY, OnUpdateXY) //{{AFX_MSG_MAP(CMainFrame) // メモ - ClassWizard はこの位置にマッピング用のマクロを追加または削除します。 // この位置に生成されるコードを編集しないでください。 ON_WM_CREATE() //}}AFX_MSG_MAP END_MESSAGE_MAP()int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { //省略 // CG: 次のブロックは「ステータス バー」コンポーネントにより追加されています。 { // AppWizard の定義したスタティック変数 'indicators' のサイズを // 調べて保存します。 int nOrigSize = sizeof(indicators) / sizeof(UINT); UINT* pIndicators = new UINT[nOrigSize + 1]; //+1は1個追加することを示す。 memcpy(pIndicators, indicators, sizeof(indicators)); // ステータス バー コンポーネントのステータス バー作成ルーチンを呼び出します。 if (!InitStatusBar(pIndicators, nOrigSize, 60)) { TRACE0("Failed to initialize Status Bar\n"); return -1; } delete[] pIndicators; } //省略 } BOOL CMainFrame::InitStatusBar(UINT *pIndicators, int nSize, int nSeconds) { // CG: 次のブロックは「ステータス バー」コンポーネントにより追加されています。 m_nXYPaneNo = nSize++; pIndicators[m_nXYPaneNo] = ID_INDICATOR_XY; return m_wndStatusBar.SetIndicators(pIndicators, nSize); } void CMainFrame::OnUpdateXY(CCmdUI* pCmdUI) { // 現在の座標を書式にしたがって変換します。 CString strxy = _T("100,100");//<------------------座標を文字列にする。この場合は、(100,100)固定です。 // BLOCK: 文字列の幅を計算します。 CSize size; { HGDIOBJ hOldFont = NULL; HFONT hFont = (HFONT)m_wndStatusBar.SendMessage(WM_GETFONT); CClientDC dc(NULL); if (hFont != NULL) hOldFont = dc.SelectObject(hFont); size = dc.GetTextExtent(strxy); if (hOldFont != NULL) dc.SelectObject(hOldFont); } // 現在の座標を反映するようにペインを更新します。 UINT nID, nStyle; int nWidth; m_wndStatusBar.GetPaneInfo(m_nXYPaneNo, nID, nStyle, nWidth); m_wndStatusBar.SetPaneInfo(m_nXYPaneNo, nID, nStyle, size.cx); pCmdUI->SetText(strxy); pCmdUI->Enable(TRUE); } //インクルードファイル class CMainFrame : public CFrameWnd { protected: // シリアライズ機能のみから作成します。 afx_msg void OnUpdateXY(CCmdUI* pCmdUI); public: int m_nXYPaneNo; //リソース 文字列リソースに ID_INDICATOR_XYを適当な文字列(たとえばxy)で定義しておく。
タイトルバーを独自に表示する。
[Update'97.8.12]
1.WM_NCACTIVATE,WM_NCPAINTを独自に処理する。
MSDNで「How to Draw a Custom Window Caption」を参考のこと。
2.void CFrameWnd::OnUpdateFrameTitle(BOOL bAddToTitle)をオーバーライドし、デフォルト処理後にWM_NCPAINT処理を呼び出す。
MSJ(日本語版) No.49 P160の記事も参考になります。[Add'97.11.26]
タイトルバーを消す
[New'97.7.29]
ModifyStyle(WS_CAPTION|WS_SYSMENU,0)でスタイルから削除する。
ステータスバーに時刻を表示する。
[New'97.7.21]
コンポーネントギャラリーでステータスバーを挿入する。
ダイアログバー上のスクロール系コントロールの通知メッセージ取得方法
[New'97.7.18]
1.CDialogBarの派生クラスを作成し、派生クラスを使用してダイアログバーをCreateする。
2.派生クラスにメンバ関数OnHScroll()を定義し、CMainFrameへメッセージを中継する。
3.CMainFrame::OnHScroll()でコントロールIDで判別して処理する。
ダイアログバー上のコントロールの操作方法
[New'97.7.18]
1.操作したいコントロールに対応するメンバ変数をCMainFrameに宣言する。
CButton m_Btn1;//IDC_BTN1用のメンバ変数
2.CMainFrame::OnCreate()でダイアログバーの生成後、リソースIDでコントロールを動的サブクラス化する。
BOOL bret=m_Btn1.SubclassDlgItem(IDC_BTN1,&m_DlgBar);//m_DlgBarはダイアログバーのポインタ
3.メンバ変数でダイアログバー上のコントロールが操作できる。
OCXをダイアログに貼り付ける。
[New'97.7.17]
1.コンポーネントギャラリーでOCXを指定して挿入を行う。
2.ダイアログエディタに挿入したOCXが表示されるようになる。
3.ダイアログにOCXを貼り付ける。
4.コンテナの設定をしていない場合は、コンポーネントギャラリーでOLEコントロールコンテナを指定して挿入する。
5.OCXへの操作をする場合は、1で自動生成されたOCXに対応したクラスを使用する。
起動時に最大化表示を行う。
[New'97.7.10]
InitInstance()の最初で、CWinAppのメンバ変数m_nCmdShowにSW_SHOWMAXIMIZEDを代入する。
ダイアログのコントロールに対するメンバ変数を配列にする。
[New'97.7.10]
1.コントロールのIDC_XXXを通し番号で設定する。
2.ClassWizardとは関係なくメンバ変数を記述する。
例:10個のエディットコントロールの場合 変数宣言 xxxdlg.h // ダイアログ データ //{{AFX_DATA(CXXXDlg) enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA CString m_edit[10]; <-----AFX_DATAの外に宣言 xxxdlg.cpp CXXXDlg::CXXXDlg() : CDialog(CXXXDlg::IDD) { //{{AFX_DATA_INIT(CXXXDlg) //}}AFX_DATA_INIT int nID = IDC_EDIT1; for ( int i = 0; i < 10; i++) { //たとえば10個のとき m_edit[i] = _T(""); <-----AFX_DATA_INITの外に宣言 } } void CXXXDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CXXXDlg) <-----残しておく //}}AFX_DATA_MAP <-----残しておく int nID = IDC_EDIT1; for ( int i = 0; i < 10; i++) { //たとえば10個のとき DDX_Text(pDX,nID, m_edit[i]); nID++; } }
明示的にアクティブViewを指定する。
[New'97.7.10]
CFrameWnd::SetActiveView()でアクティブになるViewを指定する。
CViewをCreateする。
[Update'98.1.25]
(1)CreateView()で作成する。
(2)Viewのポインタを作成して、ポインタを用いてCreateを行う。
このようにしないと、CXXXViewのコンストラクタがPublicでないといって
コンパイルエラーになります。また、強引にPublicにすると
実行時にエラーとなります。
CRuntimeClass *pViewClass=RUNTIME_CLASS(CXXXView); CXXXView * pNewView = (CXXXView *) pViewClass->CreateObject(); if (pNewView == NULL) { //エラー } if (!pNewView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, CRect(0,0,0,0), this, AFX_IDW_PANE_FIRST, &context)) { //エラー }
分割ウィンドウのCViewのポインタを取得する。
[New'97.7.10]
MFC AppWizardで分割ウィンドウを作成したときは、CMainFrame::OnCreateClient()で
CSplitterWndのポインタがCMainFrameのメンバ変数m_wndSplitterを使用して、
m_wnsSplitter.GetPane()でViewのポインタを取得できる。
初めて使用したときにコンパイルエラーとなる
[Update'97.7.6]
CTreeView等を利用するときは、stdafx.hに#include <afxcview.h>を追加する。
CTabCtrlのフォントを変更する。
[New'97.6.28]
CTablCtrl::SetFontでフォントを変更する。
このとき、指定したCFontはCTabCtrlを破棄するまでメンバ変数で保持
しておく。
コンボボックスのあるツールバーの作成
[New'97.6.28]
コンポーネントギャラリーでダイアログバーを挿入して
自動生成されたダイアログリソースにボタン、コンボボックスを追加する。
分割した画面をさらに分割する
[New'97.6.28]
CViewのOnCreateの中で、CSplitterWndで分割ウィンドウを作成する。
そのとき、CreateViewに渡すpContextには、lpCreateStruct->lpCreateParams
を指定する。
現在アクティブ(前景)になっているトップレベルウィンドウを取得する。
[New'97.6.26]
CWnd::GetForegroundWindow()を使用する。戻り値がNULLの場合があるので注意する必用がある。
CWnd *pActiveWnd=CWnd::GetForegroundWindow(); if (pActiveWnd!=NULL) { //処理 }
CWinApp内でCDocumentポインタを取得する方法
[New'97.6.23]
Documentが一つしかない場合
POSITION posDocTemp=CWinApp::GetFirstDocTemplatePosition( );//まずCDocTemplateを取得 CDocTemplate* pDocTemplate=GetNextDocTemplate( posDocTemp ); POSITION posDoc=pDocTemplate->GetFirstDocPosition( );//次にCDocumentを取得 CDocument* pDoc=pDocTemplate->GetNextDoc( posDoc);
CDocument内でCViewポインタを取得する方法
[New'97.6.23]
Viewが一つしかない場合
POSITION posView = CDocument::GetFirstViewPosition(); CView* pFirstView = CDocument::GetNextView( posView );
CListCtrlにサブアイテム(カラム)を追加する。
[New'97.6.23]
1.カラムを追加する。
CListCtrl::InsertColumn(nCol,_T("サブアイテムの見出し"));
2.行を追加する。
CListCtrl::InsertItem(nItem,_T("先頭のアイテムの内容"));
3.サブアイテムを設定する。
CListCtrl::SetItem(nItem,nSubItem,LVIF_TEXT,_T("サブアイテムの内容"),0,0,0,0);
EXE,DLLが呼び出しているDLLを確認する。
[New'97.6.23]
VC++のインストールディレクトリ下のBINディレクトリ(たとえばc:\msdev\bin)にあるdumpbinを使用する。
使用方法
dumpbin /IMPORTS ファイル名
ON_THREAD_MESSAGEで使用するハンドラの型
[New'97.6.17]
戻り値の型はLRESULTではなくvoidでないとコンパイルエラーとなる。
テキストファイルを行単位にアクセスする
[New'97.6.17]
読み込み:CStdioFile::ReadString
書き込み:CStdioFile:WriteString
CImageList::CreateのI/F誤り
[New'97.6.17]
誤 BOOL Create( int cx, int cy, BOOL bMask, int nInitial, int nGrow ); 正 BOOL Create( int cx, int cy, UINT frags, int nInitial, int nGrow ); frags 作成するイメージ リストの種類を指定します。この引数には、以下の値の組み合わせを指定できます。 値 説明 ILC_COLOR4 4 ビットのデバイスに依存しないビット マップ (DIB) セクション。 ILC_COLOR8 8 ビットの DIB セクション。 ILC_COLOR16 16 ビットの DIB セクション。 ILC_COLOR24 24 ビットの DIB セクション。 ILC_COLOR32 32 ビットの DIB セクション。 ILC_COLORDDB デバイスに依存するビット マップを使用 ILC_MASK 2 つのビット マップを使い、1 つはマスクとして使用するモノクロのビット マップを使用。この値がない場合は、イメージ リストに含まれるビット マップは 1 つだけとなります。 ILC_PALETTE イメージ リストを持つカラー パレットを使用。
Windows95のインジケータ領域にアイコンを登録する
[New'97.6.10]
1.Windows APIのShell_NotifyIconを使用する。
ヘルプで「Adding and Deleting Taskbar Icons」を参照のこと。
// 作成したウインドウのアイコンをタスクバーに設定する #define WM_USER_TRY WM_USER+1 //ユーザメッセージ #define ID_SHL_ICON 1 NOTIFYICONDATA nid; memset( &nid, 0, sizeof( NOTIFYICONDATA ) ); nid.cbSize = sizeof(NOTIFYICONDATA); nid.hWnd = hwnd; //WM_USER_TRYを受け取るウィンドウ nid.uID = ID_SHL_ICON;//ID nid.uFlags = NIF_MESSAGE | NIF_ICON|NIF_TIP ; nid.uCallbackMessage = WM_USER_TRY;// 定義したユーザメッセージ nid.hIcon = hicon; // 登録したいアイコンのハンドル _tcscpy( nid.szTip, _T("ツールチップ") ); //登録したいツールチップ BOOL bret=::Shell_NotifyIcon( NIM_ADD, &nid ); // タスクバーからアイコンを消す #define WM_USER_TRY WM_USER+1 #define ID_SHL_ICON 1 NOTIFYICONDATA nid; memset( &nid, 0, sizeof( NOTIFYICONDATA ) ); nid.cbSize = sizeof(NOTIFYICONDATA); nid.hWnd = hwnd; nid.uID = ID_SHL_ICON; nid.uFlags = 0; BOOL bret=::Shell_NotifyIcon( NIM_DELETE, &nid ); // メニューを表示する #define WM_USER_TRY WM_USER+1 #define ID_SHL_ICON 1 switch( message ) { case WM_USER_TRY: if( lParam == WM_RBUTTONDOWN ) { // アイコン上で右クリック ::GetCursorPos( &point ); ::SetForegroundWindow( hWnd ); ::TrackPopupMenu( hMenu, TPM_BOTTOMALIGN | TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, 0, hWnd, NULL );//メニューを表示する } break; }
newではデフォルトでは例外は発生しない
[New'97.6.10]
newでメモリ不足が発生したとき、デフォルトでは例外は発生せず、0(NULL)が帰ってくる。
VC++のヘルプで「new」とか「_set_new_handler」を参照のこと。
リムーバブルメディアがFDかを判断する
[Update'00.1.19]
1.メディアタイプ情報を取得する。
(1)WindowsNTの場合
IOCTL_DISK_GET_MEDIA_TYPESを指定してDeviceIoControlを発行する。
DISK_GEOMETRY SupportedGeometry[20]; DWORD SupportedGeometryCount; HANDLE hDisk = CreateFile("\\\\.\\A:", 0, FILE_SHARE_READ, NULL,OPEN_ALWAYS,0,NULL); DeviceIoControl(hDisk, IOCTL_DISK_GET_MEDIA_TYPES, NULL,0, SupportedGeometry,sizeof(SupportedGeometry), &ReturnedByteCount, NULL) //Geometry[ ].MediaTypeで判断 SupportedGeometryCount = ReturnedByteCount / sizeof(DISK_GEOMETRY); for (i=0;i<SupportedGeometryCount ;i+;) {//そのドライブが支援しているメディアタイプ個数 switch ( Geometry[i].MediaType ) { case F5_1Pt2_512: MediaType = "5.25, 1.2MB, 512 bytes/sector"; break; case F3_1Pt44_512: MediaType = "3.5, 1.44MB, 512 bytes/sector"; break; case F3_2Pt88_512: MediaType = "3.5, 2.88MB, 512 bytes/sector"; break; case F3_20Pt8_512: MediaType = "3.5, 20.8MB, 512 bytes/sector"; break; case F3_720_512: MediaType = "3.5, 720KB, 512 bytes/sector"; break; case F5_360_512: MediaType = "5.25, 360KB, 512 bytes/sector"; break; case F5_320_512: MediaType = "5.25, 320KB, 512 bytes/sector"; break; case F5_320_1024: MediaType = "5.25, 320KB, 1024 bytes/sector"; break; case F5_180_512: MediaType = "5.25, 180KB, 512 bytes/sector"; break; case F5_160_512: MediaType = "5.25, 160KB, 512 bytes/sector"; break; case RemovableMedia: MediaType = "Removable media other than floppy"; break; case FixedMedia: MediaType = "Fixed hard disk media"; break; default: MediaType = "Unknown"; break; } } CloseHandle(hDisk);詳細は、VCのヘルプで「Getting Floppy Drive Information」を探して見てください。
#define VWIN32_DIOC_DOS_IOCTL 1 typedef struct _DEVIOCTL_REGISTERS { DWORD reg_EBX; DWORD reg_EDX; DWORD reg_ECX; DWORD reg_EAX; DWORD reg_EDI; DWORD reg_ESI; DWORD reg_Flags; } DEVIOCTL_REGISTERS, *PDEVIOCTL_REGISTERS; //int 21h 440Dh 60hのファンクションを使用して取得する。 DEVIOCTL_REGISTERS reg; //構造体はMSDNでDEVICEPARAMS,EA_DEVICEPARAMETERSで内容を //確認してください。 DEVICEPARAMS deviceparams; EA_DEVICEPARAMETERS exdeviceparams; //ブロックデバイスのデバイスパラメタを返す(int 21h 440Dh 60h) reg.reg_EAX = 0x440D; reg.reg_EBX = nDrive; //1=a:,2=b: //48h(OSR2の指定)で一度チェックして、NGなら08hで再度発行する。 //MSDN 440Dhで検索して60hの記述のままです。 reg.reg_ECX = 0x4860; reg.reg_EDX = (DWORD) &exdeviceparams; hDevice = CreateFile("\\\\.\\vwin32", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, (LPSECURITY_ATTRIBUTES) NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL); fResult = DeviceIoControl(hDevice, VWIN32_DIOC_DOS_IOCTL, preg, sizeof(*preg), preg, sizeof(*preg), &cb, 0); if (!fResult) { //エラーならOSR2ではない reg.reg_EAX = 0x440D; reg.reg_EBX = nDrive; reg.reg_ECX = 0x0860; //08hにして再発行 reg.reg_EDX = (DWORD) &deviceparams; fResult = DeviceIoControl(hDevice, VWIN32_DIOC_DOS_IOCTL, preg, sizeof(*preg), preg, sizeof(*preg), &cb, 0); if (fResult) { //deviceparams.bDevTypeで0,1,2,3,4,7,8ならFD //この値が何に対応しているかは不明です //MSDNの「How to Determine Drive Types in Windows」の //記述のままです。(Windows 3.1のKBですが) } } else { //exdeviceparams.bDevTypeで0,1,2,3,4,7,8ならFD //この値が何に対応しているかは不明です } CloseHandle(hDevice);VCのヘルプで「Calling DeviceIoControl on Windows 95」、MSDNで「How to Determine Drive Types in Windows」をクエリーで探して見てください。
追加('00.1.19 dioさんからの情報です。ありがとうございます) MSDNの「HOWTO: Getting Floppy Drive Type Information」から、 0: // 5.25 360K floppy 1: // 5.25 1.2MB floppy 2: // 3.5 720K floppy 3: // 8" low-density floppy 4: // 8" high-density floppy 5: // hard drive 6: // tape drive 7: // 3.5 1.44MB floppy 8: // optical disk 9: // 3.5 2.88MB floppy のようです。2.ドライブに対するエクスプローラのアイコンの番号を取得してみる。
タイトルを変更する
[New'97.5.31]
1.CWinApp::m_pszAppNameを変更してメッセージBOXのタイトルを変更する。
m_pszAppNameは文字列ポインタのため、新しいタイトルをCWinAppのメンバ変数で定義して、そのポインタを代入する。
2.SetWindowTextでCMainFrameのタイトルを変更する。
リアルモードのドライバを使用したCD−ROM等でのメモリマップドファイルの注意
[Update'97.6.10]
リアルモードのドライバがWindows95で拡張されたファイルの情報取得APIを
支援していないとき、4096BYTE以上をアクセスするとAPエラーとなる場合がある。
そのため、例外処理をする必要がある。
(ISO 9660形式のVIDEO CDをパラレル接続のSCSI CD/SoundBlaster経由のCD参照で発生した)
非矩形ウィンドウを作る
[New'97.5.31]
::SetWindowRgnでウィンドウの領域を指定する。
256色でのビットマップの表示
[New'97.5.31]
1.コンポーネントギャラリーでパレットサポートを挿入する。
2.WM_QUERYNEWPALETTE,WM_PALETTECHANGED[hWndが自分のウィンドウでないとき]
(問題があればWM_ACTIVATEAPP[自分がアクティブになったとき],WM_PAINTも)でRealizePaletteを行なう。
また、RealizePaletteの戻り値が0でないときは、InvalidateRectで再表示を行なう。(WM_PAINT以外)
256色のビットマップリソースの扱い
[New'97.5.31]
LoadResourceで直接参照する(LoadBitmapでは16色しか対応していない)
VC++ 4.0のヘルプで「Retrieving Palette Information from a Bitmap Resource」を参照のこと
bret=::PostMessage(hWnd,WM_SYSCOMMAND,SC_CLOSE,0L); 注意:終了させようとしているAPがメッセージBOXやダイアログを表示しているときは、 まず、メッセージBOX,ダイアログを閉じる必要がある。メインウィンドウに対して終了要求を行うと、 そのAPでアプリケーションエラーが発生する。
1.リソースのバージョン情報を変更する。 2.エクスプローラでEXEのプロパティでバージョン情報を確認する。
EXEのアイコンを指定する
リソースのアイコンの指定で
16x16
,32x32共に変更する。
16x16のアイコンを変更しないとエクスプローラの小さいアイコン・詳細表示のときMFCのアイコンが表示される。
カーソルを時計にする
1.時計にする。
(1)AfxGetApp()->DoWaitCursor(1);
2.元に戻す。
(1)AfxGetApp()->DoWaitCursor(-1);
ダイアログのアイテムの内容の設定、取得
1.初期値を入れる。
(1)ClassWizardでアイテムにメンバ変数を割り付ける。
(2)DoModal()を呼び出す前にメンバ変数に値を代入する。
2.設定値を参照する。
(1)OnOKを定義する。
(2)CDialog::OnOK()を先に呼んでからメンバ変数を参照する。(CDialog::OnOK()を呼ばないとメンバ変数に値が代入されません)
ダイアログベースアプリケーションのアイコンの指定
(1)16bitの場合
VC++ 1.5 MFCでダイアログベースのAPを作る場合はダイアログのクラスが#32770固定
であるために、SetClassWordでアイコンを指定すると他のダイアログベースのAP
(Windowsセットアップ等)とアイコンが同じになってしまいます。
これを回避するためには、#32770からクラスをサブクラスさせかつリソースファイルにCLASS
指定をします。(MSDN MSJ '95/5 Windows Q&A参考)
例
リソースファイル:
ICON_MYAPPLI DIALOG 54, 48, 300, 140
STYLE WS_OVERLAPPED | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
CLASS "ICON_MYAPPLI" //<---------------これが必要
CAPTION "XXXXXX"
ソース:
if ( !GetClassInfo( 0, MAKEINTRESOURCE(32770), &wndclass ) ) return 0; wndclass.hInstance = HInstance; wndclass.hIcon = LoadIcon(HInstance,"ICON_MYAPPLI"); wndclass.lpszClassName = "ICON_MYAPPLI"; //<---リソースファイルのCLASSと合わせる if ( !RegisterClass(&wndclass) ) return 0;(2)32bitの場合
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { // TODO: この位置で CREATESTRUCT cs を修正して、Window クラスやスタイルを // 修正してください。 cs.style ^= FWS_ADDTOTITLE; return CFrameWnd::PreCreateWindow(cs); }
タイトルをプロジェクト名と違うものにする
(1)プロジェクトワークスペースを新規作成するときMFC AppWizard ステップ 4/6で高度な設定で
メインフレームのキャプション
を書き換える。
(2)リソースファイルのStringTableの
IDR_MAINFRAME
と
AFX_IDS_APP_TITLE
を書き換える。
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) { // TODO: この位置に固有の処理を追加するか、または基本クラスを呼び出してください SetMenu(NULL); BOOL bret=CFrameWnd::OnCreateClient(lpcs, pContext); return bret; }
void CMainFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) { // TODO: この位置にメッセージ ハンドラ用のコードを追加するかまたはデフォルトの処理を呼び出してください CFrameWnd::OnGetMinMaxInfo(lpMMI); //必ずデフォルトの処理を先に行う lpMMI->ptMinTrackSize.x=最小の幅; lpMMI->ptMinTrackSize.y=最小の高さ; lpMMI->ptMaxTrackSize.x=最大の幅; lpMMI->ptMaxTrackSize.y=最大の高さ; }
BOOL CXXXXApp::InitInstance() { //* プログラムの複数起動抑止 HWND hWndCap,hWndPopup; CString strCaption; HANDLE hPrevMutex = OpenMutex(MUTEX_ALL_ACCESS,FALSE,_T("h_XXXX_PrevInstance"));//プログラムで一意的な文字列 if(hPrevMutex) //* もし、オープンできれば以前のアプリケーションが起動している { CloseHandle(hPrevMutex); //* クローズ strCaption.LoadString(AFX_IDS_APP_TITLE); hWndCap = FindWindow(NULL,strCaption); //* APのハンドル取得 if( hWndCap != NULL ){ //* アクティブ化 } return FALSE; //* 終了 } hExeCheckMutex = CreateMutex(FALSE,0,"h_XXXX_PrevInstance");//* 複数起動確認用ミューテックス作成 //以下省略 return TRUE; } int CXXXXApp::ExitInstance() { ReleaseMutex(hExeCheckMutex); //* Mutexを開放
return CWinApp::ExitInstance(); }
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) { // TODO: この位置に固有の処理を追加するか、または基本クラスを呼び出してください CMenu *sysmenu=GetSystemMenu(FALSE); sysmenu->AppendMenu(MF_SEPARATOR); sysmenu->AppendMenu(MF_STRING,ID_APP_ABOUT,_T("バージョン情報(&A)...")); bret=CFrameWnd::OnCreateClient(lpcs, pContext); return bret; } void CMainFrame::OnSysCommand(UINT nID, LPARAM lParam) { // TODO: この位置にメッセージ ハンドラ用のコードを追加してください if (nID==ID_APP_ABOUT) OnAppAbout(); else CFrameWnd::OnSysCommand(nID,lParam); }
Docと関係なしにエクスプローラからDropされたファイル名を読み込む
[Update'98.6.28]
BOOL CXXXXApp::InitInstance() { //途中省略 // ドラッグ/ドロップ オープンを許可します m_pMainWnd->DragAcceptFiles(); return TRUE; } void CMainFrame::OnDropFiles(HDROP hDropInfo) { // TODO: この位置にメッセージ ハンドラ用のコードを追加するかまたはデフォルトの処理を呼び出してください UINT filecnt; UINT usize; UINT i; char buf[MAX_PATH+1]; int pos; CXXXXView *lview=(CXXXXView *)GetActiveView(); filecnt=::DragQueryFile(hDropInfo,0xffffffff,buf,sizeof(buf)-1);//Dropされたファイル数を取得 for (i=0;i<filecnt;i++) { usize=::DragQueryFile(hDropInfo,i,buf,sizeof(buf)-1);//Dropされたファイル名を取得 //ファイル名を保存する処理 } ::DragFinish(hDropInfo); // CFrameWnd::OnDropFiles(hDropInfo);//これを実行するとドキュメント名に反映される }
一つのソースで英語対応を行う
[Update'97.6.28]
1.文字列を全てリソースファイルのStringTableに登録し、リソースを参照するようにする。
2.リソースファイルのStringTableでStringTableをコピーの複写でコピーしそのとき、言語を英語(アメリカ)と指定する。
3.リソースファイルのダイアログ、バージョン情報、メニューをコピーの複写でコピーしそのとき、言語を英語(アメリカ)と指定する。
EXEを1つの言語のみ専用にするときは
条件を日本語と英語で異なるマクロを指定する。(例 日本語:_LANG_JP、英語:_LANG_US)
このとき、クラスウィザードでボタン等へのメンバ変数割り当ては、マクロを指定する前に行う。
(クラスウィザードに出てこなくなる。その場合は、一度マクロの指定を解除する。)
4.プロジェクトの設定でリソースで言語を英語(U.S.)と指定する。また、3.で指定したマクロ名を定義する。
5.
EXEを1つの言語のみ専用にするときは
(たとえば英語)ビルドするときに、StringTableのデフォルトを日本語以外にし、ビルド後日本語に戻す。
日本語以外にしたときは、StringTableを開かず、また絶対に保存しないこと。(日本語が全て?に化けます)
CListViewでカラムにアイコンを表示する
[Update'97.11.25]
1.CListViewから派生クラスを作成する
2.ClistViewのCreateで
LVS_OWNERDRAWFIXED
を指定する。
int CXXXXListView::OnCreate(LPCREATESTRUCT lpCreateStruct) { lpCreateStruct->style |= LVS_REPORT | LVS_OWNERDRAWFIXED | LVS_NOSORTHEADER; //.レポートビューを指定 if (CListView::OnCreate(lpCreateStruct) == -1){ //.リストビューのOnCreateをコール return -1; } return 0; } void CXXXXListView::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { CListCtrl& ctlList = (CListCtrl&) GetListCtrl(); //.リストへの参照取得 CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); //途中省略 return; }