mshtml.py :  » Ajax » pyjamas » src » pyjd » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Ajax » pyjamas 
pyjamas » src » pyjd » mshtml.py
#import win32traceutil

import traceback
import sys
import os
import time
import new

# these three are required pre-imported, for pyjamas to work
# with the pyjd imputil etc.  awful, i know...
import threading
import encodings
import encodings.cp437


from windows import *
from ctypes import *
from ctypes.wintypes import *

import comtypes
from comtypes import IUnknown,GUID,COMMETHOD
from comtypes.automation import IDispatch,VARIANT
from comtypes.client import wrap,GetModule
from comtypes.client.dynamic import Dispatch

import comtypes.gen

if not hasattr(sys, 'frozen'):
    GetModule('atl.dll')
    GetModule('shdocvw.dll')
    try:
        GetModule('msxml2.dll')
    except:
        pass
    try:
        GetModule('msxml3.dll')
    except:
        pass
    try:
        GetModule('msxml6.dll')
    except:
        pass
    GetModule('mshtml.tlb') 
    #GetModule('progdlg.tlb') 

from comtypes.gen import SHDocVw
from comtypes.gen import MSHTML
try:
    from comtypes.gen import MSXML2
except:
    pass
try:
    from comtypes.gen import MSXML6
except:
    pass
try:
    from comtypes.gen import MSXML3
except:
    pass

atl = windll.atl                  # If this fails, you need atl.dll

# do this after gen stuff, above
import mshtmlevents 

SID_SShellBrowser = GUID("{000214E2-0000-0000-C000-000000000046}")

class IOleWindow(IUnknown):
    _case_insensitive_ = True
    u'IOleWindow Interface'
    _iid_ = GUID('{00000114-0000-0000-C000-000000000046}')
    _idlflags_ = []

    _methods_ = [
        COMMETHOD([], HRESULT, 'GetWindow',
                  ( ['in'], POINTER(c_void_p), 'pHwnd' ))
        ]

class IOleInPlaceActiveObject(IOleWindow):
    _iid_ = GUID("{00000117-0000-0000-C000-000000000046}")
    _idlflags_ = []
    _methods_ = IOleWindow._methods_ + [
        COMMETHOD([], HRESULT, 'TranslateAccelerator',
                  ( ['in'], POINTER(MSG), 'pMsg' ))
        ]
    

# http://www.mail-archive.com/comtypes-users@lists.sourceforge.net/msg00439.html
class IServiceProvider(IUnknown):
    _iid_ = GUID('{6D5140C1-7436-11CE-8034-00AA006009FA}')

    # Overridden QueryService to make it nicer to use (passing it an
    # interface and it returns a pointer to that interface)
    def QueryService(self, serviceIID, interface):
        p = POINTER(interface)()
        self._QueryService(byref(serviceIID), byref(interface._iid_), byref(p))
        return p

    _methods_ = [
        COMMETHOD([], HRESULT, 'QueryService',
                  ( ['in'], POINTER(GUID), 'guidService' ),
                  ( ['in'], POINTER(GUID), 'riid' ),
                  ( ['in'], POINTER(c_void_p), 'ppvObject' ))
        ]

#class IInputObject(IUnknown):
#    _iid_= GUID("{68284FAA-6A48-11D0-8C78-00C04FD918B4}")
#
#    _methods_= IUnknown._methods_ + [
#        (STDMETHOD (HRESULT, "UIActivateIO", BOOL, POINTER(MSG))),
#        (STDMETHOD (HRESULT, "HasFocusIO")),
#        (STDMETHOD (HRESULT, "TranslateAcceleratorIO", POINTER(MSG)))]

class EventSink(object):
    # some DWebBrowserEvents
    def OnVisible(self, this, *args):
        print "OnVisible", args

    def BeforeNavigate(self, this, *args):
        print "BeforeNavigate", args

    def NavigateComplete(self, this, *args):
        print "NavigateComplete", this, args
        return

    # some DWebBrowserEvents2
    def BeforeNavigate2(self, this, *args):
        print "BeforeNavigate2", args

    def NavigateComplete2(self, this, *args):
        print "NavigateComplete2", args

    def DocumentComplete(self, this, *args):
        print "DocumentComplete", args
        if self.workaround_ignore_first_doc_complete == False:
            # ignore first about:blank.  *sigh*...
            # TODO: work out how to parse *args byref VARIANT
            # in order to get at the URI.
            self.workaround_ignore_first_doc_complete = True
            return
            
        self._loaded()

    def NewWindow2(self, this, *args):
        print "NewWindow2", args
        return
        v = cast(args[1]._.c_void_p, POINTER(VARIANT))[0]
        v.value = True

    def NewWindow3(self, this, *args):
        print "NewWindow3", args
        return
        v = cast(args[1]._.c_void_p, POINTER(VARIANT))[0]
        v.value = True

fn_txt = """\
def event_fn(self, *args):
    #print "event %s", self, args
    #print "event callbacks", self._listeners
    callbacks = self._listeners.get('%s', [])
    for fn in callbacks:
        try:
            fn(self._sender, Dispatch(args[0]), True)
        except:
            traceback.print_exc()
            sys.stderr.flush()
"""

class EventCaller:
    def __init__(self, handler, name):
        self.handler = handler
        self.name = name
    def __call__(self, *args):
        callbacks = self.handler._listeners.get(self.name, [])
        #print "event", self.name, callbacks
        for fn in callbacks:
            try:
                fn(self.handler._sender, Dispatch(args[0]), True)
            except:
                sys.stderr.write( traceback.print_exc() )
                sys.stderr.flush()

class EventHandler(object):
    def __init__(self, sender):
        self._sender = sender
        self._listeners = {}
    def __getattr__(self, name):
        if name.startswith('__') and name.endswith('__'):
            raise AttributeError(name)
        #print "EventHandler requested ", name
        if name.startswith('_') or name == 'addEventListener':
            return self.__dict__[name]
        idx = name.find('_on')
        if idx >= 0:
            if idx > 0:
                name = name[idx+1:]
            #return EventCaller(self, name)
            exec fn_txt % (name[2:], name[2:])
            #exec fn_txt % (name[2:])
            #print event_fn
            return new.instancemethod(event_fn, self)
        raise AttributeError(name)

    def addEventListener(self, name, fn):
        if not self._listeners.has_key(name):
            self._listeners[name] = []
        self._listeners[name].append(fn)

class Browser(EventSink):
    def __init__(self, application, appdir):
        EventSink.__init__(self)
        self.platform = 'mshtml'
        self.application = application
        self.appdir = appdir
        self.already_initialised = False
        self.workaround_ignore_first_doc_complete = False
        self.window_handler = None
        self.node_handlers = {}

        # Create an instance of IE via AtlAxWin.
        atl.AtlAxWinInit()
        hInstance = GetModuleHandle(None)

        self.hwnd = CreateWindowEx(0,
                              "AtlAxWin",
                              "about:blank",
                              WS_OVERLAPPEDWINDOW |
                              WS_VISIBLE | 
                              WS_HSCROLL | WS_VSCROLL,
                              CW_USEDEFAULT,
                              CW_USEDEFAULT,
                              CW_USEDEFAULT,
                              CW_USEDEFAULT,
                              NULL,
                              NULL,
                              hInstance,
                              NULL)

        # Get the IWebBrowser2 interface for the IE control.
        self.pBrowserUnk = POINTER(IUnknown)()
        atl.AtlAxGetControl(self.hwnd, byref(self.pBrowserUnk))
        # the wrap call querys for the default interface
        self.pBrowser = wrap(self.pBrowserUnk)
        self.pBrowser.RegisterAsBrowser = True
        self.pBrowser.AddRef()

        self.conn = mshtmlevents.GetEvents(self.pBrowser, sink=self,
                        interface=SHDocVw.DWebBrowserEvents2)

        #print "browser HWND", SetFocus(self.pBrowser.HWND)

    def _alert(self, txt):
        self.getDomWindow().alert(txt)

    def load_app(self):

        uri = self.application
        if uri.find(":") == -1:
            # assume file
            uri = 'file://'+os.path.abspath(uri)

        #print "load_app", uri

        self.application = uri
        v = byref(VARIANT())
        self.pBrowser.Navigate(uri, v, v, v, v)

        # Show Window
        cw = c_int(self.hwnd)
        ShowWindow(cw, c_int(SW_SHOW))
        UpdateWindow(cw)


        # http://msdn.microsoft.com/en-us/library/aa752126%28VS.85%29.aspx
        wba = self.pBrowser.QueryInterface(IServiceProvider)
        wn = wrap(wba.QueryService(SID_SShellBrowser, IOleWindow))

        hwnd = c_void_p(0)
        pHnd = byref(hwnd)
        wn.GetWindow(pHnd)

        #PostMessage(pHnd.value, WM_SETFOCUS,0,0)
        SetFocus(hwnd)
        #print self.hwnd, pHnd.value

    def getDomDocument(self):
        return Dispatch(self.pBrowser.Document)

    def getDomWindow(self):
        return self.getDomDocument().parentWindow

    def _addXMLHttpRequestEventListener(self, node, event_name, event_fn):
        
        #print "_addXMLHttpRequestEventListener", event_name

        rcvr = mshtmlevents._DispEventReceiver()
        rcvr.dispmap = {0: event_fn}

        #print rcvr
        rcvr.sender = node
        #print rcvr.sender
        ifc = rcvr.QueryInterface(IDispatch)
        #print ifc
        v = VARIANT(ifc)
        #print v
        setattr(node, event_name, v)
        return ifc

    def addEventListener(self, node, event_name, event_fn):
        
        rcvr = mshtmlevents._DispEventReceiver()
        rcvr.dispmap = {0: event_fn}

        rcvr.sender = node
        ifc = rcvr.QueryInterface(IDispatch)
        v = VARIANT(ifc)
        setattr(node, "on"+event_name, v)
        return ifc

        rcvr = mshtmlevents.GetDispEventReceiver(MSHTML.HTMLElementEvents2, event_fn, "on%s" % event_name)
        rcvr.sender = node
        ifc = rcvr.QueryInterface(IDispatch)
        node.attachEvent("on%s" % event_name, ifc)
        return ifc

    def mash_attrib(self, attrib_name):
        return attrib_name

    def _addWindowEventListener(self, event_name, event_fn):
        
        #print "_addWindowEventListener", event_name, event_fn
        #rcvr = mshtmlevents.GetDispEventReceiver(MSHTML.HTMLWindowEvents,
        #                   event_fn, "on%s" % event_name)
        #print rcvr
        #rcvr.sender = self.getDomWindow()
        #print rcvr.sender
        #ifc = rcvr.QueryInterface(IDispatch)
        #print ifc
        #v = VARIANT(ifc)
        #print v
        #setattr(self.getDomWindow(), "on%s" % event_name, v)
        #return ifc

        wnd = self.pBrowser.Document.parentWindow
        if self.window_handler is None:
            self.window_handler = EventHandler(self)
            self.window_conn = mshtmlevents.GetEvents(wnd,
                                        sink=self.window_handler,
                                    interface=MSHTML.HTMLWindowEvents2)
        self.window_handler.addEventListener(event_name, event_fn)
        return event_name # hmmm...

    def getXmlHttpRequest(self):
        #print "getXMLHttpRequest"
        o = comtypes.client.CreateObject('MSXML2.XMLHTTP.3.0')
        #print "getXMLHttpRequest", o
        return Dispatch(o)
        
    def getUri(self):
        return self.application

    def _loaded(self):

        #print "loaded"

        if self.already_initialised:
            return
        self.already_initialised = True

        self._addWindowEventListener("unload", self.on_unload_callback)

        from __pyjamas__ import pygwt_processMetas,set_main_frame
        set_main_frame(self)

        (pth, app) = os.path.split(self.application)
        if self.appdir:
            pth = os.path.abspath(self.appdir)
        sys.path.append(pth)
        
    def on_unload_callback(self, *args):
        PostQuitMessage(0)

global timer_q
timer_q = []

WM_USER_TIMER = RegisterWindowMessage("Timer Notify")

global wv
wv = None

def MainWin(one_event):

    # Pump Messages
    msg = MSG()
    pMsg = pointer(msg)
    
    while 1:
        res = GetMessage( pMsg, NULL, 0, 0)
        if res == -1:
            return 0
        if res == 0:
            break 

        if timer_q:
            fn = timer_q.pop()
            fn()

        if msg.message == WM_USER_TIMER:
            continue

        app = wv.pBrowser.Application
        ao = app.QueryInterface(IOleInPlaceActiveObject)
        if ao.TranslateAccelerator(pMsg):
        #if not TranslateAccelerator( 
        #                wv.hwnd,  #handle to receiving window 
        #                NULL,    #handle to active accelerator table 
        #                pMsg):     #message data 
            TranslateMessage(pMsg)
            DispatchMessage(pMsg)

        if one_event:
            break

    return msg.wParam
    
def add_timer_queue(fn):
    timer_q.append(fn)
    PostMessage(c_int(wv.hwnd), UINT(WM_USER_TIMER), WPARAM(0), LPARAM(0xffff))

def is_loaded():
    return wv.already_initialised

def run(one_event=False, block=True):
    try:
        MainWin(one_event) # TODO: ignore block arg for now
    except:
        sys.stderr.write( traceback.print_exc() )
        sys.stderr.flush()

def setup(application, appdir=None, width=800, height=600):

    global wv
    wv = Browser(application, appdir)

    wv.load_app()

    while 1:
        if is_loaded():
            return
        run(one_event=True)

www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.