LianaEnt Posted April 2, 2005 Posted April 2, 2005 Does anyone have the GetOpenFilename API code for opening custom dialog boxes (in particular with the ability to save the Views - Thumbnails, Tiles, Icons) in VB.Net, that actually works? I've found code in C++ that I don't understand, in CE.Net that doesn't translate, I've found VB6 code and Access code that works but I have not been able to translate successfully yet. MSDN doesn't seem to have any examples in VB.Net, I've searched Google, this forum, and others. Occasionally I see someone who can't get multiple file selection or some aspect of it to work, but there's never any code along with it. Please help! VB.Net!!! Thanks, Larry Quote
LianaEnt Posted April 3, 2005 Author Posted April 3, 2005 I got the dialogbox to open... But I keep getting a null reference when I try to use the OFNHookProc. Without the hook procedure, this is really no better than the standard OpenFileDialog box. I'm using for the delegate: Delegate Function OFNHookProc(ByVal hwnd As IntPtr, ByVal uMsg As Integer, ByVal wParam As Long, ByVal lParam As Long) As Integer and setting the OpenFileName hook paramter to: ofn.hook = New OFNHookProc(AddressOf OFNHookProcSub) I've tried different variations of the parameter types such as Long, etc. In every case, when the OFNHookProcSub function fires, the handle and message being fed to it are meaningless - the message is none of the standard hook messages such as WM_NOTIFY (78) or WM_INITDIALOG (272). It's integer value is 48. Again, I've seen hook examples in other languages, but nothing in VB.Net! If anyone wants to see the code to get the dialogbox to just open, let me know! Thanks, Larry Quote
LianaEnt Posted April 5, 2005 Author Posted April 5, 2005 Update - would you believe I'm "this" close? Here's all the code for the entire class that I have so far (in 2 posts)... Imports System Imports System.Text Imports Microsoft.VisualBasic Imports System.Runtime.InteropServices Public Class OpenFilename Inherits CommonDialog 'Declare a bunch of API's, hoping some will work... Declare Auto Function GetOpenFileName Lib "Comdlg32.dll" (<[in](), Out()> ByVal ofn As OpenFileName) As Boolean Declare Function GetParent Lib "user32" (ByVal hwnd As IntPtr) As IntPtr Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As IntPtr, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As String) As Long Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As IntPtr, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As IntPtr, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As IntPtr) As Long Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr, ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr Declare Function SetWindowText Lib "user32" Alias "SetWindowTextA" (ByVal hwnd As IntPtr, ByVal lpString As String) As Long Declare Auto Function SetDlgItemText Lib "user32" (ByVal hDlg As IntPtr, ByVal nIDDlgItem As Long, ByVal lpString As String) As Long 'Declare the Hook delegate so we can "hook" to it later. Delegate Function OFNHookProc(ByVal hwnd As IntPtr, ByVal msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr 'If you don't persist the hook procedure, it will be GC'd before the call gets to it. Private HookProcSub As OFNHookProc = AddressOf HookProc 'Set the initial view - Thumbnail, Icons, Details, etc. (yeah, right!) Private lngInitialView As Long 'Set all possible constants I've found so far. ''Hook constants Const WM_SETFOCUS = &H7 Const WM_INITDIALOG = &H110 Const WM_LBUTTONDOWN = &H201 Const WM_RBUTTONDOWN = &H204 Const WM_MOVE = &H3 Const WM_COMMAND = &H111 Const WM_NOTIFY As Long = &H4E& ''Flags for OpenFileName Const OFN_ALLOWMULTISELECT As Long = &H200 Const OFN_CREATEPROMPT As Long = &H2000 Const OFN_ENABLEHOOK As Long = &H20 Const OFN_ENABLETEMPLATE As Long = &H40 Const OFN_ENABLETEMPLATEHANDLE As Long = &H80 Const OFN_EXPLORER As Long = &H80000 Const OFN_EXTENSIONDIFFERENT As Long = &H400 Const OFN_FILEMUSTEXIST As Long = &H1000 Const OFN_HIDEREADONLY As Long = &H4 Const OFN_LONGNAMES As Long = &H200000 Const OFN_NOCHANGEDIR As Long = &H8 Const OFN_NODEREFERENCELINKS As Long = &H100000 Const OFN_NOLONGNAMES As Long = &H40000 Const OFN_NONETWORKBUTTON As Long = &H20000 Const OFN_NOREADONLYRETURN As Long = &H8000& Const OFN_NOTESTFILECREATE As Long = &H10000 Const OFN_NOVALIDATE As Long = &H100 Const OFN_OVERWRITEPROMPT As Long = &H2 Const OFN_PATHMUSTEXIST As Long = &H800 Const OFN_READONLY As Long = &H1 Const OFN_SHAREAWARE As Long = &H4000 Const OFN_SHAREFALLTHROUGH As Long = 2 Const OFN_SHAREWARN As Long = 0 Const OFN_SHARENOWARN As Long = 1 Const OFN_SHOWHELP As Long = &H10 Const OFS_MAXPATHNAME As Long = 260 ''ToolbarWindow32 buttons. I've actually only found the first two, and I'm guessing at the FileView button. Const TB_BTN_UPONELEVEL = 40961 Const TB_BTN_NEWFOLDER = 40962 Const TB_BTN_FILEVIEW = 40963 Const BM_SETSTATE = &HF3 ''Constants on the dialog window. Const IDOK As Long = 1 Const IDCANCEL As Long = 2 Const IDFILEOFTYPETEXT As Long = &H441 Const IDFILENAMETEXT As Long = &H442 Const IDLOOKINTEXT As Long = &H443 Const WM_USER = &H400 Const CDM_FIRST = (WM_USER + 100) Const CDM_SETCONTROLTEXT As Long = CDM_FIRST + &H4 Const CDM_HIDECONTROL As Long = (CDM_FIRST + &H5) Const EM_GETTEXTRANGE = (WM_USER + 75) Const TB_GETBUTTON = (WM_USER + 23) ''View constants. Public Const SHVIEW_ICON As Long = &H7029 Public Const SHVIEW_LIST As Long = &H702B Public Const SHVIEW_REPORT As Long = &H702C Public Const SHVIEW_THUMBNAIL As Long = &H702D Public Const SHVIEW_TILE As Long = &H702E 'Don't know what this is for, but it looked good Public Structure TBBUTTON Dim iBitmap As Integer Dim idCommand As Integer Dim fsState As Byte Dim fsStyle As Byte Dim bReserved1 As Byte Dim bReserved2 As Byte Dim dwData As Integer Dim iString As Integer End Structure 'Don't know what this is for, but it looked good Public Structure LHDR Public hwndFrom As IntPtr Public idFrom As Integer Public code As Integer End Structure 'Don't know what this is for, but it looked good Private Structure TEXTRANGE Dim cpMin As Long Dim cpMax As Long Dim lpstrText As Long End Structure (rest of code to follow) Quote
LianaEnt Posted April 5, 2005 Author Posted April 5, 2005 Update - continued Public Property SetInitialView() As Long Get Return lngInitialView End Get Set(ByVal Value As Long) lngInitialView = Value End Set End Property 'Hook procedure - uh huh... <System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name:="FullTrust")> _ Protected Overrides Function HookProc(ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr Dim hWndParent As IntPtr Dim hwndLv As IntPtr Dim hwndButton As IntPtr Static bLvSetupDone As Boolean Dim lngRetVal As Long ' Evaluates the message parameter to determine the user action. Select Case msg Case WM_INITDIALOG bLvSetupDone = False 'MessageBox.Show("The WM_INITDIALOG message was received.") Case WM_SETFOCUS 'MessageBox.Show("The WM_SETFOCUS message was received.") Case WM_LBUTTONDOWN 'MessageBox.Show("The WM_LBUTTONDOWN message was received.") Case WM_RBUTTONDOWN 'MessageBox.Show("The WM_RBUTTONDOWN message was received.") Case WM_MOVE 'MessageBox.Show("The WM_MOVE message was received.") Case WM_NOTIFY If Not bLvSetupDone Then 'MessageBox.Show("The WM_NOTIFY message was received.") hWndParent = GetParent(hWnd) SetWindowText(hWndParent, "We're ALL bozos on this bus!") 'This actually works, so I know at least I'm pointing at the main dialog form. hwndLv = FindWindowEx(hWndParent, hwndLv, "ToolbarWindow32", vbNullChar) 'This returns a handle, but not sure what to do with it. I don't know how to access the buttons in ToolbarWindow32. Dim lhdr As LHDR = CType(Marshal.PtrToStructure(lParam, GetType(LHDR)), LHDR) 'This returns something, but not sure what to do with it. lngRetVal = SendMessage(hwndLv, CDM_HIDECONTROL, TB_BTN_UPONELEVEL, 0) 'This certainly doesn't work - trying to hide the UpOneLevel button. Dim strLookIn As String = "Find it in:" & ChrW(0) lngRetVal = SendMessage(hWndParent, CDM_SETCONTROLTEXT, IDLOOKINTEXT, strLookIn) 'Attempt to change the text "Look In:" to "Find it in:" doesn't work. bLvSetupDone = True End If End Select ' Always call the base class hook procedure. Return MyBase.HookProc(hWnd, msg, wParam, lParam) End Function Public Overrides Sub Reset() End Sub 'This is what's called from the front end button click - ' Dim OpenFile As New OpenFilename ' OpenFile.ShowDialog() Protected Overrides Function RunDialog(ByVal hwndOwner As System.IntPtr) As Boolean Dim ofn As New OpenFilename With ofn .nStructSize = Marshal.SizeOf(ofn) .ptrOwner = hwndOwner .sFilter = "Picture Files" & ChrW(0) & "*.jpg" & ChrW(0) & "All files" & ChrW(0) & "*.*" & ChrW(0) .sFile = New String(New Char(256) {}) .nMaxFile = .sFile.Length .sFileTitle = New String(New Char(64) {}) .nMaxFileTitle = .sFileTitle.Length .sTitle = "Open file..." .sDefExt = "jpg" .nFlags = OFN_EXPLORER Or _ OFN_ENABLEHOOK Or _ OFN_LONGNAMES Or _ OFN_NODEREFERENCELINKS Or _ OFN_CREATEPROMPT Or _ OFN_ALLOWMULTISELECT .ofnHook = HookProcSub End With If GetOpenFileName(ofn) Then MessageBox.Show(ofn.sFile) End If End Function 'Even with persisting the hook, I still got a null reference unless I set up the OpenFileName like this: <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _ Public Class OpenFileName Public nStructSize As Integer = 0 Public ptrOwner As IntPtr = IntPtr.Zero Public hInstance As Integer = 0 <MarshalAs(UnmanagedType.LPTStr)> Public sFilter As String = Nothing <MarshalAs(UnmanagedType.LPTStr)> Public sCustomFilter As String = Nothing Public nMaxCustFilter As Integer = 0 Public nFilterIndex As Integer = 0 <MarshalAs(UnmanagedType.LPTStr)> Public sFile As String = Nothing Public nMaxFile As Integer = 0 <MarshalAs(UnmanagedType.LPTStr)> Public sFileTitle As String = Nothing Public nMaxFileTitle As Integer = 0 <MarshalAs(UnmanagedType.LPTStr)> Public sInitialDir As String = Nothing <MarshalAs(UnmanagedType.LPTStr)> Public sTitle As String = Nothing Public nFlags As Integer = 0 Public nFileOffset As Short = 0 Public nFileExt As Short = 0 Public sDefExt As String = Nothing Public ptrCustData As IntPtr = IntPtr.Zero Public ofnHook As OFNHookProc 'IntPtr = IntPtr.Zero <MarshalAs(UnmanagedType.LPTStr)> Public sTemplateName As String = Nothing Public ptrReserved As IntPtr = IntPtr.Zero Public nReserved As Integer = 0 Public nFlagsEx As Integer = 0 End Class 'OpenFileName End Class Quote
Administrators PlausiblyDamp Posted April 5, 2005 Administrators Posted April 5, 2005 Have you tried changing the 'As Long' bits in the API declarations to 'As Integer'? Under .Net Integers are now 32bits and Longs 64bits; if these declares have come from a VB6 sample then that could be a source of potential problems. Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
LianaEnt Posted April 5, 2005 Author Posted April 5, 2005 Well, that does help a little... Now at least I can "sorta" set the text in the buttons and main window, however, the text always looks like a little black square box with two white vertical lines in it. I tried null terminating the text strings. Maybe the text strings have to be put in a buffer or something. I still can't access the buttons in the ToolbarWindow32. Thanks so far PlausiblyDamp! And yes, almost everything I've found is non-VB.Net, so it's up for interpretation. :) Quote
Recommended Posts