#!/usr/bin/env python

# TODO: hook paint, add bitblt (stretchblt), resizing handlers (and aspect ratio), allocate a bitmap, draw using your own functions.

import win32gui
import win32con
import struct
import sys
import win32api

# "winxpgui" is "win32gui" replacement.

# SetWindowLong(hWnd, GWL_USERDATA, (long)(cs->lpCreateParams));
# ClassOfTheWindow* TheWindow = (ClassOfTheWindow *)(GetWindowLong(hWnd, GWL_USERDATA));
# SetWindowLong(hWndButton, GWL_WNDPROC, (LONG)Button1_WndProc);

class Window(object):
    def __init__(self, title = sys.argv[0]):
        self.window = None
        self.pixmap = None
        self.title = title
        self.instance = win32api.GetModuleHandle(None) # cache.
        self.ensure_window()
        self.ensure_pixmap()

    def show(self):
        win32gui.ShowWindow(self.window, win32con.SW_SHOWNORMAL)
        win32gui.UpdateWindow(self.window)

    def hide(self):
        win32gui.ShowWindow(self.window, win32con.SW_HIDE)
        win32gui.UpdateWindow(self.window)

    def minimize(self):
        self.ShowWindow(self.window, win32con.SW_MINIMIZE)

    def destroy(self, handle, message, W_param, L_param):
        # win32gui.DeleteObject(self.pixmap)
        win32gui.PostQuitMessage(0)
        return True

    def ensure_window(self):
        if self.window is not None:
            return
        
        instance = self.instance # cached.
        style = win32con.WS_OVERLAPPEDWINDOW
        xstyle = win32con.WS_EX_LEFT
        title = self.title
        self.window = win32gui.CreateWindow(self.__class__.__name__, title, style, win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, 500, 400, 0, 0, instance, None)
        # 1st: atom, not class name?

    def update_window_content(self, DC):
        """ DC: actual DC proxy object created by #"win32ui.CreateDCFromHandle". """
        #old_object = win32gui.SelectObject(DC)

        #.BitBlt((0, 0), (width, height), DC, (0,0), win32con.SRCCOPY)
        self.pixmap.Paint(DC)
        
        #win32gui.SelectObject(old_object)

    def ensure_pixmap(self):
        if self.pixmap is not None:
            return
        
        self.ensure_window()
        #left, top, right, bottom = win32gui.GetClientRect(handle)
        # width = right - left
        # height = bottom - top
        window_DC_Handle = win32gui.GetDC(self.window)
        # window_DC = win32ui.CreateDCFromHandle(window_DC_Handle)

        self.pixmap = win32ui.CreateBitmap()
        self.CreateCompatibleBitmap(window_DC_Handle, width, height)

        win32gui.ReleaseDC(self.window, window_DC_Handle)
        #win32gui.DeleteDC(window_DC_Handle)
        
    def paint(self, handle, message, W_param, L_param):
        window_DC, painting_jobs = win32gui.BeginPaint(handle)
        # painting_jobs: fErase(erase background-P), rcPaint(the area), ...
        # background auto-erased when there is a brush in WNDCLASS's hbrBackground field.
        left, top, right, bottom = win32gui.GetClientRect(handle)
        
        #win32gui.DrawText(context, "Hi!", -1, client_rectangle, win32con.DT_SINGLELINE, win32con.DT_CENTER, win32con.DT_VCENTER)

        #window_DC = win32ui.CreateDCFromHandle(window_DC_Handle)
        self.update_window_content(window_DC)
        #win32gui.ReleaseDC(self.window, window_DC)
        #win32gui.DeleteDC(window_DC)
        # IntersectClipRect
        # bitmap.GetSize()
        # window_DC.GetWindowExt()
        
        win32gui.EndPaint(window_DC, painting_jobs)

    def register_class(klass):
        class_name = klass.__name__
        message_map = {
                #win32con.WM_DESTROY: self.destroy,
                #win32con.WM_PAINT: self.paint
        }
        Win32_class = win32gui.WNDCLASS()
        Win32_class.style = win32con.CS_HREDRAW | win32con.CS_VREDRAW
        Win32_class.lpfnWndProc = message_map
        Win32_class.cbWndExtra = 0
        Win32_class.hCursor = win32gui.LoadCursor(0, win32con.IDC_ARROW)
        Win32_class.hbrBackground = win32con.COLOR_WINDOW + 1 # win32gui.GetStockObject(win32con.WHITE_BRUSH)
        Win32_class.hIcon = win32gui.LoadIcon(0, win32con.IDI_APPLICATION)
        Win32_class.lpszClassName = class_name
        Win32_class.cbWndExtra = win32con.DLGWINDOWEXTRA + struct.calcsize("Pi") # C code: Win32_class.cbWndExtra = DLGWINDOWEXTRA + sizeof(HBRUSH) + sizeof(COLORREF)
        #Win32_class.hIconSm = 0
        class_atom = win32gui.RegisterClass(Win32_class)
        return class_atom
    
    register_class = classmethod(register_class)

Window.register_class()

# __metaclass__

if __name__ == "__main__":
    window_1 = Window()
    window_1.show()
    
    win32gui.PumpMessages()
