// button2- // // This program demonstrates changing a button's caption and other attributes // under program control, program button2; #linker( "comdlg32.lib" ) #linker( "comctl32.lib" ) ?compileAll := true; ?@NoDisplay := true; ?@NoStackAlign := true; #includeOnce( "stdlib.hhf" ) #includeOnce( "howl.hhf" ) const applicationName := "Button #2"; formX := w.CW_USEDEFAULT; // Let Windows position this guy formY := w.CW_USEDEFAULT; formW := 600; formH := 600; static align( 4 ); bkgBrush_g :dword; bkgColor_g :dword; // Forward declarations for the onClick widgetProcs that we're going to // call when a button is pressed. proc onSetFocus1:widgetProc; @forward; proc onKillFocus1:widgetProc; @forward; proc onClickChange1:widgetProc; @forward; proc onClickChange2:widgetProc; @forward; proc onQuit:widgetProc; @forward; // Here's the main form definition for the app: wForm( mainAppWindow ); wPushButton ( button1, // Field name in mainWindow object "Press to change", // Caption for push button 10, // x position 10, // y position 125, // width 25, // height onClickChange1 // 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 onSetFocus and onKillFocus widgetProcs simply print to the console // what has happened. proc onSetFocus1:widgetProc; begin onSetFocus1; stdout.put( "Set focus to button 1" nl ); end onSetFocus1; proc onKillFocus1:widgetProc; begin onKillFocus1; stdout.put( "Shifted focus from button 1" nl ); end onKillFocus1; // Here's 1 of 2 onClick handlers for button1. This widgetProc // changes the caption to "Restore caption" and sets the // onClick pointer to point at the second onClick handler. proc onClickChange1:widgetProc; var curCaption :string; curCapBuf :char[256]; begin onClickChange1; str.init( curCapBuf, @size( curCapBuf )); mov( eax, curCaption ); mov( thisPtr, esi ); // ESI already contains this, but just in case... // Print the current caption to the console window: (type wPushButton_t [esi]).get_text( curCaption ); stdout.put( "Current caption1: ", curCaption, nl ); // Change the caption: (type wPushButton_t [esi]).set_text( "Restore original" ); // Point the onClick handler at onClickChange2: (type wPushButton_t [esi]).set_onClick( &onClickChange2 ); // Print the new caption to the console window: (type wPushButton_t [esi]).a_get_text(); stdout.put( "New caption1: ", (type string eax), nl nl ); str.free( eax ); end onClickChange1; // Here's 2 of 2 onClick handlers for button1. This widgetProc // changes the caption back to "Restore caption" and sets the // onClick pointer to point at the first onClick handler. proc onClickChange2:widgetProc; var curCaption :string; curCapBuf :char[256]; begin onClickChange2; str.init( curCapBuf, @size( curCapBuf )); mov( eax, curCaption ); mov( thisPtr, esi ); // ESI already contains this, but just in case... // Print the current caption to the console window: (type wPushButton_t [esi]).get_text( curCaption ); stdout.put( "Current caption2: ", curCaption, nl ); // Change the caption: (type wPushButton_t [esi]).set_text( "Press to change" ); // Point the onClick handler at onClickChange1: (type wPushButton_t [esi]).set_onClick( &onClickChange1 ); // Print the new caption to the console window: (type wPushButton_t [esi]).a_get_text(); stdout.put( "New caption2: ", (type string eax), nl nl ); str.free( eax ); end onClickChange2; // 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; // The following gets called immediately after the main application // window is created. It must be provided, even if it does nothing. method mainAppWindow_t.onCreate; begin onCreate; // Lets set up the button1's onSetFocus and onKillFocus event handlers: mov( this.button1, esi ); (type wPushButton_t [esi]).set_onSetFocus( &onSetFocus1 ); (type wPushButton_t [esi]).set_onKillFocus( &onKillFocus1 ); 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: w.GetSysColor( w.COLOR_MENU ); mov( eax, bkgColor_g ); w.CreateSolidBrush( eax ); mov( eax, bkgBrush_g ); 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, // Form x-coordinate formY, // Form y-coordinate formW, // Width formH, // Height 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(); w.DeleteObject( bkgBrush_g ); 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 button2; HowlMainApp(); end button2;