<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>TAKABO SOFT&#187; カテゴリー「MFC」｜TAKABO SOFT</title>
	<atom:link href="http://takabosoft.com/category/mfc/feed" rel="self" type="application/rss+xml" />
	<link>http://takabosoft.com</link>
	<description>ドット絵エディタ「EDGE2」、MIDI音楽編集ソフト「Domino」、楽曲などを配布している個人サイトです。</description>
	<lastBuildDate>Sun, 01 Jan 2012 03:56:35 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>MFCでコマンドライン引数を解析</title>
		<link>http://takabosoft.com/20100804054534.html</link>
		<comments>http://takabosoft.com/20100804054534.html#comments</comments>
		<pubDate>Wed, 04 Aug 2010 05:45:34 +0000</pubDate>
		<dc:creator>takabosoft</dc:creator>
				<category><![CDATA[MFC]]></category>
		<category><![CDATA[ProgrammingTips]]></category>

		<guid isPermaLink="false">http://takabosoft.com/20100804054534.html</guid>
		<description><![CDATA[MFCでコマンドライン引数を解析する方法と言えば、
CWinApp::ParseCommandLine
を使うやり方が一般的・・・と言いますか、SDIやMDIプロジェクトだったら、最初からこれが使われているため、ここを拡 [...]]]></description>
			<content:encoded><![CDATA[<p>MFCでコマンドライン引数を解析する方法と言えば、<br />
<a href="http://msdn.microsoft.com/ja-jp/library/64c73803(VS.80).aspx">CWinApp::ParseCommandLine</a><br />
を使うやり方が一般的・・・と言いますか、SDIやMDIプロジェクトだったら、最初からこれが使われているため、ここを拡張して独自の起動引数なんかを解析するのが普通かと思います。</p>
<p>長年その方法でやっていたのですが、最近になって <strong>__argc</strong> や <strong>__targv</strong> （頭にアンダースコア２個） を使えば、解析済みの引数が参照出来る事を知りました。<br />
ParseCommandLineを使うとわざわざCCommandLineInfoの派生クラスを作る必要があったりして面倒くさいのですが、__argcと__targvならば簡単に参照できるので、場合によってはこちらを使った方が手軽そうです。</p>
<p>データ構造として、起動引数を１クラスに管理させたい、とか思い始めるとParseCommandLineの方が良いのかなとも思ったりして、悩みどころではあります。</p>
]]></content:encoded>
			<wfw:commentRss>http://takabosoft.com/20100804054534.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[MFC] マウスホイールで、マウスカーソル位置のウィンドウをスクロールするには</title>
		<link>http://takabosoft.com/20100727050742.html</link>
		<comments>http://takabosoft.com/20100727050742.html#comments</comments>
		<pubDate>Tue, 27 Jul 2010 05:07:42 +0000</pubDate>
		<dc:creator>takabosoft</dc:creator>
				<category><![CDATA[MFC]]></category>
		<category><![CDATA[ProgrammingTips]]></category>

		<guid isPermaLink="false">http://takabosoft.com/20100727050742.html</guid>
		<description><![CDATA[ホイールイベントはフォーカスを持つウィンドウで優先的に処理されるようなのですが、場合によってはフォーカスよりもマウスカーソル位置を優先したい事があります。
今まで結構回りくどいやり方をしていたのですが、PreTransl [...]]]></description>
			<content:encoded><![CDATA[<p>ホイールイベントはフォーカスを持つウィンドウで優先的に処理されるようなのですが、場合によってはフォーカスよりもマウスカーソル位置を優先したい事があります。</p>
<p>今まで結構回りくどいやり方をしていたのですが、PreTranslateMessageにちょろっと書いたら上手く動いたようなので、載せておきます。<br />
（あまり動作検証していませんが）</p>
<pre class="brush: cpp;">BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
{
	if (pMsg-&gt;message == WM_MOUSEWHEEL) {
		CWnd* pWnd = WindowFromPoint(pMsg-&gt;pt);
		if (pWnd &amp;&amp; IsChild(pWnd)) {
			pMsg-&gt;hwnd = pWnd-&gt;GetSafeHwnd();
		}
	}

	return __super::PreTranslateMessage(pMsg);
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://takabosoft.com/20100727050742.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>(VS2008+MFC) CTreeCtrlの動的作成で枠がおかしい</title>
		<link>http://takabosoft.com/20100323221849.html</link>
		<comments>http://takabosoft.com/20100323221849.html#comments</comments>
		<pubDate>Tue, 23 Mar 2010 13:18:49 +0000</pubDate>
		<dc:creator>takabosoft</dc:creator>
				<category><![CDATA[MFC]]></category>
		<category><![CDATA[ProgrammingTips]]></category>
		<category><![CDATA[日記]]></category>

		<guid isPermaLink="false">http://takabosoft.com/20100323221849.html</guid>
		<description><![CDATA[
↑右がリソースエディタで貼ったツリーコントロールで、
左が↓のコードで貼ったツリーコントロール。
// m_TreeはCTreeCtrl型
m_Tree.CreateEx(WS_EX_CLIENTEDGE, WS_CH [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://takabosoft.com/wp-content/uploads/2010/03/Edge1.png" alt="Edge1" title="Edge1" width="482" height="337" class="alignnone size-full wp-image-1030" /></p>
<p>↑右がリソースエディタで貼ったツリーコントロールで、<br />
左が↓のコードで貼ったツリーコントロール。</p>
<pre class="brush: cpp;">// m_TreeはCTreeCtrl型
m_Tree.CreateEx(WS_EX_CLIENTEDGE, WS_CHILD | WS_VISIBLE | TVS_SHOWSELALWAYS, CRect(10, 10, 200, 200),
this, 0);
m_Tree.InsertItem(_T(&quot;ああああ&quot;));</pre>
<p>見てお判りの通りWS_EX_CLIENTEDGEが付きません。<br />
CTreeCtrl::CreateExのソースを見てみると、変なことやってますので、そりゃ付かないですね。</p>
<pre class="brush: cpp;">BOOL CTreeCtrl::CreateEx(DWORD dwExStyle, DWORD dwStyle, const RECT&amp; rect,
	CWnd* pParentWnd, UINT nID)
{
	BOOL bRet = Create(dwStyle, rect, pParentWnd, nID);
	if (bRet &amp;&amp; dwExStyle != 0)
	{
		bRet = ModifyStyleEx(0, dwExStyle);
	}
	return bRet;
}</pre>
<p>かと言って</p>
<pre class="brush: cpp;">m_Tree.CreateEx(0, WS_CHILD | WS_VISIBLE | TVS_SHOWSELALWAYS, CRect(10, 10, 200, 200), this, 0);
m_Tree.ModifyStyleEx(0, WS_EX_CLIENTEDGE, SWP_FRAMECHANGED);
m_Tree.InsertItem(_T(&quot;ああああ&quot;));</pre>
<p>こんなコードにしても、↓のようにビジュアルテーマ（？）が適用されません。<br />
<img src="http://takabosoft.com/wp-content/uploads/2010/03/Edge5.png" alt="Edge5" title="Edge5" width="482" height="337" class="alignnone size-full wp-image-1031" /><br />
（WS_BORDERだとちょっと濃い枠が付くため、これもちょっと違います。）</p>
<p>回避方法としては、</p>
<pre class="brush: cpp;">m_Tree.CWnd::CreateEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, _T(&quot;&quot;), WS_CHILD | WS_VISIBLE | TVS_SHOWSELALWAYS, CRect(10, 10, 200, 200), this, 0);
m_Tree.InsertItem(_T(&quot;ああああ&quot;));</pre>
<p>というように、CWnd::CreateExを直接呼び出してしまう事ぐらいでしょうか。</p>
<p>これで一応リソースエディタで貼った物と同じ枠が付きます。<br />
<img src="http://takabosoft.com/wp-content/uploads/2010/03/Edge6.png" alt="Edge6" title="Edge6" width="482" height="337" class="alignnone size-full wp-image-1033" /></p>
<p>MFCのバグ一覧とかどっかにまとまってたりしないのかな・・・。</p>
]]></content:encoded>
			<wfw:commentRss>http://takabosoft.com/20100323221849.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>(VS2008+SP1+MFC) ダイアログ上でポップアップメニューを出す場合の注意点</title>
		<link>http://takabosoft.com/20091115235818.html</link>
		<comments>http://takabosoft.com/20091115235818.html#comments</comments>
		<pubDate>Sun, 15 Nov 2009 14:58:18 +0000</pubDate>
		<dc:creator>takabosoft</dc:creator>
				<category><![CDATA[MFC]]></category>
		<category><![CDATA[ProgrammingTips]]></category>

		<guid isPermaLink="false">http://takabosoft.com/?p=980</guid>
		<description><![CDATA[VS2008 SP1 MFC環境では、ポップアップメニューの表示には
theApp.GetContextMenuManager()->ShowPopupMenu(・・・)
などと呼ぶことになりますが、これを何気なくダイア [...]]]></description>
			<content:encoded><![CDATA[<p>VS2008 SP1 MFC環境では、ポップアップメニューの表示には<br />
theApp.GetContextMenuManager()->ShowPopupMenu(・・・)<br />
などと呼ぶことになりますが、これを何気なくダイアログ上でやると、メニューは表示されるものの、適当な場所をクリックしてもメニューが閉じてくれません。</p>
<p>これで少しハマっていたのですが、ダイアログの親クラスをCDialogではなくCDialogExにするとうまくメニュー処理がされるようです。<br />
（こういうものこそASSERTで引っかけてくれよorz）</p>
<p><img src="http://takabosoft.com/wp-content/uploads/2009/11/Edge12.png" alt="Edge12" title="Edge12" width="272" height="128" class="alignnone size-full wp-image-981" /></p>
]]></content:encoded>
			<wfw:commentRss>http://takabosoft.com/20091115235818.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[MFC] 汎用的なスクロールイベントハンドラを作ってみた</title>
		<link>http://takabosoft.com/20091105172158.html</link>
		<comments>http://takabosoft.com/20091105172158.html#comments</comments>
		<pubDate>Thu, 05 Nov 2009 08:21:58 +0000</pubDate>
		<dc:creator>takabosoft</dc:creator>
				<category><![CDATA[MFC]]></category>
		<category><![CDATA[ProgrammingTips]]></category>

		<guid isPermaLink="false">http://takabosoft.com/?p=976</guid>
		<description><![CDATA[MFCでアプリを書いていると、スクロール処理が必要になってくる場合が多々あります。
CScrollViewで行ける場合は良いのですが、自前でやらないといけない場合には、OnHScrollとOnVScrollをインプリメン [...]]]></description>
			<content:encoded><![CDATA[<p>MFCでアプリを書いていると、スクロール処理が必要になってくる場合が多々あります。<br />
CScrollViewで行ける場合は良いのですが、自前でやらないといけない場合には、OnHScrollとOnVScrollをインプリメントしてやらないといけません。</p>
<p>これが結構面倒だなーといつも思っていたので使い回せるようなイベントハンドラを作ってみました。</p>
<pre class="brush: cpp;">bool Scroll(CWnd* pWnd, int nBar, UINT nSBCode, UINT nPos, int nLine /*= 1*/)
{
	SCROLLINFO info = {sizeof(SCROLLINFO), SIF_ALL};
	if (!pWnd-&gt;GetScrollInfo(nBar, &amp;info)) {
		return false;
	}
	int nNewPos = pWnd-&gt;GetScrollPos(nBar);
	int nOldPos = nNewPos;

	switch (nSBCode) {
	case SB_LEFT:
		nNewPos = info.nMin;
		break;
	case SB_ENDSCROLL:
		break;
	case SB_LINELEFT:
		nNewPos -= nLine;
		break;
	case SB_LINERIGHT:
		nNewPos += nLine;
		break;
	case SB_PAGELEFT:
		nNewPos -= info.nPage;
		break;
	case SB_PAGERIGHT:
		nNewPos += info.nPage;
		break;
	case SB_RIGHT:
		nNewPos = info.nMax;
		break;
	case SB_THUMBPOSITION:
		nNewPos = nPos;
		break;
	case SB_THUMBTRACK:
		nNewPos = nPos;
		break;
	}

	pWnd-&gt;SetScrollPos(nBar, nNewPos);
	return pWnd-&gt;GetScrollPos(nBar) != nOldPos;
}</pre>
<p>スクロール位置に変更があったときにtrueを返しますので、これを見て画面更新などを行います。</p>
<p>こんな感じで使います。</p>
<pre class="brush: cpp;">void CHogeHogeWnd::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	if (Scroll(this, SB_HORZ, nSBCode, nPos, 16)) {
		// ここで画面更新など
	}
}

void CHogeHogeWnd::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	if (Scroll(this, SB_VERT, nSBCode, nPos, 16)) {
		// ここで画面更新など
	}
}</pre>
<p>page移動量は若干の調整が必要かもしれませんね。</p>
<p>てか、CScrollWnd的なものを作ってテンプレートっぽくしておくのがベストなんだろうなぁ。</p>
]]></content:encoded>
			<wfw:commentRss>http://takabosoft.com/20091105172158.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VS2008(MFC, SP1)で作ったアプリのカスタマイズ機能が動かない場合の対処方法</title>
		<link>http://takabosoft.com/20091105110744.html</link>
		<comments>http://takabosoft.com/20091105110744.html#comments</comments>
		<pubDate>Thu, 05 Nov 2009 02:07:44 +0000</pubDate>
		<dc:creator>takabosoft</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[MFC]]></category>
		<category><![CDATA[ProgrammingTips]]></category>

		<guid isPermaLink="false">http://takabosoft.com/?p=975</guid>
		<description><![CDATA[適当にウィザードでプロジェクトを作成したのち、「カスタマイズ」機能でツールバーやメニューコマンドをドラッグ＆ドロップしようと思ったら、動かない！なんて事がありましたので原因を探ってみたところ、プロジェクト作成ウィザードで [...]]]></description>
			<content:encoded><![CDATA[<p>適当にウィザードでプロジェクトを作成したのち、「カスタマイズ」機能でツールバーやメニューコマンドをドラッグ＆ドロップしようと思ったら、動かない！なんて事がありましたので原因を探ってみたところ、プロジェクト作成ウィザードでActiveXのチェックを外してしまっていたのが原因のようです。</p>
<p>中は見ていませんが、おそらくカスタマイズ時のドラッグ＆ドロップ処理はOLEのドラッグ＆ドロップなんでしょうね。<br />
なので、<br />
CXXXXApp::InitInstanceの適当な所で「AfxOleInit()」を呼べばカスタマイズ機能が正常に動くようになります。</p>
]]></content:encoded>
			<wfw:commentRss>http://takabosoft.com/20091105110744.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VC, MFCでグラデーションを描画するには</title>
		<link>http://takabosoft.com/20091104163953.html</link>
		<comments>http://takabosoft.com/20091104163953.html#comments</comments>
		<pubDate>Wed, 04 Nov 2009 07:39:53 +0000</pubDate>
		<dc:creator>takabosoft</dc:creator>
				<category><![CDATA[MFC]]></category>
		<category><![CDATA[ProgrammingTips]]></category>
		<category><![CDATA[Win32 API]]></category>

		<guid isPermaLink="false">http://takabosoft.com/?p=974</guid>
		<description><![CDATA[GradientFill APIのラッパー関数を作ってみました。
と言っても縦のグラデしか対応させていませんが。
void FillGrad(CDC* pDC, CRect rc, COLORREF colBegin,  [...]]]></description>
			<content:encoded><![CDATA[<p>GradientFill APIのラッパー関数を作ってみました。<br />
と言っても縦のグラデしか対応させていませんが。</p>
<pre class="brush: cpp;">void FillGrad(CDC* pDC, CRect rc, COLORREF colBegin, COLORREF colEnd)
{
	TRIVERTEX av[2] = {
		rc.left, rc.top, GetRValue(colBegin) &lt;&lt; 8, GetGValue(colBegin) &lt;&lt; 8, GetBValue(colBegin) &lt;&lt; 8, 0xff00,
		rc.right, rc.bottom, GetRValue(colEnd) &lt;&lt; 8, GetGValue(colEnd) &lt;&lt; 8, GetBValue(colEnd) &lt;&lt; 8, 0xff00,
	};
	GRADIENT_RECT gr = {0, 1};
	GradientFill(pDC-&gt;GetSafeHdc(), av, 2, &amp;gr, 1, GRADIENT_FILL_RECT_V);
}</pre>
<p>GradientFill APIは古いOSでは動きませんのでご注意ください。</p>
]]></content:encoded>
			<wfw:commentRss>http://takabosoft.com/20091104163953.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Visual Studio 2008 + MFCでExcelを操作するには</title>
		<link>http://takabosoft.com/20091030101433.html</link>
		<comments>http://takabosoft.com/20091030101433.html#comments</comments>
		<pubDate>Fri, 30 Oct 2009 01:14:33 +0000</pubDate>
		<dc:creator>takabosoft</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[MFC]]></category>
		<category><![CDATA[ProgrammingTips]]></category>

		<guid isPermaLink="false">http://takabosoft.com/?p=967</guid>
		<description><![CDATA[仕事で開発を行っていると、他の人がエクセルファイルでデータ資料を作り、プログラマがその情報をアプリに組み込む、なんて事がよくあります。
一度CSVに書き出してからプログラムでそれを読み、使いやすいデータ（XMLやCのソー [...]]]></description>
			<content:encoded><![CDATA[<p>仕事で開発を行っていると、他の人がエクセルファイルでデータ資料を作り、プログラマがその情報をアプリに組み込む、なんて事がよくあります。<br />
一度CSVに書き出してからプログラムでそれを読み、使いやすいデータ（XMLやCのソース）にコンバートして利用するのが定石かと思いますが、エクセルファイルを直接読めればCSVに書き出す手間が多少軽減されます。<br />
（そもそもVBAでコンバート処理書いちゃうという人は尊敬されれば良いと思います）</p>
<p>Visual C++6.0ではよくそういう事をやっていたのですが、Visual Studio 2008 + MFCだとどうやるんだろう？と思いましてちょっとやってみました。</p>
<p>メニューからクラスの追加を実行します。<br />
<a href="http://takabosoft.com/wp-content/uploads/2009/10/xls00.png"><img src="http://takabosoft.com/wp-content/uploads/2009/10/xls00-320x56.png" alt="xls00" title="xls00" width="320" height="56" class="alignnone size-medium wp-image-968" /></a></p>
<p>「TypeLibからのMFCクラス」を選びます。<br />
<a href="http://takabosoft.com/wp-content/uploads/2009/10/xls01.png"><img src="http://takabosoft.com/wp-content/uploads/2009/10/xls01-320x166.png" alt="xls01" title="xls01" width="320" height="166" class="alignnone size-medium wp-image-969" /></a></p>
<p>エクセルのタイプライブラリを選び、使うインターフェースを追加して（今回は面倒なので全部追加）完了ボタンを押します。<br />
<a href="http://takabosoft.com/wp-content/uploads/2009/10/xls02.png"><img src="http://takabosoft.com/wp-content/uploads/2009/10/xls02-320x206.png" alt="xls02" title="xls02" width="320" height="206" class="alignnone size-medium wp-image-973" /></a></p>
<p>ちょっと生成に時間が掛かりますが、ヘッダーファイルが生成されます。<br />
ただ、何故か#import文が入っていて、コンパイル時にエラー（名前の競合）が出てしまうので一括置換でコメントアウトします。<br />
<a href="http://takabosoft.com/wp-content/uploads/2009/10/xls03.png"><img src="http://takabosoft.com/wp-content/uploads/2009/10/xls03-320x18.png" alt="xls03" title="xls03" width="320" height="18" class="alignnone size-medium wp-image-971" /></a></p>
<p>VC6ではできなかった芸当ですね（ソリューション内一括置換）<br />
<a href="http://takabosoft.com/wp-content/uploads/2009/10/xls04.png"><img src="http://takabosoft.com/wp-content/uploads/2009/10/xls04-320x237.png" alt="xls04" title="xls04" width="320" height="237" class="alignnone size-medium wp-image-972" /></a></p>
<p>あとはごりごりコードを書けばエクセルの操作ができます。</p>
<p>既存のファイルを開いて、最初のシートのA1のテキストを取得するにはこんな感じになるかと思います。<br />
（Excel 2007使用）</p>
<pre class="brush: cpp;">#include &quot;CApplication.h&quot;
#include &quot;CWorkbooks.h&quot;
#include &quot;CWorksheets.h&quot;
#include &quot;CWorkbook.h&quot;
#include &quot;CWorksheet.h&quot;
#include &quot;CRange.h&quot;

void CHogeHogeDlg::OnBnClickedButton1()
	CApplication App;
	if (!App.CreateDispatch(_T(&quot;Excel.Application&quot;))) {
		ASSERT(0);
		return;
	}
	App.put_Visible(TRUE);

	CWorkbooks Workbooks = App.get_Workbooks();

	// 既存のエクセルファイルを開く
	COleVariant varNull;
	varNull.ChangeType(VT_NULL);
	CWorkbook Workbook = Workbooks.Open(_T(&quot;c:\\hogehoge.xls&quot;), varNull, varNull, varNull, varNull, varNull, varNull, varNull, varNull, varNull, varNull, varNull, varNull,varNull, varNull);

	CWorksheets Worksheets = Workbook.get_Worksheets();
	CWorksheet Worksheet = Worksheets.get_Item(COleVariant((long)1));

	CRange Cells = Worksheet.get_Cells();
	CRange Cell = Cells.get_Item(COleVariant((long)1), COleVariant((long)1)).pdispVal;
	CString str = Cell.get_Text().bstrVal;
}</pre>
<p>CRange::DialogBoxとかいう関数でコンパイルエラーが出ますが関数名変えるなどして回避します。</p>
<p>当然ながら実行する環境にエクセルがインストールされている必要があります。<br />
また、使用したタイプライブラリと実行時のエクセルのバージョンが違うと、うまく動かない事があるかもしれません。うろ覚えですが。上位互換はあるかも？</p>
<p>もしいろんな操作をやりたい場合、エクセルのマクロのヘルプが参考になると思います。若干関数名は違いますが、構造などはほぼ同じです。</p>
]]></content:encoded>
			<wfw:commentRss>http://takabosoft.com/20091030101433.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>(MFC) CSplitterWndで非ビュー(CWndなど)を載せるには</title>
		<link>http://takabosoft.com/20090905085500.html</link>
		<comments>http://takabosoft.com/20090905085500.html#comments</comments>
		<pubDate>Fri, 04 Sep 2009 23:55:00 +0000</pubDate>
		<dc:creator>takabosoft</dc:creator>
				<category><![CDATA[MFC]]></category>
		<category><![CDATA[ProgrammingTips]]></category>
		<category><![CDATA[日記]]></category>

		<guid isPermaLink="false">http://takabosoft.com/?p=941</guid>
		<description><![CDATA[CSplitterWndと言えば、CView系のみスプリット表示するというイメージがありますが、ヘルプを見ていたら
静的分割ウィンドウを作成するとき、同時にすべてのペインを作成する必要があります。CreateView メ [...]]]></description>
			<content:encoded><![CDATA[<p>CSplitterWndと言えば、CView系のみスプリット表示するというイメージがありますが、ヘルプを見ていたら</p>
<blockquote><p>静的分割ウィンドウを作成するとき、同時にすべてのペインを作成する必要があります。CreateView メンバ関数は、この目的のために使われます。しかし、さらにほかの<strong>非ビュー クラスも作成できます</strong>。</p></blockquote>
<p>と書いてあるではありませんか。</p>
<p>が、具体的にどうやって実装すれば良いかは書かれておらず、ソースを読んでいたところ、</p>
<ul>
<li>親にCSplitterWndのインスタンスを指定してコントロール等を作成</li>
<li>IDをCSplitterWnd::IdFromRowCol関数で算出した値にしておく</li>
</ul>
<p>だけで良いみたいです。</p>
<pre class="brush: cpp;">m_wndSplitter.CreateStatic(this, 2, 1, WS_CHILD | WS_VISIBLE);
m_edit1.CreateEx(WS_EX_CLIENTEDGE, _T(&quot;Edit&quot;), _T(&quot;&quot;), WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | ES_WANTRETURN | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_MULTILINE, CRect(0, 0, 300, 300), &amp;m_wndSplitter, m_wndSplitter.IdFromRowCol(0, 0));
m_edit2.CreateEx(WS_EX_CLIENTEDGE, _T(&quot;Edit&quot;), _T(&quot;&quot;), WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | ES_WANTRETURN | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_MULTILINE, CRect(0, 0, 300, 300), &amp;m_wndSplitter, m_wndSplitter.IdFromRowCol(1, 0));</pre>
<p>あとはm_wndSplitter自体をウィンドウ全体に広げて配置したりだとか、m_wndSplitter.SetRowInfoで行の高さを変更したりするだけです。<br />
ダイアログベースのアプリでも気軽に使えそうですね。</p>
]]></content:encoded>
			<wfw:commentRss>http://takabosoft.com/20090905085500.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MFCでグリッドコントロールを使うには</title>
		<link>http://takabosoft.com/20090831200748.html</link>
		<comments>http://takabosoft.com/20090831200748.html#comments</comments>
		<pubDate>Mon, 31 Aug 2009 11:07:48 +0000</pubDate>
		<dc:creator>takabosoft</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[MFC]]></category>
		<category><![CDATA[日記]]></category>

		<guid isPermaLink="false">http://takabosoft.com/?p=929</guid>
		<description><![CDATA[表形式でデータを表示するだけならリストコントロールのレポートビューでなんとでもなりますが、入力に対応させようとするとリストコントロールではちょっと無理があります（頑張ればこれでも行けないことはないと思いますが）。
他の開 [...]]]></description>
			<content:encoded><![CDATA[<p>表形式でデータを表示するだけならリストコントロールのレポートビューでなんとでもなりますが、入力に対応させようとするとリストコントロールではちょっと無理があります（頑張ればこれでも行けないことはないと思いますが）。</p>
<p>他の開発環境ではグリッドコントロールなどと呼ばれている物が有りますが、VC（MFC）には付いてきません。<br />
（標準のコントロールとしては、そのような物が無いため）</p>
<p>とはいえ、実際にアプリを作る際には、グリッドコントロールはしょっちゅう必要になってきますし、ソフトウェアハウスなんかではグリッドコントロールを独自開発して使っているのが実状だと思います。</p>
<p>そんな中、商品でも何でも良いのである程度汎用的に使えるグリッドコントロールは無いものか、ざっくりと探してみたので、ざっくりとまとめておきます。</p>
<h4>Microsoft FlexGrid Control</h4>
<p>ActiveXで使うグリッドコントロール。<br />
<a href="http://noribeat.s38.xrea.com/developer/03031501.html">http://noribeat.s38.xrea.com/developer/03031501.html</a><br />
<a href="http://hp.vector.co.jp/authors/VA014436/prg_memo/windows/vctips/004.html">http://hp.vector.co.jp/authors/VA014436/prg_memo/windows/vctips/004.html</a></p>
<p>DataGridという奴もあるようですが、こちらはDB用なのかな？</p>
<h4>MFC Grid control</h4>
<p>Code Projectで公開されているライブラリ。<br />
<a href="http://www.codeproject.com/KB/miscctrl/gridctrl.aspx">http://www.codeproject.com/KB/miscctrl/gridctrl.aspx</a></p>
<p>UNICODE環境でコンパイルするとOLEデータの貼り付け時に文字化けたり、そもそもコピペ時にCF_TEXT使ってたり（UNICODEなら本来はCF_UNICODETEXT）、ちょっとプログラムを修正する必要がありますが、結構いろんな事ができます。</p>
<p>ただ、操作性やデザイン面で好き嫌いが出そうな予感です。</p>
<h4>BCGControlBar Library Professional Edition</h4>
<p>VS2008 Future Packの元ネタである、このライブラリ集にもグリッドコントロールがあります。<br />
<a href="http://www.bcgsoft.com/samples/grid.htm">http://www.bcgsoft.com/samples/grid.htm</a>（サンプル）</p>
<p>デザインがなかなか格好良く、しかもかなりの高機能っぷりです。<br />
なんでも出来そうです。</p>
<p>ただ、これだけデザイン良くて高機能なのに、すごく動作が重いんです。<br />
とても実用に耐えられるものではありません。<br />
（データが１画面に納まるような時でないと使い物になりません。）<br />
これが動作が軽ければ文句なしに買っていたのに、非常に残念です。</p>
<h4>ご意見お待ちしております</h4>
<p>うちの会社はこの万能グリッドコントロールを使ってるよ！とか、むしろうちの会社でグリッドコンポーネント作ってるから買ってよ！みたいな宣伝とかありましたらメールください。</p>
<p>※ VS2005/VS2008 + UNICODE + MFC 環境でサクっと動く物をお願いいたします。</p>
]]></content:encoded>
			<wfw:commentRss>http://takabosoft.com/20090831200748.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>(VS2008MFC) メニューなどのフォントがおかしい</title>
		<link>http://takabosoft.com/20090812235606.html</link>
		<comments>http://takabosoft.com/20090812235606.html#comments</comments>
		<pubDate>Wed, 12 Aug 2009 14:56:06 +0000</pubDate>
		<dc:creator>takabosoft</dc:creator>
				<category><![CDATA[MFC]]></category>
		<category><![CDATA[ProgrammingTips]]></category>

		<guid isPermaLink="false">http://takabosoft.com/?p=919</guid>
		<description><![CDATA[Visual Studio 2008 SP1とMFC(feature pack相当)を使ってアプリを書いていたのですが、

↑こんな感じでメニューの文字が小さくなってしまいました（Dominoのメニューフォントサイズが、 [...]]]></description>
			<content:encoded><![CDATA[<p>Visual Studio 2008 SP1とMFC(feature pack相当)を使ってアプリを書いていたのですが、<br />
<img src="http://takabosoft.com/wp-content/uploads/2009/08/edge1.png" alt="" title="" width="285" height="158" class="alignnone size-full wp-image-918" /><br />
↑こんな感じでメニューの文字が小さくなってしまいました（Dominoのメニューフォントサイズが、設定してあるフォントサイズ）。</p>
<p>一応回避方法があったので載せておきます。</p>
<p>CMainFrame::OnCreateの上の方で</p>
<pre class="brush: cpp;">
LOGFONT lf;
SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &amp;lf, 0);
CMFCMenuBar::SetMenuFont(&amp;lf);
m_fontGUI.CreateFontIndirect(&amp;lf);
</pre>
<p>を実行すれば良さそうです。</p>
<p>これどっかに連絡すればsp2で治してくれるのかな？<br />
MSのサポートって有料なのでこういう不具合を見つけてもいまいち報告する気にならないのですが。</p>
<p>-----<br />
（コード修正しました）<br />
なにやらSPI_GETNONCLIENTMETRICSでフォントを取得する方法は<br />
開発環境によってはXPでうまく動作しないようなので、<br />
SPI_GETICONTITLELOGFONTを使う方式に変更しました。<br />
参考：<a href="http://d.hatena.ne.jp/NyaRuRu/20080303/p1<br />
">http://d.hatena.ne.jp/NyaRuRu/20080303/p1</a></p>
]]></content:encoded>
			<wfw:commentRss>http://takabosoft.com/20090812235606.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>最近のMFCについて</title>
		<link>http://takabosoft.com/20090301101036.html</link>
		<comments>http://takabosoft.com/20090301101036.html#comments</comments>
		<pubDate>Sun, 01 Mar 2009 01:10:36 +0000</pubDate>
		<dc:creator>takabosoft</dc:creator>
				<category><![CDATA[MFC]]></category>

		<guid isPermaLink="false">http://takabosoft.com/20090301101036.html</guid>
		<description><![CDATA[半年ぐらい前にVisual Studio 2008にFeature PackというMFCのコンポーネントが追加されまして（VS2008 SP1に含まれています）、 Office等で使われているリボンコントロール類がわりと [...]]]></description>
			<content:encoded><![CDATA[<p>半年ぐらい前にVisual Studio 2008にFeature PackというMFCのコンポーネントが追加されまして（VS2008 SP1に含まれています）、 Office等で使われているリボンコントロール類がわりと簡単に使えるようになったわけなんですが、ようやく最近になって実際に触ってみる機会がありましたので、ちょこっとご報告。<br />
VS2008 SP1からは、Officeのようなインターフェースが手軽に使えるだけでなく、Office2003のツールバーやメニュー等のカスタマイズ機能（もちろん環境の保存・復元機能も）、ドッキングウィンドウ機能などが標準で付いているのが凄いと思いました。</p>
<p>EDGE2を作ろうとした頃、タブブラウザで有名なsleipnir 1.66を使っていまして（今は2を使っています）、 sleipnirはわりとカスタマイズ性を売りにしているところがあって、どうやってカスタマイズ機能などを実現しているのかちょこっと調べてみた事があるのですが、どうやらBCGSoftというメーカーが出しているBCGControlBarという商用ライブラリを使っていたようなんですね。</p>
<p>それで初めてBCGControlBarというライブラリの存在を知って、当時買おうかちょっと迷ったんです。こうした機能を独自で実装するとなると、なかなか手間が掛かりまして、面倒くさいんですよね。当時の私はまだ学生だったという事もありまして（バイトもあまりやっていなかったので）結局自前でなんとかしたわけなんですが、それがVS2008 SP1からは新規作成した所で全部備わっちゃってるわけですから凄いものです。</p>
<p>で、どうもこのBCGControlBarの一部の機能がVS2008 SP1にそのまま入ってるみたいなんです。ただ、一部と書いたとおり、すべての機能が入ってるわけではなくて、商品のBCGControlBar Pro版には、更にグリッドコントロールや高機能エディターなどが付いているようです。<br />
（VS2008 SP1との機能比較が個人的には欲しかったです＾＾；）</p>
<p>そうしてVS2008 SP1持っているけどそれでは足りない人向けにBCGSuiteという商品があるっぽいです。<br />
（Pro版からSP1を引いた程度の内容になっている感じです。）</p>
<p>ちなみに製品の紹介はこちらが参考になるかと。<br />
<a href="http://www.bcgsoft.com/featuretour/bcgcontrolbar-tour.htm">http://www.bcgsoft.com/featuretour/bcgcontrolbar-tour.htm</a><br />
（グリッドコントロール標準で欲しいですわorz）</p>
<p>VS2008 SP1、実際に使ってみると、結構クラス設計とか綺麗に作られている印象を受けました。<br />
BCGSoftさんやり手ですね。</p>
<p>ただ、デフォルトでカスタマイズ機能の保存先がレジストリになっている点が、一部のユーザーに反感を買いそうな感じではあります（＾＾；<br />
一応頑張ればiniファイルとかバイナリに保存できるようになっているようですが、最初っからレジストリに当たり前のように書くのはちょっと勘弁して欲しいですね。</p>
<p>他にもツールバーの登録がツールバーリソース経由しかなさそう（？）なのが個人的にはちょっと痛いところ。<br />
VS2008のツールバーエディタで16色のツールバー画像を作成し、その後で自動作成されたbmpをフルカラー画像に置き換えるか（置き換えるとVS2008上で開けなくなりますが）、もしくは別リソースとしてフルカラー画像リソースを用意してCMFCToolBar::LoadBitmap（だったっけ）しないといけません。<br />
どちらにしてもあとで手を入れるときに二度手間な時があってあんまり好きじゃありません。</p>
<p>そういえば、マニュアルには載ってませんが、ソースを追っていたら、CMFCToolBar::LoadBitmapだったかは、 PNG形式のリソース画像も読めるっぽいです（試していませんが）。<br />
そこはマニュアルに書いておくべきかと（＾＾；<br />
なので、16色のツールバーリソース＋PNGフルカラー画像リソースという組み合わせが現状ではベストかと思われます。<br />
（フルカラーBITMAPリソースはEXEがメタボになるのであんまりリソースとして持ちたくないんですよね）</p>
<p>何かSP1MFCの詳しい書籍が出てくれると良いんですが。<br />
インプレスさん、Visual Studio 2008 SP1 MFCパワフルテクニック大全集とか出してくれませんかね？</p>
<p>需要ないかな・・・</p>
<p>《参考資料》<br />
CodeZineさんの記事→<a href="http://codezine.jp/article/detail/2516">http://codezine.jp/article/detail/2516</a><br />
BCGSoft→<a href="http://www.bcgsoft.com/">http://www.bcgsoft.com/</a><br />
MSDNのチュートリアルとか→<a href="http://msdn.microsoft.com/ja-jp/library/bb982451.aspx">http://msdn.microsoft.com/ja-jp/library/bb982451.aspx</a></p>
]]></content:encoded>
			<wfw:commentRss>http://takabosoft.com/20090301101036.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Domino Ver.1.28アップ</title>
		<link>http://takabosoft.com/20080131121202.html</link>
		<comments>http://takabosoft.com/20080131121202.html#comments</comments>
		<pubDate>Thu, 31 Jan 2008 03:12:02 +0000</pubDate>
		<dc:creator>takabosoft</dc:creator>
				<category><![CDATA[Domino]]></category>
		<category><![CDATA[MFC]]></category>
		<category><![CDATA[ProgrammingTips]]></category>
		<category><![CDATA[お知らせ]]></category>
		<category><![CDATA[ゲーム]]></category>
		<category><![CDATA[日記]]></category>

		<guid isPermaLink="false">http://takabosoft.com/20080131121202.html</guid>
		<description><![CDATA[少し忙しくなりそうな予感なのでドミノ更新しておきます。
更新内容はダウンロードページの下にありますので、そちらをどうぞ。
→ダウンロードなどはこちらから
◇
昼休みゲオにダッシュで行ったんですが、スマブラ売り切れでした。 [...]]]></description>
			<content:encoded><![CDATA[<p>少し忙しくなりそうな予感なのでドミノ更新しておきます。<br />
更新内容はダウンロードページの下にありますので、そちらをどうぞ。</p>
<p>→<a href="http://takabosoft.com/domino">ダウンロードなどはこちらから</a></p>
<p>◇</p>
<p>昼休みゲオにダッシュで行ったんですが、スマブラ売り切れでした。</p>
<p>(´・ω・`)ｼｮﾎﾞｰﾝ<br />
(´・ω・,';,';,',<br />
(´・ω,';,';,',<br />
(´,';,';,',<br />
(,';,';,<br />
';,,('</p>
<p>世の中のお父さんはすごいね！</p>
<p>◇</p>
<p>ところで仕事でもVisual Studio 2005（MFC）を使っているのですが、印刷周りでいくつかバグを見つけましたので、情報として出しておきます。</p>
<p><strong>《その１》</strong><br />
例えば印刷可能範囲が１～１０だとして、印刷画面で２～３ページを印刷しようとした場合、実際には２～１０ページが印刷されてしまう。</p>
<p>→回避策：<a href="http://codezine.jp/forum/message.aspx?thid=472">http://codezine.jp/forum/message.aspx?thid=472</a></p>
<p>海外のサイトではOnPrint内で印刷範囲を書き換えて回避するコードもありました。</p>
<p><strong>《その２》</strong><br />
リリースでMFCをスタティックリンクすると、印刷プレビュー画面の上のボタン類が英語になる。</p>
<p>これは、リソースファイルのインクルードで<br />
#include "afxprint.rc" // 印刷/印刷プレビュー リソース<br />
となっている所を<br />
#include "l.jpn/afxprint.rc"<br />
にすればOK。</p>
<p>ちなみに、字が小さいのをなんとかしたい場合は、この「l.jpn/afxprint.rc」を開いてプロジェクトフォルダに別名保存し、中のリソースの文字サイズを変え、#include "l.jpn/afxprint.rc"の代わりに別名保存したファイルをインクルードすればOKです。</p>
<p><strong>《その３》</strong><br />
A4縦用紙の印刷プレビュー画面にて、一段階拡大したときに、マウスカーソル（ルーペ）と用紙の当たり判定がおかしい（紙の右側をクリックしても、もう一段階拡大しない）</p>
<p>こちらは検索しても回避策が出てきませんでしたので自前でなんとかしました。<br />
CPreviewViewの派生クラスを作成して、マウスカーソルの当たり判定部分を修正すればOKです。</p>
<p>.NETもいいですがVS2005でせっかくMFCもバージョンアップするなら、こういう初歩的なバグは直してからリリースしてほしいです（というか未チェックなんじゃ・・・）。<br />
あと、クラスウィザードは復活させてほしいです（イベントハンドラの追加が面倒）。<br />
あと、ラジオボタンかなんかの変数を追加したときにBOOL型にしようとするのは止めてほしいです。<br />
あと、インテリセンスの更新をVC6並にちょっぱやにしてほしいです。<br />
あと、CFile系の処理でブレークポイント貼ると落ちることがあるのをなんとかしてほしいです。<br />
あと、「CHogeHoge* pHoge」の「CHogeHoge*」だけをCtrl＋左ドラッグで選択出来るようにしてほしいです（VC6ではできた）</p>
<p>そんな事を挙げていくとキリがないですが・・・。<br />
コンパイラはVC6よりも2005の方が良いと思うのですが、IDEは使いづらいところが目立ちます(´･ω･`)ｼｮﾎﾞｰﾝ<br />
何か、改善策などをご存じの方がいらっしゃいましたら、こっそり教えてくださると助かります。</p>
]]></content:encoded>
			<wfw:commentRss>http://takabosoft.com/20080131121202.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Visual Studio 2005 MFC考察</title>
		<link>http://takabosoft.com/20070920194518.html</link>
		<comments>http://takabosoft.com/20070920194518.html#comments</comments>
		<pubDate>Thu, 20 Sep 2007 10:45:18 +0000</pubDate>
		<dc:creator>takabosoft</dc:creator>
				<category><![CDATA[MFC]]></category>
		<category><![CDATA[日記]]></category>

		<guid isPermaLink="false">http://takabosoft.com/20070920194518.html</guid>
		<description><![CDATA[仕事でも趣味でもだんだん使うようになってきたVisual Studio 2005なんですが、便利になった部分、すごく使いづらくなった部分、いろいろ変わったなーという感じです。
ＭＦＣに関してはバグもいくつか確認しています [...]]]></description>
			<content:encoded><![CDATA[<p>仕事でも趣味でもだんだん使うようになってきたVisual Studio 2005なんですが、便利になった部分、すごく使いづらくなった部分、いろいろ変わったなーという感じです。</p>
<p>ＭＦＣに関してはバグもいくつか確認していますが（印刷のページ範囲がバグるとか、ＭＦＣをスタティックリンクするとシステムの文章がデフォルトで英語になってるとかｗ）そんなことよりも未だに慣れないのがイベントハンドラの追加周り。</p>
<p>例えばメニューコマンドのイベントハンドラを作成する場合、ＶＣ６だったらクラスウィザードを表示させて各コマンドのUPDATE_COMMAND_UIとCOMMANDハンドラを一気に追加する事が出来たんですが、 VS2005だとクラスビューを右クリックしてプロパティ選んで、プロパティペインから対象のコマンドを探してUPDATE_COMMAND_UIを追加したら、ソースが切り替わってプロパティペインの内容が変わっちゃうもんだから、次COMMANDハンドラを追加したいときはまたクラスビューからクラスを探して右クリックして・・・・まだ一つのコマンドなら良いんですがそれが「切り取り」「コピー」「貼り付け」「削除」・・・と複数追加したい時に、毎回この作業しなくちゃならなくて、やってるウチにムキィーーーっとなるわけです。</p>
<p>各言語間で操作を統一する事は否定しませんが、今までより効率が下がるのは勘弁してほしいなと思います。</p>
<p>インテリセンスにしても、たしかにＶＣ６より性能が上がったとは思うのですが、さっき追加したばかりのメンバ関数が候補になかなか出てこない、というのが気になる所です。ＶＣ６の時はすぐに反映されたのですが・・・。インテリセンス情報が更新されるまでネットサーフィンしてやろうかと思うこともしばしば(笑)</p>
<p>たぶん、どこかいじればこの辺の問題も解決できると思いこんでるのですが、何かそのあたりの情報をご存知の方はこっそり教えていただけると嬉しいです！ </p>
]]></content:encoded>
			<wfw:commentRss>http://takabosoft.com/20070920194518.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>EDGE2 Ver.0.90 beta002 アップ</title>
		<link>http://takabosoft.com/20050504133557.html</link>
		<comments>http://takabosoft.com/20050504133557.html#comments</comments>
		<pubDate>Wed, 04 May 2005 04:35:57 +0000</pubDate>
		<dc:creator>takabosoft</dc:creator>
				<category><![CDATA[EDGE2]]></category>
		<category><![CDATA[MFC]]></category>
		<category><![CDATA[お知らせ]]></category>

		<guid isPermaLink="false">http://takabosoft.com/20050504133557.html</guid>
		<description><![CDATA[→ダウンロードなどはこちらから
MFCのCRectクラスは初期化を忘れてもデバッグビルドではそれなりに動作するのですが、リリースビルドだとうまく動かないため、開発時に検出しづらいです＿&#124;￣&#124;○
CStringクラスは初期 [...]]]></description>
			<content:encoded><![CDATA[<p>→<a href="http://takabosoft.com/edge2">ダウンロードなどはこちらから</a></p>
<p>MFCのCRectクラスは初期化を忘れてもデバッグビルドではそれなりに動作するのですが、リリースビルドだとうまく動かないため、開発時に検出しづらいです＿|￣|○</p>
<p>CStringクラスは初期化しなくとも（？）データが無い状態となりますが、それと同じような感覚でCRectなんかを使うと痛い目にあいますので開発者の方はご注意を。<br />
（普通こんなミスしないか）</p>
]]></content:encoded>
			<wfw:commentRss>http://takabosoft.com/20050504133557.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>アクセラレータ不具合修正</title>
		<link>http://takabosoft.com/20050502133258.html</link>
		<comments>http://takabosoft.com/20050502133258.html#comments</comments>
		<pubDate>Mon, 02 May 2005 04:32:58 +0000</pubDate>
		<dc:creator>takabosoft</dc:creator>
				<category><![CDATA[EDGE2]]></category>
		<category><![CDATA[MFC]]></category>
		<category><![CDATA[日記]]></category>

		<guid isPermaLink="false">http://takabosoft.com/20050502133258.html</guid>
		<description><![CDATA[先日、MFCにてアクセラレータキーが場合によって効かなくなるという症状を書いたのですが、一応自己解決いたしましたので、報告します。
（解決案をくださったAOIさん、Thanx!）
そもそもの原因は「TranslateAc [...]]]></description>
			<content:encoded><![CDATA[<p>先日、MFCにてアクセラレータキーが場合によって効かなくなるという症状を書いたのですが、一応自己解決いたしましたので、報告します。<br />
（解決案をくださったAOIさん、Thanx!）</p>
<p>そもそもの原因は「TranslateAccelerator」というAPIの仕様とMFCの相性が悪いことにあります。 TranslateAcceleratorはキー入力をメニューコマンドへ変換するAPIですが、メニュー状態が無効だったら変換（送信）しないという仕様になっています。そのため、 MFCのコマンド更新ハンドラで pCmdUI->Enable(TRUE); となっていても、メニュー状態が無効ならば、ショートカットキーは使えません（深い場所のメニューコマンドは）。</p>
<p>ちなみに浅いコマンドが効くようになったことについては、少し憶測ですが書いてみますね。 TranslateAcceleratorの仕様として、キー→メニューコマンド直前（？）に WM_INITMENUなどのメッセージを送信してきます。そのメッセージをMFCフレームワークが掴み、メニューコマンドを「コマンド更新ハンドラ」を使って更新し、最新の状態になるため、ショートカットが効いたのだと思われます。<br />
（ルート直下のメニューコマンドしか更新しません）</p>
<p>さて、深い位置のメニューコマンドを効かせるために、まず思いつくのが、「メニュー状態を更新する」という方法です。しかしいつ更新してよいのかわかりません。毎回キー入力（またはTranslateAcceleratorが送信してくるWM_INITMENUなど）でメニューコマンド全ての状態を更新することは負荷となりパフォーマンスの低下に繋がることは目に見えています。</p>
<p>で、私が使用した解決方法は、以前ちょろっと書きましたが、アクセラレータ処理を「TranslateAccelerator」を使わず自前で実装するという事です。もともとEDGE2はショートカットキーのカスタマイズに対応しており、キーの設定をリソースではなく、通常のデータ（謎）として持っているため、WM_KEYDOWNやらWM_SYSKEYDOWNメッセージを捕まえて、メニューコマンドへ変換し、SendMessage(WM_COMMAND・・・);しています。幸い、MFCはコマンドを実行する直前でコマンドUI更新ハンドラを呼び出して、コマンドを実行可能か調べているため、例えば「実行出来ないはずのメニューコマンドを実行する」というような事も起こりません（コマンド更新ハンドラでEnable(FALSE)となっているとwarningはTRACEされますが＾＾；）。</p>
<p>現在公開しているEDGE2β版では既にこの方法で実装しています。今のところ問題も出ていませんので、おそらく大丈夫かと思われます。</p>
]]></content:encoded>
			<wfw:commentRss>http://takabosoft.com/20050502133258.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>アクセラレータ不具合(VisualC++6.0 + MFC)</title>
		<link>http://takabosoft.com/20050414135559.html</link>
		<comments>http://takabosoft.com/20050414135559.html#comments</comments>
		<pubDate>Thu, 14 Apr 2005 04:55:59 +0000</pubDate>
		<dc:creator>takabosoft</dc:creator>
				<category><![CDATA[MFC]]></category>
		<category><![CDATA[ProgrammingTips]]></category>
		<category><![CDATA[日記]]></category>

		<guid isPermaLink="false">http://takabosoft.com/20050414135559.html</guid>
		<description><![CDATA[（一応解決しました。）
最近はEDGE2の動作チェックなどをやっているのですが、また新たな不具合が発生しまして・・・、これがなかなか曲者でして、今まで気が付きませんでしたがなんとEDGE1でも再現します＿&#124;￣&#124;○・・・。 [...]]]></description>
			<content:encoded><![CDATA[<p>（一応解決しました。）</p>
<p>最近はEDGE2の動作チェックなどをやっているのですが、また新たな不具合が発生しまして・・・、これがなかなか曲者でして、今まで気が付きませんでしたがなんとEDGE1でも再現します＿|￣|○・・・。</p>
<p>例によってシンプルなプロジェクトファイルと実行ファイルを用意しましたので、もし通りすがった方で良い解決策などをご存知の方がいらっしゃれば、私まで連絡をお願いいたします（という他力本願な日記です）。なお、興味のある方向けに実行ファイルも用意しました。</p>
<p><a href="http://takabosoft.com/wp-content/uploads/2005/04/accelkeyproj.lzh">Visual C++ 6.0 プロジェクトファイル</a><br />
<a href="http://takabosoft.com/wp-content/uploads/2005/04/accelkeyexe.lzh">実行ファイル</a></p>
<h4>概要</h4>
<p>今回の不具合は、アクセラレータキー（Ctrl+Zでアンドゥが効くような機構・・・ショートカットキーと呼ぶのが一般的？）が場合によって効かなくなるというものです。</p>
<h4>再現手順</h4>
<ol>
<li>起動する
<li>「↑（矢印）」キーが「浅い」というコマンドに割り当てられ、「↓」キーが「深い」というコマンドに割り当てられています。<br />
<img src="http://takabosoft.com/wp-content/uploads/2005/04/050414_00.png" alt="050414_00" title="050414_00" width="205" height="94" class="alignnone size-full wp-image-598" /></p>
<p><img src="http://takabosoft.com/wp-content/uploads/2005/04/050414_01.png" alt="050414_01" title="050414_01" width="324" height="96" class="alignnone size-full wp-image-599" /></p>
<p>つまり、「↑」キーを押せば「浅い」が実行され、「↓」キーを押せば「深い」が実行されるというわけです。</p>
<li>では試しに「↑」「↓」キーを押してみてください。<br />
どちらもコマンドが実行されるとメッセージボックスが表示され、「実行された」という事が目で見て解るようにしてあります。</p>
<p>どちらのキーでも処理が実行されることを確認してみてください。<br />
<img src="http://takabosoft.com/wp-content/uploads/2005/04/050414_02.png" alt="050414_02" title="050414_02" width="210" height="164" class="alignnone size-full wp-image-600" /></p>
<li>ここで、ツールボタン「ONで有効」の凹んでる状態を解除します（OFFになります）<br />
<img src="http://takabosoft.com/wp-content/uploads/2005/04/050414_03.png" alt="050414_03" title="050414_03" width="194" height="158" class="alignnone size-full wp-image-601" /></p>
<li>すると、「浅い」や「深い」が無効状態になります（無効状態にしています）。
<p>メニューを表示し、各コマンドが両方とも使えなくなっていル事を確認してください（必須）<br />
<img src="http://takabosoft.com/wp-content/uploads/2005/04/050414_04.png" alt="050414_04" title="050414_04" width="200" height="98" class="alignnone size-full wp-image-602" /></p>
<p><img src="http://takabosoft.com/wp-content/uploads/2005/04/050414_05.png" alt="050414_05" title="050414_05" width="320" height="96" class="alignnone size-full wp-image-603" /></p>
<li>さて、ここで「↑」「↓」キーを押してみてください。
<p>「浅い」や「深い」は使えない状態ですので、もちろん処理は実行されません。</p>
<li>では、ツールボタン「ONで有効」をもう一度凹まし、ONの状態にしてください。
<p><img src="http://takabosoft.com/wp-content/uploads/2005/04/050414_06.png" alt="050414_06" title="050414_06" width="194" height="158" class="alignnone size-full wp-image-604" /></p>
<li>これで内部的には「浅い」も「深い」も実行可能状態になります。<br />
（メニューは開かないでください。）</p>
<p>このまま、「↑」「↓」キーを押してみてください。</p>
<p>「浅い」は処理されますが、「深い」が処理されません。</p>
<p>「浅い」位置にあるコマンド（ルートの直下）は使えるのに、<br />
「深い」位置にあるコマンド（サブメニュー？）は使えないのです。</p>
<p>これが今回の不具合です。</p>
<li>ちなみに、このあとメニューを開き、「深い」が有効状態になっているのを確認してから「↓」キーを押せば処理されるようになります。
</ol>
<h4>EDGE1の場合・・・</h4>
<p>EDGE1の場合は、矢印キーで選択範囲を移動する事が出来るのですが、<br />
選択範囲が無い時点でメニューを見に行き、座標微調整コマンドが無効状態になっているのを確認してから、画像を選択し、矢印キーを押してみると、キーが効かなくなるという不具合が発生します。</p>
<h4>考察</h4>
<p>まだちょこっとしか調査していませんが、キーアクセラレータ機構については、キー入力系メッセージ（KEYDOWNとか）からTranslateAccelerator APIを通ってコマンド(WM_COMMAND)に変換されるようなのです。<br />
その際にTranslateAcceleratorは、対応するメニューコマンドが無効だとコマンドを送信しない仕様らしいんです（MSDNの資料は<a href="http://www.microsoft.com/japan/msdn/library/ja/jpwinui/html/_win32_translateaccelerator.asp">こちら</a>）。<br />
だから、MFCのフレームワークで深い位置にあるメニューコマンド状態が更新されないのかなぁなどと推測しています（あんまりWindowsSDKとかメッセージ処理とか詳しくないのでどっかかん違いしていたらごめんなさい）。</p>
<p>仕様なのか不具合なのか、どちらにせよ、便利であるはずのライブラリに時間を取られるのだけは勘弁してほしいです(´･ω･`)ｼｮﾎﾞｰﾝ</p>
<p>＃アクセラレータキー処理を自前でやれば問題無しかも？</p>
<p>＃今回は矢印キーばかりでしたが、「Ctrl+A」のような感じのキーも同様です</p>
]]></content:encoded>
			<wfw:commentRss>http://takabosoft.com/20050414135559.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MFCフレームワークと闘え！</title>
		<link>http://takabosoft.com/20050314145101.html</link>
		<comments>http://takabosoft.com/20050314145101.html#comments</comments>
		<pubDate>Mon, 14 Mar 2005 05:51:01 +0000</pubDate>
		<dc:creator>takabosoft</dc:creator>
				<category><![CDATA[MFC]]></category>
		<category><![CDATA[ProgrammingTips]]></category>
		<category><![CDATA[日記]]></category>

		<guid isPermaLink="false">http://takabosoft.com/20050314145101.html</guid>
		<description><![CDATA[土曜日に書いたツールバードッキングで嫌な感じ事件ですが、無事（？）に解決いたしました。
当初は闘う前から負けていた（だってドッキング部分はいろいろなサイトで難解と言われていましたから）のですが、きよのさんの協力もあってや [...]]]></description>
			<content:encoded><![CDATA[<p>土曜日に書いたツールバードッキングで嫌な感じ事件ですが、無事（？）に解決いたしました。</p>
<p>当初は闘う前から負けていた（だってドッキング部分はいろいろなサイトで難解と言われていましたから）のですが、きよのさんの協力もあってやる気が出まして(笑)、駄目元でデバッグをしていったところ、それっぽい原因を見つけ出すことができました。</p>
<p>折角ですので、VC6.0を使ってどうやって問題を解決したかなどを簡単に書き記しておこうと思います。</p>
<p>さてさて、ドッキングしているツールバーをドラッグ＆ドロップした際、ドロップした位置より下側にずれてドッキングしていまう、というのが今回の不具合です（詳しくは12日の日記を参照してください）。</p>
<p>なんとなく「ドロップしたあとのツールバー位置を決める処理」に不具合があるんだろうなぁとは予想出来ましたので、その辺をさぐろうと思ったのですが、ソースを見るに当たってまずは大体どんなかんじでドッキングしたツールバーなどを管理しているのか、データ構造を探ることにしました（その方がソース見ていて解りやすくなると思いまして）。</p>
<p>もともとCToolBarやCStatusBarのヘルプを見たときに、それらがCControlBarというクラスから派生していたのを何度か目にしていたため、「きっとメインフレームがCControlBarの一覧を持ってるんだろう」という憶測はしていました。</p>
<p>早速、CMainFrameの親クラスを参照機能でたどって行くとCFrameWndというクラスに</p>
<pre class="brush: cpp;">CPtrList m_listControlBars;</pre>
<p>という名前がそのままの変数を見つけました。</p>
<p>ためしに一つずつポインタを取得してみてGetWindowRectでウィンドウ座標を取り、その位置に四角形を描画してみたのですが、思ったとおり、全てのツールバーやステータスバーが格納されていました。</p>
<p>しかし実際にはそれだけでなく、謎のクラスCDockBarというクラス（これもCControlBarの派生クラス）が上下左右に1つずつ存在していました。どうやらこのCDockBarというのがツールバーのドッキングを受け入れるバーのようです（受け入れるバーと受け入れられるツールバーが同じリスト内に存在している、というのも不思議な気がしますが）。</p>
<p><img src="http://takabosoft.com/wp-content/uploads/2005/03/050314_00.png" alt="050314_00" title="050314_00" width="294" height="228" class="alignnone size-full wp-image-626" /></p>
<p>＃ちなみにCDockBarのコンストラクタにブレークポイントを設定してみたところ、<br />
　上下左右の4つだけでなく、ツールバーを浮かせた状態にした際にも生成されるようです。</p>
<p>CDockBarがドッキングを受け入れるバーならば、そのCDockBarがドッキングしているコントロールバーの座標を持っているんじゃないかと思い、さっそくソースを見ていったところ、</p>
<pre class="brush: cpp;">CPtrArray m_arrBars;    // each element is a CControlBar</pre>
<p>という怪しいポインタ配列を見つけたので、例によって一つずつポインタを取得してみてGetWindowRectでウィンドウ座標を取り、その位置に四角形を描画してみましたが、またも思ったとおり、ドッキングされているツールバーなどが格納されていました。<br />
ところが、中にはNULLという情報も含まれており、どういったルールでこの配列の中身が決まっているかが気になりました。</p>
<p>そこで、ツールバーのドッキング状態をいろいろ変えながらm_arrBarsがどのように変化するか試したところ、上の行から順番にコントロールバーのポインタが格納されており、NULLは「コントロールバーの改行」を意味するようでした。</p>
<p>つまり、<br />
<img src="http://takabosoft.com/wp-content/uploads/2005/03/050314_01.png" alt="050314_01" title="050314_01" width="185" height="138" class="alignnone size-full wp-image-627" /></p>
<p>↑このような状態では、</p>
<pre class="brush: cpp;">
    m_arrBars[0] = NULL;
    m_arrBars[1] = ツールバー1のアドレス;
    m_arrBars[2] = NULL;
    m_arrBars[3] = ツールバー2のアドレス;
    m_arrBars[4] = NULL;
    m_arrBars[5] = ツールバー3のアドレス;
    m_arrBars[6] = NULL;
</pre>
<p>このような配列状態になり、</p>
<p><img src="http://takabosoft.com/wp-content/uploads/2005/03/050314_02.png" alt="050314_02" title="050314_02" width="180" height="116" class="alignnone size-full wp-image-628" /></p>
<p>↑このような状態では、</p>
<pre class="brush: cpp;">
    m_arrBars[0] = NULL;
    m_arrBars[1] = ツールバー1のアドレス;
    m_arrBars[2] = ツールバー4のアドレス;
    m_arrBars[3] = NULL;
    m_arrBars[4] = ツールバー2のアドレス;
    m_arrBars[5] = NULL;
    m_arrBars[6] = ツールバー3のアドレス;
    m_arrBars[7] = NULL;
</pre>
<p>このような配列状態になりました。</p>
<p>「・・・ということは、ツールバーをドロップした際、この配列への挿入場所を導き出す処理がうまくいかず、こちらが期待する位置にツールバーが配置されず、下の段にドッキングしてしまうのではないか」、というような考えにいきつきました。</p>
<p>データ構造は大体解りましたので（？）ようやくここからドッキング部分のソースを追うことにします。</p>
<p>・・・どうやって追うのか？</p>
<p>10秒ぐらい悩みましたが、ドッキング後には、メインフレームのRecalLayoutが呼び出されると思い、ここにブレークポイントを設置し、実際にツールバーをドラッグ＆ドロップしてみたところ、見事にひっかかりました。</p>
<p><img src="http://takabosoft.com/wp-content/uploads/2005/03/050314_03.png" alt="050314_03" title="050314_03" width="282" height="84" class="alignnone size-full wp-image-629" /></p>
<p>そこからコールスタックウィンドウを駆使して呼び出し元を辿り、<br />
<img src="http://takabosoft.com/wp-content/uploads/2005/03/050314_04.png" alt="050314_04" title="050314_04" width="306" height="130" class="alignnone size-full wp-image-630" /></p>
<p>CDockContext::EndDrag()という関数の最初の方でまたブレークポイントを設置し、また実行してドラッグ＆ドロップして停止させて、今度はステップ実行でひとつずつ怪しいところが無いか見ていきました。</p>
<p>しばらく追っていき、<br />
CDockContext::EndDrag()　→　CFrameWnd::DockControlBar()　→　CDockBar::DockControlBar()　→CDockBar::Insert()　この関数内で先に出た「CPtrArray m_arrBars;」というポインタ配列へバーを挿入している事が判明しました。</p>
<p>というわけでこの関数の先頭にブレークポイントを設定して、実行→ツールバーをドラッグ＆ドロップ→ブレークポイントで停止させ、<br />
今度は変数ウォッチに、この関数内で使用している変数を表示させ、変数の変化を見ながらステップ実行していきました。</p>
<p>このCDockBar::Insert()という関数、完璧に理解したわけではありませんが、<br />
配列の先頭（＝一番上のコントロールバー）から順番に座標を照らし合わせながら、<br />
ドッキングしたいコントロールバーの「順番（配列番号）」を求め、ポインタを挿入している関数だと思われます。</p>
<pre class="brush: cpp;">
int CDockBar::Insert(CControlBar* pBarIns, CRect rect, CPoint ptMid)
{
    ASSERT_VALID(this);
    ASSERT(pBarIns != NULL);

    int nPos = 0;
    int nPosInsAfter = 0;
    int nWidth = 0;
    int nTotalWidth = 0;
    BOOL bHorz = m_dwStyle &amp; CBRS_ORIENT_HORZ;

    for (nPos = 0; nPos &lt; m_arrBars.GetSize(); nPos++)
    {
        CControlBar* pBar = GetDockedControlBar(nPos);
        if (pBar != NULL &amp;&amp; pBar-&gt;IsVisible())
        {
            CRect rectBar;
            pBar-&gt;GetWindowRect(&amp;rectBar);
            ScreenToClient(&amp;rectBar);
            nWidth = max(nWidth,
                bHorz ? rectBar.Size().cy : rectBar.Size().cx - 1);
            if (bHorz ? rect.left &gt; rectBar.left : rect.top &gt; rectBar.top)
                nPosInsAfter = nPos;
        }
        else // end of row because pBar == NULL
        {
            nTotalWidth += nWidth - afxData.cyBorder2;

            nWidth = 0;
            if ((bHorz ? ptMid.y : ptMid.x) &lt; nTotalWidth)
            {
                if (nPos == 0) // first section
                    m_arrBars.InsertAt(nPosInsAfter+1, (CObject*)NULL);
                m_arrBars.InsertAt(nPosInsAfter+1, pBarIns);
                return nPosInsAfter+1;
            }
            nPosInsAfter = nPos;
        }
    }

    // create a new row
    m_arrBars.InsertAt(nPosInsAfter+1, (CObject*)NULL);
    m_arrBars.InsertAt(nPosInsAfter+1, pBarIns);

    return nPosInsAfter+1;
}
</pre>
<p>この関数でどんな処理が行われているか、私の解釈で簡単に説明しますと・・・</p>
<p>コントロールバーというのは種類によってバーの高さが異なりますので、行の中で一番高いサイズをnWidthという変数で記憶しておいて、改行（=NULL）または表示されていないバーが来たら「高さの合計」を示すnTotalWidth変数にnWidthを足す、というような処理が入っています。</p>
<p>この高さ合計と、ドッキングしたい場所のY座標（中央）を比較し、条件が合えばその位置にバーを挿入、というような感じです。</p>
<p>＃垂直状態のドッキングも考慮しているとはいえ、何故「nWidth」という名前なのかはちょっとわかりません・・・</p>
<p>さて、デバッグ実行しているときに気が付いたのが、改行と表示されていないバーが連続で来たときなどに、</p>
<pre class="brush: cpp;">
    nTotalWidth += nWidth - afxData.cyBorder2;
</pre>
<p>という処理が実行されると、nTotalWidthが減るという事です。</p>
<p>nWidthは0ですが、afxData.cyBorder2は0ではないため（2だったかな？）<br />
改行＆表示されていないバーが来るたびに<br />
nTotalWidthの値がどんどん減っていきました。<br />
　<br />
　<br />
・・・これってバグじゃないの？<br />
　<br />
　<br />
　<br />
この部分の不具合疑惑が浮上し、ここをなんとか書き換えて実行しようと思いました。<br />
　<br />
書き換えたい気持ちは山々なのですが、ここはMFCソース内部、変えるのが困難な部分です。</p>
<p>誰か変えた人いないの！？ってなかんじでぐぐってみましたが、ヒットせず＿|￣|○</p>
<p>しょうがないので自分でやることに（＾＾；<br />
　<br />
　<br />
まず、CDockBar::Insertという関数はvirtual関数ではないため、オーバーライドさせることが出来ません。そんなわけで、virtual関数が出てくるまで呼び出し元をたどりました。</p>
<p>CDockContext::StartDrag(CPoint pt);<br />
という関数が仮想関数であることがわかったため、<br />
この関数からCDockBar::Insertまでのすべての呼び出し処理を変更すればCDockBar::Insert処理を別のものに変えられそうでした。</p>
<p>具体的には<br />
CDockContext::StartDrag() → CDockContext::Track() → CDockContext::EndDrag() → CFrameWnd::DockControlBar() → CDockBar::DockControlBar() →CDockBar::Insert()<br />
これら全ての関数を修正する必要があるという事です(´･ω･`)ｼｮﾎﾞｰﾝ</p>
<p>クラス別に見て</p>
<ul>
<li>CDockContext
<li>CFrameWnd
<li>CDockBar
</ul>
<p>これら3つがありますで、これらから新たにクラスを派生させ、そこで別関数を用意すれば良いという事です。<br />
（CFrameWndに関してはCMainFrameという関数がありますので、クラスを新しく用意する必要はありませんね。）</p>
<p>で、これらのクラスから新たに</p>
<p>CDockContext<br />
→CMyDockContext<br />
CDockBar<br />
→CMyDockBar</p>
<p>というクラスを作るのはまぁ出来るだろうとは思うのですが、<br />
いままでCDockContextクラスをnewしていた部分を今度はCMyDockContextクラスをnewさせるようにしないといけないわけで、それが出来るかどうかの実験から始めました。<br />
　<br />
　<br />
CDockContextのコンストラクタにブレークポイントを設定して生成タイミングなどを調査した結果、<br />
CControlBar::EnableDocking();関数内でnewされている事が解りました。</p>
<p>CToolBarから新たにクラスを派生させ、そこからEnableDocking()を作る、というのが普通かもしれませんが、<br />
なにしろツールバー以外にもコントロールバーというのは多数ありますから（ダイアログバーなど）<br />
少し汚い手ですが、</p>
<p>EnableDocking();させた後で全コントロールバーに対してメンバ変数m_pDockContextを見て、インスタンスあれば一旦deleteして、CMyDockContextをnewさせ、保持させておくという手段を用いました（爆</p>
<p>CDockBarの方はCFrameWnd::EnableDocking時に生成されるようでしたので、その関数のソースをそのままコピペしてnew CDockBar部分を書き換えました。</p>
<p>これでクラスのインスタンスをごっそり変える事が出来ましたので、<br />
CMyDockContextや、CMyDockBarのメンバ変数をコピペしたりして<br />
各関数を実装します。</p>
<p>CMyDockContext::StartDrag() → CMyDockContext::TrackDebug() → CMyDockContext::EndDragDebug()　→　CMainFrame::DockControlBarDebug() → CMyDockBar::DockControlBarDebug() →CMyDockBar::InsertDebug()</p>
<p>というように呼ばれるわけです。</p>
<p>CMyDockContext::EndDragDebug()　→　CMainFrame::DockControlBarDebug()<br />
というように、クラスが異なる呼び出しの場合には、<br />
呼び出す際の型キャストも必要です。</p>
<pre class="brush: cpp;">
    CMainFrame* pMainFrame = dynamic_cast&lt;CMainFrame*&gt;(m_pDockSite);
    if (pMainFrame) {
        pMainFrame-&gt;DockControlBarDebug(m_pBar, pDockBar, &amp;rect);
    }
    else {
        m_pDockSite-&gt;DockControlBar(m_pBar, pDockBar, &amp;rect);
    }
</pre>
<p>こんな感じで最終的にCMyDockBar::InsertDebug()が呼ばれるようにし、<br />
これでようやく・・・ようやくCDockBar::Insert部分をいじれるようになりました＿|￣|○</p>
<p>早速例の「高さの合計を示すnTotalWidth変数にnWidth足す」という部分に修正を試みます。</p>
<pre class="brush: cpp;">
#if 1
            if (nWidth &gt; 0) {
                nTotalWidth += nWidth - afxData.cyBorder2;
            }
#else
            nTotalWidth += nWidth - afxData.cyBorder2;
#endif
</pre>
<p>これで実行してみたところ、ドッキング不具合は発生しなくなりました！<br />
　<br />
　<br />
・・・長かった。<br />
　<br />
　<br />
そんなわけで治ったっぽいプロジェクトは<a href="http://takabosoft.com/wp-content/uploads/2005/03/toolbartest00bugfix.lzh">こちら</a>です。<br />
今後同じような問題にぶちあたった人のお役に立てられれば幸いです・・・。<br />
　<br />
　<br />
・・・Microsoftさん、貴重な休日を返して（T_T</p>
]]></content:encoded>
			<wfw:commentRss>http://takabosoft.com/20050314145101.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ツールバー不具合(VisualC++6.0 + MFC)</title>
		<link>http://takabosoft.com/20050312143654.html</link>
		<comments>http://takabosoft.com/20050312143654.html#comments</comments>
		<pubDate>Sat, 12 Mar 2005 05:36:54 +0000</pubDate>
		<dc:creator>takabosoft</dc:creator>
				<category><![CDATA[MFC]]></category>
		<category><![CDATA[ProgrammingTips]]></category>

		<guid isPermaLink="false">http://takabosoft.com/20050312143654.html</guid>
		<description><![CDATA[EDGE2のツールバーカスタマイズ周りを実装中なんですが、
カスタマイズとは関係無い部分でおかしな部分が見つかりました＿&#124;￣&#124;○
もし解決策、回避策などが解る技術者の方がおられましたら、
私まで連絡をお願いします。
＃M [...]]]></description>
			<content:encoded><![CDATA[<p>EDGE2のツールバーカスタマイズ周りを実装中なんですが、<br />
カスタマイズとは関係無い部分でおかしな部分が見つかりました＿|￣|○</p>
<p>もし解決策、回避策などが解る技術者の方がおられましたら、<br />
私まで連絡をお願いします。</p>
<p><font color=gray>＃Microsoftに質問メール送る方法が解らなかった＿|￣|○<br />
　プロフェッショナルサポートとか契約してないとメールで質問出来ないのかな～？<br />
　変わりにMSへ問い合わせてくれる人でも構いません(＾＾ゞ<br />
</font></p>
<h4>症状１　ツールバードッキングで嫌な感じ （解決したかも？）</h4>
<p><a href="http://takabosoft.com/wp-content/uploads/2005/03/toolbartest00.lzh">→問題部分のみを抽出したプロジェクトファイルはこちら(40KB)</a><br />
（Visual C++6.0が必要です）<br />
VisualC持ってないけど見てみたいという方は<a href="http://takabosoft.com/wp-content/uploads/2005/03/toolbartest00false.lzh">こちら</a>をどうぞ。</p>
<p>プロジェクトの主な作成手順は次の通りです。</p>
<ol>
<li>ウィザードでMFC→MDIアプリケーションを作成（他の設定はそのまま）
<li>CMainFrame::OnCreateにて
<ol>
<li>ツールバーを5個以上作成する
<li>作成したツールバーで、最初の2個だけを残し、残りのツールバーをShowControlBar(・・・,FALSE, TRUE);で非表示する
<li>また、症状がわかり易くなるように、ここでダイアログバーを一つ作成しています。（無くても症状は発生します）
</ol>
<li>ビルドし、実行します。
</ol>
<p>症状の再現方法は次の通りです。</p>
<ol>
<li>EXEを実行します。<br />
<img src="http://takabosoft.com/wp-content/uploads/2005/03/050312_00.png" alt="050312_00" title="050312_00" width="240" height="168" class="alignnone size-full wp-image-610" /></p>
<p>ツールバー5個中、2個が表示されています。<br />
<img src="http://takabosoft.com/wp-content/uploads/2005/03/050312_01.png" alt="050312_01" title="050312_01" width="368" height="125" class="alignnone size-full wp-image-611" /></p>
<li>上のツールバーを、ダイアログバーの下へドラッグ＆ドロップしてドッキングさせます。<br />
<img src="http://takabosoft.com/wp-content/uploads/2005/03/050312_02.png" alt="050312_02" title="050312_02" width="258" height="147" class="alignnone size-full wp-image-612" /></p>
<p>すると、普通にドッキングします。<br />
<img src="http://takabosoft.com/wp-content/uploads/2005/03/050312_03.png" alt="050312_03" title="050312_03" width="280" height="144" class="alignnone size-full wp-image-613" /></p>
<li>さて、ここでもう一つのツールバーを、さきほどのツールバーの横へドラッグ＆ドロップしてドッキングさせようとすると・・・
<p><img src="http://takabosoft.com/wp-content/uploads/2005/03/050312_04.png" alt="050312_04" title="050312_04" width="374" height="130" class="alignnone size-full wp-image-614" /></p>
<p>下にずれる。<br />
<img src="http://takabosoft.com/wp-content/uploads/2005/03/050312_05.png" alt="050312_05" title="050312_05" width="361" height="116" class="alignnone size-full wp-image-615" /></p>
</ol>
<p>これが嫌な症状です。<br />
ちなみに、がんばると（ちょっとダイアログバーへめり込むようにドロップすると）、隣へドッキングさせることも出来るのですが、また少しずらそうとすると、一段下がった場所へ勝手に配置されてしまいます。</p>
<p>二つしかツールバーが無い程度ならばいいのですが、それが複数になって、隣へ配置出来なくなるのは、ツールとしての使い勝手が悪くなる要因ともなりかねませんので、解決したいところです。</p>
<p>ツールバーは5個中2のみ表示、と書きましたが、5個全て表示したり、最初から2個しか<br />
作らなかった場合には、これらの症状は発生しません。</p>
<p>症状が発生しない期待通りの実行ファイルは<a href="http://takabosoft.com/wp-content/uploads/2005/03/toolbartest00true.lzh">こちら</a></p>
<p>MFC側の不具合のような気もするのですが、もしそうであっても直したい部分ではあります＾＾；</p>
<p>（20:00 追記）<br />
きよのさんからメールを頂きまして（有難うございます！）<br />
Visual C++ 6.0 Enterprise Edition SP6では症状が発生しないとの情報を頂きました。<br />
ちなみに私の環境は<br />
Visual C++ 6.0 Professional Edition SP6です。<br />
MFCのソースが異なるんでしょうかね～＿|￣|○<br />
もう少し追ってみます。</p>
<p>（20:24 追記）<br />
と思ったらEnterprise Editionでも症状が確認されたようです（＾＾；<br />
更にはVisual C++ .NET Professional 2003でも再現したそうです＿|￣|○</p>
<p>ツールバーの表示方法とか作成方法が間違ってるのかなぁ、と不安になってきました。</p>
<p>（3/13 0:55 追記）<br />
解決したかも？明日解決方法などを紹介します。</p>
<p>あ、掲示板のSISTさんサンクス！<br />
たしかにでにくくなってましたが、いろいろやっているうちに症状が再現してました。</p>
<h4>症状２　ツールサイズ変更でアプリがフリーズ （解決しました！）</h4>
<p>こちらはだいぶ解りやすい症状です＾＾；</p>
<p><a href="http://takabosoft.com/wp-content/uploads/2005/03/toolbartest02.lzh">→問題部分のみを抽出したプロジェクトファイルはこちら(40KB)</a><br />
（Visual C++6.0が必要です）<br />
VisualC持ってないけど見てみたいという方は<a href="http://takabosoft.com/wp-content/uploads/2005/03/toolbartest02false.lzh">こちら</a>をどうぞ。</p>
<p>プロジェクトの主な作成手順は次の通りです。</p>
<ol>
<li>ウィザードでMFC→MDIアプリケーションを作成（他の設定はそのまま）
<li>CMainFrame::OnCreateにて、デフォルトで作成されたツールバーの状態をいじり、ドロップダウンボタンをいくつか追加する（2つぐらいあると症状が発生しやすい）
<li>ビルドし、実行します。
</ol>
<p>症状の再現方法は次の通りです。</p>
<ol>
<li>EXEを実行します。
<li>ツールバーをドラッグ＆ドロップし、浮かせます（ドッキングを解除）<br />
<img src="http://takabosoft.com/wp-content/uploads/2005/03/050312_06.png" alt="050312_06" title="050312_06" width="249" height="169" class="alignnone size-full wp-image-619" /></p>
<p><img src="http://takabosoft.com/wp-content/uploads/2005/03/050312_07.png" alt="050312_07" title="050312_07" width="287" height="140" class="alignnone size-full wp-image-620" /></p>
<li>あとは、その浮いたツールバーの上の部分を上へドラッグするとフリーズします。<br />
<img src="http://takabosoft.com/wp-content/uploads/2005/03/050312_08.png" alt="050312_08" title="050312_08" width="287" height="140" class="alignnone size-full wp-image-621" />
</ol>
<p>ドロップダウンボタンが2つぐらい有ると起こる症状のようです。<br />
フリーズ状態でVCのブレークを実行すると、CToolBar::SizeToolBarやらCToolBar::CalcSizeで無限ループに陥っているのかなぁ、というように思えます。<br />
各関数にvirtualがついていないので、単純にオーバーライドして値をTRACEさせるという技も使えず＾＾；</p>
<p>こちらもMFC側の不具合のような気もするのですが、もしそうであっても直したい部分ではあります。</p>
<p>（追記）<br />
CToolBar::CalcDynamicLayoutがvirtualになっていましたので、オーバーライドし、その中で使用されている関数などをMFCのソースからコピペ、問題を探ったところ、<br />
CMyToolBar::SizeToolBarの中で無限ループに陥っていることが解りました。</p>
<p>無限ループにならないように、勝手にreturnしてみたのですが、これで良いのやら・・・<br />
→修正後のプロジェクトファイルは<a href="http://takabosoft.com/wp-content/uploads/2005/03/toolbartest02ok.lzh">こちら</a></p>
<pre class="brush: cpp;">
        while (sizeMin.cx &lt; sizeMax.cx)
        {
            sizeMid.cx = (sizeMin.cx + sizeMax.cx) / 2;
            WrapToolBar(pData, nCount, sizeMid.cx);
            sizeMid = CalcSize(pData, nCount);

// ここの判定分を追加してみた by takabo soft
#if 1
            if (sizeMax == sizeMid) {
                return;
            }
#endif

            if (nLength &lt; sizeMid.cy)
            {
                if (sizeMin == sizeMid)
                {
                    WrapToolBar(pData, nCount, sizeMax.cx);
                    return;
                }
                sizeMin = sizeMid;
            }
            else if (nLength &gt; sizeMid.cy)
                sizeMax = sizeMid;
            else
                return;
        }
</pre>
<p>（20:00 追記）<br />
きよのさんからメールを頂きまして（ありがとうございます）、MSのサポートサイトにて解決策があると教えていただきました！<br />
<a href="http://support.microsoft.com/default.aspx?scid=kb;ja;190501">http://support.microsoft.com/default.aspx?scid=kb;ja;190501</a><br />
すっきりです(笑)</p>
]]></content:encoded>
			<wfw:commentRss>http://takabosoft.com/20050312143654.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>あたり判定(MFC)</title>
		<link>http://takabosoft.com/20040915154957.html</link>
		<comments>http://takabosoft.com/20040915154957.html#comments</comments>
		<pubDate>Wed, 15 Sep 2004 06:49:57 +0000</pubDate>
		<dc:creator>takabosoft</dc:creator>
				<category><![CDATA[MFC]]></category>
		<category><![CDATA[ProgrammingTips]]></category>
		<category><![CDATA[日記]]></category>

		<guid isPermaLink="false">http://takabosoft.com/20040915154957.html</guid>
		<description><![CDATA[相互リンク1件追加しました。

Dot+s（ドット絵）

このサイトの管理人さんであるウォーターさんから
相互リンクの依頼メールを頂いていたのですが、
トップページ３回連続リンク更新のみってのは寒いな（＆多忙）って事で
 [...]]]></description>
			<content:encoded><![CDATA[<p>相互リンク1件追加しました。</p>
<ul>
<li><a href="http://www2.odn.ne.jp/willowisp/">Dot+s</a>（ドット絵）</li>
</ul>
<p>このサイトの管理人さんであるウォーターさんから<br />
相互リンクの依頼メールを頂いていたのですが、<br />
トップページ３回連続リンク更新のみってのは寒いな（＆多忙）って事で<br />
「明日やろう」の無限ループに突入。</p>
<p>昨日再度メールを貰ってしまったのでbreakしました（＾＾；<br />
気が付けば最初に依頼されたときから2週間も経ってました・・・早っ。<br />
可愛そうな事をしてしまってごめんなさい＿|￣|○＞ウォーターさん</p>
<p>最近仕事でシューティングゲームっぽいものを作っているのですが(MFCで)、<br />
「あたり判定」処理を</p>
<pre class="brush: cpp;">
CRect rcMy; // 自機の矩形とする
CRect rcBullet; // 弾の矩形とする
if (!(rcMy &amp; rcBullet).IsRectEmpty()) {
（当たっている）
}
</pre>
<p>なんて書いて横着っぷり（？）を発揮しています。<br />
最近のCPUパワーなら無駄も無視出来ると思い込んでマス。</p>
]]></content:encoded>
			<wfw:commentRss>http://takabosoft.com/20040915154957.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

