Iwao Dev

気付いたことをメモしています.

この画面は、簡易表示です

MFC

MFC ドキュメントの関連付け

スケルトン作成時,ファイルの拡張子を指定しなかったプロジェクトに,後から関連付けのコードを追加する手順.


アプリケーションクラスの InitInstance に EnableShellOpen と RegisterShellFileTypes を追加.

BOOL CXxxxApp::InitInstance()
{
	//	...
	AddDocTemplate(pDocTemplate);

	// DDE Execute open を使用可能にします。
	EnableShellOpen();  
	RegisterShellFileTypes(TRUE);  

	// DDE、file open など標準のシェル コマンドのコマンドラインを解析します。
	CCommandLineInfo cmdInfo;
	ParseCommandLine(cmdInfo);

	//	...

	// メイン ウィンドウが初期化されたので、表示と更新を行います。
	m_pMainWnd->ShowWindow(SW_SHOW);
	m_pMainWnd->UpdateWindow();

	// ドラッグ/ドロップ オープンを許可します
	m_pMainWnd->DragAcceptFiles();  

	return TRUE;
	}

必要に応じて,DragAccesptFiles .


リソースの String Table IDR_MAINFRAME で,ファイルタイプと拡張子を指定する.
文字列は 7 つに区切られている.CDocTemplate::GetDocString
CDocTemplate DocStringIndex


最近の Windows は,RegisterShellFileTypes では登録できない.
そのため,自前の RegFileType::SetFileType(TRUE) を呼出す.
RegFType.hxx RegFType.cxx
RegisterShellFileTypes とは違い,HKEY_CURRENT_USER\Software\Classes\ に登録している.

この投稿は役に立ちましたか? 役に立った 役に立たなかった 0 人中 0 人がこの 投稿 は役に立ったと言っています。

  にほんブログ村 IT技術ブログへ

  • カテゴリー:

スタティック ライブラリで MFC …

「共有 DLL で MFC を使う」にしていたプロジェクトを「スタティック ライブラリで MFC を使用する」に変更.
ビルドして実行すると起動時エラーに.
MFC をスタティックリンクした exe でうまく動作しない
VC 6 から順にあげてきたプロジェクトで,設定がうまく引き継がれていない.
個々のソースなどは変更した が,それだけでは足りないみたい.
プロジェクトの設定で「リソース」の「プリプロセッサの定義」に _AFXDLL が定義されてしまっている.
「<親またはプロジェクトの既定値から継承>」に
<親またはプロジェクトの既定値から継承>」に変更してうまく動作する様になった.


MDI.exe では,起動時にはエラーにならない.
印刷プレビューなどを実行するとエラーになる.
MDI exe _AFXDLL が合ってない時,実行時エラー

この投稿は役に立ちましたか? 役に立った 役に立たなかった 0 人中 0 人がこの 投稿 は役に立ったと言っています。

  にほんブログ村 IT技術ブログへ


MFC 起動時のドキュメントの変更

ドキュメントのドロップ時のファイル名の変更 には対応したが,今度は起動時のドキュメントの変更.
InitInstance の所をデバッガで追いかけると,CWinApp::ProcessShellCommand の前後で対応できそう.
CWinApp::ProcessShellCommand
次の様に,対象のファイルを変更して起動できることは確認.

	CCommandLineInfo cmdInfo;
	ParseCommandLine(cmdInfo);
	{
		if (cmdInfo.m_nShellCommand == CCommandLineInfo::FileOpen) {
			cmdInfo.m_strFileName = ::Path_ChangeExt(cmdInfo.m_strFileName,_T("ig3")).c_str() ;
			}
		}
	if (!ProcessShellCommand(cmdInfo))
	//	...
この投稿は役に立ちましたか? 役に立った 役に立たなかった 0 人中 0 人がこの 投稿 は役に立ったと言っています。

  にほんブログ村 IT技術ブログへ

  • カテゴリー:

SDI exe でファイルのドロップ

SDI exe でファイルをドロップされた時,関連する異なるファイルを開きたくなった.
次の様に,変換済みのデータが存在している時はそれを対象とする.
https://mish.myds.me/wordpress/dev/2021/03/03/win-prevent-2nd/


ドキュメントクラスの OnOpenDocument で変更するのは可能だが「MRU ファイル リスト」に残ってしまう.


15 年位前に,ブラウザからリンクをドロップして動作させるコードを書いた.
最近のブラウザでは,当時の様な操作はできないみたい.
WM_DROPFILES でリンクのテキストが取れたのだったと思う.
この時,何を参考にしてここにたどり着いたかは不明.
それを見ると CMainFrame::OnDropFiles にコードが書いてある.
デフォルトのコードとしては,CFrameWnd::OnDropFiles を呼出している.
CFrameWnd::OnDropFiles
::DragQueryFile でファイル名を取って CWinApp::OpenDocumentFile を呼出している.


CMainFrame::OnDropFiles でファイル名を取った後,処理を追加して CWinApp::OpenDocumentFile を呼べば良い.
手順としては (VC)\…\atlmfc\src\mfc\winfrm.cpp の CMainFrame::OnDropFiles をコピーして編集している.

void CMainFrame::OnDropFiles(HDROP hDropInfo) 
{
	SetActiveWindow();      // activate us first !
	CWinApp* pApp = AfxGetApp();
	ASSERT(pApp != NULL);
	v_tstring	files = ::DropFilesTo(hDropInfo) ;
	if (files.size() > 0) {
		tstring	file = files[0] ;
	//	ここで,必要に応じてファイル名を変更するなどの処理
		pApp->OpenDocumentFile(file.c_str()) ;
		}
	::DragFinish(hDropInfo);
//	CFrameWnd::OnDropFiles(hDropInfo);
	}

今回は SDI なのでこんな感じ.MDI であればループで回せば良い.

この投稿は役に立ちましたか? 役に立った 役に立たなかった 0 人中 0 人がこの 投稿 は役に立ったと言っています。

  にほんブログ村 IT技術ブログへ


MBCS_Support_Deprecated_In_MFC

最初 VC 6 で作成したプロジェクト.VC 8 までは順にあげてあった.これをさらに VC 14.x まであげたもの.
その中の一部のプロジェクトを「マルチ バイト文字セットを使用する」に変更してビルドすると,

1>------ ビルド開始: プロジェクト:TEDHPro4, 構成:Debug Win32 ------
1>  StdAfx.cpp
1>c:\program files (x86)\microsoft visual studio 14.0\vc\atlmfc\include\afx.h(38): warning C4996: 'MBCS_Support_Deprecated_In_MFC': MBCS support in MFC is deprecated and may be removed in a future version of MFC.
1>  c:\program files (x86)\microsoft visual studio 14.0\vc\atlmfc\include\afx.h(33): note: 'MBCS_Support_Deprecated_In_MFC' の宣言を確認してください
1>  _WIN32_WINNT not defined. Defaulting to _WIN32_WINNT_MAXVER (see WinSDKVer.h)
1>  TEDHPro4.cpp
1>  TEDHProD.cpp
1>  コードを生成中...
1>StdAfx.obj : warning LNK4075: /EDITANDCONTINUE は /OPT:LBR の指定によって無視されます。
1>  TEDH4140.vcxproj -> c:\Temp\EDHProM\TEDHPro4\Debug.140\TEDHPro4.exe
1>  TEDH4140.vcxproj -> c:\Temp\EDHProM\TEDHPro4\Debug.140\TEDHPro4.pdb (Full PDB)
========== ビルド: 1 正常終了、0 失敗、4 更新不要、0 スキップ ==========

C4996: 'MBCS_Support_Deprecated_In_MFC'
今回のプロジェクトは,dll の単体テストのためのものなのでこのまま(warning が出る状態)とする.
これを回避するには「文字セット」を「Unicode 文字セットを使用する」にすること.
どうしても warning C4996 を消したいのではあれば,StdAfx.h で afx*.h のインクルードの前に NO_WARN_MBCS_MFC_DEPRECATION を定義すれば良い.
#define NO_WARN_MBCS_MFC_DEPRECATION

この投稿は役に立ちましたか? 役に立った 役に立たなかった 0 人中 0 人がこの 投稿 は役に立ったと言っています。

  にほんブログ村 IT技術ブログへ


VC 14 デバッグ MFC にステップイン

VC 2015 で MFC を使用した SDI.exe をデバッグしていると,MFC のコードにステップインできない?
入っている他の VC で試すと VC 2013 まではうまく機能している.
検索しても,これはという内容には引っ掛からなかった?


アプリケーションクラスの CG3toMApp::InitInstance() を抜ける時,そのままステップ実行していると…
mfc140ud.i386.pdb は読み込まれていません
「Microsoft Symbol Servers」にチェックを付けて「読み込み」.
MFC ソース内のデバッグができる様になった.


設定としては「ツール」-「オプション」の中の「デバッグ」-「シンボル」.
「ツール」-「オプション」-「デバッグ」-「シンボル」

この投稿は役に立ちましたか? 役に立った 役に立たなかった 0 人中 0 人がこの 投稿 は役に立ったと言っています。

  にほんブログ村 IT技術ブログへ


CMutex の使用でデッドロック?

何年も前(2015/11?)からなのかもしれないが,
今の PC になってから作成した exe が起動時やサムネイルの表示などで停止する現象が時々発生している.
「ファイル更新監視」が停止
発生する頻度が低いのと,現象が絞り切れていなかったのでそのままになっていた.


今日,デバッグしていると exe が起動しない.
その時までに起動済みのものは動作しているが,止まってしまうものもあり.
以前この現象が発生した時は再起動することで回避したが,今回はもう少し調べてみることにした.


デバッガで追いかけると CMutex の Lock(INFINITE) で戻って来ない
CMutex Lock(INFINITE) で戻って来ない
使用している所は次の様な感じ.

{
	_MutexS_  mt(FALSE,_T("DocIB::GetBitmap")) ;
	MutexS    m(&mt) ;
	{
	//	共有のリソースに対する操作
		}
	}

通常の動作では Unlock されないことがある様には思えないが…
デバッガを使っていて Lock 中に exe を強制終了してしまったか?

_MutexS_	UseGdiPlus::ME(FALSE,_T("UseGdiPlus::GP_Token")) ;

{
	MutexS	me(&ME) ;
	if (IsInitialized())	{
		//	...
		}
	//	..
	}

いい修正方法が思い浮かばないので,とりあえずメモ.


2021/02/19
その後いろいろと検索して調べたが,通常の動作ではロックされたままとなることはなさそう.
https://docs.microsoft.com/ja-jp/dotnet/standard/threading/mutexes


表示されてはないが起動したままの exe があるかと思い,タスクバーを見たが特になさそう.
昨日,わかっているものの幾つかは「タスクの終了」で終わらせている.
そうなるとロックされている Mutex は,自前のシェルエクステンションと思われる.
「タスクバー」に表示されている「エクスプローラ」は終了させたが,まだ誰かがロックしている.
画面には表示されていない explorer.exe が幾つかか存在したので,すべて終わらせた.
これでロックされた Mutex は解放されたみたい.


今度は,デバッガを使用してうまく起動しなかった exe をいろいろ試すことに.
デバッガで Lock した直後にブレイクポイントを設定して停止.
当然であるが他の exe を起動すると Lock の所で止まってしまう.
デバッガで Unlock の後まで実行すると,他の exe も止まっていた所から動き出す.


デバッガで Lock した直後に停止させて,他の exe を起動.
デバッガで「デバッガの停止」してみる(Unlock していない)と,他の exe が動き出す.


これらの動作を見ると,使い方としてはそれ程間違ってはなさそう.
コードを追いかける限りでは,「マズい」所がわからない.
複数のプロセスから呼ばれた時に意図しないタイミングとなってしまう所があるのか?
ある程度はっきりしたのは,自前のシェルエクステンションの GDIPlus 関係の時の Lock で止まっていること.

この投稿は役に立ちましたか? 役に立った 役に立たなかった 0 人中 0 人がこの 投稿 は役に立ったと言っています。

  にほんブログ村 IT技術ブログへ


ドキュメント付きの起動で抜ける?

個人的なコートでのメモです.


普通に exe を起動してドキュメントを開くのは問題ない.
ドキュメント付きで起動すると,ウィンドウが表示されて,ドキュメントを読込み後終了してしまっている.
コマンドライン引数の設定
デバッガで追いかけると,ProcessShellCommand の呼び出しで FALSE となっている.
ProcessShellCommand の結果が FALSE
原因は,ドキュメントの読込み後にアプリケーションクラスにアクセスしている所で初期化が済んでないため.
初期化のコード(RcntFM)を CCommandLineInfo の前にして対応.

	// メイン MDI フレーム ウィンドウを作成
	CMainFrame* pMainFrame = new CMainFrame;
	if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
		return FALSE;
	m_pMainWnd = pMainFrame;
	// ドラッグ/ドロップ オープンを許可します
	m_pMainWnd->DragAcceptFiles();
	{
		RcntFM.Read() ;
		RcntFM.SetStartID(ID_RECENT_FILE_00) ;
		}
	// DDE、file open など標準のシェル コマンドのコマンドラインを解析します。
	CCommandLineInfo cmdInfo;
	ParseCommandLine(cmdInfo);
	if (cmdInfo.m_nShellCommand == CCommandLineInfo::FileNew) {
		cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing ;
		}
	// コマンドラインでディスパッチ コマンドを指定します。
	if (!ProcessShellCommand(cmdInfo))
		return FALSE;

これをやっていて困ったのが,ソースのタイル表示.
VC 2019 タイル表示
VS 2019 ではうまく動作するが,2017 など他のものではエラーになってしまう.
VC 2015 タイル表示でアプリケーションエラー

---------------------------
GLSm140: devenv.exe - アプリケーション エラー
---------------------------
0x000000006359C044 の命令が 0x0000000000000000 のメモリを参照しました。メモリが read になることはできませんでした。
プログラムを終了するには [OK] をクリックしてください
プログラムをデバッグするには [キャンセル] をクリックしてください
---------------------------
OK   キャンセル   
---------------------------
この投稿は役に立ちましたか? 役に立った 役に立たなかった 0 人中 0 人がこの 投稿 は役に立ったと言っています。

  にほんブログ村 IT技術ブログへ


MFC DLL error C2371 cerr

FBX SDK を使用したテストプロジェクト.
以前「MFC を使用する」になっていたもの.
関連するコードを変更して「MFC を使用しない」に書き換え.
そのままのコードを「MFC を使用する」に戻すと,…

--------------------構成: T_FBX - Win32 DebugM--------------------
コンパイル中...
T_FBX.cpp
c:\program files\microsoft visual studio\vc98\mfc\include\afx.h(1941) : error C2371: 'cerr' : 再定義されています。異なる基本型です。
        c:\program files\microsoft visual studio\vc98\include\iostream(19) : 'cerr' の宣言を確認してください。
nothing   FS_VER
  VC 6    200508
cl.exe の実行エラー

T_FBX.exe - エラー 1、警告 0

MFC を使用する方法に戻してエラー C2371
前に変更しているが,元に戻す方が良いのか?
そもそもこの部分を削除した方が良いか?
https://mish.myds.me/wordpress/dev/2020/04/17/rc1047-c2679/


今回は i_define.hxx から次の部分を削除.

#ifdef	_MSC_VER
	#ifdef		_MFC_VER
	#else
		#ifndef	afxDump
		#define	afxDump		std::terr
		#endif
	#endif
#endif

必要があれば i_debug.hxx に追加する.

この投稿は役に立ちましたか? 役に立った 役に立たなかった 0 人中 0 人がこの 投稿 は役に立ったと言っています。

  にほんブログ村 IT技術ブログへ


CListBox などのオーナードロー

リストスクロール時,動作が逆に見える現象の調査のため調べたこと.


WinCore.cpp CWnd::OnMeasureItem での CtlType の値

/*
 * Owner draw control types
 */
#define ODT_MENU        1
#define ODT_LISTBOX     2
#define ODT_COMBOBOX    3
#define ODT_BUTTON      4
#if(WINVER >= 0x0400)
#define ODT_STATIC      5
#endif /* WINVER >= 0x0400 */
/*
 * Listbox Styles
 */
#define LBS_NOTIFY            0x0001L
#define LBS_SORT              0x0002L
#define LBS_NOREDRAW          0x0004L
#define LBS_MULTIPLESEL       0x0008L
#define LBS_OWNERDRAWFIXED    0x0010L
#define LBS_OWNERDRAWVARIABLE 0x0020L
#define LBS_HASSTRINGS        0x0040L
#define LBS_USETABSTOPS       0x0080L
#define LBS_NOINTEGRALHEIGHT  0x0100L
#define LBS_MULTICOLUMN       0x0200L
#define LBS_WANTKEYBOARDINPUT 0x0400L
#define LBS_EXTENDEDSEL       0x0800L
#define LBS_DISABLENOSCROLL   0x1000L
#define LBS_NODATA            0x2000L
#if(WINVER >= 0x0400)
#define LBS_NOSEL             0x4000L
#endif /* WINVER >= 0x0400 */
#define LBS_STANDARD          (LBS_NOTIFY | LBS_SORT | WS_VSCROLL | WS_BORDER)
// Measure item implementation relies on unique control/menu IDs
void CWnd::OnMeasureItem(int /*nIDCtl*/, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
	if (lpMeasureItemStruct->CtlType == ODT_MENU)
	{
	//	...
	}
	else
	{
		CWnd* pChild = GetDescendantWindow(lpMeasureItemStruct->CtlID, TRUE);
		if (pChild != NULL && pChild->SendChildNotifyLastMsg())
			return;     // eaten by child
	}
	// not handled - do default
	Default();
}

GetDescendantWindow で求めた pChild が NULL のため CListBox::OnChildNotify から MeasureItem が呼ばれない?
呼ばれた時の lpMeasureItemStruct->itemHeight は,ODT_LISTBOX は 18 ,ODT_COMBOBOX は 20 .
デバッガで高さを設定すると,その高さになる.
OWNERDRAWVARIABLE は項目ごとに呼ばれるが,OWNERDRAWFIXED の時はうまくない?


結局,VC 6 などの場合にそうなる(逆にスクロール)様子.
コモンコントロール Ver.6 を使う様にすることで回避できる.
コモンコントロール Ver.6 の指定

この投稿は役に立ちましたか? 役に立った 役に立たなかった 0 人中 0 人がこの 投稿 は役に立ったと言っています。

  にほんブログ村 IT技術ブログへ



    top

    %d人のブロガーが「いいね」をつけました。