プロが教える店舗&オフィスのセキュリティ対策術

他カテゴリで質問させていただいたのですが、回答が得られませんでしたので、こちらのカテゴリへ再質問させていただきました。

VC++のソースをExcel2003VBA用に翻訳しているのですが動いてくれません。
解かる方いらっしゃいましたら、ご教授お願い致します。

構造体が4バイト区切りになってしまうことと、
コントロールコードを取得する部分が問題点?
かと思っているのですが解決方法がわかりません。


「PPJoy」という仮想ジョイスティックを作成するフリーソフトと、
「PPJoy」で用意されているプログラミング方法で仮想ジョイスティックを操作する方法、

この2つを利用して、コード上から仮想ジョイスティックを利用したいと思っています。

「PPJoy」のインストール方法が詳しく書いてあるサイト
http://z800.blog.shinobi.jp/Entry/123/

「PPJoy」のプログラミング方法が書いてあるサイト
http://www.geocities.com/deonvdw/Docs/Diagrams/V …
http://chihara.naist.jp/people/STAFF/imura/compu …


文字数制限が掛かってしまうため、分割してアップします。
以上です。よろしくお願いいたします。

A 回答 (3件)

問題点1


これは マクロ展開処理です
#defineで定義された文字列は PPORTJOY_IOCTLと引数_index_をつかって スペースで区切られた後ろの文字列に置換します
関数定義の簡易版と考えてください

問題点2
unsigend longについては VBではlong型で代用します
ただし 定数でUL付きで宣言されている場合は気をつけましょう
2147483647以上の数値を VBでは整数として認識出来ません
HEX関数などで文字列にして 比較するような工夫が必要です

問題点3
CreateFileの戻り値が -1以外なら大丈夫なように思います
    • good
    • 0

構造体のメンバーはこのソースの場合 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などで大きさを調べられます

この回答への補足

予想問題点をあげてみます。

予想問題点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_PPORTJOYFILE_DEVICE_UNKNOWN
>#define PPORTJOY_IOCTL(_index_)\
>CTL_CODE (FILE_DEVICE_PPORTJOY, _index_, METHOD_BUFFERED, FILE_ANY_ACCESS)
>#define IOCTL_PPORTJOY_SET_STATEPPORTJOY_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は帰ってこないので合ってるのでしょうか。


以上です。引き続きアドバイスお待ちしております。

補足日時:2008/04/11 04:54
    • good
    • 0
この回答へのお礼

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個の要素を自動で確保してくれると勘違いしておりました。
ご指摘ありがとうございます。


#defineNUM_ANALOG 8
#defineNUM_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歩前進しました。ありがとうございます。

お礼日時:2008/04/11 04:53

====VC++のソースのオリジナル開始==============================================



/* PPJIoctl.h ファイル開始================================*/

#ifndef __PPJIOCTL_H__
#define __PPJIOCTL_H__

/* Define to use byte-size values for joystick axes, else dword size */
#undef UCHAR_AXES

#definePPJOY_AXIS_MIN1
#ifdef UCHAR_AXES
#definePPJOY_AXIS_MAX127
#else
#definePPJOY_AXIS_MAX32767
#endif

#define FILE_DEVICE_PPORTJOYFILE_DEVICE_UNKNOWN

#define PPORTJOY_IOCTL(_index_)\
CTL_CODE (FILE_DEVICE_PPORTJOY, _index_, METHOD_BUFFERED, FILE_ANY_ACCESS)

#define IOCTL_PPORTJOY_SET_STATEPPORTJOY_IOCTL (0x0)

#defineJOYSTICK_STATE_V10x53544143

typedef struct
{
ULONGVersion;
UCHARData[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"

#defineNUM_ANALOG8/* Number of analog values which we will provide */
#defineNUM_DIGITAL16/* Number of digital values which we will provide */

#pragma pack(push,1)/* All fields in structure must be byte aligned. */
typedef struct
{
unsigned longSignature;/* Signature to identify packet to PPJoy IOCTL */
charNumAnalog;/* Num of analog values we pass */
longAnalog[NUM_ANALOG];/* Analog values */
charNumDigital;/* Num of digital values we pass */
charDigital[NUM_DIGITAL];/* Digital values */
}JOYSTICK_STATE;
#pragma pack(pop)

int main (int argc, char **argv)
{
HANDLEh;
charch;
JOYSTICK_STATEJoyState;

DWORDRetSize;
DWORDrc;

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用ソース終了==============================================

補足日時:2008/04/11 01:57
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!