Blitzsys File Requester

Blitz3D Forums/Blitz3D Programming/Blitzsys File Requester

JoeGr(Posted 2005) [#1]
I've been using Rob Hutchinson's blitzsys dll with an app I'm making to bring up a Windows file requester. It works very well, but does anyone know how I might:

1) Make the file requester appear initially at coordinates other than the very top left corner of the screen (which looks a bit messy)?

2) Ensure that the file requester maintains the focus until the user either chooses a file or closes the window?

I suspect that if I could just get the relevant window handle I could figure out how to do these things using WinAPI commands. Any suggestions?

Thanks


John Blackledge(Posted 2005) [#2]
No, I can't do it either, and it is so annoying!

Yes please, can anyone help?


jfk EO-11110(Posted 2005) [#3]
I guess the filerequest window has a HWND handle. If it has one, you only have to find it and then position the window using the Api Calls. Although not sure how to find its HWND. GetActiveWindow may work, but probably it isn't very save.


solitaire(Posted 2005) [#4]
After opening the filerequester the programm stopps,
so it isn't possible to get the handle.
But if you able to use API, it is a better way to use
the API to open a filerequester.


John Blackledge(Posted 2005) [#5]
"it is a better way to use the API to open a filerequester. "
Any clues how to do this?


JoeGr(Posted 2005) [#6]
Solitaire is quite right - the program is 'paused' until a file is selected or the file requester window is closed, and this seems to be the main obstacle to getting the required window handle. As for using WinAPI commands directly, I can deal with the easy ones but the GetOpenFileName function requires "an OPENFILENAME structure that contains information used to initialize the dialog box." (MSDN) which I'm pretty sure I don't have enough experience to create. Might it possible to modify the blitzsys.bb include or the dll itself slightly so that coordinates are specified for the window?

I did find this:

http://www.blitzbasic.com/codearcs/codearcs.php?code=916

but I haven't tested it yet. To be honest I would rather use blitzsys if at all possible as its simple and it works. I just wish it could do these two extra little things.


John Blackledge(Posted 2005) [#7]
I've given it a quick try.
It's fine but no different from the BlitzSys function.

It's still not possible to get a window handle, and it _is_ still possible to click the parent window to be on top of the Dialog - which to me is the real problem.


jfk EO-11110(Posted 2005) [#8]
did you try GetActiveWindow right after opening the box? Using WinwowPos you should be able to force it alwaysontop. Of course, only when the req box is running parallely with the blitz app and won't pause it.


BlackD(Posted 2005) [#9]
The only way to do what you're describing is to write a DLL which as such launches a different process which will handle the file request, positioning, and focus of the window, so you can simply program your software to wait for the returned file from the DLL.

If you don't know C++ then you're in trouble. :\

+BlackD


John Blackledge(Posted 2005) [#10]
jfk, the call is effectively a one-liner:
pseudo: 'result = Fileselect()'
so there is no chance (in Blitz) of interaction.
BlackD is right.

But we're open to any other ideas.


JoeGr(Posted 2005) [#11]
I think I might have found a way round. It may be impossible to get the file requester's window handle, but its possible to disable the main application window immediately before calling the requester with

AppHWND=SystemProperty("AppHWND")
api_EnableWindow(AppHWND,False)

which as far as I can tell amounts to the same thing as forcing the file requester to be on top. There is a small problem though. I expected to be able to re-enable the main window with

api_EnableWindow(AppHWND,True)

but strangely, using this code seems to stop the window being disabled in the first place.

EDIT: You can still click on the application's taskbar entry to bring it to the front, so this isn't quite perfect.


JoeGr(Posted 2005) [#12]
Regarding what I said there about
api_EnableWindow(AppHWND,True)
screwing things up, it does cause me problems when I use it with the archive code that I linked to above but it works as it should with blitzsys. Try the following.

AppHWND=SystemProperty("AppHWND")
api_EnableWindow(AppHWND,False)

path$=DLLGetOpenFileName$() ;Fill in parameters

api_SetForegroundWindow(AppHWND)
api_EnableWindow(AppHWND,True)
This still has its flaws but at least it stops the user bringing the Blitz app back in front of the file requester by clicking in its window.


John Blackledge(Posted 2005) [#13]
Joe, absolutely brilliant!
We've needed this for so long.

I implemented it completely through my app in 5 minutes, and it works perfectly.

Can I suggest that you add this to the code archives.


JoeGr(Posted 2005) [#14]
Thanks John, glad to be of help. I'd like to improve this further if possible before adding it to the archives though.


John Blackledge(Posted 2005) [#15]
Slightly off the topic, I've just found an added bonus use of api_SetForegroundWindow:
apptitlename$ = "Help"
handlewinhlp% = api_FindWindow(0,apptitlename$) 
If handlewinhlp%=0
 ExecFile("help\help.chm")
Else
 api_SetForegroundWindow(handlewinhlp%) 
EndIf

i.e. If the help file is already running but hidden by the main window, when I click my help button it jumps the help file back on top of the main window. Hee-hee.


JoeGr(Posted 2005) [#16]
I finally discovered how to do this properly! All it needed in the end was a simple adjustment to MPZ's code from the code archives.

First, get MPZ's code here:

http://www.blitzbasic.com/codearcs/codearcs.php?code=916

Add the line
Global hWnd=SystemProperty("AppHWND")
just after the Graphics command. Then in the getOpenFile$() and getSaveFile$() functions, change
hwndOwner=0
to
hwndOwner=hWnd
That's it. A proper Windows file requester which appears at the top left of the app's client area instead of the top left of the screen, and which maintains its focus. Woohoo!

Note: Be sure to use the 'updated' getOpenFile$() function found a little way down the code archive thread.