WTL 7 心得筆記 (3): 使用 control

Last Update:06/30/2004

DDX 無用論

Michael Dunn 的 WTL 系列文章中花了許多篇幅講述如何使用 DDX / DDV,不幸的是,在 WTL 7.5 中,DDX / DDV 的支援不完備 (或者說比起 7.0 之前的版本更糟),只在某些狀況下可用。特別是 DDX_CONTROL 的部份,若你想要直接做像這樣的效果

class CMainDlg : public CDialogImpl<CMainDlg>,
                 public CWinDataExchange<CMainDlg>
{
protected:
    CListBox m_wndList;

public:
    BEGIN_DDX_MAP(CMainDlg)
        DDX_CONTROL(IDC_LIST1, m_wndList)
    END_DDX_MAP()
...
};

這註定是慘淡收場,因為對於 control 的部份,WTL 已經改變它的 programming paradigm,轉成一種比較類似 C# 和 VB 的方法。

wizard 是無用的

由於 WTL 並沒有被 VC7 正式支援,當然 Add member variable wizard 是無用的。更糟的是,就算你將它當成一般的 variable 來加,若你用的類別是 WTL 和 MFC 中都有的類別 (e.g. CListBox),那麼還可能會造成你 compile 上的困擾 (因為 ATL 7 和 MFC 7 部份類別是合體的,路徑優先順序沒設好的話 MFC 的會先被找到)。

因此,wizard 是無用的,乖乖用手做。

新的 Instantiate / Attach approach

WTL 的 control 類別都在 atlctrls.h 裡,首先先在適當的地方加入 atlctrls.h,並宣告你要的變數:

#include <atlctrls.h>

class CMainDlg : public CDialogImpl<CMainDlg>
{
protected:
    CListBox m_wndList;
...
};

接下來在 OnInitDialog() 中將這些變數與 resource bind 起來

LRESULT CMainDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
    // center the dialog on the screen
    CenterWindow();

    // set icons
    HICON hIcon = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
	IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
    SetIcon(hIcon, TRUE);
    HICON hIconSmall = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME), 
	IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
    SetIcon(hIconSmall, FALSE);

    m_wndList.Attach(GetDlgItem(IDC_LIST1));

    return TRUE;
}

接下來就是直接對該變數做動作了。

DDX 不是很好嗎?為什麼要做這樣的改變呢?那是因為 WTL 原本的 DDX 是以 subclass 的方法來達成,這違背了 WTL 設計上力求精簡的精神 (你用 CWindowImpl<> 去 subclass 出 CListBoxImpl,不就又走回 MFC CWnd 的老路了嗎?) 因此由 CWindow 衍生的諸多 control class 直接 instantiate 後再 attach,便可保有 CWindow 小而美的靈活性。

Message Reflection

當使用 Owner-draw control 時常需用到的 message reflection,在 WTL 7.5 中最好是使用 ATL 7 裡本已提供的一些 reflection macro,詳細的用法和說明在 MSDN 中都有。

Customized Controls

底下的連結是一些可以找到 WTL 用的 customized controls 的地方。不過呢,因為 .Net 盛行的關係,大部份的 customized control 都只停留在 WTL 3.0 的時代,對於 WTL 7.x 而言不一定是直接可用的,通常需要花點時間稍做修改:

Code Project: http://www.codeproject.com/wtl

Viksoe.dk: http://www.viksoe.dk/code