I call Filerequest (save as) with a single file ext filter.
The file request shows subdirectories and show files with the filter extension I passed.
However, when I type the 1st letter of the filename I want to use, if there are other files with the same 1st letter but different ext then they appear in the combo box dropdown.
If I select one of those in the combobox then the file name returned has it's original extension with the desired extension appended to it (like test.txt.html)
Is there a way to disable the combo dropdown so other filenames with different extensions from showing?
Larry
Not that I am aware of, although you might be able to do it with a hook. Tried a few other programs, like paint and wordpad, and the behavior seems inherent to the common file dialog, for example in Paint I typed the letter c and it tried to let me open the C:\ drive as an image.
Paul.
It is possible to filter out the autocommplete strings. I thik you need to implement IEnumString interface and hook up the IAutoComplete::Init method address in the IAutoComplete jumptable (a single integer replacement to your function address). I use this hook technique in several projects, but newer tried it with autocomplete.
ok, thanks
Larry
Thsi is the simplest (?) way to suggest files with single extension:
$include "windowssdk.inc"
$include "shldisp.inc"
' allow only .eba extension
$define SZ_EXTENSION L".eba"
$define SZ_INITIAL_FILENAME "hello.eba"
' example code
InitAutocompleteHook()
MessageBox 0, FileRequest("autocomplete hook test", NULL, TRUE, "Ebasic fles (*.eba)|*.eba||", "eba", OFN_EXPLORER, GetStartPath()), ""
DestroyAutocompleteHook()
end
/****************************************************
* autocomplete hook 1.0
****************************************************/
UINT g_pfnInit
declare FNINITDEF(IAutoComplete this, HWND hwndEdit, IUnknown punkACL, LPCOLESTR pwszRegKeyPath, LPCOLESTR pwszQuickComplete),HRESULT
union IAC
IAutoComplete pautoc
pointer pac
endunion
class CEnumString
declare CEnumString()
declare virtual QueryInterface(pointer riid,pointer ppvObject),HRESULT
declare virtual AddRef(),ULONG
declare virtual Release(),ULONG
declare virtual _Next(ULONG celt,pointer rgelt,pointer pceltFetched),HRESULT
declare virtual Skip(ULONG celt),HRESULT
declare virtual Reset(),HRESULT
declare virtual Clone(pointer ppenum),HRESULT
int m_refcnt
' IUnknown m_punkACL
IEnumString m_enum ' the original IEnumString
HWND m_hwndEdit
LPCOLESTR m_pwszRegKeyPath
LPCOLESTR m_pwszQuickComplete
endclass
sub InitAutocompleteHook()
IAC iac
CoInitialize(0)
if (g_pfnInit = 0)
if (CoCreateInstance(_CLSID_AutoComplete, NULL, CLSCTX_INPROC_SERVER, _IID_IAutoComplete, &iac.pautoc) = 0)
' install hook at IAutoComplete::Init
pointer vtable = iac.*<pointer>pac
pointer pInit = &*<int>vtable[3]
' save the original IAutoComplete::Init pointer
g_pfnInit = *<UINT>pInit
' and replace it
int pfnInit = &IAutoCompleteInit
WriteProcessMemory(GetCurrentProcess(), pInit, &pfnInit, 4, NULL)
iac.pautoc->Release()
endif
endif
endsub
sub DestroyAutocompleteHook()
IAC iac
if (g_pfnInit)
if (CoCreateInstance(_CLSID_AutoComplete, NULL, CLSCTX_INPROC_SERVER, _IID_IAutoComplete, &iac.pautoc) = 0)
pointer vtable = iac.*<pointer>pac
pointer pInit = &*<int>vtable[3]
' restore the original method
WriteProcessMemory(GetCurrentProcess(), pInit, &g_pfnInit, 4, NULL)
' release the interfae
iac.pautoc->Release()
' cleanup
g_pfnInit = 0
endif
endif
CoUninitialize()
endsub
sub IAutoCompleteInit(IAutoComplete this, HWND hwndEdit, IUnknown punkACL, LPCOLESTR pwszRegKeyPath, LPCOLESTR pwszQuickComplete),HRESULT
' this
' hwndEdit
' punkACL: IEnumString interface
pointer pcac = new(CEnumString, 1)
settype pcac, CEnumString
if (punkACL->QueryInterface(_IID_IEnumString, &*pcac.m_enum))
delete pcac
return E_FAIL
endif
' punkACL->QueryInterface(_IID_IUnknown, &*pcac.m_punkACL)
*pcac.m_hwndEdit = hwndEdit
*pcac.m_pwszRegKeyPath = pwszRegKeyPath
*pcac.m_pwszQuickComplete = pwszQuickComplete
' use hwndEdit to set initial file name
SetWindowText(hwndEdit, SZ_INITIAL_FILENAME)
' call the original method, but with our EnumString class
return !<FNINITDEF>g_pfnInit(this, hwndEdit, pcac, pwszRegKeyPath, pwszQuickComplete)
endsub
sub CEnumString::CEnumString()
m_refcnt = 1
endsub
sub CEnumString::QueryInterface(pointer riid,pointer ppvObject),HRESULT
if (IsEqualGUID(riid, _IID_IUnknown) or IsEqualGUID(riid, _IID_IEnumString))
*<pointer>ppvObject = this
AddRef()
return S_OK
endif
return E_NOINTERFACE
endsub
sub CEnumString::AddRef(),ULONG
m_refcnt++
return m_refcnt
endsub
sub CEnumString::Release(),ULONG
m_refcnt--
if (m_refcnt = 0)
m_enum->Release()
' m_punkACL->Release()
delete this
return 0
endif
return m_refcnt
endsub
sub CEnumString::_Next(ULONG celt,pointer rgelt,pointer pceltFetched),HRESULT
while (1)
' force single string
HRESULT hr = m_enum->_Next(1, rgelt, pceltFetched)
if (hr)
return hr
endif
' get the returned string
pointer pwstr = *<pointer>rgelt
' find and compare the extension. If is invalid, try with next string
pointer pExt = wcsrchr(pwstr, asc("."))
if (pExt)
if (wcsicmp(pExt, SZ_EXTENSION) = 0)
return S_OK
endif
endif
CoTaskMemFree(pwstr)
endwhile
' failure
return S_FALSE
endsub
sub CEnumString::Skip(ULONG celt),HRESULT
return m_enum->Skip(celt)
endsub
sub CEnumString::Reset(),HRESULT
return m_enum->Reset()
endsub
sub CEnumString::Clone(pointer ppenum),HRESULT
pointer pcac = new(CEnumString, 1)
settype pcac, CEnumString
m_enum->QueryInterface(_IID_IEnumString, &*pcac.m_enum)
' m_punkACL->QueryInterface(_IID_IUnknown, &*pcac.m_punkACL)
*pcac.m_hwndEdit = m_hwndEdit
*pcac.m_pwszRegKeyPath = m_pwszRegKeyPath
*pcac.m_pwszQuickComplete = m_pwszQuickComplete
*<pointer>ppenum = pcac
return S_OK
endsub
There was an invalid comparision in CEnumString::Release, please update. It should be if (m_refcnt = 0).
Thanks Sapero!
Larry