ホーム » MFC (ページ 8)
「MFC」カテゴリーアーカイブ
コントロールをサブクラス化した時のエラー
ダイアログのコントロールをサブクラス化した時の実行時エラーの対応.
m_ListXxx.SubclassDlgItem(IDC_Xxxx_LIST,this) ;
—————————
Microsoft Visual C++ Debug Library
—————————
Debug Assertion Failed!
Program: …\Xxxx\Xxxx\Debug\Xxxx.exe
File: wincore.cpp
Line: 321
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
(Press Retry to debug the application)
—————————
中止(A) 再試行(R) 無視(I)
—————————
以前 CListBox として使用していたので,変数として割り付けられていた.
変数を削除してOK.
画像付 RecentFile の追加
RecentFileMF クラスを利用して,画像でのメニュー表示を可能にする
- ODMenu を利用可能な様に追加する.
アプリケーションクラスのヘッダなどで MetaFile.hxx をインクルードして,ODMMetaFile を利用可能に. - ID_RECENT_FILE_00 ~ の必要数分のリソースを作成する.
- アプリケーションクラスのヘッダに,include と変数を追加する.
#include "RecentFM.hxx"
RecentFileMF RcntFM ; - アプリケーションクラスのコンストラクタに RecnetFileMF の初期化を追加する.
: RcntFM(_T("RecentFileMF"),30) - InitInstance で,RcntFM のデータを読込む処理を追加する.
{
RcntFM.Read() ;
RcntFM.SetStartID(ID_RECENT_FILE_00) ;
} - アプリケーションクラスに,範囲でコマンドハンドラを追加する.
ON_COMMAND_RANGE (ID_RECENT_FILE_00,ID_RECENT_FILE_29,OnRecentFile)
void CXxxxApp::OnRecentFile(UINT nID)
{
CString selFile = RcntFM.GetSelectFile(nID) ;
AfxGetApp()->OpenDocumentFile(selFile) ;
} - ドキュメントクラスのファイルの読み書きの時に,次の様にドキュメントと対応する画像を指定する.
{
CXxxxApp* app = (CXxxxApp*)AfxGetApp() ;
app->RcntFM.Add(fileName,emfName) ;
}
- さらに,ドキュメントに対するファイル名をステータスバーなどに表示するために,CMainFrame に追加する.
// ツールチップの表示データの更新
BOOL CMainFrame::OnToolTipText(UINT id, NMHDR *pNMHDR, LRESULT *pResult)
{
BOOL ret = CFrameWnd:: OnToolTipText(id,pNMHDR,pResult) ;
Prompt:: OnToolTipText(id,pNMHDR,pResult) ;
return ret ;
}
// ステータスバーの表示データの更新
void CMainFrame::GetMessageString(UINT nID, CString &rMessage) const
{
CFrameWnd:: GetMessageString(nID,rMessage) ;
Prompt:: GetMessageString(nID,rMessage) ;
}
2012/06/12 追記
VC6 でドロップタウンが有効にならない場合,CBRS_SIZE_DYNAMIC を外す.
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | …
… | CBRS_FLYBY/* | CBRS_SIZE_DYNAMIC*/) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
ODMenu が有効にならない場合,
#include “ODMenu.hxx”
#include “WinMFC.cxx”
Prompt が有効にならない場合,
#include “Prompt.hxx”
#include “RecentFM.cxx”
ODMenu は有効ではあるが,何も表示されない
手動で追加していたため,メッセージマップの修正漏れ
ON_WM_MEASUREITEM()
ON_WM_DRAWITEM()
2019/09/20
OnMeasureItem , OnDrawItem が呼ばれない.
内部的には ODMenu::ModifyMenu が呼ばれていない.
WinMFC.cxx を読み込む前に ODMenu.hxx が必要.
App.h 内の include の最後辺りに ODMenu.hxx の追加で対応可能.
ツールバーにドロップダウンボタン
ツール バー コントロールでのドロップダウン ボタンの使い方
http://msdn.microsoft.com/ja-jp/library/1ke6s1fc.aspx
上の方法だけでは,MFC のバージョンによりうまく動作しないので…
ToolBar.hxx
BOOL ToolBar::SetStyleDropDown (CToolBar* toolBar,int commandID)
MFC 6 では,CBRS_SIZE_DYNAMIC を無効にして.Create する必要あり.
2024/07/30
次を追加して,ドロップダウンにならなかった.
{
ToolBar::SetStyleDropDown(&m_wndToolBar, ID_EDIT_UNDO) ;
ToolBar::SetStyleDropDown(&m_wndToolBar, ID_EDIT_REDO) ;
}
原因は CBRS_SIZE_DYNAMIC が無効になっていなかったため.
if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY
/* | CBRS_SIZE_DYNAMIC */
) ||
!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}
ファイルを選択した状態で explorer.exe
explorer.exe /select,c:~exmple.txt
http://support.microsoft.com/kb/314853/ja
https://www.betaarchive.com/wiki/index.php?title=Microsoft_KB_Archive/314853
void CXxxxDoc::OnExecExplorer()
{
CString docName = GetPathName() ;
ShellExec se ;
se.SetNon2QMark(TRUE) ;
se.SetFile(_T("explorer.exe")) ;
se.SetParamaters(_T("/e,/select,")+docName) ;
se.Execute() ;
}
CChildFrame を最大化して表示
MDI の新規ウィンドウで ChildFrame を最大化して表示
BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs) { cs.style = WS_CHILD | WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | FWS_ADDTOTITLE | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_MAXIMIZE; if( !CMDIChildWnd::PreCreateWindow(cs) ) { return FALSE; } return TRUE; }
分割ウィンドウ CSplitterWnd
MDI 分割ウィンドウ
ChildFrm.cpp 内の CChildFrame::OnCreateClient で分割数などを指定している.
SDI は,CMainFrame::OnCreateClient
静的分割ウィンドウ
OnCreateClient 内のコードを書き換える.
/* // コメント部分はスケルトンで生成されたもの
return m_wndSplitter.Create( this,
2, 2, // TODO: 行と列の数を調整してください。
CSize( 10, 10 ), // TODO: 最小の区画サイズを調整してください。
pContext );
*/
if (!m_wndSplitter.CreateStatic(this,1,2)) {
return FALSE ;
}
if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CLeft_View), CSize(150, 100), pContext) ||
!m_wndSplitter.CreateView(0, 1, RUNTIME_CLASS(CRightView), CSize(100, 100), pContext)) {
m_wndSplitter.DestroyWindow(); // この部分は,どこに書かれていたか不明
return FALSE;
}
return TRUE ;
CString で保存される形式
UNICODE | FF FE FF | 04 | 32 00 | 30 00 | 31 00 | 30 00 |
MBCS | 04 | 32 | 30 | 31 | 30 |
// VC98\MFC\SRC\ArcCore.cpp
// CString serialization code
// String format:
// UNICODE strings are always prefixed by 0xff, 0xfffe
// if < 0xff chars: len:BYTE, TCHAR chars
// if >= 0xff characters: 0xff, len:WORD, TCHAR chars
// if >= 0xfffe characters: 0xff, 0xffff, len:DWORD, TCHARs
CArchive& AFXAPI operator<<(CArchive& ar, const CString& string)
{
// special signature to recognize unicode strings
#ifdef _UNICODE
ar << (BYTE)0xff;
ar << (WORD)0xfffe;
#endif
if (string.GetData()->nDataLength < 255) {
ar << (BYTE)string.GetData()->nDataLength;
}
else if (string.GetData()->nDataLength < 0xfffe) {
ar << (BYTE)0xff;
ar << (WORD)string.GetData()->nDataLength;
}
else {
ar << (BYTE)0xff;
ar << (WORD)0xffff;
ar << (DWORD)string.GetData()->nDataLength;
}
ar.Write(string.m_pchData, string.GetData()->nDataLength*sizeof(TCHAR));
return ar;
}
ビューのそのままを 1 ページに印刷
{
CXxxxDoc* pDoc = GetDocument();
CRect drawRect ;
GetClientRect(drawRect) ;
pDoc->Object.Draw(pDC,drawRect,…) ;
}
CXxxxView::OnPrint を追加.
void CXxxxView::OnPrint(CDC* pDC, CPrintInfo* pInfo)
{
CXxxxDoc* pDoc = GetDocument();
CRect drawRect ;
drawRect = pInfo->m_rectDraw ;
pDoc->Object.Draw(pDC,drawRect,…) ;
// CView::OnPrint(pDC, pInfo);
}
StringArrayToString と VC
以下のコードで,VC のそれぞれのバージョン,32 ビット MBCS/UNICODE で約 1 M 文字の変換を計測
BOOL O_StringArrayToString(const CStringArray& strAry,CString& str,const CString& sp=_T("rn"))
{
for (int lineCount=0 ; lineCount<strAry.GetSize() ; lineCount++) {
str += strAry.GetAt(lineCount) ;
if (str.Right(sp.GetLength()) != sp) {
str += sp ;
}
}
return TRUE ;
}
1+2 x 333,333 999,999 文字 |
10+2 x 83,333 999,996 文字 |
100+2 x 9,803 999,906 文字 |
1,000+2 x 998 999,996 文字 |
||
VC 6.0 | MB | 351.205 | 88.576 | 9.984 | 0.962 |
VC 7.0 | MB | 0.351 | 0.280 | 0.231 | 0.210 |
VC 7.1 | MB | 0.351 | 0.290 | 0.240 | 0.230 |
VC 8.0 | MB | 0.340 | 0.250 | 0.220 | 0.231 |
VC 9.0 | MB | 0.360 | 0.240 | 0.240 | 0.201 |
VC 10. | MB | 0.090 | 0.020 | 0.000 | 0.000 |
VC 6.0 | WC | 936.567 | 228.458 | 25.857 | 2.584 |
VC 7.0 | WC | 1.342 | 1.281 | 1.252 | 1.261 |
VC 7.1 | WC | 1.462 | 1.282 | 1.252 | 1.272 |
VC 8.0 | WC | 1.392 | 1.281 | 1.252 | 1.242 |
VC 9.0 | WC | 1.382 | 1.322 | 1.302 | 1.232 |
VC 10. | WC | 0.080 | 0.020 | 0.010 | 0.010 |
VC 10 は,ほとんど無視できる速度.
VC 7 ~ VC 9 は,UNICODE exe で少し時間がかかる.
VC 6 exe では,ループの回数にかなり影響を受ける
(恐らく領域の割り当ての関係と思われる).
また,CString のサイズが大きくなる(ループの lineCount が大きくなる)程,遅くなった.
綺麗なコードでないが,~ VC 9 の場合に置き換える
BOOL N_StringArrayToString(const CStringArray& strAry,CString& str,const CString& sp=_T("rn"))
{
CStringArray tmpSA ;
CString tmpStr ;
for (int lineCount=0 ; lineCount<strAry.GetSize() ; lineCount++) {
tmpStr += strAry.GetAt(lineCount) ;
if (tmpStr.Right(sp.GetLength()) != sp) {
tmpStr += sp ;
}
if ((lineCount%100-1) == 0) {
tmpSA.Add(tmpStr) ;
tmpStr.Empty() ;
}
}
if (!tmpStr.IsEmpty()) {
tmpSA.Add(tmpStr) ;
}
if (tmpSA.GetSize() > 1) {
::N_StringArrayToString(tmpSA,str,sp) ;
}
else if (tmpSA.GetSize() == 1) {
str = tmpSA[0] ;
}
else {
return FALSE ;
}
return TRUE ;
}
…/Test/TsSAtoS.zip
「無効な引数が発生しました。」
MFC 7.1 以降,AfxThrowInvalidArgException が呼ばれるようになっている
C:\Program Files\Microsoft Visual Studio\VC98\MFC\Include\AfxColl.inl Line 96
_AFXCOLL_INLINE DWORD& CDWordArray::ElementAt(int nIndex)
{ ASSERT(nIndex >= 0 && nIndex < m_nSize);
return m_pData[nIndex]; }
C:\Program Files\Microsoft Visual Studio 8\VC\atlmfc\include\AfxColl.inl Line 126
_AFXCOLL_INLINE DWORD& CDWordArray::ElementAt(INT_PTR nIndex)
{ ASSERT(nIndex >= 0 && nIndex < m_nSize);
if( nIndex < 0 || nIndex >= m_nSize )
AfxThrowInvalidArgException();
return m_pData[nIndex]; }
—————————
App
—————————
無効な引数が発生しました。
—————————
OK
—————————
nIndex が配列の範囲を超えている場合に ASSERT .
2010/06/15 追記
VC8 AtlSimpStr.h Line 389
XCHAR operator[]( __in int iChar ) const
{
ATLASSERT( (iChar >= 0) && (iChar <= GetLength()) ); // Indexing the ” is OK
if( (iChar < 0) || (iChar > GetLength()) )
AtlThrow(E_INVALIDARG);
return( m_pszData[iChar] );
}
—————————
App
—————————
パラメータが間違っています。
—————————
OK
—————————
Visual Style を無効に
ダイアログ上のボタンなどの Visual Style を無効に
BOOL DisableVisualStyle (CWnd* wnd)
//************************************************************************************************** // ファイル名 :HelpVSty.hxx // 機能名 :ビジュアルスタイルヘルパ Visual Style 関数の簡略化 // 作成者 : // 作成年月日 :’09/07/02 // 変更履歴 :’09/07/02 //************************************************************************************************** #ifndef _INC_H_HELP_THEME_API #define _INC_H_HELP_THEME_API #include <AfxWin.h> //******************************************************************************* // 関数名 :SetWindowTheme // 作成日 :’09/07/02 //******************************************************************************* inline HRESULT Hlp_SetWindowTheme (HWND hwnd,LPCWSTR pszSubAppName,LPCWSTR pszSubIdList) { HMODULE hDll = ::LoadLibrary(_T("UxTheme.dll")) ; if (hDll == NULL) { return !S_OK ; } HRESULT (WINAPI *pfSetWindowTheme)(HWND,LPCWSTR,LPCWSTR) = NULL ; (FARPROC&)pfSetWindowTheme = ::GetProcAddress(hDll,("SetWindowTheme")) ; HRESULT res = !S_OK ; if (pfSetWindowTheme != NULL) { res = pfSetWindowTheme(hwnd,pszSubAppName,pszSubIdList) ; } ::FreeLibrary(hDll) ; return res ; } //******************************************************************************* // 関数名 :Visual Style を OFF に // 作成日 :’09/07/02 //******************************************************************************* inline BOOL DisableVisualStyle (CWnd* wnd) { if (wnd == NULL) { return FALSE ; } if (wnd->m_hWnd == NULL) { return FALSE ; } #ifdef __ATLBASE_H__ { // コモンコントロールのバージョンをチェック DWORD ccMajor = 0 ; DWORD ccMinor = 0 ; AtlGetCommCtrlVersion(&ccMajor,&ccMinor) ; if (ccMajor < 6) { return TRUE ; } } #endif HRESULT res = !S_OK ; res = ::Hlp_SetWindowTheme(wnd->GetSafeHwnd(), L" ", L" ") ; return (res == S_OK) ; } #endif
コンボボックスの高さ指定
//******************************************************************************* // 関数名 :コンボボックスの高さを,親ウィンドウの下に合わせる // 作成日 :’09/07/01 //******************************************************************************* #ifndef CBM_FIRST // C:Program Files (x86)Microsoft SDKsWindowsv7.0AIncludeCommCtrl.h #define CBM_FIRST 0x1700 // Combobox control messages #define CB_SETMINVISIBLE (CBM_FIRST + 1) #define CB_GETMINVISIBLE (CBM_FIRST + 2) #define CB_SETCUEBANNER (CBM_FIRST + 3) #define CB_GETCUEBANNER (CBM_FIRST + 4) #endif BOOL FitDropHeight (CComboBox* ctrl,CWnd* parent) { if (ctrl == NULL) { return FALSE ; } if (ctrl->m_hWnd == NULL) { return FALSE ; } CRect tRect ; ctrl->GetWindowRect (&tRect) ; parent->ScreenToClient(&tRect) ; CRect pRect ; parent->GetClientRect(&pRect) ; tRect.bottom= pRect.bottom ; ctrl->MoveWindow(&tRect) ; // ここから上は,Visual Style が無効な exe の時に動作する { // ここから下は,Visual Style が有効な場合に必要 MoveWindow では変更されない? int minV = tRect.Height()/ctrl->GetItemHeight(0) ; if (minV >= 3) { minV-= 2 ; } if (minV <= 0) { minV = 1 ; } ctrl->SendMessage(CB_SETMINVISIBLE,minV) ; } return TRUE ; }
CB_SETCUEBANNER
CComboBox::SetCueBanner
Windows Vista コントロールの拡張
Windows Vista コモン コントロールの作成要件
サポートされなくなった ANSI API
CCriticalSection と CMutex
P4 | VirtualPC | Xeon | |
CCriticalSection | 734 | 160 | 94 |
*1 | 78 | 20 | 15 |
CMutex | 8200 | 710 | 1140 |
*1 | 950 | 250 | 437 |
Profile INI | 2900 | 950 | 920 |
Reg | 2100 | 570 | 740 |
ElapseTick et_cs ;
{
CCriticalSection cs ;
for (int index=0 ; index<500000 ; index++) {
//CCriticalSection cs ;
cs.Lock() ;
cs.Unlock() ;
}
}
DWORD e_cs = et_cs.GetElapse() ;
ElapseTick et_me ;
{
CMutex mt ;
for (int index=0 ; index<500000 ; index++) {
mt.Lock() ;
mt.Unlock() ;
}
}
DWORD e_me = et_me.GetElapse() ;
ElapseTick et_pr ;
{
Profile profile ;
for (int index=0 ; index<500000 ; index++) {
int data = profile.GetInt(_T("Test"),_T("Test"),100) ;
}
}
DWORD e_pr = et_pr.GetElapse() ;
MFC Static → DLL
MFC を「スタティック ライブラリ」から「共有 DLL」に変更した時,以下のエラーになることがある.
—— ビルド開始: プロジェクト: Project , 構成: Release Win32 ——
コンパイルしています…
StdAfx.cpp
C:Program FilesMicrosoft Visual Studio 8VCatlmfcincludeafx.h(24) : fatal error C1189: #error : Building MFC application with /MD[d] (CRT dll version) requires MFC shared dll version. Please #define _AFXDLL or do not use /MD[d]
Project – エラー 1、警告 0
========== ビルド: 0 正常終了、1 失敗、0 更新、0 スキップ ==========
*.vcproj をエディタで開き,"$(NoInherit)" を削除.
2010/04/21 追記
—— ビルド開始: プロジェクト: Project , 構成: Release Win32 ——
StdAfx.cpp
C:Program Files (x86)Microsoft Visual Studio 10.0VCatlmfcincludeafxver_.h(81): fatal error C1189: #error : Please use the /MD switch for _AFXDLL builds
========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========
プロジェクトの「プロパティ」-「構成プロパティ」-「C/C++」-「コード生成」-「ランタイムライブラリ」
マルチスレッド (/MT) → マルチスレッド DLL (/MD)
2021/06
https://dev.mish.work/wordpress/2021/01/23/vc-12-lnk1104-vc14-2-lnk2019/
https://dev.mish.work/wordpress/2021/04/01/change-mfc-static-error/