2010年10月22日 星期五

MFC PropertyGrid Control

我的工作經常要做些測試用的程式來調整參數或是驗証功能,這其中最大的UI使用就是拉出一堆Edit Box來做為輸入的界面,有時候為了美觀(or自虐)會把這些參數設定做成像Visual Studioproperty page的功能,可能我是個老傢伙了,我的作法還停留在太古時代,先繼承自ClistBox產生我自己的property grid class,然後再用subclass的方法,把原先resource上的list換成我寫好的property grid class以產生出我要的property grid style class。嗯,這還不是最麻煩的,最麻煩的是property必需要能edit吧,所以我還要偵測mouse的點擊動作,當點在edit區時create一個edit box把他蓋在原本的位置上方讓,還記得我第一次作出這樣功能時是VC 4.2時代吧,想不到這個class用了10年還在用真是一點都不長進。

我這元件只能單純的輸入文字而已,想說10多年了,來加個新功能把combo box也弄進來試試,結果

我在拉元件時不小心撇見了Visual Studio 2010Toolbox中的一角

難道說時代已經進步到這東西己是MFC內建的元件了嗎,癈話不多說直接拉元件就上了

例用Add Member Variable Wizard把這元件加進來方便操作。

Dialog::OnInitDialog中把我要的property加入

BOOL CSetCompareMethodDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    CMFCPropertyGridProperty* pProp = new CMFCPropertyGridProperty(_T("Different Threshold"),_T("1"));

    pProp->AllowEdit(TRUE);

    m_wndPropClass.AddProperty(pProp);
    m_wndPropClass.AdjustLayout();

    return TRUE;  // return TRUE unless you set the focus to a control
}

結果,好像有點怪怪的


首先,我有設定border,但似乎沒畫出來,其次就是property namewidth似乎是太太太太小了。

研究了這2class的相關成員發現似乎沒有辦法指定我要的欄位大小(很神奇,可以get不能set這不像是M$style,只能用AdjustLayout讓他自己算),border style也嘗試了幾種組合也都無法顯現。在計無可施下,突然有一個聲音,告訴我這是M$bug, bug, bug, bug…,可能是DDX的交握出了問題,我把他改成用老方法subclass試試

BOOL CSetCompareMethodDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    CWnd* pWnd = GetDlgItem(IDC_PROPERTYGRID_METHOD);
    CRect rectPropList;
    pWnd->GetClientRect(&rectPropList);
    pWnd->MapWindowPoints(this, &rectPropList);

    m_wndPropClass.Create(WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER, rectPropList, this, (UINT)-1);

    m_wndPropClass.EnableHeaderCtrl(FALSE);
    m_wndPropClass.SetVSDotNetLook(FALSE);
    m_wndPropClass.MarkModifiedProperties(TRUE);
    m_wndPropClass.SetAlphabeticMode(FALSE);
    m_wndPropClass.SetShowDragContext(FALSE);
   
    CMFCPropertyGridProperty* pProp = new CMFCPropertyGridProperty(_T("Different Threshold"),_T("1"));

    pProp->AllowEdit(TRUE);

    m_wndPropClass.AddProperty(pProp);
    m_wndPropClass.AdjustLayout();

    return TRUE;  // return TRUE unless you set the focus to a control
}

別忘了把原本的DDX斷掉

void CSetCompareMethodDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialogEx::DoDataExchange(pDX);
    //  DDX_Control(pDX, IDC_PROPERTYGRID_METHOD, m_wndPropClass);
}

正確的style出現啦

如果想要做出combo的效果,就把想加入的CMFCPropertyGridProperty objectAddOption的方式一項一項的加進去,也可以用AddSubItem做成樹狀結構。相關可使用的調整還很多,有興趣可參考相關連結。

CMFCPropertyGridProperty的生成方式很像Composite的做法,特別是要做成樹狀的結構時,非常的容易操作。以我的懶性而言,要做出樹狀應該是不可能吧。

create的方式建立的CMFCPropertyGridProperty必需設resouceinvisible否則會產生2個property,一個無法控制。


沒有留言:

張貼留言