Another one, using hook and timer.
Code: Select all
Structure mbData
hHook.l
x.l
y.l
flags.l
time.l
TxtGadget.l
oldWndProc.l
EndStructure
Global mb.mbData
Procedure MBWndProc(hWnd, uMsg, wParam, lParam)
Protected i, c, hDef, val, res
Protected wi.WINDOWINFO, x, y, w, h, fl=#SWP_NOZORDER|#SWP_NOMOVE
With mb
If uMsg = #WM_TIMER ;And wParam = 1
If \time > 0
SetGadgetText(\TxtGadget, "Select in "+Str(\time)+" sec.")
\time - 1
Else
Debug "Time over"
If \flags & #MB_DEFBUTTON3
c=2
ElseIf \flags & #MB_DEFBUTTON2
c=1
Else
c=0
EndIf
For i=0 To c
hDef = GetNextDlgTabItem_(hWnd, hDef, 0)
Next
val = GetDlgCtrlID_(hDef)
EndDialog_(hWnd, val)
EndIf
;uMsg = #WM_NULL ;For message override. Without this, #WM_TIMER fired only once.
ProcedureReturn ;or use this.
EndIf
If uMsg = #WM_INITDIALOG
wi\cbSize = SizeOf(WINDOWINFO)
GetWindowInfo_(hWnd, @wi)
w = wi\rcWindow\right - wi\rcWindow\left
h = wi\rcWindow\bottom - wi\rcWindow\top
x = wi\rcWindow\left
y = wi\rcWindow\top
If \x >= 0 : x= \x : fl= fl & (~#SWP_NOMOVE) : EndIf
If \y >= 0 : y= \y : fl= fl & (~#SWP_NOMOVE) : EndIf
If \time > 0
h + 20
CreateGadgetList(hWnd)
\TxtGadget=TextGadget(#PB_Any, 0, wi\rcClient\bottom-wi\rcClient\top, w, 20,"Select in "+Str(\time)+" sec.",#PB_Text_Center)
Debug "Set timer"
\time - 1
SetTimer_(hWnd, 1, 1000, 0)
Else
fl = fl | #SWP_NOSIZE
Debug "Remove callback"
SetWindowLong_(hWnd, #GWL_WNDPROC, \oldWndProc)
EndIf
SetWindowPos_(hWnd, 0, x, y, w, h, fl)
EndIf
If uMsg = #WM_DESTROY
Debug "Kill timer"
KillTimer_(hWnd, 1)
If IsGadget(\TxtGadget)
Debug "freed"
FreeGadget(\TxtGadget)
EndIf
EndIf
res = CallWindowProc_(\oldWndProc, hWnd, uMsg, wParam, lParam)
EndWith
ProcedureReturn res
EndProcedure
Procedure.l MBHookProc(nCode, wParam, lParam)
Protected *p.CWPSTRUCT
With mb
If nCode = #HC_ACTION
*p = lParam
If *p\message = #WM_INITDIALOG
UnhookWindowsHookEx_(\hHook)
\oldWndProc=SetWindowLong_(*p\hwnd, #GWL_WNDPROC, @MBWndProc())
ProcedureReturn #False
EndIf
EndIf
;ProcedureReturn CallNextHookEx_(\hHook, nCode, wParam, lParam)
EndWith
EndProcedure
Procedure MBox(hParentWnd, Title$, Text$, DelayTime=0, x=-1, y=-1, Flags=0)
Protected hThreadId, res
With mb
\x=x : \y=y : \flags=Flags : \time=DelayTime
hThreadId = GetCurrentThreadId_()
\hHook = SetWindowsHookEx_(#WH_CALLWNDPROC, @MBHookProc(), 0, hThreadId)
res = MessageBox_(hParentWnd, Text$, Title$, Flags)
EndWith
ProcedureReturn res
EndProcedure
;-------------------
;- Test
;-------------------
Procedure SelBtn(res)
Protected msg$
Select res
Case #IDOK : msg$="OK"
Case #IDCANCEL : msg$="Cancel"
Case #IDABORT : msg$="Abort"
Case #IDRETRY : msg$="Retry"
Case #IDIGNORE : msg$="Ignore"
Case #IDYES : msg$="Yes"
Case #IDNO : msg$="No"
EndSelect
MessageRequester("Selected", msg$)
EndProcedure
hwnd=OpenWindow(0,100,100,400,300,"MBox Test")
res=MBox(hwnd, "test0", "Normal")
SelBtn(res)
res=MBox(hwnd, "test1", "Esc to cancel", 6, 10, -1, #MB_ICONASTERISK|#MB_YESNOCANCEL|#MB_DEFBUTTON3)
SelBtn(res)
res=MBox(hwnd, "test2", "waiting...", 4, -1, 100)
SelBtn(res)
StickyWindow(0,1)
res=MBox(hwnd, "test3", "Esc to cancel", 0, 50, 300, #MB_ICONERROR|#MB_DEFBUTTON3|#MB_OKCANCEL)
SelBtn(res)
res=MBox(hwnd, "test4", "Esc to cancel", 4, -1, -1, #MB_ICONERROR|#MB_DEFBUTTON3|#MB_OKCANCEL)
SelBtn(res)
res=MBox(hwnd, "test5", "waiting...", 4, -1, -1, #MB_ICONEXCLAMATION|#MB_DEFBUTTON1|#MB_ABORTRETRYIGNORE)
SelBtn(res)