WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

Dialog Boxes

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

UDF Replacement for Message


I have had a frustration for a while that message() boxes were always centered. This is made worse by the fact that more than half the systems in my office have two or three displays. This meant that messages would be split between the monitors where it is hard to read (two display systems), or centered on the second monitor which would occasionally escape my notice.

I have just completed a UDF to replace the default Message() command, it supports the following:

I am posting this for your amusement, use it as you will. I am not an advanced WinBatch user and would welcome any comments/criticisms/suggestions any of you may have.

If you run the WBT file there is a short demo of its capabilities. Good luck.

- Sean

;*******************************************************************************
;****                                                                       ****
;****  _udfMessage v1.02                                                    ****
;****  Sean Dorn   2003Sep11                                                ****
;****                                                                       ****
;****  This function is a replacement for the standard message box.         ****
;****  Its main purpose is to allow placement control of the dialog.        ****
;****                                                                       ****
;****  Usage:                                                               ****
;****                                                                       ****
;****  udfMessage(Title,Text,TextJust,Timeout,Buttons,PositionBox)          ****
;****                                                                       ****
;****     Title: This is the string that appears in the title bar.          ****
;****     Text: This is the string that appears in the body of the dialog,  ****
;****         multiple lines can be used by placing a @CRLF in the string   ****
;****     TextJust:                                                         ****
;****        "Center": Text will be centered in the dialog                  ****
;****        "Left": Text will be left justified in the dialog              ****
;****        "Right": Text will be right justified in the dialog            ****
;****     Timeout: The number of seconds to wait before auto closing the    ****
;****         dialog, positive integer only. Use 0 for no timeout.          ****
;****     Buttons: This string determins which buttons appear in the dialog ****
;****        The button names need to be separated by a "|", any number     ****
;****        of buttons may be used. The first button will be the default   ****
;****        and the last button will be connected to the ESC key.          ****
;****        Examples:                                                      ****
;****            "": No buttons - you must use a timeout in this case ;)    ****
;****            "OK": OK button only                                       ****
;****            "Continue|Quit": Continue and Quit buttons                 ****
;****            "Yes|No|Cancel": Yes, No and Cancel buttons                ****
;****     PositionBox: This is a box as returned by the WinPosition()       ****
;****                  function (string with four comma-deimited values).   ****
;****                  The message box will be centered on this position    ****
;****                  box. The coordinates are in WinBatch virtual         ****
;****                  coordinates (screen is 1000x1000).                   ****
;****                  Examples: Sending (0,0,1000,1000) would center the   ****
;****                            on the screen. Sending the value returned  ****
;****                            by WinPosition on an existing window will  ****
;****                            center on that window.                     ****
;****                                                                       ****
;****  Returns: If the dialog timed out then "Timeout" will be returned,    ****
;****           otherwise the text of the button pressed will be returned   ****
;****           (ie. if the "Continue" button is pressed then the return    ****
;****           value will be "Continue".                                   ****
;****                                                                       ****
;*******************************************************************************

;********************************************************************************************************************************************************

        ;********************************************************
        ;****                                                ****
        ;****    BEGIN SUBROUTINE:  MessageUdfProc           ****
        ;****                                                ****
        ;********************************************************
        #DEFINESUBROUTINE MessageUdfProc(dlgMessageUdfHandle,dlgMessageUdfEvent,dlgMessageUdfEventControlID,dlgMessageUdfParam4,dlgMessageUdfParam5)
        switch (dlgMessageUdfEvent)
            case 0 ;dialog initialization event
                if Timeout > 0
                       dialogprocoptions(dlgMessageUdfHandle, 1, 1000)  ;if timeout is specified then watch for timer at 1 sec intervals
                    else
                        dialogcontrolstate(dlgMessageUdfHandle, 1, 3, 1) ; hide control
                    endif
                dialogprocoptions(dlgMessageUdfHandle, 2, 1)  ;watch for push button events
                msgTimeStart = TimeYmdHms()
                beep
                break
            case 1 ;timer event
                msgTimeLeft = Timeout - TimeDiffSecs(TimeYmdHms(),msgTimeStart)
                if msgTimeLeft < 1
                    ReturnValue = "Timeout"
                    return 1
                    endif
                dialogcontrolset(dlgMessageUdfHandle,1,4,msgTimeLeft)  ;update timeout display
                break
            case 2 ;pushbutton event
                tmpButtonText = dialogcontrolget(dlgMessageUdfHandle,dlgMessageUdfEventControlID,4)
                ReturnValue = tmpButtonText
                return 1
                break
            endswitch
        return -2
        #ENDSUBROUTINE  ;
        ;********************************************************
        ;****                                                ****
        ;****    END SUBROUTINE:  MessageUdfProc             ****
        ;****                                                ****
        ;********************************************************

        ;********************************************************************************************************************************************************

;********************************************************
;****                                                ****
;****    BEGIN FUNCTION:  udfMessage                 ****
;****                                                ****
;********************************************************
#DEFINEFUNCTION udfMessage(Title,Text,TextJust,Timeout,Buttons,PositionBox)

;**** define dialog box template ****
dlgMessageUdfFormat=`WWWDLGED,6.1`

dlgMessageUdfCaption=`Title`
dlgMessageUdfX=0
dlgMessageUdfY=0
dlgMessageUdfWidth=102
dlgMessageUdfHeight=053
dlgMessageUdfNumControls=004
dlgMessageUdfProcedure=`MessageUdfProc`
dlgMessageUdfFont=`DEFAULT`
dlgMessageUdfTextColor=`DEFAULT`
dlgMessageUdfBackground=`DEFAULT,DEFAULT`
dlgMessageUdfConfig=2

dlgMessageUdf001=`001,001,010,008,STATICTEXT,DEFAULT,"000 (Timeout)",DEFAULT,1,DEFAULT,DEFAULT,"0|128|128",DEFAULT`
dlgMessageUdf002=`011,009,070,009,STATICTEXT,DEFAULT,"Sample Text Line",DEFAULT,2,512,DEFAULT,DEFAULT,DEFAULT`
dlgMessageUdf003=`012,026,036,012,PUSHBUTTON,DEFAULT,"OK",1,3,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
dlgMessageUdf004=`054,026,036,012,PUSHBUTTON,DEFAULT,"Cancel",0,4,DEFAULT,DEFAULT,DEFAULT,DEFAULT`

ButtonPushed=Dialog("dlgMessageUdf",0) ; WinBatch will not display this dialog.

;****  check that the timeout value is a valid number  ****
if IsNumber(Timeout) && Timeout > 0
        Timeout = Int(Timeout)
    else
        Timeout = 0
    endif

;**** Break input text into multiple lines if necessary  ****
TextMaxLength = 0
LineNum = 1
while @TRUE
    CRLFPos = StrScan(Text, @crlf, 1, @FWDSCAN)
    If CRLFPos == 0
            TextLine%LineNum% = Text
            TextMaxLength = Max(strlen(TextLine%LineNum%), TextMaxLength)
            break
        else
            TextLine%LineNum% = StrSub(Text, 1, CRLFPos-1)
            TextMaxLength = Max(strlen(TextLine%LineNum%), TextMaxLength)
            Text = StrSub(Text, CRLFPos+2, -1)
            LineNum = LineNum + 1
        endif
    endwhile

;****  examine dialog template (above) and extract dimensions  ****
TextHeight = 9  ;average height of default font
TextWidth = 3  ;average width of default font (should be 4 but 3 seems better, why?)
TextWidthMax = int(TextWidth * TextMaxLength)
BorderX = ItemExtract(1, dlgMessageUdf002, ",")    ;get X border gap from dialog template
BorderY = ItemExtract(2, dlgMessageUdf002, ",")    ;get Y border gap from dialog template
ButtonHeight = ItemExtract(4, dlgMessageUdf003, ",")    ;get button width from dialog template
ButtonWidth = ItemExtract(3, dlgMessageUdf003, ",")    ;get button height from dialog template
TextToButtonGap = ItemExtract(2,dlgMessageUdf003,",") - BorderY - TextHeight   ;get the space between the text and buttons from dialog template
ButtonToButtonGap = ItemExtract(1,dlgMessageUdf004,",") - ItemExtract(1,dlgMessageUdf003,",") - ButtonWidth
CurrentYPos = BorderY  ;set current dialog height

;**** get styles from dialog template  ****
ControlStyle = ItemExtract(10, dlgMessageUdf002, ",")
ControlFont = ItemExtract(11, dlgMessageUdf002, ",")
ControlTextColor = ItemExtract(12, dlgMessageUdf002, ",")
ControlBackgroundColor = ItemExtract(13, dlgMessageUdf002, ",")

dlgMessageUdf001 = itemreplace(`"%Timeout%"`,7,dlgMessageUdf001,",")  ;Change timeout display to correct value
ControlCount = 1    ;one control created so far (the timeout display)
dlgMessageUdfCaption = Title  ;set the correct title for the dialog

;****  add text lines to dialog box  ****
tmpJustification = 512   ; set default to centered
if strupper(TextJust) == "LEFT" then tmpJustification = 0
if strupper(TextJust) == "RIGHT" then tmpJustification = 1024
for tmpLineNum = 1 to LineNum
    tmpTextLine = TextLine%tmpLineNum%
    ControlCount = ControlCount + 1   ;add a control
    ControlCount = strfixleft(ControlCount,"0",3)  ;pad to three digits with leading zeros
    dlgMessageUdf%ControlCount%=`%BorderX%,%CurrentYPos%,%TextWidthMax%,%TextHeight%,STATICTEXT,DEFAULT,"%tmpTextLine%",DEFAULT,%ControlCount%,%tmpJustification%,%ControlFont%,%ControlTextColor%,%ControlBackgroundColor%`
    CurrentYPos = CurrentYPos + TextHeight  ; move CurrentYPos to bottom of line
    next

;****  Identify Buttons  ****
ButtonCount = itemcount(Buttons,"|")
for CurrentButton = 1 to ButtonCount
    Button%CurrentButton%Text = itemextract(CurrentButton,Buttons,"|")
    next
if ButtonCount==0 && Timeout<=0 then Timeout = 8  ;safety in case there is no timeout and no buttons (bad idea!)
if ButtonCount > 0 then CurrentYPos = CurrentYPos + TextToButtonGap  ;place a gap between text and buttons

;****  Check widths  ****
TotalWidthOfButtons = max(0, ButtonWidth*ButtonCount+ButtonToButtonGap*(ButtonCount-1))
WidthOfTextBoxes = max(TextWidthMax,TotalWidthOfButtons)
DialogWidth = BorderX*2 + max(TextWidthMax,TotalWidthOfButtons)  ;set dialog width to whichever is wider - buttons or text

;****  adjust text boxes to max width
for tmpCurTextLine = 2 to LineNum+1
    ControlNum = strfixleft(tmpCurTextLine,"0",3)  ;pad to three digits with leading zeros
    dlgMessageUdf%ControlNum% = itemreplace("%WidthOfTextBoxes%",3,dlgMessageUdf%ControlNum%,",")      
    next

;****  create dialog buttons  ****
for CurrentButton = 1 to ButtonCount
    CurrentButtonText = Button%CurrentButton%Text
    ControlCount = ControlCount + 1   ;add a control
    ControlCount = strfixleft(ControlCount,"0",3)  ;pad to three digits with leading zeros
    XPosition = int(DialogWidth/2.0 - TotalWidthOfButtons/2.0 + (ButtonWidth+ButtonToButtonGap)*(CurrentButton-1)) - 1  ;place button horizontally
    dlgMessageUdf%ControlCount%=`%XPosition%,%CurrentYPos%,%ButtonWidth%,%ButtonHeight%,PUSHBUTTON,DEFAULT,"%CurrentButtonText%",%CurrentButton%,%ControlCount%,%ControlStyle%,%ControlFont%,%ControlTextColor%,%ControlBackgroundColor%`
    next

if ButtonCount > 0 then CurrentYPos = CurrentYPos + ButtonHeight  ;move CurrentYPos to bottom of button buttons
    
;****  Find the center of PositionBox and convert it from WinBatch virtual screen units to Dialog units  ****
PixelsPerDialogUnitX = winmetrics(-6)
PixelsPerDialogUnitY = winmetrics(-5)
PixelsPerWbtUnitX = winmetrics(0)/1000.0
PixelsPerWbtUnitY = winmetrics(1)/1000.0
CenterXPosWbtUnits = itemextract(1,PositionBox,",") + int((itemextract(3,PositionBox,",")-itemextract(1,PositionBox,",")) / 2.0)
CenterYPosWbtUnits = itemextract(2,PositionBox,",") + int((itemextract(4,PositionBox,",")-itemextract(2,PositionBox,",")) / 2.0)
CenterXPosPixels = CenterXPosWbtUnits * PixelsPerWbtUnitX
CenterYPosPixels = CenterYPosWbtUnits * PixelsPerWbtUnitY
CenterXPosDialogUnits = int(CenterXPosPixels / PixelsPerDialogUnitX)
CenterYPosDialogUnits = int(CenterYPosPixels / PixelsPerDialogUnitY)

;****  update final dialog settings  ****
if ButtonCount > 1 then dlgMessageUdf%ControlCount% = itemreplace("0",8,dlgMessageUdf%ControlCount%,",")  ;make the last button the cancel button
dlgMessageUdfNumControls = ControlCount
dlgMessageUdfWidth = DialogWidth
dlgMessageUdfHeight = CurrentYPos + BorderY + 1 ;add a border gap to bottom of dialog
dlgMessageUdfX = CenterXPosDialogUnits - int(dlgMessageUdfWidth / 2.0)  ;center dialog on PositionBox
dlgMessageUdfY = CenterYPosDialogUnits - int(dlgMessageUdfHeight / 2.0)  ;center dialog on PositionBox

;display dialog and start making estimate
dlgCancelHandler = "CancelBack"
dlgMessageUdfButtonPushed=Dialog("dlgMessageUdf")
dlgCancelHandler = ""

return ReturnValue

#ENDFUNCTION
;********************************************************
;****                                                ****
;****    END FUNCTION:  udfMessage                   ****
;****                                                ****
;********************************************************


;**********************************
;**********************************
;*******                   ********
;*******   T E S T I N G   ********
;*******                   ********
;**********************************
;**********************************

tmpResult = udfMessage("Sample 1", "This example demonstrates the timeout function.","Center",8,"","0,0,1000,1000")
runshell("Calc.exe","","",@NORMAL,@NOWAIT)
timedelay(1)
tmpResult = udfMessage("Sample 2", "This example demonstrates multi-line text%@CRLF%and centering on the calculator.","Center",0,"OK",winposition("Calculator"))
tmpResult = udfMessage("Sample 3", "This example has two buttons along with%@CRLF% a timeout and is centered to the screen.","Center",15,"Continue|Quit","0,0,1000,1000")
tmpResult = udfMessage("Sample 4", "This example has Yes, No and Cancel buttons.","Center",15,"Yes|No|Cancel","0,0,1000,1000")

Article ID:   W16246
File Created: 2004:03:30:15:43:34
Last Updated: 2004:03:30:15:43:34