Window Defs
Volume Number: 2
Issue Number: 10
Column Tag: Pascal Procedures
Window Definition Routines
By Darryl Lovato, TML Systems, Inc., MacTutor Contributing Editor
In my first article describing definition routines, I stated that the best way to
create a Definition Routine was to develop the routine as a procedure or function in
your code, and when it is finished, make it into its respective resource (MDEF, WDEF,
CDEF, LDEF). This finished resource can then be installed into your application and
used just as you would a standard Definition Routine. There seems to be some confusion
about this.
Creating the routine within your program requires that you do some hacking that
isn't very nice, and slightly buggy, but it usually works. The reason you would want to
create the routine as part of your code is because it's much faster to compile a
definition procedure as part of your code as opposed to compiling the procedure into a
resource, installing it, and then running the program that uses it.
As my first article explained, there are several ways to create the Definition
Routine as part of your program. The way I choose to include the Definition Routine is
shown below:
.....
var {our menu handle}
myMenuHdl : MenuHandle;
.....
{this is the proc that will become a resource}
procedure TheMenuProc(.....);
begin
.....
end;
.....
{first, we need to get a menu handle!}
myMenuHdl := GetNewMenu(.....);
{second, we create a new handle that will be the handle to our
routine. }
myMenuHdl^^.menuProc := NewHandle(0);
{third, we make the handle point to a pointer to our routine.
This, in effect makes a handle to our routine (which is what we
went through all this for!). We can do this because the routine
is in the first code segment that is always locked.}
myMenuHdl^^.menuProc^ := Ptr(@TheMenuProc);
Mike Shulster's approach to creating a definition routine is a bit different, but
works just as well. He makes a 6 byte resource, MDEF, WDEF, etc. All the resource
contains is a JMP XXXXXXXX instruction. After he gets the handle to the routine, he
patches the contents of the resource so that it will to jump back to his code!!! This
method is shown below.
.....
var {our menu handle}
myMenuHdl : MenuHandle;
.....
{this is the proc that will become a resource}
procedure TheMenuProc(.....);
begin
.....
end;
.....
{first, we need to get a menu handle. This will read the 6 byte
"defintion" resource and place a handle to it in the menu record}
myMenuHdl := GetNewMenu(.....);
{Now we need to patch the resource's JMP XXXXXXXX
instruction so that it will jump to our Definition Routine.
This is done by making a blind pointer}
{get a ptr to the resource data}
MyPtr := Pointer(myMenuHdl^^.menuProc^);
{skip JMP instruction but not address}
MyPtr := Pointer(Ord4(myPtr) + 2);
{and stuff the address of the menu proc in the XXXXXXXX portion
of the resource}
MyPtr^ := Ord4(@TheMenuProc);
{the resource data now consists of a jump back to the
applications code that implements the definition routine.}
These methods should only be used during development!
Normally, a fairly large program consists of more than one code segment,
therefore you can never be sure if the procedure is going to be part of segment one
(which is locked). You could Hlock the code segment the code is a part of, but this would
result in heap fragmentation which is a BIG NO NO!
How do you compile the Definition Procedure into a resource? TML Pascal
allows you to do this very easily. When I wrote this, mid-August, the only other
compiler that I know of that had this capability was Lisa Pascal.
A TML Pascal shell is shown below for a program that is to be compiled into a
resource. Note: it must be compiled with the create desk accessory option checked.
program TheDefProcProgram;
{$C type id [attribute] [name]}
{$H ''}
{----------------------- RESOURCE STARTS HERE --}