Here is the modified sample.
* ----------
FUNCTION DoMnuPrg(PrgName)
MEMVAR gWrkPrgm, gTmpPrgm, gFinish, gNextPrgm, GetList, mPrgmOK, ;
gUserLevel, gPrgmLevel
//030 CLEAR GETS
gTmpPrgm := PrgName
gFinish := .T.
gNextPrgm := gTmpPrgm
mPrgmOK = .F.
ChkPrgmOK() && If ChkPrgmOK = .T.,
IF mPrgmOk && gNextPrgm is return
gUserLevel = gPrgmLevel
ENDIF
RETURN gNextPrgm #include "dcdialog.ch"
#INCLUDE "dctree.CH"
#INCLUDE "appevent.CH"
#INCLUDE "DCBITMAP.CH"
#define MENU_ITEM_DESC 1
#define MENU_ITEM_TYPE 2
#define MENU_ITEM_ACTION 3
#define MENU_ITEM_ACTION_TEXT 4
#define MENU_ITEM_IS_PROGRAM "P"
#define MENU_ITEM_IS_EXECUTABLE "X"
#define MENU_ITEM_IS_SUBMENU "A"
#define CRLF CHR(13)+CHR(10)
#define FILE_Local "LOCAL"
#define FILE_Shared "SHARED"
#define FILE_User "USER"
#DEFINE FALSE .f.
#DEFINE TRUE .t.
#DEFINE COLOR_BLACK GraMakeRGBColor( { 0, 0, 0 } )
#DEFINE COLOR_GREEN GraMakeRGBColor( { 0, 255, 0 } )
#DEFINE COLOR_BLUE GraMakeRGBColor( { 0, 0, 255 } )
#DEFINE COLOR_WHITE GraMakeRGBColor( { 255, 255, 255 } )
#DEFINE COLOR_BROWN GraMakeRGBColor( { 127, 127, 0 } )
#DEFINE COLOR_BUTTONS_FG GraMakeRGBColor( { 0, 0, 0 } )
#DEFINE COLOR_BUTTONS_BG GraMakeRGBColor( { 165, 195, 243 } )
#DEFINE COLOR_SPLITBAR GraMakeRGBColor( { 78, 113, 255 } )
#DEFINE COLOR_BUTTONS_FG_MOUSEOVER GraMakeRGBColor( { 0, 0, 0 } )
#DEFINE COLOR_BUTTONS_BG_MOUSEOVER GraMakeRGBColor( { 248, 186, 104 } )
#DEFINE COLOR_TITLE_FG GraMakeRGBColor( { 255, 255, 255 } )
#DEFINE COLOR_TITLE_BG GraMakeRGBColor( { 78, 113, 255 } )
#DEFINE COLOR_TOGGLE_OUTLOOK_FG GraMakeRGBColor( { 0, 0, 0 } )
#DEFINE COLOR_TOGGLE_OUTLOOK_BG GraMakeRGBColor( { 248, 186, 104 } )
FUNCTION Main()
LOCAL GetList[0], aMenuItems, aButtons, oDlg, oOutlookBar, nEvent, oXbp, mp1, mp2
PUBLIC aKillMnuItm := {}
USE TAXMNU INDEX TAXMNU1 VIA 'DBFNTX' ALIAS 'SysMnu' NEW
USE TAXKEY INDEX TAXKEY1 VIA 'DBFNTX' ALIAS 'SysKey' NEW
aMenuItems := LdMnuStr( 'TAX' )
SYSMNU->(dbCloseArea())
// 'calendar.bmp'
aButtons := { ;
{ 'Accounts Payable', 'AccountsPayable.Exe', '', BITMAP_SCANGLOBAL_M }, ;
{ 'Technical Support', '
http://www.bmsi-fund.com/BMSI-support.aspx', '', 'design.bmp' }, ;
{ 'Payroll 2000', 'Payroll2000.exe', '', 'display.bmp' }, ;
{ 'Cash Receipts', 'CashReceipts.Exe', '', 'copyclip.bmp' }, ;
{ 'Google Search', '
http://www.google.com', '', 'colorset.bmp' }, ;
{ 'Payroll 2000', 'Payroll2000.exe', '', 'display.bmp' }, ;
{ 'Snyffle', '
http://snyffle.com', '', 'expicon.bmp' }, ;
{ 'Taxes && Utilities', 'TAXESANDUTILITIES.Exe', '', 'dialog.bmp' }, ;
{ 'Notepad', 'Notepad.Exe', '', 'editmemo.bmp' } }
DCREAD GUI FIT EVAL {|o| oOutlookBar := OutlookBar():new(o),;
oOutlookBar:menuArray := aMenuItems,oOutlookBar:buttonArray := aButtons, oOutlookBar:create() };
TITLE 'BMSI Outlook Bar Test Program'
/*
oDlg := DC_XbpDialog1():new(,,{100,100},{1000,800})
oDlg:title := 'BMSI Outlook Bar Test Program'
oDlg:taskList := .t.
oDlg:create()
oOutlookBar := OutlookBar():new( oDlg )
oOutlookBar:menuArray := aMenuItems
oOutlookBar:buttonArray := aButtons
oOutlookBar:create()
DO WHILE nEvent # xbeP_Close
nEvent := AppEvent( @mp1, @mp2, @oXbp, .1 )
IF nEvent > 0
oXbp:handleEvent(nEvent,mp1,mp2)
ENDIF
ENDDO
*/
RETURN nil
* ------------
CLASS OutlookBar
EXPORTED:
VAR GetList
VAR menuArray
VAR buttonArray
VAR openBarButton
VAR titleStaticObject
VAR titleStaticCaption
VAR treeRootObject
VAR drawingArea
VAR parentDlg
METHOD init, create
ENDCLASS
* ---------
METHOD OutlookBar:init( oParent )
::parentDlg := oParent
::drawingArea := ::parentDlg:drawingArea
::titleStaticCaption := 'Accounts Payable'
RETURN self
* -----------
METHOD OutlookBar:create() // OutlookBarMenu( oParent, aMenuItems, aButtons )
LOCAL GetList[0], GetOptions, i, oStatic, lBarClosed := .f., oDlg, ;
oDlg1, oStatic2, oStatic3, oSplitBar
DC_BitmapTransparentColor( { 192, 192, 192 } )
@ 0,0 DCSTATIC ;
TYPE XBPSTATIC_TYPE_TEXT ;
OBJECT oStatic ;
SIZE 220, ::drawingArea:currentSize()[2] ;
RESIZE DCGUI_RESIZE_RESIZEONLY_Y ;
COLOR nil, COLOR_BUTTONS_BG
@ 5,5 DCPUSHBUTTONXP ;
OBJECT ::openBarButton ;
CAPTION {||IIF(lBarClosed,'Open','Close') + ' Outlook Bar'} ;
PARENT oStatic ;
SIZE DCGUI_PARENTWIDTH - 10, 25 ;
ACTION {||ToggleBarClosed(@lBarClosed,oDlg,oStatic), DC_GetRefresh(GetList)} ;
RADIUS 6 ;
GRADIENT 3 ;
FONT '10.Arial' ;
COLOR COLOR_TOGGLE_OUTLOOK_FG, COLOR_TOGGLE_OUTLOOK_BG ;
MOUSECOLOR COLOR_TOGGLE_OUTLOOK_FG, COLOR_TOGGLE_OUTLOOK_BG ;
RESIZE DCGUI_RESIZE_REPOSONLY_Y
@ 35,5 DCPUSHBUTTONXP STATIC ;
OBJECT ::titleStaticObject ;
CAPTION ::titleStaticCaption ;
PARENT oStatic ;
SIZE DCGUI_PARENTWIDTH - 10, 30 ;
FONT '12.Arial' ;
COLOR COLOR_TITLE_FG, COLOR_TITLE_BG ;
GRADIENT 2 ;
RESIZE DCGUI_RESIZE_REPOSONLY_Y
@ 70,5 DCTREEROOT ;
OBJECT ::treeRootObject ;
PARENT oStatic ;
SIZE DCGUI_PARENTWIDTH - 10, ::drawingArea:currentSize()[2]/2 - 30 ;
HASLINES ;
HASBUTTONS ;
ITEMSELECTED {|a,b,o|TreeItemSelected(o)} ;
RESIZE DCGUI_RESIZE_REPOSONLY_Y
@ ::drawingArea:currentSize()[2]/2 + 50,5 DCSTATIC TYPE XBPSTATIC_TYPE_TEXT ;
SIZE DCGUI_PARENTWIDTH - 10, ::drawingArea:currentSize()[2]/2 - 80 ;
OBJECT oStatic2 ;
PARENT oStatic ;
RESIZE DCGUI_RESIZE_RESIZEONLY_Y ;
EVAL {|o|o:resize := {|a,b,o|ButtonBarResized(oStatic2,oStatic3)}}
@ ::drawingArea:currentSize()[2] - 35, 5 DCSTATIC TYPE XBPSTATIC_TYPE_TEXT ;
OBJECT oStatic3 ;
SIZE DCGUI_PARENTWIDTH-10, 30 ;
PARENT oStatic
FOR i := 1 TO Len(::buttonArray)
@ (i-1)*35, 0 DCPUSHBUTTONXP ;
CAPTION ::buttonArray[i,1] ;
CARGO ::buttonArray
;
GRADIENT 2 ;
PARENT oStatic2 ;
FONT '10.Arial Bold' ;
SIZE DCGUI_PARENTWIDTH, 35 ;
COLOR COLOR_BUTTONS_FG, COLOR_BUTTONS_BG ;
MOUSECOLOR COLOR_BUTTONS_FG_MOUSEOVER, COLOR_BUTTONS_BG_MOUSEOVER ;
ACTION {|a,b,o|ButtonSelected(o)} ;
RESIZE DCGUI_RESIZE_REPOSONLY_Y ;
BITMAP ::buttonArray[i,4] OFFSET 5
@ 3, (i-1)*28 DCPUSHBUTTONXP ;
BITMAP ::buttonArray[i,4] OFFSET 1 ;
PARENT oStatic3 ;
CARGO ::buttonArray ;
GRADIENT 2 ;
SIZE 26, 26 ;
COLOR COLOR_BUTTONS_FG, COLOR_BUTTONS_BG ;
MOUSECOLOR COLOR_BUTTONS_FG_MOUSEOVER, COLOR_BUTTONS_BG_MOUSEOVER ;
FONT '10.Arial Bold' ;
ACTION {|a,b,o|ButtonSelected(o)} ;
TOOLTIP ::buttonArray[i,1] ;
MOUSESCALE 1.2
NEXT
@ ::drawingArea:currentSize()[2]/2 + 42,5 DCSPLITBAR oSplitBar ;
SIZE DCGUI_PARENTWIDTH-10,6 ;
PARENT oStatic ;
ORIENTATION DCGUI_SPLITBAR_HORIZONTAL ;
PREDECESSOR oStatic2 ;
SUCCESSOR ::treeRootObject ;
COLOR COLOR_SPLITBAR ;
MOVECOLOR COLOR_SPLITBAR ;
RESIZE DCGUI_RESIZE_REPOSONLY_Y
DCGETOPTIONS ;
PIXEL ;
FITPAD 0 ;
RESIZE
DCREAD GUI ;
PARENT ::drawingArea ;
TITLE 'BMSI Outlook Bar Test Program' ;
OPTIONS GetOptions ;
EXIT ;
SAVE
FillTree(::menuArray,::treeRootObject:rootItem)
PostAppEvent(xbeP_Resize,,,oStatic2)
::parentDlg:resize := {|a,b,o,x|x := SetAppFocus(), ;
DC_ReSize(a,b,o,GetList), ;
SetAppFocus(x), ;
o:invalidateRect(), ;
IIF(ProcLine(100)==0,DC_CompleteEvents(),nil), ;
nil }
RETURN nil
* -----------
PROC appsys ; RETURN
* -----------
STATIC FUNCTION FillTree( aMenuItems, oTreeParent )
LOCAL cText, nType, i, oTreeBranch, cType
FOR i := 1 TO Len(aMenuItems)
cText := Alltrim(aMenuItems[i,MENU_ITEM_DESC])
cType := aMenuItems[i,MENU_ITEM_TYPE]
oTreeBranch := oTreeParent:addItem( cText )
oTreeBranch:cargo := aMenuItems
IF cType == 'A'
FillTree( aMenuItems[i,MENU_ITEM_ACTION], oTreeBranch )
ENDIF
NEXT
RETURN nil
* -----------
STATIC FUNCTION TreeItemSelected( oTreeRoot )
LOCAL oTreeBranch, aMenuItem
oTreeBranch := oTreeRoot:getData()
aMenuItem := oTreeBranch:cargo
wtf aMenuItem
IF aMenuItem[2] == 'P'
DCMSGBOX 'You selected: ' + DC_XtoC(aMenuItem[MENU_ITEM_ACTION])
ELSEIF aMenuItem[2] == 'X'
DCMSGBOX 'You selected: ' + DC_XtoC(aMenuItem[MENU_ITEM_ACTION_TEXT])
ENDIF
RETURN nil
* -----------
STATIC FUNCTION ButtonSelected( oButton )
LOCAL oTreeBranch, aItem
aItem := DC_GetCargo(oButton)
wtf aItem
IF Valtype(aItem[2]) == 'B'
Eval(aItem[2])
ELSEIF Valtype(aItem[2]) == 'C'
DC_SpawnUrl(aItem[2])
ENDIF
RETURN nil
* -----------
STATIC FUNCTION ToggleBarClosed( lBarClosed, oDlg, oStatic )
LOCAL aChildList := oStatic:childList(), i, aSize, aPos
lBarClosed := !lBarClosed
FOR i := 2 TO Len(aChildList)
IF lBarClosed
aChildList:hide()
ELSE
aChildList:show()
ENDIF
NEXT
IF lBarClosed
DC_GetCargo(oStatic, { oStatic:currentSize(), oStatic:currentPos() } )
oStatic:setSize( { oStatic:currentSize()[1], aChildList[1]:currentSize()[2]+10 } )
aChildList[1]:setPos( { 5, 5 })
oStatic:setPos( { oStatic:currentPos()[1], oStatic:setParent():currentSize()[2]-oStatic:currentSize()[2]})
ELSE
aSize := DC_GetCargo(oStatic)[1]
aPos := DC_GetCargo(oStatic)[2]
oStatic:setSize(aSize)
aChildList[1]:setPos( { 5, oStatic:currentSize()[2] - aChildList[1]:currentSize()[2] - 5 } )
oStatic:setPos( aPos )
ENDIF
RETURN nil
* -----------
STATIC FUNCTION ButtonBarResized( oStatic2, oStatic3 )
LOCAL aChildList2 := oStatic2:childList(), aChildList3 := oStatic3:childList(), ;
i, oButton2, oButton3, nOffset := 0
oStatic2:lockUpdate(.t.)
oStatic3:lockUpdate(.t.)
FOR i := 1 TO Len(aChildList2)
oButton2 := aChildList2
oButton3 := aChildList3
IF IsClipped(oButton2)
oButton2:hide()
oButton3:show()
oButton3:setPos({nOffset,oButton3:currentPos()[2]})
nOffset += 28
ELSE
oButton2:show()
oButton3:hide()
ENDIF
NEXT
oStatic2:lockUpdate(.f.)
oStatic3:lockUpdate(.f.)
oStatic2:invalidateRect()
oStatic3:invalidateRect()
RETURN nil
* -----------
STATIC FUNCTION IsClipped( oXbp )
RETURN oXbp:currentPos()[2] < 0
* -----------
STATIC FUNCTION LdMnuStr(cMenu)
LOCAL aMenuItems := {}
LOCAL nMenuOpts := 0
LOCAL nMaxActs := 0
LOCAL nItems := 0
LOCAL cMnuStr := ""
LOCAL cThisItem := ""
LOCAL cMenuItem := ""
LOCAL cAction := ""
LOCAL cType := ""
LOCAL j
IF SYSMNU->(DbSeek(UPPER(cMenu))) //037
cMnuStr := RTRIM(RTRIM(SysMnu->MnuGrp1)+;
RTRIM(SysMnu->MnuGrp2)+;
RTRIM(SysMnu->MnuGrp3))
nMaxActs := SysMnu->MnuActs
WHILE ++nItems <= nMaxActs
cThisItem := LEFT(cMnuStr,41)
cMnuStr := SUBSTR(cMnuStr,42)
cAction := ALLTRIM(LEFT(RIGHT(cThisItem,9),8))
cType := RIGHT(cThisItem,1)
IF cType == "M"
cMenuItem := ALLTRIM(ALLTRIM(LEFT(cThisItem,16))+" "+ALLTRIM(SUBSTR(cThisItem,17,15)))
ELSE
cMenuItem := ALLTRIM(SUBSTR(cThisItem,4,29))
ENDIF
// Load Item if not in the Public kill menu item list...
IF ASCAN(M->aKillMnuItm,cAction) == 0
// Override menus here.
IF cMenuItem == "Print Mailing Labels" .AND. ; //053
.t. // FileExists("PRINTMAILINGLABELS.EXE",FILE_Shared) //053
//053
AADD(aMenuItems,{"Print Mailing Labels", ; //053
MENU_ITEM_IS_EXECUTABLE, ; //053
"PRINTMAILINGLABELS.EXE", ; //053
"PRINTMAILINGLABELS.EXE"}) //053
ELSE //053
AADD(aMenuItems,{cMenuItem,cType,cAction,cAction}) //044
ENDIF //053
// Add new menu items here. //053
IF cMenuItem == "Print Budget Reports" //043
IF .t. // FileExists("BDGTRPT.EXE",FILE_Shared) //047
AADD(aMenuItems,{"Export Budget Report", ;
MENU_ITEM_IS_EXECUTABLE,"BDGTRPT.EXE", ;
"BDGTRPT.EXE"}) //044
ENDIF //043
IF .t. // FileExists("BDGDRILLDOWNREPORT.EXE",FILE_Shared) //052
AADD(aMenuItems,{"Budget Drilldown Rpt", ; //052
MENU_ITEM_IS_EXECUTABLE, ; //052
"BDGDRILLDOWNREPORT.EXE", ; //052
"BDGDRILLDOWNREPORT.EXE"}) //052 //044
ENDIF //052
ENDIF //043
IF cMenuItem == "Print Budget Worksheet" //043
IF .t. // FileExists("BDGTWKST.EXE",FILE_Shared) //047
AADD(aMenuItems,{"Export Budget Worksheet", ;
MENU_ITEM_IS_EXECUTABLE,"BDGTWKST.EXE", ;
"BDGTWKST.EXE"}) //044
ENDIF //043
IF .t. // FileExists("BUDGETIMPORT.EXE",FILE_Shared) //051
AADD(aMenuItems,{"Import Budget Worksheet", ; //051
MENU_ITEM_IS_EXECUTABLE,"BUDGETIMPORT.EXE", ; //051
"BUDGETIMPORT.EXE"}) //051
ENDIF //051
ENDIF //043
ENDIF
ENDDO
nMenuOpts := LEN(aMenuItems)
FOR j := 1 TO nMenuOpts
//043 IF aMenuItems[j,MENU_ITEM_TYPE] == MENU_ITEM_IS_PROGRAM //043
IF aMenuItems[j,MENU_ITEM_TYPE] == MENU_ITEM_IS_PROGRAM .OR. ;
aMenuItems[j,MENU_ITEM_TYPE] == MENU_ITEM_IS_EXECUTABLE //043
// No Processing Required...
ELSE
// Load/Process this SubMenu
// Using Recursive Calls to LdMnuStr()
aMenuItems[j,MENU_ITEM_ACTION] := LdMnuStr( aMenuItems[j,MENU_ITEM_ACTION] )
aMenuItems[j,MENU_ITEM_TYPE] := MENU_ITEM_IS_SUBMENU
ENDIF
NEXT
ENDIF
RETURN aMenuItems
/*****
*
* ChkPrgmOK() --> TRUE
*
* Checks for ability and authority to execute the indicated PROGRAM.
*
* Calls ChkPrgAuth()
*
******/
FUNCTION ChkPrgmOK
MEMVAR mPrgmTest, gNextPrgm, mTestPrgm
PRIVATE mPrgmTest := ALLTRIM(gNextPrgm)+"()"
PRIVATE mTestPrgm := ALLTRIM(gNextPrgm)
IF EMPTY(gNextPrgm)
DC_WinAlert("Program not defined in system menu file.")
ELSEIF IsFunction("&mTestPrgm")
wtf gNextPrgm
// ChkPrgAuth(gNextPrgm) // check authority program
ELSE
DC_WinAlert("Program not defined in program library.")
ENDIF
RETURN .t. // ChkPrgmOK
* ----------
FUNCTION FileExists( cFileName, cType ) //073
//073
// Note: Make sure to pass in '.DBF' file extension if not //073
// already part of the file name. //073
//073
LOCAL lExists //073
//073
lExists := FALSE //073
IF cType == FILE_Local .OR. cType == FILE_User //092
IF FILE(cFileName) //073
lExists := TRUE //073
ENDIF //073
ELSE //073
IF FILE(cFileName) //073
lExists := TRUE //073
ENDIF //073
ENDIF //073
//073
RETURN lExists //FileExits //073
* ----------