天天看點

ActiveX控件的MFC設計之旅-第9步 .

 通常情況下,内制的圖檔屬性頁 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<m_saItems.GetSize(); i++, y+=nhei){

        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);

        }

    }

}

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.可以編譯運作進行測試了

剛知道可以插入圖檔,試試

ActiveX控件的MFC設計之旅-第9步 .