|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Visual Basic
Hook Routines GetOpenFileName: Set an Open/Save Dialog's Initial Listview View |
||
Posted: | Monday July 26, 2004 | |
Updated: | Monday December 26, 2011 | |
Applies to: | VB5, VB6 | |
Developed with: | VB6, Windows XP | |
OS restrictions: | None | |
Author: | Brad Martinez, VBnet - Randy Birch | |
Related: | GetOpenFileName: File Open/Save Common Dialog API - Overview GetSaveFileName: File Save Common Dialog Basics GetOpenFileName: File Open Common Dialog Basics GetOpenFileName: Advanced Dialog Centering using a Callback GetOpenFileName: Customize File Open/Save Common Dialog Controls |
|
Prerequisites |
None. |
|
Using
a hook it is possible to send a message to the listview within an Open or
Save dialog created using the Common Dialog APIs to set the initial
display state of the listview control to that other than the default
"list" view. This demo contains the code required to do this, including
code to determine the operating system through which the proper
OPENFILENAME structure is used for a given OS version, providing users of
Windows 2000 or later to view the dialog with the Places Bar presented.
The code also shows setting the OFN_EX_NOPLACESBAR flag to suppress the
Places Bar display. On pre-Win2000 systems, the No Places Bar checkbox is
disabled.
The initial call in the Command1_Click routine calls the SetOSVersion routine to assign the proper OPENFILENAME structure length to a work variable used to complete the ofn.nStructSize member. The illustrations cycling below shows the effect of the selection made in the demo. Although the demo does not show calling the Save dialog, the methodology is identical.
|
BAS Module Code |
Place the following code into the general declarations area of a bas module: |
|
Option Explicit '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved. ' Some pages may also contain other copyrights by the author. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Distribution: You can freely use this code in your own ' applications, but you may not reproduce ' or publish this code on any web site, ' online service, or distribute as source ' on any media without express permission. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'var for exposed property Private m_lvInitialView As Long 'windows version constants Private Const VER_PLATFORM_WIN32_NT As Long = 2 Private Const OSV_LENGTH As Long = 76 Private Const OSVEX_LENGTH As Long = 88 Public OSV_VERSION_LENGTH As Long 'our const to hold appropriate OSV length Private Type OSVERSIONINFO OSVSize As Long dwVerMajor As Long dwVerMinor As Long dwBuildNumber As Long PlatformID As Long szCSDVersion As String * 128 End Type 'windows messages & notifications etc Private Const WM_COMMAND = &H111 Public Const WM_NOTIFY As Long = &H4E& Public Const WM_INITDIALOG As Long = &H110 Public Const CDN_FIRST As Long = -601 Public Const CDN_INITDONE As Long = (CDN_FIRST - &H0&) Public Const MAX_PATH As Long = 260 'openfilename constants Public Const OFN_ENABLEHOOK As Long = &H20 Public Const OFN_EXPLORER As Long = &H80000 Public Const OFN_ENABLESIZING As Long = &H800000 Public Const OFN_EX_NOPLACESBAR As Long = &H1 'constants for listview view state 'provided by Brad Martinez 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 'this is the version 5+ definition of 'the OPENFILENAME structure containing 'three additional members providing 'additional options on Windows 2000 'or later. The SetOSVersion routine 'will assign either OSV_LENGTH (76) 'or OSVEX_LENGTH (88) to the OSV_VERSION_LENGTH 'variable declared above. This variable, rather 'than Len(OFN) is used to assign the required 'value to the OPENFILENAME structure's nStructSize 'member which tells the OS if extended features '- primarily the Places Bar - are supported. Public Type OPENFILENAME nStructSize As Long hwndOwner As Long hInstance As Long sFilter As String sCustomFilter As String nMaxCustFilter As Long nFilterIndex As Long sFile As String nMaxFile As Long sFileTitle As String nMaxTitle As Long sInitialDir As String sDialogTitle As String flags As Long nFileOffset As Integer nFileExtension As Integer sDefFileExt As String nCustData As Long fnHook As Long sTemplateName As String pvReserved As Long dwReserved As Long flagsEx As Long End Type Public OFN As OPENFILENAME 'defined As Any to support either the 'OSVERSIONINFO or OSVERSIONINFOEX structure Private Declare Function GetVersionEx Lib "kernel32" _ Alias "GetVersionExA" _ (lpVersionInformation As Any) As Long Public Declare Function GetOpenFileName Lib "comdlg32.dll" _ Alias "GetOpenFileNameA" _ (pOpenfilename As OPENFILENAME) As Long Private Declare Function FindWindowEx Lib "user32" _ Alias "FindWindowExA" _ (ByVal hWndParent As Long, _ ByVal hWndChildAfter As Long, _ ByVal lpClassName As String, _ ByVal lpWindowName As String) As Long Private Declare Function GetParent Lib "user32" _ (ByVal hwnd As Long) As Long Private Declare Function SendMessage Lib "user32" _ Alias "SendMessageA" _ (ByVal hwnd As Long, _ ByVal wMsg As Long, _ ByVal wParam As Long, _ lParam As Any) As Long Public Function FARPROC(pfn As Long) As Long 'A dummy procedure that receives and returns 'the return value of the AddressOf operator. 'Obtain and set the address of the callback 'This workaround is needed as you can't assign 'AddressOf directly to a member of a user- 'defined type, but you can assign it to another 'long and use that (as returned here) FARPROC = pfn End Function Public Function IsWin2000Plus() As Boolean 'returns True if running Windows 2000 or later Dim osv As OSVERSIONINFO osv.OSVSize = Len(osv) If GetVersionEx(osv) = 1 Then IsWin2000Plus = (osv.PlatformID = VER_PLATFORM_WIN32_NT) And _ (osv.dwVerMajor = 5 And osv.dwVerMinor >= 0) End If End Function Public Property Let OFN_SetInitialView(ByVal initview As Long) m_lvInitialView = initview End Property Public Function OFNHookProc(ByVal hwnd As Long, _ ByVal uMsg As Long, _ ByVal wParam As Long, _ ByVal lParam As Long) As Long Dim hWndParent As Long Dim hwndLv As Long Static bLvSetupDone As Boolean Select Case uMsg Case WM_INITDIALOG 'Initdialog is set when the dialog 'has been created and is ready to 'be displayed, so set our flag 'to prevent re-executing the code 'in the wm_notify message. This is 'required as the dialog receives a 'number of WM_NOTIFY messages throughout 'the life of the dialog. If this is not 'done, and the user chooses a different 'view, on the next WM_NOTIFY message 'the listview would be reset to the 'initial view, probably ticking off 'the user. The variable is declared 'static to preserve values between 'calls; it will be automatically reset 'on subsequent showing of the dialog. bLvSetupDone = False 'other WM_INITDIALOG code here, such 'as caption or button changing, or 'centering the dialog. Case WM_NOTIFY If bLvSetupDone = False Then 'hwnd is the handle to the dialog 'hwndParent is the handle to the common control 'hwndLv is the handle to the listview itself hWndParent = GetParent(hwnd) hwndLv = FindWindowEx(hWndParent, 0, "SHELLDLL_DefView", vbNullChar) If hwndLv > 0 Then Call SendMessage(hwndLv, WM_COMMAND, ByVal m_lvInitialView, ByVal 0&) 'since we found the lv hwnd, assume the 'command was received and set the flag 'to prevent recalling this routine bLvSetupDone = True End If 'hwndLv End If 'bLvSetupDone Case Else End Select End Function Public Sub SetOSVersion() Select Case IsWin2000Plus() Case True OSV_VERSION_LENGTH = OSVEX_LENGTH '5.0+ structure size Case Else OSV_VERSION_LENGTH = OSV_LENGTH 'pre-5.0 structure size End Select End Sub |
Form Code |
To form containing a list box, check box and command button with the default names add the following code: |
|
Option Explicit Private Sub Form_Load() Command1.Caption = "Get File Open" With Check1 .Caption = "No Places Bar" .Enabled = IsWin2000Plus() End With With List1 .AddItem "Thumbnails" .ItemData(.NewIndex) = SHVIEW_THUMBNAIL .AddItem "Tiles" .ItemData(.NewIndex) = SHVIEW_TILE .AddItem "Icon (Large)" .ItemData(.NewIndex) = SHVIEW_ICON .AddItem "List (default view)" .ItemData(.NewIndex) = SHVIEW_LIST .AddItem "Details (Report view)" .ItemData(.NewIndex) = SHVIEW_REPORT .ListIndex = 3 'list view, the default view End With End Sub Private Sub Command1_Click() Dim sFilters As String Dim OFN As OPENFILENAME If OSV_VERSION_LENGTH = 0 Then SetOSVersion 'filters for the dialog sFilters = "All Files" & vbNullChar & "*.*" & vbNullChar & vbNullChar 'populate the structure With OFN .nStructSize = OSV_VERSION_LENGTH .hwndOwner = Form1.hwnd .sFilter = sFilters .nFilterIndex = 0 .sFile = vbNullChar & Space$(MAX_PATH) & vbNullChar & vbNullChar .nMaxFile = Len(.sFile) .sDefFileExt = "*.*" & vbNullChar & vbNullChar .sFileTitle = vbNullChar & Space$(512) & vbNullChar & vbNullChar .nMaxTitle = Len(OFN.sFileTitle) .sInitialDir = "D:\Graphics\vbgfx\icons\Downloads 5" & vbNullChar & vbNullChar .sDialogTitle = "VBnet GetOpenFileName Demo" .flags = OFN_EXPLORER Or OFN_ENABLEHOOK Or OFN_ENABLESIZING If Check1.Value = vbChecked Then .flagsEx = OFN_EX_NOPLACESBAR End If .fnHook = FARPROC(AddressOf OFNHookProc) End With 'call the API.(See the other demos for 'how to retrieve selected file(s) info 'from the dialog.) Call GetOpenFileName(OFN) End Sub Private Sub List1_Click() With List1 If .ListIndex > -1 Then OFN_SetInitialView = .ItemData(.ListIndex) End If End With End Sub |
Comments |
For a discussion on modifying the OPENFILENAME structure in order to display the new Windows 2000 or Windows XP-style Open and Save dialogs, please see the comments section in the page GetOpenFileName: File Dialog Centering using a Callback. |
|
|
|
|||||
|
|||||
|
|||||
Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved. |