News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

HOWL has arrived!

Started by Randall Hyde, April 22, 2010, 01:19:59 AM

Previous topic - Next topic

Randall Hyde

Hi All,

I pleased to announce a new addition to the HLA
Standard Library: HOWL - the HLA Object Windows Library.
This is a set of library routines and macros for HLA
that dramatically simplifies Win32 GUI application
development in assembly language.

HOWL, as its name suggests, takes avantage of HLA's
object-oriented programming facilities and powerful
macro facilities to create a new macro-based
"mini-language" that lets you define windows and
forms using a very-high-level-language-like syntax.
For example, to create a form on which you can
attach "widgets" (Windows' controls), you just
write the following two statements

wForm( formName )

endwForm


This, plus some boilerplate code that you cut
and paste for just about every HOWL application,
is all you need to write to bring up a (blank)
window when your application runs.

If you want to add a button to your form, here's
all you need to write:

wForm( mainAppWindow );


   // Place a quit button in the lower-right-hand corner of the form:
   
   wPushButton
   (
      button,            // 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

Note that wForm, wPushButton, and endwForm are
simply macros whose definition is included as
part of the HOWL package. This isn't some magic
new compiler processing this code.

The interesting part is the last argument to the
wPushButton macro: the onQuit event handler.
This is the name of a special "widgetProc"
procedure (that you must write) that will
be called whenever the user presses the
button on the form.  In the example I've copied
the code above from (002_button1.hla, from
the HOWL examples in the HLA examples download),
the onQuit procedure looks like this:

proc onQuit:widgetProc;
begin onQuit;

   // Quit the app:
   
   w.PostQuitMessage( 0 );

end onQuit;


This is the magical part of HOWL. Like Microsoft's
MFC or Borland's VCL, the HOWL library is an
application framework. You specify the widgets
(controls) you want on a form and you specify
various event handler functions ("widgetProc"
procedures) to call when the user interacts
with those widgets and HOWL takes care of the
rest of the work for you. Generally, you
don't have to worry about message processing
loops, WndProcs, or any of the other gory
details that make Win32 assembly language
programming so messy.

If you'd like to check out HOWL's capabilities,
you can view the HOWL documentation on-line
at the following URL:

http://homepage.mac.com/randyhyde/webster.cs.ucr.edu/HighLevelAsm/HLADoc/HLAStdlib/2_PDF/

The HOWL library is included as part of the
HLA v2.8 download, which you can find on
Webster at the following URL:

http://homepage.mac.com/randyhyde/webster.cs.ucr.edu/HighLevelAsm/dnld.html

There are also over 100 sample Win32 GUI application
demos written with HOWL available as part of the
HLA examples download. You can find these examples
here:

http://homepage.mac.com/randyhyde/webster.cs.ucr.edu/HighLevelAsm/HLAv2.8/hlaexamples.zip

Note that the HOWL examples appear in the win32/HOWL directory
of the examples download.

Allow me to leave you with a full HOWL example program.
cheers,
Randy Hyde

// pgm_trackBar1-
//
//  This program demonstrates the use of track bar controls on a form.

program pgm_trackBar1;
#linker( "comdlg32.lib" )
#linker( "comctl32.lib" )

const
    applicationName := "Track Bar #1";

?@NoDisplay     := true;
?@NoStackAlign  := true;

#includeOnce( "stdlib.hhf" )
#includeOnce( "howl.hhf" )

static
    align( 4 );
    bkgBrush_g      :dword;
    bkgColor_g      :dword;
   
   
// Forward declarations for the onClick widgetProcs that we're going to
// call when an event occurs.

proc onChange           :widgetProc; @forward;
proc onQuit             :widgetProc; @forward;



// Here's the main form definition for the app:

wForm( mainAppWindow );

    wTrackBar
    (
        trackBar1,
        10,
        10,
        500,
        40,
        w.TBS_HORZ,
        onChange
    )       
   
   
   
    wProgressBar
    (
        progressBar1,
        10,
        75,
        500,
        25
    )       
   
   
   
    // 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();
   

   



   
// Here's the onChange event handler for the trackbar object:

proc onChange:widgetProc;
begin onChange;

    push( esi );
    push( edi );
   
    // Get the track bar position into EAX:
   
    mov( thisPtr, esi );
    (type wTrackBar_t [esi]).get_position();
   
    // Set the corresponding position in the progress bar:
   
    mov( mainAppWindow.progressBar1, esi );
    (type wProgressBar_t [esi]).set_position( ax );
   
    pop( edi );
    pop( esi );
           
end onChange;


   

// 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;
begin onCreate;


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                                     
        w.CW_USEDEFAULT,        // Let Windows position this guy
        w.CW_USEDEFAULT,        //  "    "         "      "   "
        600,                    // Width
        600,                    // 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 pgm_trackBar1;

    HowlMainApp();         
               
end pgm_trackBar1;