【實現內容】做一個可編輯的表格控件。
【使用控件】一個MSFLEXGRID表格控件,一個文本控件,一個下拉列表控件。
【實現原理】我喜歡把這個方法稱為視覺假象。由於MSFLEXGRID控件本身是不支持直接編輯的。所以需要結合文本控件或者下拉列表控件,使表格控件的運行效果如同可以直接編輯一樣。
【實現步驟】
1. 當鼠標點擊表格控件的某一格時,首先判斷該列的屬性,是直接編輯呢,還是用下拉列表進行選擇。
2. 顯示隱藏的文本控件或者下拉列表控件,顯示的位置和大小與選中格的位置大小完全相同,這樣可以覆蓋選中格
3. 將選中格的內容填到文本控件或者下拉列表控件中
4. 修改完畢後,將新的內容填到選中格中,同時隱藏文本控件或者下拉列表控件。
【主要程序段及說明】
變量定義:
CComboBox m_ChangeCombo;--下拉列表控件,初始時不可見
CEdit m_Change;---------------文本控件,初始時不可見
CSring m_sChange;----------------與文本控件關聯的字符串
CMSFlexGrid m_FlexGrid;-----表格控件
程序段:
表格點擊事件:選中某一格後,就要顯示相應的文本控件或者列表控件
void CChartInfoEditDlg::OnClickMsflexgrid()
{
//點擊無效區,返回
long lRow = m_FlexGrid.GetRowSel();//獲取點擊的行號
long lCol = m_FlexGrid.GetColSel(); //獲取點擊的列號
if(lRow>m_SAttrInfo.attrNum) //如果點擊區超過最大行號,則點擊是無效的
return;
if(lRow == 0) //如果點擊標題行,也無效
return;
//
CRect rect;
m_FlexGrid.GetWindowRect(rect); //獲取表格控件的窗口矩形
ScreenToClIEnt(rect); //轉換為客戶區矩形
// MSFlexGrid 控件的函數的長度單位是"缇(twips)",
//需要將其轉化為像素,1440 缇 = 1 英寸
CDC* pDC =GetDC();
//計算象素點和缇的轉換比例
int nTwipsPerDotX = 1440 / pDC->GetDeviceCaps(LOGPIXELSX) ;
int nTwipsPerDotY = 1440 / pDC->GetDeviceCaps(LOGPIXELSY) ;
//計算選中格的左上角的坐標(象素為單位)
long y = m_FlexGrid.GetRowPos(lRow)/nTwipsPerDotY;
long x = m_FlexGrid.GetColPos(lCol)/nTwipsPerDotX;
//計算選中格的尺寸(象素為單位)。加1是實際調試中,發現加1後效果更好
long width = m_FlexGrid.GetColWidth(lCol)/nTwipsPerDotX+1;
long height = m_FlexGrid.GetRowHeight(lRow)/nTwipsPerDotY+1;
//形成選中個所在的矩形區域
CRect rc(x,y,x+width,y+height);
//轉換成相對對話框的坐標
rc.OffsetRect(rect.left+1,rect.top+1);
//清空下拉列表的內容
m_ChangeCombo.ResetContent( );
//以下省略哪一列用文本控件,哪一列用下拉列表控件的判斷。如果是用下拉列表控件,則會先向下拉列表控件中增加數據,否則為空
……………………………….
……………………………….
//獲取選中格的文本信息
CString strValue = m_FlexGrid.GetTextMatrix(lRow,lCol);
int num = m_ChangeCombo.GetCount();
//如果下拉列表控件中有數據,則表示使用下拉列表控件來進行數據選擇
if(num!=0)
{
m_ChangeCombo.ShowWindow(SW_SHOW);//顯示控件
m_ChangeCombo.MoveWindow(rc); //移動到選中格的位置,覆蓋
m_ChangeCombo.SelectString(-1,strValue); //內容全選。方便直接修改
m_ChangeCombo.SetFocus(); //獲取焦點
UpdateData(false);
return;
}
//
m_Change.ShowWindow(SW_SHOW); //顯示控件
m_Change.SetWindowText(strValue); //顯示文本
m_Change.SetFocus(); //獲取焦點
m_Change.SetSel(0,-1); //全選
m_Change.MoveWindow(rc); //移動到選中格的位置,覆蓋
}
文本編輯完畢後,回車即將新的文本信息填到選中格中
void CChartInfoEditDlg::OnKillfocusEditChange()
{
UpdateData(true);
m_FlexGrid.SetText(m_SChange);//設置文本信息
m_Change.ShowWindow(SW_HIDE); //隱藏文本控件
UpdateData(false);
}
下拉列表編輯完畢後,將新的新息填到選中格中
void CChartInfoEditDlg::OnKillfocusChangecombo()
{
UpdateData(true);
CString str;
m_ChangeCombo.GetWindowText(str);
m_FlexGrid.SetText(str);
m_ChangeCombo.ShowWindow(SW_HIDE);
UpdateData(false);
}
【總結】這是一個比較簡單的程序。如果表格中列較多,屬性各有不同,也許大家可以試著用更加復雜的控件來編輯信息。也可以同時做多個文本控件和下拉列表控件,以對應不同列的不同信息要求(比如有的格信息可能又不同的格式要求,那麼可以預先做好各種不同風格的控件與之對應)。
【筆者注】雖然當前有許多這樣的例子。但筆者做這個程序時,並沒有借鑒現有的東西。因此可能在方法上不見得最簡單。但確實效果不錯,對付一般情況是沒有問題的。大家如果對此有疑問或新思想,可以和筆者討論。聯系信箱:[email protected]