Imports System.Runtime.InteropServices
Module Module1
Sub Main()
'' OPENFILENAME構造体を用意
Dim ofn As New Win32.OPENFILENAME()
ofn.lStructSize = Marshal.SizeOf(ofn)
ofn.lpstrFilter = "Text files" & ChrW(0) & "*.txt" & ChrW(0)
ofn.lpstrFile = New String(New Char(256) {})
ofn.nMaxFile = ofn.lpstrFile.Length
ofn.lpstrFileTitle = New String(New Char(64) {})
ofn.nMaxFileTitle = ofn.lpstrFileTitle.Length
ofn.lpstrInitialDir = "C:"
ofn.lpstrTitle = "名前を付けて保存 - 保存先ファイルを指定して下さい。"
ofn.lpstrdefext = "txt"
ofn.flags = &H80826
ofn.lpfnHook = AddressOf Win32.WinHookProc
Dim point As New Win32.POINT
point.x = 500 '' ダイアログの左上X座標
point.y = 100 '' ダイアログの左上Y座標
Dim lpPoint As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(point))
Try
Marshal.StructureToPtr(point, lpPoint, True)
ofn.lCustData = lpPoint
If Win32.GetSaveFileName(ofn) Then
Console.WriteLine("Selected File with Full-Path:[{0}]", ofn.lpstrFile)
Else
Console.WriteLine("Selected Cancel.")
End If
Finally
Marshal.FreeHGlobal(lpPoint)
End Try
#If DEBUG Then
Console.WriteLine("Push Key to End Debug...")
Console.ReadKey()
#End If
End Sub
End Module
'' フックプロシージャのデリゲート宣言(関数ポインタ)
Public Delegate Function HookProc _
(ByVal p_hWnd As Integer, ByVal p_uiMsg As Integer, _
ByVal wParam As Integer, ByVal lParam As Integer) As Integer
Public Class Win32
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
Public Class OPENFILENAME
Public lStructSize As Integer = 0
Public hwndOwner As IntPtr = IntPtr.Zero
Public hInstance As IntPtr = IntPtr.Zero
Public lpstrFilter As String = Nothing
Public lpstrCustomFilter As String = Nothing
Public nMaxCustomFilter As Integer = 0
Public nFilterIndex As Integer = 0
Public lpstrFile As String = Nothing
Public nMaxFile As Integer = 0
Public lpstrFileTitle As String = Nothing
Public nMaxFileTitle As Integer = 0
Public lpstrInitialDir As String = Nothing
Public lpstrTitle As String = Nothing
Public flags As Integer = 0
Public nFileOffset As Short = 0
Public nFileExtension As Short = 0
Public lpstrdefext As String = Nothing
Public lCustData As IntPtr = IntPtr.Zero
Public lpfnHook As HookProc = Nothing
Public lpTemplateName As String = Nothing
'' 注:以下のメンバは最新のOPENFILENAME構造体のメンバとなります。
Public pvReserved As IntPtr = IntPtr.Zero
Public dwReserved As Integer = 0
Public FlagsEx As Integer = 0
End Class
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
Public Class NMHDR
Public hWnd As IntPtr = IntPtr.Zero
Public idFrom As Integer = 0
Public code As Integer = 0
End Class
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
Public Class OFNOTIFY
Public hdr As NMHDR
Public lpOFN As IntPtr = IntPtr.Zero
Public pszFile As IntPtr = IntPtr.Zero
End Class
<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
Public Class POINT
Public x As Long
Public y As Long
End Class
Declare Auto Function GetSaveFileName Lib "Comdlg32.dll" _
(<[In](), Out()> ByVal ofn As OPENFILENAME) As Boolean
Declare Function SetWindowPos Lib "user32" _
(ByVal hWnd As Integer, ByVal hWndAfter As Integer, _
ByVal X As Integer, ByVal Y As Integer, _
ByVal cx As Integer, ByVal cy As Integer, ByVal uFlags As Integer) As Integer
Declare Function GetParent Lib "user32" (ByVal hWnd As Integer) As Integer
Public Shared Function WinHookProc(ByVal hWnd As Integer, ByVal message As Integer, _
ByVal wParam As Integer, ByVal lParam As Integer) As Integer
If message = &H4E Then '' &H4E = WM_NOTIFY
Dim lpNmhdr As NMHDR
'' WM_NOTIFYの際、lParamは、NMHDR構造体へのポインタ or NMHDR構造体を先頭に持つ構造体へのポインタ
lpNmhdr = Marshal.PtrToStructure(New IntPtr(lParam), GetType(NMHDR))
'' NMHDR.codeを見て、通知内容を確認。(CDN_INITDONEかを確認)
If lpNmhdr.code = (-601) Then
'' CDN_INITDONE時、lParamの正体はOFNOTIFY構造体
Dim lpOfn As OFNOTIFY
lpOfn = Marshal.PtrToStructure(New IntPtr(lParam), GetType(OFNOTIFY))
'' OFNOTIFY構造体には、OPENFILENAME構造体へのポインタが含まれる。
'' ポインタが示すOPENFILENAME構造体は呼び出し時に渡したOPENFILENAME構造体
Dim lpOpenFn As OPENFILENAME
lpOpenFn = Marshal.PtrToStructure(lpOfn.lpOFN, GetType(OPENFILENAME))
'' OPENFILENAME構造体に設定したカスタムデータ(今回はPOINT構造体)
Dim lpPoint As POINT
lpPoint = Marshal.PtrToStructure(lpOpenFn.lCustData, GetType(POINT))
If lpPoint IsNot Nothing Then
'' 当プロシージャに渡っているhWndはダイアログのハンドルではなく、子コントロールのハンドルなので
'' 子コントロールの親(つまりダイアログ)のハンドルをWin32API:GetParentで取得し
'' Win32API:SetWindowsPosで位置設定を行う
Win32.SetWindowPos(Win32.GetParent(hWnd), Nothing, lpPoint.x, lpPoint.y, 0, 0, &H1)
End If
End If
End If
Return 0
End Function
End Class
|