With the Visual Studio .NET IDE it is easy to create an ActiveX control, but there are some pitfalls and tricks, so I've created this step-by-step tutorial to help other programmers. The control shows a text, which is provided by a PARAM-tag within the object tag in a web page. Source code with project files: HelloWorld.zip
Select the "ATL Project" icon and enter "HelloWorld" for the name
Hit "OK" and commit the next screen with "Finish". All default-settings are OK.
Project->Add Class...: Select "ATL Control", Click "OK"
Check the "Insertable"-Checkbox in the Appearance-Screen:
Commit with "Finish"
Open the interface in the class viewer and add a property with the context menu "Add->Property" of the IHelloWorldCtl interface:
Property type: BSTR, name: text
Commit with "Finish".
Add a member variable for the text-property, show the content in the sample draw method and add the IPersistPropertyBagImpl class as a base class for using the PARAM from the HTML page to set the property:
Add the bold lines in the file HelloWorldCtl.h and replace two lines in the drawing method by the two bold lines:
PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
PROP_ENTRY("text", 1, CHelloWorldCtl::GetObjectCLSID())
// Example entries
// PROP_ENTRY("Property Description", dispid, clsid)
class ATL_NO_VTABLE CHelloWorldCtl :
SetTextAlign(di.hdcDraw, TA_CENTER|TA_BASELINE);Implement the getter and setter in HelloWorldCtl.cpp:
(rc.left + rc.right) / 2,
(rc.top + rc.bottom) / 2,
STDMETHODIMP CHelloWorldCtl::get_text(BSTR* pVal)
*pVal = m_text.Copy();
STDMETHODIMP CHelloWorldCtl::put_text(BSTR newVal)
m_text = newVal;
Using BSTR is a little bit tricky: If a parameter in COM is declared as "out", like in the get_text method, you get a pointer of a pointer of the value the caller wants and you have to create a new object, which is freed by the caller. If a parameter is declared as "in", like in the put_text method, you get a pointer of the value (think of BSTR as a "const char*") and you have to create your own object and copy the content. See http://www.michaelmoser.org/eightrules.htm for details. The CComBSTR class and the CW2A macro/class helps you a bit by encapsulating the details.
Now you can build the project. On my computer I had problems building it in debug mode, because there was a "fatal error LNK1113: invalid machine type 0xFF", but I fixed it by setting "Basic Runtime Check" in the project properties to "Default":
The control will be registered for you automaticly. Edit the automaticly generated test-page "HelloWorldCtl.htm" and add the "text"-parameter:
<TITLE>ATL 7.0 test page for object HelloWorldCtl</TITLE>
<OBJECT ID="HelloWorldCtl" CLASSID="CLSID:59E937ED-AC7E-407D-B40B-6545B1EECDE7">
<PARAM name="text" value="Hello World!">
Now you can view your control in the Internet Explorer and you should see the following, if you answer the warning question with "Yes":
If your control is safe, you can add the IObjectSafetyImpl class and you don't get the warning dialog (edit the file HelloWorldCtl.h):
public IObjectSafetyImpl<CHelloWorldCtl, INTERFACESAFE_FOR_UNTRUSTED_CALLER
8. July 2002, Frank Buß