Introduction
This article explains how one ATL full control (contained control) can be used dynamically inside another ATL composite control. This control is built in ATL 3.0.
Contained control
The contained Control is "Static - subclassed" ATL full control. I have used it to display any image but on top of another background image/color which can act as a border to the image. The control contains two LPPICTURE
data members m_lpPicture
and m_lpPictureBk
to hold the image and background image streams. Images can be displayed using this control by two ways.
- Either any image file physical path can be specified OR
- Any image
IPICTURE
stream can be directly assigned. (which may be used to directly display images stored in database in binary format
The main interfaces of this control used are:
HRESULT BorderColor([in]OLE_COLOR clr);
HRESULT BorderColor([out, retval]OLE_COLOR* pclr);
USED TO SET A BACKGROUND BORDER COLOR
HRESULT BorderWidth([in]long width);
HRESULT BorderWidth([out, retval]long* width);
USED TO SPECIFY THE BORDER WIDTH.
HRESULT Enabled([in]VARIANT_BOOL vbool);
HRESULT Enabled([out,retval]VARIANT_BOOL* pbool);
USED TO ENABLE THE CONTROL.
HRESULT SetParameters([in]BSTR ImagePath, [in] BSTR ImageBkPath, [in]
VARIANT_BOOL Proportional, [in] VARIANT_BOOL Transparent);
The proportionality can be specified as true if the image should be resized as per the control size proportionally. I have not coded it yet but hook is provided to do that.
HRESULT SetImageID([in] BSTR ImageID);
HRESULT ID([out, retval] BSTR *pVal);
HRESULT ID([in] BSTR newVal);
HRESULT DisplayName([out, retval] BSTR *pVal);
HRESULT DisplayName([in] BSTR newVal);
[HRESULT SetBkIPicture([in] LPUNKNOWN IBkPicture);
HRESULT SetParentWnd([in] DWORD hParent);
HRESULT SetIPicture([in] LPUNKNOWN Picture);
HRESULT BorderColorSelected([out, retval] OLE_COLOR *pVal);
HRESULT BorderColorSelected([in] OLE_COLOR newVal);
HRESULT Selected([out, retval] VARIANT_BOOL *pVal);
HRESULT Selected([in] VARIANT_BOOL newVal);
HRESULT BorderImgSelected([out, retval] BSTR *pVal);
HRESULT BorderImgSelected([in] BSTR newVal);
HRESULT BorderImage([out, retval] BSTR *pVal);
HRESULT BorderImage([in] BSTR newVal);
HRESULT ImagePath([out, retval] BSTR *pVal);
HRESULT ImagePath([in] BSTR newVal);
Compile the project StaticX.dsp and build the StaticX.dll.
The composite control
This control used the above StaticX control and a Recordset
to dynamically create the StaticX controls and display the image directly from database. To access database I am using a wrapper class of ADO which I downloaded from Code Project. Thanks to the author of the class.
This also incorporates paging. But I don't know how to add scrolling functionality. Need to find out. Any way, I used STL map to keep lists of the images in the RecordSet
and also the dynamic instances of StaticX control.
To host the control, CAxWindow
window instance is used.
The following are the interfaces used to interact with the main composite control.
HRESULT SetPagingDetails([in] int ItemsPerPage,
[in] int NumberOfColumns, [in] int PageSlotSize);
HRESULT GetPagingDetails([out] int *ItemsPerPage,
[out] int *NumberOfColumns, [out] int *PageSlotSize);
like 1,2�10. And then on clicking NEXT -> 11,12,�20.
HRESULT ConnectionString([out, retval] BSTR *pVal);
HRESULT ConnectionString([in] BSTR newVal);
HRESULT Init([in] int nMode);
HRESULT Query([out, retval] BSTR *pVal);
HRESULT Query([in] BSTR newVal);
HRESULT BackImage([out, retval] BSTR *pVal);
HRESULT BackImage([in] BSTR newVal);
HRESULT NextImage([out, retval] BSTR *pVal);
HRESULT NextImage([in] BSTR newVal);
STDAPI OleCreatePictureIndirect
(
PICTDESC
REFIID
BOOL,
VOID**
);
Rest all is pretty easy.
To display the image directly from database, I again used IPICTURE
stream. I read the image in binary format in a buffer which then I converted into stream and passed to StaticX control. Also to easily have stream operations, I have used CCOMString
, again a wrapper class provided by Paul E. Bible. Thanks for that implementation.