CWindow RC 21

Started by José Roca, September 09, 2016, 02:32:30 PM

Previous topic - Next topic

José Roca

#30
To allow that, I have made an small change in a CBSTR constructor and LET operator that accept ansi strings (I had to do it anway) and added a new constructor to CVARIANT that accepts a variant passed by value:


' ========================================================================================
' Initializes the variant from a VARIANT.
' This consstructor allows a syntax like:
' DIM cv AS CVARIANT = TYPE<VARIANT>(VT_ERROR,0,0,0,DISP_E_PARAMNOTFOUND)
' ========================================================================================
PRIVATE CONSTRUCTOR CVariant (BYVAL v AS VARIANT)
   CVARIANT_DP("CVARIANT CONSTRUCTOR - BYVAL VARIANT")
   ' // Load the PopsSys.DLL
   psLib = DyLibLoad("propsys.dll")
   ' // Initialize the variant
   VariantCopy(@vd, @v)
END CONSTRUCTOR
' ========================================================================================


This allows the use of temporary types for optional variant parameters, e.g.


SUB Foo (BYVAL cv AS CVARIANT = TYPE<VARIANT>(VT_ERROR,0,0,0,DISP_E_PARAMNOTFOUND))


and also have optional BSTR parameters


SUB Foo (BYVAL cbs AS CBSTR = "")


José Roca

#31
The only problem would be if the called method returns an array of BSTRs or VARIANTs. Still, we could use CBSTR and CVARIANT for all the other cases. I will first use BSTR and VARIANT and do tests to see if CBSTR and CVARIANT can be safely used.

Marc Pons

#32
Jose

some remarks :

on the "abstract view"  using IAnimation as example,  to be coherent with the forward declaration

TYPE IAnimation AS IAnimation_
  IAnimationVTbl shoud be IAnimation_

#ifndef __IAnimation_INTERFACE_DEFINED__
#define __IAnimation_INTERFACE_DEFINED__

TYPE IAnimationVTbl EXTENDS Afx_IDispatch   ' should be : TYPE IAnimation_  EXTENDS Afx_IDispatch
   DECLARE ABSTRACT FUNCTION put_AutoPlay () AS HRESULT
   DECLARE ABSTRACT FUNCTION get_AutoPlay () AS HRESULT
  ...
END TYPE


on the "Automation view"  using IMonthView as example,
we could simplify by using 
Quoteextends IDispatchVtbl
the 7 functions are already defined on the fb headers, so we can avoid to add them

#ifndef __IMonthView_INTERFACE_DEFINED__
#define __IMonthView_INTERFACE_DEFINED__

TYPE IMonthViewVTbl extends IDispatchVtbl
   'QueryInterface AS FUNCTION (BYVAL this AS IMonthView PTR, BYVAL riid AS CONST IID CONST PTR, BYVAL ppvObj AS ANY PTR PTR) AS HRESULT
   'AddRef AS FUNCTION (BYVAL this AS IMonthView PTR) AS ULONG
   'Release AS FUNCTION (BYVAL this AS IMonthView PTR) AS ULONG
   'GetTypeInfoCount AS FUNCTION (BYVAL this AS IMonthView PTR, BYVAL pctinfo AS UINT PTR) AS HRESULT
   'GetTypeInfo AS FUNCTION (BYVAL this AS IMonthView PTR, BYVAL iTInfo AS UINT, BYVAL lcid AS LCID, BYVAL ppTInfo AS ITypeInfo PTR PTR) AS HRESULT
   'GetIDsOfNames AS FUNCTION (BYVAL this AS IMonthView PTR, BYVAL iTInfo AS UINT, BYVAL lcid AS LCID, BYVAL ppTInfo AS ITypeInfo PTR PTR) AS HRESULT
   'Invoke AS FUNCTION (BYVAL this AS IMonthView PTR, BYVAL dispIdMember AS DISPID, BYVAL riid AS CONST IID CONST PTR, BYVAL lcid AS LCID, BYVAL wFlags AS WORD, BYVAL pDispParams AS DISPPARAMS PTR, BYVAL pVarResult AS VARIANT PTR, BYVAL pExcepInfo AS EXCEPINFO PTR, BYVAL puArgErr AS UINT PTR) AS HRESULT
   get_Appearance AS FUNCTION (BYVAL pthis AS ANY PTR, BYVAL penumAppearances As AppearanceConstants Ptr) AS HRESULT
   put_Appearance AS FUNCTION (BYVAL pthis AS AS ANY PTR, BYVAL penumAppearances As AppearanceConstants ) AS HRESULT
   ...
   get_Year AS FUNCTION (BYVAL pthis AS ANY PTR, ByVal psYear As Short Ptr) AS HRESULT
   put_Year AS FUNCTION (BYVAL pthis AS ANY PTR, ByVal sYear As Short) AS HRESULT
   AboutBox AS FUNCTION (BYVAL pthis AS ANY PTR, ByVal DummyVAR As Byte = 0) AS HRESULT ' adding DummyVAR variable
  ...
END TYPE


we can also use  ANY PTR , every where to replace the  IMonthView PTR ( in that case)

we can also avoid the long list of #define ...
as :
#define IMonthView_put_Week(this) (this)->lpVtbl->put_Week(this)
#define IMonthView_get_Year(this, pYear) (this)->lpVtbl->get_Year(this, pYear)
#define IMonthView_put_Year(this, Year) (this)->lpVtbl->put_Year(this, Year)
#define IMonthView_AboutBox(this) (this)->lpVtbl->AboutBox(this)


just by putting only 1 (for all classes) generic variadic define like the following
#Define Ax_Vt(a, b, arg...) a->lpvtbl->b(a,arg) ' easiest way to adress vtable function with argument
it works every where except when arg is empty  ( that's the case here on AboutBox)
for these cases when no argument : it is simply to add a dummy variable like the following in the class\type

AboutBox AS FUNCTION (BYVAL pthis AS ANY PTR, ByVal DummyVAR As Byte = 0) AS HRESULT ' adding DummyVAR variable
that dummy argument as no effect, but the variadic function will always work fine with that workarround!

so usage example :

   'using vtable interface
DIM pMV2 AS IMonthView ptr = cast(any PTR , MyOleCon2.OcxDispPtr)
        DIM year AS short
   IF pMV2 THEN
'pMV2->lpvtbl->Refresh(pMV2)
'pMV2->lpvtbl->AboutBox(pMV2)
'pMV2->lpvtbl->put_Year(pMV2 , 1985)
'pMV2->lpvtbl->put_Month(pMV2 , 4)
'pMV2->lpvtbl->put_Day(pMV2 , 21)
                'pMV2->lpvtbl->Get_Year(pMV2 , @year)

Ax_Vt(pMV2, AboutBox)
Ax_Vt(pMV2, Refresh)
Ax_Vt(pMV2, put_Year, 1985)
Ax_Vt(pMV2, put_Month, 4)
Ax_Vt(pMV2, put_Day, 21)
                Ax_Vt(pMV2, get_Year, @year)
   end if


just to avoid the pMV2->lpvtbl->put_Year(pMV2 , 1985) complex form

Marc Pons

remarks on parameters

taking the previous sample usage 'using vtable interface
DIM pMV2 AS IMonthView ptr = cast(any PTR , MyOleCon2.OcxDispPtr)
        DIM year AS short
   IF pMV2 THEN
'pMV2->lpvtbl->Refresh(pMV2)
'pMV2->lpvtbl->AboutBox(pMV2)
'pMV2->lpvtbl->put_Year(pMV2 , 1985)
'pMV2->lpvtbl->put_Month(pMV2 , 4)
'pMV2->lpvtbl->put_Day(pMV2 , 21)
                'pMV2->lpvtbl->Get_Year(pMV2 , @year)

Ax_Vt(pMV2, AboutBox)
Ax_Vt(pMV2, Refresh)
Ax_Vt(pMV2, put_Year, 1985)
Ax_Vt(pMV2, put_Month, 4)
Ax_Vt(pMV2, put_Day, 21)
                Ax_Vt(pMV2, get_Year, @year)
   end if


what surprise me, is works in input using direct values  (without variable)
and more surprising, on ouput, just giving the pointer of the variable to get the result

I was thinking the exchange as to be throught Variant, is it some implicit cast to work directly ?

it even could be simplyfied if on the type\class we use as : with byref on the out parameter
get_Year AS FUNCTION (BYVAL pthis AS ANY PTR, ByRef  sYear As Short) AS HRESULT

in that the usage could be just

'pMV2->lpvtbl->Get_Year(pMV2 , year)
Ax_Vt(pMV2, get_Year, year)


and it works !

José Roca

#34

on the "Automation view"  using IMonthView as example,
we could simplify by using

extends IDispatchVtbl

the 7 functions are already defined on the fb headers, so we can avoid to add them


We can't do that. If we use extends, we have to use abstract methods. Choose the VTable option by unchecking the Automation view.

Quote
we can also avoid the long list of #define ...
just by putting only 1 (for all classes) generic variadic define like the following

Variadic functions don't work in FB 64-bit. Bad news for the variadic "aficionados" still working with XP. Sorry.

José Roca

#35
> and it works !

Of course it works, but we aware that if you use an initialized CBSTR or CVARIANT type, you must clear them first with <CBSTR name>.Clear / <CVARIANT>.Clear before passing the address to an OUT parameter or you will get a memory leak. I have exaplained it in another thread.

And I mean calling .Clear, not setting it to empy with <CBSTR Name> = "".

<CBSTR name>.Clear frees the underlying BSTR and sets the pointer to null, whereas <CBSTR Name> = "" creates an empty but valid BSTR. Empty BSTRs are needed with some COM methods that require it instead of a null pointer.

<CVARIANT>.Clear calls VariantClear.


José Roca

I have almost finished the code to retrieve the parameters. There are still a few mistakes. There are also some problems with reserved words like Property and Delete.

Marc Pons

Jose you said
QuoteWhat can't be detected are the vtable events interfaces.

in the treeview you see them on CoClasses : checked with outgoing2.ocx on my previous post

so it can be deployed if needed, with a specific treatment , i can imagine,
what i don't know is firing that vtables events interfaces.

The code button : good choice

may I ask for an little evolution :
when changing the "Ole Automation view" option, it could be nice, the tree info and the code  be regenerated 


Marc Pons

QuoteVariadic functions don't work in FB 64-bit. Bad news for the variadic "aficionados" still working with XP. Sorry.

i agree with functions, its seems because of gen c option , but is it the same with variadic define ?

I have done previously some c coding on a 64 machine and variadic define were working well...

if you are right, i am happy to be with xp :D


José Roca

> I have done previously some c coding on a 64 machine and variadic define were working well...

C works, but FB not.

> if you are right, i am happy to be with xp :D

But your code won't be useful to 64 bit users.

José Roca

> in the treeview you see them on CoClasses : checked with outgoing2.ocx on my previous post

Only the default events interfaces can be detected, but not other additional events interfaces.

For example, ADO has two dispatch events interfaces, ConnectionEvents and RecordsetEvents, but also two VTable events interfaces, ConnectionEventsVt and RecordsetEventsVt. As VB6 can't use the VTable ones, they haven't bothered to flag the others as event interfaces. They could have done it, but they don't care.

José Roca

#41
> what i don't know is firing that vtables events interfaces.

In the webbrowser examples that I have posted there is a vtable events interface, IDocHostUiHandler.

Connecting events with these interfaces depends on the way chosen by the programmer of the COM server or OCX. Sometimes using a connetion point, but most of the times calling and ad hoc method provided by one interface.

In the case of the WebBrowser control...


' ========================================================================================
' Sets our implementation of the IDocHostUIHandler interface to customize the WebBrowser.
' ========================================================================================
PRIVATE FUNCTION CWebBrowser.SetUIHandler () AS HRESULT
   CWB_DP("-BEGIN CWebBrowser.SetUIHandler")

   ' // After the MSHTML document has been loaded, we retrieve a reference to its
   ' // ICustomDoc interface and give him a pointer to our IDocHostUIHandler interface
   ' // to allow for customization.
   IF m_pWebBrowser = NULL THEN RETURN E_POINTER

   ' // Get a reference to the active document
   DIM pIHTMLDocument2 AS IHTMLDocument2 PTR
   DIM pDispatch AS IDispatch PTR
   m_pWebBrowser->get_Document(@pDispatch)
   pIHTMLDocument2 = cast(IHTMLDocument2 PTR, pDispatch)
   IF pIHTMLDocument2 = NULL THEN EXIT FUNCTION

   ' // Get a reference to the CustomDoc interface
   DIM pICustomDoc AS ICustomDoc PTR
   ' extern IID_ICustomDoc is broken and causes the linker to fail
   ' IID_ICustomDoc = "{3050F3F0-98B5-11CF-BB82-00AA00BDCE0B}"
   DIM IID_ICustomDoc_ AS GUID = (&h3050F3F0, &h98B5, &h11CF, {&hBB, &h82, &h00, &hAA, &h00, &hBD, &hCE, &h0B})
   pIHTMLDocument2->lpvtbl->QueryInterface(pIHTMLDocument2, @IID_ICustomDoc_, @pICustomDoc)
   IUnknown_Release(pIHTMLDocument2)
   IF pICustomDoc = NULL THEN EXIT FUNCTION

   ' // Create an instance of the IDocHostUIHandler class
   IF m_pIDocHostUIHandler = NULL THEN m_pIDocHostUIHandler = NEW CDocHostUIHandler2Impl
   ' // Set our IDocHostUIHandler interface for MSHTML
   ' // MSHTML will release its previous IDocHostUIHandler interface
   ' // (if one is present) and call pDocHostUIHandler's AddRef method.
   IF m_pIDocHostUIHandler THEN pICustomDoc->lpvtbl->SetUIHandler(pICustomDoc, _
      cast(IDocHostUIHandler PTR, cast(ULONG_PTR, m_pIDocHostUIHandler)))
   IUnknown_Release(pICustomDoc)

   CWB_DP("-END CWebBrowser.SetUIHandler")
END FUNCTION
' ========================================================================================


So, if you were thinking in something consistent, like Advise / Unadvise, you will be disappointed.

VB6 imposed a series of strict rules for events interfaces in OCXs, like inheriting from IDispatch, using a connection point and a default events interface. This way, its IDE could know which interface to use and how to use it. Low-level COM is another world.

José Roca

#42
> The code button : good choice

It runs so fast that not code or stop buttons are needed, and I like GUIs simple.

> may I ask for an little evolution :
> when changing the "Ole Automation view" option, it could be nice, the tree info and the code  be regenerated

Done.

BTW. How look the toolbar icons in your XP?

Marc Pons

QuoteOnly the default events interfaces can be detected, but not other additional events interfaces.

For example, ADO has two dispatch events interfaces, ConnectionEvents and RecordsetEvents, but also two VTable events interfaces, ConnectionEventsVt and RecordsetEventsVt. As VB6 can't use the VTable ones,

yes i can see them, to mark them as event interface in tlb, it could be a specific treatment
as most case the name is something....events...  , it could be possible to check the name to correctly affect them
but in most case if you already have the dispach ones is enougth.

Thanks also for the sample, how to fire the vtable events , i have to study it more deeply
( i must definively admit my knowledge on COM is  just at the surface )

Marc Pons

as requested

my toolbar in xp