ホーム » MFC (ページ 7)

MFC」カテゴリーアーカイブ

2024年4月
 123456
78910111213
14151617181920
21222324252627
282930  

カテゴリー

アーカイブ

ブログ統計情報

  • 80,212 アクセス



WM_MOUSE??? ,WM_?BUTTON???

マウス関係のイベントを表示するコードと exe

手元のマウスでは,zDelta は 120
CTH-460 では,16 や 5
VirtualPC 内では統合機能を有効にしないとうまくイベントが上がらない.

以下の様なコードになっていたので,zDelta が 120 より小さい時は効果がなかった.
short zDelta= (short)HIWORD(msg->wParam) ;
int count = abs(zDelta)/120 ;
for (int index=0 ; index<count ; index++) {
  if (zDelta < 0) { … }
  else     { … }
  }

zDelta に対して,ある値をかけて 120 で割る様な操作が必要
ViewScrl.cpp より
int nToScroll = ::MulDiv(-zDelta, uWheelScrollLines, WHEEL_DELTA);

short zDelta= (short)HIWORD(msg->wParam) ;
double ratio = … ; // 1.4
ratio = (ratio-1.)*abs(zDelta)/WHEEL_DELTA ;
ratio += 1.0 ;

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

CEdit::SetSel である位置を選択

SetSel を UpdateData(FALSE) の呼び出しより後に使用すれば良い.
UpdateData(TRUE) ;

// 例えば文字列の最後へ
int pos = m_SelectStr.GetLength() ;
m_CtrlSelectStr.SetSel (pos,pos) ;

// UpdateData(FALSE) ;
または,UpdateData を使用しないで取得,更新する.
CEdit::Setsel の使い方

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

コントロールをサブクラス化した時のエラー

ダイアログのコントロールをサブクラス化した時の実行時エラーの対応.
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.

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

画像付 RecentFile の追加

RecentFileMF クラスを利用して,画像でのメニュー表示を可能にする

  1. ODMenu を利用可能な様に追加する.
    アプリケーションクラスのヘッダなどで MetaFile.hxx をインクルードして,ODMMetaFile を利用可能に.
  2. ID_RECENT_FILE_00 ~ の必要数分のリソースを作成する.
  3. アプリケーションクラスのヘッダに,include と変数を追加する.
    #include "RecentFM.hxx"
    RecentFileMF RcntFM ;
  4. アプリケーションクラスのコンストラクタに RecnetFileMF の初期化を追加する.
    : RcntFM(_T("RecentFileMF"),30)
  5. InitInstance で,RcntFM のデータを読込む処理を追加する.
    {
     RcntFM.Read() ;
     RcntFM.SetStartID(ID_RECENT_FILE_00) ;
     }
  6. アプリケーションクラスに,範囲でコマンドハンドラを追加する.
    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) ;
     }
  7. ドキュメントクラスのファイルの読み書きの時に,次の様にドキュメントと対応する画像を指定する.
    {
     CXxxxApp* app = (CXxxxApp*)AfxGetApp() ;
     app->RcntFM.Add(fileName,emfName) ;
     }
  8. さらに,ドキュメントに対するファイル名をステータスバーなどに表示するために,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 の追加で対応可能.

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

ツールバーにドロップダウンボタン

ツール バー コントロールでのドロップダウン ボタンの使い方
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 する必要あり.
ツールバーにドロップダウンボタンを追加

ToolBar.hxx

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

ファイルを選択した状態で 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() ;
 }


ShellExc.hxx , ShellExc.cxx


S_Exec.hxx

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

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;
  }
Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

分割ウィンドウ 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 ;

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

CString で保存される形式

BOM — U+FEFF

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

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

ビューのそのままを 1 ページに印刷

CXxxxView::OnDraw が以下の様な場合,それを単純にプリンタに送る
{
  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);
  }

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

ドキュメントのダブルクリックを無効に

ドキュメントのファイルタイプを指定してスケルトンを作成した場合
CXxxxApp::InitInstance 内の以下をコメントに
 // EnableShellOpen();
 // RegisterShellFileTypes(TRUE);

後から,ドキュメントタイプを指定する場合
リソースの StringTable の対応するドキュメント文字列を変更する.

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

MDI , SDI へのドロップの追加

CXxxxApp::InitInstance のメインフレームを作成した後に,以下を追加.
 m_pMainWnd->DragAcceptFiles();

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

起動時に MDI 子ウィンドウを表示しない

起動時に MDIチャイルドウインドウを表示させない
CXxxxApp::InitInstance の ParseCommandLine(cmdInfo); の後に
if (cmdInfo.m_nShellCommand == CCommandLineInfo::FileNew) {
  cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing ;
  }

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

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

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

「無効な引数が発生しました。」

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  
—————————

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

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

HelpVSty.hxx
HelpVSty.hxx

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

CStatic をはみ出さない様に

ダイアログ上の CStatic をはみ出さない様に描画する

CDC::IntersectClipRect 

   ...
   CClientDC dc(&m_Image) ;
   CRect  rect ;
   m_Image.GetClientRect(rect) ;
   dc.IntersectClipRect(rect) ;
   ...
Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

コンボボックスの高さ指定

//*******************************************************************************
//	関数名	:コンボボックスの高さを,親ウィンドウの下に合わせる
//	作成日	:’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

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

DDX/DDV の順番を…

順番をいじってしまうと,入力中の最大チェックが働かなかったり,値の修正ができない様になってしまう.

 DDX_Text     (pDX, IDC_TEXT_1 , m_Text1);
 DDV_MaxChars (pDX,    m_TEXT1 , 25);
 DDX_Text     (pDX, IDC_TEXT_2 , m_Text2);
 DDV_MaxChars (pDX,    m_TEXT2 , 25);
Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

CCriticalSection と CMutex

それぞれ,500,000 回呼出した時間 (m sec) 

      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() ;

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.