What's New » この記事

WindowsSDK 備忘録 その九

字句解析以降のことはさらっと流す感じにします。ここから先は処理がややこしくてめんどうくさいし、もう備忘の域を越えてるしねヽ(´Д`;)ノ

ログを追えばいい話ですが、メインとなる処理の流れは、main.cpp のInterpreter オブジェクトの生成がスタートとなりスクリプト文が入ってるファイルをロードした後、CInterpreter の各関数を、Run();–>>WM_TIMER 経由で Tick();–>>Continue();–>>ParseLine();[※Mascot宣言の処理の場合のルート(字句解析)]–>>構造解析–>>以下、マスコットの登録処理へと、続いていきます。

※教本では 25ms 間隔でWM_TIMER イベントが設定してあって、Tick();関数で処理を分けてます。ここで入力待ちなどの処理をしてます。しかしマスコット文には関係しないので無視です。

※マスコットの宣言などのスクリプト文の処理に関しては、入力待ちのスクリプト文などがはいってParsingフラグが立たなければ、どんどん行を処理することになります。

※Tick(),Continue(),ParseLine()の各関数で分岐します。分岐からの処理はVoid 型の処理になりますので(つまりやりっぱなし)、それぞれへ処理を投げると、タイマーイベント待ちになり、WM_TIMERイベントが起きると、二回目以降は、Tick();を基点とするループ作業になります。

※字句解析以降の処理では、オブジェクトが増えてくるのでmascot.cpp の頭にメモリリークチェックをするような文を挿入しました。いれとくと便利ですね。

制作メモ[v07] —————————————————————–
★v07以降は、スクリプトを読み込んで処理するのだが、テスト用なのでビルドしたらDebugフォルダに出来ているWin32Project1.exe をダブルクリックすることで、デフォルトのスクリプトindex.mctを取り込んで実行する。

パーザープログラムの定義の前に、ファイルパスなどを加工するUtility.hとcppを追加。
マスコット宣言とテキストをスクリプトから読み出せるように、パーザープログラムの定義を開始。
CInterpreter.cpp のコンストラクタ実装時、config設定は、取りあえず形を崩さないで残し、
メンバの設定はNULLにしておくことにした。

また、メモリーリークをチェックする仕掛けを施した。
(参考)http://marupeke296.com/TIPS_No7_SearchMemoryLeak.html
——————————————————————————-

ソースコード[v07.lzh]

WindowsSDK 備忘録 その八

ソースコード[v06e.lzh]では、CImageWindow::WndProc(); のWM_PAINT: にimgwnd->WmPaint(); と指定し、子クラスのWm_Paint(); を実行する様に変更しました。画面上にも子クラスのメンバで書いてますとでるようにしました。

また前回のstaticなテスト用変数をCImageWindowクラスのstaticなメンバ変数のMapコンテナと置き換えました。このMapコンテナに、ウィンドウズハンドル値をキーにして、カレントのマスコットクラスのオブジェクトを登録してします。マスコットが一つ(小窓がひとつ)だけならMapコンテナはいらないですが、スクリプトの読み取りと実行まで再現する場合は、外せないものなのでここで組み込んでみました。

imgwnd->WmPaint(); のimgwnd の内容が変動するところが要所になりますよね。

これで一区切りになります。ここまではコードの量も少なくて構造も把握しやすいんではと思います。

この先の分岐としては、取りあえずビットマップ画像を画面表示したいだけなのなら、教本の様にCMascotクラスに画像を管理するクラスを追加して拡張すれば実行可能でしょう。これは比較的労力が少なく実行できそうです。

もう一つの分岐としては、スクリプトファイルを読み込んで解析しコマンドを実行するルートになります。教本では画面表示の実装が終わると、字句解析・構文解析へと解説を進めています。このルートに進むと定型的な処理とはいえ構文解析のところがやっぱりかなりややこしいので大変だと思います。削りに削ってマスコット宣言の処理だけに絞って抽出したものでさえ、補助関数を行ったり来たりしながらメインの関数をじりじり進んでいくような感じになります。

ソースコード[v06e.lzh]

WindowsSDK 備忘録 その七

備忘録七では、派生クラス CMascot のプロトタイプを取り植えず定義してみました。

メインとなるのは、CImageWindow 基本クラスから派生する CMascot 派生クラスの定義になります。備忘録四のメモで取り上げた、プロシージャから指定された関数を基本クラスから派生クラスの同名の関数に委託する処理をvirtual指定することで成立させています。

[CMascot.h]

virtual void WmPaint(); // 仮想関数。実装は各子クラスの同名の関数に委託。

[cMascot.h]

void WmPaint();

基本クラスにvirtual指定がされていることで、マスコットには、マスコットクラスのWmPaint();が、バルーン(ふきだし)には、バルーンクラスのWmPaint();にそれぞれ処理が委託されるようになります。基本クラスのvirtual指定を取り払ってしまうと、(参考)http://wisdom.sakura.ne.jp/programming/cpp/cpp30.html のサイトの実験結果からの引用にあるように、

(以下引用)
この機能は、同名のメンバ名を持つクラス間で面白い現象が発生します
メンバ名が基本クラスと派生クラスで衝突している場合
クラスを明示しなかった場合は常に自分のクラスのメンバを優先しました

と、同様の結果になります。メインの多態性についてはこれぐらいで置いといて、
もうひとつここではサブとして、static なメンバ関数内に配置されているメンバ変数の取り扱いに関してとりあげておきます。

教本では、作成した複数の小窓を登録しておくMapコンテナが、staticなメンバ関数として定義されているウィンドウプロシージャの中で使われている都合上、staticで宣言されています。そのルールは知ってたんですが、実装の仕方を知らなかったんでここで散々エラーに悩まされました(確か外部リンクエラーがでたと思う)

static なメンバ変数の実装に関するルールに関しての説明はこちらを読んでいただければいいと思います。(参考)http://www.geocities.jp/ky_webid/cpp/language/019.html
ここに、静的メンバ変数を宣言した場合、その実体の定義をクラス定義の外側に記述しなくてはなりませんと、書いてあります。

試験的な変数をCMascot.h のCImageWindow に、
static int TestNumber; // テスト用
というメンバ変数を宣言してます。

で、
[CMascot.cpp]

// 静的メンバ変数の定義(★クラス外部で行う)
int CImageWindow::TestNumber = 100;

と、いう形で実体の定義を行っています。

あとは、プロシージャ内でこのstaticなメンバ変数を呼び出して、値をログに書きだすテストを行っています。

尚、子クラスのオブジェクトは作りましたが、まだ CImageWindow::WndProc の WM_PAINT に子クラスのWmPaint(); に飛べって書いて無いので、それは次のv06e.lzh でやります。

ソースコード[v06b.lzh]

RSSが出力できてなかった点を修正

WordPress3.4 を入れなおした後から、RSSの出力がおかしくなっていた点を修正しました。

[修正の手順]
今のテーマのfunction.php にadd_theme_support(‘automatic-feed-links’); が、入っていなかったので、RSSをheadタグに書きだすように修正。

(参考)http://www.prime-strategy.co.jp/wp/391/

修正したら、ブログのindex.html を開いて、rssのlinkタグが出力されているか確認。

<link rel="alternate" type="application/rss+xml" title="気流邂逅点 &raquo; フィード" href="http://haganenomori.net/wp/?feed=rss2" />

に、出力されているので一応RSSは、配信されているのでいいけど、右サイドバーのウィジットの表示がエラーを出しているので、Wordpress管理画面より、上のlinkタグに書きだされているアドレスをコピー&ペーストして修正ヽ(`Д´)ノ

WindowsSDK 備忘録 その六

前回はオブジェクトの生成はしなかったので、今回は、 mascot.cpp に動的にオブジェクトを生成します。またレム文の形で、静的にオブジェクトを配置してみました。

プログラムを実行すると、小窓がでるようになりました。また、ログに通過点の情報を書きだしました。カーソル等のレム文は削除してすっきりさせました。

ソースコード[v05b.lzh]

WindowsSDK 備忘録 その五

その五では、CImageWindowクラスを最小限の構成で定義してみました。教本では、もう最初からフル装備になってるのですが、プロトタイプはコンストラクタ・デストラクタ・コールバック関数の三つの関数があればいいと思います。

細かいところに目を配ると、インスタンスやメインのウィンドウハンドルをCMascot.cpp 中のCImageWindow();のコンストラクタで利用するので、mascot.cpp の本文中で宣言されている HINSTANCE Instance; HWND MainWindow; の二つを取り込みたいので、mascot.h 中に extern 宣言をしてこれを使って経由して間接取り込みをしているところでしょうか。

その五での大きな注意箇所は、コールバック関数をstaticで宣言しているところでしょうか。この何故staticなのかに関しては、「なぜstaticをつけるのかという質問に対しての答え」(引用)http://d.hatena.ne.jp/bnkyshr/20110107/1294391512
に詳しく説明がされています。また教本の原文では、静的に定義されたコールバック関数内で使うカーソルに、静的メンバを割り当ててますが、これをコピー&ペーストするとややこしくなるので、レムにして標準カーソルを割り付けました。静的メンバ変数の関数外での実装に関しては、CMascotクラスの定義まで踏み込んだ時、Mapコンテナを配置することになるのでその時、触れてみようかと思います。取りあえず今は無視(・3・)

注目行は、この二か所かな..

[CMascot.h]

static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);

[CMascot.cpp]

wcex.lpfnWndProc=(WNDPROC)&CImageWindow::WndProc;

クラスのメンバ関数をキャストしてコールバック関数として登録してるとこ。

最低限の定義と実装はしましたが、オブジェクトを生成していないので見かけ上は、プログラムを実行しても何の変化もありませんね。

ソースコード[v04b.lzh]

WindowsSDK 備忘録 その四

備忘録の四回目はメモ書きです。

参考にしている教本のPart3(P.163~)からマスコットシステムの設計に入ってますが、教本では、表示機能→スクリプトエンジンという順番で、マスコットシステムに実装してる機能をひとつひとつ解説していってます。しかし、自分のように大掴みでいいから全体の流れを俯瞰して把握したいと考えている者にとっては、焦点がぼやけて全体像が見えにくく感じられます。単純にクラスを使って画面に何かを表示するということだけに焦点を絞って考えるならば、表示機能の仕組みを理解できてればいいので、スクリプトエンジンのことはこの時点では無視して、仕掛けに関して整理してみました。

以下メモ書きより

(さらに…)

WindowsSDK 備忘録 その三

備忘録三回目は、下準備としてログを出力できるようにしておきます。ある時点での変数の中身や指定行をどう通過したかをログに出力できれば、気持ち的にもだいぶ楽になるのでmascot.cppにLog.hをインクルードします。(5行目)


// [チェック用] ログ出力用関数の宣言
#include "log.h"

とします。ログを書き出す関数に関しては、今は閉鎖されてしまっているみたいですが、電子通さんというサイトさんで公開されていたログを書き出すための関数が使いやすかったのでそちらを使わせてもらいました。ログの初期化をかけたら、あとはコードに埋め込んであるように文字列を出力するように指定します。尚、可変引数をとることができるので、Log(“Aの中身は %s です\n”, str); の様な書き方もできます(重宝してます)。書き出したログは、初期化時に与えた名前でプロジェクトフォルダ内に出力されます。今回の場合は、check.log になります。

ソースコード[v03.lzh]

WindowsSDK 備忘録 その二

VSE2012がどんな感じかは前回ので分かったので、二回目以降は「空のプロジェクト」でプロジェクトを作り、一回目で自動的に作られた基本コードと以下の教本から必要なコードをコピー&ペーストしながらクラスを中心にしたWindowsプログラムの流れを備忘録では追ってみようかと思います。

教本としては、「デスクトップマスコットを作ろう!!」という本が自分が読んだ本の中では、比較的シンプルにC++とWindowsSDKを使ってアドベンチャー系ゲームの雛形を解説しているので、これを利用することにしました。

Amazon でのレビュー記事で述べられているように入門書としていい本かといわれると「?」な感じの本ですが、それでも一通りの流れは一冊の本の中で説明されているのと、directxやMFCを使ってないところやプロジェクトを構成するファイル数もなんとかなりそうな数で済んでいるので、とっつきやすい方の本ではないかと思います。

今回のコードですが、教本の方でメインとなるファイルの mascot.cpp を最低限の構成に組み替えてみました。
内容的には前回の内容「Hello World!!」をmascot.cpp に適用してみただけのものです。

注釈としては、40行目からのところで、教本では領域外に出して非表示状態にしてある親窓を見える位置に置きなおしたのと、初期設定データの取り込みに始まる準備処理をごっそり削り落としました。

MainWindow=CreateWindowEx(0, MainWndClassName, MainWndClassName, WS_OVERLAPPEDWINDOW, 0, 0, 800, 600, NULL, NULL, Instance, NULL);
ShowWindow(MainWindow, SW_SHOW);

「猫でもわかるプログラミング」の 「イントロダクション」のコードの形に近くなりました。

あと引っ掛かった点は、制作メモ.txtにも書いてますが、

[引っ掛かったところ]
WNDCLASS の登録のところで、構造体のメンバlpszClassNameがデフォルトだと
(LPCWSTR)型を求めてくるのだが、キャストで対処するとタイトルバーの文字が化ける。

(引用)
プロジェクトのプロパティで「構成」が「Unicode文字セットを使用する」とか書いてあると思うんだけど
「マルチバイト文字セットを使用する」とする。
http://yuxx.net/1081/computer/programming/win32-sdk

にあるように、コード系を変えてあげると文字化けは回避できる

ソースコード[v02.lzh]

WindowsSDK 備忘録 その一

まんがタイムきららMAXで連載中の「ステラのまほう」を読んでて、そういえば最近趣味で書いたりするWindowsSDKのスクリプトも全然作っていないなーと思ったので備忘録をつけてみることにしました。

最初は”Hello World!!”を画面に出すいつものあれが、VisualStudioExpress2012 (マイクロソフトのサイトで無料で配ってる)で出来るかの確認をします。Windows7のマシンにインストールして起動し、Win32プロジェクトを新規作成、そのまま完了。すでにコードが準備されているのでちょっと追加と書き換えをして期待通りに動くか確認してみました。

Win32Project1.cppのコールバック関数に、

	PAINTSTRUCT ps;
	HDC hdc;
	char *szStr = "最初の一歩";

あと、


	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		// TODO: 描画コードをここに追加してください...
		TextOutA(hdc, 10, 10, (LPCSTR)szStr, strlen(szStr));
		EndPaint(hWnd, &ps);
		break;

それと、少し戻って


hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, szWindowClass, szWindowClass, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL);

拡張型で窓を作るようにしてみました。で、出来たらビルド。動きましたね。

ソースコード[v01.lzh]

4 / 512345