タイトル | : Re^2: unlha32のコールバックを受け取った時の構造体がおかしい? |
記事No | : 10437 |
投稿日 | : 2011/02/06(Sun) 07:57 |
投稿者 | : A.K |
魔界の仮面弁士様
ご返答ありがとうございます。 指摘された部分を順番に試してみました。
> 現行バージョンでは、Function も Structure も CharSet.Unicode の方が > 良い気がしますが、それぞれの CharSet 指定は一致していますか? 全てAnsiで定義しており、定義は一致しています。 が、一応全てUnicodeに直しました。
> exinfo の 4 バイト前の位置の値が dwStructSize になっていたのでしょうか? これは確認していません。(その前に直ったので… dwStructSizeをコメントアウトせずに実行し、取得してみても、値はデタラメになっていたのは確認しました。
> クラスでは無いので、New は不要な気も。 Newがないと警告が出るので入れていました。現在は消しましたが、どちらにしても動作には影響ないようです(w
> Marshal.SizeOf の結果は、何が返されていますか? ○unlha32を使って解凍処理を行うクラス Unicode 4218 Ansi 2146 ○unlha32のコールバックを受け取るFormクラス Unicode 4214 Ansi 2142 でした。(Integerを削ったら32ビット減るはずが… 不思議です)
> WndProc で LParam から受ける代わりに、ARCHIVERPROC のデリゲートを渡して > 構造体を直接受け取った場合も、同じ結果になりますか? Form規定のコールバック Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message) の代わりに、マニュアルに載っていたコールバック関数 LRESULT CALLBACK WindowProc( HWND _hwnd, UINT _uMsg, // wm_arcextract WPARAM _wParam, LPARAM _lParam で受取るようにしたところ、普通に正常な値が取れてしまいました。 どういう理屈があるのかよく分かりませんが、Formを継承したクラス以外でコールバックを受取れる方が便利なので、こちらを使うことにします。 ただ、マニュアルには「Returnに0を返すと継続、それ以外は中断」とあったものが、 0を返すと中断で、それ以外が継続になっているようで面食らいましたが… (Dllのバージョンが違うのでしょうか? 書き忘れていましたがUnlha32.Dllのバージョンは2.67です)
ともあれ、色々とヒントをいただき、ありがとうございました。 本当に助かりました。
お目汚しですが、今回のソースを挙げてみます。
'モジュール部 <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode, Pack:=1)> _ Public Structure EXTRACTINGINFO Public dwFileSize As Integer Public dwWriteSize As Integer <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=513)> _ Public szSourceFileName As String <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=3)> _ Public dummy1 As String <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=513)> _ Public szDestFileName As String <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=3)> _ Public dummy As String End Structure
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode, Pack:=1)> _ Public Structure EXTRACTINGINFO64 Public dwStructSize As Integer Public exinfo As EXTRACTINGINFO Public llFileSize As Long Public llCompressedSize As Long Public llWriteSize As Long Public dwAttributes As Integer Public dwCRC As Integer Public uOSType As Integer Public wRatio As Short Public ftCreateTime As Long Public ftAccessTime As Long Public ftWriteTime As Long <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=8)> _ Public szMode As String <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=513)> _ Public szSourceFileName As String <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=3)> _ Public dummy1 As String <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=513)> _ Public szDestFileName As String <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=3)> _ Public dummy As String End Structure
Public Const WM_ARCEXTRACT As String = "wm_arcextract" 'ウィンドウメッセージ用定数 Friend wm_arcextractMsg As Integer = 0 'ウィンドウメッセージ用変数
'Unlha使用を使うクラス
Private Delegate Function WindowProcDelegate(ByVal _hwnd As IntPtr, ByVal _uMsg As Integer, _ ByVal _wParam As IntPtr, ByVal _lParam As IntPtr) As Integer
<DllImport("unlha32", _ EntryPoint:="UnlhaSetOwnerWindowEx64", _ ExactSpelling:=True)> _ Private Shared Function UnlhaSetOwnerWindowEx64(ByVal _hwnd As IntPtr, _ ByVal _lpArcProc As WindowProcDelegate, _ ByVal _dwStructSize As Integer) As Boolean End Function
<DllImport("unlha32", _ EntryPoint:="UnlhaKillOwnerWindowEx64", _ ExactSpelling:=True)> _ Private Shared Function UnlhaKillOwnerWindowEx64(ByVal _hwnd As IntPtr) As Boolean End Function
Private _hwnd As IntPtr
'コード部
Public Sub New(ByVal hwnd As IntPtr)
_hwnd = hwnd
'コールバック取得準備 If wm_arcextractMsg = 0 Then wm_arcextractMsg = RegisterWindowMessage(WM_ARCEXTRACT) End If
'ウィンドウメッセージの設定 Dim struct As EXTRACTINGINFO64 Dim winProcDelegate As New WindowProcDelegate(AddressOf WndProc)
If Not UnlhaSetOwnerWindowEx64(hwnd, winProcDelegate, Marshal.SizeOf(struct)) Then 'エラーにする End If
End Sub
Protected Function WndProc(ByVal _hwnd As IntPtr, ByVal _uMsg As Integer, _ ByVal _wParam As IntPtr, ByVal _lParam As IntPtr) As Integer
If _uMsg = wm_arcextractMsg AndAlso _wParam.ToInt64 = 1 Then 'mode=1:解凍処理 Dim extractingInfo As EXTRACTINGINFO64 Dim typeHandle As System.RuntimeTypeHandle = System.Type.GetTypeHandle(extractingInfo) Dim extractingInfoType As Type = Type.GetTypeFromHandle(typeHandle)
'構造体の取得 extractingInfo = DirectCast(Marshal.PtrToStructure(_lParam, extractingInfoType), EXTRACTINGINFO64)
Debug.Print("SourceFileName : " & extractingInfo.szSourceFileName) Debug.Print("DestFileName : " & extractingInfo.szDestFileName)
Debug.Print("FileSize : " & extractingInfo.llFileSize.ToString) Debug.Print("WriteSize : " & extractingInfo.llWriteSize.ToString)
End If
'処理の継続 Return -1
End Function
' IDisposable Protected Overridable Sub Dispose(ByVal disposing As Boolean) If Not Me.disposedValue Then If disposing Then ' TODO: 明示的に呼び出されたときにマネージ リソースを解放します End If
' TODO: 共有のアンマネージ リソースを解放します
'ウィンドウハンドルの解放 UnlhaKillOwnerWindowEx64(IntPtr.Zero)
End If Me.disposedValue = True End Sub
|