tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板)
VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板)
[ツリー表示へ]  [ワード検索]  [Home]

タイトル Re^2: unlha32のコールバックを受け取った時の構造体がおかしい?
投稿日: 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

- 関連一覧ツリー をクリックするとツリー全体を一括表示します)

古いスレッドにレスはつけられません。