MFC第十九天 记事本项目功能完善和开发、CTabCtrl类与分页模式开发

记事本项目功能完善和开发

查找界面的记忆功能 、使用F3快捷键自动向下查找功能 的开发

获取选择的文字

CString CMainDlg::GetSelText()
{
	CString str;
	m_edit.GetWindowText(str);

	int nStart, nEnd;
	m_edit.GetSel(nStart, nEnd);

	if(nEnd<=nStart)
		return CString();
	return str.Mid(nStart, nEnd - nStart);
}

向下查找

void CMainDlg::OnEditNext()
{
	if (m_sFind.IsEmpty())
		OnEditFind();
	else
	{
		CString sText;
		m_edit.GetWindowText(sText);
		if (m_sFind.GetLength() > 0)
			m_sFind = theApp.GetProfileString(_T("SETTINGS"), _T("Search"));
		CString str = m_sFind;

		if (!theApp.GetProfileInt(_T("SETTINGS"),_T("Mathcase"),0))
		{
			str.MakeLower();
			sText.MakeLower();	
		}
		int nStart, nEnd;
		m_edit.GetSel(nStart, nEnd);
		int n = sText.Find(str, nEnd);
		if (n < 0)
		{
			AfxMessageBox(_T("找不到 ") + str);
			return;
		}
		m_edit.SetSel(n, n + str.GetLength());
		m_edit.GetFocus();
	}
}

单次替换的算法研究

查找替换功能

LRESULT CMainDlg::OnFindReplace(WPARAM wParam, LPARAM lParam)
{
	if (m_pFRDlg->IsTerminating()) 
		return false;
	if (m_pFRDlg->ReplaceAll())
	{
		ReplaceAll();
	}
	if (m_pFRDlg->ReplaceCurrent())
	{
		ReplaceCurrent();
	}
	if (m_pFRDlg->FindNext())
	{
		theApp.WriteProfileString(_T("SETTINGS"), _T("SEARCH"), m_pFRDlg->GetFindString());
		theApp.WriteProfileInt(_T("SETTINGS"), _T("MatchCase"), m_pFRDlg->MatchCase());
		theApp.WriteProfileInt(_T("SETTINGS"), _T("MatchWholeWord"), m_pFRDlg->MatchWholeWord());
		theApp.WriteProfileInt(_T("SETTINGS"), _T("SearchDown"), m_pFRDlg->SearchDown());
		if (m_pFRDlg->SearchDown())
			SerachDown();
		else
			SerachUp();
	}
	return LRESULT();
}

向下

void CMainDlg::SerachDown()
{
	if (!IsWindow(m_pFRDlg->GetSafeHwnd()))
		return;

	CString sText;
	m_edit.GetWindowText(sText);
	CString str = m_pFRDlg->GetFindString();

	int nStart, nEnd;
	m_edit.GetSel(nStart, nEnd);
	int n = sText.Find(str, nEnd);
	if (n<0)
	{
		AfxMessageBox(_T("找不到 ") + str);
		return;
	}
	m_edit.SetSel(n, n + str.GetLength());
	m_edit.GetFocus();
}

向上

void CMainDlg::SerachUp()
{
	if (!IsWindow(m_pFRDlg->GetSafeHwnd()))
		return;

	CString sText;
	m_edit.GetWindowText(sText);
	CString str = m_pFRDlg->GetFindString();

	if (!m_pFRDlg->MatchCase())  //区分大小写, 设置之后只能查找小写
	{
		str.MakeLower();
		sText.MakeLower();
	}

	int nStart, nEnd;
	m_edit.GetSel(nStart, nEnd);
	str.MakeReverse();
	sText.MakeReverse();
	int nLen = sText.GetLength();
	int n = sText.Find(str, nLen-nStart);
	if (n < 0)
	{
		AfxMessageBox(_T("找不到 ") + str);
		return;
	}
	nEnd = nLen - n;
	nStart = nEnd - str.GetLength();
	m_edit.SetSel(nStart, nEnd);
	m_edit.GetFocus();
}

不区分大小写的

int CMainDlg::FindNoCase(const CString& str, TCHAR s1, int i)
{
	TCHAR s2 = s1 ^ 32;
	int nLen = str.GetLength();
	while (++i < nLen)
	{
		TCHAR s = str[i];
		if (s == s1 || s == s2)
			return i;
	}
	return -1;
}

替换当前选中

void CMainDlg::ReplaceCurrent()
{
	CString sText, sOld, sNew;
	sOld = m_pFRDlg->GetFindString();
	sNew = m_pFRDlg->GetReplaceString();
	m_edit.GetWindowText(sText);
	BOOL bMatchCase = m_pFRDlg->MatchCase();
	int nStart, nEnd;
	m_edit.GetSel(nStart, nEnd);

	CString str = sText.Mid(nStart, nEnd - nStart);
	if (str.CompareNoCase(sOld))
		nStart += nEnd;
	else
	{
		m_edit.ReplaceSel(sNew);
		m_edit.GetWindowText(sText);

		nStart += sNew.GetLength();
	}
	if (!m_pFRDlg->MatchCase())
	{
		sText.MakeLower();
		sOld.MakeLower();
	}
	nStart = sText.Find(sOld, nStart);//因为替换过了
	sOld = m_pFRDlg->GetFindString();
	if (nStart < 0)
	{
		AfxMessageBox(_T("没有找到 “") + sOld + _T("”"));
	}
	else
		m_edit.SetSel(nStart, nStart + sOld.GetLength());
}	

替换全部

void CMainDlg::ReplaceAll()
{
	CString sText, sOld, sNew;
	sOld = m_pFRDlg->GetFindString();
	sNew = m_pFRDlg->GetReplaceString();
	m_edit.GetWindowText(sText);
	BOOL bMathCase = m_pFRDlg->MatchCase(); //确定用户是否希望完全匹配搜索字符串的大小写 成功返回非零
	int nStart, nEnd;
	m_edit.GetSel(nStart, nEnd);
	if (bMathCase)
	{
		sText.Replace(sOld, sNew);
	}
	else
	{
		ReplaceNoCase(sText, sOld, sNew);
	}
	m_edit.SetWindowText(sText);
	m_edit.SetSel(nStart, nEnd);
}

打开查找编辑框需要加载的

void CMainDlg::OnEditFind()
{
	if (IsWindow(m_pFRDlg->GetSafeHwnd()))
		m_pFRDlg->DestroyWindow();
	m_pFRDlg = new CFindReplaceDialog;
	CString str = GetSelText();
	if (str.IsEmpty())
		str = theApp.GetProfileString(_T("SETTINGS"), _T("SEARCH"));
	else
		theApp.WriteProfileString(_T("SETTINGS"), _T("SEARCH"),str);
	DWORD dw = 0;
	if (theApp.GetProfileInt(_T("SETTINGS"), _T("MatchCase"), 0))
		dw |= FR_MATCHCASE;
	if (theApp.GetProfileInt(_T("SETTINGS"), _T("MatchWholeWord"), 0))
		dw |= FR_WHOLEWORD;
	if (theApp.GetProfileInt(_T("SETTINGS"), _T("SearchDown"), 0))
		dw |= FR_DOWN;
	if (str.GetLength() > 0)
			m_sFind = str;
	m_pFRDlg->Create(TRUE,str,NULL,dw);

}

CFileDialog 构造函数详解 应用另存为时选择编码 (三种方案)

CFileDialog 构造函数详解

explicit CFileDialog(
   BOOL bOpenFileDialog,   //指定是否为打开文件对话框
 	//该参数为TRUE,创建一个打开文件对话框;如果该参数为 FALSE,则创建一个保存文件对话框
   LPCTSTR lpszDefExt = NULL, //指定默认文件扩展名。如果用户没有指定文件扩展名,则自动添加该扩展名
   LPCTSTR lpszFileName = NULL, //指定默认文件名。如果用户没有指定文件名,则将显示此默认文件名。
   DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
   //用于指定文件对话框的标志。可以使用位操作符 | 来组合多个标志
   
   LPCTSTR lpszFilter = NULL, //指定文件过滤器。文件过滤器用于限制用户可以选择的文件类型
   CWnd* pParentWnd = NULL,//指定文件对话框的父窗口。如果为 NULL,文件对话框将没有父窗口。
   DWORD dwSize = 0, //指定文件对话框的大小。如果为 0,则使用默认大小
   BOOL bVistaStyle = TRUE
   //用于指定是否在 Windows Vista 或更高版本的操作系统上使用 Vista 风格的文件对话框。如果该参数为 TRUE,则文件对话框将使用 Vista 风格;如果该参数为 FALSE,则文件对话框将使用旧版样式
);

vista 样式文件对话框 bVistaStyle 为TRUE时 1

pch.h

enum EType
{
	T_ANSI = 0,
	T_U16LE,
	T_U16BE,
	T_U8,
	T_U8BOM,
};

CApp NotePad.cpp 对编码的解析 以及对编码格式的转换

EType CApp::ParseText(CEdit& edit, LPSTR p)
{
	wchar_t* q = nullptr;
	switch (*(WORD*)p)
	{
	case 0xFFFE:
		theApp.ConvertBig(p);
		edit.SetWindowText((LPCWSTR)(p + 2));
		return T_U16BE;
	case 0xFEFF:
		edit.SetWindowText((LPCWSTR)(p + 2));
		delete[]q;
		return T_U16LE;
	case 0xBBEF:
		if (p[2] == (char)0xBF)
		{
			q = theApp.UTF8ToUnicode(p + 3);
			edit.SetWindowText(q);
			delete[]q;
			return T_U8BOM;
		}
	}
	if (theApp.CheckUtf8(p))
	{
		q = theApp.UTF8ToUnicode(p);
		edit.SetWindowText(q);
		delete[]q;
		return T_U8;
	}
	q = ANSIToUnicode(p);
	edit.SetWindowText(q);//ANSI
	delete[]q;
	return T_ANSI;
	
}
bool CApp::CheckUtf8(LPCSTR p){
	auto q = p;
	while (*p){
		BYTE c = *p;	int n = 0;
		while ((c & 0x80) == 0x80)
			++n, c <<= 1;
		if (n == 1 || n > 4)
			return false;
		++p;
		while (--n > 0)	{
			c = *p++;
			if (c >> 6 != 2)//00000010
				return false;	}}
	return true;	
}
void CApp::ConvertBig(LPSTR p)
{
	while (*(WORD*)p)
	{
		*p = *p ^ p[1];
		p[1] = *p ^ p[1];
		*p = *p ^ p[1];
		p += 2;
	}
}
wchar_t* CApp::UTF8ToUnicode(const char* str)
{
	int n = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
	auto p = new wchar_t[n + 1];
	n = MultiByteToWideChar(CP_UTF8, 0, str, -1, p, n);
	p[n] = 0;
	return p;
}
wchar_t* CApp::ANSIToUnicode(const char* str)
{
	int n = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
	auto p = new wchar_t[n + 1];
	MultiByteToWideChar(CP_ACP, 0, str, -1, p, n);
	return p;
}
char* CApp::UnicodeToANSI(const wchar_t* str)
{
	int n = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0,NULL,NULL);
	auto p = new char[n + 1];
	n= WideCharToMultiByte(CP_ACP, 0, str, -1, p, n,NULL,NULL);
	p[n] = 0;
	return p;
}

char* CApp::UnicodeToUTF8(const wchar_t* str)
{
	int n = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
	auto p = new char[n + 1];
	n = WideCharToMultiByte(CP_UTF8, 0, str, -1, p, n, NULL, NULL);
	return p;
}

CMainDlg.h

LPCTSTR m_szFilter = _T("文本文件 (*.txt)|*.txt|配置文件 (*.ini;*.inf)|*.ini;*.inf|")
		_T("代码文件(*.h;*.c;*.cpp)|*.h;*.c;*.cpp|所有文件(*.*)|*.*||");
CString m_sFile; //isEmpty代表没有关联(无标题)
EType m_eType{ T_U8 };

CMainDlg.cpp

void CMainDlg::OnFileSaveAs()
{
	enum { IDC_COMBO = 888 };
	CFileDialog dlg(FALSE,_T("txt"), NULL,OFN_OVERWRITEPROMPT,m_szFilter);
	dlg.AddComboBox(IDC_COMBO);
	dlg.AddControlItem(IDC_COMBO, 0, _T("ANSI"));
	dlg.AddControlItem(IDC_COMBO, 1, _T("Utf-16 LE"));
	dlg.AddControlItem(IDC_COMBO, 2, _T("Utf-16 BE"));
	dlg.AddControlItem(IDC_COMBO, 3, _T("Utf-8"));
	dlg.AddControlItem(IDC_COMBO, 4, _T("带Bom头的Utf-8"));
	dlg.SetSelectedControlItem(IDC_COMBO, m_eType);
	if (IDCANCEL == dlg.DoModal())
		return;
	dlg.GetSelectedControlItem(IDC_COMBO, (DWORD&)m_eType);
	m_sFile =dlg.GetPathName();

	OnFileSave();
}

派生类 vista 样式文件对话框 bVistaStyle 为FALSE时 2

CMainDlg.h

LPCTSTR m_szFilter = _T("文本文件 (*.txt)|*.txt|配置文件 (*.ini;*.inf)|*.ini;*.inf|")
		_T("代码文件(*.h;*.c;*.cpp)|*.h;*.c;*.cpp|所有文件(*.*)|*.*||");
CString m_sFile; //isEmpty代表没有关联(无标题)

CMainDlg.cpp

void CMainDlg::OnFileSaveAs()
{
	enum { IDC_COMBO = 888 };
	CFileDialogXq dlg(FALSE,_T("txt"), NULL,OFN_OVERWRITEPROMPT,m_szFilter);
 
	if (IDCANCEL == dlg.DoModal())
		return;
	m_sFile =dlg.GetPathName();
	OnFileSave();
}

CFileDialogXq.h

class CFileDialogXq : public CFileDialog{
	DECLARE_DYNAMIC(CFileDialogXq)
		CComboBox m_combo;	//派生类 	
		//CFileDlg m_dlg;
public:
	CFileDialogXq(BOOL bOpenFileDialog, // 对于 FileOpen 为 TRUE,对于 FileSaveAs 为 FALSE
		LPCTSTR lpszDefExt = nullptr,	LPCTSTR lpszFileName = nullptr,
		DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
		LPCTSTR lpszFilter = nullptr,	CWnd* pParentWnd = nullptr);
	virtual ~CFileDialogXq();
protected:
	DECLARE_MESSAGE_MAP()
public:	
	virtual BOOL OnInitDialog();
};

CFileDialogXq.cpp

#include "pch.h"
#include "NotePad.h"
#include "CFileDialogXq.h"

// CFileDialogXq
IMPLEMENT_DYNAMIC(CFileDialogXq, CFileDialog)

CFileDialogXq::CFileDialogXq(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName,
		DWORD dwFlags, LPCTSTR lpszFilter, CWnd* pParentWnd) :
		CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName, 
		dwFlags, lpszFilter, pParentWnd, 0, FALSE)  构造函数的一个参数
{

}
CWnd* FindDlgItem(CWnd* p, int nID)  //遍历
{
	p = p->GetWindow(GW_HWNDFIRST);// 兄弟的第一个
	while (p)
	{
		CString str;
		p->GetWindowText(str);
		int n = p->GetDlgCtrlID();
		if (n == nID)
			return p; //查找到要找到控件
		p = p->GetWindow(GW_HWNDNEXT);
	}
	return nullptr;
}
BOOL CFileDialogXq::OnInitDialog(){
CWnd* pStatic = FindDlgItem(this, 0x441);
	if (!IsWindow(pStatic->GetSafeHwnd()))
		return FALSE;
	CRect rect;
	pStatic->GetWindowRect(rect);

	auto p = GetParent();
	p->ScreenToClient(rect);
	rect.OffsetRect(0, rect.Height());
	m_combo.Create(WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST, rect, p, 990);
	m_combo.AddString(_T("ANSI"));
	m_combo.AddString(_T("UTF16 LE"));
	m_combo.AddString(_T("UTF16 BE"));
	m_combo.AddString(_T("UTF8"));
	m_combo.AddString(_T("UTF8 BOM"));
	m_combo.SetFont(p->GetFont());
	m_combo.SetCurSel(0);
}

子对话框 3

CMainDlg.h

LPCTSTR m_szFilter = _T("文本文件 (*.txt)|*.txt|配置文件 (*.ini;*.inf)|*.ini;*.inf|")
		_T("代码文件(*.h;*.c;*.cpp)|*.h;*.c;*.cpp|所有文件(*.*)|*.*||");
CString m_sFile; //isEmpty代表没有关联(无标题)

CMainDlg.cpp

void CMainDlg::OnFileSaveAs()
{
	enum { IDC_COMBO = 888 };
	CFileDialogXq dlg(FALSE,_T("txt"), NULL,OFN_OVERWRITEPROMPT,m_szFilter);
 
	if (IDCANCEL == dlg.DoModal())
		return;
	m_sFile =dlg.GetPathName();
	OnFileSave();
}

CFileDialogXq.h

#include "CFileDlg.h"
class CFileDialogXq : public CFileDialog{
	DECLARE_DYNAMIC(CFileDialogXq)
		//派生类 	CComboBox m_combo;	
		CFileDlg m_dlg;
public:
	CFileDialogXq(BOOL bOpenFileDialog, // 对于 FileOpen 为 TRUE,对于 FileSaveAs 为 FALSE
		LPCTSTR lpszDefExt = nullptr,	LPCTSTR lpszFileName = nullptr,
		DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
		LPCTSTR lpszFilter = nullptr,	CWnd* pParentWnd = nullptr);
	virtual ~CFileDialogXq();
	
public:	
	virtual BOOL OnInitDialog();
};

CFileDialogXq.cpp

#include "pch.h"
#include "NotePad.h"
#include "CFileDialogXq.h"

// CFileDialogXq
IMPLEMENT_DYNAMIC(CFileDialogXq, CFileDialog)

CFileDialogXq::CFileDialogXq(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName,
		DWORD dwFlags, LPCTSTR lpszFilter, CWnd* pParentWnd) :
		CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName, 
		dwFlags, lpszFilter, pParentWnd, 0, FALSE)  构造函数的一个参数
{

}
CWnd* FindDlgItem(CWnd* p, int nID)  //遍历
{
	p = p->GetWindow(GW_HWNDFIRST);// 兄弟的第一个
	while (p)
	{
		CString str;
		p->GetWindowText(str);
		int n = p->GetDlgCtrlID();
		if (n == nID)
			return p; //查找到要找到控件
		p = p->GetWindow(GW_HWNDNEXT);
	}
	return nullptr;
}
BOOL CFileDialogXq::OnInitDialog(){
CFileDialog::OnInitDialog();
	CWnd* pStatic = FindDlgItem(this, 0x441);
	if (!IsWindow(pStatic->GetSafeHwnd()))
		return FALSE;
	CRect rect,rc;
	pStatic->GetWindowRect(rect);
	
	auto p = GetParent();
	p->ScreenToClient(rect);
	p->GetClientRect(rc);
	rc.left = rect.left;
	rc.top = rect.bottom + 8;
	rc.bottom += 32;
	m_dlg.Create(IDD_FILE_DLG, p);
	m_dlg.MoveWindow(rc);
	m_dlg.ShowWindow(SW_SHOW);
	GetWindowRect(rect);
	rect.bottom += 32;
	SetWindowPos(NULL, rect.left, rect.top, rect.Width(), rect.Height(), SWP_NOZORDER);

	rect.OffsetRect(0, rect.Height());

	return TRUE;  // return TRUE unless you set the focus to a control
	// 异常: OCX 属性页应返回 FALSE
}

CFileDlg.h

#include "afxdialogex.h"
class CFileDlg : public CDialogEx{
	DECLARE_DYNAMIC(CFileDlg)
public:
	CFileDlg(CWnd* pParent = nullptr);   // 标准构造函数
	virtual ~CFileDlg();

#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_FILE_DLG };// 对话框数据
#endif
public:
	CComboBox m_combo;
	virtual BOOL OnInitDialog();
	afx_msg void OnSelchangeCode();
};

CFileDlg.cpp

CFileDlg::CFileDlg(CWnd* pParent /*=nullptr*/): CDialogEx(IDD_FILE_DLG, pParent)
{

}
void CFileDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_CODE, m_combo);
}	
void CFileDlg::OnSelchangeCode()
{
	m_combo.GetCurSel();
}
BOOL CFileDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();
	m_combo.AddString(_T("ANSI"));
	m_combo.AddString(_T("UTF16 LE"));
	m_combo.AddString(_T("UTF16 BE"));
	m_combo.AddString(_T("UTF8"));
	m_combo.AddString(_T("UTF8 BOM"));
	m_combo.SetFont(GetFont());
	m_combo.SetCurSel(0);
	return TRUE;  // return TRUE unless you set the focus to a control
	// 异常: OCX 属性页应返回 FALSE
}

在这里插入图片描述

CTabCtrl类与分页模式开发

CTabCtrl类简介

CTabCtrl 用于创建和管理标签控件(Tab Control),也称为选项卡控件。

class CTabCtrl : public CWnd
{
public:
	CTabCtrl();
	// Generic creator
	virtual BOOL Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID);
	// Generic creator allowing extended style bits
virtual BOOL CreateEx(DWORD dwExStyle,DWORD dwStyle,const RECT& rect,CWnd*pParentWnd,UINT nID);

// Attributes
	CImageList* GetImageList() const; //获取图像列表。
	CImageList* SetImageList(_In_ CImageList* pImageList);//设置图像列表
	// Retrieves the number of tabs in the tab control.
	int GetItemCount() const;
	
	// Retrieves information about the specified tab in the tab control.
	BOOL GetItem(_In_ int nItem, _Out_ TCITEM* pTabCtrlItem) const;
	// Sets some or all attributes of the specified tab in the tab control.
	BOOL SetItem(_In_ int nItem, _In_ TCITEM* pTabCtrlItem);

	// Sets the number of bytes per tab reserved for application-defined data in the tab 
	BOOL GetItemRect(_In_ int nItem, _Out_ LPRECT lpRect) const;
	
	// Determines the currently selected tab in the tab control.
	int GetCurSel() const; 获取当前选中

	// Selects the specified tab in the tab control.
	int SetCurSel(_In_ int nItem); 设置当前选中

	// Sets the focus to the specified tab in the tab control.
	void SetCurFocus(_In_ int nItem);

	// Sets the width and height of tabs in a fixed-width or owner-drawn tab control.
	CSize SetItemSize(_In_ CSize size);

	// Sets the amount of space (padding) around each tab's icon and label in the tab control.
	void SetPadding(_In_ CSize size);
	
	// Retrieves the current number of rows of tabs in the tab control.
	int GetRowCount() const;

	// Retrieves the ToolTip control associated with the tab control.
	CToolTipCtrl* GetToolTips() const;

	// Assigns a ToolTip control to the tab control.
	void SetToolTips(_In_ CToolTipCtrl* pWndTip);

	// Returns the index of the tab that has the focus in a tab control.
	int GetCurFocus() const;

	// Sets the minimum width of tabs in the tab control.
	int SetMinTabWidth(_In_ int cx);

	// Retrieves the extended styles that are currently in use for the tab control.
	DWORD GetExtendedStyle() const;

	// Sets the extended styles that the tab control will use.
	DWORD SetExtendedStyle(_In_ DWORD dwNewStyle, _In_ DWORD dwExMask = 0);

	// Retrieves state of a tab in the tab control.
	DWORD GetItemState(_In_ int nItem, _In_ DWORD dwMask) const;

	// Sets state for a tab in the tab control.
	BOOL SetItemState(_In_ int nItem, _In_ DWORD dwMask, _In_ DWORD dwState);

// Operations
	// Inserts a new tab in the tab control.
	LONG InsertItem(_In_ int nItem, _In_ TCITEM* pTabCtrlItem);
	LONG InsertItem(_In_ int nItem, _In_z_ LPCTSTR lpszItem);
	LONG InsertItem(_In_ int nItem, _In_z_ LPCTSTR lpszItem, _In_ int nImage);
	LONG InsertItem(_In_ UINT nMask, _In_ int nItem, _In_z_ LPCTSTR lpszItem,
		_In_ int nImage, _In_ LPARAM lParam);
	LONG InsertItem(_In_ UINT nMask, _In_ int nItem, _In_z_ LPCTSTR lpszItem,
		_In_ int nImage, _In_ LPARAM lParam, _In_ DWORD dwState, _In_ DWORD dwStateMask);

	// Removes a tab from the tab control.
	BOOL DeleteItem(_In_ int nItem);
	// Removes all tabs from the tab control.
	BOOL DeleteAllItems();

	// Calculates the tab control's display area given a window rectangle.
	void AdjustRect(_In_ BOOL bLarger, _Inout_ LPRECT lpRect);
	// Removes an image from the tab control's image list.
	void RemoveImage(_In_ int nImage);
	// Determines which tab, if any, is at a specified screen position.
	int HitTest(_In_ TCHITTESTINFO* pHitTestInfo) const;
	// Resets tabs in the tab control, clearing any that were in the pressed state.
	void DeselectAll(_In_ BOOL fExcludeFocus)
	// Sets the highlight state of a tab in the tab control.
	BOOL HighlightItem(_In_ int idItem, _In_ BOOL fHighlight = TRUE);

// Implementation
public:
	virtual ~CTabCtrl();
protected:
	virtual BOOL OnChildNotify(UINT, WPARAM, LPARAM, LRESULT*);
	afx_msg void OnDestroy();
	DECLARE_MESSAGE_MAP()
};

CTabCtrl的风格

#define TCS_SCROLLOPPOSITE      0x0001   // assumes multiline tab
#define TCS_BOTTOM              0x0002 底部
#define TCS_RIGHT               0x0002
#define TCS_MULTISELECT         0x0004  多选// allow multi-select in button mode
#define TCS_FLATBUTTONS         0x0008
#define TCS_FORCEICONLEFT       0x0010
#define TCS_FORCELABELLEFT      0x0020
#define TCS_HOTTRACK            0x0040 追踪 
#define TCS_VERTICAL            0x0080
#define TCS_TABS                0x0000
#define TCS_BUTTONS             0x0100 按钮风格
#define TCS_SINGLELINE          0x0000
#define TCS_MULTILINE           0x0200 多行
#define TCS_RIGHTJUSTIFY        0x0000
#define TCS_FIXEDWIDTH          0x0400
#define TCS_RAGGEDRIGHT         0x0800
#define TCS_FOCUSONBUTTONDOWN   0x1000
#define TCS_OWNERDRAWFIXED      0x2000
#define TCS_TOOLTIPS            0x4000			
#define TCS_FOCUSNEVER          0x8000

分页模式开发

在这里插入图片描述
MainDlg.h: 头文件

#pragma once
#include "CPage1.h"
#include "CPage2.h"
#include "CPage3.h"
class CMainDlg : public CDialogEx
{
// 构造
	CPage1 m_p1;
	CPage2 m_p2;
	CPage3 m_p3;
public:
	CMainDlg(CWnd* pParent = nullptr);	// 标准构造函数
// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_PAGING_DIALOG };
#endif
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持

// 实现
protected:
	HICON m_hIcon;
	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	CTabCtrl m_tab;
	afx_msg void OnSelchangeTab(NMHDR* pNMHDR, LRESULT* pResult);
};

MainDlg.cpp: 实现文件
创建标签,将三个分页创建在这里面进行显示

BOOL CMainDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();
	
	m_tab.InsertItem(0, _T("基础信息"));
	m_tab.InsertItem(1, _T("联系信息"));
	m_tab.InsertItem(2, _T("其他信息"));
	
	m_p1.Create(IDD_PAGE1, &m_tab);//把三个分页创建在这里面 父子关系 Create 一个对象只能创建一次
	m_p2.Create(IDD_PAGE2, &m_tab);	
	m_p3.Create(IDD_PAGE3, &m_tab);
	
	m_p1.ShowWindow(SW_SHOW);	
	m_p2.ShowWindow(SW_SHOW);	
	m_p3.ShowWindow(SW_SHOW);
	
	CRect rect, rc;
	m_tab.GetClientRect(rect); //将分页窗口的位置向下平移了 要不然回覆盖掉原窗口
	m_tab.GetItemRect(0, rc);	
	rect.top = rc.bottom;
	m_p1.MoveWindow(rect);		
	m_p2.MoveWindow(rect);		
	m_p3.MoveWindow(rect);
	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

当选择不同的标签时对不同的窗口进行隐藏或者显示

void CMainDlg::OnSelchangeTab(NMHDR* pNMHDR, LRESULT* pResult)
{
	*pResult = 0;
	int nIndex = m_tab.GetCurSel();
	int nCount = m_tab.GetItemCount();
	CWnd* ps[] = { &m_p1,&m_p2,&m_p3 };
	int i = -1;
	while (++i<nCount)
	{
		if (nIndex == i) 
			ps[i]->ShowWindow(SW_SHOW);
		else
			ps[i]->ShowWindow(SW_HIDE);

	}
}

实际效果:
在这里插入图片描述

演示向导模式的多页窗口开发

MainDlg.h: 头文件 定义相关的变量和函数

#pragma once
#include "CPage1.h"
#include "CPage2.h"
#include "CPage3.h"
class CMainDlg : public CDialogEx
{
// 构造
	CPage1 m_p1;
	CPage2 m_p2;
	CPage3 m_p3;
	int m_nIndex{};
	void ChangePage();
public:
	CMainDlg(CWnd* pParent = nullptr);	// 标准构造函数

// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_PAGING_DIALOG };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持

// 实现
protected:
	HICON m_hIcon;
	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	CTabCtrl m_tab;
//	afx_msg void OnSelchangeTab(NMHDR* pNMHDR, LRESULT* pResult);
	afx_msg void OnBnClickedBack();
	afx_msg void OnBnClickedNext();
	afx_msg void OnBnClickedFinish();
};

MainDlg.cpp: 实现文件

void CMainDlg::ChangePage()
{
	CWnd* ps[] = { &m_p1,&m_p2,&m_p3 };
	int i = -1;
	while (++i < _countof(ps))
		ps[i]->ShowWindow(i == m_nIndex ? SW_SHOW : SW_HIDE);
	GetDlgItem(IDC_BACK)->EnableWindow(m_nIndex != 0);  
	GetDlgItem(IDC_NEXT)->EnableWindow(m_nIndex != _countof(ps)-1);
}
BOOL CMainDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	m_p1.Create(IDD_PAGE1, this);//把三个分页创建在这里面 父子关系 Create 一个对象只能创建一次
	m_p2.Create(IDD_PAGE2, this);
	m_p3.Create(IDD_PAGE3, this);
	ChangePage();
	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}
void CMainDlg::OnBnClickedBack() //上一步
{
	if (m_nIndex >0)
		--m_nIndex;
	ChangePage();
}

void CMainDlg::OnBnClickedNext()//下一步
{
	if (m_nIndex<3)
		++m_nIndex;
	ChangePage();
}

void CMainDlg::OnBnClickedFinish() //完成
{
	EndDialog(IDOK);
}

实际效果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jcrry

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值