鏑矢の憂鬱2001年2月後半
透明1ドットイメージ
 
2001/02/16 (Fri)
・今日も MS XML を使ってみました。うがーっ ISAXContentHandler::characters() が呼ばれねーっ! と思ったら、単にサンプルの継承関係がごっちゃになっててオーバーライドがうまくいってなかっただけだったとゆー(汗)。これで実際の値を取得できるようになりましたです。んでも書き込めないとあかんかな。あ、パーサーだから書き込みは別なのかな。
 
・この SAX と、もひとつ DOM っていうのが主なパーサーらしくて、両方とも MS XML に COM として実装されてるみたいです。この両方とも標準パーサーだそうで、だから Java とかでも使えるらしいです。てっきり MS だけのだと思ってたんでちょっと助かったり。これで勉強しとけば後で他の言語やライブラリに移行してもなんとかなりそう。
 
・それに、標準でいろんな言語でサポートされてるってことは、それだけサンプルも多いってことだと思うし。日本語の解説も結構ありそうだし。ただこうなると、ライブラリとしての難しさよりも、 XML そのものの難しさの方が壁になるかもしんない。なんとか理解していかねば。
 
・今日のお便り!
 
透明1ドットイメージ
透明1ドットイメージ
 こんにちは。コントロールについて質問です。
 ソフト会社などから、オリジナルのコントロールが販売されていますが、そういったコントロールを自作するにはどうしたらよいのでしょうか?
 参考になるホームページ等があったら教えていただけると嬉しいのですが。よろしくお願いします。
透明1ドットイメージ
透明1ドットイメージ
 
・んーと、基本的にああいうコントロールは ActiveX コントロールっていうので、新規プロジェクトで MFC ActiveX ControlWizard っていうのを選ぶのかな。実はそんなに詳しくないです(汗)。基本的には COM をベースにしてるんだけど、 VB とかでも使えるようにかなり仕組みが複雑らしいです。
 
・ホームページは残念ながら知らないです。検索すると VB や Delphi のもかなり引っかかっちゃって。そういうのを取り除いて検索すると逆に必要なページ見つからなそうだし。ただ、 ActiveX のサンプルそのものは MSDN とかにあるはずなんで、その中の API とかで検索すれば結構見つかるかもしんない。
 
・ただ……もう ActiveX って時代じゃないのかも(汗)。 VB.Net はたぶん誰も使わないだろうし。だからって次はこれっていうものがあるわけでもないしなー。ま、 VB6 はこれからも使われるだろうから作っておいて損はないのかも。
 
・でわまたっ!
透明1ドットイメージ
 
2001/02/17 (Sat)
・今日はお休み〜。
透明1ドットイメージ
 
2001/02/18 (Sun)
・今日は Perl プログラミングをしてました。なぜか文字コードの変換ができない(泣)。なぜに〜!? 実際に他のコードでの書き込みしてみないとテストできないのかなぁ。
 
・今日のお便り。
 
透明1ドットイメージ
透明1ドットイメージ
 こんにちは、いつも楽しくFAQを読ませてもらっています。
 
 えーと、質問なんですが、クラスの値返しとクラスの参照返しとコンスタントクラスの参照返しとコンスタントクラスの値返しの関数をどう使い分けていいか分かりません。
 
 特にコンスタントクラスの値返しとコンスタントクラスの参照返しの使い分けが分からなくて混乱してます。
 
 教えてください。 お願いします。
透明1ドットイメージ
透明1ドットイメージ
 
・えーっと、ようするに CTest ってクラスがあったときに、そのクラスを返す関数を作るときに「 CTest func() 」と「 CTest &func() 」と「 const CTest func() 」と「 const CTest &func() 」のどれにしたらいいのか迷っちゃうってことですよね。
 
・まず基本的に「 const CTest func() 」はほとんど使いません。受け取る側が「 CTest cTest = func(); 」ってしたらその時点で const が消えちゃうんで。「 CTest func() 」は、わざとコピーを作りたい場合に使用します。たとえばローカル変数の値とか、メンバ変数でも新たにコピーとして返したいとか。値として返すとコンストラクタが呼ばれちゃうんで、クラスは基本的に参照やポインタでやりとりすることが多いです。でもそれじゃまずいって時に値を使いましょう。
 
・「 CTest &func() 」と「 const CTest &func() 」は、参照先は非ローカルな、関数から抜けても消えない変数、つまりメンバ変数へとアクセスする場合に使用します。非 const は書き込み用、 const は読み込み用ってするのが一般的。前者はメンバ変数に直接アクセスできるわけだからね。その関係で const の方は const メンバ関数にすることが多いです。この辺は std::vector::at() とか見てくれると分かると思うです。
 
・つまり基本は「 CTest &func() 」か「 const CTest &func() const 」。書き込み用が前者で読み取り用が後者。両方作るのもあり。参照じゃまずい場合は「 CTest func() 」と値で。あ、たぶん値のと参照のとを両方作ると、使う時に「どっちを呼べばいいのか」って問題でコンパイルエラーになると思うです。だから作るとしたらどっちかね。
 
・でわまたっ!
透明1ドットイメージ
 
2001/02/19 (Mon)
・昨日やってた Perl プログラムは、臨時板に書き込むためのものでした。んでもエンコーディングや日本語処理を全然してないんでちょっとうまくいってない部分も(汗)。まーわてが書き込むだけだし、こんなもんでいいかなー。
 
・今日のお便り!
 
透明1ドットイメージ
透明1ドットイメージ
 半透明オブジェクト(CStatic)を作るにはどうしたらいいですか?
 
 Windows98 VC++6.0 です。
 画像のビットマップまたはデバイスコンテキスト、グレイスケールのデバイスコンテキストまたはビットマップとを結合してグレイスケールの黒い部分は完全に透過して白い部分は白く残したい、灰色の部分は濃さによって透過の具合を変えたいです。
 OnPaint に BitBlt を書いて試そうとしたのですが、うまくいきませんでした。
 どうか教えてください。
透明1ドットイメージ
透明1ドットイメージ
 
・ん〜、たぶん簡単に実現する方法なない様な気が……。 MSDN に AlphaBlend() とか TransparentBlt() とか書いてあるけど使えるのかこれ……。一応 Knowledge Base の Article ID: Q79212 "HOWTO: Drawing Transparent Bitmaps" に透明ビットマップの表示方法ってあるけど、たぶんこれは「だんだん透明」はできないんじゃないかなぁ。あ、売ってるコントロール使えばできると思う(爆)。
 
・理論上は、各ピクセルで、描画元の色に透明度を掛けたものを描画先に加えて、その結果としての色を描画先に描き込む、って形式になると思うです。 GetPixel() とか SetPixel() とか使って。でもえらい時間かかりそう……。実際に売られてるのは、もっと効率的な処理するんだと思うです。ビットマップを配列に置き換えてばばっと計算する感じに。
 
・その辺は、その手の詳しいサイト見た方がいいかも。特にゲーム関係とかデモ関係とかの方が詳しそう。あーでもそーゆーとこは DirectX で実現してるのかもなぁ。
 
・でわまたっ!
透明1ドットイメージ
 
2001/02/20 (Tue)
・今日はお休み〜。
透明1ドットイメージ
 
2001/02/21 (Wed)
・今日もお休み。たぶん明日もお休み(汗)。
透明1ドットイメージ
 
2001/02/22 (Thu)
・今日もお休みですー。明日は休まない……はず(汗)。
透明1ドットイメージ
 
2001/02/23 (Fri)
・今日は久しぶりに XML プログラミング。 XML を操作するライブラリには DOM と SAX があって、どっちもいろんな言語で使えるってことが判明したっていうのが前回までの話。そんな時にちょうどよく @ITVBScriptでXMLプログラミングっていうのが始まって、これに DOM の使用例が載ってたんで試してみました。
 
・必要なアプリのうち WSH だけ入れてなかったんでこれをダウンロードしてインストール。んで Sample.xml と GetTitle.vbs を作って実行……うまくいかない(汗)。 MsgBox を printf() 代わりにしてデバッグしてみると、どうやら DOMDocument.load で False が返ってくるらしい。っつーか Sample.xml を IE5.5 で読み込んでみるとエラー出るし(泣)。
 
・と、そのエラーをよく見るとどうやら2バイト文字で問題になってるらしい。って、 Sample.xml に encoding="utf-8" って書いてあるじゃん(爆)。とりあえず2バイト文字を全部削除して実行。おおっ、ちゃんと title を抽出してる! この辺の処理をまんま VC に移してうまくいくかどうか今度試してみましょう。
 
・で、2バイト文字使えないってのはしゃくだなーと思ってたら、秀丸は UTF8 で保存できた(爆)。なんで UTF8 で保存すると、 IE5.5 でもちゃんと読めるし、スクリプトもちゃんと通ったしでひと安心。あと encoding="Shift_JIS" ってすればシフト JIS でもOK。秀丸は UTF8 を自動判断できないみたいなんで、とりあえずシフト JIS で書いて最後に UTF8 でってのがいいのかも。
 
・今日のお便り〜。
 
透明1ドットイメージ
透明1ドットイメージ
 OnMouseOver OnMouseOut に匹敵するイベントを教えてください。
 
 なければ、実現方法を教えてください。
 
 または、OnMouseOverで、ポップアップウインドウを表示し、OnMouseOutで、ポップアップウインドウを閉じるようなプログラムの見本を示してください。
透明1ドットイメージ
透明1ドットイメージ
 
・よーするに「ウィンドウにカーソルが乗った!」「ウィンドウからカーソルが出た!」ってのが分かればいいんですよね。「乗った!」は特定のメッセージがないんで WM_MOUSEMOVE を常に拾い続けてチェックしないといけないみたいです。「出た!」は _TrackMouseEvent() を呼ぶと WM_MOUSELEAVE が来るんでそれを拾いましょう。
 
・おおっと、当然メッセージは「目的のウィンドウ」に送られるんで、ボタンとかにこの機能を付けるときにはサブクラス化する必要ありますです。 MFC でのサブクラス化は2月7日のとか見てね。これに気付くのに30分かかった(汗)。まだまだダメねわても。最新の SDK だと WM_NCMOUSELEAVE って便利なのがあるらしい……。
 
・でわまたっ!
透明1ドットイメージ
 
2001/02/24 (Sat)
・今日も引き続き XML プログラミング。まだ昨日の VBS でテストしてます。 VB って使ったことないからちょっと新鮮。最後にセミコロン要らないってのが不安だ……。
 
・とりあえず MSXML のリファレンスを元に昨日の VBS を解析。まず DOMDocument.childNodes から ノードリストを取得。ん?  C++ だと XMLDOMNodeList を取得するみたいだけど、このサンプルは DOMDocument のプロパティ使ってるなぁ。 VB って型がないからなんかよく分かんない……。
 
・各ノードを再帰呼び出しで関数に掛けていって、タイプが NODE_TEXT で親ノードの値が title っていうものを見つけてそれを MsgBox で表示しているんですな。こういうのは基本的に簡単なんだけど、 MSXML に書かれてるのと結構異なるんでその辺をどうするか……英語だし。
 
・今度は、逆に nodeValue に値を格納してみる。おお、ちゃんと格納されてる。さらに DOMDocument.save( "Sample_Out.xml" ) みたくしてみる。おおっ、ちゃんと新しいファイルができて保存されてる!! そっか、こうやって XML データを保存すればいいんだなー。んだが、その保存した方には勝手にタブが加えられてた(爆)。謎だ。
 
・ま、これなら何とかなるかもしんない。あとは、 <?xml> タグをどう設定するのかとか、 C++ でどう呼び出せばいいのかとか分かれば、それこそデータ保存にそのまま使えるようになると思うです。うんうんうん、結構 XML が分かってきたかもしんない。
 
・でわまたっ!
透明1ドットイメージ
 
2001/02/25 (Sun)
・今日はお便りが3通。では今日のお便り!
 
透明1ドットイメージ
透明1ドットイメージ
 バイナリI/Oについての質問です。
 
#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>
typedef struct Test{
  int dat1, dat2;
  double a[2];
};

int main(){
  Test a;
  ofstream out_file("test.dat");
  a.dat1 = 10;
  a.dat2 = 11;
  a.a[0] = 1.5;
  a.a[1] = 3.7;
  out_file.write((char*)&a,2*sizeof(a.a[0]) + 
    sizeof(a.dat1) + sizeof(a.dat2));
  ifstream in_file("test.dat");
  in_file.read((char*)&a, 2*sizeof(a.a[0]) + 
    sizeof(a.dat1) + sizeof(a.dat2));
  cout << a.dat1 << ' ' << a.dat2 
    << ' ' << a.a[0] << ' ' << a.a[1];
  return 0;
}
	
 
 これなんですけれども、データの並びが変わることなくうまく動いてくれていますが、 write()した時に、データの並び順の保証はあるんでしょうか? あったらいいなぁ
透明1ドットイメージ
透明1ドットイメージ
 
・えーっと、データの並び順ってことそのものは大丈夫。 Test 構造体型の変数として a を作ったでしょ、その変数 a のメモリ上のバイナリーデータそのものがファイルに書き込まれるんで、同じく read() でそのまんま取り込めば問題なし。
 
・だけど、それ以外はちょっと問題(汗)。まず構造体のサイズ。構造体の中の変数はそのまんま置かれるんじゃなくて、変数の間に無駄な空間が作られる場合があるんです。この仕組みをアライメントって言います。たとえば VC の場合、 Test::dat1 と Test::dat2 の型を char にすると動かなくなっちゃいます。 dat1 と dat2 の間に無駄な領域が作られちゃうんで、この例だと変数 a の最後が書き込まれないです。
 
・このあたりはコンパイラの設定によるし、今回みたいにちょうどアライメントとサイズが同じだったりするとうまくいくんだけど……。そういうの回避するためにも、 sizeof( Test ) の値を write() に渡しましょう。っつーか、ホント言うと構造体を write() するのは避けた方がいいんだけどね。コンパイラ依存ってことは、移植したら前のデータが使えないなんてことに……。面倒だけどデータひとつひとつ書き込むのを勧めますです。
 
・あと、わてが試したときは ofstream::close() を呼ばないと ifstream でファイルを開けなかったです。だから ifstream::read() は失敗してたんで変数 a の値がそのまんま残ってました。「うまくいってた」のがもしかしたらその理由って可能性も。その辺かなぁ。古いコンパイラみたいだからデバッグ大変だと思うんで、少しずつテストしていった方がいいかもしんない。今回のは読み込みと書き込みを別プログラムにするとか。
 
・もひとつお便り。
 
透明1ドットイメージ
透明1ドットイメージ
 こんにちわ。マルチスレッドのワーカースレッドのことなんですけど、このワーカースレッドが走ってる時にアプリケーションを終了するとどうなるんでしょうか?
 
 ワーカースレッドの終了を待って終了できてればいいんですけど...もし、できてなかったら終了を待つにはどうすればいいんでしょうか?
透明1ドットイメージ
透明1ドットイメージ
 
・ん〜、スレッドがどういうことしてるかに寄る、ってことみたいです。 MSDN の "Terminating a Process" ってページを見ると "When a process is terminated, all threads of the process are terminated immediately with no chance to run additional code." って書いてあるんで、その場ですぐスレッドが中止されるみたいです。
 
・ってことは、後処理が必要な場合にはまずいかも。まー、たいがいのことはプロセスが削除されればなんとかなってるんで、大丈夫だとは思うけど。ウィンドウズのハンドル系はたいがい大丈夫。でも、たとえばネットワークに接続してて、いきなりこっちが閉じるとまずい場合とかは問題かも。その辺は、マルチスレッド関係なく「デバッグの中止」とかするとそういう状態になるんでその辺でチェックするといいかも。
 
・で、スレッドを待つには WaitForSingleObject() って API を使います。これにスレッドのハンドルを渡すと、もしスレッドが終了してたらすぐ返ってきて、終了してなかったら終了するまで返ってこないとゆー機能を持ってます。とりあえずこんな感じに。
 
void Func( LPVOID )
{
//  Sleep( 3000 );
    TRACE0( "Func infinited\n" );
}

void Test()
{
    DWORD dwThreadID;
    HANDLE hThread
        = CreateThread
            ( 0, 0
            , (LPTHREAD_START_ROUTINE)Func
            , 0, 0, &dwThreadID );

    Sleep( 3000 );
    TRACE0( "Sleeped\n" );
    WaitForSingleObject
        ( hThread
        , INFINITE );
    TRACE0( "Thread infinited\n" );
}
	
 
・こうすれば、スレッドの方が先に終わってるんで WaitForSingleObject() はすぐに返ってきます。逆に、 Test() 内の Sleep() をコメントアウトして Func() の Sleep() を機能するようにすると、 WaitForSingleObject() がちゃんと待ってくれるのが分かると思います。この処理をアプリの最後にすれば大丈夫。たーだ、もしスレッドが「終わらないかも」とか「すんごく時間がかかるかも」って場合にはユーザーに迷惑がかかるんで、他の方法の方がいいかもしんない。
 
・もひとつお便り!
 
透明1ドットイメージ
透明1ドットイメージ
 三好です。
 
 エディタ作りの最後の詰めでこけています。CFindReplaceDialog の使い方を教えてください。とくに、検索すべき文字列をダイアログから取得する方法が知りたいです。なぜかうまくいきません。
 
 よろしくお願いします。
透明1ドットイメージ
透明1ドットイメージ
 
・おおっ、ついにそこまで行きましたか!! しかし CFindReplaceDialog ってものがあるとは知らなかった(汗)。このパターン最近多いな……。えっと、とりあえず簡単にテストしてみました。なんかエラー出ちゃうけど、とりあえず検索ダイアログの文字列は取得できてるんで。
 
CFindReplaceDialog g_cFindDlg;

void Test()
{
    if( g_cFindDlg.GetSafeHwnd() == NULL )
    {
        g_cFindDlg.Create( TRUE, "" );
    }
    else
    {
        // これはテスト用。
        TRACE( "%s\n", g_cFindDlg.GetFindString() );
    }
}

LRESULT WindowProc(UINT message
    , WPARAM wParam, LPARAM lParam) 
{
    if( message == RegisterWindowMessage( FINDMSGSTRING ) )
    {
        LPFINDREPLACE lpfn
             = (LPFINDREPLACE)lParam; 
        TRACE( "%s\n", lpfn->lpstrFindWhat );
    }
 
    return 0;
}
	
 
・検索ダイアログの「検索」ボタンを押すと、 FINDMSGSTRING で登録されたメッセージが送られてくるんで、それをウィンドウプロシージャで受け取って、 lParam を LPFINDREPLACE にキャストしたのの lpstrFindWhat に検索文字列が入ってるんでそれを元に検索すればいいようです。
 
・もひとつの「テスト用」の方でも取得できるんだけど、検索ダイアログの「検索」を押さないと lpstrFindWhat の中身が更新されないんで、最後に押したときの文字列しか取得できないです。っつーか FINDMSGSTRING の lParam と g_cFindDlg.m_fr は同じものだし。なんかこういう「既製品」はどうも信用できないとこが(汗)。
 
・でわまたっ!
透明1ドットイメージ
 
2001/02/26 (Mon)
・今日はお便り紹介〜。
 
透明1ドットイメージ
透明1ドットイメージ
 三好です。
 
 やはりエラーが出ますか。「うまくいかない」と私が書いたのは、アサートかけられてしまうことでした。やはり自前で実装するほうがいいような気がしてきました。
 
 現在バグ取りとコードの単純化を図っているところです。これで、検索機能とかつけたら、立派にエディタ完成ですね。
透明1ドットイメージ
透明1ドットイメージ
 
・昨日のうまくいかないって ASSERT() のことでしたか。 _free_dbg() で発生してたんでコールスタックでどの delete で発生するのか調べてみたら CFindReplaceDialog::PostNcDestroy() で delete this してました(汗)。どういう理由でこういう仕様になってるんだろう。フレームワーク関係のクラスならこういうのも分かるんだけど。
 
・とりあえず CFindReplaceDialog 型変数を new で作ってみてください。そうすれば delete が成功するんで。これでうまくいくはず。でもちょっと応急処置かも。んでも MFC の仕組み調べるのも面倒だしなー。
 
・もひとつお便り。
 
透明1ドットイメージ
透明1ドットイメージ
 ワーカースレッドについて質問したものです。
 どうもありがとうございました!めちゃくちゃ役にたちました。
 ネットワークをちょっと見に行くだけの機能なんでちょっとしか時間は食わないんですけど、終了処理がどうなってしまうのかと思ったもので...
透明1ドットイメージ
透明1ドットイメージ
 
・この辺って分かりにくくて難しいですもんね。基本は MSDN の Platform SDK を読み潰すってことになるんだろうけど、必ずしも分かりやすく書いてないし(汗)。それに英語だし(爆)。ウィンドウズプログラミングの壁のひとつかもしんないです。そういうの、分かりやすく簡単に全体的に書いてる本とかないもんかな……。
 
・でわまたっ!
透明1ドットイメージ
 
2001/02/27 (Tue)
・今日はお休み〜。
透明1ドットイメージ
 
2001/02/28 (Wed)
・今日はお便り紹介!
 
透明1ドットイメージ
透明1ドットイメージ
 Microsoft(R) Visual Studio(R) 6.0 Service Pack 5の無償提供開始のニュースを受けて、さっそくダウンロードしてみました。
http://www.microsoft.com/japan/developer/vstudio/download/sp/
 
 インストールしてみると MFC42.DLL の更新日時が 99/10/27 です。
 
 手持ちの DLL をみると 99/04/27 なので(ファイルバージョン: 6.00.8447.0 -> 6.00.8665.0 製品バージョン: 6.0.300 -> 6.0.400 )新しくなっているような気がします。
 でも readme.htm を読むと、「6.3.10 Microsoft Foundation Classes (MFC) の問題」に「Service Pack 5 で修正された問題」の項目がありません。いったいどんな変更があったのでしょうか。それとも勘違いなのでしょうか。
透明1ドットイメージ
透明1ドットイメージ
 
・たぶん色々やったんだけど「問題」が「修正」されなかったんでしょう(爆)。もしくは「問題」が「追加」されたか(爆)。 VS のサービスパックってことは MFC のソースコードも着いてると思うから、バックアップ取っといて差分取ってみればどの辺が変わったのか分かったのかもしんない。 .Net まわりとかこそこそっと追加されてたりしそうだなー。うちはダウンロードはきついんで、Cマガに付いてきたら試してみるです。
 
・でわまたっ!
 
 
(C)KAB-studio 2001 ALL RIGHTS RESERVED.