概述
- MFC微軟基礎(chǔ)類庫(kù)的作用在Windows平臺(tái)做GUI開發(fā)使用
- MFC框架設(shè)計(jì)思想
Windows消息機(jī)制
- SDK 軟件開發(fā)工具包(Software Development Kit)
SDK是軟件開發(fā)人員為特定軟件包谓媒、框架赂摆、硬件平臺(tái)、操作系統(tǒng)等建立引用軟件的開發(fā)工具的集合知纷。
- API 應(yīng)用程序編程接口(Application Programming Interface)
WindowsAPI函數(shù)是通過C實(shí)現(xiàn)的浩峡,主要在windows.h
頭文件中進(jìn)行了聲明禁谦。
- 窗口和句柄
窗口是Windows應(yīng)用程序中非常重要的元素划纽,一個(gè)Windows應(yīng)用程序至少要有一個(gè)窗口锁荔,稱為主窗口结洼。
窗口時(shí)屏幕上的一塊矩形區(qū)域黎做,是Windows應(yīng)用程序與用戶進(jìn)行交互的接口叉跛,利用窗口可接受用戶輸入及顯示輸出松忍。
窗口可分為客戶區(qū)和非客戶區(qū),客戶區(qū)市窗口的一部分筷厘。
窗口可有一個(gè)父窗口鸣峭,有父窗口的窗口稱為子窗口。
Windows應(yīng)用程序中酥艳,窗口時(shí)通過窗口句柄(HWND)來標(biāo)識(shí)摊溶,對(duì)窗口的操作時(shí)首先要得到窗口句柄。
句柄(HANDLE)是Windows程序的一個(gè)重要概念充石,在Windows程序中莫换,有各種資源如窗口、圖標(biāo)骤铃、光標(biāo)拉岁、畫刷等。系統(tǒng)在創(chuàng)建這些資源時(shí)會(huì)為其分配內(nèi)存惰爬,并返回標(biāo)識(shí)資源的標(biāo)識(shí)號(hào)即句柄喊暖。
- 消息和消息隊(duì)列
Windows程序設(shè)計(jì)是一種完全不同于傳統(tǒng)DOS的程序設(shè)計(jì)方法,是一種事件驅(qū)動(dòng)方式的程序設(shè)計(jì)模式撕瞧,主要是基于消息的陵叽。
每個(gè)Windows應(yīng)用程序開始執(zhí)行后,系統(tǒng)都會(huì)為該程序創(chuàng)建一個(gè)消息隊(duì)列丛版,這個(gè)消息隊(duì)列用來存放該程序創(chuàng)建的窗口的消息巩掺。
例如,當(dāng)用戶在窗口中畫圖時(shí)页畦,按下鼠標(biāo)左鍵胖替,此時(shí)操作系統(tǒng)會(huì)感知此事件,于是將事件包裝成一個(gè)消息寇漫,投遞到應(yīng)用程序的消息隊(duì)列中刊殉,等待應(yīng)用程序的處理。然后州胳,應(yīng)用程序通過一個(gè)消息循環(huán)不斷地從消息隊(duì)列中取出消息记焊,并進(jìn)行響應(yīng)。在這個(gè)處理過程中栓撞,操作系統(tǒng)會(huì)給應(yīng)用程序發(fā)送消息遍膜,實(shí)際是操作系統(tǒng)調(diào)用程序中一個(gè)專門負(fù)責(zé)處理消息的函數(shù)碗硬,這個(gè)函數(shù)成為窗口過程。
- WinMain函數(shù)
當(dāng)Windows操作系統(tǒng)啟動(dòng)一個(gè)程序時(shí)瓢颅,它調(diào)用的就是該程序的WinMain()
函數(shù)恩尾,實(shí)際上是由插入到可執(zhí)行文件中的啟動(dòng)代碼調(diào)用的。
WinMain()
是Windows程序的入口函數(shù)挽懦,與DOS程序的入口點(diǎn)函數(shù)main()
的作用是相同的翰意,但WinMain()
函數(shù)結(jié)束或返回時(shí),Windows程序結(jié)束信柿。
Windows編程模型
完整的Win32程序#include<windows.h>
實(shí)現(xiàn)的功能是創(chuàng)建一個(gè)窗口冀偶,并在該窗口中響應(yīng)鍵盤及鼠標(biāo)消息,程序?qū)崿F(xiàn)步驟:
- WinMain函數(shù)定義
- 創(chuàng)建窗口
- 消息循環(huán)
- 編寫窗口過程函數(shù)
VS2017配置
包含目錄的路徑渔嚷,這里以SDk版本10.0.15063.0為例进鸠,添加路徑如下:
C:\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\shared
C:\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\ucrt
C:\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\um
C:\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\winrt
庫(kù)目錄的路徑,添加路徑如下:
C:\Program Files (x86)\Windows Kits\10\Lib\10.0.15063.0\ucrt\x86
C:\Program Files (x86)\Windows Kits\10\Lib\10.0.15063.0\um\x86
windows.c
$ vim windows.c
//底層實(shí)現(xiàn)窗口的頭文件
#include <windows.h>
/**
* 程序入口函數(shù)
* WINAPI 宏 代表 __stdcall形病,表示參數(shù)傳遞順序客年,從右到左依次入棧,在函數(shù)返回前清空棧漠吻。
* HINSTACE H表示句柄
* HINSTACE hInstance 應(yīng)用程序?qū)嵗浔?* HINSTACE hPrevInstance 上一個(gè)應(yīng)用程序句柄量瓜,在win32環(huán)境下參數(shù)一般為NULL,不起作用侥猩。
* LPSTR lpCmdLine 代表 char * argv[]
* int nShowCmd 顯示命令榔至,即最大化、最小化欺劳、正常
*/
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
//1.設(shè)計(jì)窗口
//2.注冊(cè)窗口
//3.創(chuàng)建窗口
//4.顯示更新
//5.通過循環(huán)獲取消息
//6.處理消息即窗口過程
//設(shè)計(jì)窗口
WNDCLASS wc;//Windows類
wc.cbClsExtra = 0;//類的額外內(nèi)存
wc.cbWndExtra = 0;//窗口額外內(nèi)存
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//設(shè)置背景
wc.hCursor = LoadCursor(NULL, IDC_HAND);//設(shè)置光標(biāo),參數(shù)1為NULL為系統(tǒng)提供的光標(biāo)
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);//設(shè)置圖標(biāo)
wc.hInstance = hInstance;//應(yīng)用程序?qū)嵗浔笕。瑐魅雽?shí)例句柄
wc.lpfnWndProc = WindowProc;//窗口過程,即回調(diào)函數(shù)
wc.lpszClassName = TEXT("WIN");//窗口類名
wc.lpszMenuName = NULL;//窗口菜單名稱
wc.style = 0;//顯示風(fēng)格 0默認(rèn)風(fēng)格
//注冊(cè)窗口
RegisterClass(&wc);
//創(chuàng)建窗口
// lpClassName 窗口類名
// lpWindowName 窗口標(biāo)題名稱
// dwStyle 窗口風(fēng)格 混合風(fēng)格
// x X坐標(biāo) 默認(rèn)值 CW_USERDEFAULT
// y Y坐標(biāo) 默認(rèn)值 CW_USERDEFAULT
// nWidth
// nHeight 默認(rèn)值 CW_USERDEFAULT
// hWndParent 父窗口划提,頂層方式彈出為NULL
// hMenu 窗口菜單
// hInstance 實(shí)例句柄
// lpParam 附加值
HWND hwnd = CreateWindow(
wc.lpszClassName,
TEXT("WINDOWS"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
CW_USEDEFAULT
);//todo “CreateWindowExW”: 指針與實(shí)參 12 不匹配
//顯示更新
ShowWindow(
hwnd,
SW_SHOWNORMAL//展示方式 普通方式
);
UpdateWindow(hwnd);
//通過循環(huán)獲取消息
/*
每個(gè)消息都是一個(gè)結(jié)構(gòu)體
HWND hwnd; 主窗口句柄
UINT message; 消息名稱
WPARAM wParam; 附件消息 通常為鍵盤消息
LPARAM lParam; 附加消息 通常為鼠標(biāo)左右鍵消息
DWORD time; 消息產(chǎn)生時(shí)間
POINT pt; 附加消息 鼠標(biāo)坐標(biāo)點(diǎn)消息
*/
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
/*
捕獲消息 GetMessage()
_Out_ LPMSG lpMsg;//消息地hi
_In_opt_ HWND hWnd;//捕獲窗口 NULL為捕獲所有窗口
_In_ UNIT wMsgFilterMin;//最小的過濾消息 0表示捕獲所有消息
_In_ UINT wMsgFilterMax;//最大的過濾消息 0表示捕獲所有消息
*/
//if (GetMessage(&msg, NULL, 0, 0) == FALSE) {
// break;//若關(guān)閉窗口則退出死循環(huán)
//}
// 翻譯消息
TranslateMessage(&msg);//例如針對(duì)鍵盤組合快捷鍵需翻譯
// 分發(fā)消息
DispatchMessage(&msg);
}
return 0;
}
窗口處理過程
/**
* 處理窗口過程
* HWND hWnd 消息所屬的窗口句柄
* UINT uMsg 具體的消息名稱
* WPARAM wParam 鍵盤附加消息
* LPARAM lParam 鼠標(biāo)附加消息
*/
LRESULT CALLBACK WindowProc(
HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
//根據(jù)不同消息做不同的處理
switch (uMsg) {
//關(guān)閉窗口 發(fā)送另一個(gè)消息WM_DESTROY
case WM_CLOSE:
DestroyWindow(hWnd); //所有xxxWindow為結(jié)尾的方法都不會(huì)進(jìn)入消息隊(duì)列而會(huì)直接執(zhí)行
break;
//關(guān)閉窗口退出進(jìn)程
case WM_DESTROY:
PostQuitMessage(0);
break;
//鼠標(biāo)左鍵按下
case WM_LBUTTONDOWN:
{
int xPos = LOWORD(lParam);
int yPos = HIWORD(lParam);
char buf[1024];
wsprintf(buf, TEXT("X = %d Y = %d"), xPos, yPos);//todo 從“char [1024]”到“LPCWSTR”的類型不兼容
MessageBox(hWnd, buf, TEXT("TITLE"), MB_OK);
break;
}
//鍵盤按下
case WM_KEYDOWN:
MessageBox(hWnd, TEXT("KEYDOWN"), TEXT("TITLE"), MB_OK);
break;
//繪圖
case WM_PRINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
TextOut(hdc, 100, 100, TEXT("PRINT"), strlen("PRINT"));
EndPaint(hWnd, &ps);
break;
}
}
//返回值使用默認(rèn)處理方式
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
MFC
MFC(Microsoft Foundation Classes枫弟, 微軟基礎(chǔ)類庫(kù))是微軟提供的類庫(kù)(class libraries),以C++類的形式封裝的WindowsAPI鹏往,包含一個(gè)應(yīng)用程序框架淡诗,以減少應(yīng)用程序開發(fā)人員的工作量。其中類包含大量Windows句柄封裝類和Windows內(nèi)建控件和組件的封裝類伊履。
MFC把Windows SDK API函數(shù)包裝成幾百個(gè)類韩容,MFC給Windows操作系統(tǒng)提供面向?qū)ο蟮慕涌冢С挚芍赜眯蕴破佟⒆园砸约捌渌鸒PP原則群凶。MFC通過編寫類來封裝窗口、對(duì)話框等其他對(duì)象哄辣,引入關(guān)鍵的虛函數(shù)(覆蓋虛函數(shù)可改變派生類的功能)來完成请梢,MFC設(shè)計(jì)者使類庫(kù)帶來的總開銷降到了最低赠尾。
MFC快速入門
- MFC源文件后綴為
.cpp
,因?yàn)镸FC是C++編寫的毅弧。 - 編寫MFC程序需包含
#include<afxwin.h>
頭文件
$ vim MFCApp.h
// MFCApp.h: PROJECT_NAME 應(yīng)用程序的主頭文件
#pragma once
#ifndef __AFXWIN_H__
#error "在包含此文件之前包含“stdafx.h”以生成 PCH 文件"
#endif
// 主符號(hào)
#include "resource.h"
// CMFCAppApp:
// 有關(guān)此類的實(shí)現(xiàn)气嫁,請(qǐng)參閱 MFCApp.cpp
//應(yīng)用程序類CWinApp派生類(子類)
class CMFCAppApp : public CWinApp
{
public:
CMFCAppApp();
// 重寫
public:
//基類的虛函數(shù),派生類只是重寫够坐,MFC程序的入口地址寸宵。
virtual BOOL InitInstance();
// 實(shí)現(xiàn)
//聲明消息映射,必須在類聲明中咆霜。
DECLARE_MESSAGE_MAP()
};
extern CMFCAppApp theApp;
MFC消息映射
消息映射是將消息和成員函數(shù)相互關(guān)聯(lián)的表邓馒,例如框架窗口接收一個(gè)鼠標(biāo)左擊消息嘶朱,MFC將搜索該窗口的消息映射蛾坯,如果存在一個(gè)處理WM_LBUTTONDOWN
消息的處理程序,就調(diào)用OnLButtonDown
疏遏。
//聲明消息映射脉课,必須在類聲明中。
DECLARE_MESSAGE_MAP()
// 定義消息宏财异,必須在類實(shí)現(xiàn)中倘零。
BEGIN_MESSAGE_MAP(CMFCAppApp, CWinApp)
ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()
Windows 字符集
- 多字節(jié)中1個(gè)字符對(duì)應(yīng)1個(gè)字節(jié)
- 中文 1個(gè)字符對(duì)應(yīng)多個(gè)字節(jié)
- 寬字節(jié) Unicode
- 多字節(jié)轉(zhuǎn)為寬字節(jié)
L"test"
-
TEXT()
具有自適應(yīng)編碼轉(zhuǎn)碼 -
TCHER()
具有自適應(yīng)編碼轉(zhuǎn)碼
統(tǒng)計(jì)字符串長(zhǎng)度
//統(tǒng)計(jì)多字節(jié)長(zhǎng)度
int num = 0;
char * p = "test";
num = strlen(p);
//統(tǒng)計(jì)寬字節(jié)字符串
wchar_t *p = L"test";
int num = wcslen(p);
char *
與CString
之間的轉(zhuǎn)換
// char *轉(zhuǎn)CString
char * p = "test";
CString str = CString(p);
//CString轉(zhuǎn)char *
CString str = CString("test");
CStringA tmp;
tmp = str;
char * p = tmp.GetBuffer();
- MFC中后綴為
Ex
的函數(shù)都是擴(kuò)展函數(shù) - MFC中以
Afx
為前綴的都是全局函數(shù)
MFC基于對(duì)話框編程
對(duì)話框是一種特殊類型的窗口,大多數(shù)Windows程序都是通過對(duì)話框與用戶進(jìn)行交互戳寸。
模態(tài)對(duì)話框
- 創(chuàng)建對(duì)話框
資源視圖>Dialog>右鍵>插入Dialog>重命名為 IDD_EXEC - 為對(duì)話框添加類
IDD_EXEC>右擊>添加類>類命名為CDlgExec 頭文件命名為DlgExec - 為按鈕添加事件處理程序
// TODO: 在此添加控件通知處理程序代碼
void CMfcDlg::OnBnClickedLogin()
{
//彈出模態(tài)對(duì)話框呈驶,具有堵塞功能。
CDlgExec dlg;
dlg.DoModal();
}
非模態(tài)對(duì)話框
- 創(chuàng)建對(duì)話框
資源視圖>Dialog>右鍵>插入Dialog>重命名為 IDD_Show - 為對(duì)話框添加類
IDD_EXEC>右擊>添加類>類命名為CDlgShow 頭文件命名為DlgShow - 主對(duì)話框頭文件添加私有屬性
$ vim MfcDlg.h
#include "DlgShow.h"
// 類中添加私有屬性
private:
CDlgShow dlg;
- 主對(duì)話框消息處理程序初始化中添加創(chuàng)建非模態(tài)框?qū)υ捒?/li>
$ vim MfcDlg.cpp
BOOL CMfcDlg::OnInitDialog()
{
//創(chuàng)建非模態(tài)對(duì)話框
dlg.Create(IDD_SHOW);
}
- 事件處理程序中添加顯示
// 控件通知處理程序代碼
void CMfcDlg::OnBnClickedLogin()
{
//彈出非模態(tài)對(duì)話框
//CDlgShow dlg;
//dlg.Create(IDD_SHOW);//創(chuàng)建
dlg.ShowWindow(SW_SHOWNORMAL);//顯示
}
靜態(tài)文本 CStaticText
- 添加變量 以
STATIC
為結(jié)尾的ID是不可以添加變量的需修改ID - 設(shè)置內(nèi)容
SetWindowTextW()
- 獲取內(nèi)容
GetWindowTextW()
void CMfcDlg::OnBnClickedSet()
{
text.SetWindowTextW(TEXT("Account"));
btnSet.SetWindowTextW(TEXT("禁用"));
btnSet.EnableWindow(FALSE);//禁用按鈕
}
void CMfcDlg::OnBnClickedGet()
{
CString str;
text.GetWindowTextW(str);
MessageBox(str);
}
靜態(tài)圖片BMP
- 添加變量
- 初始化顯示圖片
//顯示圖片
img.ModifyStyle(0xf, SS_BITMAP | SS_CENTERIMAGE);//設(shè)置風(fēng)格為16進(jìn)制位圖并居中顯示
//獲取圖片路徑獲取bitmap句柄
#define HBMP(filepath, width, height)(HBITMAP)LoadImage(AfxGetInstanceHandle(), filepath, IMAGE_BITMAP, width, height, LR_LOADFROMFILE|LR_CREATEDIBSECTION)
//寬高按空間大小設(shè)置
CRect rect;
img.GetWindowRect(rect);
//設(shè)置bitmap
img.SetBitmap(HBMP(TEXT("./Image/plane.bmp"), rect.Width(), rect.Height()));
編輯框 EditControl
- 屬性:
mutiline
多行疫鹊、want return
換行 - 獲取設(shè)置值:
GetWindowTextW()
和SetWindowText()W
- 單行點(diǎn)擊回車會(huì)退出袖瞻,重寫
OnOK()
注釋其中代碼。對(duì)話框 - 退出當(dāng)前對(duì)話框
CDialog::OnOk()
和CDialog::OnCancel()
// 源編輯框默認(rèn)文本
editor_src.SetWindowTextW(TEXT("please input something"));
//點(diǎn)擊復(fù)制按鈕
void CMfcDlg::OnBnClickedBtnCopy()
{
CString str;
editor_src.GetWindowTextW(str);
editor_dst.SetWindowTextW(str);
}
退出的方式
void CMfcDlg::OnBnClickedExit()
{
//退出當(dāng)前對(duì)話框
CDialog::OnOK();//點(diǎn)擊確定退出對(duì)話框
//CDialog::OnCancel();//點(diǎn)擊取消推出對(duì)話框
//exit(0);//退出所有對(duì)話框
}
添加變量時(shí)添加value
拆吆,本身關(guān)聯(lián)的變量就是值聋迎。
UpdateData(TRUE);//將控件中的內(nèi)容同步到變量中
void CMfcDlg::OnBnClickedBtnSetval()
{
editval = TEXT("setval");
UpdateData(FALSE);//將變量中的值同步到控件中
}
void CMfcDlg::OnBnClickedBtnGetval()
{
UpdateData(TRUE);//將控件中的內(nèi)容同步到變量中
MessageBox(editval);
}
下拉框CComBox
-
data
屬性中添加數(shù)據(jù),逗號(hào)分隔枣耀。sort
屬性排序霉晕。 -
type
屬性為DropList
則不可編輯 - 添加元素
AddString()
- 刪除元素
DeleteString()
- 插入元素
InsertString()
- 設(shè)置默認(rèn)
SetCurSel()
- 獲取當(dāng)前索引
GetCurSel()
- 根據(jù)索引獲取元素
GetLBText(int Index, CString str)
- 控件事件
OnCbnSelChangeXXX()
//下拉框添加元素
role.AddString(TEXT("管理員"));
role.AddString(TEXT("渠道商"));
role.AddString(TEXT("代理商"));
role.AddString(TEXT("員工"));
role.AddString(TEXT("玩家"));
//設(shè)置默認(rèn)選項(xiàng)
role.SetCurSel(0);
//插入選項(xiàng)
role.InsertString(4, TEXT("會(huì)員"));
//刪除選項(xiàng)
role.DeleteString(3);
//獲取索引所對(duì)應(yīng)的值
CString str;
role.GetLBText(1, str);
//MessageBox(str);
void CMfcDlg::OnCbnSelchangeComboRole()
{
//獲取當(dāng)前索引
int index = role.GetCurSel();
//獲取值
CString str;
role.GetLBText(index, str);
MessageBox(str);
}
列表控件 CListCtrl
- 控件屬性
view
設(shè)置為報(bào)表模式Report
- 添加表頭
InsertColumn()
- 添加正文 從0開始
InsertItem(0,content)
- 添加正文其他列表
SetItemText(row, col, content)
- 設(shè)置風(fēng)格 整行選中
LVS_EX_FULLROWSELECT
網(wǎng)格顯示LVS_EX_GRIDLINES
/*列表控件*/
//設(shè)置屬性 整行選中 網(wǎng)格顯示
list.SetExtendedStyle(list.GetExtendedStyle()|LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);
//設(shè)置表頭
CString strArr[] = {TEXT("賬號(hào)"), TEXT("昵稱"), TEXT("郵箱")};
for (int i = 0; i < 3; i++) {
list.InsertColumn(i, strArr[i], LVCFMT_LEFT, 100);//參數(shù) 索引 內(nèi)容 對(duì)齊 列寬
}
list.InsertItem(0, TEXT("a12l31c09e"));
list.SetItemText(0, 1, TEXT("Alice"));
list.SetItemText(0, 2, TEXT("alice520@gmail.com"));
//循環(huán)添加
int j;
for (int i = 0; i < 10; i++) {
j = 0;
CString str;
str.Format(TEXT("alice%d"), i);
list.InsertItem(i, str);
list.SetItemText(i, ++j, str);
list.SetItemText(i, ++j, str);
}
樹形控件Tree Control
- 拖拽控件,命名ID為
IDC_TREE
- 設(shè)置私有
private
變量CTreeCtrl tree;
- 設(shè)置屬性:
Has Buttons
設(shè)置按鈕捞奕、Has Lines
設(shè)置線牺堰、Lines At Root
設(shè)置根節(jié)點(diǎn)線 - 準(zhǔn)備圖標(biāo):資源視圖>Icon>右鍵>添加資源>Icon>導(dǎo)入,圖標(biāo)采用ico文件72像素颅围。
- 初始化中設(shè)置圖標(biāo)
CMfcDlg::OnInitDialog()
//設(shè)置圖標(biāo)
//CImageList imglist;//圖片集合伟葫,必須保存.h作為成員屬性。
imglist.Create(30, 30, ILC_COLOR32, 6, 6);
//添加圖標(biāo)
HICON icons[6];
icons[0] = AfxGetApp()->LoadIconW(IDI_ICON1);
icons[1] = AfxGetApp()->LoadIconW(IDI_ICON2);
icons[2] = AfxGetApp()->LoadIconW(IDI_ICON3);
icons[3] = AfxGetApp()->LoadIconW(IDI_ICON4);
icons[4] = AfxGetApp()->LoadIconW(IDI_ICON5);
icons[5] = AfxGetApp()->LoadIconW(IDI_ICON6);
for (int i = 0; i < 6; i++) {
imglist.Add(icons[i]);
}
//設(shè)置圖標(biāo)
tree.SetImageList(&imglist, TVSIL_NORMAL);
//設(shè)置根節(jié)點(diǎn)
HTREEITEM root = tree.InsertItem(TEXT("ROOT"), 0, 1, NULL);
//設(shè)置父節(jié)點(diǎn)
HTREEITEM parent = tree.InsertItem(TEXT("PARENT"), 2, 3, root);
//設(shè)置子節(jié)點(diǎn)
HTREEITEM child1 = tree.InsertItem(TEXT("CHILD1"), 4, 5, parent);
HTREEITEM child2 = tree.InsertItem(TEXT("CHILD2"), 4, 5, parent);
//設(shè)置默認(rèn)選項(xiàng)
tree.SelectItem(child1);
- 設(shè)置事件
OnTvnSelchanged
//樹項(xiàng)目切換
void CMfcDlg::OnTvnSelchangedTree(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
*pResult = 0;
//獲取當(dāng)前選中項(xiàng)
HTREEITEM item = tree.GetSelectedItem();
CString text = tree.GetItemText(item);
MessageBox(text);
}
標(biāo)簽頁(yè)Tab Control
- 引用
TabSheet.h
和TabSheet.cpp
并添加到項(xiàng)目中
TabSheet.h
#if !defined(AFX_TABSHEET_H__42EE262D_D15F_46D5_8F26_28FD049E99F4__INCLUDED_)
#define AFX_TABSHEET_H__42EE262D_D15F_46D5_8F26_28FD049E99F4__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// TabSheet.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CTabSheet window
#define MAXPAGE 16
class CTabSheet : public CTabCtrl
{
// Construction
public:
CTabSheet();
// Attributes
public:
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CTabSheet)
//}}AFX_VIRTUAL
// Implementation
public:
int GetCurSel();
int SetCurSel(int nItem);
void Show();
void Free();
void SetRect();
BOOL AddPage(LPCTSTR title, CDialog *pDialog, UINT ID);
virtual ~CTabSheet();
// Generated message map functions
protected:
LPCTSTR m_Title[MAXPAGE];
UINT m_IDD[MAXPAGE];
CDialog* m_pPages[MAXPAGE];
int m_nNumOfPages;
int m_nCurrentPage;
//{{AFX_MSG(CTabSheet)
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_TABSHEET_H__42EE262D_D15F_46D5_8F26_28FD049E99F4__INCLUDED_)
TabSheet.cpp
// TabSheet.cpp : implementation file
//
#include "stdafx.h"
#include "TabSheet.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CTabSheet
CTabSheet::CTabSheet()
{
m_nNumOfPages = 0;
m_nCurrentPage = 0;
}
CTabSheet::~CTabSheet()
{
}
BEGIN_MESSAGE_MAP(CTabSheet, CTabCtrl)
//{{AFX_MSG_MAP(CTabSheet)
ON_WM_LBUTTONDOWN()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTabSheet message handlers
BOOL CTabSheet::AddPage(LPCTSTR title, CDialog *pDialog, UINT ID)
{
if (MAXPAGE == m_nNumOfPages)
return FALSE;
m_nNumOfPages++;
m_pPages[m_nNumOfPages - 1] = pDialog;
m_IDD[m_nNumOfPages - 1] = ID;
m_Title[m_nNumOfPages - 1] = title;
return TRUE;
}
void CTabSheet::SetRect()
{
CRect tabRect, itemRect;
int nX, nY, nXc, nYc;
GetClientRect(&tabRect);
GetItemRect(0, &itemRect);
nX = itemRect.left;
nY = itemRect.bottom + 1;
nXc = tabRect.right - itemRect.left - 2;
nYc = tabRect.bottom - nY - 2;
m_pPages[0]->SetWindowPos(&wndTop, nX, nY, nXc, nYc, SWP_SHOWWINDOW);
for (int nCount = 1; nCount < m_nNumOfPages; nCount++)
m_pPages[nCount]->SetWindowPos(&wndTop, nX, nY, nXc, nYc, SWP_HIDEWINDOW);
}
void CTabSheet::Show()
{
for (int i = 0; i < m_nNumOfPages; i++)
{
m_pPages[i]->Create(m_IDD[i], this);
InsertItem(i, m_Title[i]);
}
m_pPages[0]->ShowWindow(SW_SHOW);
for (int i = 1; i < m_nNumOfPages; i++)
m_pPages[i]->ShowWindow(SW_HIDE);
SetRect();
}
void CTabSheet::OnLButtonDown(UINT nFlags, CPoint point)
{
CTabCtrl::OnLButtonDown(nFlags, point);
if (m_nCurrentPage != GetCurFocus())
{
m_pPages[m_nCurrentPage]->ShowWindow(SW_HIDE);
m_nCurrentPage = GetCurFocus();
m_pPages[m_nCurrentPage]->ShowWindow(SW_SHOW);
// m_pPages[m_nCurrentPage]->SetFocus();
}
}
int CTabSheet::SetCurSel(int nItem)
{
if (nItem < 0 || nItem >= m_nNumOfPages)
return -1;
int ret = m_nCurrentPage;
if (m_nCurrentPage != nItem)
{
m_pPages[m_nCurrentPage]->ShowWindow(SW_HIDE);
m_nCurrentPage = nItem;
m_pPages[m_nCurrentPage]->ShowWindow(SW_SHOW);
// m_pPages[m_nCurrentPage]->SetFocus();
CTabCtrl::SetCurSel(nItem);
}
return ret;
}
int CTabSheet::GetCurSel()
{
return CTabCtrl::GetCurSel();
}
//釋放page資源
void CTabSheet::Free()
{
CTabCtrl::DeleteAllItems();
for (int i = 0; i < m_nNumOfPages; i++)
{
m_pPages[i]->DestroyWindow();
m_IDD[i] = NULL;
m_Title[i] = NULL;
}
m_nCurrentPage = 0;
m_nNumOfPages = 0;
//CTabCtrl::DestroyWindow(); //注意不要將this指針釋放了
}
- 拖入控件
TabControl
- 添加變量谷浅,設(shè)置類型為
TabSheet
- 創(chuàng)建標(biāo)簽頁(yè)扒俯,設(shè)置屬性
border
為none
奶卓,設(shè)置style
為child
- 標(biāo)簽頁(yè)添加類
- 主窗口添加標(biāo)簽
/*標(biāo)簽頁(yè)*/
tab.AddPage(TEXT("系統(tǒng)設(shè)置"), &tabcfg, IDD_TAB_CFG);
tab.AddPage(TEXT("系統(tǒng)管理"), &tabmgr, IDD_TAB_MGR);
//顯示
tab.Show();