[前][次][番号順一覧][スレッド一覧]

ruby-changes:6539

From: suke <ko1@a...>
Date: Sun, 13 Jul 2008 21:36:40 +0900 (JST)
Subject: [ruby-changes:6539] Ruby:r18055 (trunk): * ext/win32ole/win32ole.c (EVENTSINK_Invoke): using hash

suke	2008-07-13 21:36:26 +0900 (Sun, 13 Jul 2008)

  New Revision: 18055

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=18055

  Log:
    * ext/win32ole/win32ole.c (EVENTSINK_Invoke): using hash
      to set value to the reference argument of event.
    
    * test/win32ole/test_win32ole_event.rb: ditto.

  Modified files:
    trunk/ChangeLog
    trunk/ext/win32ole/win32ole.c
    trunk/test/win32ole/test_win32ole_event.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 18054)
+++ ChangeLog	(revision 18055)
@@ -1,3 +1,10 @@
+Sun Jul 13 21:23:08 2008  Masaki Suketa  <masaki.suketa@n...>
+
+	* ext/win32ole/win32ole.c (EVENTSINK_Invoke): using hash
+	  to set value to the reference argument of event.
+
+	* test/win32ole/test_win32ole_event.rb: ditto.
+
 Sun Jul 13 06:57:09 2008  Nobuyoshi Nakada  <nobu@r...>
 
 	* ext/pty/pty.c (raise_from_wait, pty_syswait, get_device_once):
Index: ext/win32ole/win32ole.c
===================================================================
--- ext/win32ole/win32ole.c	(revision 18054)
+++ ext/win32ole/win32ole.c	(revision 18055)
@@ -118,7 +118,7 @@
 
 #define WC2VSTR(x) ole_wc2vstr((x), TRUE)
 
-#define WIN32OLE_VERSION "1.2.3"
+#define WIN32OLE_VERSION "1.2.4"
 
 typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX)
     (REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*);
@@ -499,6 +499,8 @@
 static VALUE foleparam_inspect(VALUE self);
 static long ole_search_event_at(VALUE ary, VALUE ev);
 static VALUE ole_search_event(VALUE ary, VALUE ev, BOOL  *is_default);
+static void hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams);
+static VALUE hash2result(VALUE hash);
 static void ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams);
 static HRESULT find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo);
 static HRESULT find_coclass(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **pTypeInfo2, TYPEATTR **pTypeAttr2);
@@ -7371,7 +7373,45 @@
     return def_event;
 }
 
+static void 
+hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams)
+{
+    BSTR *bstrs;
+    HRESULT hr;
+    UINT len, i;
+    VARIANT *pvar;
+    VALUE val;
+    VALUE key;
+    len = 0;
+    bstrs = ALLOCA_N(BSTR, pdispparams->cArgs + 1);
+    hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid, 
+                                     bstrs, pdispparams->cArgs + 1,
+                                     &len);
+    if (FAILED(hr))
+	return;
 
+    for (i = 0; i < len - 1; i++) {
+	key = WC2VSTR(bstrs[i + 1]);
+        val = rb_hash_aref(hash, INT2FIX(i));
+	if (val == Qnil) 
+	    val = rb_hash_aref(hash, key);
+	if (val == Qnil)
+	    val = rb_hash_aref(hash, rb_str_intern(key));
+        pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
+        ole_val2ptr_variant(val, pvar);
+    }
+}
+
+static VALUE 
+hash2result(VALUE hash)
+{
+    VALUE ret = Qnil;
+    ret = rb_hash_aref(hash, rb_str_new2("return"));
+    if (ret == Qnil)
+	ret = rb_hash_aref(hash, rb_str_intern(rb_str_new2("return")));
+    return ret;
+}
+
 static void
 ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams)
 {
@@ -7443,10 +7483,19 @@
         argv = rb_ary_new();
         rb_ary_push(args, argv);
         result = rb_apply(handler, rb_intern("call"), args);
-        ary2ptr_dispparams(argv, pdispparams);
+	if(TYPE(result) == T_HASH) {
+	    hash2ptr_dispparams(result, pTypeInfo, dispid, pdispparams);
+	    result = hash2result(result);
+	} else {
+	    ary2ptr_dispparams(argv, pdispparams);
+	}
     }
     else {
         result = rb_apply(handler, rb_intern("call"), args);
+	if(TYPE(result) == T_HASH) {
+	    hash2ptr_dispparams(result, pTypeInfo, dispid, pdispparams);
+	    result = hash2result(result);
+	}
     }
     if (pvarResult) {
         ole_val2variant(result, pvarResult);
@@ -7829,7 +7878,6 @@
     IEVENTSINKOBJ *pIEV;
     DWORD dwCookie;
     struct oleeventdata *poleev;
-    VALUE events = Qnil;
 
     rb_secure(4);
     rb_scan_args(argc, argv, "11", &ole, &itf);
@@ -7966,9 +8014,28 @@
  * 
  *  Defines the callback event.
  *  If argument is omitted, this method defines the callback of all events.
+ *  If you want to modify reference argument in callback, return hash in
+ *  callback. If you want to return value to OLE server as result of callback
+ *  use `return' or :return.
+ *
  *    ie = WIN32OLE.new('InternetExplorer.Application')
- *    ev = WIN32OLE_EVENT.new(ie, 'DWebBrowserEvents')
+ *    ev = WIN32OLE_EVENT.new(ie)
  *    ev.on_event("NavigateComplete") {|url| puts url}
+ *    ev.on_event() {|ev, *args| puts "#{ev} fired"} 
+ *
+ *    ev.on_event("BeforeNavigate2") {|*args| 
+ *      ...
+ *      # set true to BeforeNavigate reference argument `Cancel'.
+ *      # Cancel is 7-th argument of BeforeNavigate,
+ *      # so you can use 6 as key of hash instead of 'Cancel'.
+ *      # The argument is counted from 0. 
+ *      # The hash key of 0 means first argument.)
+ *      {:Cancel => true}  # or {'Cancel' => true} or {6 => true}
+ *    }
+ *
+ *    ev.on_event(...) {|*args|
+ *      {:return => 1, :xxx => yyy}
+ *    }
  */
 static VALUE
 fev_on_event(int argc, VALUE *argv, VALUE self)
@@ -7982,7 +8049,13 @@
  * 
  *  Defines the callback of event.
  *  If you want modify argument in callback, 
- *  you should use this method instead of WIN32OLE_EVENT#on_event.
+ *  you could use this method instead of WIN32OLE_EVENT#on_event.
+ *
+ *    ie = WIN32OLE.new('InternetExplorer.Application')
+ *    ev = WIN32OLE_EVENT.new(ie)
+ *    ev.on_event_with_outargs('BeforeNavigate2') {|*args|
+ *      args.last[6] = true
+ *    }
  */
 static VALUE
 fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self)
Index: test/win32ole/test_win32ole_event.rb
===================================================================
--- test/win32ole/test_win32ole_event.rb	(revision 18054)
+++ test/win32ole/test_win32ole_event.rb	(revision 18055)
@@ -164,6 +164,76 @@
       assert_equal(bl, @ie.locationURL)
     end
 
+    def test_on_event_hash_return
+      ev = WIN32OLE_EVENT.new(@ie)
+      ev.on_event('BeforeNavigate2'){|*args|
+        {:return => 1, :Cancel => true}
+      }
+      bl = @ie.locationURL
+      @ie.navigate("file:///#{@f}")
+      while @ie.busy
+        sleep 0.1
+        WIN32OLE_EVENT.message_loop
+      end
+      assert_equal(bl, @ie.locationURL)
+    end
+
+    def test_on_event_hash_return2
+      ev = WIN32OLE_EVENT.new(@ie)
+      ev.on_event('BeforeNavigate2'){|*args|
+        {:Cancel => true}
+      }
+      bl = @ie.locationURL
+      @ie.navigate("file:///#{@f}")
+      while @ie.busy
+        sleep 0.1
+        WIN32OLE_EVENT.message_loop
+      end
+      assert_equal(bl, @ie.locationURL)
+    end
+
+    def test_on_event_hash_return3
+      ev = WIN32OLE_EVENT.new(@ie)
+      ev.on_event('BeforeNavigate2'){|*args|
+        {'Cancel' => true}
+      }
+      bl = @ie.locationURL
+      @ie.navigate("file:///#{@f}")
+      while @ie.busy
+        sleep 0.1
+        WIN32OLE_EVENT.message_loop
+      end
+      assert_equal(bl, @ie.locationURL)
+    end
+    
+    def test_on_event_hash_return4
+      ev = WIN32OLE_EVENT.new(@ie)
+      ev.on_event('BeforeNavigate2'){|*args|
+        {'return' => 2, 'Cancel' => true}
+      }
+      bl = @ie.locationURL
+      @ie.navigate("file:///#{@f}")
+      while @ie.busy
+        sleep 0.1
+        WIN32OLE_EVENT.message_loop
+      end
+      assert_equal(bl, @ie.locationURL)
+    end
+
+    def test_on_event_hash_return5
+      ev = WIN32OLE_EVENT.new(@ie)
+      ev.on_event('BeforeNavigate2'){|*args|
+        {6 => true}
+      }
+      bl = @ie.locationURL
+      @ie.navigate("file:///#{@f}")
+      while @ie.busy
+        sleep 0.1
+        WIN32OLE_EVENT.message_loop
+      end
+      assert_equal(bl, @ie.locationURL)
+    end
+
     def handler1
       @event2 = "handler1"
     end
@@ -180,8 +250,19 @@
       @ie.quit
       WIN32OLE_EVENT.message_loop
       @ie = nil
-      File.unlink(@f)
+      WIN32OLE_EVENT.message_loop
+      sleep 0.1
+      begin 
+        File.unlink(@f)
+      rescue Error::EACCESS
+        WIN32OLE_EVENT.message_loop
+        sleep 0.2
+        File.unlink(@f)
+      end
+
       GC.start
+      WIN32OLE_EVENT.message_loop
+      sleep 0.1
     end
   end
 end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]