Before I get heavily embroiled in PBCC V5, and can no longer see the wood for the trees, I must say that it is really very good indeed.
A non-windows programmer (as I sometimes wish I still was) can create a whole GUI application inside a GRAPHIC WINDOW without a thought for Windows - well maybe a couple of API calls, but without the old familiar Windows program structure. In other words, you can concentrate on the job in hand, not on fighting the whole M$ empire.
FWIW, here is my first attempt, please advise improvements:
A non-windows programmer (as I sometimes wish I still was) can create a whole GUI application inside a GRAPHIC WINDOW without a thought for Windows - well maybe a couple of API calls, but without the old familiar Windows program structure. In other words, you can concentrate on the job in hand, not on fighting the whole M$ empire.
FWIW, here is my first attempt, please advise improvements:
Code:
' PBCC V5 try-out program by Chris Holbrook Oct 2008 ' just to experiment with GRAPHIC WINDOW commands ' and to discover that you don't need to know Windows programming ' to make it work ' #INCLUDE "WIN32API.INC" ' <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ' graphic "windlet" stack stuff ' these two arrays work together ' first contains bitmap strings of graphics windows ' second contains coordinates of overlaid graphics objects GLOBAL grstack() AS STRING GLOBAL grectstack() AS QUAD '------------------------------------------------------------------------- ' push a windlet on th stack MACRO mpushgr ( r ) MACROTEMP i, q LOCAL i AS LONG LOCAL q AS QUAD q = MAK(QUAD,MAK(DWORD,r.nleft, r.ntop),MAK(DWORD,r.nright, r.nbottom)) i = UBOUND(grstack) + 1 REDIM grstack(0 TO i) AS GLOBAL STRING GRAPHIC GET BITS TO grstack(i) REDIM grectstack(0 TO i) AS GLOBAL QUAD grectstack(i) = q END MACRO '------------------------------------------------------------------------- ' pop a windlet from the stack MACRO mpopgr MACROTEMP i LOCAL i AS LONG i = UBOUND(grstack) GRAPHIC SET BITS grstack(i) REDIM grstack(0 TO i-1) AS GLOBAL STRING REDIM grectstack(0 TO i-1) AS GLOBAL QUAD END MACRO '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> '------------------------------------------------------------------------- ' display a vertical menu in the current graphic window ' a selection can be made by kbd or mouse ' a mouse click outside the menu will also return to the caller ' The returned value is a QUAD integer which contains ' the selection (if any), together with the click coordinates FUNCTION vmenu (hGW AS DWORD, x AS LONG, y AS LONG, s AS STRING) AS QUAD LOCAL clicked, clickX, clickY, i, j, chigh, cwide, cpxwide, cpxhigh, lchoice, noptions, pxwide, pxhigh AS LONG LOCAL skey AS STRING LOCAL pt AS POINTAPI LOCAL r AS RECT ' noptions = PARSECOUNT(s) FOR i = 1 TO noptions j = LEN(PARSE$(s,i)) IF j > cwide THEN cwide = j NEXT GRAPHIC CHR SIZE TO cpxwide, cpxhigh pxwide = cwide * cpxwide pxhigh = noptions * cpxhigh r.nleft = x + cpxwide r.ntop = y + cpxhigh r.nright = x + pxwide + cpxwide*3 r.nbottom = y + pxhigh+ cpxhigh*2 ' push the gr screen on entry on the GR stack mpushgr ( r) r.nleft = x r.ntop = y r.nright = x + pxwide + cpxwide*2 r.nbottom = y + pxhigh + cpxhigh ' push the gr screen on entry on the GR stack mpushgr(r) GRAPHIC BOX (x, y) - (x + pxwide + cpxwide*2, y + pxhigh+ cpxhigh), 20, %BLUE, %WHITE FOR i = 1 TO noptions GRAPHIC SET POS (x + cpxwide, y + cpxhigh/2 + (i-1)*cpxhigh ) IF lchoice = i THEN GRAPHIC COLOR %RED, %WHITE ELSE GRAPHIC COLOR 0, %WHITE END IF GRAPHIC PRINT PARSE$(s, i) NEXT skey = "" WHILE skey <> $ESC IF LEN(skey) = 1 THEN SELECT CASE skey CASE "U"' up DECR lchoice IF lchoice < 1 THEN lchoice = noptions CASE "D"'down INCR lchoice IF lchoice > noptions THEN lchoice = 1 END SELECT END IF FOR i = 1 TO noptions GRAPHIC SET POS (x + cpxwide, y + cpxhigh/2 + (i-1)*cpxhigh ) IF lchoice = i THEN GRAPHIC COLOR %BLACK,&HD0D0D0 ELSE GRAPHIC COLOR 0, %WHITE END IF GRAPHIC PRINT PARSE$(s, i) NEXT GRAPHIC INKEY$ TO skey IF LEN(skey) THEN ? STR$(LEN(skey)) IF LEN(skey) = 0 THEN getcursorpos BYVAL VARPTR(pt) screentoclient(hGW, BYVAL VARPTR(pt)) ' is the cursor position inside the menu box? IF (pt.x > x + cpxwide) AND (pt.x < x + pxwide + cpxwide*3) THEN IF ( pt.y > (y + cpxhigh/2)) AND (pt.y < y + pxhigh+ cpxhigh*1.5) THEN lchoice = (pt.y - y - cpxhigh/2) / cpxhigh INCR lchoice END IF END IF END IF GRAPHIC WINDOW CLICK TO clicked, clickX, clickY IF clicked = 1 THEN FUNCTION = lchoice ' pop the underlying screen off the GR stack mpopgr' pop shadow mpopgr' pop menu FUNCTION = MAK(QUAD, lchoice, MAK(DWORD, clickX, clickY)) EXIT FUNCTION END IF WEND END FUNCTION '------------------------------------------------------- ' draw a CLOSEME box on the current graphic window ' parameter is # of pixels on each side of the box ' suggest 15 or 10 (not less) here ' and return its coordinates in a QUAD integer FUNCTION DrawCloseMeBox ( l AS LONG)AS QUAD LOCAL i, x, y, xofs AS LONG LOCAL r AS rect LOCAL dw AS DWORD xofs = l \ 5 ' offset of X inside box in pixels ' get the width of the current object from the rectstack array i = UBOUND(grectstack) dw = LO(DWORD,grectstack(i)) Y = HI(WORD,dw) dw = HI(DWORD,grectstack(i)) X = LO(WORD,dw) ' r.nleft = x - 1.33*l r.ntop = y + l/3 r.nright = x - l/3 r.nbottom = y + (l * 1.33) GRAPHIC BOX (r.nleft, r.ntop) - (r.nright, r.nbottom ), 0, %RED, %RED, 0 GRAPHIC WIDTH 2 GRAPHIC LINE (r.nleft + xofs , r.ntop + xofs) - (r.nright - xofs, r.nbottom - xofs), %WHITE GRAPHIC LINE ( r.nright-xofs, r.ntop +xofs) - (r.nleft + xofs, r.nbottom - xofs), %WHITE ' return the box coordinates an a QUAD FUNCTION = MAK(QUAD, MAK(DWORD,r.nleft, r.ntop),MAK(DWORD,r.nright, r.nbottom)) END FUNCTION '------------------------------------------------------- ' SR to display a message box and wait for a keypress before clearing it ' lots of assumptions, no wordwrap, etc SUB mymsgbox ( msg AS STRING) LOCAL clicked, clickX, clickY,l, x, y, pxcwide, pxchigh AS LONG LOCAL r AS rect GRAPHIC WINDOW CLICK TO clicked, clickX, clickY l = LEN(msg) GRAPHIC GET CLIENT TO x, y GRAPHIC CHR SIZE TO pxcwide, pxchigh r.nleft = ( x - l*pxcwide - 2*pxcwide)\2 r.ntop = ( y - 2*pxchigh) \ 2 r.nright = r.nleft + pxcwide*2 + pxcwide*l r.nbottom = r.ntop + 2 * pxchigh mpushgr(r) GRAPHIC BOX (r.nleft, r.ntop) - (r.nright, r.nbottom), 10, -1, &Hd0d0ff GRAPHIC SET POS (r.nleft + pxcwide, r.ntop + pxchigh/2) GRAPHIC COLOR %BLUE, &Hd0d0ff GRAPHIC PRINT msg drawclosemebox (10) WHILE clicked = 0 GRAPHIC WINDOW CLICK TO clicked, clickX, clickY SLEEP 10 WEND mpopgr END SUB '------------------------------------------------------- ' CLOSEME returns TRUE if the menucoords place ' the click in the Closemecoords box FUNCTION CLOSEME ( menucoords AS QUAD, closemecoords AS QUAD) AS LONG LOCAL x, y AS LONG LOCAL r AS RECT LOCAL pt AS POINTAPI LOCAL dw AS LONG dw = HI(DWORD,menucoords) pt.x = LO(WORD,dw): pt.y = HI(WORD,dw) ' dw = LO(DWORD,closemecoords) r.nleft = LO(WORD,dw): r.ntop = HI(WORD, dw) dw = HI(DWORD,closemecoords) r.nright = LO(WORD, dw): r.nbottom = HI(WORD, dw) ' FUNCTION = ptinrect( BYVAL VARPTR(r), pt.x, pt.y) END FUNCTION '---------------------------------------------------------- FUNCTION ConsoleHandler(BYVAL dwEvent AS DWORD) AS LONG 'Alt + F4 not trapped here, Ctrl-C not working either SELECT CASE dwEvent CASE %CTRL_BREAK_EVENT PRINT "Ctrl-Break pressed" CASE %CTRL_CLOSE_EVENT PRINT "[x] Close clicked" CASE %CTRL_LOGOFF_EVENT PRINT "User logging off or restarting" CASE %CTRL_SHUTDOWN_EVENT PRINT "System shutting down" END SELECT SLEEP 500 END FUNCTION '------------------------------------------------------- FUNCTION PBMAIN () AS LONG LOCAL bigx, bigy, thisW, thisH AS LONG LOCAL menuchoice, closemecoords AS QUAD LOCAL r AS RECT LOCAL dw AS DWORD LOCAL smenu AS STRING LOCAL hGW AS DWORD SetConsoleCtrlHandler CODEPTR(ConsoleHandler), 1 DESKTOP GET SIZE TO bigx, bigy thisW = 200: thisH = 200 GRAPHIC WINDOW "", (bigx - thisw)/2, (bigY - thisH)/2, 200, 200 TO hGW GRAPHIC ATTACH hGW, 0 setrect BYVAL VARPTR(r), 0, 0, thisW, thisH mpushgr(r) GRAPHIC BOX (r.nleft, r.ntop) - (r.nright, r.nbottom), 0, -1, %BLUE, 4 GRAPHIC FONT "COURIER NEW", 10, 0 closemecoords = drawclosemebox(15) smenu = "red, blue, green, yellow, white, black" menuchoice = vmenu (hGW, 20, 20, smenu) IF CloseME(menuchoice, closemecoords) THEN mymsgbox("you clicked CLOSEME!") ELSE dw = LO(DWORD, menuchoice) mymsgbox "you chose "+ PARSE$(smenu,dw) END IF mpopgr SetConsoleCtrlHandler CODEPTR(ConsoleHandler), 0 END FUNCTION