鏑矢の憂鬱2000年8月後半
透明1ドットイメージ
 
2000/08/16 (Wed)
・今日はお休みします。
透明1ドットイメージ
 
2000/08/17 (Thu)
・今日もプログラミング辞書書き。「アトミック」とか難しいのが(汗)。辞書引くと「原子」とか出るし、 MSDN は「アトミック」ってカタカナだし(泣)。ただ、こういう単語こそ、追加していく価値があるかなとか。それこそ、他の辞書とか見ても分かんない単語だと思うし。まー、いろんなサイト見たりして苦労して調べたのをタダで載っけるのもアレかなと思うが(爆)、でもこれがヒット数の原動力のひとつだしね。
 
・プログラミング辞書のいいところは、更新が頻繁だから、間違っててもすぐ直せるところ(爆)。たとえば CMemFile を「ファイルマッピングの MFC 版」とか書いてたんだけど、実は全然関係ないことが発覚(爆)。 malloc() 使ってるからグローバルオブジェクトじゃないですな。そーゆーのも速攻で直したりできるのが助かります。
 
・実際、プログラミング辞書をやってくと、自分の知識の隙間をびっちり埋められる感じかな。間違ってる部分、まだ触れてない部分に知識を詰め込んでいけるし、わすれても読めばいいし(爆)。ま、そんなわけで、色々わての役に立ってたりするのでした。皆さんにもお勧め<そんなめんどいの絶対誰もしねぇ。
 
・でわまたっ!
透明1ドットイメージ
 
2000/08/18 (Fri)
・今日はお便りが来てるからそれの紹介をしましょー。
 
透明1ドットイメージ
透明1ドットイメージ
 早速質問なんですが、MFCでクライアント領域だけを表示させたい場合はどのようにすればいいんでしょうか?
 つまり、タイトルバーもけしてウィンドウのエッジもけしたウィンドウにしたいんですが...
CMainFrame::PreCreateWindow関数の引数の構造体CREATESTRUCT csを
 
cs.dwExStyle = WS_POPUP;
 
とやると思ったんですけど、「空のドキュメントの作成に失敗しました」ってでてきてしまいます。
 
 これって、どのようにすればいいんでしょうか?
透明1ドットイメージ
透明1ドットイメージ
 
・と、その続き。
 
透明1ドットイメージ
透明1ドットイメージ
 さっき、クライアント領域関係について質問したものですが、わかりました。っていうかバカなこといってしまいました。拡張スタイルに指定しまったようです。すみません! さっきの質問はなかったことに...
 
 でも、新たに問題が浮上してしまったので質問します。(なんか騒がしくてすみません。)
 
 WS_POPUPでタイトルバーとかは消すことはできたのですが、今度は微妙にウィンドウのエッジが残ってしまいます。内側のエッジなのですが...
 
 これはどのように消すか教えてください。
 よろしくお願いします。
透明1ドットイメージ
透明1ドットイメージ
 
・うおホントだ、 dwExStyle って気付かなかった(汗)。えーっと、いくつか思い付くこと。まず、ウィンドウ枠を指定するウィンドウスタイルがあるんです。 WS_BORDER とか WS_THICKFRAME とか、拡張スタイルの方にも WS_EX_CLIENTEDGE とか WS_EX_WINDOWEDGE 。こういったものが指定されてないかどうか、っていうことがひとつ。
 
・もうひとつ。最初のお便り見ると CMainFrame って書いてあるから SDI だと思うんだけど、実は SDI って、後ろのフレームウィンドウと、手前のビューウィンドウとのふたつのウィンドウが重なってるんです。 MSDN の「フレーム ウィンドウのトピック」とかに書いてあります(でもこれ分かりにくい……)。ビューウィンドウのサイズはちょうどクライアント領域と同じ。だけど変な縁とかあるのかもしんない。だから、もしかしたらビューウィンドウの方もスタイルを変えなきゃいけないかもしんない。
 
・ただそう考えると、わざわざフレームウィンドウとビューウィンドウを用意する意味がないような気も(汗)。んでも MFC 使ってるとこーゆーの変えるの面倒だからなー、変でもこれで行った方が楽かもしんない。ドキュメントアーキテクチャーとか必要だと変えようがないし。あーあと思い付くのは、そのエッジは必ずあるもの、とか(汗)。 API で CreateWindowEx() で、一番シンプルなウィンドウ作って確認した方がいいかもしんない。
 
・でわまたっ!
透明1ドットイメージ
 
2000/08/19 (Sat)
・今日もお便りの紹介。
 
透明1ドットイメージ
透明1ドットイメージ
 早速、枠の件どうもありがとうございました。  手前のビューフレームについて、わすれてました。
 で、早速、スタイルとか変更してみたんですがダメでした。
 それで、
 
AfxGetMainWnd()->m_hWnd
 
でウィンドウハンドルを取得して手前のフレームウィンドウを乗り越えて描画したらうまくとりはらえました。(この場合はDirectXにこのWindowハンドルを渡して、塗りつぶしました。)
 
 しかし、なんでスタイルで変更できないんでしょう...
 仕様!?
 
 ところで、また質問があるんですが、ウィンドウを常に後ろに置いとく方法はないもんなんでしょうか?
透明1ドットイメージ
透明1ドットイメージ
 
・「常に後ろに置いておく」って難しそう。「常に手前に」なら WS_EX_TOPMOST とかあるけど。後ろだと SetWindowPos() に HWND_BOTTOM ってことになるから、タイマー掛けておいてこまめにするか、フックを掛けておいて手前に来そうなときにするか、っていうところだけど、どっちにしろうまくいくか不明。ウィンドウのZ位置を頻繁に変えると、他のウィンドウの再描画が頻繁に行われて重くなっちゃうし。……デスクトップの子ウィンドウとして作れないかな(爆)。もしできたら手前にはこれないだろうけど、できるんかなぁ。
 
・ビューのウィンドウスタイルは変えられると思うです。方法は CFrameWnd::GetActiveView() でビュー取得して ModifyStyle() で。変わったかどうかは Spy++ で確認できるから。ただ、こっちで試してみたら、なんかウィンドウの再描画をしなきゃいけないみたいです。フレームウィンドウのサイズ変えたら、そのときにウィンドウの見た目が変わりました。なんで、フレームウィンドウ側でそーゆー処理をしたらいいのかも。ってゆーかウィンドウ全体の再描画ってどーすればできるんだっけ(汗)。
 
・でわまたっ!
透明1ドットイメージ
 
2000/08/20 (Sun)
・プログラミング辞書、1週ごとに20以上単語が増えていく(汗)。シャレにならんなー。今日はこれだけ(汗)。
 
・でわまたっ!
透明1ドットイメージ
 
2000/08/21 (Mon)
・今日はお休み〜。
透明1ドットイメージ
 
2000/08/22 (Tue)
・今日はお休みです。そいや、フリーウェアのマイナーバージョンアップの話はどこへやら……。
透明1ドットイメージ
 
2000/08/23 (Wed)
・今日はお便りを紹介します。ってゆーか、まともな更新って、お便りが来たときだけのよーな気が(汗)。
 
透明1ドットイメージ
透明1ドットイメージ
 はじめまして。先日よりMFCを勉強し始めたのですが、メニューについてわからないことがあり、質問致します。VC++でSDIの画面を作り、そこに動的にメニューを追加しました。その追加したメニューでアクセラレータキーを使用できるようにしたいのですが、どうしても、やり方がわかりません。現在、CreateAcceleratorTableを用いて、試みているのですが、プログラムの書き方が悪いのか、根本的に手段が間違っているのか追加したメニューに対して、全くアクセラレータキーを使うことができません。何かよい解決策をご存知でしたら、恐れ入りますが、アドバイスをお願い致します。
透明1ドットイメージ
透明1ドットイメージ
 
・初めまして〜。んーと、ちょっと時間なかったんで追認してない状態で書くからそのつもりで聞いてくださいな。基本的には CreateAcceleratorTable() で追加するんだと思います。そこで渡す ACCEL の ACCEL::cmd に整数値入れるでしょ、この値と、新しく作ったメニューのIDの値が同じものが、アクセラレーターとして働くんじゃないかなと思うです。この値がうまく一致してるかどうかチェックしてみてください。
 
・メニューに表示される「 Ctrl+X 」とかは、実際に書き込まないとダメみたいですね。これは動的追加するときに書き加えるようにすれば大丈夫かな。この辺の整合性が難しそう。んーそういうわけで、その辺チェックしてみてください。こちらでも明日……はちょっと忙しいかも(汗)。明日かあさってにはこっちでも試してみます。
 
・でわまたっ!
透明1ドットイメージ
 
2000/08/24 (Thu)
・今日も昨日に引き続きお便り紹介っ!
 
透明1ドットイメージ
透明1ドットイメージ
 こんにちは。さっそく、ご解答していただきまして、ありがとうございます。今日も色々と試行錯誤してみたのですが、やはり上手くいかなくてすこし、落ち込み気味です。今の状態としては動的にメニューを作成することはできています。その後に、CreateAcceleratorTableを作成しています(動的にアクセラレータテーブルを作成しています)。これはSDIのMainFrm.cppのOnCreateの部分に書いています。ご指摘を受けた、ACCEL構造体については確認済みで、正しい値を設定しています。やはり、MFCの裏の裏技があるのでしょうか・・・。たびたび申し訳ありませんが、よきアドバイスをお願い致します。
透明1ドットイメージ
透明1ドットイメージ
 
・というわけで、こちらでもテストしてみました。まずは最初からあるメニュー( ID_FILE_OPEN )をアクセラレーターで機能するように……としたら、これがまた大変だった(汗)。とゆーわけで今回テストはここまでしかできなかったです。動的にメニュー追加するのは明日してみますね。で、実際に、次のようなコードを書きました。
 
HACCEL GetAccel()
{
	// 一度だけ機能するように。
	static HACCEL s_hAccel = NULL;
	if( s_hAccel != NULL )
		return s_hAccel;
	ACCEL stAccel;
	stAccel.fVirt = FCONTROL | FVIRTKEY | FVIRTKEY;
	stAccel.cmd = ID_FILE_OPEN;
	stAccel.key = 'B';
	s_hAccel = CreateAcceleratorTable( &stAccel, 1 );
	TRACE( "%X\n", s_hAccel );
	return s_hAccel;
}
	
 
・仮想キーコードをどうするかのフラグでやたら手間取ってしまった(汗)。で、実はこれだけじゃダメです。アクセラレーターのシステムっていうのは【メッセージループでメッセージを TranslateAccelerator() に渡す】ことで実行されます。 TranslateAccelerator() の呼び出しで「アクセラレーターに入ってるキーが押されたかなー」とゆーチェックがされて、もしあればそれをコマンド ID へと変換します。
 
・で、この TranslateAccelerator() の呼び出し時に、照らし合わせるアクセラレーターテーブルのハンドル、上の例だと s_hAccel を渡すんです。つまりここをなんとかしないと、全然意味ないんです(汗)。でも MFC はこの部分をカスタマイズする方法を提供してくれてました。いやー、ハードコーディングされてたら死ねるところだったです。で、その方法は、ドキュメントクラス(プロジェクト内の CDocument 派生クラス)で GetDefaultAccelerator() をオーバーライドすること。
 
HACCEL CT_SDI03Doc::GetDefaultAccelerator()
{
	return GetAccel();    // アクセラレーターテーブルのハンドル。
}

	
 
・これで、 TranslateAccelerator() にこの関数の戻り値を渡してくれるんで、アクセラレーターが機能するはず。これ、情報皆無(汗)。一応ナレッジベースの CPJ3887 に載ってるけど、実際には MFC のソースコード見て調べました。これしてなかったら試してみて。もししてたらごめんです。そのあとのメニュー追加の部分を明日の更新までにしときますんでそれまでお待ちを。
 
・でわまたっ!
透明1ドットイメージ
 
2000/08/25 (Fri)
・う”〜、プログラミング辞書疲れた(汗)。なんか知らない単語多いなー、 COM がらみは結構辛いかもしんない。むぅ。
 
・昨日の続き。メニューの動的追加をしてみました。方法はCodianに書いたのと同じ。このメニューのIDとアクセラレーターのIDを同じにしたらうまく働きました。たぶん昨日のオーバーライドの部分が鍵なんじゃないかなー。
 
・そのオーバーライドの部分が分かりにくいかもしんないんでもう一度ちゃんと書きます。オーバーライドっていうのは C++ の機能のひとつで、継承元クラスと同じメンバ関数を派生クラスでも作ることで、継承元のじゃなく派生先のメンバ関数を呼んでもらえるっていうものです。詳しくは C++ の本を読んでください。
 
・ MFC のソースコードを見ると、 CDocument::GetDefaultAccelerator() っていうメンバ関数があります。 MFC 内部のメッセージループは、このメンバ関数の戻り値を TranslateAccelerator() に渡すことで、アクセラレーターを機能させています。でも、 CDocument::GetDefaultAccelerator() の中身は単に NULL を返すだけ。 NULL を返すと、メッセージループ側はリソースのアクセラレーターテーブルを使用するよう実装されてます。
 
・そこで、 CDocument::GetDefaultAccelerator() をオーバーライドします。このメンバ関数は virtual って仮想関数になってるから、オーバーライドすると、 CDocument::GetDefaultAccelerator() じゃなくオーバーライド後のメンバ関数が呼び出されるようになります。
 
・実際のオーバーライドの方法だけど、プロジェクトの中に CDocument の派生クラスがあるから、そのクラスの中に GetDefaultAccelerator() のメンバ関数を作ればOK。昨日書き忘れたんだけど、クラスの定義部(ヘッダーファイルの中の方)にも、メンバ関数書かないとダメ。こんな感じに。
 
// プロジェクト内の CDocument 派生クラスが CT_SDI03Doc の場合。
// T_SDI03Doc.h 内。
class CT_SDI03Doc : public CDocument
{
	HACCEL GetDefaultAccelerator();
// あとはそのまま。
}:
	
 
・で、あと昨日と同じのを実装部(ソースファイルの方)にも書けばOK。
 
// T_SDI03Doc.cpp 内。
HACCEL CT_SDI03Doc::GetDefaultAccelerator()
{
	return GetAccel();    // アクセラレーターテーブルのハンドル。
}
	
 
・これでオーバーライド完了。面倒じゃないんだけど、ソースコード見ないとこーゆー仕組みになってるって分かんないのがあれかな。皆さんはこーゆー設計はしないようにしましょうねー。
 
・でわまたっ!
透明1ドットイメージ
 
2000/08/26 (Sat)
・今日はお便り紹介っ!
 
透明1ドットイメージ
透明1ドットイメージ
 大変初歩的な質問で恐縮です。  BCB5でプログラムの勉強を始めたばかりです。
 coutの出力を標準出力ではなく,LabelやEditに出力するにはどうしたらよいのでしょうか?
 御教示願えれば幸いです。
透明1ドットイメージ
透明1ドットイメージ
 
・初めまして〜。えーっと、 BCB5 は持ってないんで Label や Edit がどういうのか分からないんです、ごめんなさい。たぶん char * にさえできればこういうのに渡せますよね。えっと、基本的に「 cout に渡したのが自動的に他の部分に表示される」ことはちょっと難しいです。なので、 cout に似たのを使います。
 
・ cout は「標準 C++ ライブラリ」の std::ostream っていうクラスの変数です。で、この cout の代わりに、 std::strstream っていうのを使うと、似たような感じで char 配列に文字列を書き込むことができます。つまり << を使って書き込めるってこと。こんな感じに。
 
#include <iostream>
#include <strstream>	// をインクルードしてください。

void CharCopy()
{
	char ch[130];
	std::strstream cStrStrm
			( ch		// 文字配列へのポインタ。
			, 128		// 書き込める範囲。
			, std::ios::out );	// 書き込み専用。

	cStrStrm
		<< "Written.."
		<< std::endl
		<< std::ends;

	// あとは、 ch を Label や Edit に渡せばOK。
}
	
 
・つまり、上の例で cStrStrm を cout の代わりに使って、そのあと ch を Label や Edit に渡すように処理すればOKです。あーでも、その辺が実は難しいのかなぁ。まぁとりあえず試してみてください。
 
・ちなみにこのコードは、メールマガジンの「 STL & iostream 入門」に載せたのを少し変えたもの(汗)。10月になったらバックナンバー公開するからそんときにもう一度見てくださいね。こういうとき、メールマガジンは不便かも……。
 
・でわまたっ!
透明1ドットイメージ
 
2000/08/27 (Sun)
・今日はお休みします。
透明1ドットイメージ
 
2000/08/28 (Mon)
・今日はお便りを紹介。
 
透明1ドットイメージ
透明1ドットイメージ
 こんにちは。アクセラレータキーについて、お世話になった者です。お陰様で、思うような動作をさせることができました!!ありがとうございます!!!!!ところで、ご解答してくださった事に関してお調べになるときに「ナレッジベースの CPJ3887 」を参照されたとのことですが、もし、差し支えなければそのURLを教えて頂けないでしょうか。また、「MFC のソースコード見て調べました。」とのことですが、どの書籍を参照されたのか教えていただけませんでしょうが。まだまだ、未熟なもので、正直なところどの様なものを調べればよいのかよくわからなくて・・・・・。厚かましいお願いで申し訳ありませんが、教えて頂ければ幸いです。よろしくお願い致します。
透明1ドットイメージ
透明1ドットイメージ
 
・おー、うまくいって良かったです。最近すぱっと答えられること少なくて(汗)。えっと、まず「ナレッジベース」ですが、ホントは英語で KNOWLEDGE BASE って書くもので、マイクロソフトが出してる公式の「バグ情報」です。日本語だと「サポート技術情報」って訳されてるのかな。
 
・ CPJ3887 はそのナレッジベースの「文章番号」。 MSDN なら、この番号で検索するとその文章が出るはず。サポート技術情報のホームページで検索すれば見つか……らねぇ!!(爆) なんでぇ? と思ったら文章番号変わってるし(汗)。えっと、ネット版の文章番号は J020618 です。これで検索すれば見つかるはず。ちなみに J020618 のページはここです。
 
・さて後半、「MFC のソースコード」は、 Visual C++ のCD−ROMに入ってると思います。わてはフルインストールしちゃってるけど。標準設定でインストールすると C:\Program Files\Microsoft Visual Studio\VC98\MFC\SRC にソースコードが入ってるはず。CD−ROMでも同じようなパスだと思うです。つっても実際にここを見にいくわけじゃなくて、 VC の【編集】−【ファイルから検索】でこのパスを指定して、何かないかなーとあら探しすることの方が多いです。
 
・今回の場合、 API の TranslateAccelerator() が鍵になってると思ったんで、 MFC のどこでこれが呼ばれてるのかをさっきの【ファイルから検索】で調べて、 CFrameWnd::PreTranslateMessage(MSG* pMsg) で呼ばれててそこで TranslateAccelerator() に渡されてるアクセラレーターテーブルが CFrameWnd::GetDefaultAccelerator() から返されたものでそれがまた CDocument::GetDefaultAccelerator() から返されたもので、この CDocument::GetDefaultAccelerator() がオーバーライド用に仮想化されてたからあーそーゆー仕組みになってたんだ、とゆー。ソースコード読めるようになるとかなり色々分かってくるです。
 
・でわまたっ!
透明1ドットイメージ
 
2000/08/29 (Tue)
・今日はお休み〜。
透明1ドットイメージ
 
2000/08/30 (Wed)
・今日はお休みします。
透明1ドットイメージ
 
2000/08/31 (Thu)
・今日はお便りを2通紹介。って、お便り来てないときしか更新しとらん(汗)。まーそれもいっか。えっと、ひとつめのお便り。
 
透明1ドットイメージ
透明1ドットイメージ
 こんにちは。初めましてです。
 今ウインドウのビュー領域をキャプチャするプログラムを作成しているのですが、他のウインドウに隠れているウインドウを前面に出さないでそのままキャプチャする、ということはできるのでしょうか ? また、最小化されているウインドウのビューについても、そのままで同様のことができますか ?
透明1ドットイメージ
透明1ドットイメージ
 
・どうも初めまして〜。これ実際にコード書いて試してみました。方法はウィンドウハンドルからデバイスコンテキストハンドルを取得してビットマップを転送しちゃうっていうもの。ウィンドウハンドルは、キャプチャしたいウィンドウのハンドルを Spy++ で調べて直打ちしてます(汗)。まーテスト用ってことで。 AfxGetMainWnd() は MFC の関数で、自アプリの親ウィンドウを返すものです。コードはこんな感じ。
 
void Test()
{
	HDC hSourceDc
		= ::GetDC( (HWND)0x92C );
	::BitBlt
		( AfxGetMainWnd()->GetDC()->GetSafeHdc()
		, 0, 0, 100, 100
		, hSourceDc
		, 0, 0, SRCCOPY );
}
	
 
・結果:失敗(汗)。画面をキャプチャリングしたみたいに、上に乗っている画像がそのまま来ちゃいますね。これ以外に方法は思い付かないなー。ちょっと特殊な方法としては、グローバルフックを掛けて、アクティブになった時を見計らってキャプチャリングして取っておくとか(汗)。なんか邪道だなー、しかも一度もアクティブにならなかったら失敗するし。こーゆーこと実現してるアプリ誰か知ってたら教えて〜、それ調べてみるから。
 
・もうひとつお便り。
 
透明1ドットイメージ
透明1ドットイメージ
 こんにちは。アクセラレータキーについてお世話になったものです。ナレッジベースの件まで、色々と教えて頂きましてありがとうございます。お陰様で、色々な資料を集めることができ、作業がはかどっております。また、質問することが多々あると思いますが、そのときはどうぞよろしくお願い致します。本当にいろいろとありがとうございました。
透明1ドットイメージ
透明1ドットイメージ
 
・どうもです〜。ナレッジベースを含めて、 MSDN はホント便利です。昔は VC に付いてなかったんだよねー。いい時代だ(汗)。いやマジでさ、これなかったらプログラミングなんてできないって。 VC でする以外にも、ランタイムの使用例とかすぐ見つけられるし、色々読むと意外なこと分かるし。会社入って、これ使えなかったりしたらちょっと死ねる……。
 
・でわまたっ!
 
 
(C)KAB-studio 2000 ALL RIGHTS RESERVED.