October 31, 2025, 11:52:46 AM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


FileRequest Question

Started by LarryMc, March 01, 2009, 12:24:32 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

LarryMc

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
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Ionic Wind Support Team

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.
Ionic Wind Support Team

sapero

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.

LarryMc

LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

sapero

March 02, 2009, 06:59:54 AM #4 Last Edit: March 03, 2009, 12:59:36 AM by sapero
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

sapero

There was an invalid comparision in CEnumString::Release, please update. It should be if (m_refcnt = 0).

LarryMc

LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library