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;
}