For this example, I´m using Yes and NO to make it different from Ok And Cancel.
I would like the Y of the Yes to be Underlined and The N in the no to be underlined and the user could just type Y or y or N or n. Let´s put the No as default, so it must be with the lines around it to show that it is defaulted, and of course the user could use left and right arrow to move from Yes to No or from No to Yes and Enter to make the choice without using the mouse.
It is very similar to DC_MsgBox(,,{'add your string here'},,,,.t.)
Here is the code to start with
Code: Select all
FUNCTION sConfirm(string) // Yes or No
LOCAL GetList := {}, GetOptions, nChoice := 2
// this function will return 1 for Yes and 2 for No
@ 1,1 DCSAY string
@ 04,01 DCPUSHBUTTON CAPTION ' Yes ' SIZE 13,1.2 ;
ID 'YES' ;
ACTION {|| DC_ReadGuiEvent(DCGUI_EXIT_OK,GetList), nChoice := 1 }
@ 04,20 DCPUSHBUTTON CAPTION ' No ' SIZE 13,1.2 ;
ID 'NO' ;
ACTION {|| DC_ReadGuiEvent(DCGUI_EXIT_OK,GetList), nChoice := 2 }
DCGETOPTIONS ;
TITLE ''
DCREAD GUI ;
FIT ;
MODAL ;
TITLE '' ;
OPTIONS GetOptions
RETURN nChoice
This does not look that simple. This is how it is implemented in Express++
The following code from DC_MSGBOX
Code: Select all
FUNCTION dc_msgbox ( nRow, nCol, aMessage, cTitle, lWait, nSeconds, lYesNo,;
nChoice, aItems, aMenuId, cMenuName, cHotKey, cFont, ;
bEval, nIcon, lNoRestore, lAlwaysOnTop, aColor, ;
aButtSize, lHorizButtons, oOwner )
LOCAL nWidth, i, cSaveScreen, nYesNoCol, nCursor, cSaveColor, ;
lPrint, lConsole, cDevice, aChoice, cColor1, cColor2, ;
cMessage, oDlg, oXbp, nHeight, oParent, lInLoop, oOldApp, ;
GetList := {}, aLocals[7], lOk, nTabGroup, GetOptions, ;
oAppFocus := SetAppFocus(), nLine, cKey, cPrompt, lAction := .f., ;
lOutput, nIconType, nButtHeight, nButtWidth, lPixel, nColumn, ;
nCharHeight, nTextWidth
l_Escape := DC_MsgBoxEscape()
l_EscHit := .f.
lOutput := .f.
DEFAULT nChoice := 0, ;
lNoRestore := .t., ;
lAlwaysOnTop := .f., ;
lHorizButtons := .f., ;
aColor := DC_MsgBoxColor(), ;
oOwner := SetAppWindow(), ;
cFont := DC_MsgBoxFont()
IF Empty(cFont)
cFont := DC_BaseFont()
ENDIF
IF Valtype( nRow ) = 'C'
aMessage := { nRow }
lWait := .t.
nRow := 0
nCol := 0
ELSEIF Valtype(nRow) ='A'
aMessage := AClone(nRow)
lWait := .t.
nRow := 0
nCol := 0
ENDIF
DC_VALTYPE( @lYesNo, .f. )
DC_VALTYPE( @nRow,0, @nCol,0, @aMessage,{}, @cTitle,DC_MsgBoxTitle(), ;
@nSeconds,0, @lWait,!lYesNo, @aItems,{} )
IF Valtype(nIcon) # 'N'
IF lYesNo
nIcon := XBPSTATIC_SYSICON_ICONQUESTION
nIconType := XBPSTATIC_TYPE_SYSICON
ELSE
nIcon := XBPSTATIC_SYSICON_ICONINFORMATION
nIconType := XBPSTATIC_TYPE_SYSICON
ENDIF
ELSE
nIconType := XBPSTATIC_TYPE_ICON
ENDIF
IF nIcon < 100
nIconType := XBPSTATIC_TYPE_SYSICON
ENDIF
FOR i := 1 TO LEN(aMessage)
aMessage[i] := DC_XtoC(aMessage[i])
NEXT
IF LEN(aMessage)>0 .AND. lWait .AND. !('Y/N'$UPPER(aMessage[1])) ;
.AND. nSeconds=0 .AND. !lYesNo .AND. LEN(aItems)=0
CLEAR TYPEAHEAD
ENDIF
IF ( lYesNo .OR. lWait .OR. LEN(aItems)>0 ) .AND. !DC_Gui() .AND. !DC_MsgBoxGui()
IF LEN( aMessage ) > 0
AADD(aMessage,' ')
ENDIF
AADD(aMessage,' ')
AADD(aMessage,' ')
FOR i := 1 TO LEN(aItems)-2
AADD(aMessage,' ')
NEXT
ENDIF
nWidth := 0
FOR i := 1 TO LEN(aMessage)
nTextWidth := DC_GraQueryTextBox(aMessage[i],cFont)[1]
nTextWidth /= DC_GetOptDefault()[nGETOPT_COLPIXELS]
nWidth := MAX( nWidth, nTextWidth )
NEXT
FOR i := 1 TO LEN(aItems)
nTextWidth := DC_GraQueryTextBox(aItems[i],cFont)[1]
nTextWidth /= DC_GetOptDefault()[nGETOPT_COLPIXELS]
nWidth := MAX( nWidth, nTextWidth )
NEXT
nWidth := MAX(nWidth,LEN(cTitle)+4)
IF !DC_Gui() .AND. !DC_MsgBoxGui()
nRow := IIF( nRow <> 0, nRow,INT( (DC_Maxrow()-LEN(aMessage)) /2 -1 ) )
nCol := IIF( nCol <> 0 ,nCol,INT( ( DC_Maxcol()-nWidth )/2 - 1 ) )
DC_InkeyRele(0)
nCursor := SET(_SET_CURSOR,0)
cSaveColor := SETCOLOR()
lPrint := SET(_SET_PRINTER,.f.)
lConsole := SET(_SET_CONSOLE,.t.)
cDevice := SET(_SET_DEVICE,'SCREEN')
IF lYesNo .AND. DC_MsgBoxYesNo()
IF nChoice # 2
cColor1 := 'W/G'
cColor2 := 'W+/G'
ELSE
cColor1 := 'W/R'
cColor2 := 'W+/R'
ENDIF
cSaveScreen := DC_Explode( nRow, nCol, nRow+LEN(aMessage)+ ;
IIF(Empty(aItems),1,2), nCol+nWidth+4, ;
cColor1, cColor2,,cTitle )
ELSE
cSaveScreen := DC_EXPL( nRow, nCol, nRow+LEN(aMessage)+IIF(Empty(aItems),1,2),;
nCol+nWidth+4, cTitle )
ENDIF
FOR i := 1 TO LEN(aMessage)
@ nRow+i, nCol+2 SAY aMessage[i]
NEXT
ENDIF
DO CASE
CASE lWait .AND. LEN(aItems)=0 .AND. nSeconds=0 .AND. !DC_Gui() .AND. !DC_MsgBoxGui()
nYesNoCol := nCol + INT( ( nWidth-10 )/2 - 1 )
lYesNo := DC_OK( nRow + LEN(aMessage) - 2, nYesNoCol, nChoice, .t. )
CASE lYesNo .OR. lWait .OR. Len(aItems)>0
IF DC_Gui() .OR. DC_MsgBoxGui()
@ 1,1 DCSTATIC TYPE nIconType SIZE 5,1.8 CAPTION nIcon
IF lYesNo
IF nWidth < 25
nWidth := 25
ENDIF
ELSE
IF nWidth < 20
nWidth := 20
ENDIF
ENDIF
IF !Empty(cFont)
nCharHeight := DC_GraQueryTextBox('test',cFont)[2]
ELSE
nCharHeight := DC_GetOptDefault()[nGETOPT_ROWPIXELS]
ENDIF
nCharHeight /= DC_GetOptDefault()[nGETOPT_ROWPIXELS]
nLine := 3.5 + nCharHeight
FOR i := 1 TO LEN(aMessage)
@ nLine, 1 DCSAY aMessage[i] FONT cFont SIZE 0
IF Valtype(aColor) == 'A'
ATail(GetList)[aGETLIST_COLOR] := aColor
ENDIF
nLine += nCharHeight
NEXT
nLine++
IF Empty(nChoice)
nChoice := 1
ENDIF
nColumn := 1
IF Empty(aButtSize)
nButtHeight := nCharHeight + .4
nButtWidth := 0
FOR i := 1 TO LEN(aItems)
nTextWidth := DC_GraQueryTextBox(aItems[i],cFont)[1]
nTextWidth /= DC_GetOptDefault()[nGETOPT_COLPIXELS]
nButtWidth := MAX( nButtWidth, nTextWidth+3 )
NEXT
lPixel := .f.
ELSE
nButtHeight := aButtSize[2]
nButtWidth := aButtSize[1]
lPixel := .t.
nLine-- // PC CAW 06-12-12 if button size provided, one extra line was inserted
nLine *= DC_GetOptDefault()[nGETOPT_ROWPIXELS]
ENDIF
IF LEN(aItems) > 0 .AND. lHorizButtons // PC CAW 06-12-12 begin // need to use static for centering in horizontal mode only
nColumn := 0
@ nLine,0 DCSTATIC TYPE XBPSTATIC_TYPE_TEXT ;
SIZE (nButtWidth * len(aItems)) + (IIF( lPixel,10,1.4 )*(len(aItems)-1)), nButtHeight+.5 OBJECT o_Static ;
_PIXEL lPixel
ENDIF // PC CAW 06-12-12 end
FOR i := 1 TO Len(aItems)
cPrompt := Alltrim(aItems[i])
IF '~' $ cPrompt
cKey := Substr(cPrompt,At('~',cPrompt)+1,1)
ELSEIF '&' $ cPrompt
cKey := Substr(cPrompt,At('&',cPrompt)+1,1)
ELSE
cKey := Substr(cPrompt,1,1)
ENDIF
IF i = 1
nTabGroup := XBP_BEGIN_GROUP
ELSEIF i = Len(aItems)
nTabGroup := XBP_END_GROUP
ELSE
nTabGroup := XBP_WITHIN_GROUP
ENDIF
IF !Empty(aItems[i]) .AND. !aItems[i] == '@'
IF lHorizButtons // PC CAW 06-12-12 added for horizontal buttons - begin - to allow centering
@ .2, nColumn DCPUSHBUTTON CAPTION aItems[i] SIZE nButtWidth, nButtHeight ;
ACTION _ActionBlock(i,@nChoice,@cHotKey,GetList,cKey) ;
EVAL _EvalBlock(i,nChoice) ;
_PIXEL lPixel ;
PARENT o_Static ;
TABSTOP ;
FONT cFont ;
TABGROUP nTabGroup ;
ACCELKEY { DC_KeyTran(Asc(Lower(cKey))), DC_KeyTran(Asc(Upper(cKey))) }
ELSE // PC CAW 06-12-12 added for horizontal buttons - end
@ nLine, nColumn DCPUSHBUTTON CAPTION aItems[i] SIZE nButtWidth, nButtHeight ; // original code
ACTION _ActionBlock(i,@nChoice,@cHotKey,GetList,cKey) ;
EVAL _EvalBlock(i,nChoice) ;
_PIXEL lPixel ;
TABSTOP ;
FONT cFont ;
TABGROUP nTabGroup ;
ACCELKEY { DC_KeyTran(Asc(Lower(cKey))), DC_KeyTran(Asc(Upper(cKey))) }
ENDIF
ENDIF
IF lHorizButtons
IF lPixel
nColumn += nButtWidth + 10
ELSE
nColumn += nButtWidth + 1.4
ENDIF
ELSE
IF lPixel
nLine += nButtHeight + 10
ELSE
nLine += nButtHeight +.2
ENDIF
ENDIF
NEXT
l_YesNo := lYesNo
IF lYesNo .OR. Empty(aItems)
@ nLine,0 DCSTATIC TYPE XBPSTATIC_TYPE_TEXT ;
SIZE IIF( lYesNo,20.6,10 ), 1.7 OBJECT o_Static ;
_PIXEL lPixel
ENDIF
IF lYesNo
IF nChoice = 2
lYesNo := .f.
ENDIF
lAction := .f.
@ .2,.6 DCPUSHBUTTON CAPTION DC_LangMsg(DCMSG_YES) ;
SIZE 9,1.3 ;
PARENT o_Static ;
TABSTOP ;
TABGROUP XBP_BEGIN_GROUP ;
OBJECT oYes ;
ACTION {||lAction := .t., lYesNo := .t., DC_ReadGuiEvent(DCGUI_EXIT_OK,GetList)} ;
EVAL {|o|IIF( lYesNo, SetAppFocus(o),nil ) }
@ .2,11.4 DCPUSHBUTTON CAPTION DC_LangMsg(DCMSG_NO) ;
SIZE 9,1.3 ;
PARENT o_Static ;
TABGROUP XBP_END_GROUP ;
TABSTOP ;
OBJECT oNo ;
ACTION {||lAction := .t., lYesNo := .f., DC_ReadGuiEvent(DCGUI_EXIT_ABORT,GetList)} ;
EVAL {|o|IIF( lYesNo, nil, SetAppFocus(o) ) }
ELSEIF Empty(aItems)
@ .2, .6 DCPUSHBUTTON CAPTION DC_LangMsg(DCMSG_OK) ;
TABSTOP ;
SIZE 9,1.3 ;
PARENT o_Static ;
OBJECT oOk ;
ACTION {||PostAppEvent( xbeP_Close,nil,nil,oDlg )} ;
EVAL {|o|SetAppFocus(o)}
ENDIF
IF !Empty(nRow) .AND. !Empty(nCol)
DCGETOPTIONS NOMAXBUTTON NOMINBUTTON NORESIZE ;
WINDOWROW nRow ;
WINDOWCOL nCol ;
HIDE ;
_ALWAYS lAlwaysOnTop
ELSE
DCGETOPTIONS NOMAXBUTTON NOMINBUTTON NORESIZE ;
HIDE ;
_ALWAYS lAlwaysOnTop
ENDIF
GetOptions[lGETOPT_PIXEL] := .f.
GetOptions[nGETOPT_BUTTONALIGN] := DCGUI_BUTTONALIGN_CENTER
DCREAD GUI FIT MODAL TITLE cTitle OPTIONS GetOptions ;
TIMEOUT nSeconds ;
HANDLER dlgHandler REFERENCE aLocals ;
PARENT @oDlg ;
_NOAUTORESTORE lNoRestore ;
CLEAREVENTS ;
;// EXPRESS ;
TO lOutput ;
OWNER oOwner ;
EVAL {|o|;
DC_CenterObject(o, oOwner), ;
IIF(lYesNo .OR. Empty(aItems) .OR. lHorizButtons,_CenterStatic(o, aLocals),nil), ; // PC 06-12-12 added to allow centering of horizontal buttons when array presented
o:Show(), ;
IIF(Valtype(bEval)=='B',Eval(bEval,o),nil)}
IF !lOutput
nChoice := 0
ENDIF
IF lAction
lYesNo := lOutput
ENDIF
ELSE
lYesNo := ;
DC_YESNO( nRow + LEN(aMessage) - 2, nYesNoCol, nChoice, .t., cMenuName )
ENDIF
CASE LEN(aItems)>0
aChoice := DC_MSGITEMS( nRow + LEN(aMessage) - LEN(aItems), nCol, ;
nChoice, aItems, aMenuId, cMenuName )
nChoice := aChoice[2]
cHotKey := aChoice[1]
lYesNo := LASTKEY()#27
CASE !DC_Gui() .AND. !DC_MsgBoxGui()
DC_INKEYRELE(0)
DC_INKEY(,nSeconds)
lYesNo := UPPER(CHR(LASTKEY()))='Y'
ENDCASE
IF !DC_Gui() .AND. !DC_MsgBoxGui()
DC_IMPL( cSaveScreen )
DC_INKEYRELE(0)
SET(_SET_CURSOR,nCursor)
SET(_SET_PRINTER,lPrint)
SET(_SET_DEVICE,cDevice)
SET(_SET_CONSOLE,lConsole)
SETCOLOR( cSaveColor )
ELSE
// DC_ClearEvents()
ENDIF
IF Valtype(oAppFocus) = 'O'
SetAppFocus(oAppFocus)
ENDIF
IF l_EscHit // .OR. !lOutput
lYesNo := .f.
nChoice := 0
ENDIF
RETURN lYesNo