ActiveX Controls

How can i use the activex controls example.. MSFlexGrid ActiveX Control.. in win32 Programming..
Boy! Have you ever asked for it! That's not trivial. Not at all.

Actually, I'm writing an ActiveX Grid control right now and using Win32 C++ clients (hosts) to test it. However, back to your original question. The MSFlexGrid ActiveX control was created for Visual Basic type environments, and in fact, that particular control is IDispatch based, so that it can even be used in scripting environments such as VB Script. Of course, its very easy to use in VB6 or .NET. Might I suggest you use C# if you want to use ActiveX controls?

Actually, getting that control to work in Win32 C++ would be a good project for me, but I just haven't gotten around to it yet (was planning it though). One of the things I don't like about the MSFlexGrid is that it is typical Microsoft bloatware (its many hundreds of K in size). The ActiveX grid control I am presently writing is nearly done, and is only 45K.

Since I don't have a C++ example to show you the closest thing I do have are PowerBASIC examples. I've actually worked with the MSFlexGrid very extensively in the PowerBASIC programming I do, and that language I use in exactly the same way as I use C++, i.e., straight Win32 Sdk style coding with RegisterClassEx(), CreateWindowEx(), WndProc() and the works. Would you like to see some of that code?
It's very easy with native OCX Container control
Nearly no code needed
Last edited on
@HenaryLee: Please don't hijack threads. If you have a question of your own, post a question of your own.

As for ActiveX, there is no simple way of explaining it. It is one of those topics that require that you read at least one good book on the matter. No way on Earth can this topic be explained in a forum post.
Below is an old PowerBASIC MSFlexGrid demo of mine where I instantiate an instance of the MSFlexGrid with four columns and twenty rows on a simple SDK window host. Part of it would readily translate to C++, and part of it is proprietary PowerBASIC syntax and wouldn’t translate.

The part that would translate well is in my WM_CREATE handler ( fnWndProc_OnCreate() )where I instantiate the grid through the use of the ATL ActiveX Container. First I call AtlAxWinInit(), then use CreateWindow() to create a “static” control to serve as the parent for the grid. This is then fed into AtlAxCreateControl() along with the ProgId and one ends up with an MSFlexGrid on one’s form.

My program is using the IDispatch interface and variants to feed info into the grid (setup of rows and columns, and so forth).

But the part that wouldn’t translate to C++ is the PowerBASIC WithEvents stuff where the Sink object is set up which receives the events generated in the Grid’s OutBound interface. Actually, this could be done low level too in PowerBASIC, but my example doesn’t show that. It relies on the internal implementation of the sink, no doubt something like old VB5 – VB6 did, and like .NET does now. .NET generates the interface wrappers, which is something like the MSFlexGrid.inc include listed below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#Compile            Exe
#Include            "Win32api.inc"
#Include Once       "Atl.inc"
#Include Once       "MSFlexGrid.inc"
%ID_CONTAINER       = 1250
Global oEvents      As DMSFlexGridEvents


Type WndEventArgs
  wParam            As Long
  lParam            As Long
  hWnd              As Dword
  hInst             As Dword
End Type


Class Class_DMSFlexGridEvents $CLSID_Event_DMSFlexGridEvents As Event
  Interface DMSFlexGridEvents $IID_DMSFlexGridEvents : Inherit IDispatch
    Method KeyDown <-602> (ByRef KeyCode As Integer, ByRef PB_Shift As Integer)
      MsgBox("You Pressed Some Key!")
    End Method
    Method DblClick <-601> ()
      MsgBox("You Double Clicked Somewhere In The Grid!")
    End Method
  End Interface
End Class


Sub GridSetup(Byval oGrid As IMSFlexGrid)
  Local vCols As Variant,vRows As Variant
  Local vVnt As Variant,vText As Variant
  Local vCol As Variant,vRow As Variant
  Local Grid As Dispatch

  Grid=oGrid
  vCols=4                     : Object Let Grid.Cols=vCols
  vRows=20                    : Object Let Grid.Rows=vRows
  vVnt=200:vCol=0             : Object Let Grid.ColWidth(vCol)=vVnt
  vVnt="Times New Roman"      : Object Let Grid.FontName = vVnt
  vVnt=10                     : Object Let Grid.FontSize=vVnt
  vCol=1:vVnt=1200:vRow=0:    : Object Let Grid.ColWidth(vCol)=vVnt
  Object Let Grid.Col=vCol    : Object Let Grid.Row=vRow
  vText="Column 1"            : Object Let Grid.Text=vText
  vCol=2:vRow=0:vVnt=1200     : Object Let Grid.ColWidth(vCol)=vVnt
  Object Let Grid.Col=vCol    : Object Let Grid.Row=vRow
  vText="Column 2"            : Object Let Grid.Text=vText
  vCol=3:vRow=0:vVnt=1200     : Object Let Grid.ColWidth(vCol)=vVnt
  Object Let Grid.Col=vCol    : Object Let Grid.Row=vRow
  vText="Column 3"            : Object Let Grid.Text=vText
End Sub


Function fnWndProc_OnCreate(Wea As WndEventArgs) As Long
  Local lpCreateStruct As CREATESTRUCT Ptr
  Local pStream,ppUnkContainer As IUnknown
  Local hContainer,hCtrl As Dword
  Local oGrid As IMSFlexGrid
  Local strCtrl As String

  lpCreateStruct=Wea.lParam
  Wea.hInst=@lpCreateStruct.hInstance
  Call AtlAxWinInit()
  hContainer=CreateWindowEx _
  ( _
    %WS_EX_OVERLAPPEDWINDOW,"static","",%WS_CHILD OR %WS_VISIBLE,10,10,280,250,Wea.hWnd,%ID_CONTAINER,Wea.hInst,Byval %NULL _
  )
  strCtrl=UCode$("MSFlexGridLib.MSFlexGrid") 'Program ID
  hCtrl=AtlAxCreateControl(Strptr(strCtrl),hContainer,pStream,ppUnkContainer)
  oEvents=Class "Class_DMSFlexGridEvents"
  oGrid=AtlAxGetDispatch(hContainer)
  If IsObject(oGrid) Then
     Events From oGrid Call oEvents
     Call GridSetup(oGrid)
  End If
  
  fnWndProc_OnCreate=0
End Function


Function fnWndProc_OnDestroy(Wea As WndEventArgs) As Long
  Events End oEvents
  Call PostQuitMessage(0)

  fnWndProc_OnDestroy=0
End Function


Function fnWndProc(ByVal hWnd As Long,ByVal wMsg As Long,ByVal wParam As Long,ByVal lParam As Long) As Long
  Local Wea As WndEventArgs

  Select Case As Long wMsg
    Case %WM_CREATE
      Wea.hWnd=hWnd : Wea.wParam=wParam : Wea.lParam=lParam
      fnWndProc=fnWndProc_OnCreate(Wea)
      Exit Function
    Case %WM_DESTROY
      Call PostQuitMessage(0)
      fnWndProc=fnWndProc_OnDestroy(Wea)
      Exit Function
  End Select

  fnWndProc=DefWindowProc(hWnd,wMsg,wParam,lParam)
End Function


Function WinMain(ByVal hIns As Long,ByVal hPrev As Long,ByVal lpCL As Asciiz Ptr,ByVal iShow As Long) As Long
  Local winclass As WndClassEx
  Local szAppName As Asciiz*16
  Local Msg As tagMsg
  Local hWnd As Dword

  szAppName="OCX Test"                                    : winclass.cbSize=SizeOf(winclass)
  winclass.style=%CS_HREDRAW Or %CS_VREDRAW               : winclass.lpfnWndProc=CodePtr(fnWndProc)
  winclass.cbClsExtra=0                                   : winclass.cbWndExtra=0
  winclass.hInstance=hIns                                 : winclass.hIcon=LoadIcon(%NULL,ByVal %IDI_APPLICATION)
  winclass.hCursor=LoadCursor(%NULL, ByVal %IDC_ARROW)    : winclass.hbrBackground=%COLOR_BTNFACE+1
  winclass.lpszMenuName=%NULL                             : winclass.lpszClassName=VarPtr(szAppName)
  Call RegisterClassEx(winclass)
  hWnd=CreateWindow(szAppName,"Try MSFlexGrid",%WS_OVERLAPPEDWINDOW Xor %WS_MAXIMIZEBOX,200,100,300,300,0,0,hIns,ByVal 0)
  Call ShowWindow(hWnd,iShow)
  While GetMessage(Msg,%NULL,0,0)
    TranslateMessage Msg
    DispatchMessage Msg
  Wend

  Function=msg.wParam
End Function 


Possibly within a few weeks I might be able to find the time to translate this fully to C++. The event interface presents the most difficulties, I believe.

This business of ActiveX controls and COM is something I've spent tremendous amounts of time (years) working with, but have only barely scratched the surface of the difficulties and complexities. For example, I doubt very much that there are more than a couple hundred people in the whole world that would know how to create a visual ActiveX control with OLE embedding support from scratch without tool support such as ATL or MFC. These latter tools auto generate wizard code to support many of the interfaces. Just using one of the controls though is a good bit easier, even with no tool support.


It just dawned on me - I almost forgot...ActiveX controls (MSFlexGrid, MSCAL.OCX, etc.) can be used very easily in C++ if one wants to use Microsoft's MFC class library. About ten years ago when I was attempting to learn MFC I had a book - I forget the name, but it taught how to make MFC GUI programs mostly with dialogs, but anyway, there was a whole chapter on using ActiveX controls. Its all just point and click stuff - same as with VB4 - VB6 or .NET. I can't tell you the exact sequence of steps, but basically one finds a references dialog box which lists all the registered COM objects on a system, and one then selects the control or COM object one wishes to use. Like I said, just point and click. When you select it the framework environment reads the type library for the control and auto-generates the necessary interface declarations for incomming and outgoing interfaces and these are included in your project. Everything then shows up in intellisense, so on and so forth. This was all with VC6.

I imagine VC9 and 10 have it too, but I never checked. I gave up with class frameworks a long time ago. But this question and issue points out the justification I suppose for using class frameworks instead of the raw Win32 Api. The low level underpinnings of COM and ActiveX technology are so complex it can eat you alive. I've studied and worked with it for years with several different languages (C, C++, Visual Basic 4 through 6, .NET, and PowerBASIC), but nontheless, it would be a major project for me right now to provide a working implementation of that PowerBASIC program listed above in low level C++ raw Win32 Api with no class framework support. On the other hand, with MFC (or possibly ATL - not sure) you would be there in a couple mouse clicks.
Topic archived. No new replies allowed.