// graphics4- // // This program demonstrates the use of polygons on a form. program graphics4; #linker( "comdlg32.lib" ) #linker( "comctl32.lib" ) ?@NoDisplay := true; ?@NoStackAlign := true; #includeOnce( "stdlib.hhf" ) #includeOnce( "howl.hhf" ) const applicationName := "Graphics #4"; formX := w.CW_USEDEFAULT; // Let Windows position this guy formY := w.CW_USEDEFAULT; formW := 600; formH := 600; // Forward declarations for the onClick widgetProcs that we're going to // call when an event occurs. proc hideShowPolygon :widgetProc; @forward; proc movePolygon :widgetProc; @forward; proc resizePolygon :widgetProc; @forward; proc changeHeight :widgetProc; @forward; proc changeWidth :widgetProc; @forward; proc colorPolygon :widgetProc; @forward; proc onClick :widgetProc; @forward; proc onQuit :widgetProc; @forward; // Here's the main form definition for the app: wForm( mainAppWindow ); var showState :boolean; align(4); wPolygon ( polygon1, 10, 10, 200, 200, RGB( 0, 0, 0 ), RGB( 255, 255, 255 ), howl.bkgColor_g ) wPolygon ( polygon2, 10, 210, 200, 200, RGB( 0, 0, 0 ), RGB( 255, 0, 0 ), howl.transparent_g, 0, 0, 100,0, 100, 100, 0,100 ) wPolygon ( polygon3, 10, 210, 200, 200, RGB( 0, 0, 0 ), RGB( 0, 255, 0 ), howl.transparent_g, 0,0, 50,0, 50, 50 ) wPolygon ( polygon4, 10, 210, 200, 200, RGB( 0, 0, 0 ), RGB( 0, 0, 255 ), howl.transparent_g, 50,50, 100,50, 100, 100 ) wPushButton ( button2, // Field name in mainWindow object "Hide polygon", // Caption for push button 250, // x position 10, // y position 175, // width 25, // height hideShowPolygon // initial "on click" event handler ) wPushButton ( button3, // Field name in mainWindow object "Move Polygon", // Caption for push button 250, // x position 40, // y position 175, // width 25, // height movePolygon // initial "on click" event handler ) wPushButton ( button4, // Field name in mainWindow object "Resize Polygon", // Caption for push button 250, // x position 70, // y position 175, // width 25, // height resizePolygon // initial "on click" event handler ) wPushButton ( button5, // Field name in mainWindow object "Change width", // Caption for push button 250, // x position 100, // y position 175, // width 25, // height changeWidth // initial "on click" event handler ) wPushButton ( button6, // Field name in mainWindow object "Change height", // Caption for push button 250, // x position 130, // y position 175, // width 25, // height changeHeight // initial "on click" event handler ) wPushButton ( button7, // Field name in mainWindow object "Change Color", // Caption for push button 250, // x position 160, // y position 175, // width 25, // height colorPolygon // initial "on click" event handler ) // Place a quit button in the lower-right-hand corner of the form: wPushButton ( quitButton, // Field name in mainWindow object "Quit", // Caption for push button 450, // x position 525, // y position 125, // width 25, // height onQuit // "on click" event handler ) endwForm // Must invoke the following macro to emit the code generated by // the wForm macro: mainAppWindow_implementation(); // The colorPolygon widget proc will change the foreground and background color. proc colorPolygon:widgetProc; begin colorPolygon; mov( mainAppWindow.polygon1, esi ); (type wPolygon_t [esi]).get_lineColor(); if( eax = RGB( 0, 0, 0 )) then (type wPolygon_t [esi]).set_lineColor( RGB( 0, 255, 0 )); (type wPolygon_t [esi]).set_fillColor( RGB( 255, 0, 0 )); else (type wPolygon_t [esi]).set_lineColor( RGB( 0, 0, 0 )); (type wPolygon_t [esi]).set_fillColor( RGB( 255, 255, 255 )); endif; end colorPolygon; // The resizePolygon widget proc will resize label1 between widths 150 and 200. proc resizePolygon:widgetProc; begin resizePolygon; mov( mainAppWindow.polygon1, esi ); (type wPolygon_t [esi]).get_width(); if( eax = 200 ) then stdout.put( "Resizing polygon to width/height 150" nl ); (type wPolygon_t [esi]).resize( 150, 150 ); else stdout.put( "Resizing label to width/height 200" nl ); (type wPolygon_t [esi]).resize( 200, 200 ); endif; end resizePolygon; // The changeWidth widget proc will set the polygon between widths 150 and 200. proc changeWidth:widgetProc; begin changeWidth; mov( mainAppWindow.polygon1, esi ); (type wPolygon_t [esi]).get_width(); if( eax = 200 ) then stdout.put( "Resizing polygon to width 150" nl ); (type wPolygon_t [esi]).set_width( 150 ); else stdout.put( "Resizing label to width 200" nl ); (type wPolygon_t [esi]).set_width( 200 ); endif; end changeWidth; // The changeHeight widget proc will set the polygon between Heights 150 and 200. proc changeHeight:widgetProc; begin changeHeight; mov( mainAppWindow.polygon1, esi ); (type wPolygon_t [esi]).get_height(); if( eax = 200 ) then stdout.put( "Resizing polygon to height 150" nl ); (type wPolygon_t [esi]).set_height( 150 ); else stdout.put( "Resizing label to height 200" nl ); (type wPolygon_t [esi]).set_height( 200 ); endif; end changeHeight; // The movePolygon widget proc will move label // between y positions 10 and 40. proc movePolygon:widgetProc; begin movePolygon; mov( mainAppWindow.polygon1, esi ); (type wPolygon_t [esi]).get_y(); if( eax = 10 ) then stdout.put( "Moving polygon to y-position 40" nl ); (type wPolygon_t [esi]).set_y( 40 ); else stdout.put( "Moving polygon to y-position 10" nl ); (type wPolygon_t [esi]).set_y( 10 ); endif; end movePolygon; // The hideShowPolygon widget proc will hide and show polygon1. proc hideShowPolygon:widgetProc; begin hideShowPolygon; mov( thisPtr, esi ); if( mainAppWindow.showState ) then (type wPushButton_t [esi]).set_text( "Hide Polygon" ); mov( false, mainAppWindow.showState ); stdout.put( "Showing polygon 1" nl ); mov( mainAppWindow.polygon1, esi ); (type wPolygon_t [esi]).show(); else (type wPushButton_t [esi]).set_text( "Show Polygon" ); mov( true, mainAppWindow.showState ); stdout.put( "Hiding polygon 1" nl ); mov( mainAppWindow.polygon1, esi ); (type wPolygon_t [esi]).hide(); endif; end hideShowPolygon; // Here's the onClick event handler the graphic object: proc onClick:widgetProc; begin onClick; stdout.put( "Clicked on graphic object" nl ); mov( thisPtr, esi ); (type wPolygon_t [esi]).set_lineColor( RGB( 0, 0, 255 )); (type wPolygon_t [esi]).set_fillColor( RGB( 255, 0, 255 )); end onClick; // Here's the onClick event handler for our quit button on the form. // This handler will simply quit the application: proc onQuit:widgetProc; begin onQuit; // Quit the app: w.PostQuitMessage( 0 ); end onQuit; // We'll use the main application form's onCreate method to initialize // the various buttons on the form. // // This could be done in appStart, but better to leave appStart mainly // as boilerplate code. Also, putting this code here allows us to use // "this" to access the mainAppWindow fields (a minor convenience). method mainAppWindow_t.onCreate; readonly polyList :w.POINT[] := [ w.POINT:[0,0], w.POINT:[100,0], w.POINT:[100, 20], w.POINT:[10,20], w.POINT:[150,150], w.POINT:[50,150] ]; begin onCreate; // Initialize the showState data field: mov( false, this.showState ); // Set up the polgon points: mov( mainAppWindow.polygon1, esi ); (type wPolygon_t [esi]).set_points( @elements( polyList ), &polyList ); // Install onClick handler for the graphic object: (type wPolygon_t [esi]).set_onClick( &onClick ); // We have to redraw the last three polygons because they overlap. mov( mainAppWindow.polygon2, esi ); w.InvalidateRect( (type wBase_t [esi]).handle, NULL, false );; mov( mainAppWindow.polygon3, esi ); w.InvalidateRect( (type wBase_t [esi]).handle, NULL, false );; mov( mainAppWindow.polygon4, esi ); w.InvalidateRect( (type wBase_t [esi]).handle, NULL, false );; end onCreate; /////////////////////////////////////////////////////////////////////////////// // // // The following is mostly boilerplate code for all apps (about the only thing // you would change is the size of the main app's form) // // /////////////////////////////////////////////////////////////////////////////// // // When the main application window closes, we need to terminate the // application. This overridden method handles that situation. Notice the // override declaration for onClose in the wForm declaration given earlier. // Without that, mainAppWindow_t would default to using the wVisual_t.onClose // method (which does nothing). method mainAppWindow_t.onClose; begin onClose; // Tell the winmain main program that it's time to terminate. // Note that this message will (ultimately) cause the appTerminate // procedure to be called. w.PostQuitMessage( 0 ); end onClose; // When the application begins execution, the following procedure // is called. This procedure must create the main // application window in order to kick off the execution of the // GUI application: procedure appStart; begin appStart; push( esi ); // Create the main application window: mainAppWindow.create_mainAppWindow ( applicationName, // Window title w.WS_EX_CONTROLPARENT, // Need this to support TAB control selection w.WS_OVERLAPPEDWINDOW, // Style NULL, // No parent window formX, // x-coordinate for window. formY, // y-coordinate for window. formW, // Width formH, // Height howl.bkgColor_g, // Background color true // Make visible on creation ); mov( esi, pmainAppWindow ); // Save pointer to main window object. pop( esi ); end appStart; // appTerminate- // // Called when the application is quitting, giving the app a chance // to clean up after itself. // // Note that this is called *after* the mainAppWindow_t.onClose method // executes (indeed, mainAppWindow_t.onClose, by posting the quit message, // is what actually causes the program to begin terminating, which leads // to the execution of this procedure). procedure appTerminate; begin appTerminate; // Clean up the main application's form. // Note that this will recursively clean up all the widgets on the form. mainAppWindow.destroy(); end appTerminate; // appException- // // Gives the application the opportunity to clean up before // aborting when an unhandled exception comes along: procedure appException( theException:dword in eax ); begin appException; raise( eax ); end appException; // The main program for a HOWL application must simply // call the HowlMainApp procedure. begin graphics4; // Set up the background and transparent colors that the // form will use when registering the window_t class: w.GetSysColor( w.COLOR_MENU ); mov( eax, howl.bkgColor_g ); or( $FF00_0000, eax ); mov( eax, howl.transparent_g ); w.CreateSolidBrush( howl.bkgColor_g ); mov( eax, howl.bkgBrush_g ); HowlMainApp(); // Delete the brush we created earlier: w.DeleteObject( howl.bkgBrush_g ); end graphics4;