程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> 如何實現由列表控件控制的屬性表

如何實現由列表控件控制的屬性表

編輯:關於VC++

摘要:很多MFC的程序都用到了屬性表和屬性頁來實現選項設置的界面,但是MFC本身提供的屬性表頁功能有限,界面也很原始,一些新軟件都實現了自己定義的更為美觀的屬性頁。MFC原始的屬性頁是通過CTabCtrl進行切換控制的,本文給出了一種現在較為常見的用CListCtrl進行頁面切換的屬性頁的方法,並且對對列表控件進行了重繪。 CMyPropertySheet是一個從CPropertySheet派生而來的類,因此你仍然可以不費力的利用MFC CPropertySheet的諸多特性,具體使用方法稍後我會詳細說明。

該屬性表的實現效果如下:

圖一

一、使用

CMyPropertySheet的使用方法與MFC的CPropertySheet類似,首先要在程序中創建兩個屬性頁,也就是兩個CPropertyPage的派生對象。然後將MyPropertySheet.cpp 和 MyPropertySheet.h添加至工程,在程序的視圖類頭文件中(假定是個SDI程序)將CMyPropertySheet的頭文件包含進來

#include “MyPropertySheet.h”

在資源視圖裡設置一個新的菜單項“選項”(放在哪兒隨你) 用ClassWizard添加響應函數,在該函數裡添加如下代碼創建一個屬性表對象myPS

CMyPropertySheet myPS;

然後向屬性表添加兩個屬性頁。

myPS.AddPage(&m_page1);
myPS.AddPage(&m_page2);

接下來要添加屬性頁的圖標,該圖標會在對應列表項以及屬性頁的標題上顯示,注意這裡添加的順序要與屬性頁的添加順序保持一致。

myPS.AddIcon(IDI_GLOBAL);
myPS.AddIcon(IDI_ADDITION);

最後創建並顯示該屬性頁。

myPS.DoModal();

剩下的工作就跟一般屬性表完全一樣了。

CMyPropertySheet類提供如下自定義函數,可以對屬性表的外觀進行設置。

SetSepratorColor,SetCaptionColor與SetSelectedColor都接受一個類型為COLORREF的參數,分別用以設置列表分隔線,屬性頁標題以及列表選擇項背景的顏色。

SetListFont設置列表的字體。

讀者也可以根據自己的需要對其進行擴充。

二、實現邏輯

MFC原來的屬性頁是由TabCtrl控制的,而且屬性頁的大小已經與屬性表按比例設置好,因此,要實現如圖一所示的屬性頁,我們有如下幾步工作需要做:

1.對屬性頁原來的TabCtrl進行隱藏。

2.調整屬性表的大小,將屬性頁移至屬性表右側,以容納列表控件。

3.獲得TabCtrl的矩形,根據該矩形畫屬性頁標題。

4.初始化列表控件內容,調整列表項高度。

5.響應列表的NM_CLICK事件,根據得到的點擊項ID進行屬性頁的切換。

其中調整尺寸的工作必須在OnInitDialog函數中進行。

BOOL CMyPropertySheet::OnInitDialog()
{

  BOOL bResult = CPropertySheet::OnInitDialog();
  //計算屬性頁的矩形,擴大屬性表並將屬性頁其移至右側
  CRect rect, rectPage, rectTab;
  GetPage(0)->GetWindowRect(&rectPage);

  GetWindowRect(&rect);
  rect.right += 150;

  int nWidth = rectPage.Width();
  rectPage.right = rect.right - 20;
  rectPage.left = rect.right - nWidth;
  ScreenToClient(&rectPage);
  m_rectPage = rectPage;
  MoveWindow(&rect);
  GetPage(0)->MoveWindow(&rectPage);

  //隱藏屬性頁原來的TabControl
  CTabCtrl *pTab = GetTabControl() ;
  pTab->GetWindowRect(&rectTab);
  ScreenToClient(&rectTab);
  if(!pTab->ShowWindow(SW_HIDE))
    return FALSE;

  //創建列表控件並用一個CImageList對象與之關聯
  if(!m_wndList.Create(WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_NOCOLUMNHEADER ,
              CRect(10 ,rectTab.top,150,rectPage.bottom ),this,0xFFFF))
    return FALSE;
  m_wndList.SetExtendedStyle(LVS_EX_FULLROWSELECT);
  m_wndList.SetImageList(&m_imgList, LVSIL_SMALL);

  InitList();
  //設置行高度
  CFont font;
  font.CreatePointFont(240,_T("宋體"));
  m_wndList.SetFont(&font);

  CString strCaption;
  GetPage(0)->GetWindowText(strCaption);
  _tcscpy(m_szCaption, strCaption.GetBuffer(strCaption.GetLength()));
  return bResult;
}

屬性頁的切換:

void CMyPropertySheet::OnNMClick(NMHDR *pNMHDR, LRESULT *pResult)
{
  LPNMITEMACTIVATE lpItem = reinterpret_cast(pNMHDR);
  m_nSelectedItem = lpItem->iItem ;
  if (lpItem->iItem >= 0 && lpItem->iItem < m_wndList.GetItemCount())
  {
    m_nSelectedItem = lpItem->iItem;
    CString strCaption = m_wndList.GetItemText(lpItem->iItem,0);
   _tcscpy(m_szCaption, strCaption);
  SetActivePage(m_nSelectedItem);

  Invalidate();

  GetPage(m_nSelectedItem)->MoveWindow(&m_rectPage);
  m_wndList.SetFocus();
  }

}

三、總結

關於列表控件自繪的問題在這裡不做詳細討論,可以參考源代碼裡面OnNMCustomDraw的部分以及MSDN上的相關資料。對屬性頁的修改還有很多種方法和很多種方式,比如還可以用樹型控件進行控制,這裡提供的方法也可以做一般意義上的推廣 ,並不難實現其它方式的控制。程序在Visual C++ 2005 下編譯通過。

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved