‘プログラミング’のエントリ

exe ファイルをデバッガで追いかけた場合のアドレス。0x400000 が加えられた値となるようだ。


デバッガで配列を見たとき,表示を 16 進にしておくと配列の添字が何故か 16 進として評価される。バグ?


mid を聞きつつ Web ページを見る。すると Web ページの mid が聞こえてきた。のはいいけど 2 重に聞こえる。ちょっとびっくり。

コンソールアプリを,DOS 窓なしで GUI から呼び出す。

// コマンドライン
LPTSTR lpCommandLine;
lpCommandLine = "app.exe";

// パイプの作成
HANDLE hReadPipe, hWritePipe;
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
::CreatePipe(&hReadPipe, &hWritePipe, &sa, 0);

// STARTUPINFO
static STARTUPINFO StartupInfo;
static PROCESS_INFORMATION ProcessInfo;

::ZeroMemory(&StartupInfo, sizeof(STARTUPINFO));
StartupInfo.cb = sizeof(STARTUPINFO);
StartupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow = SW_HIDE;
StartupInfo.hStdOutput = hWritePipe;

::CreateProcess(
    NULL,
    lpCommandLine,
    NULL,
    NULL,
    FALSE,
    0,
    NULL,
    NULL,
    &StartupInfo, &ProcessInfo);

char buf[255];
unsigned long num;
::ReadFile(hReadPipe, buf, 255, &num, NULL);
if(::WaitForSingleObject(ProcessInfo.hProcess, INFINITE) == WAIT_OBJECT_0)
{
    DWORD res;
    ::GetExitCodeProcess(ProcessInfo.hProcess, &res);
    CloseHandle(ProcessInfo.hProcess);
}
::CloseHandle(hWritePipe);
::CloseHandle(hReadPipe);

これを使えば Java コンパイラを呼び出したりとかで統合環境を作ったりできるかな。いつかやってみたい。

# 2000.05にもう少しちゃんとしたものを載せた。

ILS2,タイマーを 5ms ごとにしたら,描画・通信の同期の関係で異常な重さとなった。

下のミス。リリースバージョンでしか出ないバグで,デバッグに時間がかかった。

if(p != NULL)
{
    p = new char[10];
}

これでは条件が逆で,正しくは

if(p == NULL)
{
    p = new char[10];
}

デバッグでは値が NULL 以外に割り当てられるが,リリースでは値が NULL になったりならなかったりで動作がおかしくなる。

リリースのデバッグ情報を生成し,やっと見つけた。

同じ値の char 同士を比較したのに値が違う,と言われる。signed と unsigned を比較していた。

ILS2 DirectPlay のイベントスレッド,終了のためにイベントをもう 1 つ用意する。

while(1)
{
    // イベントを待つ
    HANDLE hHandles[2];
    hHandles[0] = m_hDPEvent;
    hHandles[1] = m_hDPKillEvent;
    if(::WaitForMultipleObjects(2, hHandles, FALSE, INFINITE) == WAIT_OBJECT_0 + 1)
    {
        // 終了イベント
        return;
    }
    else
    {
        処理
    }
}

のようにするとスッキリする。


VB から VC++ DLL を使う。VC++ で,MFC 拡張 DLL を作成し,

"func.h"
#ifdef __cplusplus
extern "C" {
#endif
int APIENTRY func();
#ifdef __cplusplus
}
#endif
"func.cpp"
int APIENTRY func()
{
    return 0;
}

で公開する関数を作成。この中からはクラスも呼び出せる。

次に def ファイル。

"library.def"
LIBRARY      "DialUpCommon"
DESCRIPTION  'DialUpCommon Windows Dynamic Link Library'

EXPORTS
    func=XXXXXXXX

XXXXXXXX の部分は内部名。@ がたくさん付いてるやつ。

VB 側

Private Declare Function func Lib "library.dll" () As Long

Private Sub Command1_Click()
func
End Sub

とする。その際,開発環境からは DLL をフルパスにするか,DLL をパスの通っている場所に置かなくてはダメだった。

DLL を作成。inline を書くのを忘れ,メソッドが 2 回定義され,DLL リンケージが違うと言われる。


実行ファイル名の取得方法。グローバル変数 _pgmptr を参照する。


プロセス ID の取得方法。_getpid() を使用する。

Direct3D と 2D を重ねる方法。最初 2D の上に 3D を描いてうまくいかなかったが,Direct3D の Clear を,2D 描画の前で行うようにすればよい。

VC。アプリケーションの拡張子を後から変える方法

String Table の IDR_MAINFRAME を

xxxnnxxxnxxx File (*.xxx)n.xnxxx.Documentnxxx Document

のようにする。(xxx が拡張子)

Direct3D,Viewport の ForceUpdate で画面が更新されなくて困る。原因は ForceUpdate の 3,4 番目の引数が幅,高さだと思っていたこと。実際はクライアント座標。

DirectDraw カラーキーについて

DirectDraw のカラーキーは,実際のハードウェア,BPP などに対応する値を指定してやる必要がある。1 番確実な方法はサンプルのように,サーフェスに GDI で描画をし,値を読み出すこと。

DWORD CDirectDraw::DDColorMatch(LPDIRECTDRAWSURFACE pSurface, COLORREF rgb)
{
    DWORD result;
    COLORREF oldrgb;

    HDC hdc;

    // GDI を使って色を置く
    if(rgb != CLR_INVALID && pSurface->GetDC(&hdc) != DD_OK)
    {
        return 0;
    }

    // 前の値を保持
    oldrgb = ::GetPixel(hdc, 0, 0);

    // 色を置いてみる
    ::SetPixel(hdc, 0, 0, rgb);

    pSurface->ReleaseDC(hdc);

    // ハードウェア依存の値を読み込む
    DDSURFACEDESC ddsd;
    ddsd.dwSize = sizeof(DDSURFACEDESC);

    HRESULT hres;
    while((hres = pSurface->Lock(NULL, &ddsd, 0, NULL)) == DDERR_WASSTILLDRAWING)
    {
        ;
    }

    if(hres == DD_OK)
    {
        result = *(DWORD *)ddsd.lpSurface;

        // BPP に対する修正
        if(ddsd.ddpfPixelFormat.dwRGBBitCount < 32)
        {
            result &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount) - 1;
        }

        pSurface->Unlock(NULL);
    }

    // 書き込んだ値を元に戻す
    if(rgb != CLR_INVALID && pSurface->GetDC(&hdc) != DD_OK)
    {
        return 0;
    }

    // 色を置いてみる
    ::SetPixel(hdc, 0, 0, oldrgb);

    pSurface->ReleaseDC(hdc);

    return result;
}

Direct3D,メッシュを見えなくするには,Frame.DeleteVisual すればよいが,メッシュの参照がなくなり,メッシュが削除され,もう 1 度表示するときに困る。これを防ぐには先に Mesh->AddRef() をしてやればよい。

DirectSound で音が鳴り終わったことを検出する為に IDirectSoundNotify を使う。DIRECTSOUNDBUFFER 作成時のフラグに DSBCAPS_CTRLPOSITIONNOTIFY を指定するのを最初忘れた。

DirectSound,弾を撃つバッファを static で作ったが,複数の音が鳴らない。これは別々にバッファを用意するしかないようだ。

DirectInput。GetDeviceData が Release フルスクリーンでうまくいかなかった。原因は第 3 引数が入出力両用ということに気付かず,初期化しないまま渡していたからだ。

SendChatMessage を使うために DirectPlay インターフェースを IDirectPlay3 に。しかしインターフェースがかなり変わっていて戸惑う。

結局 SendChatMessage はロビーを使わないとだめなので使わなかった。

DirectSound が初期化できなかった。原因はサスペンドした時にサウンドカードが使えなくなってたため。もう一度差し直すことで解決。

スタティックライブラリにリソースを埋め込む方法。[挿入] – [リソース] でリソースを作成,その後プロジェクトに *.rc を追加する。

DirectX の簡易ライブラリを作ろうと思う。使いたい DirectX ラッパークラスを継承するというものにしようと思う。


スタティックライブラリの作り方。何度かやってるがいつも迷うのでここに書いておく。新規ワークスペースで Win32 Static Library を選び,プリコンパイル済みヘッダ,MFC サポートを on にする。


DirectSound。DSound.h をインクルードする前に MMSystem.h をインクルードする必要がある。ちなみにライブラリは DSound.lib と WinMM.lib。


Information の r が抜けていた。全部直す。

ILS2 で面白いミス。

if(m_pDDSOffScreen->BltFast(MESSAGE_X, MESSAGE_Y, m_pDDSMessage, CRect(0, 0, MESSAGE_WIDTH, MESSAGE_HEIGHT), DDBLTFAST_NOCOLORKEY | DDBLTFAST_WAIT) != DD_OK)

m_pFrameScene->Move(D3DVAL(1.0));

のようなことをやって,Move されずに悩んだ。if 文の中身を忘れて次の文が実行されなかったのだ。


クラス情報にアクセスできないとか言われる。対処法は,dsw,dsp を除いて clw などを消せばよい。


Surface の GetDC を使う際,ReleaseDC を忘れて次に呼び出されたときに固まった。よくやるので気を付けねば。


SetOrientation で,回転した場合速度ベクトルが更新されなくて困る。これは一旦絶対座標で速度を 0 にしてから速度を絶対的に設定することで解決。

Direct3D,テクスチャは 2 の n 乗でないと SetTexture でエラーが出るようだ。ていうかそんな制限どっか書いてあったっけ?

テクスチャがどうやってもできないと思ってふと裏から見るとちゃんと見られる。でも何故裏にできる?

ということでよく調べると座標系を勘違いしていた。ヘルプを見てやっと座標系を理解できた。しかしカメラ,ライトは z 方向を向くとかはどこにも書いてないような。試行錯誤でやっと分かってきた。

念のため。SetPosition は自分のフレームの位置をベース座標で指定する。SetOrientation は自分のフレームの向きをベース座標で指定する。その際,第 2 ~ 4 引数は自分の z 軸をベース座標で表した値,第 5 ~ 7 引数は自分の y 軸をベース座標で表した値である。

Direct3D,X ファイルをリソースからロードしようとして失敗する。見つからないと言われる。D3DRMLOADRESOURCE の loadResource.lpName が LPCTSTR なのが不思議に思ったのだが,結局リソース ID を MAKEINTRESOURCE で変換することで解決。

D3DRMLOADRESOURCE loadResource;
loadResource.hModule = AfxGetInstanceHandle();
loadResource.lpName = MAKEINTRESOURCE(RESOURCE_ID);
loadResource.lpType = "X";
pMeshBuilder->Load(&loadResource, NULL, D3DRMLOAD_FROMRESOURCE, NULL, NULL);

VisualC++6.0 の,Doc-View を使わない設定だと,AppWizard で LoadStdProfileSettings が生成されない。ILS2 に以下の部分を追加

LoadStdProfileSettings();

Direct3D の初期化をする。ぷぅさんからテストデータがあがったので試してみたいのだ。しばらくやってると妙に動作が重い。ふと時計を見ると他の時計より 30 分ばかり遅れている。おや? と思って修正しようとすると,明らかに時間が進むのが遅い! ていうか何だコリャ。熱くなりすぎておかしくなったのか? ともあれ時間が遅れるとはビックリ。ちなみに再起動したら直った。

ILS2 を進める。

クライアントウィンドウに対するメインウィンドウの合わせ方

AdjustWindowRectEx を使う。これはあるウィンドウサイズ,あるメニューに対してメインウィンドウをどのくらいにすればよいかを返す関数で,例えば CMainFrame::PreCreateWindow で

CRect rectClient(WINDOW_BASE, WINDOW_BASE, WINDOW_BASE + WINDOW_WIDTH, WINDOW_BASE + WINDOW_HEIGHT);
::AdjustWindowRectEx(&rectClient, cs.style, NULL, cs.dwExStyle);
cs.x = rectClient.left;
cs.y = rectClient.top;
cs.cx = rectClient.Width();
cs.cy = rectClient.Height();

のように使う。


で,ウィンドウモードだが,なかなかうまくいかなかった。原因を調査していると,Primary Surface に BltFast しているのがいけないらしい。Blt ならうまくいく。何故だろう。

ILS2 で使用する Sound ライブラリ。なんとか wav ファイルの再生が完成。これで Direct Sound もいけるだろう。


ウィンドウのサイズを固定にする方法。例えば AppWizard で作ったものなら,

cs.style &= ~(WS_MAXIMIZEBOX | WS_THICKFRAME);

としておけば ok。

Apache 状況変わらず。設定ファイルは間違ってないような感じだが…


Denasu System のカウンタを SSI に変える。メインページのファイル名を index.shtml にし,counter.pl を修正。最初日本語を EUC にするのを忘れた。ちなみに拡張子を shtml にしても今まで通り http://www.eva.hi-ho.ne.jp/minoru-f/ で表示される。ちょっと心配してたのでひと安心。

起動しない。どうやら Hi-HO の許す include 方式(私命名)では Content-type がいるらしい。これを付けて再試行。おお。うまくいった。

何故 SSI にしたかというと,HTTP_REFERER をきちんと作用させるためだ。今までの img 方式(同じく私命名。img のソースに CGI を指定する。)では,呼び出し元が Denasu ページなので,HTTP_REFERER が Denasu ページになっていた。これからはやっと他のページが表示されるだろう。ひょっとすると Infoseek からの検索キーワードも分かるかも知れない。ちなみに Pha-jtd 氏のページ のリンクで動作を確認。

大学の課題の n 次元女王支配問題が完成。とりあえずプロファイルをとるか,と思ったが,そういえば VC6.0(だけ?)ではプロファイルのチェックボックスがインクリメンタルリンクとごっちゃになって指定できないバグがあったのを思い出す。

プロジェクトオプションに手動で

/profile

を付ければいいだけだが。ていうかサービスパック 3 でもなおっていないとは。

Perl を起動しようとすると

libgdbm.so.2

がないと怒られる。PJE のページにあるように

ln -s /usr/lib/libdb.so.1 /usr/lib/libdb.so.2
ln -s /lib/libgdbm.so.1 libgdbm.so.2

としてリンクを作ることで解決。


JDK1.1.6 を入れる。割とすんなり入った。

HTML,ローカルで <a href=”./”> を開くとディレクトリリストが表示されてしまうが,サーバーではちゃんと表示されることを知る。Denasu の全ての index へのリンクを修正。

スタイルシート,背景を transparent にしていると NN では背景が真っ黒になって困った。しかし考えてみれば背景を指定しなければ body が継承されてちゃんとなることが分かった。

IE で FONT を serif とかで指定してると …(点点点)が文字化けする。NN では問題なし。MS 明朝とか指定しないとダメなのか。

スタイルシートでの複数要素指定を

h1 h2 h3
{
}

のようにやっていた。これでは

<h1><h2><h3></h3></h2></h1>

のことになってしまう。正しくは

h1, h2, h3
{
}

スタイルシートだが,NN では行送りを指定していると,通常のテキストとテキストフィールドが同じ行送りとなり画面が崩れることを発見。

CGI などの URL で,& を a.pl?a=b&amp;c=d のように実体参照にしなければならないことを知り,修正する。

Java から CGI データを使う方法。

Java から CGI で作ったサーバーのローカルファイルを読み込みたいが,うまくいくサーバーとできないサーバーがあった。結局データを読み込むのはあくまでも CGI に任せ,Java から ファイル読み込み CGI を呼び出すことで解決した。が,これだとせっかく普通は読めない場所にファイルを置いといても,直接 CGI を起動すれば他人にファイルが読まれてしまう。パスワードとかを設定すればいいのかな。


カレントディレクトリのファイルを tar ファイルにアーカイブする。

tar -c * > a.tar

ってやったら a.tar の中に a.tar が入ってしまった。結局

tar -c * > ..a.tar

とかでごまかした。

ちなみにすぐ忘れるので解凍方法。

tar xvf a.tar