• Welcome to Theos PowerBasic Museum 2017.

ActiveX visual controls

Started by Edwin Knoppert, April 02, 2009, 11:21:12 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Edwin Knoppert

We process data and present it, how is not important but we would like to use an ActiveX or OLE container to present the data in Word, PowerPoint and Excel.
You can compare this part as embedding Excel into Word, doubleclick goes to editmode.

Now i have done the same with a VB6 usercontrol but instead of embedding this via INSERT>Object dialog we use the ... button in the Word's toolsbox and select our activex control.
This is unwanted.
Another issue is of course that this isn't a real OLE control, iow it will always need to be available and has no substitute image like Excel does.
This is something we allow, we suspect that writing a real OLE container is a terrible job.

So far our VB6 control is 100% interactive, a doubleclick produces an event so we can show a modal dialog to reedit the settings.
Question is how we could add this usercontrol into the INSERT>OBJECT dialog since users will know this dialog part better.
I found out that adding the key "Insertable" should do the trick but it does not work.
(We have a computer having MSCAL in that same list but this is not an OLE container)

Questions are:
1)
Is there a way to make this VB control insertable?

2)
Can we write a similar visible ActiveX control with your includes?
(And evt. make that insertable)

3)
Is there a way to make a real OLE container with PB, VB6 or C#?


Edwin Knoppert

Good news, my VB6 usercontrol is being kept as image in the Word document.
I moved it to another computer but did not copy the UC to this computer and the image shows fine.
Iow, it seems to behave like an ordinary OLE container.
When i save it to another worddoc and open it on the computer having the ocx it will activate the ocx fine (i have a timer + label to show)

Dominic Mitchell

#2
Quote3)
Is there a way to make a real OLE container with PB, VB6 or C#?

The short answer is yes, because the Phoenix 3.0 OLE container is an embedding and in-place container which was written using low-level COM.  It requires quite a bit of code and interfaces.
The container should support, among other things, the OLE presentation cache and IStorage(this is not optional).  This requires knowledge of how the prime the cache in cases where the OleCreateXXX functions are not used.
Dominic Mitchell
Phoenix Visual Designer
http://www.phnxthunder.com

Edwin Knoppert

>IPersistStorage
This is most likely the propertybag in VB i guess.
Since i have implemented this part in VB Word keeps the settings for the OCX.

--

Yesterday i created a VB usercontrol and like i mentioned, Word derives an image from the control for saving, this is cool so that another user can use the doc without the OCX (but no edit of course)
But i have managed to load a child control using a PB dll and Windowclass as child on the usercontrol.
Unf. it does not generate an image from that part, somehow it is embedded.

Any idea?

Dominic Mitchell

Quote
This is most likely the propertybag in VB i guess.
No. A property bag is a persistence mechanism that enables a container to store the properties of
an ActiveX usually as name/value pairs in a text file. It requires the container to support
IPropertyBag and the control to support IPersistPropertyBag or IPersistPropertyBag2.

Presentation data requires the container to support IStorage and allows it to display a visual representation
(usually a metafile) of and ActiveX when the ActiveX is not available or not activated.
I made a mistake in my earlier post when I said IPersistStorage.  IPersistStorage is required for OLE
documents and is optional for OCXs.

Quote
But i have managed to load a child control using a PB dll and Windowclass as child on the usercontrol.
Unf. it does not generate an image from that part, somehow it is embedded.
Oh? What interfaces does your control support?
What mechanism did you use to load it?
Dominic Mitchell
Phoenix Visual Designer
http://www.phnxthunder.com

Edwin Knoppert

#5
Here is the VB UC's code.
It does support preparing an passive image but only for it's own controls, not my child control.
The UC paint event does not work, i was messing a little and suspected a paint was done for the passive image.
I don't mind to much about using VB but if we can get rid of it..?
My colleague also prepared a UC via Borland c builder, it lacks storing properties (In a word doc) and soes not even produce the passive side.


Option Explicit
Private Const WS_CHILD = &H40000000
Private Const WS_VISIBLE = &H10000000
Private Const WS_Ex_ControlParent = &H10000
Private Type RECT
        Left As Long
        Top As Long
        Right As Long
        Bottom As Long
End Type

Private Declare Function CreateWindowEx Lib "user32" Alias "CreateWindowExA" (ByVal dwExStyle As Long, ByVal lpClassName As String, ByVal lpWindowName As String, ByVal dwStyle As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hWndParent As Long, ByVal hMenu As Long, ByVal hInstance As Long, lpParam As Any) As Long
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Declare Function GetClientRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
Private Declare Function MoveWindow Lib "user32" (ByVal hwnd As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal bRepaint As Long) As Long
Private Declare Function DestroyWindow Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long
Private Declare Function MoveToEx Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, lpPoint As POINTAPI) As Long
Private Type POINTAPI
        x As Long
        y As Long
End Type
Private Declare Function LineTo Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long
Private Declare Function UpdateWindow Lib "user32" (ByVal hwnd As Long) As Long

Const m_def_CustomData = ""
Const m_def_WindowClassName = ""
Const m_def_Library = ""
'Property Variables:
Dim m_CustomData As String
Dim m_WindowClassName As String
Dim m_Library As String
Dim m_hWndChild As Long
Dim m_DllInstance As Long

'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES!
'MemberInfo=13,0,0,
Public Property Get Library() As String
    Library = m_Library
End Property

Public Property Let Library(ByVal New_Library As String)
    m_Library = New_Library
    PropertyChanged "Library"
End Property

'Initialize Properties for User Control
Private Sub UserControl_InitProperties()
    m_Library = m_def_Library
    m_WindowClassName = m_def_WindowClassName
    m_CustomData = m_def_CustomData
End Sub

Private Sub UserControl_Paint()

    Dim hdc As Long
    Dim lpPoint As POINTAPI
   
    hdc = UserControl.hdc
   
    MoveToEx hdc, 10, 10, lpPoint
    LineTo hdc, 50, 50

    If m_hWndChild Then
        SendMessage m_hWndChild, 10000, hdc, 0
    End If

End Sub

'Load property values from storage
Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
    Dim R           As RECT
    Dim hWndParent As Long
    m_Library = PropBag.ReadProperty("Library", m_def_Library)
    m_WindowClassName = PropBag.ReadProperty("WindowClassName", m_def_WindowClassName)
    m_CustomData = PropBag.ReadProperty("CustomData", m_def_CustomData)
   
    hWndParent = UserControl.hwnd
    If Len(m_Library) And Len(m_WindowClassName) > 0 Then
   
        m_DllInstance = LoadLibrary(m_Library)
        If m_DllInstance <> 0 Then
            GetClientRect hWndParent, R
            m_hWndChild = CreateWindowEx(WS_Ex_ControlParent, m_WindowClassName _
                , "", WS_CHILD Or WS_VISIBLE _
                , R.Left, R.Top + 60, R.Right, R.Bottom, hWndParent, 0, m_DllInstance, ByVal 0&)
            'If m_hWndChild Then UserControl_Resize
'            MsgBox Str$(m_hWndChild)
        End If
   
    End If
   
End Sub

Private Sub UserControl_Resize()
    Dim hWndParent  As Long
    Dim R           As RECT
    hWndParent = UserControl.hwnd
    If m_hWndChild Then
        GetClientRect hWndParent, R
        MoveWindow m_hWndChild, R.Left, R.Top + 60, R.Right, R.Bottom, 1
    End If
End Sub

Private Sub UserControl_Terminate()
    If m_hWndChild Then
        DestroyWindow m_hWndChild
        FreeLibrary m_DllInstance
    End If
End Sub

'Write property values to storage
Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
    Call PropBag.WriteProperty("Library", m_Library, m_def_Library)
    Call PropBag.WriteProperty("WindowClassName", m_WindowClassName, m_def_WindowClassName)
    Call PropBag.WriteProperty("CustomData", m_CustomData, m_def_CustomData)
End Sub

'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES!
'MemberInfo=13,0,0,
Public Property Get WindowClassName() As String
    WindowClassName = m_WindowClassName
End Property

Public Property Let WindowClassName(ByVal New_WindowClassName As String)
    m_WindowClassName = New_WindowClassName
    PropertyChanged "WindowClassName"
End Property

'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES!
'MemberInfo=13,0,0,
Public Property Get CustomData() As String
    CustomData = m_CustomData
End Property

Public Property Let CustomData(ByVal New_CustomData As String)
    m_CustomData = New_CustomData
    PropertyChanged "CustomData"
End Property



Edwin Knoppert

The ocx is here:

http://www.hellobasic.com/trials/vb6uccontainer.zip

Use in Word and set properties.
Library, full folder+filename to  a dll which will load a windowclass (or use a standard windowclass like EDIT)
Windowclass, custom class or standard classname.
That's all..

Edwin Knoppert

I have some good news.
During the UC paint i now draw a line (see code) and this is stored for passive mode as well.
So maybe the WM_PRINT (my windowclass>UC DC) may work after all..

Edwin Knoppert

I renewed the code above and the zip.
The zip now also has the custom control and paint's itself onto the usercontrol on demand.
During the UC's paint i send a message (10000) to paint the CC on the UC.
The control is for testing purposes placed on top 60px so you can see it draws.
The line painting is done in the onpaint and *is* shown in the passive image but not the CC.

I suspect, when i toggle from devleopment to active in Word, it does not know the properties and can not load the dll for painting.
I get the same as with the passive images, green and a line.
That is to bad.