覆寫 `OnNcCalcSize` 縮減客戶區矩形,配合 `OnNcPaint` 繪製 3D 邊框,實現類似內嵌面板效果。
void CMyFrame::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS* lpncsp) {
CFrameWnd::OnNcCalcSize(bCalcValidRects, lpncsp); // 必須呼叫基類
CRect& rc = *(CRect*)&lpncsp->rgrc[0];
rc.DeflateRect(7, 7); // 四周縮減 7px
}
void CMyFrame::OnNcPaint() {
CWindowDC dc(this);
CRect rc; GetWindowRect(&rc); rc.OffsetRect(-rc.TopLeft());
// 繪製 3D 邊框
dc.Draw3dRect(rc, GetSysColor(COLOR_3DHILIGHT), GetSysColor(COLOR_3DSHADOW));
rc.DeflateRect(1,1);
dc.Draw3dRect(rc, GetSysColor(COLOR_3DLIGHT), GetSysColor(COLOR_3DDKSHADOW));
}
關鍵:`bCalcValidRects` 為 FALSE 時 `lpncsp` 指向單一 `RECT`,MFC 強制轉 `NCCALCSIZE_PARAMS` 仍可安全修改第一個矩形。
自製輕量拖放管理器,避免重型 COM `IDropTarget` 實作。
struct DRAGDROPWND { UINT id; DWORD flags; }; // flags: DDW_SOURCE | DDW_TARGET
static DRAGDROPWND g_ddWnds[] = {
{ IDC_LIST_SRC, DDW_SOURCE },
{ IDC_LIST_DST, DDW_SOURCE | DDW_TARGET },
{ IDC_EDIT_DST, DDW_TARGET },
{ 0, 0 }
};
CDragDropMgr m_ddm;
BOOL CMyDialog::OnInitDialog() {
m_ddm.Install(this, g_ddWnds);
return TRUE;
}
BOOL CMyDialog::PreTranslateMessage(MSG* pMsg) {
return m_ddm.PreTranslateMessage(pMsg) || CDialog::PreTranslateMessage(pMsg);
}
BEGIN_MESSAGE_MAP(CMyDialog, CDialog)
ON_MESSAGE(WM_DD_DRAGENTER, OnDragEnter)
ON_MESSAGE(WM_DD_DRAGOVER, OnDragOver)
ON_MESSAGE(WM_DD_DRAGDROP, OnDragDrop)
ON_MESSAGE(WM_DD_DRAGABORT, OnDragAbort)
END_MESSAGE_MAP()
LRESULT CMyDialog::OnDragEnter(WPARAM wp, LPARAM lp) {
DRAGDROPINFO& ddi = *(DRAGDROPINFO*)lp;
CListBox* pSrc = (CListBox*)CWnd::FromHandle(ddi.hwndSource);
int idx = pSrc->GetCurSel();
if (idx == LB_ERR) return FALSE;
CString text; pSrc->GetText(idx, text);
ddi.data = new CDragDropText(text); // 庫提供文字拖放類
return TRUE;
}
LRESULT CMyDialog::OnDragDrop(WPARAM wp, LPARAM lp) {
DRAGDROPINFO& ddi = *(DRAGDROPINFO*)lp;
CString* pText = (CString*)ddi.data->OnGetData();
CWnd* pTarget = CWnd::FromHandle(ddi.hwndTarget);
if (pTarget->IsKindOf(RUNTIME_CLASS(CListBox))) {
((CListBox*)pTarget)->AddString(*pText);
} else if (pTarget->IsKindOf(RUNTIME_CLASS(CEdit))) {
((CEdit*)pTarget)->SetWindowText(*pText);
}
return 0;
}
繼承 `CDragDropData` 實作 `OnGetDragSize`、`OnDrawData`、`OnGetData`,配合 `CImageList` 繪製半透明拖放影像。