C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[4]: Winmm.DLLでwaveOutSetVolumeを使用


(過去ログ 177 を表示中)

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■101698 / inTopicNo.1)  Winmm.DLLでwaveOutSetVolumeを使用
  
□投稿者/ LINK (1回)-(2023/04/04(Tue) 13:16:01)

分類:[.NET 全般] 

開発環境
Windows10
VB2022 + FW4.7.2
Formアプリ

お世話になります。 LINKと申します。

FW3.5で作成したアプリをFW4.7.2に変更しています。
アプリ自体はVB2022 + FW3.5の状態でコンパイルでき、起動までできました。

そこで、ターゲットフレームワークを4.7.2に変更したところ起動時にエラーが発生しました。
「マネージド デバッグ アシスタント 'PInvokeStackImbalance' 
  Message=マネージド デバッグ アシスタント 'PInvokeStackImbalance' : 'PInvoke 関数 '[アプリ名]::waveOutSetVolume' がスタックを不安定にしています。PInvoke シグネチャがアンマネージ ターゲット シグネチャに一致していないことが原因として考えられます。呼び出し規約、および PInvoke シグネチャのパラメーターがターゲットのアンマネージ シグネチャに一致していることを確認してください。'」

Declare Function waveOutSetVolume Lib "Winmm.DLL" (ByVal wDeviceID As Integer, ByVal dwVolume As Long) As Integer
と宣言しており、上記の呼び出し時にエラーが発生します。

    Private Sub NumericUpDown1_ValueChanged(sender As Object, e As EventArgs) Handles NumericUpDown1.ValueChanged

        CurrentVolLeft = CLng(Me.NumericUpDown1.Value)

        ' Increase the left sound channel setting:
        Dim x As Integer
        'CurrentVolLeft = CurrentVolLeft + &H1000&
        '' Prevent the channel setting from exceeding the maximum limit:
        'If CurrentVolLeft > &HFFFF& Then CurrentVolLeft = &HFFFF&

        Dim r As String = Convert.ToString(CurrentVolRight, 16).PadLeft(4, "0"c)
        Dim l As String = Convert.ToString(CurrentVolLeft, 16).PadLeft(4, "0"c)
        Dim BothVolumes As Long = Convert.ToUInt32(r + l, 16)

        ' Enter the following two lines as one, single line:
        x = waveOutSetVolume(0, BothVolumes) ←ここでエラー

    End Sub


調べてみたところ、FW3.5時代はエラーのチェックの有無で問題が発生しないのではとありました。
参考URL「https://social.msdn.microsoft.com/Forums/security/ja-JP/df3b7e6d-1ae0-468a-ac87-dec9755e9434/c12398pinvoke1239112289pinvokestackimbalance12364303302998312377124271239?forum=netfxgeneralja」

ちなみに、宣言部分に「Alias」を追加してみましたが、回避できませんでした。
Declare Function waveOutSetVolume Lib "Winmm.DLL" (ByVal wDeviceID As Integer, ByVal dwVolume As Long) As Integer
↓
Declare Function waveoutSetVolume Lib "Winmm.DLL" Alias "waveOutSetVolume" (ByVal wDeviceID As Integer, ByVal dwVolume As Long) As Integer


回避方法をご教示いただければ幸いです。


引用返信 編集キー/
■101699 / inTopicNo.2)  Re[1]: Winmm.DLLでwaveOutSetVolumeを使用
□投稿者/ Hongliang (1286回)-(2023/04/04(Tue) 14:04:42)
https://learn.microsoft.com/ja-jp/windows/win32/api/mmeapi/nf-mmeapi-waveoutsetvolume
第1引数hwoはHWAVEOUT、ポインタ型をtypedefしたものなので、VBですとIntPtrになります。
第2引数dwVolumeはDWORD、32ビット整数ですので、VBですとIntegerになります。
引用返信 編集キー/
■101700 / inTopicNo.3)  Re[2]: Winmm.DLLでwaveOutSetVolumeを使用
□投稿者/ LINK (3回)-(2023/04/04(Tue) 15:01:29)
Hongliang さん、確認ありがとうございます。

■No101699 (Hongliang さん) に返信
> https://learn.microsoft.com/ja-jp/windows/win32/api/mmeapi/nf-mmeapi-waveoutsetvolume
> 第1引数hwoはHWAVEOUT、ポインタ型をtypedefしたものなので、VBですとIntPtrになります。
> 第2引数dwVolumeはDWORD、32ビット整数ですので、VBですとIntegerになります。
→承知しました。

宣言を
Declare Auto Function waveOutSetVolume Lib "Winmm.DLL" (ByVal wDeviceID As IntPtr, ByVal dwVolume As Integer) As Integer

呼び出しを
        'Dim BothVolumes As Long = Convert.ToUInt32(r + l, 16)
        Dim BothVolumes As Integer = Convert.ToUInt32(r + l, 16)

        ' Enter the following two lines as one, single line:
        x = waveOutSetVolume(IntPtr.Zero, BothVolumes)
と、しました。

エラーが発生せずに起動が確認できました。
ちなみに下記のサイトでは第2引数を「UInteger」で指定していますが、何か違いがあるのでしょうか
参考URL「https://www.pinvoke.net/default.aspx/winmm/waveOutSetVolume.html」

Hongliang さん、対応ありがとうございました。
解決済みにしておきます。


解決済み
引用返信 編集キー/
■101701 / inTopicNo.4)  Re[3]: Winmm.DLLでwaveOutSetVolumeを使用
□投稿者/ 魔界の仮面弁士 (3614回)-(2023/04/04(Tue) 15:16:51)
No101700 (LINK さん) に返信
> ちなみに下記のサイトでは第2引数を「UInteger」で指定していますが、何か違いがあるのでしょうか
> 参考URL「https://www.pinvoke.net/default.aspx/winmm/waveOutSetVolume.html

DWORD は「符号なし 32bit 整数型」なので、
厳密には UInteger や UInt32 型が正しいです。

とはいえ API としては、メモリ配置さえ同一であれば
構わないので、「符号付き 32bit 整数型」であるところの
「Integer や Int32 型」にしても問題なく呼び出せます。



&H00000000〜&H7FFFFFFF の範囲のバイナリ値は、Integer でも UInteger でも、
共に 0 〜 2,147,483,647 を示す同一の数値として扱われます。

&H80000000〜&HFFFFFFFF の範囲のバイナリ値は、
UInteger だと 2147483648 〜 4,294,967,295 という範囲を示し、
Integer だと -2,147,483,648 〜 -1 という範囲を意味します。


今回の waveOutSetVolume の場合、その 32bit のうち、
下位 16bit 部が左チャンネルの音量設定、
上位 16bit 部が右チャンネルの音量設定を意味します。

それぞれの 16bit 値のうち、
0000 だと無音(ボリューム 0%)
FFFF だと最大(ボリューム 100%) です。
解決済み
引用返信 編集キー/
■101702 / inTopicNo.5)  Re[4]: Winmm.DLLでwaveOutSetVolumeを使用
□投稿者/ LINK (4回)-(2023/04/04(Tue) 16:31:24)
No101701 (魔界の仮面弁士 さん) に返信

魔界の仮面弁士 さん参考情報ありがとうございます。
> 厳密には UInteger や UInt32 型が正しいです。
とのことですので、UIntegerに修正して対応することにします。
ありがとうございました。


解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -