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

VC++ 仿 QQ 界面開發實戰(下):抽屜選單、訊息對話框與桌面邊緣吸附

     編輯:關於VC++

前言

承接上篇,本文將深入解析 QQ 經典界面的三大核心模組:動感十足的抽屜式導航選單、動態建立的訊息對話框、以及桌面頂端的智慧型吸附/隱藏機制。所有程式碼基於 MFC 對話框架構,經實測可在 VC6.0/VC++.NET 環境下穩定執行。

一、抽屜式導航選單的動畫實現

QQ 的側邊選單以「刷」的一聲滑動展開/收合,極具辨識度。核心思路:預先記錄各分頁按鈕的初始位置,點擊時透過 MoveWindow 重新計算並移動按鈕與內容區域,配合計時器可實現漸變動畫。

關鍵步驟

  1. 初始化座標: 在 OnInitDialog 中取得首尾按鈕的客戶區座標(rect0, rect1)。
  2. 統一處理函數 ChangeView(): 根據 clicknum(目標分頁)與 TopButtonNum(當前頂層分頁)判斷移動邏輯。
  3. 按鈕堆疊邏輯: 被點擊的分頁按鈕移至頂層,其餘按鈕依序下沉;同步顯示/隱藏對應的列表控制項(CListCtrl 或 CTreeCtrl)。

核心程式碼片段

void CMyQQDlg::ChangeView()
{
    if (TopButtonNum != 1 && clicknum == 1) // QQ好友分頁
    {
        m_QQothers.MoveWindow(0, rect1.bottom, rect0.Width(), rect0.Height(), TRUE);
        m_QQqun.MoveWindow(0, rect1.bottom - rect0.Height(), rect0.Width(), rect0.Height(), TRUE);
        // 切換圖示列表大小
        m_List1.SetImageList(&m_imagelist2, LVSIL_SMALL);
        m_List1.DeleteAllItems();
        for (int i = 1; i < 34; i++) {
            m_List1.InsertItem(0xFFFF, _T(""));
            m_List1.InsertItem(0xFFFF, _T("\n") + myClass[i-1], i);
        }
        m_List1.ShowWindow(SW_SHOW);
        m_List2.ShowWindow(SW_HIDE);
        treeCtrl.ShowWindow(SW_HIDE);
        return;
    }
    // ... 群組、最近聯絡人分頁邏輯類似
}

進階技巧:隱形定位點

在對話框最上/下方放置兩個極小、不可見的 Picture 控制項,作為按鈕移動的目標座標錨點,配合所有按鈕統一寬高,大幅簡化座標計算。

二、動態建立訊息對話框與熱鍵發送

1. 雙擊好友列表動態建立聊天視窗

void CMyQQDlg::OnDblclkMyFriend(NMHDR* pNMHDR, LRESULT* pResult)
{
    NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
    int nSel = pNMListView->iItem;
    CString strName = m_List1.GetItemText(nSel, 0);

    CQQSendMessage* pDlg = new CQQSendMessage;
    pDlg->msg = strName;
    pDlg->Create(IDD_QQ_MESSAGE); // 以模板建立無模式對話框
    pDlg->SetWindowText(_T("你正在與 ") + strName + _T(" 聊天中"));
    pDlg->SetIcon(AfxGetApp()->LoadIcon(IDR_MAINFRAME), FALSE);
    pDlg->ShowWindow(SW_SHOW);
    *pResult = 0;
}

2. Ctrl+Enter 快捷鍵發送訊息

在訊息對話框類別中重寫 PreTranslateMessage 攔截鍵盤訊息:

BOOL CQQSendMessage::PreTranslateMessage(MSG* pMsg)
{
    if (pMsg->message == WM_KEYDOWN) {
        if (pMsg->wParam == VK_RETURN && (GetKeyState(VK_CONTROL) & 0x8000)) {
            OnSend(); // 呼叫發送處理函數
            return TRUE;
        }
    }
    return CDialog::PreTranslateMessage(pMsg);
}

三、桌面頂端智慧型吸附/隱藏

QQ 主面板可「掛」在螢幕頂端,僅露一條細線;滑鼠靠近即展開,移開自動收合。核心邏輯:

  • 使用 WM_TIMER 定期檢測滑鼠座標(GetCursorPos)。
  • 判斷滑鼠是否進入視窗擴展區域(InflateRect 擴大判定範圍)。
  • 展開時恢復完整高度;收合時僅保留 3 像素高度(MoveWindow(..., 3, TRUE))。

收合/展開核心邏輯

void CMyQQDlg::OnTimer(UINT nIDEvent)
{
    if (nIDEvent == 1) // 滑鼠離開偵測
    {
        POINT pt; GetCursorPos(&pt);
        CRect rc; GetWindowRect(&rc);
        rc.InflateRect(10, 10); // 擴大 10 像素判定區
        if (!rc.PtInRect(pt)) {
            KillTimer(1);
            m_hiding = TRUE; // 進入收合狀態
            SetTimer(2, 5, NULL); // 啟動動畫計時器
        }
    }
    else if (nIDEvent == 2) // 動畫幀
    {
        m_hiding ? DoHide() : DoShow();
    }
    CDialog::OnTimer(nIDEvent);
}

總結與原始碼下載

本系列完整實現了 QQ 2005 風格的主面板、抽屜選單、動態聊天視窗、熱鍵發送、桌面吸附等核心體驗。完整原始碼請至知識庫下載,歡迎交流指正:xuwenq88@126.com。

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