このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。
今日は、必須の関数の実装を行う。
scrnsave.lib を使う場合、
以下の関数を用意する必要がある。
・RegisterDialogClasses
・ScreenSaverConfigureDialog
・ScreenSaverProc
ScreenSaverProc はプレビューと実行モードの時に使われる。
scrnsave.lib は、最初にウィンドウを作成する。
これは、実行モードの時は、画面全体を覆うサイズに、
プレビューモードの時は、プレビュー画面に収まるように、
自動的にサイズが計算された状態で表示される。
ScreenSaverProc は、そのウィンドウの、
ウィンドウプロシージャとして登録されるため、
ScreenSaverProc 内で、イベントを自由に処理できるのだ。
RegisterDialogClasses と ScreenSaverConfigureDialog は、
設定モードの時に呼び出される関数である。
設定モードの場合、scrnsave.lib は、
ID が DLG_SCRNSAVECONFIGURE のリソースを使って、
ダイアログボックスを作成して表示する。
ScreenSaverConfigureDialog はそのダイアログボックスの、
ダイアログプロシージャとなっている。
もう一つの関数である RegisterDialogClasses は、
ダイアログが作成される直前に呼び出される。
これは、利用者が設計したダイアログリソース上で、
特別なコントロールが使われるケースに対応するためだ。
自作等のコントロールをダイアログボックスで使う場合、
ダイアログボックスが作成される前に、
コントロールのウィンドウクラスを登録しなければならない。
RegisterDialogClasses はそのために存在するのだ。
では、コードを書いていこう。
まず、基本的な環境の設定を含むヘッダを作る。
========== config.hpp ==========
#ifndef z_config
#define z_config
#define WINVER 0x400
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <scrnsave.h>
#endif /* !z_config */
========== end of config.hpp ==========
WINVER が 0x400 で、Windows 95/NT 以降ということ。
STRICT は Windows の型に関する厳格モードを指定する、
WIN32_LEAN_AND_MEAN はコンパイルを迅速に行うおまじない。
続いて、関数の本体を実装する。
========== module.cpp ==========
#include "config.hpp"
BOOL WINAPI RegisterDialogClasses(HANDLE hInst) {
UNREFERENCED_PARAMETER(hInst);
return TRUE;
}
BOOL WINAPI ScreenSaverConfigureDialog(
HWND hdlg, UINT message,
WPARAM wParam, LPARAM lParam) {
UNREFERENCED_PARAMETER(wParam);
UNREFERENCED_PARAMETER(lParam);
switch (message) {
case WM_COMMAND:
switch (wParam) {
case IDOK:
EndDialog(hdlg, 0);
return TRUE;
case IDCANCEL:
EndDialog(hdlg, 1);
return TRUE;
}
break;
}
}
return FALSE;
}
LRESULT WINAPI ScreenSaverProc(
HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_PAINT:
{
const char *text = "Hello World!";
PAINTSTRUCT ps;
HDC hdc;
hdc = BeginPaint(hwnd, &ps);
TextOut(hdc, 0, 0, text, lstrlen(text));
EndPaint(hwnd, &ps);
}
return 0;
}
return DefScreenSaverProc(hwnd, message, wParam, lParam);
}
========== end of module.cpp ==========
今回作ったダイアログは単純そのものなので、
特別なウィンドウクラスは必要ない。
そのため、RegisterDialogClasses は TRUE を返すだけ。
UNREFERENCED_PARAMETER は、未使用の引数に関する、
コンパイラの警告を抑制するためだ。
本当はコンパイラの設定で制御するのが良いのだろうが、
SDK プログラミングでは慣例となっている。
ScreenSaverConfigureDialog はダイアログプロシージャ。
2 つのボタンが押された処理を行うために、
WM_COMMAND メッセージを処理する。
ダイアログを閉じる際は、EndDialog 関数を呼び出す。
今回は、IDOK が押された場合、戻り値 0 で閉じ、
IDCANCEL が押された場合、戻り値 1 で閉じるとする。
なお、この戻り値はそのままプログラムの戻り値となる。
ダイアログプロシージャの場合、
TRUE を返すとメッセージを処理したことになるが、
FLASE を返すと、メッセージを処理しなかったことになり、
ダイアログボックスとしての既定の処理が行われる。
ScreenSaverProc はウィンドウプロシージャ。
今回は、WM_PAINT メッセージを捕まえて、
画面上に自由に描画を行うことができる。
ここではお決まりの「Hello World!」を描画することにした。
WM_PAINT では、まず BeginPaint を呼び、
適当に描画した上で、EndPaint を呼んで止める。
今回は、TextOut 関数でテキストを描画してみた。
さて、ウィンドウプロシージャの場合、
戻り値を自分で返すとメッセージを処理したことになり、
DefWindowsProc 関数を同じ引数で呼び出すと、
ウィンドウとしての既定の処理が行われる。
scrnsave.lib には、DefScreenSaverProc 関数があり、
これは、スクリーンセーバーとしての既定の処理が行われる。
DefScreenSaverProc は DefWindowsProc と異なり、
マウスやキーボードが動いた時の自動終了などを、
自動的に行ってくれるので楽だ。
どうだろう、結構コードは短くて済んだようだ。