CWindow RC 21

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

Previous topic - Next topic

José Roca

CWindow Release Candidate 21

Incorporates some minor changes and a few functions more.

The novelty is the new CWebBrowser class. It allows to embed instances of the WebBrowser control using COleCon.

It also provides methods to connect and disconnect to the events fired by the WebBrowser control, set event handlers (pointers to callback procedures) for both the DWebBrowser2 and IDocHostUIHandler2 interfaces, a method to navigate to a URL, and function to get references to the OLE Container class and the IWebBrowser2 interface.

The file AfxExDisp.bi provides declarations to call the methods of the WebBrowser interfaces using abstract methods.

The WebBrowser events sink class is provided in the file CWebBrowserEventsImpl.inc, and the DocHostUIHandler events sink class is provided in the file CDocHostUIHandler2Impl.inc.

In a similar way to Visual Basic, it allows to subscribe only to the events in which you're interested, e.g.


   ' // Add a WebBrowser control
   DIM pwb AS CWebBrowser = CWebBrowser(@pWindow, IDC_WEBBROWSER, 0, 0, pWindow.ClientWidth, pWindow.ClientHeight)
   ' // Connect events
   pwb.Advise
   ' // Set event callback procedures
   pwb.SetEventProc("StatusTextChange", @WebBrowser_StatusTextChangeProc)
   pwb.SetEventProc("DocumentComplete", @WebBrowser_DocumentCompleteProc)
   ' // Set the IDocHostUIHandler interface
   pwb.SetUIHandler
   ' // Set event callback procedures
   pwb.SetUIEventProc("ShowContextMenu", @DocHostUI_ShowContextMenuProc)
   pwb.SetUIEventProc("GetHostInfo", @DocHostUI_GetHostInfo)
   pwb.SetUIEventProc("TranslateAccelerator", @DocHostUI_TranslateAccelerator)
   ' // Navigate to a URL
   pwb.Navigate("http://com.it-berater.org/")


The help file provides prototypes for all the WebBrowser and IDocHostUIHandler events in the SetEventProc and SetUIEventProc topics.

And last, but not the least, it is High DPI aware.

Update 12 Sep 2016:

AfxOpenFileDialog: Returned filename had a trailing comma (file AfxWin.inc).
TreeView_ItemExists: Was causing memory corruption (file AfxCtl.inc).


José Roca

#1
An small example:


' ########################################################################################
' Microsoft Windows
' Contents: WebBrowser customization test
' Compiler: FreeBasic 32 & 64 bit
' Copyright (c) 2016 Jose Roca. Freeware. Use at your own risk.
' THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
' EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
' MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
' ########################################################################################

#define UNICODE
'#define _OC_DEBUG_ 1
'#define _CWB_DEBUG_ 1
#INCLUDE ONCE "Afx/CWindow.inc"
#INCLUDE ONCE "Afx/AfxCtl.inc"
#INCLUDE ONCE "Afx/CWebBrowser/CWebBrowser.inc"
USING Afx

CONST IDC_WEBBROWSER = 1001
CONST IDC_SATUSBAR = 1002

DECLARE FUNCTION WinMain (BYVAL hInstance AS HINSTANCE, _
                          BYVAL hPrevInstance AS HINSTANCE, _
                          BYVAL szCmdLine AS ZSTRING PTR, _
                          BYVAL nCmdShow AS LONG) AS LONG

   END WinMain(GetModuleHandleW(NULL), NULL, COMMAND(), SW_NORMAL)

DECLARE FUNCTION WndProc (BYVAL hwnd AS HWND, BYVAL uMsg AS UINT, BYVAL wParam AS WPARAM, BYVAL lParam AS LPARAM) AS LRESULT

' // Forward declarations
DECLARE SUB WebBrowser_StatusTextChangeProc (BYVAL this AS CWebBrowserEventsImpl PTR, BYVAL pwszText AS WSTRING PTR)
DECLARE SUB WebBrowser_DocumentCompleteProc (BYVAL this AS CWebBrowserEventsImpl PTR, BYVAL pdisp AS IDispatch PTR, BYVAL vUrl AS VARIANT PTR)
DECLARE FUNCTION DocHostUI_ShowContextMenuProc (BYVAL this AS CDocHostUIHandler2Impl PTR, BYVAL dwID AS DWORD, BYVAL ppt AS POINT PTR, BYVAL pcmdtReserved AS IUnknown PTR, BYVAL pdispReserved AS IDispatch PTR) AS HRESULT
DECLARE FUNCTION DocHostUI_GetHostInfo (BYVAL this AS CDocHostUIHandler2Impl PTR, BYVAL pInfo AS DOCHOSTUIINFO PTR) AS HRESULT
DECLARE FUNCTION DocHostUI_TranslateAccelerator (BYVAL this AS CDocHostUIHandler2Impl PTR, BYVAL lpMsg AS LPMSG, BYVAL pguidCmdGroup AS const GUID PTR, BYVAL nCmdID AS DWORD) AS HRESULT

' ========================================================================================
' Main
' ========================================================================================
FUNCTION WinMain (BYVAL hInstance AS HINSTANCE, _
                  BYVAL hPrevInstance AS HINSTANCE, _
                  BYVAL szCmdLine AS ZSTRING PTR, _
                  BYVAL nCmdShow AS LONG) AS LONG

   ' // Set process DPI aware
   ' // The recommended way is to use a manifest file
   AfxSetProcessDPIAware

   ' // Creates the main window
   DIM pWindow AS CWindow
   ' -or- DIM pWindow AS CWindow = "MyClassName" (use the name that you wish)
   DIM hwndMain AS HWND = pWindow.Create(NULL, "Embedded WebBrowser control with events and customization", @WndProc)
   ' // Sizes it by setting the wanted width and height of its client area
   pWindow.SetClientSize(750, 450)
   ' // Centers the window
   pWindow.Center

   ' // Add a status bar
   DIM hStatusbar AS HWND = pWindow.AddControl("Statusbar", , IDC_SATUSBAR)

   ' // Add a WebBrowser control
   DIM pwb AS CWebBrowser = CWebBrowser(@pWindow, IDC_WEBBROWSER, 0, 0, pWindow.ClientWidth, pWindow.ClientHeight)
   ' // Connect events
   pwb.Advise
   ' // Set event callback procedures
   pwb.SetEventProc("StatusTextChange", @WebBrowser_StatusTextChangeProc)
   pwb.SetEventProc("DocumentComplete", @WebBrowser_DocumentCompleteProc)
   ' // Set the IDocHostUIHandler interface
   pwb.SetUIHandler
   ' // Set event callback procedures
   pwb.SetUIEventProc("ShowContextMenu", @DocHostUI_ShowContextMenuProc)
   pwb.SetUIEventProc("GetHostInfo", @DocHostUI_GetHostInfo)
   pwb.SetUIEventProc("TranslateAccelerator", @DocHostUI_TranslateAccelerator)
   ' // Navigate to a URL
   pwb.Navigate("http://com.it-berater.org/")

   ' // Display the window
   ShowWindow(hWndMain, nCmdShow)
   UpdateWindow(hWndMain)

   ' // Dispatch Windows messages
   DIM uMsg AS MSG
   WHILE (GetMessageW(@uMsg, NULL, 0, 0) <> FALSE)
      IF AfxForwardMessage(GetFocus, @uMsg) = FALSE THEN
         IF IsDialogMessageW(hWndMain, @uMsg) = 0 THEN
            TranslateMessage(@uMsg)
            DispatchMessageW(@uMsg)
         END IF
      END IF
   WEND
   FUNCTION = uMsg.wParam

END FUNCTION
' ========================================================================================

' ========================================================================================
' Main window procedure
' ========================================================================================
FUNCTION WndProc (BYVAL hwnd AS HWND, BYVAL uMsg AS UINT, BYVAL wParam AS WPARAM, BYVAL lParam AS LPARAM) AS LRESULT

   SELECT CASE uMsg

      CASE WM_COMMAND
         SELECT CASE LOWORD(wParam)
            CASE IDCANCEL
               ' // If ESC key pressed, close the application by sending an WM_CLOSE message
               IF HIWORD(wParam) = BN_CLICKED THEN
                  SendMessageW hwnd, WM_CLOSE, 0, 0
                  EXIT FUNCTION
               END IF
         END SELECT

      CASE WM_SIZE
         ' // Optional resizing code
         IF wParam <> SIZE_MINIMIZED THEN
            ' // Resize the toolbar
            DIM hStatusBar AS HWND = GetDlgItem(hwnd, IDC_SATUSBAR)
            SendMessage hStatusBar, uMsg, wParam, lParam
            ' // Calculate the size of the status bar
            DIM StatusBarHeight AS DWORD, rc AS RECT
            GetWindowRect hStatusBar, @rc
            StatusBarHeight = rc.Bottom - rc.Top
            ' // Retrieve a pointer to the CWindow class
            DIM pWindow AS CWindow PTR = AfxCWindowPtr(hwnd)
            ' // Move the position of the control
            IF pWindow THEN pWindow->MoveWindow GetDlgItem(hwnd, IDC_WEBBROWSER), _
               0, 0, pWindow->ClientWidth, pWindow->ClientHeight - StatusBarHeight / pWindow->ryRatio, CTRUE
         END IF

    CASE WM_DESTROY
         ' // Ends the application by sending a WM_QUIT message
         PostQuitMessage(0)
         EXIT FUNCTION

   END SELECT

   ' // Default processing of Windows messages
   FUNCTION = DefWindowProcW(hwnd, uMsg, wParam, lParam)

END FUNCTION
' ========================================================================================

' ========================================================================================
' Process the WebBrowser StatusTextChange event.
' ========================================================================================
SUB WebBrowser_StatusTextChangeProc (BYVAL this AS CWebBrowserEventsImpl PTR, BYVAL bstrText AS AFX_BSTR)
   IF bstrText THEN StatusBar_SetText(GetDlgItem(GetParent(this->m_hwndContainer), IDC_SATUSBAR), 0, *bstrText)
END SUB
' ========================================================================================

' ========================================================================================
' Process the WebBrowser DocumentComplete event.
' ========================================================================================
SUB WebBrowser_DocumentCompleteProc (BYVAL this AS CWebBrowserEventsImpl PTR, BYVAL pdisp AS IDispatch PTR, BYVAL vUrl AS VARIANT PTR)
   ' // The vUrl parameter is a VT_BYREF OR VT_BSTR variant
   DIM varUrl AS VARIANT
   VariantCopyInd(@varUrl, vUrl)
   DIM bstrUrl AS AFX_BSTR = varUrl.bstrVal
   IF bstrUrl THEN StatusBar_SetText(GetDlgItem(GetParent(this->m_hwndContainer), IDC_SATUSBAR), 0, "Document complete: " & *bstrUrl)
   VariantClear(@varUrl)
END SUB
' ========================================================================================

' ========================================================================================
' Process the IDocHostUIHandler ShowContextMenu event.
' ========================================================================================
FUNCTION DocHostUI_ShowContextMenuProc (BYVAL this AS CDocHostUIHandler2Impl PTR, BYVAL dwID AS DWORD, BYVAL ppt AS POINT PTR, BYVAL pcmdtReserved AS IUnknown PTR, BYVAL pdispReserved AS IDispatch PTR) AS HRESULT
   ' // This event notifies that the user has clicked the right mouse button to show the
   ' // context menu. We can anulate it returning %S_OK and show our context menu.
   ' // Do not allow to show the context menu
   AfxMsg "Sorry! Context menu disabled"
   RETURN S_OK
   ' // Host did not display its UI. MSHTML will display its UI.
   RETURN S_FALSE
END FUNCTION
' ========================================================================================

' ========================================================================================
' Process the IDocHostUIHandler GetHostInfo event.
' ========================================================================================
PRIVATE FUNCTION DocHostUI_GetHostInfo (BYVAL this AS CDocHostUIHandler2Impl PTR, BYVAL pInfo AS DOCHOSTUIINFO PTR) AS HRESULT
   IF pInfo THEN
      pInfo->cbSize = SIZEOF(DOCHOSTUIINFO)
      pInfo->dwFlags = DOCHOSTUIFLAG_NO3DBORDER OR DOCHOSTUIFLAG_THEME OR DOCHOSTUIFLAG_DPI_AWARE
      pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT
      pInfo->pchHostCss = NULL
      pInfo->pchHostNS = NULL
   END IF
   RETURN S_OK
END FUNCTION
' ========================================================================================

' ========================================================================================
' Process the IDocHostUIHandler TranslateAccelerator event.
' ========================================================================================
PRIVATE FUNCTION DocHostUI_TranslateAccelerator (BYVAL this AS CDocHostUIHandler2Impl PTR, BYVAL lpMsg AS LPMSG, BYVAL pguidCmdGroup AS const GUID PTR, BYVAL nCmdID AS DWORD) AS HRESULT
   ' // When you use accelerator keys such as TAB, you may need to override the
   ' // default host behavior. The example shows how to do this.
    IF lpMsg->message = WM_KEYDOWN AND lpMsg->wParam = VK_TAB THEN
       RETURN S_FALSE   ' S_OK to disable tab navigation
    END IF
   ' // Return S_FALSE if you don't process the message
   RETURN S_FALSE
END FUNCTION
' ========================================================================================


José Roca

Update 12 Sep 2016:

AfxOpenFileDialog: Returned filename had a trailing comma (file AfxWin.inc).
TreeView_ItemExists: Was causing memory corruption (file AfxCtl.inc).

José Roca

#3
By "popular" demand (James and Marc), I have started to work in a TypeLib Browser for Free Basic.

The attached file contains the source code, the resources and an 64-bit executable.

The only part missing is the code generation. Maybe I will do it parsing the information displayed in the treeview instead of messing the convoluted typelib parsing code that I have managed to keep clean.

Sorting

Click the wanted ListView header column.

Expand

Expands all the nodes in the TreeView.

Collapse

Collapses all the nodes in the TreeView.

Size

The main window is resizable. The size and placement are saved in the .ini file.

ListView

The width of the columns can be changed with the mouse and the order of the columns can be changed by dragging and dropping the column header with the mouse.

Options

Currently, only the "Use Automation View" option has been implemented.

After changing this option, you must reparse the typelib by double clicking it again in the ListView.

The browser supports two kinds of  views, the default VTable view and the Automation view, aka Visual Basic view.

The VTable view lists only the methods and properties that belongs to an interface. It is the more suitable for making interface declarations that use abstract methods.

The Automation view, lists all the methods and properties, including these belonging to the inherited interfaces. It is the more suitable for making interface declarations and object macros like the ones provided in the FB official headers. A minor quirk is that, as it was designed for Automation lnguages like VB6, in which the name of right side parameter of the properties is not needed, only the result type, it does not return the name. The browser uses RHS (Right Hand Side) as the name of these parameters.

Load

You can load unregistered type libraries, either stand alone ones (.TLB) or attached in .OCX, .DLL and .EXE files as a resource.

José Roca

For those interested, I have posted an small tutorial about the making of the typelib browser. As I don't have talent for writing, I have heavily illustrated it with code. It is easier to me to write code than to explain what it does...

See: http://www.planetsquires.com/protect/forum/index.php?topic=3933.0

José Roca

Found a little bug in the CParseTypeLib.GetFunctions method (TLB_ParseLib.inc).

Instead of


         IF UCASE$(cbstrName) = "QUERYINTERFACE" AND pFuncdesc->oVft > 24 THEN cbstrName += "_"
         IF UCASE$(cbstrName) = "ADDREF" AND pFuncdesc->oVft > 24 THEN cbstrName += "_"
         IF UCASE$(cbstrName) = "RELEASE" AND pFuncdesc->oVft > 24 THEN cbstrName += "_"
         IF UCASE$(cbstrName) = "GETTYPEINFOCOUNT" AND pFuncdesc->oVft > 24 THEN cbstrName += "_"
         IF UCASE$(cbstrName) = "GETTYPEINFO" AND pFuncdesc->oVft > 24 THEN cbstrName += "_"
         IF UCASE$(cbstrName) = "GETIDSOFNAMES" AND pFuncdesc->oVft > 24 THEN cbstrName += "_"
         IF UCASE$(cbstrName) = "INVOKE" AND pFuncdesc->oVft > 24 THEN cbstrName += "_"


We should use


         DIM vtOffset AS LONG
#ifdef __FB_64BIT__
         vtOffset = 48
#else
         vtOffset = 24
#endif
         IF UCASE$(cbstrName) = "QUERYINTERFACE" AND pFuncdesc->oVft > vtOffset THEN cbstrName += "_"
         IF UCASE$(cbstrName) = "ADDREF" AND pFuncdesc->oVft > vtOffset THEN cbstrName += "_"
         IF UCASE$(cbstrName) = "RELEASE" AND pFuncdesc->oVft > vtOffset THEN cbstrName += "_"
         IF UCASE$(cbstrName) = "GETTYPEINFOCOUNT" AND pFuncdesc->oVft > vtOffset THEN cbstrName += "_"
         IF UCASE$(cbstrName) = "GETTYPEINFO" AND pFuncdesc->oVft > vtOffset THEN cbstrName += "_"
         IF UCASE$(cbstrName) = "GETIDSOFNAMES" AND pFuncdesc->oVft > vtOffset THEN cbstrName += "_"
         IF UCASE$(cbstrName) = "INVOKE" AND pFuncdesc->oVft > vtOffset THEN cbstrName += "_"


Because pointers are 8 bytes in 64-bit and 4 bytes in 32 bits.

José Roca

#6
Another little bug, this time in CParseTypeLib.GetParameters.

Instead of


         IF cbstrTypeKind = "TKIND_UNKNOWN" THEN cbstrFBKeyword = "IUnknown PTR"
         IF cbstrTypeKind = "TKIND_DISPATCH" THEN cbstrFBKeyword = "IDispatch PTR"


should be


         IF cbstrTypeKind = "TKIND_UNKNOWN" THEN cbstrFBKeyword = "IUnknown"
         IF cbstrTypeKind = "TKIND_DISPATCH" THEN cbstrFBKeyword = "IDispatch"


I expect there will be some more minor bugs lithe this one. When code generation will be added, they will become self evident, since the compiler will detect many of the mistakes.

José Roca

Not a bug, but additional parsing.

In CParseTypeLib.GetConstants, change


      SELECT CASE pVarDesc->elemdescVar.tdesc.vt
         CASE VT_I1, VT_UI1, VT_I2, VT_UI2, VT_INT, VT_UINT
            cbstrValue = **cbstrValue & " (&h" & HEX(VAL(**cbstrValue), 8) & ")"
      END SELECT


to


      SELECT CASE pVarDesc->elemdescVar.tdesc.vt
         CASE VT_I1, VT_UI1, VT_I2, VT_UI2, VT_INT, VT_UINT
            cbstrValue = **cbstrValue & " (&h" & HEX(VAL(**cbstrValue), 8) & ")"
         CASE VT_BSTR, VT_LPSTR, VT_LPWSTR
            ' // cdosys.dll contains VT_BSTR constants
            cbstrValue = CHR(34) & **cbstrValue & CHR(34)
         CASE VT_PTR
            ptdesc = pVarDesc->elemdescVar.tdesc.lptdesc
            IF ptdesc THEN
               ' WORD PTR (null terminated unicode string)
               ' hxds.dll contains a module with these kind of constants.
               IF ptdesc->vt = VT_UI2 THEN cbstrValue = CHR(34) & **cbstrValue & CHR(34)
            END IF
         ' // Other types can be VT_CARRAY and VT_USERDEFINED, but don't have a typelib to test
      END SELECT


Some details can't be checked unless I have an appropriate typelib.

José Roca

Another little correction, in CParseTypeLib.GetParameters

After


            CASE "VT_LPSTR"
               cbstrFBSyntax = "BYVAL " & cbstrParamName & " AS ZSTRING PTR"
            CASE "VT_LPWSTR"
               cbstrFBSyntax = "BYVAL " & cbstrParamName & " AS WSTRING PTR"


add


            CASE "VT_BSTR"
               cbstrFBSyntax = "BYVAL " & cbstrParamName & " AS BSTR"


José Roca

Will need some help to find mistakes, specially with parameters.

In CParseTypeLib.GetParameters, change


            CASE "VT_UNKNOWN"
               IF wIndirectionLevel = 2 THEN
                  cbstrFBSyntax = "BYVAL " & cbstrParamName & " AS IUnknown PTR PTR"
               ELSE
                  cbstrFBSyntax = "BYVAL " & cbstrParamName & " AS IUnknown PTR"
               END IF
            CASE "VT_DISPATCH"
               IF wIndirectionLevel = 2 THEN
                  cbstrFBSyntax = "BYVAL " & cbstrParamName & " AS IDispatch PTR PTR"
               ELSE
                  cbstrFBSyntax = "BYVAL " & cbstrParamName & " AS IDispatch PTR"
               END IF


to


            CASE "VT_UNKNOWN"
               IF wIndirectionLevel = 2 THEN
                  cbstrFBSyntax = "BYVAL " & cbstrParamName & " AS IUnknown PTR PTR"
               ELSE
                  IF (wFlags AND PARAMFLAG_FOUT) = PARAMFLAG_FOUT THEN
                     cbstrFBSyntax = "BYVAL " & cbstrParamName & " AS IUnknown PTR PTR"
                  ELSE
                     cbstrFBSyntax = "BYVAL " & cbstrParamName & " AS IUnknown PTR"
                  END IF
               END IF
            CASE "VT_DISPATCH"
               IF wIndirectionLevel = 2 THEN
                  cbstrFBSyntax = "BYVAL " & cbstrParamName & " AS IDispatch PTR PTR"
               ELSE
                  IF (wFlags AND PARAMFLAG_FOUT) = PARAMFLAG_FOUT THEN
                     cbstrFBSyntax = "BYVAL " & cbstrParamName & " AS IDispatch PTR PTR"
                  ELSE
                     cbstrFBSyntax = "BYVAL " & cbstrParamName & " AS IDispatch PTR"
                  END IF
               END IF


The use by FB of PTR PTR is somewhat problematic. Probably I will have to do more changes.


Marc Pons

#10
Jose

Thanks another time to your huge job.
The tutorial is very, very interresting...

As you could imagine, i tried it immediatly , but the exe is 64bits so not working for me

I'd complied it , no problem to compile but nothing when executing...

why? because i'm in xp sp3 and you put
#define _WIN32_WINNT &h0602
wich is not true for me, changing it by :
#define _WIN32_WINNT &h0502
error in
SendMessageW(hHeader, HDM_SETFOCUSEDITEM, 0, ColumnToSort)

so simply commented that line ( and after put #if(_WIN32_WINNT > &h0602) ) was enougth to get it working !

made also your evolutions, seems working well

You know, i was digging on the variant types and i noticed something :

about the INT_ and UINT_ types 
theses types are in fact typedef for long and ulong types : 32bit  ( x86 or 64)

but normally they are
VT_INT       A signed machine integer.
VT_UINT      An unsigned  machine integer.

I think it would be better to use
for VT_INT         Integer
     VT_UINT       UInteger

wich are 32 or 64 depending the os

do you agree ?

last update  : remark on BOOL , probably better to use BOOLEAN
CASE    11 : s = "BOOLEAN"     '"BOOL"               ' VT_BOOL


Marc Pons

#11
And if needed 2 ocx samples if needed for your tests of code

outgoing2.ocx: with only ole automation interface (and events ole automation interface)

gauge32.ocx: with only dispach interface (and events dispach interface)

José Roca

Quote
about the INT_ and UINT_ types
theses types are in fact typedef for long and ulong types : 32bit  ( x86 or 64)

but normally they are
VT_INT       A signed machine integer.
VT_UINT      An unsigned  machine integer.

I think it would be better to use
for VT_INT         Integer
     VT_UINT       UInteger

wich are 32 or 64 depending the os

do you agree ?

No, I don't. In COM 64 bit, these values continue being 32 bit. Using Integer and UInteger fails in 64 bit (I have tested it).

Quote
last update  : remark on BOOL , probably better to use BOOLEAN

A C++ BOOL is not the same that FB BOOLEAN. A BOOL uses 0 for FALSE and 1 for TRUE, not 0 and -1. In COM, the equivalent to FB's BOOLEAN is VARIANT_BOOL.

Thanks very much for the files. I will test them.

José Roca

I have made the corrections for XP. Hope the next version will compile without problems. I already had used the AfxOpenFileDialog instead of the COM version.

I have fixed some typos in the tutorial and modified reply #2, in which I had repeated the code for the interface definition instead of the code to load the typelib.

José Roca

#14
> gauge32.ocx: with only ole automation interface (and events ole automation interface)

Can be loaded with a 32 bit of the browser. With 64 bit, it gives error TYPE_E_UNSUPFORMAT, that means that it has an older format not supported.

It has been usful to test the code that retrieves the alias names and the data members. Only very old VB6 OCXs use data members. If I remember well, these are shared (global) variables that can be retrieved directly using Automation, not vtable calls. Many years ago, Microsoft modified some of his OCXs adding properties to return these values and deprecated and advised against the use of data members.

> outgoing2.ocx: with only dispach interface (and events dispach interface)

Seems to work fine.

What I have to revise carefully is the code that decides if the parameter has to be passed by value (no problem) of by reference (something PTR or PTR PTR). Checking the indirection level and if it is an out parameter should be the way, but some buggy type libraries don't have the PARAMFLAG_FOUT set, and checking by name is only useful for IUnknown and IDispatch.

There are many buggy type libraries that don't have some flags set, I also found one that did not returned the return type of some properties, etc. In these cases, we can only make a guess.