1. 程式人生 > >MFC-小型工具通用介面框架

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