API関数の使い方(簡単な)
                                                      玄関へお回り下さい。
簡単なAPI関数を使ってみる        (037)
     まず、どの関数を使うかAPI関数の本等で調べる。今回は、Sleepという関数を使って[プログラムの実行を一定時間だけ停止する]やり方を説明します。
API 関数の使用法の例題に Sleep 関数を使いましたが、実使用には色々弊害があるので、極力避けて下さい。どうしても必要な場合は、下記で紹介している、SetWaitableTimer を使用する等十分注意を払って下さい。
   1.構文
  [Public | Private] Declare Sub name Lib "libname" [Alias "aliasname"] [([arglist])] 
  実文  Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
  
指定項目 内            容
Public 省略可能です。モジュール内のすべてのプロシージャから参照できるプロシージャを宣言するときに指定します
Private 省略可能です。宣言が行われたモジュール内でのみ参照できるプロシージャを宣言するときに指定します。
Sub 省略可能です。ただし、Sub を省略する場合には、Function を指定する必要があります。プロシージャが値を返さないことを示します。
Function 省略可能です。ただし、Function を省略する場合には、Sub を指定する必要があります。プロシージャが値を返し、式の中で使えることを示します。
name 必ず指定します。任意の有効なプロシージャ名を指定します。DLL のエントリ ポイントは大文字小文字を区別して指定することに注意してください。
Lib 必ず指定します。宣言するプロシージャが DLL またはコードリソースに含まれていることを示します。Lib 節は、すべての宣言で必要です。
libname 必ず指定します。宣言するプロシージャが含まれている DLL またはコードリソースの名前を指定します。
Alias 省略可能です。呼び出すプロシージャが、DLL の中で別の名前を持っていることを示します。外部プロシージャの名前が Visual Basic のキーワードと同じ場合に役に立ちます。
DLL プロシージャの名前が、パブリック変数、パブリック定数、または適用範囲内のほかのプロシージャの名前と同じ場合でも、Alias を使えます。
また、Alias は、DLL の名前付け規則に合っていない文字がDLL プロシージャ名に含まれている場合にも使えます。
aliasname 省略可能です。DLL またはコードリソース内のプロシージャの名前を指定します。先頭の文字がシャープ記号 (#) でない場合、引数 aliasname には DLL 内で定義されているプロシージャのエントリ ポイント名を指定します
先頭の文字がシャープ記号 (#) の場合は、2 文字目以降の文字にはプロシージャのエントリ ポイントの序数を指定します。
arglist 省略可能です。プロシージャを呼び出すときに、プロシージャに渡す引数を表す変数のリストを指定します。
type 省略可能です。Function プロシージャの戻り値のデータ型を指定します。
バイト型 (Byte)、ブール型 (Boolean)、整数型 (Integer)、長整数型 (Long)、通貨型 (Currency)、単精度浮動小数点数型 (Single)、倍精度浮動小数点数 (Double)、10 進型 (Decimal) (現在はサポートされていません)、日付型 (Date)、文字列型 (String) (可変長のみ)、バリアント型 (Variant)、ユーザー定義型、オブジェクト型のいずれかを指定できます。
    2.APIビューアを使って関数を貼り付ける。

  (1).APIビューアを起動する。
  


  (2).APIファイルを開く
    ファイル→テキストファイルの読込み でWin32api.txtを開く
  


  (3).目的の関数を指定し [追加] [コピー] を実施クリップボードにコピーする

  


  (4).クリップボードからモジュールの宣言セクションに貼り付けます。

  

  又は、メニューバーの[アドイン]→A[PIビューア]
  (初めてはアドインマネージャーから)→APIビューアが開いたら→ファイル
  →テキストファイルの読み込み→WINAPIのフォルダーを開く→
  Win32api.txtを開く、尚、種類のところで、定数・型等を選択すれば、
  それぞれ表示されます。


3.プログラムを書く
  (1).フォームにラベルとコマンドボタンを貼り付ける。
  (2).コマンドボタンに下記コードを記入する。
        Private Sub Command1_Click()
        'APIを使って5秒間待つ
            Label1.Caption = "5秒後に消去します。"
            DoEvents
            Sleep 5000   
'ミリ秒で指定する(この場合5秒)
   
         'この間このウィンドウは一切のイベントに反応しない
            Label1.Caption = ""
        End Sub


4.実行して見て下さい、コマンドボタンをクリックするとラベルに"5秒後に消去します。"
  が表示され5秒立つと消えます。
  ちなみに、これをVisual Basicだけで実現するには下記のように書きます。但し、
  停止時間が長くなると誤差が生じます。Nwe関数を使ったやり方がマイクロソフトに
  あります
Private Sub Command2_Click()
'タイマー関数を使って5秒間待つ
   
Dim lngSt As Long
    Label1.Caption = "5秒後に消去します。"
    lngSt = Timer
   
Do While Timer - lngSt < 5
        DoEvents 
'制御をWindowsに渡す
   
Loop
   
'この場合は他のイベントも受け付ける
    Label1.Caption = ""
End Sub

上記を関数化すると
Private Sub StopTime(st As Single)
'タイマー関数を使って Sleep 関数と同様の関数を作成
   
Dim sngSt As Single
    sngSt = Timer
   
Do While Timer - sngSt < st
       '
Debug.Print Timer - sngSt
        DoEvents
   
Loop
End Sub

Private Sub Command3_Click()
'自作関数(StopTime)を使って5秒間待つ
    Label1.Caption = "5秒後に消去します。"
    StopTime 5.05
   
'この場合は他のイベントも受け付ける
    Label1.Caption = ""
End Sub

※ 掲載しておきながら、なんですが、上記のようなループで待機するような処理は、好ましくありませんので、極力避けて下さい。(以前はMSのサンプルでも見られたが!)
現在は、下記のような関数を紹介されています。

 SetWaitableTimer を使用する方法
 http://support.microsoft.com/kb/231298/ja

こんなに簡単な事で便利なAPI関数が使用できます。まず、簡単な関数から初めてだんだん複雑な関数を使用できるように挑戦して下さい。かくゆう、私もまだまだ十分に理解しておりません。
但し、関数の機能等をよく調べ使用しないと動作が不安定になったりします。上記の例でも解るようにSleep関数を使って待ち時間を作るとその間は、他のイベントを受け付けなくなる等の不都合がでます。VBの機能でも工夫すれば便利に使えます。
私の使っているAPIの参考書
発行所 (株)秀和システム 著者 河北潤二
Windows98 APIリファレンス for Visual basic Programmers
ByVal とByRef の使い方をよく、どちらが、どちらかと迷うことがありますので、HELPより抜粋して記入しておきます。

ByVal 省略可能です。その引数が、値渡し(変数の値のコピーをサブルーチンに渡すこと)で渡されることを示します。
ByRef 省略可能です。その引数が、参照渡し(呼び出されたプロシージャ内で渡された変数の値を変更すると、元の変数の値も変更されます。Visual Basic では、特に指定しない限り、プロシージャの引数は参照渡しで渡されます。)で渡されることを示します。Visual Basic では、既定値は ByRef ですが、参照渡し (ByRef) の代わりに値渡し (ByVal) で引数を渡す方が処理速度が速くなり、プログラムの最適化につながりますので、できれば宣言しておいて下さい。
実際は処理速度に関しては使い方次第で、あまり大差ないようです。

試しに、下記コードを貼り付けて実行して見て下さい。

Private Sub Command1_Click()
  Dim intA  As Integer
  Dim intB  As Integer

  intA = 1
  intB = 2
  Call subByRef(intA, intB)
  Debug.Print "ByRef :" & intA, intB

  intA = 1
  intB = 2
  Call subByVal(intA, intB)
  Debug.Print "ByVal :" & intA, intB

End Sub
Sub subByRef(ByRef a As Integer, ByRef b As Integer)
  a = 1000
  b = 2000
End Sub
Sub subByVal(ByVal a As Integer, ByVal b As Integer)
  a = 1000
  b = 2000
End Sub


 結果
     ByRef  : 1000     2000
     ByVal  : 1        2




2002/04/14