Hiho Team,
attached a small example for a self-centering FileOpenDialog() using a self-terminating timer call.
In the past I used _Timer_SetTimer() with a callback function, which works on x86, but does not under x64.
So here's an example working for x64 too, using a global variable and WM_TIMER calls.
What I just realized is that the doc for _WinAPI_SetTimer(), but also the MSDN doc for SetTimer, seem to be false.
Success: The timer identifier. An application can pass this value to the _WinAPI_KillTimer() function to destroy the timer.
_WinAPI_KillTimer() does not work when used with a hWnd and no callback func, _WinAPI_SetTimer() needs to be fed a dedicated TimerID (see "9876" used below). When I use the TimerID returned by _WinAPI_SetTimer() then _WinAPI_KillTimer() does not work.
Hopefully useful for someone 😉.
Edit: Replace fixed TimerID value 9876 with a TimerInit() call, I like the idea of a unique ID more.
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_UseX64=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPISysWin.au3>
Global $a_Global_FileOpenDialog_Wrapper[3] ; 0 = Title, 1 = hWnd, 2 = TimerID
Local $s_Selected_File = _FileOpenDialog_Wrapper("Select File", @ScriptDir, "All (*.*)", 1 + 2 + 4)
If Not @error Then MsgBox(0, "", $s_Selected_File)
Func _FileOpenDialog_Wrapper($sTitle, $sInitDir, $sFilter, $iOptions = 0, $sDefaultName = "", $hWnd = 0)
; https://groups.google.com/forum/?hl=en&fromgroups=#!topic/microsoft.public.vc.mfc/HafQr4gIRY0
; The problem is that GetOpenFileName changes the current directory to the last browsed one. The current directory and any of its parents cannot be deleted.
If Not $sInitDir Then $sInitDir = "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" ; CLSID for "My Computer"
Local $sWorkingDir = @WorkingDir
$a_Global_FileOpenDialog_Wrapper[0] = $sTitle
Local $old_GUISwitch = GUISwitch(0)
$a_Global_FileOpenDialog_Wrapper[1] = GUICreate("_FileOpenDialog_Wrapper")
GUISwitch($old_GUISwitch)
GUIRegisterMsg($WM_TIMER, "WM_TIMER")
$a_Global_FileOpenDialog_Wrapper[2] = _WinAPI_SetTimer($a_Global_FileOpenDialog_Wrapper[1], TimerInit(), 10, 0)
Local $sFilename = FileOpenDialog($sTitle, $sInitDir, $sFilter, $iOptions, $sDefaultName, $hWnd)
Local $iError = @error
ConsoleWrite("_WinAPI_KillTimer-2= " & _WinAPI_KillTimer($a_Global_FileOpenDialog_Wrapper[1], $a_Global_FileOpenDialog_Wrapper[2]) & @CRLF)
GUIRegisterMsg($WM_TIMER, "")
GUIDelete($a_Global_FileOpenDialog_Wrapper[1])
FileChangeDir($sWorkingDir)
If Not $iError Then
If StringInStr($sFilename, "|", 2) Then ; multiple selection
Local $aFilename = StringSplit($sFilename, "|")
Else
Local $sPath = StringTrimRight($sFilename, StringLen($sFilename) - StringInStr($sFilename, "\", 2, -1))
EndIf
EndIf
Return SetError($iError, 0, $sFilename)
EndFunc ;==>_FileOpenDialog_Wrapper
Func WM_TIMER($hWnd, $iMsg, $iwParam, $ilParam)
#forceref $hWnd, $iMsg, $iwParam, $ilParam
ConsoleWrite("WM_TIMER " & @TAB & TimerInit() & @TAB & $hWnd & @TAB & $iMsg & @TAB & $iwParam & @TAB & $ilParam & @CRLF)
Local $hWnd_Timer_Move_FileOpenDialog = WinGetHandle("[TITLE:" & $a_Global_FileOpenDialog_Wrapper[0] & ";CLASS:#32770]", "")
If IsHWnd($hWnd_Timer_Move_FileOpenDialog) Then
ConsoleWrite("WinMove= " & WinMove($hWnd_Timer_Move_FileOpenDialog, "", (@DesktopWidth - (@DesktopWidth / 4 * 3)) / 2, (@DesktopHeight - (@DesktopHeight / 4 * 3)) / 2, @DesktopWidth / 4 * 3, @DesktopHeight / 4 * 3) & @CRLF)
ConsoleWrite("_WinAPI_KillTimer-1= " & _WinAPI_KillTimer($a_Global_FileOpenDialog_Wrapper[1], $a_Global_FileOpenDialog_Wrapper[2]) & @CRLF)
ConsoleWrite(_WinAPI_GetLastErrorMessage() & @CRLF)
EndIf
Return $GUI_RUNDEFMSG
EndFunc ;==>WM_TIMER
Different approach, same result as with