ATL 动态复合控件






1.71/5 (3投票s)
2002年8月31日
2分钟阅读

75852

1801
展示了在一个复合控件中动态创建ATL全控件,以及无需文件系统干预即可直接从数据库显示图像的方法。
引言
本文解释了如何在一个ATL复合控件中动态使用一个ATL全控件(包含的控件)。此控件是在ATL 3.0中构建的。
包含的控件
包含的控件是“静态 - 子类化”的ATL全控件。我用它来显示任何图像,但在另一个背景图像/颜色之上,该背景图像/颜色可以作为图像的边框。该控件包含两个 LPPICTURE
数据成员 m_lpPicture
和 m_lpPictureBk
,用于保存图像和背景图像流。可以使用两种方式通过此控件显示图像。
- 可以指定任何图像文件的物理路径,或者
- 可以直接分配任何图像
IPICTURE
流。(这可以用于直接显示以二进制格式存储在数据库中的图像)
此控件使用的主要接口是
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.
如果应该根据控件大小按比例调整图像大小,则可以将比例指定为 true。我还没有编写代码,但提供了钩子来执行此操作。
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
编译项目 StaticX.dsp 并构建 StaticX.dll。
复合控件
此控件使用了上述 StaticX 控件和一个 Recordset
来动态创建 StaticX 控件并直接从数据库显示图像。 为了访问数据库,我使用了一个从 Code Project 下载的 ADO 包装类。感谢该类的作者。
这还包含了分页功能。但是,我不知道如何添加滚动功能。 需要找出。 无论如何,我使用了 STL map 来保存 RecordSet
中的图像列表以及 StaticX 控件的动态实例。
为了承载控件,使用了 CAxWindow
窗口实例。
以下是用于与主复合控件交互的接口。
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 );
其余都很容易。
为了直接从数据库显示图像,我再次使用了 IPICTURE
流。我以二进制格式在缓冲区中读取图像,然后将其转换为流并传递给 StaticX 控件。 同样,为了方便进行流操作,我使用了 CCOMString
,这也是由 Paul E. Bible 提供的包装类。感谢该实现。