• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:win32api構造体引数の型指定について)

win32api構造体引数の型指定について

このQ&Aのポイント
  • 「win32api構造体引数の型指定について」というタイトルで、初めてwin32apiに挑戦し、構造体引数の渡し方が上手くいかない問題を質問しています。
  • 具体的には、利用したいAPIである「midiOutGetDevCaps」で発生するエラーについて説明しており、エラーの詳細な内容として「型 'UInt32' のフィールド '_vDriverVersion' を持つ構造体のファイル入出力 (I/O) は無効です。」というメッセージが表示されると述べています。
  • さらに、実際のAPI呼び出しのソースコードをVBで示し、エラーが発生する箇所を指定しています。

質問者が選んだベストアンサー

  • ベストアンサー
  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.1

VB.netは使ったことはありませんし、エラーの原因になる理由もわかりませんが… 気になったところを。 ><MarshalAs(UnmanagedType.LPTStr)> Dim szPname As String コレで、MAXPNAMELENバイトの領域になりますか? この場合、APIから値を返されるコトになりますので、 http://akademeia.info/index.php?VB.NET%2F%A5%C6%A5%AF%A5%CB%A5%C3%A5%AF%2FWin32API%A4%CE%CD%F8%CD%D1#d12bfd5e で説明されている「VB.NETがAPIから文字列を受け取る場合はString型でもうまくいかない。」に関わる様な気がします。 そして、構造体のサイズ(バイト数)をmidiOutGetDevCaps()の第3引数に渡すことになりますが… sizeof(MIDIOUTCAPSA)とLen(mc)は同じになるのでしょうか? # APIの説明的には想定している構造体よりサイズが小さい場合は後ろのメンバは触られないみたいですが。

selfesteem
質問者

お礼

Wr5様 ご回答ありがとうございます! UInt32 → Integer <MarshalAs(UnmanagedType.LPTStr)> → <MarshalAs(UnmanagedType.ByValTStr, sizeconst:=32)> とすることで解決しました。大変助かりました。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 構造体配列

    こんにちわ。VB.NET初心者です。伝授お願いします。 VB6では Type Tpn_Index IdxSu As Integer idx(MAXTPN-1) As Integer End Type と定義できますが、VB.netでは構造体の中の配列部分が定義できません。 どのように書けばよろしいでしょうか? Public Structure Tpn_Index Dim IdxSu As Integer Dim idx() As Integer End Structure 上記の Dim idx() As Integer の部分です 宜しくお願いします

  • vc++のAPI(dll)の引数をVBAでうけとる

    Excelで開発しなければならない事情があり、 vc++のAPIが持っている関数を ExcelVBAでコールしておりますが、エラー1041でExcelが強制終了してしまいます。 VBAからVisual C++にchar*型で渡し、ByRef String型でVBAにて受け取ります。 VCの関数の第四引数「char* 型/attribute_value」をVBAの「String 型/sValue」で受け取る際にエラーになっているようです。 VBAでcharに相当する変数型がないためと思われますが、何かよいアイデアがありましたらご教授願います。 --VC-- XDW_GetDocumentAttributeByName(h, attribute_name, &attribute_type, attribute_value, size, NULL); --VBA-- <宣言部> Public Declare Function XDW_GetDocumentAttributeByName Lib "C:\Users\○○○\Desktop\dwsdk710jpn\XDWAPI\DLL\xdwapi.dll" (ByVal lnghandle As Long, ByVal sName As String, ByRef lngType As Long, ByRef sValue As String, ByVal lngSize As Long, ByVal reserved As String) As Long <呼び出し部> Dim lngHandle As Long Dim sName as String Dim lngType As Long Dim sValue As String Dim lngSize as Long Dim tmpSize as Long lngSize = 0 sName = "keiyaku" tmpSize = XDW_GetDocumentAttributeByName(lngHandle, sName, sType, sValue, lngSize, vbNullString) XDW_GetDocumentAttributeByName lngHandle, sName, sType, vbNullString, tmpSize, vbNullString degug.print sValue

  • VB.NET2013多次元構造体の初期化について

    Visual Studio2013 VB.NETを始めたばかりです 多次元構造体の初期化で困ってました 内容的には Public Structure ST1 Public a1 As Boolean Public a2 As Integer <VBFixedArray((9), (2)), MarshalAs(UnmanagedType.ByValArray, sizeconst:=30)> _ Public a3(,) As Long Public Sub Initialize() ReDim a3(9, 2) End Sub End Structure Public ss1(0) as ST! Public Sub test() ss1.Initialize() ss1(0).a3(0,0)=0 この状態では、多次元配列は確保されなくNothingで 初期化できない、参照型であると言うのが分かり 色々と調べてみてやっと、 コピーコンストラクタを用意して複製する方法で出来るのが分かりました Public Sub New(ByVal ss As ST1) MyClass.a1 = ss.a1 MyClass.a2 = ss.a2 MyClass.a3 = DirectCast(ss.a3.Clone(), Long(,)) End Sub End Structure Public Sub test() Dim ss0 As ST1 ss0.a1 = True ss0.a2 = 1 ss0.a3 = New Longr(,) {・・・・} Dim ss1(0) As New ss0 ただa3のサイズが大きいため定義するのは大変なので Dim bb(9,2) As Long ss0.a3 = bb としても上手く初期化できるのが分かり そしてステップ実行で中を確認していると あれっと思い 「コピーコンストラクタを用意して複製」 の方法ではなく元のまま Public Sub test() Dim bb(9,2) As Long ss1.Initialize() ss1(0).a3=bb とすると、上手く初期化され ss1(0).a3(0,1) = 100 と処理できるようになりました ただ、これで本当にいいのかが分かりません よろしくお願いします

  • 構造体配列を引数とするDLL作成し、VBで呼ぶには?

    はじめまして。 VisualC++6.0でDLLを作り、VisualBasic6.0にて VisualC++の関数をコールし、構造体配列の値を 渡そうとしていますがうまくいきません。 どなたかよい知恵をお貸しください。 宜しくお願い致します。 下記に、VisualC++6.0とVisualBasic6.0のやりとり を記します。 *====Visual C++ 6.0側===== typedef struct _DLP_MSGDATA { int flg; char msg[504]; int tmp; } DLP_MSGDATA; _declspec(dllexport) int _stdcall SampSub(int data, DLP_MSGDATA *mdata) { return( 0 ); } *====Visual Basic 5.0側===== Declare Function SampSub Lib "test.dll" Alias "_SampSub@8" _ ( _ ByVal tlp_id As Long, _ ByRef mdata() As DLP_TLP_MSGDATA _ ) As Long Type DLP_TLP_MSGDATA flg As Long msg As String * 504 tmp As Long End Type Private Sub test() Dim mdata(0 To 130) As DLP_TLP_MSGDATA Dim aa As Long Call SampSub( aa, mdata ) End sub

  • VBA ウィンドウの列挙 Win32 API

    http://d.hatena.ne.jp/cartooh/20090618 上記のページに記載されているVBAです。 動作は確認できたのですが、どのような処理の流れとなっているのかがわかりません。 どなたかコメントを付けていただけないでしょうか。 よろしくお願いいたします。 Option Explicit Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal cnm As String, ByVal cap As String) As Long Declare Function IsWindowVisible Lib "user32" (ByVal hWnd As Long) As Long Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As Long, ByVal lpString As String, _ ByVal cch As Long) As Long Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hWnd As Long, ByVal lpClassName As String, _ ByVal nMaxCount As Long) As Long Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent As Long, ByVal lpEnumFunc As Long, _ ByVal lParam As Long) As Long Declare Function IsWindow Lib "user32" (ByVal hWnd As Long) As Long Const INDENT_KEY = "INDENT" Public Function EnumChildWindowsProc(ByVal hWnd As Long, ByVal lParam As Object) As Long EnumChildWindowsProc = EnumWindowsProc(hWnd, lParam) End Function Public Function EnumWindowsProc(ByVal hWnd As Long, ByVal lParam As Object) As Long EnumWindowsProc = True If IsWindowVisible(hWnd) = 0 Then Exit Function End If Dim strClassName As String ' * 255 Dim strCaption As String ' * 255 strClassName = String(255, vbNullChar) strCaption = String(255, vbNullChar) GetWindowText hWnd, strCaption, Len(strCaption) GetClassName hWnd, strClassName, Len(strClassName) strCaption = RTrim(left(strCaption, InStr(1, strCaption, vbNullChar) - 1)) strClassName = RTrim(left(strClassName, InStr(1, strClassName, vbNullChar) - 1)) ActiveCell.Cells(1, 1).Value = Hex(hWnd) ActiveCell.Cells(1, 2).Value = IsWindowVisible(hWnd) ActiveCell.Cells(1, 3).Value = strCaption ActiveCell.Cells(1, 4).Value = strClassName ActiveCell.Cells(2, 2).Activate Dim c As Collection Set c = lParam Dim indent As Long indent = c(INDENT_KEY) c.Add String(indent * 2, " ") & Hex(hWnd) & " " & strCaption & " " & strClassName, before:=c.Count indent = indent + 1 c.Remove INDENT_KEY c.Add indent, INDENT_KEY Call EnumChildWindows(hWnd, AddressOf EnumChildWindowsProc, ObjPtr(c)) indent = c(INDENT_KEY) - 1 c.Remove INDENT_KEY c.Add indent, INDENT_KEY ActiveCell.Cells(1, 0).Activate End Function Sub hoge() Application.ScreenUpdating = False Dim sht As Worksheet Set sht = ThisWorkbook.Worksheets(1) sht.UsedRange.Clear sht.Activate sht.Range("A1").Activate Dim c As Collection Set c = New Collection c.Add 0, INDENT_KEY Dim ret As Long ret = EnumWindows(AddressOf EnumWindowsProc, ObjPtr(c)) c.Remove INDENT_KEY Set sht = ThisWorkbook.Worksheets(2) sht.UsedRange.Clear sht.Activate sht.Range("A1").Activate Dim o As Variant For Each o In c ActiveCell.Value = o ActiveCell.Cells(2, 1).Activate Next Application.ScreenUpdating = True End Sub

  • VB.NETで子ウィンドウの列挙の仕方がわかりません。

    VB.NET+FrameWork1.1環境なのですが、 子ウィンドウの取得の仕方がどうしてもわからず教えて頂きたいです。 Dim Oya As Long Oya = FindWindow(vbNullString, "電卓") Dim Ret As Long Ret = EnumChildWindows(Oya, AddressOf EnumChildWnd, 0) このようにして使うAPIのようなのですが、 デリゲート型をLong型に変換できませんと出てしまいます。 色々検索してみたのですが、それらしい記事が見つかるも どうしても理解できず、正常に動作させることが出来ませんでした。 もうしわけございませんが、どなたか実行可能なコードを書いて いただけないでしょうか。 出力結果はConsole.WriteLineに出るようにして頂けると助かります。 よろしくお願いいたします。m(__)m

  • C++/C#間での構造体の引き渡し方法に関して

    現在、C++で作成したクラスを、 C#から呼び出し実行しようとしております。 引数として、構造体を利用したいので、 C++側、C#側でそれぞれ下記のように 構造体を定義しました。 【C++】 typedef struct _Msg { ULONG Code; ULONG sessionId; }Msg; 【C#】 [StructLayout(LayoutKind.Sequential)] public struct Msg { public uint Code; public uint sessionId; } そして、下記のようにC++側で定義したクラスを C#側で呼び出そうとしたのですが、 「Msg*から_Msg*に変換できません」という コンパイルエラーが発生してしまいました。 構造体の定義は同じものになっていると思うのですが、 この原因は何だと考えられるでしょうか。 よろしくお願いいたします。 【C++】 ULONG Wrap::API( Msg* sample_Msg ) { return 1; } 【C#】 Msg sample_msg; Wrap.API(&sample_msg);

  • 構造体配列のソート

    VB6 ソートのやり方は知っていますが、構造体の定義が変わると対応できません。 ソート処理部分だけを共通関数にできますでしょうか? Private Type Sort strCol1 As String intCol2 As Integer sttCol3 As String End Type Private Sub A() Dim typSort(3) As Sort 'ここに、構造体データ設定処理を記述 Call subSort(typSort(), typSortCopy) End Sub Private Sub subSort(typTaget() As Sort) Dim lngOutLoop As Long Dim lngCurent As Long Dim lngInLoop As Long Dim Min As Variant Dim typSortCopy As Sort For lngOutLoop = LBound(typTaget) To UBound(typTaget) - 1 Min = typTaget(lngOutLoop).strCol1 lngCurent = lngOutLoop For lngInLoop = lngOutLoop + LBound(typTaget) + 1 To UBound(typTaget) If typTaget(lngInLoop).strCol1 < Min Then Min = typTaget(lngInLoop).strCol1 lngCurent = lngInLoop End If Next lngInLoop typTagetCopy = typTaget(lngOutLoop) typTaget(lngOutLoop) = typTaget(lngCurent) typTaget(lngCurent) = typTagetCopy Next lngOutLoop End Sub

  • VB2008: 構造体に関するMSDNの解釈について!

    ' ================== ' 構造体変数の代入 ' ================== Module theTEST   Private Structure TEST4     Dim MembersCount As Integer     Dim Member1 As String     Dim Member2 As String   End Structure   Sub Main()     Dim T4_1 As TEST4     Dim T4_2 As TEST4     T4_1.MembersCount = 1     T4_1.Member1 = "T4_1:Member1"     T4_1.Member2 = "T4_1:Member2"     T4_2 = T4_1     Debug.Print(T4_2.MembersCount.ToString)     Debug.Print(T4_2.Member1)     Debug.Print(T4_2.Member2)   End Sub End Module [イミディエイト ウインドウ] 1 T4_1:Member1 T4_1:Member2 >構造体の要素が文字列型 (String) やオブジェクト型 (Object) などの参照型である場合は、データへのポインタがコピーされます。 (http://msdn.microsoft.com/ja-jp/library/18ytyskd(VS.80).aspx) このMSDNライブラリの説明によると、 [イミディエイト ウインドウ] 0 T4_1:Member1 T4_1:Member2 という結果を得るというのが私の予測。 もしかしたら、MSDNライブラリの説明の舌足らず。 >構造体の要素が値型であらば値がコピーされますが、文字列型 (String) やオブジェクト型 (Object) などの参照型である場合は、データへのポインタがコピーされます。 ということでしょうか?

  • VCの構造体【否 .Net】文字列

    http://okwave.jp/qa2526132.html での質問の発展です。 構造体の中に文字列を入れたいのです。 4の倍数にする必要がある、と聞いたので typedef struct {  char a[80];  int b;  int c; } Data_t; とし、VB側で Public Type vbData  a As String * 80  b As Long  c As Long End Type としましたが、うまく受け取れません。 どうかお力添えを。