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

VC++ 打造可編輯表格控件:MSFlexGrid + Edit/ComboBox 覆蓋法完整實作

     編輯:VC 教學

前言:MSFlexGrid 原生不支援編輯

MSFlexGrid 功能強大但預設唯讀。最簡單實現編輯的方法是視覺假象:滑鼠點選儲存格 → 在該位置精確覆蓋一個 CEdit 或 CComboBox → 編輯完成 → 寫回儲存格 → 隱藏控件。本文提供完整實作邏輯與程式碼。

核心變數宣告

// 對話框類別成員
CMSFlexGrid m_FlexGrid;      // 表格控件
CEdit m_Edit;                // 文字編輯控件 (初始不可見)
CComboBox m_Combo;           // 下拉選擇控件 (初始不可見)
CString m_strEditText;       // 與 m_Edit 關聯的 DDX 變數

儲存格點擊事件 → 顯示編輯控件

void CMyDialog::OnClickFlexGrid()
{
    long lRow = m_FlexGrid.GetRowSel();
    long lCol = m_FlexGrid.GetColSel();

    // 無效區域:標題列 (Row 0) 或超出資料範圍
    if (lRow == 0 || lRow > m_nMaxDataRow) return;

    // 1. 計算儲存格螢幕座標 (Twips → 像素)
    CRect rectGrid;
    m_FlexGrid.GetWindowRect(&rectGrid);
    ScreenToClient(&rectGrid);

    CDC* pDC = GetDC();
    int nTwipsPerPixelX = 1440 / pDC->GetDeviceCaps(LOGPIXELSX);
    int nTwipsPerPixelY = 1440 / pDC->GetDeviceCaps(LOGPIXELSY);
    ReleaseDC(pDC);

    long x = m_FlexGrid.GetColPos(lCol) / nTwipsPerPixelX;
    long y = m_FlexGrid.GetRowPos(lRow) / nTwipsPerPixelY;
    long w = m_FlexGrid.GetColWidth(lCol) / nTwipsPerPixelX + 1;
    long h = m_FlexGrid.GetRowHeight(lRow) / nTwipsPerPixelY + 1;

    CRect rcCell(x, y, x + w, y + h);
    rcCell.OffsetRect(rectGrid.left + 1, rectGrid.top + 1);  // 相對對話框座標

    // 2. 取得儲存格現有文字
    CString strValue = m_FlexGrid.GetTextMatrix(lRow, lCol);

    // 3. 判斷該欄使用 Edit 還是 ComboBox (此處略過判斷邏輯)
    // 假設第 1 欄用 ComboBox,其他用 Edit
    m_Combo.ResetContent();
    if (lCol == 1) {
        m_Combo.AddString(_T("選項一"));
        m_Combo.AddString(_T("選項二"));
        m_Combo.AddString(_T("選項三"));
    }

    if (m_Combo.GetCount() > 0) {
        // 使用 ComboBox
        m_Combo.MoveWindow(&rcCell);
        m_Combo.SelectString(-1, strValue);
        m_Combo.SetFocus();
        m_Combo.ShowWindow(SW_SHOW);
    } else {
        // 使用 Edit
        m_Edit.MoveWindow(&rcCell);
        m_Edit.SetWindowText(strValue);
        m_Edit.SetSel(0, -1);  // 全選
        m_Edit.SetFocus();
        m_Edit.ShowWindow(SW_SHOW);
    }

    // 記錄目前編輯的儲存格位置 (供失焦時寫回)
    m_nEditingRow = lRow;
    m_nEditingCol = lCol;
}

編輯控件失焦 → 寫回儲存格並隱藏

// Edit 失焦
void CMyDialog::OnKillfocusEdit()
{
    UpdateData(TRUE);  // DDX 取得 m_strEditText
    m_FlexGrid.SetTextMatrix(m_nEditingRow, m_nEditingCol, m_strEditText);
    m_Edit.ShowWindow(SW_HIDE);
    UpdateData(FALSE);
}

// ComboBox 失焦
void CMyDialog::OnKillfocusCombo()
{
    CString str;
    m_Combo.GetWindowText(str);
    m_FlexGrid.SetTextMatrix(m_nEditingRow, m_nEditingCol, str);
    m_Combo.ShowWindow(SW_HIDE);
}

關鍵技術細節

細節處理方式
Twips 單位轉換1440 twips = 1 英吋,用 GetDeviceCaps(LOGPIXELSX/Y) 計算像素比
儲存格座標精確對齊GetColPos/RowPos、GetColWidth/RowHeight 取得 twips 座標
控件覆蓋順序MoveWindow 定位 → SetWindowText/SelectString 內容 → SetFocus → ShowWindow(SW_SHOW)
全選方便修改Edit 用 SetSel(0,-1),Combo 用 SelectString(-1, str)
失焦觸發寫回OnKillfocus 訊息對應 EN_KILLFOCUS/CBN_KILLFOCUS

擴充建議

  • 不同欄位對應不同編輯控件:預先建立多個 CEdit/CComboBox/CDateTimeCtrl 等,依欄位屬性切換。
  • 資料驗證:失焦前檢查格式,不通過則 SetFocus 回編輯控件並提示。
  • 鍵盤導航:處理 Enter/Tab/Esc 鍵在儲存格間移動。
  • 效能優化:大量資料時考慮虛擬模式或改用 CListCtrl + LVS_EX_LABELTIP。

結語

「視覺假象」法以最小程式碼成本實現 MSFlexGrid 編輯功能,適合中小型表格編輯需求。核心在於Twips 座標精確轉換、控件即時覆蓋、失焦寫回三步驟。專案中可直接複製修改欄位判斷邏輯即用。

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