MFC中CTabCtrl控件和CListCtrl控件的组合使用
在CTabCtrl控件中插入CListCtrl控件有两种做法:
方法1:
在CTabCtrl控件的每一页中加入一个对话框资源,并在对话框中加入CListCtrl资源。这种方法适合于每一页都是多控件的情况,需要注意的是对话框响应OnSize的时候其中的控件的变动由对话框自己实现,而不是由CTabCtrl控件来实现。
方法2:
在CTabCtrl控件的每一页直接加入一个CListCtrl,让CListCtrl直接填充Tab控件或者根据Tab控件的大小改变。
方法2的代码实现(环境是VC++6.0)
.cpp文件中将表格加入Tab控件,OnSize响应处理控件大小的变化
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 // testTabControlDlg.cpp : implementation file 2 // 3 4 #include "stdafx.h" 5 #include "testTabControl.h" 6 #include "testTabControlDlg.h" 7 8 #ifdef _DEBUG 9 #define new DEBUG_NEW 10 #undef THIS_FILE 11 static char THIS_FILE[] = __FILE__; 12 #endif 13 14 ///////////////////////////////////////////////////////////////////////////// 15 // CAboutDlg dialog used for App About 16 17 class CAboutDlg : public CDialog 18 { 19 public: 20 CAboutDlg(); 21 22 // Dialog Data 23 //{{AFX_DATA(CAboutDlg) 24 enum { IDD = IDD_ABOUTBOX }; 25 //}}AFX_DATA 26 27 // ClassWizard generated virtual function overrides 28 //{{AFX_VIRTUAL(CAboutDlg) 29 protected: 30 virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support 31 //}}AFX_VIRTUAL 32 33 // Implementation 34 protected: 35 //{{AFX_MSG(CAboutDlg) 36 //}}AFX_MSG 37 DECLARE_MESSAGE_MAP() 38 }; 39 40 CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) 41 { 42 //{{AFX_DATA_INIT(CAboutDlg) 43 //}}AFX_DATA_INIT 44 } 45 46 void CAboutDlg::DoDataExchange(CDataExchange* pDX) 47 { 48 CDialog::DoDataExchange(pDX); 49 //{{AFX_DATA_MAP(CAboutDlg) 50 //}}AFX_DATA_MAP 51 } 52 53 BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) 54 //{{AFX_MSG_MAP(CAboutDlg) 55 // No message handlers 56 //}}AFX_MSG_MAP 57 END_MESSAGE_MAP() 58 59 ///////////////////////////////////////////////////////////////////////////// 60 // CTestTabControlDlg dialog 61 62 CTestTabControlDlg::CTestTabControlDlg(CWnd* pParent /*=NULL*/) 63 : CDialog(CTestTabControlDlg::IDD, pParent) 64 { 65 //{{AFX_DATA_INIT(CTestTabControlDlg) 66 // NOTE: the ClassWizard will add member initialization here 67 //}}AFX_DATA_INIT 68 // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 69 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 70 } 71 72 void CTestTabControlDlg::DoDataExchange(CDataExchange* pDX) 73 { 74 CDialog::DoDataExchange(pDX); 75 //{{AFX_DATA_MAP(CTestTabControlDlg) 76 DDX_Control(pDX, IDC_TAB1, m_tabctrl); 77 //}}AFX_DATA_MAP 78 } 79 80 BEGIN_MESSAGE_MAP(CTestTabControlDlg, CDialog) 81 //{{AFX_MSG_MAP(CTestTabControlDlg) 82 ON_WM_SYSCOMMAND() 83 ON_WM_PAINT() 84 ON_WM_QUERYDRAGICON() 85 ON_NOTIFY(TCN_SELCHANGE, IDC_TAB1, OnSelchangeTab1) 86 ON_WM_SIZE() 87 //}}AFX_MSG_MAP 88 END_MESSAGE_MAP() 89 90 ///////////////////////////////////////////////////////////////////////////// 91 // CTestTabControlDlg message handlers 92 93 BOOL CTestTabControlDlg::OnInitDialog() 94 { 95 CDialog::OnInitDialog(); 96 97 // Add "About..." menu item to system menu. 98 99 // IDM_ABOUTBOX must be in the system command range. 100 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); 101 ASSERT(IDM_ABOUTBOX < 0xF000); 102 103 CMenu* pSysMenu = GetSystemMenu(FALSE); 104 if (pSysMenu != NULL) 105 { 106 CString strAboutMenu; 107 strAboutMenu.LoadString(IDS_ABOUTBOX); 108 if (!strAboutMenu.IsEmpty()) 109 { 110 pSysMenu->AppendMenu(MF_SEPARATOR); 111 pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); 112 } 113 } 114 115 // Set the icon for this dialog. The framework does this automatically 116 // when the application's main window is not a dialog 117 SetIcon(m_hIcon, TRUE); // Set big icon 118 SetIcon(m_hIcon, FALSE); // Set small icon 119 120 // TODO: Add extra initialization here 121 TCITEM tcItem; 122 tcItem.mask = TCIF_TEXT; 123 tcItem.pszText = _T("tab1"); 124 m_tabctrl.InsertItem(0, &tcItem); 125 tcItem.pszText = _T("tab2"); 126 m_tabctrl.InsertItem(1, &tcItem); 127 128 CRect rect; 129 m_tabctrl.GetClientRect(&rect); 130 rect.top += 20; 131 LV_COLUMN lvcol; 132 lvcol.mask = LVCF_FMT|LVCF_SUBITEM|LVCF_TEXT|LVCF_WIDTH; 133 lvcol.fmt = LVCFMT_CENTER; 134 m_lsttab1.Create(WS_CHILD|WS_VISIBLE|WS_BORDER|LVS_REPORT,rect,&m_tabctrl,IDC_LST_TAB1); 135 // 设置m_lsttab1有网格线风格 136 DWORD dwStyle = m_lsttab1.GetExtendedStyle(); 137 dwStyle |= LVS_EX_GRIDLINES; 138 m_lsttab1.SetExtendedStyle(dwStyle); 139 // 加入两列并设置表头 140 lvcol.pszText = "tab1col0"; 141 lvcol.iSubItem = 0; 142 lvcol.cx = 100; 143 m_lsttab1.InsertColumn(0,&lvcol); 144 lvcol.pszText = "tab1col1"; 145 lvcol.iSubItem = 1; 146 lvcol.cx = 100; 147 m_lsttab1.InsertColumn(1,&lvcol); 148 m_lsttab1.ShowWindow(SW_SHOW); 149 m_lsttab2.Create(WS_CHILD|WS_VISIBLE|WS_BORDER|LVS_REPORT,rect,&m_tabctrl,IDC_LST_TAB2); 150 // 设置m_lsttab2有网格线风格 151 dwStyle = m_lsttab2.GetExtendedStyle(); 152 dwStyle |= LVS_EX_GRIDLINES; 153 m_lsttab2.SetExtendedStyle(dwStyle); 154 // 加入两列并设置表头 155 lvcol.pszText = "tab2col0"; 156 lvcol.iSubItem = 0; 157 lvcol.cx = 100; 158 m_lsttab2.InsertColumn(0,&lvcol); 159 lvcol.pszText = "tab2col1"; 160 lvcol.iSubItem = 1; 161 lvcol.cx = 100; 162 m_lsttab2.InsertColumn(1,&lvcol); 163 m_lsttab2.ShowWindow(SW_HIDE); 164 m_tabctrl.SetCurSel(0); 165 166 GetClientRect(&m_rect); 167 return TRUE; // return TRUE unless you set the focus to a control 168 } 169 170 void CTestTabControlDlg::OnSysCommand(UINT nID, LPARAM lParam) 171 { 172 if ((nID & 0xFFF0) == IDM_ABOUTBOX) 173 { 174 CAboutDlg dlgAbout; 175 dlgAbout.DoModal(); 176 } 177 else 178 { 179 CDialog::OnSysCommand(nID, lParam); 180 } 181 } 182 183 // If you add a minimize button to your dialog, you will need the code below 184 // to draw the icon. For MFC applications using the document/view model, 185 // this is automatically done for you by the framework. 186 187 void CTestTabControlDlg::OnPaint() 188 { 189 if (IsIconic()) 190 { 191 CPaintDC dc(this); // device context for painting 192 193 SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); 194 195 // Center icon in client rectangle 196 int cxIcon = GetSystemMetrics(SM_CXICON); 197 int cyIcon = GetSystemMetrics(SM_CYICON); 198 CRect rect; 199 GetClientRect(&rect); 200 int x = (rect.Width() - cxIcon + 1) / 2; 201 int y = (rect.Height() - cyIcon + 1) / 2; 202 203 // Draw the icon 204 dc.DrawIcon(x, y, m_hIcon); 205 } 206 else 207 { 208 CDialog::OnPaint(); 209 } 210 } 211 212 // The system calls this to obtain the cursor to display while the user drags 213 // the minimized window. 214 HCURSOR CTestTabControlDlg::OnQueryDragIcon() 215 { 216 return (HCURSOR) m_hIcon; 217 } 218 219 void CTestTabControlDlg::OnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult) 220 { 221 // TODO: Add your control notification handler code here 222 int CulSel = m_tabctrl.GetCurSel(); 223 switch(CulSel) 224 { 225 case 0: 226 m_lsttab1.ShowWindow(SW_SHOW); 227 m_lsttab2.ShowWindow(SW_HIDE); 228 break; 229 case 1: 230 m_lsttab1.ShowWindow(SW_HIDE); 231 m_lsttab2.ShowWindow(SW_SHOW); 232 break; 233 default: 234 break; 235 } 236 *pResult = 0; 237 } 238 239 void CTestTabControlDlg::OnSize(UINT nType, int cx, int cy) 240 { 241 CDialog::OnSize(nType, cx, cy); 242 // TODO: Add your message handler code here 243 if(m_tabctrl.GetSafeHwnd() != NULL) 244 { 245 CRect rect; 246 m_tabctrl.GetWindowRect(&rect); 247 ScreenToClient(rect);// 获取tab控件的原始大小 248 249 // 改变tab控件的大小 250 rect.top = rect.top*cy/m_rect.Height(); 251 rect.bottom = rect.bottom*cy/m_rect.Height(); 252 rect.left = rect.left*cx/m_rect.Width(); 253 rect.right = rect.right*cx/m_rect.Width(); 254 m_tabctrl.MoveWindow(&rect); 255 256 // 改变表格的大小 257 if(m_lsttab1.GetSafeHwnd() != NULL && m_lsttab2.GetSafeHwnd() != NULL) 258 { 259 rect.top += 20; 260 m_lsttab1.MoveWindow(&rect); 261 m_lsttab2.MoveWindow(&rect); 262 } 263 } 264 265 if(GetDlgItem(IDOK)->GetSafeHwnd() !=NULL) 266 { 267 CRect bottonrect; 268 GetDlgItem(IDOK)->GetWindowRect(&bottonrect); 269 ScreenToClient(bottonrect); 270 bottonrect.left = bottonrect.left*cx/m_rect.Width(); 271 bottonrect.top = bottonrect.top*cy/m_rect.Height(); 272 GetDlgItem(IDOK)->SetWindowPos(NULL,bottonrect.left,bottonrect.top,0,0,SWP_NOSIZE|SWP_NOZORDER); 273 } 274 275 if(GetDlgItem(IDCANCEL)->GetSafeHwnd() !=NULL) 276 { 277 CRect bottonrect; 278 GetDlgItem(IDCANCEL)->GetWindowRect(&bottonrect); 279 ScreenToClient(bottonrect); 280 bottonrect.left = bottonrect.left*cx/m_rect.Width(); 281 bottonrect.top = bottonrect.top*cy/m_rect.Height(); 282 GetDlgItem(IDCANCEL)->SetWindowPos(NULL,bottonrect.left,bottonrect.top,0,0,SWP_NOSIZE|SWP_NOZORDER); 283 } 284 285 if(GetDlgItem(IDC_BUTTON1)->GetSafeHwnd() !=NULL) 286 { 287 CRect bottonrect; 288 GetDlgItem(IDC_BUTTON1)->GetWindowRect(&bottonrect); 289 ScreenToClient(bottonrect); 290 bottonrect.left = bottonrect.left*cx/m_rect.Width(); 291 bottonrect.top = bottonrect.top*cy/m_rect.Height(); 292 GetDlgItem(IDC_BUTTON1)->SetWindowPos(NULL,bottonrect.left,bottonrect.top,0,0,SWP_NOSIZE|SWP_NOZORDER); 293 } 294 295 GetClientRect(&m_rect); 296 }
.h文件申明了三个类的成员变量
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 // testTabControlDlg.h : header file 2 // 3 4 #if !defined(AFX_TESTTABCONTROLDLG_H__10C325CB_28C8_4189_AE00_9E7FB981763C__INCLUDED_) 5 #define AFX_TESTTABCONTROLDLG_H__10C325CB_28C8_4189_AE00_9E7FB981763C__INCLUDED_ 6 7 #if _MSC_VER > 1000 8 #pragma once 9 #endif // _MSC_VER > 1000 10 11 ///////////////////////////////////////////////////////////////////////////// 12 // CTestTabControlDlg dialog 13 14 class CTestTabControlDlg : public CDialog 15 { 16 // Construction 17 public: 18 CTestTabControlDlg(CWnd* pParent = NULL); // standard constructor 19 20 // Dialog Data 21 //{{AFX_DATA(CTestTabControlDlg) 22 enum { IDD = IDD_TESTTABCONTROL_DIALOG }; 23 CTabCtrl m_tabctrl; 24 CListCtrl m_lsttab1; 25 CListCtrl m_lsttab2; 26 CRect m_rect; 27 //}}AFX_DATA 28 29 // ClassWizard generated virtual function overrides 30 //{{AFX_VIRTUAL(CTestTabControlDlg) 31 protected: 32 virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support 33 //}}AFX_VIRTUAL 34 35 // Implementation 36 protected: 37 HICON m_hIcon; 38 39 // Generated message map functions 40 //{{AFX_MSG(CTestTabControlDlg) 41 virtual BOOL OnInitDialog(); 42 afx_msg void OnSysCommand(UINT nID, LPARAM lParam); 43 afx_msg void OnPaint(); 44 afx_msg HCURSOR OnQueryDragIcon(); 45 afx_msg void OnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult); 46 afx_msg void OnSize(UINT nType, int cx, int cy); 47 //}}AFX_MSG 48 DECLARE_MESSAGE_MAP() 49 }; 50 51 //{{AFX_INSERT_LOCATION}} 52 // Microsoft Visual C++ will insert additional declarations immediately before the previous line. 53 54 #endif // !defined(AFX_TESTTABCONTROLDLG_H__10C325CB_28C8_4189_AE00_9E7FB981763C__INCLUDED_)