- 締切済み
vba引数の渡し方について
win32APIで作成したシステムを64bit環境でも動くよう修正をしています。 win7、access2010 以下のとおり宣言変更したところ、lpDevMode型が32bitの場合Long型、64bitはDEVMODE(構造体)となりました。 この時、Private Const DEFAULT_VALUES = 0のところは64bit用にどのように修正したらよいのでしょうか? このままコンパイルすると「ByRef 引数の型が一致しません。」となります。 <<宣言>> #If VBA7 And Win64 Then Private Declare PtrSafe Function DeviceCapabilities Lib "winspool.drv" _ Alias "DeviceCapabilitiesA" (ByVal lpDeviceName As String, _ ByVal lpPort As String, ByVal iIndex As Long, ByVal lpOutput As String, _ lpDevMode As DEVMODE) As Long #Else Private Declare Function DeviceCapabilities Lib "winspool.drv" _ Alias "DeviceCapabilitiesA" (ByVal lpsDeviceName As String, _ ByVal lpPort As String, ByVal iIndex As Long, lpOutput As Any, _ ByVal lpDevMode As Long) As Long #End If Private Const DEFAULT_VALUES = 0 <<呼び出し元>> lngBinCount = DeviceCapabilities(lpsDeviceName:=strDeviceName, _ lpPort:=strDevicePort, _ iIndex:=DC_BINNAMES, _ lpOutput:=ByVal vbNullString, _ lpDevMode:=DEFAULT_VALUES) ↑「ByRef 引数の型が一致しません。」
- みんなの回答 (2)
- 専門家の回答
みんなの回答
- real beatin(@realbeatin)
- ベストアンサー率82% (174/211)
回答No.1です。こちらから追記します。 『プリンターの機能をプログラムで取得します。』 https://msdn.microsoft.com/ja-jp/library/office/ff197339.aspx (2つめのサンプル) 『Excel VBAでプリンターの用紙サイズの一覧を取得して自動的に指定する』 http://locosoft.cocolog-nifty.com/blog/2012/03/excel-vba-820b.html などのサンプルを書き換えて色々試してみました。 strDeviceName, strDevicePort が正しく取得され要件を満たしているという前提ですと、 VBA7 And Win64 環境では、 ' ' <<宣言>> Private Declare PtrSafe Function DeviceCapabilities _ Lib "winspool.drv" Alias "DeviceCapabilitiesA" ( _ ByVal lpsDeviceName As String, ByVal lpPort As String, _ ByVal iIndex As Long, lpOutput As Any, _ ByVal lpDevMode As Long) As Long Private Const DEFAULT_VALUES = 0 Private Const DC_BINNAMES = 12 ' ' <<呼び出し元>> ご提示のまま lngBinCount = DeviceCapabilities( _ lpsDeviceName:=strDeviceName, _ lpPort:=strDevicePort, _ iIndex:=DC_BINNAMES, _ lpOutput:=ByVal vbNullString, _ lpDevMode:=DEFAULT_VALUES) のように、構造体には触れずに、lpDevMode をそのままByValで渡すことで ただ単に PtrSafe キーワードを追加するだけの対処で 正しい実行結果が得られることを確認しました。 VBA7 And Win64 以外の VBA7 環境に納まっている場合でしたら、 条件付きコンパイルを全く使わずに簡素に書いた方が解り易くて好いのかも知れません。 No.1のように条件付きコンパイルで lpDevMode As DEVMODE にDEVMODE型の変数をByRefで渡すやり方でも 正しい結果が得られることも確認できました。 条件付きコンパイルで書く場合でも、DEVMODE構造体は必須ではなくて、 宣言部の PtrSafe キーワードの有無だけで済ませることも出来る、というお話でした。 一応、念の為ですが、条件付きコンパイルで書く場合は 名前付き引数(lpDeviceName/lpsDeviceName)の不統一を修正するよう確認してください。 (もしくは、API関数のコールには名前付き引数を使わないとか) 以上です。
- real beatin(@realbeatin)
- ベストアンサー率82% (174/211)
こんにちは。 『Office 2010 Help Files: Win32API_PtrSafe with 64-bit Support』 https://www.microsoft.com/en-us/download/details.aspx?id=9970 参考リンクにあるダウンロードサンプル(私は常用しています)を参考に <<宣言>>部の条件付きコンパイル#If配下に DEVMODE構造体と 必要な定数(CCHDEVICENAME CCHFORMNAME DC_BINNAMES)を (Private Const DEFAULT_VALUES = 0 は #Else配下に) 宣言して、 <<呼び出し元>>を条件付きコンパイルに書き換えて #If配下に 構造体を変数として宣言して 呼び出しを書き足して、、、 #Else配下は、ご提示の記述のまま、、、 '<<呼び出し元>> #If VBA7 And Win64 Then Dim myDevMode As DEVMODE lngBinCount = DeviceCapabilities(lpDeviceName:=strDeviceName, _ lpPort:=strDevicePort, _ iIndex:=DC_BINNAMES, _ lpOutput:=ByVal vbNullString, _ lpDevMode:=myDevMode) #Else lngBinCount = DeviceCapabilities ... ご提の記述 ... #End If みたいにしてみては如何でしょう? 他のAPIを VBA7 And Win64 で扱った経験から、 形式的に一般的な方法を提示しているだけで、 私は使用したことがない関数ですから、 必ずしも実践的な正答ではないかも知れませんが。 以上、ご参考まで。