MFC-小型工具通用介面框架
MFC-小型工具通用介面框架
0x1 場景
開發桌面版小工具使用的通用介面,命令列使用起來不方便。
但是又不應該以成為介面工程師作為目標學習,掌握積累幾個MFC的常用控制元件就可以在以後的日子裡隨時呼叫。
把程式碼積累出來,把精力用在實現實際功能上。
環境:VS2017
0x2 技術點
- CListCtrl,介面增加列名、跟隨介面調整、增加內容
- 選單使用,刪除單條、刪除多條
0x3 程式碼
1、CListCtrl控制元件
介面使用部分
1、【對話方塊編輯器】-【List Control】,增加一個List控制元件拖到指定位置
2、【屬性】-【View】-【Report】,把顯示方式改成報表形式
3、【類嚮導】-【成員變數】-【新增變數】-【m_List_xxx】,繫結一個操作的變數
程式碼部分
- 新增List控制元件的列表頭,增加列 InsertColumn();
m_List_xxx.InsertColumn(i, // 插入的列 g_Column_Message_Data[i].title, // 插入的標題 LVCFMT_CENTER, // 插入的樣式 g_Column_Message_Data[i].nWidth); // 插入的寬度
封裝函式,定義結構體部分:
定義一個結構體,成員是標題【WCHAR *title】、寬度【int nWidth】。然後初始化每一列的列名佔據叫什麼名字,佔據多寬。
/////////////////////////////////////////// 列表控制元件 typedef struct { WCHAR *title; //列表的名稱 int nWidth; //列表的寬度 }COLUMNSTRUCT; COLUMNSTRUCT g_Column_Message_Data[] = { { _T("資訊型別"), 80 }, { _T("時間"), 100 }, { _T("資訊內容"), 300 } }; //變數宣告 int g_Column_Message_Count = 3; //列表的個數 int g_Column_Message_Width = 0; //列總寬度,初始化為0。在後面的函式中會賦值
新建一個函式【int GUI_InitList(void)】,在【OnInitDialog()】裡呼叫。初始化List顯示的列表名
int CAPTFilecheckDlg::GUI_InitList(void)
{
// init online list
m_CList_dirlist.SetExtendedStyle(LVS_EX_FULLROWSELECT);
for (int i = 0; i < g_Column_Online_Count; i++)
{
m_CList_dirlist.InsertColumn(i, g_Column_Online_Data[i].title, LVCFMT_CENTER, g_Column_Online_Data[i].nWidth);
g_Column_Online_Width += g_Column_Online_Data[i].nWidth; //得到總寬度
}
m_CList_MESSAGE.SetExtendedStyle(LVS_EX_FULLROWSELECT);
for (int i = 0; i < g_Column_Message_Count; i++)
{
m_CList_MESSAGE.InsertColumn(i, g_Column_Message_Data[i].title, LVCFMT_CENTER, g_Column_Message_Data[i].nWidth);
g_Column_Message_Width += g_Column_Message_Data[i].nWidth; //得到總寬度
}
return 0;;
}
- 跟隨介面調整大小
最大化的時候介面跟著變大。
【類嚮導】-【訊息】-【WM_SIZE】-【新增處理程式】,增加一個【OnSize】的訊息函式
void CMFCClistDlg::OnSize(UINT nType, int cx, int cy)
{
CDialogEx::OnSize(nType, cx, cy);
// TODO: 在此處新增訊息處理程式程式碼
// 命中目標
double dcx = cx; //對話方塊的總寬度
if (m_List_xxx.m_hWnd != NULL)
{
CRect rc;
rc.left = 1; //列表的左座標
rc.top = 20; //列表的上座標
rc.right = cx - 1; //列表的右座標
rc.bottom = cy - 20; //列表的下座標
m_List_xxx.MoveWindow(rc);
for (auto i = 0; i < g_Column_Message_Count; i++) { //遍歷每一個列
double dd = g_Column_Message_Data[i].nWidth; //得到當前列的寬度
dd /= g_Column_Message_Width; //看一看當前寬度佔總長度的幾分之幾
dd *= dcx; //用原來的長度乘以所佔的幾分之幾得到當前的寬度
auto lenth = dd; //轉換為int 型別
m_List_xxx.SetColumnWidth(i, (lenth)); //設定當前的寬度
}
}
}
- 增加列內容InsertItem()/SetItemText()
m_List_xxx.InsertItem(0, L"ok"); // 第一行的第一列內容
m_List_xxx.SetItemText(0, 1, L"2"); // 第一行的第二列內容
m_List_xxx.SetItemText(0, 2, L"hello world"); // 第一行的第三列內容
封裝函式部分1:
void CAPTFilecheckDlg::GUI_ShowMessage(bool bIsOK, CString strMsg)
{
CString strIsOK, strTime;
CTime t = CTime::GetCurrentTime();
strTime = t.Format("%H:%M:%S");
if (bIsOK)
{
strIsOK = "執行成功";
}
else {
strIsOK = "執行失敗";
}
m_CList_MESSAGE.InsertItem(0, strIsOK,2018);
m_CList_MESSAGE.SetItemText(0, 1, strTime);
m_CList_MESSAGE.SetItemText(0, 2, strMsg);
}
呼叫方法:
GUI_ShowMessage(true, L"mesage");
GUI_ShowMessage(true, L"mesage1");
GUI_ShowMessage(true, L"mesage2");
2、選單控制元件
新建選單
【資源檢視】-【新增資源】-【Menu】控制元件增加右鍵的說明
【刪除單條】
【刪除全部】
【增加內容】新增右鍵選單
在【List Control】控制元件右鍵屬性找到【NM_RCLICK】,雙擊繫結右鍵事件。有些判斷也順便加進去,根據需要再增加改動。
void CMFCClistDlg::OnNMRClickList1(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
// TODO: 在此新增控制元件通知處理程式程式碼
CMenu popup;
popup.LoadMenu(IDR_MENU1);
CMenu* pM = popup.GetSubMenu(0);
CPoint p;
GetCursorPos(&p);
int count = pM->GetMenuItemCount();
//如果沒有選中
if (m_List_xxx.GetSelectedCount() == 0)
{
for (int i = 2; i < count; i++)
{ //選單全部變灰
pM->EnableMenuItem(i, MF_BYPOSITION | MF_DISABLED | MF_GRAYED);
}
}
pM->TrackPopupMenu(TPM_LEFTALIGN, p.x, p.y, this);
*pResult = 0;
}
- 繫結事件
在每個安全事件上新增事件處理程式,在訊息型別【COMMAND】、類列表【xxxxDlg】,指定事件函式比如刪除單條就繫結【GUI_Dir_Delete()】、刪除全部就繫結【GUI_Dir_DeleteALL_Items()】。
-
- 右鍵刪除單行功能實現,GetItemCount()/DeleteItem():
刪除單條要先獲取選中的條目,然後遍歷
void CMFCClistDlg::GUI_Dir_Delete()
{
// TODO: 在此新增命令處理程式程式碼
int i, iState;
// 當前選擇的條目
int nItemSelected = m_List_xxx.GetSelectedCount();
// 檢索在列表檢視控制元件中的項的數目。
int nItemCount = m_List_xxx.GetItemCount();
// 如果沒有選擇值,就退出這個函式,不執行刪除判斷。
if (nItemSelected < 1)
return;
// 遍歷當前所有的列,找到選中的那條刪除。
for (i = nItemCount - 1; i >= 0; i--)
{
iState = m_List_xxx.GetItemState(i, LVIS_SELECTED); // 獲取選擇狀態
if (iState != 0)
{
m_List_xxx.DeleteItem(i); // 刪除
}
}
}
-
- 右鍵刪除所有行功能實現,DeleteAllItems()/SetRedraw()/RedrawWindow();
// 刪除所有特徵
void CMFCClistDlg::GUI_Dir_DeleteALL_Items()
{
// TODO: 在此新增命令處理程式程式碼
m_CList_dirlist.DeleteAllItems();
m_CList_dirlist.SetRedraw(FALSE);
//do erase and insert operation
m_CList_dirlist.SetRedraw(TRUE);
m_CList_dirlist.RedrawWindow();
}
-
- 右鍵增加內容功能實現
結合前面增加內容的函式,可以繫結一個【增加內容】的函式,【GUI_Add_Check_Dir()】。
函式作用主要是開啟檔案瀏覽器,然後選中路徑,增加到LIST控制元件中。
void CMFCClistDlg::GUI_Add_Check_Dir()
{
// TODO: 在此新增命令處理程式程式碼
CString m_strFileOut = _T("");
TCHAR servPath[MAX_PATH];//用來存放資料夾路徑
BROWSEINFO bi;
LPITEMIDLIST pidl;
bi.hwndOwner = this->m_hWnd;
bi.pidlRoot = NULL;
bi.pszDisplayName = servPath;
bi.lpszTitle = _T("選擇檔案路徑");
bi.ulFlags = BIF_RETURNONLYFSDIRS;
bi.lpfn = NULL;
bi.lParam = NULL;
bi.iImage = NULL;
if ((pidl = SHBrowseForFolder(&bi)) != NULL)
{
//得到資料夾的全路徑,不要的話,只得本資料夾名
if (SHGetPathFromIDList(pidl, servPath))
{
// 增加內容
GUI_ShowMessage(true, servPath);
}
}
// 把變數內容更新到對話方塊
UpdateData(FALSE);
}
0x4 總結
主要功能:
CListCtrl控制元件使用,右鍵選單功能刪除單行、刪除全部、增加自定義內容。
0x5 效果
0x6 參考
MSDN VS2017
https://docs.microsoft.com/zh-cn/cpp/mfc/reference/clistctrl-class?f1url=https%3A%2F%2Fmsdn.microsoft.com%2Fquery%2Fdev15.query%3FappId%3DDev15IDEF1%26l%3DZH-CN%26k%3Dk(AFXCMN%2FCListCtrl%3A%3AInsertItem)%3Bk(CListCtrl%3A%3AInsertItem)%3Bk(InsertItem)%3Bk(DevLang-C%2B%2B)%3Bk(TargetOS-Windows)%26rd%3Dtrue&view=vs-2017#insertcolumn
VS2010/MFC程式設計入門之二十九(常用控制元件:列表檢視控制元件List Control 下)
http://www.jizhuomi.com/software/197.html