--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+using DirectShowLib;
+
+namespace FDK
+{
+ public class CTimer : CTimerBase
+ {
+ public enum E種別
+ {
+ Unknown = -1,
+ PerformanceCounter = 0,
+ MultiMedia = 1,
+ GetTickCount = 2,
+ }
+ public E種別 eタイマ種別
+ {
+ get;
+ protected set;
+ }
+
+
+ public override long nシステム時刻ms
+ {
+ get
+ {
+ switch( this.eタイマ種別 )
+ {
+ case E種別.PerformanceCounter:
+ {
+ double num = 0.0;
+ if( this.n現在の周波数 != 0L )
+ {
+ long x = 0L;
+ QueryPerformanceCounter( ref x );
+ num = ( (double) x ) / ( ( (double) this.n現在の周波数 ) / 1000.0 );
+ }
+ return (long) num;
+ }
+ case E種別.MultiMedia:
+ return (long) timeGetTime();
+
+ case E種別.GetTickCount:
+ return (long) Environment.TickCount;
+ }
+ return 0;
+ }
+ }
+
+ public CTimer( E種別 eタイマ種別 )
+ :base()
+ {
+ this.eタイマ種別 = eタイマ種別;
+
+ if( n参照カウント[ (int) this.eタイマ種別 ] == 0 )
+ {
+ switch( this.eタイマ種別 )
+ {
+ case E種別.PerformanceCounter:
+ if( !this.b確認と設定_PerformanceCounter() && !this.b確認と設定_MultiMedia() )
+ this.b確認と設定_GetTickCount();
+ break;
+
+ case E種別.MultiMedia:
+ if( !this.b確認と設定_MultiMedia() && !this.b確認と設定_PerformanceCounter() )
+ this.b確認と設定_GetTickCount();
+ break;
+
+ case E種別.GetTickCount:
+ this.b確認と設定_GetTickCount();
+ break;
+
+ default:
+ throw new ArgumentException( string.Format( "未知のタイマ種別です。[{0}]", this.eタイマ種別 ) );
+ }
+ }
+
+ base.tリセット();
+
+ n参照カウント[ (int) this.eタイマ種別 ]++;
+ }
+
+ public override void Dispose()
+ {
+ if( this.eタイマ種別 == E種別.Unknown )
+ return;
+
+ int type = (int) this.eタイマ種別;
+
+ n参照カウント[ type ] = Math.Max( n参照カウント[ type ] - 1, 0 );
+
+ if( n参照カウント[ type ] == 0 )
+ {
+ if( this.eタイマ種別 == E種別.MultiMedia )
+ timeEndPeriod( this.timeCaps.wPeriodMin );
+ }
+
+ this.eタイマ種別 = E種別.Unknown;
+ }
+
+ #region [ protected ]
+ //-----------------
+ protected long n現在の周波数;
+ protected static int[] n参照カウント = new int[ 3 ];
+ protected TimeCaps timeCaps;
+
+ protected bool b確認と設定_GetTickCount()
+ {
+ this.eタイマ種別 = E種別.GetTickCount;
+ return true;
+ }
+ protected bool b確認と設定_MultiMedia()
+ {
+ this.timeCaps = new TimeCaps();
+ if( ( timeGetDevCaps( out this.timeCaps, (uint) Marshal.SizeOf( typeof( TimeCaps ) ) ) == 0 ) && ( this.timeCaps.wPeriodMin < 10 ) )
+ {
+ this.eタイマ種別 = E種別.MultiMedia;
+ timeBeginPeriod( this.timeCaps.wPeriodMin );
+ return true;
+ }
+ return false;
+ }
+ protected bool b確認と設定_PerformanceCounter()
+ {
+ if( QueryPerformanceFrequency( ref this.n現在の周波数 ) != 0 )
+ {
+ this.eタイマ種別 = E種別.PerformanceCounter;
+ return true;
+ }
+ return false;
+ }
+ //-----------------
+ #endregion
+
+ #region [ DllImport ]
+ //-----------------
+ [DllImport( "kernel32.dll" )]
+ protected static extern short QueryPerformanceCounter( ref long x );
+ [DllImport( "kernel32.dll" )]
+ protected static extern short QueryPerformanceFrequency( ref long x );
+ [DllImport( "winmm.dll" )]
+ protected static extern void timeBeginPeriod( uint x );
+ [DllImport( "winmm.dll" )]
+ protected static extern void timeEndPeriod( uint x );
+ [DllImport( "winmm.dll" )]
+ protected static extern uint timeGetDevCaps( out TimeCaps timeCaps, uint size );
+ [DllImport( "winmm.dll" )]
+ protected static extern uint timeGetTime();
+
+ [StructLayout( LayoutKind.Sequential )]
+ protected struct TimeCaps
+ {
+ public uint wPeriodMin;
+ public uint wPeriodMax;
+ }
+ //-----------------
+ #endregion
+ }
+}