DynWin lives here: dynwin.zip
DynWin uses npstruct
and calldll
, which are here:
npstruct-2005-07-06.zip
calldll-2005-07-06.zip
(these modules have been linked against Python-2.4.1, and include instructions
on how to recompile them with mingw gcc)
This project was actually never quite finished - I stopped working with windows abruptly around 1998. If I ever find myself developing windows gui code again, I'll probably pick the project back up. That said, there is much to learn from looking at this code, and useful applications can be written with it.
There's an issue with XP related to gdi or ui callbacks being made from a different thread. At one point I had this fixed, but lost the code when my laptop died. I think the only thing necessary to get it working was to use the newer GIL api functions, but I don't remember the details. If anyone figures this out, send me a patch and I'll update the distribution
My intent is to leverage the powerful dynamic capability of Python to build a class library that is:
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 1GHz CPU 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!
Other good design examples are ParcPlace Smalltalk and Fresco.
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
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
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:
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':
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!
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.
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...
The entire library is in the process of being rewritten using the
model-view-controller pattern/paradigm. You'll notice these
modules because they all start with
To get started, read
Nearly all the interactive objects; buttons, toolbars, menus use a
model derived from the Make sure you have the two auxiliary dll modules,
That should do it! Many of the modules have self-tests and can be run directly
from the command line. You can also play with them from within the interpreter
window.
Note:This section needs updating... haven't tried freezing since python1.5...
DynWin apps are easy to freeze!
I usually freeze the freeze utility itself, for convenience. To distribute
your program, just send along python21.dll, calldll.pyd, and npstruct.pyd.
Freeze lets you choose between a console or windows application.
If you choose windows, be sure to capture sys.stdout and sys.stderr, otherwise
you may lose error output from the main message loop callback.
Objects and Handles
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.
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
Synergy and Critical Mass
Dynwin as a Package
Model-View-Controller
mvc_
. This shift in
thought has been tremendously successful in helping me to understand
and organize the library.
mvc.py
carefully, and make sure you
understand what the auto_model
class is doing.
mvc_button.push_button_model
class.
Trying it out
calldll.pyd
and npstruct.pyd
. Then add the library directory to your python
path.
Finally;
d:\python\dynwin> python demo/interp_demo.py
Freezing Applications
d:\python\dynwin> freeze -p d:/src/python-1.5 demo/mvc_tree_view.py
...
d:\python\dynwin> nmake
...