diff options
author | suke <suke@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-07-13 12:36:26 +0000 |
---|---|---|
committer | suke <suke@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-07-13 12:36:26 +0000 |
commit | 6e0ed5570ec963b357e82b82a09d239fea17dee8 (patch) | |
tree | fb41472b257d16cc925b7d51bbb6116c853179ab | |
parent | b7000ccfa0a81d8cf6349b46ab618316552f3338 (diff) | |
download | ruby-6e0ed5570ec963b357e82b82a09d239fea17dee8.tar.gz |
* ext/win32ole/win32ole.c (EVENTSINK_Invoke): using hash
to set value to the reference argument of event.
* test/win32ole/test_win32ole_event.rb: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@18055 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | ext/win32ole/win32ole.c | 83 | ||||
-rw-r--r-- | test/win32ole/test_win32ole_event.rb | 83 |
3 files changed, 167 insertions, 6 deletions
@@ -1,3 +1,10 @@ +Sun Jul 13 21:23:08 2008 Masaki Suketa <masaki.suketa@nifty.ne.jp> + + * 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@ruby-lang.org> * ext/pty/pty.c (raise_from_wait, pty_syswait, get_device_once): diff --git a/ext/win32ole/win32ole.c b/ext/win32ole/win32ole.c index bfefb83e2a..4ee0ed3f7a 100644 --- a/ext/win32ole/win32ole.c +++ b/ext/win32ole/win32ole.c @@ -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_default(VALUE self); 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,6 +7373,44 @@ ole_search_event(VALUE ary, VALUE ev, BOOL *is_default) 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 @@ STDMETHODIMP EVENTSINK_Invoke( 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 @@ ev_advise(int argc, VALUE *argv, VALUE self) 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 @@ ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg) * * 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 @@ fev_on_event(int argc, VALUE *argv, VALUE self) * * 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) diff --git a/test/win32ole/test_win32ole_event.rb b/test/win32ole/test_win32ole_event.rb index 42e80ced90..dafabffc5a 100644 --- a/test/win32ole/test_win32ole_event.rb +++ b/test/win32ole/test_win32ole_event.rb @@ -164,6 +164,76 @@ if defined?(WIN32OLE_EVENT) 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 @@ if defined?(WIN32OLE_EVENT) @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 |