Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

ATL Dynamic Composite Control

0.00/5 (No votes)
30 Aug 2002 1  
Shows dynamic creation of one ATL full control in a composite control and also to show images directly from database without file system intervention.

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.

  1. Either any image file physical path can be specified OR
  2. 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);
//USED TO SET IMAGE FILE PHYSICAL PATH, 

//BACKGROUND IMAGE PATH FOR BORDER.

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);
//USING THESE INTERFACES THE CONTROL 

//CAN BE MADE TO HOLD SOME NAME AND ID

[HRESULT SetBkIPicture([in] LPUNKNOWN IBkPicture);
//USED TO SET BACKGROUND IMAGE STREAM DIRECTLY

HRESULT SetParentWnd([in] DWORD hParent);
//USED TO SET THE PARENT WINDOW (It is used to send 

//messages to parent window as I was not able to figure

//out how to source events in the Composite control in case 

//this control will be dynamically generated.

HRESULT SetIPicture([in] LPUNKNOWN Picture);
//USED TO SET IMAGE STREAM DIRECTLY

HRESULT BorderColorSelected([out, retval] OLE_COLOR *pVal);
HRESULT BorderColorSelected([in] OLE_COLOR newVal);
//USED TO SET BORDER COLOR IF THIS CONTROL IS SET ACTIVE (Selected)

HRESULT Selected([out, retval] VARIANT_BOOL *pVal);
HRESULT Selected([in] VARIANT_BOOL newVal);
//USED TO SET THIS CONTROL AS ACTIVE (Currently selected, 

//this will change to border of the image to the color specified in 

//BorderSelectedColor or image specified in BorderImgSelected)

HRESULT BorderImgSelected([out, retval] BSTR *pVal);
HRESULT BorderImgSelected([in] BSTR newVal);
//USED TO SET BORDER IMAGE IF THIS CONTROL IS SET ACTIVE (Selected)

HRESULT BorderImage([out, retval] BSTR *pVal);
HRESULT BorderImage([in] BSTR newVal);
//USED TO SET BORDER IMAGE IF THIS CONTROL IS INACTIVE (Not Selected)

HRESULT ImagePath([out, retval] BSTR *pVal);
HRESULT ImagePath([in] BSTR newVal);
//ALTERNATIVE TO SET IMAGE PHYSICAL PATH

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);
//USED TO SET PAGING DETAILS AS NUMBER OF IMAGES 

//PER PAGE, NUMBER OF COLUMNS.

//Note: PageSlotSize is provided to have a funtionality 

like 1,2�10. And then on clicking NEXT -> 11,12,�20. 
//In this case the PageSlotSize is 10. Normally keep it 1.


HRESULT ConnectionString([out, retval] BSTR *pVal);
HRESULT ConnectionString([in] BSTR newVal);
//USED TO SET THE CONNECTION STRING FOR THE DATABASE CONNECTIVITY.

//(Connection Provider String).


HRESULT Init([in] int nMode);
//USED TO INITIALIZE THE CONTROL AFTER ALL PARAMETERS ARE SET.

HRESULT Query([out, retval] BSTR *pVal);
HRESULT Query([in] BSTR newVal);
//QUERY FOR THE RECORD SET.

//(Note that your recordset should contain the following columns(fields)

//1- ImageID : To contain an Image ID

//2- Image : To contain image in binary format.


HRESULT BackImage([out, retval] BSTR *pVal);
HRESULT BackImage([in] BSTR newVal);
//USED TO SET IMAGE FOR BACK BUTTON

//(Physical path of image)

HRESULT NextImage([out, retval] BSTR *pVal);
HRESULT NextImage([in] BSTR newVal);
//USED TO SET IMAGE FOR NEXT BUTTON

//(Physical path of image)

//I used OleCreatePictureIndirect to create a 

//IPICTURE from a bmp that is created for the

//Background Border Image(of some specified color).

STDAPI OleCreatePictureIndirect
(
PICTDESC //Pointer to the structure of parameters for picture

REFIID //Reference to the identifier of the interface

BOOL, //Whether the picture is to be destroyed

VOID** //Address of output variable that receives the 

// interface pointer requested in riid

);

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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here