カクタスソフトウェア
カクタスソフトウェア
サウンド MIDI マルチメディア アプリケーション

高精度コールバック (.NET C#バージョン)

このセクションでは、マネージ環境下でマルチメディアタイマーを用いた高精度コールバック処理を実施する手法について解説します。

マルチメディアタイマーはアンマネージ環境にあるAPIですので、呼び出しにはマーシャリングを必要とします。関数の仕様や使い方はアンマネージ環境の「高精度コールバック」を参照して下さい。

マーシャリング

以下にマーシャリングに必要なコードを示します。

DllImport

public class MmTimer
{
    [DllImport("winmm.dll")]
    public static extern int timeGetSystemTime(out MmTime pmmt, int cbmmt);

    [DllImport("winmm.dll")]
    public static extern uint timeGetTime();

    [DllImport("winmm.dll")]
    public static extern int timeSetEvent(
        int               uDelay,
        int               uResolution,
        DgMmTimerCallback fptc,
        IntPtr            dwUser,
        TimerFlag         fuEvent);

    [DllImport("winmm.dll")]
    public static extern int timeKillEvent(int uTimerID);

    [DllImport("winmm.dll")]
    public static extern int timeGetDevCaps(out TimeCaps ptc, int cbtc);

    [DllImport("winmm.dll")]
    public static extern int timeBeginPeriod(int uPeriod);

    [DllImport("winmm.dll")]
    public static extern int timeEndPeriod(int uPeriod);
}

構造体

MMTIME構造体の定義です。

// MmTime

[StructLayout(LayoutKind.Explicit)]
public struct MmTime
{
    [FieldOffset(0)]
    public uint     wType;          // indicates the contents of the union

    [FieldOffset(4)]
    public uint     ms;             // milliseconds
    [FieldOffset(4)]
    public uint     sample;         // samples
    [FieldOffset(4)]
    public uint     cb;             // byte count
    [FieldOffset(4)]
    public uint     ticks;          // ticks in MIDI stream

    // SMPTE
    [FieldOffset(4)]
    public byte     hour;           // hours
    [FieldOffset(5)]
    public byte     min;            // minutes
    [FieldOffset(6)]
    public byte     sec;            // seconds
    [FieldOffset(7)]
    public byte     frame;          // frames
    [FieldOffset(8)]
    public byte     fps;            // frames per second
    [FieldOffset(9)]
    public byte     dummy;          // pad
    [FieldOffset(10)]
    public byte     pad0;
    [FieldOffset(11)]
    public byte     pad1;

    // MIDI
    [FieldOffset(4)]
    public uint     songptrpos;     // song pointer position
}

TIMECAPS構造体の定義です。

// timer device capabilities data structure

[StructLayout(LayoutKind.Sequential)]
public struct TimeCaps
{
    public int      periodMin;          // minimum period supported
    public int      periodMax;          // maximum period supported
}

デリゲート

TIMECALLBACK関数のテンプレートを定義します。

// delegate TIMECALLBACK

public delegate void DgMmTimerCallback(
    int         timerID,
    int         msg,
    IntPtr      instance,
    IntPtr      param1,
    IntPtr      param2);

定数

TIME_PERIODICなどをenumとして定義します。

// flags for fuEvent parameter of timeSetEvent() function

public enum TimerFlag
{
    OneShot    = 0x0000,                // program timer for single event
    Periodic   = 0x0001,                // program for continuous periodic event
}

タイマーの能力を調べる

TimeCaps tc = new TimeCaps();
int result = MmTimer.timeGetDevCaps(out tc, Marshal.SizeOf(typeof(TimeCaps)));

resultにゼロが戻れば、tc.periodMinに最小値、tc.periodMaxに最大値が得られます。

タイマーを起動する

インターバルの設定や事前にtimeBeginPeriod()メソッドを実行しておく点などは、アンマネージ環境のコードと同じです。

コールバック関数の指定は、関数のデリゲートを設定する必要があります。

4番目の引数はユーザー変数です。この例では利用していませんが、利用するときは、IntPtrにキャストします。

int uResolution = 設定したいインターバル;
DgMmTimerCallback dgTimerCallback = new DgMmTimerCallback(TimerCallback);

MmTimer.timeBeginPeriod(uResolution);

timerID = MmTimer.timeSetEvent(
    uResolution,
    uResolution,
    dgTimerCallback,
    IntPtr.Zero,
    TimerFlag.Periodic);

タイマーを停止する

タイマーの利用が終わったらタイマーを停止します。

if (timerID != 0)
{
    MmTimer.timeKillEvent(timerID);
    timerID = 0;
}
MmTimer.timeEndPeriod(uResolution);

コールバック関数での処理

コールバックで呼び出される関数のテンプレートを示します。timerIDは、timeSetEvent()が戻した値です。instanceにはtimeSetEvent()の4番目の引数の値が設定されます。

static void TimerCallback(
    int         timerID,
    int         msg,
    IntPtr      instance,
    IntPtr      param1,
    IntPtr      param2)
{
    // TODO:
}

コールバック関数内から呼び出せるAPIは、アンマネージ環境と同じ制限がありますので注意して下さい。特にコールバック関数内からフォームやコントロールの描画等は行わないで下さい。

ドキュメントの先頭へ

カクタスソフトウェア 技術協力 資料室 資料室の広場 SourceForge.jp お問い合わせ