首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

VC++ 客戶區非矩形視窗與 ListBox 拖曳移動項目完整指南

     編輯:VC 教學

第一部分:非矩形客戶區視窗 (WM_NCCALCSIZE)

覆寫 `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` 仍可安全修改第一個矩形。

第二部分:ListBox 之間拖曳移動項目 (CDragDropMgr)

自製輕量拖放管理器,避免重型 COM `IDropTarget` 實作。

1. 定義拖放視窗表


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

2. 安裝管理器


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

3. 處理四大通知


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

4. 擴充支援圖片/自訂資料

繼承 `CDragDropData` 實作 `OnGetDragSize`、`OnDrawData`、`OnGetData`,配合 `CImageList` 繪製半透明拖放影像。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved