|
・今日はお休みします。
|
・今日もプログラミング辞書書き。「アトミック」とか難しいのが(汗)。辞書引くと「原子」とか出るし、 MSDN は「アトミック」ってカタカナだし(泣)。ただ、こういう単語こそ、追加していく価値があるかなとか。それこそ、他の辞書とか見ても分かんない単語だと思うし。まー、いろんなサイト見たりして苦労して調べたのをタダで載っけるのもアレかなと思うが(爆)、でもこれがヒット数の原動力のひとつだしね。
・プログラミング辞書のいいところは、更新が頻繁だから、間違っててもすぐ直せるところ(爆)。たとえば CMemFile を「ファイルマッピングの MFC 版」とか書いてたんだけど、実は全然関係ないことが発覚(爆)。 malloc() 使ってるからグローバルオブジェクトじゃないですな。そーゆーのも速攻で直したりできるのが助かります。 ・実際、プログラミング辞書をやってくと、自分の知識の隙間をびっちり埋められる感じかな。間違ってる部分、まだ触れてない部分に知識を詰め込んでいけるし、わすれても読めばいいし(爆)。ま、そんなわけで、色々わての役に立ってたりするのでした。皆さんにもお勧め<そんなめんどいの絶対誰もしねぇ。 ・でわまたっ! |
・今日はお便りが来てるからそれの紹介をしましょー。
|
|
・と、その続き。
|
|
・うおホントだ、 dwExStyle って気付かなかった(汗)。えーっと、いくつか思い付くこと。まず、ウィンドウ枠を指定するウィンドウスタイルがあるんです。 WS_BORDER とか WS_THICKFRAME とか、拡張スタイルの方にも WS_EX_CLIENTEDGE とか WS_EX_WINDOWEDGE 。こういったものが指定されてないかどうか、っていうことがひとつ。
・もうひとつ。最初のお便り見ると CMainFrame って書いてあるから SDI だと思うんだけど、実は SDI って、後ろのフレームウィンドウと、手前のビューウィンドウとのふたつのウィンドウが重なってるんです。 MSDN の「フレーム ウィンドウのトピック」とかに書いてあります(でもこれ分かりにくい……)。ビューウィンドウのサイズはちょうどクライアント領域と同じ。だけど変な縁とかあるのかもしんない。だから、もしかしたらビューウィンドウの方もスタイルを変えなきゃいけないかもしんない。 ・ただそう考えると、わざわざフレームウィンドウとビューウィンドウを用意する意味がないような気も(汗)。んでも MFC 使ってるとこーゆーの変えるの面倒だからなー、変でもこれで行った方が楽かもしんない。ドキュメントアーキテクチャーとか必要だと変えようがないし。あーあと思い付くのは、そのエッジは必ずあるもの、とか(汗)。 API で CreateWindowEx() で、一番シンプルなウィンドウ作って確認した方がいいかもしんない。 ・でわまたっ! |
・今日もお便りの紹介。
|
|
・「常に後ろに置いておく」って難しそう。「常に手前に」なら WS_EX_TOPMOST とかあるけど。後ろだと SetWindowPos() に HWND_BOTTOM ってことになるから、タイマー掛けておいてこまめにするか、フックを掛けておいて手前に来そうなときにするか、っていうところだけど、どっちにしろうまくいくか不明。ウィンドウのZ位置を頻繁に変えると、他のウィンドウの再描画が頻繁に行われて重くなっちゃうし。……デスクトップの子ウィンドウとして作れないかな(爆)。もしできたら手前にはこれないだろうけど、できるんかなぁ。
・ビューのウィンドウスタイルは変えられると思うです。方法は CFrameWnd::GetActiveView() でビュー取得して ModifyStyle() で。変わったかどうかは Spy++ で確認できるから。ただ、こっちで試してみたら、なんかウィンドウの再描画をしなきゃいけないみたいです。フレームウィンドウのサイズ変えたら、そのときにウィンドウの見た目が変わりました。なんで、フレームウィンドウ側でそーゆー処理をしたらいいのかも。ってゆーかウィンドウ全体の再描画ってどーすればできるんだっけ(汗)。 ・でわまたっ! |
・プログラミング辞書、1週ごとに20以上単語が増えていく(汗)。シャレにならんなー。今日はこれだけ(汗)。
・でわまたっ! |
・今日はお休み〜。
|
・今日はお休みです。そいや、フリーウェアのマイナーバージョンアップの話はどこへやら……。
|
・今日はお便りを紹介します。ってゆーか、まともな更新って、お便りが来たときだけのよーな気が(汗)。
|
|
・初めまして〜。んーと、ちょっと時間なかったんで追認してない状態で書くからそのつもりで聞いてくださいな。基本的には CreateAcceleratorTable() で追加するんだと思います。そこで渡す ACCEL の ACCEL::cmd に整数値入れるでしょ、この値と、新しく作ったメニューのIDの値が同じものが、アクセラレーターとして働くんじゃないかなと思うです。この値がうまく一致してるかどうかチェックしてみてください。
・メニューに表示される「 Ctrl+X 」とかは、実際に書き込まないとダメみたいですね。これは動的追加するときに書き加えるようにすれば大丈夫かな。この辺の整合性が難しそう。んーそういうわけで、その辺チェックしてみてください。こちらでも明日……はちょっと忙しいかも(汗)。明日かあさってにはこっちでも試してみます。 ・でわまたっ! |
・今日も昨日に引き続きお便り紹介っ!
|
|
・というわけで、こちらでもテストしてみました。まずは最初からあるメニュー( 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 のソースコード見て調べました。これしてなかったら試してみて。もししてたらごめんです。そのあとのメニュー追加の部分を明日の更新までにしときますんでそれまでお待ちを。 ・でわまたっ! |
・う”〜、プログラミング辞書疲れた(汗)。なんか知らない単語多いなー、 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(); // アクセラレーターテーブルのハンドル。 } ・これでオーバーライド完了。面倒じゃないんだけど、ソースコード見ないとこーゆー仕組みになってるって分かんないのがあれかな。皆さんはこーゆー設計はしないようにしましょうねー。 ・でわまたっ! |
・今日はお便り紹介っ!
|
|
・初めまして〜。えーっと、 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月になったらバックナンバー公開するからそんときにもう一度見てくださいね。こういうとき、メールマガジンは不便かも……。 ・でわまたっ! |
・今日はお休みします。
|
・今日はお便りを紹介。
|
|
・おー、うまくいって良かったです。最近すぱっと答えられること少なくて(汗)。えっと、まず「ナレッジベース」ですが、ホントは英語で 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() がオーバーライド用に仮想化されてたからあーそーゆー仕組みになってたんだ、とゆー。ソースコード読めるようになるとかなり色々分かってくるです。 ・でわまたっ! |
・今日はお休み〜。
|
・今日はお休みします。
|
・今日はお便りを2通紹介。って、お便り来てないときしか更新しとらん(汗)。まーそれもいっか。えっと、ひとつめのお便り。
|
|
・どうも初めまして〜。これ実際にコード書いて試してみました。方法はウィンドウハンドルからデバイスコンテキストハンドルを取得してビットマップを転送しちゃうっていうもの。ウィンドウハンドルは、キャプチャしたいウィンドウのハンドルを Spy++ で調べて直打ちしてます(汗)。まーテスト用ってことで。 AfxGetMainWnd() は MFC の関数で、自アプリの親ウィンドウを返すものです。コードはこんな感じ。
void Test() { HDC hSourceDc = ::GetDC( (HWND)0x92C ); ::BitBlt ( AfxGetMainWnd()->GetDC()->GetSafeHdc() , 0, 0, 100, 100 , hSourceDc , 0, 0, SRCCOPY ); } ・結果:失敗(汗)。画面をキャプチャリングしたみたいに、上に乗っている画像がそのまま来ちゃいますね。これ以外に方法は思い付かないなー。ちょっと特殊な方法としては、グローバルフックを掛けて、アクティブになった時を見計らってキャプチャリングして取っておくとか(汗)。なんか邪道だなー、しかも一度もアクティブにならなかったら失敗するし。こーゆーこと実現してるアプリ誰か知ってたら教えて〜、それ調べてみるから。 ・もうひとつお便り。 |
|
・どうもです〜。ナレッジベースを含めて、 MSDN はホント便利です。昔は VC に付いてなかったんだよねー。いい時代だ(汗)。いやマジでさ、これなかったらプログラミングなんてできないって。 VC でする以外にも、ランタイムの使用例とかすぐ見つけられるし、色々読むと意外なこと分かるし。会社入って、これ使えなかったりしたらちょっと死ねる……。
・でわまたっ! |
(C)KAB-studio 2000 ALL RIGHTS RESERVED. |