Hosting Windowed ActiveX Controls in ASP Scripts (MSChart Example).

Environment: VC6.0 SP3+, NT4.0 SP3+, Win98 SE, Windows 2000/Me/XP, IIS 3.0+ or PWS
Have you ever wondered how to display charts or any other visual ActiveX controls in a web environment without having the need for the client (the browser in this case) to download these conrols in order to display the data. The best way of doing that is by creating an image from the control's client area and saving it on disk and then having that image as a link reference to display the image on the client page like the image shown above.
Well I found a lot of controls that did that, but none of them was giving away the source code for free, so I decided to write my own because I wanted to learn and on the other hand I wanted it to be custom made to suit my needs. In this Chart Example we will create an ATL project with a single COM object to host our MSChart Control.
The assumptions for the Chart Example are:
-
Running in a MS-Windows environment
-
Have a web server running on the machine (IIS or PWS)
-
Have MSChart ActiveX control registered on the system (It should come with the OS or VB or MS-Office or download it from Microsoft's web site)
There are 10 easy steps to the process:
-
Create a new ATL COM project and name it AXHostLib
-
Create an ActiveX Server Component Object and name it Host
-
Create a property and call it CreateObject with only the get attribute.
-
Create a method and call it SavePicture
-
Create a "dummy" dialog in the resource with id IDD_DIALOG1 that will be the parent window for our MSChart control
-
In the Host.h file add the include and the private section shown:
#include "afxtempl.h" ////////////////////////////////////////////////////////////// // CHost class ATL_NO_VTABLE CHost : private: CDialog* pDlg; CWnd* pControlWnd; CArray<IDISPATCH*, IDispatch*> m_DispatchArray; CArray<CDIALOG*, CDialog*> m_DialogArray; CArray<CWND*, CWnd*> m_ControlWndArray;
-
In the Host.cpp file the includes and the two methods (CreateObject and SavePicture) look like this:
Note:
Notice that the SavePicture method grabs the image from the clipboard and then saves it on the disk as a GIF, using a third-party library. You can use any other code you want at that point. You can find other functions for saving the image to disk in the http://www.codeguru.com/bitmap/ or you can download the CXImage library from http://www.codeproject.com/bitmap/cximage.asp and place the source in the CXImage directory of this project's source code. Using the CXImage library the image can be saved in one of the following formats PNG, BMP, JPG, TIFF or GIF. There are also other third party libraries that can be used under the GNU aggreement like the PaintLib found at http://www.paintlib.de/paintlib/.#include "comdef.h" #include "CXImage/CXImage/ximagif.h" //------------------------------------------------------- STDMETHODIMP CHost::get_CreateObject( BSTR ObjectID, long Width, long Height, IDispatch **pVal) { AFX_MANAGE_STATE(AfxGetStaticModuleState()) _bstr_t tmpbstr = _bstr_t(ObjectID, TRUE); CString ObjID = (char*) tmpbstr; HRESULT hr; IUnknown* pUnknown = NULL; //Create rect structure according to the size we want RECT rect; rect.left = 0; rect.top = 0; rect.bottom = Height; rect.right = Width; Create the dialog as a modeless one pDlg = new CDialog(); pDlg->Create(IDD_DIALOG1, NULL); //Create the window from an ActiveX Control with // parent the dialog pControlWnd = new CWnd(); pControlWnd->CreateControl( ObjID, NULL, WS_VISIBLE, rect, pDlg, 1); // Get the IUnknown in order to query the // IDispatch and return it to the ASP page pUnknown = pControlWnd->GetControlUnknown(); if (m_bOnStartPageCalled) hr = pUnknown->QueryInterface( IID_IDispatch, (void**) pVal); else *pVal = 0; //Save all the pointers for later clean up m_DispatchArray.Add(*pVal); m_DialogArray.Add(pDlg); m_ControlWndArray.Add(pControlWnd); return hr; } //------------------------------------------------------ STDMETHODIMP CHost::SavePicture(BSTR filename) { AFX_MANAGE_STATE(AfxGetStaticModuleState()) _bstr_t tmpbstr = _bstr_t(filename, TRUE); CString name = (char*) tmpbstr; //paste HANDLE hBitmap = NULL; if (OpenClipboard(NULL)) hBitmap = GetClipboardData(CF_DIB); if (hBitmap) { CxImage image(hBitmap); image.DecreaseBpp(8); image.SaveFile(name, CXIMAGE_FORMAT_GIF); } CloseClipboard(); return S_OK; }
- In the InitInstance of the Application in the
AXHostLib.cpp add the the following line:
AfxEnableControlContainer();
- Create the ASP page now and add the
following:
Note:
Make sure you change the line that says l_conn.Open to point to the correct directory where the database file is.
dim Host dim Chart dim l_conn 'Create our COM Object set Host = Server.CreateObject("AXHostLib.Host") Set Chart = Host.CreateObject("MSChart20Lib.MSChart", 600, 350) 'Create the data connection for our chart set l_conn = Server.CreateObject("ADODB.Connection") l_conn.Open "PROVIDER=Microsoft.Jet.OLEDB.3.51;Data Source=c:/inetpub/wwwroot/Stocks/data/MSFT.mdb;" dim l_rec dim l_sqlStatement set l_rec = Server.CreateObject("ADODB.Recordset") l_sqlstatement = "SELECT close FROM Quotes order by date asc" l_rec.Open l_sqlstatement, l_conn, 2, 3 'Set the Chart's properties and DataSource set Chart.DataSource = l_rec Chart.ChartType = 3 Chart.AllowSelections = 0 Chart.ShowLegend = 0 dim serX For Each serX In Chart.Plot.SeriesCollection serX.Pen.Width = 1 serX.Pen.VtColor.Automatic = 0 serX.Pen.VtColor.Red = 0 serX.Pen.VtColor.Green = 0 serX.Pen.VtColor.Blue = 255 Next Set XAxis = Chart.Plot.Axis(0) 'Scale of the ticks XAxis.CategoryScale.Auto = 0 XAxis.CategoryScale.DivisionsPerLabel = Chart.RowCount / 10 XAxis.CategoryScale.DivisionsPerTick = Chart.RowCount / 10 'Close connection and recordset l_rec.Close l_conn.Close 'Save the image Chart.EditCopy Host.SavePicture "c:/inetpub/wwwroot/Stocks/data/image.gif"
Links
CXImage Library with documentation and examples of how to use it.
PaintLib Library with documentation and examples of how to use it.
(The MSChart Example here uses only the GIF format from the CXImage Library to save the image on disk)
Downloads
Download demo project - 261 KbDownload source - 283 Kb
Comments