通常情况下,内制的图片属性页CLSID_CPicturePropPage能够满足需要,但有时候,也许你想有你自己的属性页来设置你的图片(IPictureDisp)类型的属性,本文将讲述如何做一个图片属性页
以上文中的例子为例(和上面的例子基本独立,可以用新的例子来做,只是懒得弄了)
1.添加Picture属性(get/set methods,LPPICTUREDISP类型),添加成员变量CPictureHolder m_pic;
LPPICTUREDISP CToppCtrl::GetPicture()
{
// TODO: Add your property handler here
return m_pic.GetPictureDispatch();
return NULL;
}
void CToppCtrl::SetPicture(LPPICTUREDISP newValue)
{
// TODO: Add your property handler here
m_pic.SetPictureDispatch(newValue);
InvalidateControl();
SetModifiedFlag();
}
2.修改OnDraw
void CToppCtrl::OnDraw(
CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
// TODO: Replace the following code with your own drawing code.
pdc->FillRect(&rcBounds, &CBrush(TranslateColor(m_color)));
m_pic.Render(pdc, rcBounds, rcBounds);
int nhei = 18;
int y = 2;
for(int i=0; i CRect rect(rcBounds.left + 4, y+2, rcBounds.right - 4, y + nhei);
pdc->FillRect(&rect, &CBrush(RGB(255, 255, 255)));
pdc->TextOut(rcBounds.left + 4, y + 2, m_saItems[i]);
}
}
3.修改DoPropExchange,添加"Picture"属性的持久化
void CToppCtrl::DoPropExchange(CPropExchange* pPX)
{
ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
COleControl::DoPropExchange(pPX);
// TODO: Call PX_ functions for each persistent custom property.
PX_Color(pPX, "Color", m_color, TranslateColor(RGB(0, 0, 0)));
PX_Picture(pPX, _T("Picture"), m_pic);
PX_Items(pPX);
}
4.新建一对话框资源(OlePropertyPage类型,IDD_PROPPAGE_MYPIC),在上面添加两按钮("浏览","清除"),用 ClassWizard建立CMyPicPropPage(派生自COlePropertyPage),以后就开始编辑CMyPicPropPage这个 属性页类了。
5.新建字符串资源IDS_MYPIC_PPG_CAPTION("图片"),将之填入以下两处,作为属性页打进标题(更改属性页的标题,就是简单的更改相应字符串资源的文字就可以了)
CMyPicPropPage::CMyPicPropPage() :
COlePropertyPage(IDD, IDS_MYPIC_PPG_CAPTION)
{
//{{AFX_DATA_INIT(CMyPicPropPage)
// NOTE: ClassWizard will add member initialization here
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_DATA_INIT
}
BOOL CMyPicPropPage::CMyPicPropPageFactory::UpdateRegistry(BOOL bRegister)
{
// TODO: Define string resource for page type; replace '0' below with ID.
if (bRegister)
return AfxOleRegisterPropertyPageClass(AfxGetInstanceHandle(),
m_clsid, IDS_MYPIC_PPG_CAPTION);
else
return AfxOleUnregisterClass(m_clsid, NULL);
}
6.为CMyPicPropPage添加成员CPictureHolder m_pic,用来保存属性页中的图片(IPictureDisp)对象
7.添加两个按钮的响应函数,在OnButtonBrowser建立图片对象(IPictureDisp),并保存在m_pic中,在OnButtonClear中则删除图片对象。
void CMyPicPropPage::OnButtonBrowser()
{
// TODO: Add your control notification handler code here
CFileDialog dlg(TRUE, "所有文件|*.*||");
if(dlg.DoModal() == IDOK){
CFile file;
if(file.Open(dlg.GetPathName(), CFile::typeBinary | CFile::modeRead)){
DWORD dwlen = file.GetLength();
HGLOBAL hMem = GlobalAlloc(GMEM_FIXED, dwlen);
file.Read((void*)hMem, dwlen);
file.Close();
LPSTREAM pstream;
CreateStreamOnHGlobal(hMem, TRUE, &pstream);
LPPICTUREDISP ppic = NULL;
OleLoadPicture(pstream, dwlen, TRUE, IID_IPictureDisp, (LPVOID*)&ppic);
if(ppic){
m_pic.SetPictureDispatch(ppic);
}
GlobalFree(hMem);
}
}
/* //需要#include "afxpriv2.h"
CFileDialog dlg(TRUE, "所有文件|*.*||");
if(dlg.DoModal() == IDOK){
CFile file;
if(file.Open(dlg.GetPathName(), CFile::typeBinary | CFile::modeRead)){
DWORD dwlen = file.GetLength();
CArchive ar(&file, CArchive::load);
CArchiveStream stm(&ar);
LPSTREAM pstream = (LPSTREAM)&stm;
LPPICTUREDISP ppic = NULL;
OleLoadPicture(pstream, dwlen, TRUE, IID_IPictureDisp, (LPVOID*)&ppic);
if(ppic){
m_pic.SetPictureDispatch(ppic);
}
ar.Close();
file.Close();
}
}*/
}
void CMyPicPropPage::OnButtonClear()
{
// TODO: Add your control notification handler code here
m_pic.CreateEmpty();
}
8.添加WM_PAINT消息响应函数,以在属性页上显示所选的图片
void CMyPicPropPage::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
CRect rect;
GetClientRect(&rect);
rect.DeflateRect(10, 10, 200, 10);
m_pic.Render(&dc, rect, rect);
// Do not call COlePropertyPage::OnPaint() for painting messages
}
9.和控件产生关联,在适当的时候载入控件的Picture属性到m_pic在和保存m_pic中的图片到控件的Picture属性:
void CMyPicPropPage::DoDataExchange(CDataExchange* pDX)
{
// NOTE: ClassWizard will add DDP, DDX, and DDV calls here
// DO NOT EDIT what you see in these blocks of generated code !
//{{AFX_DATA_MAP(CMyPicPropPage)
//}}AFX_DATA_MAP
if(pDX->m_bSaveAndValidate){
SetPic();
}
else{
GetPic();
}
DDP_PostProcessing(pDX);
}
void CMyPicPropPage::SetPic()
{
USES_CONVERSION;
COleDispatchDriver PropDispDriver;
ULONG nObjects = 0;
LPDISPATCH* ppDisp = GetObjectArray(&nObjects);
DISPID dwDispID;
LPCOLESTR lpOleStr = T2COLE("Picture");
ppDisp[0]->GetIDsOfNames(IID_NULL, (LPOLESTR*)&lpOleStr, 1, 0, &dwDispID);
PropDispDriver.AttachDispatch(ppDisp[0]);
PropDispDriver.SetProperty(dwDispID, VT_DISPATCH, m_pic.GetPictureDispatch());
PropDispDriver.DetachDispatch();
}
void CMyPicPropPage::GetPic()
{
USES_CONVERSION;
COleDispatchDriver PropDispDriver;
ULONG nObjects = 0;
LPDISPATCH* ppDisp = GetObjectArray(&nObjects);
DISPID dwDispID;
LPCOLESTR lpOleStr = T2COLE("Picture");
ppDisp[0]->GetIDsOfNames(IID_NULL, (LPOLESTR*)&lpOleStr, 1, 0, &dwDispID);
LPPICTUREDISP ppic = NULL;
PropDispDriver.AttachDispatch(ppDisp[0]);
PropDispDriver.GetProperty(dwDispID, VT_DISPATCH, (void*)&ppic);
PropDispDriver.DetachDispatch();
m_pic.SetPictureDispatch(ppic);
}
10.差点忘了一步了,因为是新建了一个属性页,不是用缺省的属性页,所以得告诉控件,你有了哪两个属性页了。
// TODO: Add more property pages as needed. Remember to increase the count!
BEGIN_PROPPAGEIDS(CToppCtrl, 2)
PROPPAGEID(CToppPropPage::guid)
PROPPAGEID(CMyPicPropPage::guid)
END_PROPPAGEIDS(CToppCtrl)
11.可以编译运行进行测试了
刚知道可以插入图片,试试