CWnd部分解释

## 学习方法:

> 主要就是模拟开发,即使你的基础不牢,模拟训练反而有助于对前期的语法理解。API的量大,API比SOCKET要简单一些,因为直观,按钮,下拉。

### 1、windows资源:

> 常用的资源有对话框、菜单、图标、光标、字符串表、快捷键、位图等。

### 2、HWND与CWnd对象之间的转换:

1. 如果有CWnd对象如何获取这个对象内部的句柄?

```C++

pWnd ->m_hWnd

pWnd ->GetSafeHwnd();

CWnd wnd;

HWND h = wnd;   // hwnd是指向cwnd对象的句柄,通过句柄可以操作控件

                // cwnd包含了hwnd。

```

2. 如果有句柄HWND如何转为CWnd?

`static CWnd* CWnd::FromHandle(HWND hWnd);`

3. 注意:`GetDlgItem`内部都是靠`FromHandle`实现的。

4. 注意:`FromHandle`内部是有Map禁止一个句柄被多个对象包含。

就如同一个端口只能被一个进程占用,一个句柄只能有一个对象包含。

5. 注意:`FromHandle`的返回值只限于本函数使用,不可以保存在成员变量长期使用。

原因是不定期清理Map,参见:`CWnd::DeleteTempMap`

### 3、句柄嫁接与子类化:

1. `Attach`和`Detach`就是单纯的嫁接与分离函数。

对象一旦嫁接入一个句柄,就可以自由地调用CWnd或其派生类的功能。

2. 子类化`Subclass`内部包含`Attach`,额外再增加一个消息转拨到派生类(SubClass就是子类)

3. `SubClassWindow`函数内部核心功能就是Attach和`::SetWindowLongPtr`

4. `SubClassWindow()`必须与`UnsubclassWindow()`成对使用,如同Attach与Detach那样。

5. `SubClassDlgItem()`是把2个函数合成一个函数:`m_eye.SubclassDlgItem(IDC_SHOW, this)`;  `m_eye.SubclassWindow(::GetDlgItem(m_hWnd, IDC_SHOW));`

6. 而且SubClassDlgItem不需要反子类化,可以不用调用UnsubclassWindow

### 4、总结嫁接与子类化:

1. Attach和Detach就是单纯的嫁接

2. 子类化Subclass内部包含Attach,增强了消息转移机制。

3. SubClassDlgItem简化了子类化功能,不需要反子类化UnsubclassWindow

4. 类向导中建立关联变量的方法(内部就是子类化)

DDX_Control函数内的核心内容是,引用类成员变量m_xxx,

```c++

{

    pDX->m_pDlgWnd->GetDlgItem(nIDC, &hWndCtrl);

    rControl.SubclassWindow(hWndCtrl);

}

void CXxxxxx::DoDataExchange(CDataExchange* pDX){

    CDialogEx::DoDataExchange(pDX);

    DDX_Control(pDX, IDC_LIST, m_list);

    DDX_Control(pDX, IDC_PRIOR, m_combo);

}

```

附录:

```C++

BOOL CWnd::SubclassWindow(HWND hWnd){

    if (!Attach(hWnd))

        return FALSE;

    // allow any other subclassing to occur

    PreSubclassWindow();

    // now hook into the AFX WndProc

    WNDPROC* lplpfn = GetSuperWndProcAddr();

    WNDPROC oldWndProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC,

        (INT_PTR)AfxGetAfxWndProc());

    ASSERT(oldWndProc != AfxGetAfxWndProc());

    if (*lplpfn == NULL)

        *lplpfn = oldWndProc;   // the first control of that type created

#ifdef _DEBUG

    else if (*lplpfn != oldWndProc)

    {

        TRACE(traceAppMsg, 0, "Error: Trying to use SubclassWindow with incorrect CWnd\n");

        TRACE(traceAppMsg, 0, "\tderived class.\n");

        TRACE(traceAppMsg, 0, "\thWnd = $%08X (nIDC=$%08X) is not a %hs.\n", (UINT)(UINT_PTR)hWnd,

            _AfxGetDlgCtrlID(hWnd), GetRuntimeClass()->m_lpszClassName);

        ASSERT(FALSE);

        // undo the subclassing if continuing after assert

      ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (INT_PTR)oldWndProc);

    }

#endif

    return TRUE;

}

void AFXAPI DDX_Control(CDataExchange* pDX, int nIDC, CWnd& rControl)

{

    if ((rControl.m_hWnd == NULL) && (rControl.GetControlUnknown() == NULL))    // not subclassed yet

    {

        ASSERT(!pDX->m_bSaveAndValidate);

        pDX->PrepareCtrl(nIDC);

        HWND hWndCtrl;

        pDX->m_pDlgWnd->GetDlgItem(nIDC, &hWndCtrl);

#if defined(_AFXDLL) || !defined(_AFX_NO_MFC_CONTROLS_IN_DIALOGS)

        CMFCControlContainer* pMFCCtrlContainer = pDX->m_pDlgWnd->GetMFCControlContainer();

        if (pMFCCtrlContainer != NULL && pMFCCtrlContainer->IsSubclassedFeaturePackControl(hWndCtrl))

        {

            pMFCCtrlContainer->ReSubclassControl(hWndCtrl, (WORD)nIDC, rControl);

            return;

        }

#endif

        if ((hWndCtrl != NULL) && !rControl.SubclassWindow(hWndCtrl))

        {

            ASSERT(FALSE);      // possibly trying to subclass twice?

            AfxThrowNotSupportedException();

        }

        else

        {

            if (hWndCtrl == NULL)

            {

                if (pDX->m_pDlgWnd->GetOleControlSite(nIDC) != NULL)

                {

                    rControl.AttachControlSite(pDX->m_pDlgWnd, nIDC);

                }

            }

            else

            {

                // If the control has reparented itself (e.g., invisible control),

                // make sure that the CWnd gets properly wired to its control site.

                if (pDX->m_pDlgWnd->m_hWnd != ::GetParent(rControl.m_hWnd))

                    rControl.AttachControlSite(pDX->m_pDlgWnd);

            }

        }

    }

}

```

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值