- 締切済み
VC++のソースをExcel2003VBA用に翻訳でまいっています。構造体等、、
他カテゴリで質問させていただいたのですが、回答が得られませんでしたので、こちらのカテゴリへ再質問させていただきました。 VC++のソースをExcel2003VBA用に翻訳しているのですが動いてくれません。 解かる方いらっしゃいましたら、ご教授お願い致します。 構造体が4バイト区切りになってしまうことと、 コントロールコードを取得する部分が問題点? かと思っているのですが解決方法がわかりません。 「PPJoy」という仮想ジョイスティックを作成するフリーソフトと、 「PPJoy」で用意されているプログラミング方法で仮想ジョイスティックを操作する方法、 この2つを利用して、コード上から仮想ジョイスティックを利用したいと思っています。 「PPJoy」のインストール方法が詳しく書いてあるサイト http://z800.blog.shinobi.jp/Entry/123/ 「PPJoy」のプログラミング方法が書いてあるサイト http://www.geocities.com/deonvdw/Docs/Diagrams/Virtual/IOCTL.htm http://chihara.naist.jp/people/STAFF/imura/computer/misc/virtual_joystick/disp_content 文字数制限が掛かってしまうため、分割してアップします。 以上です。よろしくお願いいたします。
- みんなの回答 (3)
- 専門家の回答
みんなの回答
- redfox63
- ベストアンサー率71% (1325/1856)
問題点1 これは マクロ展開処理です #defineで定義された文字列は PPORTJOY_IOCTLと引数_index_をつかって スペースで区切られた後ろの文字列に置換します 関数定義の簡易版と考えてください 問題点2 unsigend longについては VBではlong型で代用します ただし 定数でUL付きで宣言されている場合は気をつけましょう 2147483647以上の数値を VBでは整数として認識出来ません HEX関数などで文字列にして 比較するような工夫が必要です 問題点3 CreateFileの戻り値が -1以外なら大丈夫なように思います
- redfox63
- ベストアンサー率71% (1325/1856)
構造体のメンバーはこのソースの場合 1バイト境界ですよ #pragma pack( push,1) が宣言されているので 1バイト境界にでメンバーを配置します #pragma pack(pop) で 先のpack(push,1)が宣言される前の状態に戻しています Cの配列の宣言とVBの配列の宣言が違うといった部分が見落とされているようです 8個の要素を必要とする配列の場合 Cでは long a[8]; と宣言すると a[0]からa[7]が確保されます VBで同様の宣言をする場合 Option Baseを宣言していない場合は Dim a(8) as long と宣言すると a(0)から a(8)の9要素を確保します 8要素にするには dim a(7) as long といった宣言へ変更しなくてはいけません Cで書かれた構造体のサイズと VBで書いた構造体のサイズが期待通りなのか確認しましょう VBでは 構造体型の変数を Lenなどで大きさを調べられます
- kikuchi333
- ベストアンサー率0% (0/0)
====VC++のソースのオリジナル開始============================================== /* PPJIoctl.h ファイル開始================================*/ #ifndef __PPJIOCTL_H__ #define __PPJIOCTL_H__ /* Define to use byte-size values for joystick axes, else dword size */ #undef UCHAR_AXES #define PPJOY_AXIS_MIN 1 #ifdef UCHAR_AXES #define PPJOY_AXIS_MAX 127 #else #define PPJOY_AXIS_MAX 32767 #endif #define FILE_DEVICE_PPORTJOY FILE_DEVICE_UNKNOWN #define PPORTJOY_IOCTL(_index_) \ CTL_CODE (FILE_DEVICE_PPORTJOY, _index_, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_PPORTJOY_SET_STATE PPORTJOY_IOCTL (0x0) #define JOYSTICK_STATE_V1 0x53544143 typedef struct { ULONG Version; UCHAR Data[1]; } JOYSTICK_SET_STATE, *PJOYSTICK_SET_STATE; #endif /* PPJIoctl.h ファイル終了================================*/ /* main.c ファイル開始================================*/ #include <stdio.h> #include <conio.h> #include <windows.h> #include <winioctl.h> #include "ppjioctl.h" #define NUM_ANALOG 8 /* Number of analog values which we will provide */ #define NUM_DIGITAL 16 /* Number of digital values which we will provide */ #pragma pack(push,1) /* All fields in structure must be byte aligned. */ typedef struct { unsigned long Signature; /* Signature to identify packet to PPJoy IOCTL */ char NumAnalog; /* Num of analog values we pass */ long Analog[NUM_ANALOG]; /* Analog values */ char NumDigital; /* Num of digital values we pass */ char Digital[NUM_DIGITAL]; /* Digital values */ } JOYSTICK_STATE; #pragma pack(pop) int main (int argc, char **argv) { HANDLE h; char ch; JOYSTICK_STATE JoyState; DWORD RetSize; DWORD rc; long *Analog; char *Digital; char *DevName; DevName= "\\\\.\\PPJoyIOCTL1"; if (argc==2) DevName= argv[1]; /* Open a handle to the control device for the first virtual joystick. */ /* Virtual joystick devices are names PPJoyIOCTL1 to PPJoyIOCTL16. */ h= CreateFile(DevName,GENERIC_WRITE,FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL); /* Make sure we could open the device! */ if (h==INVALID_HANDLE_VALUE) { printf ("CreateFile failed with error code %d trying to open %s device\n",GetLastError(),DevName); return 1; } /* Initialise the IOCTL data structure */ JoyState.Signature= JOYSTICK_STATE_V1; JoyState.NumAnalog= NUM_ANALOG; /* Number of analog values */ Analog= JoyState.Analog; /* Keep a pointer to the analog array for easy updating */ JoyState.NumDigital= NUM_DIGITAL; /* Number of digital values */ Digital= JoyState.Digital; /* Digital array */ printf ("PPJoy virtual joystick demonstration program -- controlling virtual joystick 1.\n\n"); printf ("Press 1,2,3,4,5,6,7,8,9,0,z,x,c,v,b,n keys for buttons 1-16.\n"); printf ("Press q,w,e,r,t,y,u,i keys for up (max) values for axis 1-16.\n"); printf ("Press a,s,d,f,g,h,j,k keys for down (min) values for axis 1-16.\n"); printf ("\nPress ESC to exit..."); while ((ch=getch())!=27) { /* On each iteration clear position buffer: Analog in centre, buttons not pressed */ Analog[0]= Analog[1]= Analog[2]= Analog[3]= Analog[4]= Analog[5]= Analog[6]= Analog[7]= (PPJOY_AXIS_MIN+PPJOY_AXIS_MAX)/2; memset (Digital,0,sizeof(JoyState.Digital)); /* Convert input to upper case */ if ((ch>='A')&&(ch<='Z')) ch|=0x20; /* Very simple demo app! */ switch (ch) { /* 1,2,3,4,5,6,7,8,9,0,z,x,c,v,b,n are buttons */ case '1': Digital[0]= 1; break; case '2': Digital[1]= 1; break; case '3': Digital[2]= 1; break; case '4': Digital[3]= 1; break; case '5': Digital[4]= 1; break; case '6': Digital[5]= 1; break; case '7': Digital[6]= 1; break; case '8': Digital[7]= 1; break; case '9': Digital[8]= 1; break; case '0': Digital[9]= 1; break; case 'z': Digital[10]= 1; break; case 'x': Digital[11]= 1; break; case 'c': Digital[12]= 1; break; case 'v': Digital[13]= 1; break; case 'b': Digital[14]= 1; break; case 'n': Digital[15]= 1; break; /* q,w,e,r,t,y,u,i are "up" for each axis */ case 'q': Analog[0]= PPJOY_AXIS_MAX; break; case 'w': Analog[1]= PPJOY_AXIS_MAX; break; case 'e': Analog[2]= PPJOY_AXIS_MAX; break; case 'r': Analog[3]= PPJOY_AXIS_MAX; break; case 't': Analog[4]= PPJOY_AXIS_MAX; break; case 'y': Analog[5]= PPJOY_AXIS_MAX; break; case 'u': Analog[6]= PPJOY_AXIS_MAX; break; case 'i': Analog[7]= PPJOY_AXIS_MAX; break; /* a,s,d,f,g,h,j,k are "down" for each axis */ case 'a': Analog[0]= PPJOY_AXIS_MIN; break; case 's': Analog[1]= PPJOY_AXIS_MIN; break; case 'd': Analog[2]= PPJOY_AXIS_MIN; break; case 'f': Analog[3]= PPJOY_AXIS_MIN; break; case 'g': Analog[4]= PPJOY_AXIS_MIN; break; case 'h': Analog[5]= PPJOY_AXIS_MIN; break; case 'j': Analog[6]= PPJOY_AXIS_MIN; break; case 'k': Analog[7]= PPJOY_AXIS_MIN; break; } /* Send request to PPJoy for processing. */ /* Currently there is no Return Code from PPJoy, this may be added at a */ /* later stage. So we pass a 0 byte output buffer. */ if (!DeviceIoControl(h,IOCTL_PPORTJOY_SET_STATE,&JoyState,sizeof(JoyState),NULL,0,&RetSize,NULL)) { rc= GetLastError(); if (rc==2) { printf ("Underlying joystick device deleted. Exiting read loop\n"); break; } printf ("DeviceIoControl error %d\n",rc); } } CloseHandle(h); return 0; } /* main.c ファイル終了================================*/ ====VC++のソースのオリジナル終了==============================================
補足
====翻訳中のExcel2003VBA用ソース開始============================================== '標準モジュール============================================== Option Explicit 'ファイル(各種デバイス)を開く Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpCommName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long 'CreateFile用定数 Const GENERIC_WRITE = &H40000000 Const FILE_SHARE_WRITE = &H2 Const OPEN_EXISTING = 3 'デバイス間I/O制御 Declare Function DeviceIoControl Lib "kernel32" (ByVal hDevice As Long, ByVal dwIoControlCode As Long, lpInBuffer As Any, ByVal nInBufferSize As Long, lpOutBuffer As Any, ByVal nOutBufferSize As Long, lpBytesReturned As Long, lpOverlapped As Any) As Long 'DeviceIoControl用定数 Const FILE_DEVICE_UNKNOWN As Long = &H22 Const FILE_DEVICE_PPORTJOY As Long = FILE_DEVICE_UNKNOWN Const METHOD_BUFFERED As Long = 0 Const FILE_ANY_ACCESS As Long = 0 '構造体用定数 Const NUM_ANALOG = 8 Const NUM_DIGITAL = 16 Const JOYSTICK_STATE_V1 = &H53544143 '構造体定義 Private Type JOYSTICK_STATE Signature As Long '修正候補 NumAnalog As Byte '修正候補 Analog(NUM_ANALOG) As Long '修正候補 NumDigital As Byte '修正候補 Digital(NUM_DIGITAL) As Byte '修正候補 End Type 'カレントスレッドの最後に発生したエラーコードを取得する Declare Function GetLastError Lib "kernel32.dll" () As Long 'ハンドルを閉じる Declare Function CloseHandle Lib "kernel32" (ByVal hCom As Long) As Long Sub 仮想ジョイスティックテスト() Dim h As Long 'ハンドル用変数 Dim JoyState As JOYSTICK_STATE '構造体変数 Dim RetSize As Long ' Dim rc As Long 'エラーコード用変数 Dim ctlcode As Long 'DeviceIoControl第2引数用変数 'バーチャルジョイスティックをオープンする h = CreateFile("\\.\PPJoyIOCTL1", GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0) Debug.Print "ハンドルコード=" & h 'バーチャルジョイスティックにデータを送る前処理 ctlcode = CTL_CODE(FILE_DEVICE_PPORTJOY, 0, METHOD_BUFFERED, FILE_ANY_ACCESS) 'バーチャルジョイスティックに送る構造体のデータ変更 JoyState.Signature = JOYSTICK_STATE_V1 JoyState.NumAnalog = NUM_ANALOG JoyState.NumDigital = NUM_DIGITAL JoyState.Analog(0) = 1 'バーチャルジョイスティックにデータを送る If (DeviceIoControl(h, ctlcode, JoyState, Len(JoyState), 0, 0, RetSize, 0) = 0) Then rc = GetLastError() End If 'バーチャルジョイスティックをクローズする CloseHandle h End Sub Private Function CTL_CODE(lngDevFileSys As Long, lngFunction As Long, lngMethod As Long, lngAccess As Long) As Long CTL_CODE = (lngDevFileSys * (2 ^ 16)) Or (lngAccess * (2 ^ 14)) Or (lngFunction * (2 ^ 2)) Or lngMethod End Function ====翻訳中のExcel2003VBA用ソース終了==============================================
お礼
redfox63様、御回答ありがとうございます >#pragma pack( push,1) >が宣言されているので 1バイト境界にでメンバーを配置します >#pragma pack(pop) >で 先のpack(push,1)が宣言される前の状態に戻しています おっしゃる通りです。 Cでは1バイト区切りになるがVBでは4バイト区切りになってしまいます、と言いたかったです。 言葉足らずで申し訳ありませんでした。 >VBで同様の宣言をする場合 Option Baseを宣言していない場合は >Dim a(8) as long >と宣言すると a(0)から a(8)の9要素を確保します Option Baseを指定していない場合、Dim a(8) as longと宣言すると a(0)から8個の要素を自動で確保してくれると勘違いしておりました。 ご指摘ありがとうございます。 #define NUM_ANALOG 8 #define NUM_DIGITAL 16 #pragma pack(push,1) typedef struct { unsigned long Signature; char NumAnalog; long Analog[NUM_ANALOG]; char NumDigital; char Digital[NUM_DIGITAL]; } JOYSTICK_STATE; #pragma pack(pop) 予想サイズ54バイト のソースを '構造体用定数 Const NUM_ANALOG = 8 Const NUM_DIGITAL = 16 '構造体定義 Private Type JOYSTICK_STATE Signature As Long NumAnalog As Byte Analog(NUM_ANALOG - 1) As Long NumDigital As Byte Digital(NUM_DIGITAL - 1) As Byte End Type と変更した所Len(JoyState)=54となり期待通りになりました。 VBでは4バイト区切りになるというのも勘違いでした。申し訳ありません (NUM_ANALOGとNUM_DIGITALが1以下になることはないので簡単に書きました) redfox63様のおかげで1歩前進しました。ありがとうございます。
補足
予想問題点をあげてみます。 予想問題点1 >'DeviceIoControl用定数 >Const FILE_DEVICE_UNKNOWN As Long = &H22 >Const FILE_DEVICE_PPORTJOY As Long = FILE_DEVICE_UNKNOWN >Const METHOD_BUFFERED As Long = 0 >Const FILE_ANY_ACCESS As Long = 0 >'バーチャルジョイスティックにデータを送る前処理 >ctlcode = CTL_CODE(FILE_DEVICE_PPORTJOY, 0, METHOD_BUFFERED, FILE_ANY_ACCESS) >'バーチャルジョイスティックにデータを送る >If (DeviceIoControl(h, ctlcode, JoyState, Len(JoyState), 0, 0, RetSize, 0) = 0) Then Cのソースでは >#define FILE_DEVICE_PPORTJOY FILE_DEVICE_UNKNOWN >#define PPORTJOY_IOCTL(_index_) \ > CTL_CODE (FILE_DEVICE_PPORTJOY, _index_, METHOD_BUFFERED, FILE_ANY_ACCESS) >#define IOCTL_PPORTJOY_SET_STATE PPORTJOY_IOCTL (0x0) >if (!DeviceIoControl(h,IOCTL_PPORTJOY_SET_STATE,&JoyState,sizeof(JoyState),NULL,0,&RetSize,NULL)) PPORTJOY_IOCTL(_index_)の部分の意味がまったくわかっておりません。 何故配列のような物に一回入れているのでしょうか? _index_って、、、、何? 予想問題点2 >Const JOYSTICK_STATE_V1 = &H53544143 >'バーチャルジョイスティックに送る構造体のデータ変更 >JoyState.Signature = JOYSTICK_STATE_V1 Cのソースでは >unsigned long Signature; の符号なし変数になっているので。 予想問題点3 >'バーチャルジョイスティックをオープンする >h = CreateFile("\\.\PPJoyIOCTL1", GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0) 引数の値がまちがっている可能性。 hに-1は帰ってこないので合ってるのでしょうか。 以上です。引き続きアドバイスお待ちしております。