[racket] ActiveX support

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Sat Sep 1 18:00:46 EDT 2012

At Fri, 31 Aug 2012 17:58:07 -0600, Matthew Flatt wrote:
> At Fri, 31 Aug 2012 15:50:46 +0200, heraklea at gmx.de wrote:
> > I have an ocx-control and I would like to use it from Racket.
> > 
> > Is it possible to bind this control in any way to Racket/Scheme?
> 
> I think the way to do that is to use IE as an ActiveX container.
> 
> Below is an example that starts the "MSCAL.Calendar" control. As you
> can see, I didn't figure out how to tell IE that it should trust the
> control (so there's an 8-second pause while I click to allow in IE),
> but maybe this will be enough to give you some ideas.

Here's an improved example, but it depends on improvements and repairs
in the latest `ffi/com' implementation in the git repo. The changes
support calling the `write' method of an IE document and correctly
reference-counting objects that are received as event arguments. It
uses the "Sysmon" control that is included with Windows (I think), and
it avoids creating a temporary file.

I'll add this example to the documentation.

--------------------------------------

#lang racket
(require ffi/com
	 xml)

;; The control we want to run:
(define control-progid "Sysmon")

;; Start IE:
(define ie (com-create-instance "InternetExplorer.Application.1"))

;; Set up an event callback so that we know when the initial document
;; is ready:
(define ex (com-make-event-executor))
(void (thread (lambda () (let loop () ((sync ex)) (loop)))))
(define ready (make-semaphore))
(com-register-event-callback ie "DocumentComplete" 
                             (lambda (doc url) (semaphore-post ready)) 
                             ex)

;; Navigate to an empty URL to get an initial document:
(com-invoke ie "Navigate" "")
(semaphore-wait ready)
(define doc (com-get-property ie "Document"))

;; Install HTML to show the ActiveX control:
(com-invoke doc "write"
            (xexpr->string
             `(html
               (head (title "Demo"))
               (body
                (object ((class "object")
                         (CLASSID ,(format 
                                    "CLSID:~a"
                                    (let ([s (guid->string 
                                              (progid->clsid 
                                               control-progid))])
                                      ;; must remove curly braces:
                                      (define len 
                                        (string-length s))
                                      (substring s 1 (sub1 len)))))))))))

;; Configure the IE window and show it:
(com-set-property! ie "MenuBar" #f)
(com-set-property! ie "ToolBar" 0)
(com-set-property! ie "StatusBar" #f)
(com-set-property! ie "Visible" #t)

;; Extract the ActiveX control from the IE document:
(define ctl (com-get-property 
	     (com-invoke (com-invoke doc "getElementsByTagName" "object") 
                         "item" 
                         0)
	     "object"))

;; At this point, `ctl' is the ActiveX control;
;; demonstrate by getting a list of method names:
(com-methods ctl)


Posted on the users mailing list.