# -*- Mode: Text -*-

     =================================================================
		   DynWin, a Win32 Class Library
     =================================================================

[Goals]
---------------------------------------------------------------------------
My intent is to leverage the powerful dynamic capability of Python
to build a class library that is:

  simpler,
  more flexible,
  more easily extended,
  and more dynamic

than the various C++ class libraries can hope to be.  At first glance,
one might expect this class library to perform poorly.  However, most
GUI's do not need the speed of a 200Mhz Pentium to control user
interface elements.  And in the case where raw CPU does not suffice,
more sophisticated graphical techniques can often be employed to make
up the difference.

I believe that in choosing _only_ strongly-typed, compiled languages
for the development of user interfaces, an entire area of the language
spectrum, and the promise it holds for UI innovation, is ignored.

(Since I started this project several years ago, the Java world has
 taken a very similar tack with the 'Swing' project.  If you haven't
 seen Swing yet, you should definitely take a look!  Another good
 example is ParcPlace Smalltalk)

[Win32 Renaming]
---------------------------------------------------------------------------

Win32 entities are renamed, for my own sanity.  I wrote this, so I
have the right to rename them.  If you don't like it, you can just
GoBackToMfcWhereYouCameFrom. 8^)

The renaming will help distinguish those functions and objects
intended to work with objects implemented in python from those
intended to work at a lower level.

For example, dc.select_object() expects to be given a GDI object
implemented in python, with a get_handle()/__int__ conversion method,
where gdi32.SelectObject (which is actually a direct reference to the
routine in the system dll) expects two parameters: an HDC and an
HGDIOBJ.

In general, a multi-word name will be rendered in all lowercase, with
underscore dividers between the words, e.g.:

PreTranslateMessage ==> pre_translate_message
DlgDirSelectComboBoxEx ==> dlg_dir_select_combo_box_ex

In addition, all Hungarian notation is removed from the front of structure
slot names.

[Win32con]
---------------------------------------------------------------------------

Avoid using win32con.  Rather than burying all system-wide constants
in one huge file or database, include the constants in the source
files providing interfaces relevant to them.  For example, device
context related constants such as DRIVERVERSION (for
dc.get_device_caps()) belong in the <windc> module.  One goal of this
measure is that 'frozen' python programs will include references to
only that subset of constants necessary for the program's operation.


[Objects and Handles]
---------------------------------------------------------------------------

Python's automatic integer-cast capability (the '__int__' method)
greatly eases the burden of communicating with the Win32 API.  On
Win32, nearly every 'object' is referenced through an opaque 'handle'.
When we build a wrapper for such an object, we provide an instance
variable to hold the handle, and use an __int__ method to
automatically convert a Python object to a handle.  This allows us to
write:

    dc.select_object (brush)

  Rather than
    dc.select_object (brush.get_handle())
  or
    dc.select_object (brush.handle)

and, in general, gives the code a much more object-oriented feel.

To give you an idea of how much work Python is doing for you, here's
what that call might look like if constructed 'manually':

    calldll.call_foreign_function (
       gdi32.SelectObject.address,
       'll',
       'l',
       (dc.handle, brush.handle)
    )

You must not forget that you are programming 'against the iron' of the
operating system - very much like programming in C, but without type
safety.  If you feed bogus values to system API's, you may crash your
whole operating system.  I have crashed NT twice this way in 3 years!
[which is often enough for something that's not supposed to happen]

---------------------------------------------------------------------------
[Controls]

In general, I would like to avoid using 'controls', such as the
builtin or common controls, because the interfaces to these windows
are usually limited - consisting of a few structure definitions, api
functions, and callbacks.

There is usually no simple way to extend or modify their behavior
("subclassing" doesn't count).  To get a modified control, you must
often dive into the 'owner-drawn' cesspool, write your own message
loops/handlers, etc... At this point you might as well have written
the control yourself!

---------------------------------------------------------------------------
[Synergy and Critical Mass]

Often a new facility invites a cleaner rewrite of an existing one.
For example, once the layout managers were available, it became easy
to redesign the existing scrollbar class: Instead of hard-coding the
button-and-thumb behavior into a single class, we use the layout
manager to position separate button and thumb objects.  Now we have a
more flexible scrollbar design; for example, we may not _want_ the
buttons, or we may want to add extra buttons, or change the behavior
of the thumb tracker, etc.

The unfortunate side-effect of this is that the entire library is
constantly being rewritten.  Caveat Emptor.

---------------------------------------------------------------------------
[Dynwin as a Package]

A short experiment with using dynwin as a package proved it feasible,
however at the time the 'freeze' utility did not yet support packages;
most of my uses for dynwin involve creating standalone executables.

I hope to some day explore the idea again...


