選擇器架構
CIconPicker:繼承 CButton,點擊時彈出容器視窗。
CIconContainer:彈出視窗(WS_POPUP),內含陣列排列的 CInnerButton。
CInnerButton:自繪按鈕,顯示單一表情圖片,處理滑鼠進入/點擊。
核心流程
- 點擊選擇器(
OnLButtonDown):建立 CIconContainer,計算網格行列,依圖片大小決定視窗尺寸,建立對應數量的 CInnerButton,顯示並取得焦點。
- 容器建立(
CIconContainer::Create):動態建立按鈕陣列,額外加入「更多圖示」、「自訂圖示」功能按鈕。
- 按鈕點擊處理(
OnCommand):取得按鈕索引,呼叫 Close(index) 關閉容器並透過 PostMessage 通知父視窗(CIconPicker)選取結果。
- 失去焦點自動關閉:處理
WM_KILLFOCUS 釋放捕捉並銷毀容器。
關鍵程式碼
// CIconPicker::OnLButtonDown
m_pIconContainer = new CIconContainer;
if (m_pIconContainer->Create(pt, this, &m_BitmapArray)) {
m_pIconContainer->ShowWindow(SW_SHOW);
m_pIconContainer->SetFocus();
}
// CIconContainer::Create - 建立網格按鈕
for (int i=0; i<m_nRow; i++)
for (int j=0; j<m_nCol && i*m_nCol+j<pBitmapArray->GetSize(); j++) {
CRect r; // 計算位置
CInnerButton* btn = new CInnerButton;
btn->Create(NULL, WS_CHILD|WS_VISIBLE, r, this, IDC_INNERBUTTON + i*m_nCol+j);
btn->SetBitmap(pBitmapArray->GetAt(i*m_nCol+j));
m_InnerButtonArray.Add(btn);
}
// CIconContainer::OnCommand - 處理選取
int idx = LOWORD(wParam) - IDC_INNERBUTTON;
if (idx >= 0) Close(idx); // 一般圖示
else if (idx == -1) { /* 更多圖示 */ }
else if (idx == -2) { /* 自訂圖示:開啟檔案對話框 */ }
執行效果
擴充方向
- 支援分類標籤、搜尋過濾。
- 整合至
CRichEditCtrlEx 自動偵測 :) 等轉義字串並插入對應圖片。
- 優化記憶體管理(智慧指標)、高 DPI 適配。