65.9K
CodeProject 正在变化。 阅读更多。
Home

ATL 动态复合控件

starIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIconemptyStarIcon

1.71/5 (3投票s)

2002年8月31日

2分钟阅读

viewsIcon

75852

downloadIcon

1801

展示了在一个复合控件中动态创建ATL全控件,以及无需文件系统干预即可直接从数据库显示图像的方法。

引言

本文解释了如何在一个ATL复合控件中动态使用一个ATL全控件(包含的控件)。此控件是在ATL 3.0中构建的。

包含的控件

包含的控件是“静态 - 子类化”的ATL全控件。我用它来显示任何图像,但在另一个背景图像/颜色之上,该背景图像/颜色可以作为图像的边框。该控件包含两个 LPPICTURE 数据成员 m_lpPicturem_lpPictureBk,用于保存图像和背景图像流。可以使用两种方式通过此控件显示图像。

  1. 可以指定任何图像文件的物理路径,或者
  2. 可以直接分配任何图像 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,210. 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 提供的包装类。感谢该实现。

© . All rights reserved.