Re: alternatives to mswgui
Thomas Heller <[email protected]> 15 Nov 2002 11:31:38 +0100
| Newsgroups | gmane.comp.python.anygui.devel |
|---|---|
| Message-ID | <[email protected]> |
Robin,
now I understand what you meant by complaining about the confusing
_as_parameter_ stuff.
It seems you are using ctypes the calldll/npstruct way, but ctypes
is supposed to make it easier. Here is a part of your code:
# Robin's version
def _register_class(self):
if _verbose: log('Application._register_class:start',str(self))
class WNDCLASS(Structure):
_fields_= (
('style','i'),
('lpfnWndProc','i'),
('cls_extra','i'),
('wnd_extra','i'),
('hInst','i'),
('hIcon','i'),
('hCursor','i'),
('hbrBackground','i'),
('menu_name','i'),
('lpzClassName','i'),
)
class WINDOWPROC(CFunction):
_types_ = "iiii"
_stdcall_ = 1
self.__wndproc = WINDOWPROC(self._wndproc)
self._class_name = c_string("dw.anygui.PythonWindow")
# register a window class for toplevel windows.
wc = WNDCLASS()
wc.hbrBackground = COLOR_BTNFACE + 1
wc.hCursor = user32.LoadCursor(0, IDC_ARROW)
wc.hIcon = user32.LoadIcon(0, IDI_APPLICATION)
wc.lpzClassName = self._class_name._as_parameter_
wc.lpfnWndProc = self.__wndproc._as_parameter_
wc.hInst = kernel32.GetModuleHandle(0)
self._wc = wc
user32.UnregisterClass(wc.lpzClassName,0)
self.__class__._wndclass = user32.RegisterClass(byref(wc))
assert self.__class__._wndclass, "RegisterClass --> %s" % WinError()
if _verbose: log('Application._register_class:end',str(self))
I've rewritten the code to be more ctypes-like, and now it is this:
# Thomas' version
def _register_class(self):
if _verbose: log('Application._register_class:start',str(self))
class WINDOWPROC(CFunction):
_types_ = "iiii"
_stdcall_ = 1
class WNDCLASS(Structure):
_fields_= (
('style','i'),
('lpfnWndProc',WINDOWPROC),
('cls_extra','i'),
('wnd_extra','i'),
('hInst','i'),
('hIcon','i'),
('hCursor','i'),
('hbrBackground','i'),
('menu_name','z'),
('lpzClassName','z'),
)
# register a window class for toplevel windows.
wc = WNDCLASS()
wc.hbrBackground = COLOR_BTNFACE + 1
wc.hCursor = user32.LoadCursor(0, IDC_ARROW)
wc.hIcon = user32.LoadIcon(0, IDI_APPLICATION)
wc.lpzClassName = "dw.anygui.PythonWindow"
wc.lpfnWndProc = WINDOWPROC(self._wndproc)
wc.hInst = kernel32.GetModuleHandle(None)
self._wc = wc
print user32.UnregisterClass(wc.lpzClassName,0)
self.__class__._wndclass = user32.RegisterClass(byref(wc)) & 0xFFFF
print hex(self.__class__._wndclass)
assert self.__class__._wndclass, "RegisterClass --> %s" % WinError()
if _verbose: log('Application._register_class:end',str(self))
Maybe I should make some comments:
Use the 'z' format for a structure field containing an string pointer (LPCSTR),
and assign the python string directly. No need to use c_string in this case.
c_string is really only needed for mutable strings.
Use WINDOWPROC as format for a structure field containing a function
pointer, and assign WINDOWPROC(callable) to fill the field.
RegisterClass returns an ATOM (which is 16 bit) so we have to mask
the result with 0xFFFF to be safe, although this should better be done
by using the restype attribute. This would be able to handle errors as well:
def ATOM(value):
value = value & 0xFFFF # atoms are 16-bit
if value == 0:
raise WinError()
return value
user32.RegisterClass.restype = ATOM
It would be a good idea to set restype for other functions too,
so that you automatically get an exception when it fails without
needing to check the return value all the time.
Thomas
-------------------------------------------------------
This sf.net email is sponsored by: To learn the basics of securing
your web site with SSL, click here to get a FREE TRIAL of a Thawte
Server Certificate: http://www.gothawte.com/rd524.html