レガシー Windows API(概要)について

ここで紹介しているAPIは、Windows95、Windows NT3.5時代のAPI群であり、最新のAPIは含まれていないことに注しして欲しい。なお、当時の解説書は現在よりもより詳細に解説しているため、参考になるはずである。

  • レイアウトを変換する際、崩れているページがあります。
  • 概要およびSampleコードはありますが、APIの解説はありません。

ご要望があれば旧版のWin32 API(HELP形式)をお譲りします。問い合わせフォームより申し込みください。

Windows API マルチメディア タイマ

このトピックでは、 アプリケーションにジョイスティック入力機能を追加する方法と、 イベントのタイミングを制御する方法を示します。ジョイスティック サービスは、 2個までのジョイスティックから信号を受け取れます。タイマ割り込みサービスによって、 より高解像度で正確なタイマを利用できます。タイマの精度は、 Intel(R) システムでは16ミリ秒まで、 MIPS(R) システムでは10ミリ秒までです。

次に示すトピックでは、 タイマ サービスについて説明しています。

タイマ サービス

タイマのデータ型

タイマ サービスの使用

システム時刻の取得

最大イベント周期と最小イベント周期の判断

最小タイマ解像度の決定

タイマ イベントの開始

タイマ イベントの取り消し

タイマ コールバックの使用

ジョイスティック サービス

ジョイスティックのデータ型

ジョイスティック サービスの使用

ジョイスティックの能力の判断

ジョイスティックの状態を調べる方法

ウィンドウ プロシージャによるジョイスティックのキャプチャ

ジョイスティック メッセージの処理

ジョイスティックの解放

移動しきい値の設定

ジョイスティックのポーリング

ジョイスティック メッセージの使用

マルチメディア タイマ関数とジョイスティック関数

ジョイスティック サービスやタイマ割り込みサービスに関する関数とデータ構造体は、 MMSYSTEM.HWINMM.LIBで定義されています。

タイマ サービス

アプリケーションは、 Microsoft(R) Win32(R) アプリケーション プログラミング インターフェイス (API) で用意されているマルチメディア タイマ サービスによって、 周期的な非同期イベントや1回限りの非同期イベントをスケジュールできます。通常のタイマ サービスはWM_TIMERメッセージをメッセージ キューにポストしますが、 マルチメディア タイマ サービスは、 コールバック関数を呼び出します。

タイマのデータ型

MMSYSTEM.Hヘッダー ファイルでは、 新しいデータ型と、 タイマ関数のプロトタイプを定義しています。タイマ サービスを使うソース コード モジュールには、 このヘッダー ファイルをインクルードしてください。MMSYSTEM.Hは、 次に示す新しいデータ型を定義しています。

説明

MMTIME いくつかある形式のうちのいずれかで時刻を表現する構造体

TIMECAPS タイマの機能を問い合わせるときに使う構造体

タイマ サービスの使用

アプリケーションは、 タイマ サービスによって、 特定の間隔のタイマ メッセージを要求し、 受け取ることができます。リアルタイムのマルチメディア アプリケーションは、 次に示す関数を使って、 データのペースやプレゼンテーションの同期を制御できます。

関数 説明

timeBeginPeriod アプリケーションが使用する最小タイマ解像度を設定します。

timeEndPeriod 以前にtimeBeginPeriodを使って設定した最小タイマ解像度を解除します。

timeGetDevCaps タイマ サービスの能力に関する情報を返します。

timeGetTime ミリ秒単位のシステム時刻を返します。

timeGetSystemTime ミリ秒単位のシステム時刻をMMTIME構造体に設定します。

timeSetEvent 特定の時刻または周期で特定の動作を実行するタイマ イベントを作成します。

timeKillEvent 以前にtimeSetEventを使って作成したタイマ イベントを取り消します。

システム時刻の取得

現在のシステム時刻を取得するには、 timeGetTime関数かtimeGetSystemTime関数を使います。システム時刻とは、 Microsoft(R) Windows(TM) オペレーティング システムが起動してからのミリ秒数です。timeGetTime関数はシステム時刻を返します。また、 timeGetSystemTime関数は、 システム時刻をMMTIME構造体に設定します。

最大イベント周期と最小イベント周期の判断

タイマ サービスがサポートする最小タイマ イベント間隔と最大タイマ イベント間隔を調べるには、 timeGetDevCaps関数を使います。これらの値はコンピュータによって異なり、 Windowsの動作モードによっても異なります。

最小タイマ解像度の決定

アプリケーションは、 タイマ イベントを開始する前に、 使用する最小タイマ解像度を決定しなければなりません。タイマ イベント サービスを使い終わったら、 この値を消去してください。

アプリケーションの最小タイマ イベント解像度を設定、 消去するには、 timeBeginPeriod関数とtimeEndPeriod関数を使います。timeBeginPeriodを呼び出したら、 同じ最小解像度を指定してtimeEndPeriodを呼び出さなければなりません。timeBeginPeriodtimeEndPeriodの呼び出しが対応しているかぎり、 timeBeginPeriodは何度でも呼び出すことができます。

タイマ イベントの開始

タイマ イベントを初期化して開始するには、 timeSetEvent関数を使います。この関数は、 タイマ イベントを中止したり識別するのに使うタイマ識別子を返します。

timeSetEvent関数は、 正常に終了すると、 タイマ識別子を返します。そうでないときはNULLを返します。割り込みタイマは限られたリソースであり、 100ミリ秒以下の分解能を持つ周期タイマは、 CPU時間のかなりの部分を消費します。周期タイマの場合は、 timeSetEventの呼び出しと、 timeKillEventの呼び出しを対応させなければなりません。詳しくは、 タイマ イベントの取り消しを参照してください。

lpFunctionパラメータには、 タイマ イベントが発生したときに呼び出される関数のアドレスを指定します。

コールバック関数は割り込み時にアクセスされるため、 厳密なプログラミング基準にしたがわなければなりません。タイマ コールバック関数は、 低レベル オーディオ サービスと同じプログラミング基準にしたがいます。低レベル オーディオ コールバック関数の作成について詳しくは低レベル オーディオの概要を、 タイマ コールバックについてはTimeProcを参照してください。

タイマ イベントの取り消し

アクティブなタイマ イベントは、 いつでも取り消せます。未処理のタイマは、 コールバック関数を含むモジュールを解放する前に取り消してください。タイマ イベントを取り消すには、 timeKillEvent関数を使います。

タイマ コールバックの使用

ここでは、 アプリケーションがタイマ サービスを使う方法について説明します。アプリケーションは、 まず、 timeGetDevCaps関数を呼び出して、 タイマ サービスがサポートする最小解像度と最大解像度を調べます。タイマ イベントを設定する前に、 次の例のように、 timeBeginPeriod関数を使って、 使用する最小タイマ解像度を設定します。

#define TARGET_RESOLUTION 1 /* Try for 1-millisecond accuracy. */

TIMECAPS tc;
UINTwTimerRes;

if(timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) {
/* Error; application can't continue. */
}

wTimerRes = min(max(tc.wPeriodMin, TARGET_RESOLUTION),
tc.wPeriodMax);

timeBeginPeriod(wTimerRes);

タイマ イベントを開始するときは、 コールバックが発生するまでの時間、 必要な解像度、 コールバック関数のアドレス、 コールバックで渡されるアプリケーション定義のデータを指定します。1回限りのタイマ イベントを開始するには、 次のような関数を使います。

UINT SetTimerCallback(NPSEQ npSeq,/* Sequencer data */
UINT msInterval)/* Event interval */
{
npSeq->wTimerID = timeSetEvent(
msInterval,/* Delay*/
wTimerRes, /* Resolution (global variable) */
(LPTIMECALLBACK) OneShotTimer, /* Callback function*/
(DWORD) npSeq,/* User data*/
TIME_ONESHOT);/* Event type (one-time) */

if (npSeq->wTimerID != 0)
return TIMERR_NOCANDO;
else
return TIMERR_NOERROR;
}

この1回限りのタイマには、 次のようなコールバック関数を使います。

void PASCAL OneShotTimer(UINT wTimerID, UINT msg,
DWORD dwUser, DWORD dw1, DWORD dw2)
{
NPSEQ npSeq; /* Pointer to sequencer data*/

npSeq = (NPSEQ) dwUser;
npSeq->wTimerID = 0; /* Invalidate unused timer id*/

TimerIntRoutine(npSeq); /* Handle interrupt-time tasks */

UNREFERENCED_PARAMETER(dw1);
UNREFERENCED_PARAMETER(dw2);
UNREFERENCED_PARAMETER(msg);
UNREFERENCED_PARAMETER(wTimerID);
}

コールバック関数を含むダイナミック リンク ライブラリ (DLL) を解放する前に、 未処理のタイマをすべて取り消してください。1回限りのタイマを取り消すには、 次に示す関数を呼び出してください。

void DestroyTimer(NPSEQ npSeq)
{
if (npSeq->wTimerID) {/* If timer event is pending */
timeKillEvent(npSeq->wTimerID);/* Cancel the event */
npSeq->wTimerID = 0;
}
}

最後に、 次に示すようにtimeEndPeriodを呼び出して、 設定した最小タイマ解像度を取り消してください。

timeEndPeriod(wTimerRes);

ジョイスティック サービス

ジョイスティックは、 位置情報を提供する入力デバイスです。ジョイスティックは補助的にサポートされる入力デバイスであり、 マウスの代わりにはなりません。タッチ スクリーンやデジタイズ タブレット、 ライト ペンなどの絶対位置デバイスは、 ジョイスティック サービスを使って、 位置やボタンの情報をアプリケーションに渡します。

ジョイスティック サービスは、 Windowsの起動時にロードされます。ジョイスティック サービスは、 2つのジョイスティックを監視できます。各ジョイスティックは、 2軸または3軸の移動と、 4つまでのボタンをサポートできます。アプリケーションは、 ここで説明する関数のセットを使ってジョイスティック サービスにアクセスできます。

:IBM(R) Game Adapterのドライバは、 2つの2軸ジョイスティックまたは1つの3軸ジョイスティックをサポートしています。

ジョイスティックのデータ型

MMSYSTEM.Hヘッダー ファイルでは、 新しいデータ型と、 ジョイスティック関数のプロトタイプを定義しています。MMSYSTEM.Hでは、 次に示す新しいデータ型を定義しています。

説明

JOYCAPS ジョイスティックの能力情報を示す構造体

JOYINFO ジョイスティックの位置とボタンの情報を示す構造体

ジョイスティック サービスの使用

ジョイスティック サービスには、 各ジョイスティックの能力の問い合わせ、 各ジョイスティックの位置やボタンの情報のポーリング、 ジョイスティック イベントのメッセージの受け取りを行う関数があります。ジョイスティックからの入力を受け取るには、 次に示すジョイスティック関数を使います。

関数 説明

joyGetNumDevs ジョイスティック サービスがサポートするジョイスティックの個数を返します。

joyGetDevCaps ジョイスティックの能力を返します。

joyGetPos ジョイスティックの位置とボタンの情報を返します。

joySetCapture 特定の間隔やジョイスティックの状態が変化したときにジョイスティック入力が指定したウィンドウに送られるようにします。

joyReleaseCapture joySetCaptureでキャプチャしたジョイスティックを解放します。

joyGetThreshold ジョイスティックの移動しきい値を返します。

joySetThreshold ジョイスティックの移動しきい値を設定します。

ジョイスティックの能力の判断

現在使われているジョイスティックは、 2軸または3軸の移動と、 さまざまなボタン構成をサポートしています。また、 ジョイスティックがサポートする移動範囲やポーリング周波数はさまざまです。ジョイスティック ドライバは、 1つまたは2つのジョイスティックをサポートできます。ジョイスティック サービスには、 ジョイスティック サービスやシステムにインストールされているジョイスティック デバイスの能力を調べる関数が2つあります。

ドライバの能力の取得

ジョイスティックがサポートするジョイスティック デバイスの個数を調べるには、 joyGetNumDevs関数を使います。この関数は、 サポートされているジョイスティックの個数を返しますが、 ジョイスティックがサポートされていなければ0を返します。返される値は、 システムに接続されているジョイスティックの個数とは限りません。ジョイスティックが接続されているかどうか調べるには、 デバイスに対してjoyGetPos関数を呼び出してください。指定されたデバイスが接続されていなければ、 この関数はJOYERR_UNPLUGGEDを返します。

次の例は、 ジョイスティック サービスが利用可能かどうか調べてから、 ポートにジョイスティックが接続されているかどうか調べます。

JOYINFO joyinfo;
UINT wNumDevs, wDeviceID;
BOOL bDev1Attached, bDev2Attached;

if((wNumDevs = joyGetNumDevs()) == 0)
return ERR_NODRIVER;

bDev1Attached = joyGetPos(JOYSTICKID1,&joyinfo) != JOYERR_UNPLUGGED;
bDev2Attached = wNumDevs == 2 &&
joyGetPos(JOYSTICKID2,&joyinfo) != JOYERR_UNPLUGGED;

if(bDev1Attached || bDev2Attached) /* Decide which joystick to use */
wDeviceID = bDev1Attached ? JOYSTICKID1 : JOYSTICKID2;
else
return ERR_NODEVICE;

ジョイスティックの能力の取得

システムに接続されている各ジョイスティックの特定の能力を調べるには、 joyGetDevCaps関数を使います。この関数は、 ジョイスティックの各軸の範囲、 ボタン数、 ポーリング周波数の最大値と最大値をJOYCAPS構造体に設定します。

ジョイスティックの状態を調べる方法

ジョイスティックから情報を取得するには、 次の2つの方法のいずれかを使います。

キャプチャしたジョイスティックからのジョイスティック メッセージを処理する方法

ジョイスティックを直接ポーリングする方法

メッセージ処理による方法の方が簡単です。アプリケーションには、 ジョイスティックの位置やボタンの状態 (押されているか離されているか) を示すメッセージが送られます。

ウィンドウ プロシージャによるジョイスティックのキャプチャ

ジョイスティック入力は、 特定のウィンドウ プロシージャがキャプチャできます。ジョイスティックをキャプチャすると、 特定の間隔で、 またはユーザーがジョイスティックを操作したときに、 アプリケーションはジョイスティック メッセージを受け取ります。メッセージについては、 次に説明します。

1つのジョイスティックのジョイスティック メッセージをキャプチャできるアプリケーションは1つだけです。しかし、 ジョイスティック メッセージをキャプチャしても、 ほかのアプリケーションはjoyGetPosを使ってジョイスティックをポーリングできます。ジョイスティック入力がキャプチャされているときにjoyGetPosを呼び出すと、 joyGetPosの呼び出しの前後で発生したジョイスティック イベントはキャプチャ ウィンドウに正しく報告されない場合があります。

joySetCapture関数は、 指定したウィンドウ プロシージャがジョイスティック入力をキャプチャするようにします。ジョイスティックを解放するには、 joyReleaseCapture関数を呼び出してください。

システムに接続されている2つのジョイスティックからのメッセージをキャプチャするには、 各ジョイスティックに対してjoySetCapture1回ずつ呼び出してください。これによって、 ウィンドウは、 各デバイスに対して別々にメッセージを受け取ります。

接続されていないジョイスティックはキャプチャできません。joySetCapture関数は、 正常に終了すれば0を返します。指定されたデバイスが接続されていなければ、 JOYERR_UNPLUGGEDを返します。

:ジョイスティック サービスは、 joySetCaptureが呼び出されるごとにWindowsタイマ イベントを設定します。

joySetCaptureの周期パラメータには、 ジョイスティックの最大解像度と最小解像度の間の値を指定してください。ジョイスティックの最小解像度と最大解像度を調べるには、 joyGetDevCaps関数を呼び出します。この関数は、 JOYCAPS構造体のwPeriodMinメンバとwPeriodMaxメンバに値を設定します。

指定された周期の値が有効な解像度の範囲外ならば、 ジョイスティック サービスは、 最小解像度と最大解像度のうち、 指定された周期に近い方の値を使います。

ジョイスティック メッセージの処理

ウィンドウ プロシージャには、 次に示すジョイスティック メッセージが送られます。メッセージの数字の12は、 メッセージの送り元のジョイスティックを示します。アプリケーションが第1ジョイスティックからの入力を要求したときはMM_JOY1メッセージが送られ、 第2ジョイスティックからの入力を要求したときはMM_JOY2メッセージが送られます。どのメッセージも、 存在しないボタンは離されているものとして報告します。

メッセージ 説明

MM_JOY1MOVE

MM_JOY2MOVE ジョイスティックのx軸やy軸の位置の変化を報告します。wParamパラメータは、 押されているボタンを示すJOY_BUTTONビット フラグの組み合わせです。lParamの下位ワードはジョイスティックのx位置を示し、 上位ワードはy位置を示します。

MM_JOY1ZMOVE

MM_JOY2ZMOVE 3軸ジョイスティックのz軸位置の変化を報告します。wParamパラメータは、 押されていいるボタンを示すJOY_BUTTONビット フラグの組み合わせです。lParamの下位ワードはジョイスティックのz位置を示します。

MM_JOY1BUTTONUP

MM_JOY2BUTTONUP

MM_JOY1BUTTONDOWN

MM_JOY2BUTTONDOWN ジョイスティックのボタンが押されたか離されたことを報告します。wParamパラメータは、 状態が変化したボタンを示すJOY_BUTTONCHGビット フラグのいずれかと、 現在のボタン状態を示すJOY_BUTTONビット フラグの組み合わせを示します。wParamパラメータは、 押されているボタンを示すJOY_BUTTONビット フラグの組み合わせです。lParamの下位ワードはジョイスティックのx位置を示し、 上位ワードはy位置を示します。

ジョイスティック サービスは、 次に示すビット フラグを使って、 ジョイスティック ボタンの状態をメッセージのwParamパラメータに報告します。

フラグ 説明

JOY_BUTTON1 ボタン1が押されているときにセットされます。

JOY_BUTTON1CHG ボタン1の状態が変化したときにセットされます。

JOY_BUTTON2 ボタン2が押されているときにセットされます。

JOY_BUTTON2CHG ボタン2の状態が変化したときにセットされます。

JOY_BUTTON3 ボタン3が押されているときにセットされます。

JOY_BUTTON3CHG ボタン3の状態が変化したときにセットされます。

JOY_BUTTON4 ボタン4が押されているときにセットされます。

JOY_BUTTON4CHG ボタン4の状態が変化したときにセットされます。

MM_JOY*MOVEメッセージは、 JOY_BUTTONフラグを使って、 特定のジョイスティックのすべてのボタンの状態 (押されているか離されているか) を報告します。

MM_JOY*BUTTONUPメッセージとMM_JOYBUTTONDOWNメッセージは、 JOY_BUTTONフラグを使って、 特定のジョイスティックのすべてのボタンの状態 (押されているか離されているか) を報告します。また、 JOY_BUTTONCHGフラグを使って、 メッセージの生成の原因となった、 状態が変化したボタンを示します。

たとえば、 ユーザーがボタン1とボタン2を押したままにしてジョイスティックを動かすと、 ウィンドウ プロシージャは、 次に示すメッセージを受け取ります。

メッセージ wParamのフラグ

MM_JOY1BUTTONDOWN JOY_BUTTON1 | JOY_BUTTON1CHG

MM_JOY1BUTTONDOWN JOY_BUTTON1 | JOY_BUTTON2 | JOY_BUTTON2CHG

MM_JOY1MOVE JOY_BUTTON1 | JOY_BUTTON2

ユーザーがジョイスティックを動かさずにボタン3を押したままにすると、 ウィンドウ プロシージャは、 次に示すメッセージを受け取ります。

メッセージ wParamのフラグ

MM_JOY1BUTTONDOWN JOY_BUTTON3 | JOY_BUTTON3CHG

MM_JOY1BUTTONUP JOY_BUTTON3CHG

ジョイスティックの解放

周期的なジョイスティック メッセージを受け取る必要がなくなったら、 joyReleaseCapture関数を使ってジョイスティックを解放してください。アプリケーションがジョイスティックを解放せずに終了すると、 キャプチャしているウィンドウが破棄された少し後にジョイスティックは解放されます。

移動しきい値の設定

ジョイスティックの移動しきい値を変更するには、 joySetThreshold関数を呼び出します。移動しきい値とは、 デバイスをキャプチャしているウィンドウにMM_JOY*MOVEメッセージが送られるまでにジョイスティックが動く距離をデバイス単位で表現した値です。

ジョイスティックのポーリング

アプリケーションは、 ジョイスティックの位置とボタンの情報をポーリングできます。たとえば、 ジョイスティックをポーリングして、 ベースラインの位置の値を取得できます。ジョイスティック コントロール パネル アプリケーションは、 この方法でジョイスティックを補正します。ジョイスティックの位置やボタンの情報をポーリングするには、 joyGetPos関数を使います。

:ジョイスティック入力がキャプチャされているときにjoyGetPosを呼び出すと、 ジョイスティック サービスがジョイスティック イベントをキャプチャ ウィンドウに正確に報告できなくなる場合があります。

ジョイスティック メッセージの使用

ここでは、 デスクトップ上で射撃を行う、 簡単なジョイスティック ゲームのコードを紹介します。このプログラムは、 ジョイスティック サービスから位置とボタン状態の情報を取得します。ユーザーがジョイスティックのボタンを押すと、 ウェーブフォーム リソースを再生して、 デスクトップに弾痕を描画します。

ジョイスティック制御コードは、 ほとんどメイン ウィンドウ関数にあります。次のメッセージ ハンドラのWM_CREATEでは、 アプリケーションは、 ジョイスティック1からの入力をキャプチャします。

case WM_CREATE:
if(joySetCapture(hWnd, JOYSTICKID1,NULL, FALSE)) {
MessageBeep(MB_ICONEXCLAMATION);
MessageBox(hWnd, "Couldn't capture the joystick.", NULL,
MB_OK | MB_ICONEXCLAMATION);
PostMessage(hWnd,WM_CLOSE,0,0L);
}
break;

アプリケーションは、 MM_JOY1MOVEメッセージに応じてカーソルの位置を変更し、 どちらかのボタンが押されると、 デスクトップに穴を描画します。

case MM_JOY1MOVE :
if((UINT) wParam & (JOY_BUTTON1 | JOY_BUTTON2))
DrawFire(hWnd);
DrawSight(lParam);/* Calculate new cursor position */
break;

アプリケーションは、 MM_JOY1BUTTONDOWNメッセージに対して、 sndPlaySoundを使ってウェーブフォーム オーディオ ファイルを再生します。

case MM_JOY1BUTTONDOWN :
if((UINT) wParam & JOY_BUTTON1) {
sndPlaySound(lpButton1,
SND_LOOP | SND_ASYNC | SND_MEMORY);
DrawFire(hWnd);
}
else if(wParam & JOY_BUTTON2) {
sndPlaySound(lpButton2,
SND_ASYNC | SND_MEMORY |SND_LOOP);
DrawFire(hWnd);
}
break;

JOYTOYアプリケーションでは、 sndPlaySoundSND_LOOPフラグとSND_ASYNCフラグを指定して、 ボタンが離されるまでウェーブフォームを繰り返し再生します。

ボタンが離されると、 ウィンドウ プロシージャはMM_JOY1BUTTONUPメッセージを受け取り、 次に示す文でメッセージを処理します。

case MM_JOY1BUTTONUP:
sndPlaySound(NULL, 0);
break;

このコードは、 ウェーブフォーム オーディオの再生を停止します。

マルチメディア タイマ関数とジョイスティック関数

ジョイスティック サービスで使用される関数を次に示します。

joyGetDevCaps

joyGetNumDevs

joyGetPos

joyGetThreshold

joyReleaseCapture

joySetCapture

joySetThreshold

タイマ サービスで使われる関数を次に示します。

timeBeginPeriod

timeEndPeriod

timeGetDevCaps

timeGetSystemTime

timeGetTime

timeKillEvent

TimeProc

timeSetEvent

▲ページトップに戻る

【本を読んでもよくらからない】 … 個別指導でわかりやすくお教えします