Microsoft's recommended timed messagebox

Share your advanced PureBasic knowledge/code with the community.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

I can't even get

Code: Select all

MessageBox_(0, "Hello", "Test", #MB_YESNO) 
to work with xp themes turned on!

Strangely though, the following seems to work and produces both message boxes with xp themes turned on:

Code: Select all

MessageBox_(0, "Hello", "Test", #MB_YESNO) 

MessageRequester("Hello from requester","")
This is strange.
I may look like a mule, but I'm not a complete ass.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Code: Select all

InitCommonControls_()
This seems to fix it with xp themes; at least on my system.
I may look like a mule, but I'm not a complete ass.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

Sorry guys, this is my fault. I should have realized that there would be spotty success without an InitCommonControls, which isn't needed if you have a window with gadgets open and a CreateGadgetList has happened. Here's a better example:

Code: Select all

;*************************************************************************** 
; Program:         Yet another timed messagebox sample 
; Source:          http://support.microsoft.com/?scid=181934 
; PB version by:   netmaestro 
; Date:            March 21, 2007 
; Applies to:      Anyone who likes timed message boxes 
; Disclaimer:      Hardly any animals were harmed during the creation of 
;                  this software. (one who whined got his feelings hurt) 
;*************************************************************************** 

#MessageBox_Timeout = -1 
  
Global g_hwndTimedOwner 
Global g_bTimedOut 

Procedure MessageBoxTimer(hwnd, uiMsg, idEvent, dwTime) 
   g_bTimedOut = #True 
   If g_hwndTimedOwner 
     EnableWindow_(g_hwndTimedOwner, #True) 
   EndIf 
   PostQuitMessage_(0) 
EndProcedure 

Procedure TimedMessageBox(hwndOwner, pszMessage.s, pszTitle.s, flags, dwTimeout) 
   Protected idTimer.l, iResult.l 
   g_hwndTimedOwner = #Null 
   g_bTimedOut = #False 
   If hwndOwner And IsWindowEnabled_(hwndOwner) 
     g_hwndTimedOwner = hwndOwner 
   EndIf 
   idTimer.l = SetTimer_(#Null, 0, dwTimeout, @MessageBoxTimer()) 
   iResult.l = MessageBox_(hwndOwner, pszMessage, pszTitle, flags) 
   KillTimer_(#Null, idTimer) 
   If g_bTimedOut 
     PeekMessage_(@msg.MSG, #Null, #WM_QUIT, #WM_QUIT, #PM_REMOVE) 
     iResult = #MessageBox_Timeout 
   EndIf 
   ProcedureReturn iResult 
EndProcedure 

; Little test... 

OpenWindow(0,0,0,320,240,"",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
CreateGadgetList(WindowID(0))
ButtonGadget(0,100,200,100,25,"Do it")
Repeat
ev = WaitWindowEvent()
  If ev = #PB_Event_Gadget
    uiResult = TimedMessageBox(#Null, "Does a triangle have three sides?", "Quiz", #MB_YESNO, 5000) ; // NULL first parameter is important. 
    
    Select uiResult 
      Case #IDYES 
         MessageBox_(#Null, "That's right!", "Result", #MB_OK) 
      Case #IDNO 
         MessageBox_(#Null, "Believe it or not, triangles really do have three sides.", "Result", #MB_OK) 
      Case #MessageBox_Timeout 
         MessageBox_(#Null,  "I sensed some hesitation there. The correct answer is Yes.", "Result", #MB_OK) 
    EndSelect 
  EndIf
Until ev = #WM_CLOSE
BERESHEIT
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

It's curious though that InitCommonControls_() is not required when xp themes is not enabled!
I may look like a mule, but I'm not a complete ass.
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post by PB »

> Weird thing though, it works with XP sytle turned off!

Works here with XP style on, so go figure.
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
Little John
Addict
Addict
Posts: 4791
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Post by Little John »

2netmaestro:
Cool, thanks a lot!
Is it possible to change the code, so that the timed message box displays a countdown of the remaining seconds?

Regards, Little John
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

Hehe, I have fifty things to do today, but you happened to ask for something fun, so 49 jobs get pushed back and this gets done:

Code: Select all

;===================================================================================
; Program:         Yet another timed messagebox sample - Remaining Seconds Version
; Source:          http://support.microsoft.com/?scid=181934 
; PB version by:   netmaestro 
; Date:            March 21, 2007 
; Applies to:      Anyone who likes timed message boxes 
; Disclaimer:      Hardly any animals were harmed during the creation of 
;                  this software. (one who whined got his feelings hurt) 
;===================================================================================

#MessageBox_Timeout = -1 
  
Global g_hwndTimedOwner 
Global g_bTimedOut, g_dwTimeout, g_Quiz_ButtonHandle

Procedure MessageBoxStatus(hwnd, uiMsg, idEvent, dwTime) 
  Static numseconds=0
  Static firstrun=1
  If firstrun
    numseconds = g_dwTimeout / 1000
    firstrun = 0
  EndIf
  numseconds-1
  If IsWindow_(g_Quiz_ButtonHandle)
    SetWindowText_(g_Quiz_ButtonHandle, "&Yes = "+Str(numseconds))
  Else
    KillTimer_(hwnd, idEvent)
    firstrun = 1
  EndIf
  If numseconds < 0
    KillTimer_(hwnd, idEvent)
    firstrun = 1
  EndIf
EndProcedure 

Procedure FindButton(hwnd, param)
  ButtonText.s = Space(50)
  GetWindowText_(hwnd, @ButtonText, 49)
  If ButtonText = PeekS(param)
    g_Quiz_ButtonHandle = hwnd
    ProcedureReturn 0
  Else
    ProcedureReturn 1
  EndIf
EndProcedure

Procedure WindowProc(hwnd, msg, wparam, lparam)
  result = #PB_ProcessPureBasicEvents

  Select msg
    Case #WM_ACTIVATE
      If wparam & $FFFF = #WA_INACTIVE
        class.s = Space(50)
        caption.s = Space(50)
        GetClassName_(lparam, @class, 49)
        GetWindowText_(lparam, @caption, 49)
        If class = "#32770" 
          If caption = "Quiz"
            EnumChildWindows_(lparam, @FindButton(), @"&Yes") 
            If IsWindow_(g_Quiz_ButtonHandle)
              SetWindowText_(g_Quiz_ButtonHandle, "&Yes = "+Str(g_dwTimeout/1000))
            EndIf            
            idStatusTimer.l = SetTimer_(#Null, 0, 1000, @MessageBoxStatus()) 
          EndIf
        EndIf
      EndIf
  EndSelect
  ProcedureReturn result
EndProcedure

Procedure MessageBoxTimer(hwnd, uiMsg, idEvent, dwTime) 
   g_bTimedOut = #True 
   If g_hwndTimedOwner 
     EnableWindow_(g_hwndTimedOwner, #True) 
   EndIf 
   PostQuitMessage_(0) 
EndProcedure 

Procedure TimedMessageBox(hwndOwner, pszMessage.s, pszTitle.s, flags, dwTimeout) 
   Protected idTimer.l, iResult.l 
   g_hwndTimedOwner = #Null 
   g_bTimedOut = #False 
   g_dwTimeout = dwTimeout
   If hwndOwner And IsWindowEnabled_(hwndOwner) 
     g_hwndTimedOwner = hwndOwner 
   EndIf 
   idTimer.l = SetTimer_(#Null, 0, dwTimeout, @MessageBoxTimer()) 
   iResult.l = MessageBox_(hwndOwner, pszMessage, pszTitle, flags) 
   KillTimer_(#Null, idTimer) 
   If g_bTimedOut 
     PeekMessage_(@msg.MSG, #Null, #WM_QUIT, #WM_QUIT, #PM_REMOVE) 
     iResult = #MessageBox_Timeout 
   EndIf 
   ProcedureReturn iResult 
EndProcedure 


; Little test... 

OpenWindow(0,0,0,320,240,"",#PB_Window_ScreenCentered|#PB_Window_SystemMenu) 
CreateGadgetList(WindowID(0)) 
ButtonGadget(0,100,200,100,25,"Do it") 
SetWindowCallback(@WindowProc())

Repeat 
ev = WaitWindowEvent() 
  If ev = #PB_Event_Gadget 
    uiResult = TimedMessageBox(#Null, "Does a triangle have three sides?", "Quiz", #MB_YESNO, 5000) ; // NULL first parameter is important. 
    
    Select uiResult 
      Case #IDYES 
         MessageBox_(#Null, "That's right!", "Result", #MB_OK) 
      Case #IDNO 
         MessageBox_(#Null, "Believe it or not, triangles really do have three sides.", "Result", #MB_OK) 
      Case #MessageBox_Timeout 
         MessageBox_(#Null,  "I sensed some hesitation there. The correct answer is Yes.", "Result", #MB_OK) 
    EndSelect 
  EndIf 
Until ev = #WM_CLOSE 
BERESHEIT
Little John
Addict
Addict
Posts: 4791
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Post by Little John »

netmaestro wrote:Hehe, I have fifty things to do today, but you happened to ask for something fun, so 49 jobs get pushed back and this gets done
:D

I've seen something like that in the AVG antivirus program, and have wondered for a long time how this could be done with PureBasic.

Thank you so much!

Aside: At first, this code worked for me like the previous version, i.e. it didn't show the remaining seconds. Then I saw, that on line 59 it reads:

Code: Select all

EnumChildWindows_(lparam, @FindButton(), @"&Yes")
On my German system, the caption of the concerning button in the message box is "Ja". :D
I replaced "Yes" with "Ja" on that line, and now it works like a charm!

Many thanks again!

Regards, Little - very happy - John
Inf0Byt3
PureBasic Fanatic
PureBasic Fanatic
Posts: 2236
Joined: Fri Dec 09, 2005 12:15 pm
Location: Elbonia

Post by Inf0Byt3 »

Very nice, thanks!
None are more hopelessly enslaved than those who falsely believe they are free. (Goethe)
Little John
Addict
Addict
Posts: 4791
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Post by Little John »

There is a small issue: The TimedMessageBox() is not modal, but IMHO it
should be modal like a normal message box. At least at the first glance,
it looks as if it can be made modal by passing

Code: Select all

WindowID(#MyWindow)
as first parameter to TimedMessageBox(), but as comment you wrote
NULL first parameter is important
So how can I make TimedMessageBox() modal?

TIA, Little John
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

You should be able to go ahead and put the WindowID of your application's window there. The comment was from Microsoft and the original example wasn't called from an application with a window, which I believe was the reason for it. It should be modal with your WindowID passed in there and it'll work as expected.
BERESHEIT
Little John
Addict
Addict
Posts: 4791
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Post by Little John »

I see. Thanks again!

Best regards, Little John
breeze4me
Enthusiast
Enthusiast
Posts: 633
Joined: Thu Mar 09, 2006 9:24 am
Location: S. Kor

Post by breeze4me »

A method using undocumented API "MessageBoxTimeout"
(maybe XP+ :?: )

Code: Select all

Prototype.i MBT(hwnd, lpText.s, lpCaption.s, uType, wLanguageId, dwMilliseconds)
Global MessageBoxTimeout.MBT

#MB_TIMEDOUT = $7D00

If OpenLibrary(0, "user32.dll")
  CompilerIf #PB_Compiler_Unicode
    MessageBoxTimeout = GetFunction(0, "MessageBoxTimeoutW")
  CompilerElse
    MessageBoxTimeout = GetFunction(0, "MessageBoxTimeoutA")
  CompilerEndIf
  If MessageBoxTimeout
    res = MessageBoxTimeout(0, "Waiting for 3 seconds.", "Timeout MessageBox Test", #MB_SETFOREGROUND | #MB_YESNO | #MB_ICONASTERISK, 0, 3000)
    Select res
      Case #IDYES
        Debug "Yes"
      Case #IDNO
        Debug "No"
      Case #MB_TIMEDOUT
        Debug "Timeout"
    EndSelect
  EndIf
  CloseLibrary(0)
EndIf
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Post by Kwai chang caine »

The code of my preffered frog, works fine here on W2000 8)

Well, .....I return into my trash, for retrieve my mouse. :?
Because, i believe it's her who don't works, and click for me everywhere, when i have see, that the message box answering itself :lol:

Thanks NETMAESTRO for sharing
ImageThe happiness is a road...
Not a destination
Post Reply