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

news2024/11/27 22:46:00

文章目录

  • 记事本项目功能完善和开发
    • 查找界面的记忆功能 、使用F3快捷键自动向下查找功能 的开发
    • 单次替换的算法研究
  • CFileDialog 构造函数详解 应用另存为时选择编码 (三种方案)
    • vista 样式文件对话框 bVistaStyle 为TRUE时 1
      • pch.h
      • CApp NotePad.cpp 对编码的解析 以及对编码格式的转换
      • CMainDlg.h
      • CMainDlg.cpp
    • 派生类 vista 样式文件对话框 bVistaStyle 为FALSE时 2
      • CMainDlg.h
      • CMainDlg.cpp
      • CFileDialogXq.h
      • CFileDialogXq.cpp
    • 子对话框 3
      • CMainDlg.h
      • CMainDlg.cpp
      • CFileDialogXq.h
      • CFileDialogXq.cpp
      • CFileDlg.h
      • CFileDlg.cpp
  • CTabCtrl类与分页模式开发
    • CTabCtrl类简介
    • 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);
}

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/780073.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《Docker与持续集成/持续部署:构建高效交付流程,打造敏捷软件交付链》

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

【算法基础:搜索与图论】3.5 求最小生成树算法(PrimKruskal)

文章目录 最小生成树介绍朴素Prim算法算法思路⭐例题&#xff1a;858. Prim算法求最小生成树 Kruskal算法算法思路⭐例题&#xff1a;859. Kruskal算法求最小生成树 最小生成树介绍 最小生成树 有关树的定义 生成子图&#xff1a;生成子图是从原图中选取部分节点以及这些节点…

16.喝水

喝水 html部分 <h1>Goal: 2 Liters</h1> <div class"cup cupbig"><div class"remained"><span id"liters">2L</span><small>Remained</small></div><div class"percentage&quo…

欧姆龙cp1h-e串口以太网连接怎么设置欧姆龙CX系列

捷米特JM-ETH-CX串口转以太网通讯处理器是为满足日益增多的工厂设备信息化需求&#xff08;设备网络监控和生产管理&#xff09;而设计&#xff0c;用于欧姆龙 CPM、CQM、C200、C1000、C2000 等多个系列 PLC 的以太网数据采集&#xff0c; 非常方便构建生产管理系统。 捷米特J…

【字符流】案例:文件到集合(改进版)

案例&#xff1a;文件到集合&#xff08;改进版&#xff09; 1.需求&#xff1a; 把文本文件中的数据读取到集合中&#xff0c;并遍历集合。要求&#xff1a;文件中每一行数据是一个学生对象的成员变量值 ​ 举例&#xff1a;001,郝佳乐,20,西安 2.思路&#xff1a; 定义学…

Vue第六篇:电商网站图片放大镜功能

本文参考&#xff1a;https://blog.csdn.net/liushi21/article/details/127497487 效果如下&#xff1a; 功能实现分解如下&#xff1a; &#xff08;1&#xff09;商品图区域&#xff1a;主要是浏览图片&#xff0c;根据图片的url显示图片。当鼠标离开此区域时"放大镜区…

HTTP中GET请求和POST请求的区别

前言 HTTP&#xff08;超文本传输协议&#xff09;是用于在 Web 浏览器和 Web 服务器之间传输数据的协议。在 HTTP 中&#xff0c;GET 和 POST 是两种常见的请求方法。一般我们在浏览器输入一个网址访问网站都是 GET 请求&#xff1b;在 FORM 表单中&#xff0c;可以通过设置 …

Mac端简单好用的程序创建工具:VMware InstallBuilder Enterprise

VMware InstallBuilder Enterprise for Mac是一款用于为台式机和服务器软件构建跨平台安装程序的开发工具。使用InstallBuilder&#xff0c;您可以从单个项目文件和构建环境中为Linux&#xff0c;Windows&#xff0c;Mac OS X&#xff0c;Solaris和其他平台快速创建动态&#x…

Windows下mosquitto服务端和MQTT.fx客户端搭建模拟环境

第一部分 Mosquitto安装测试 一、概念梳理 1、Mosquitto是一款实现了消息推送协议MQTT 3.1的开源消息代理软件&#xff0c;提供轻量级的、支持可订阅/可发布的消息推送模式&#xff0c;是设备与设备之间的短消息通信变得简单&#xff0c;广泛应用于低功耗传感器、手机&#xff…

django跨域设置

1.安装 (venv) ***\data_analyse_web>pip install django-cors-headers 2.添加应用 :在settings.py中添加应用,放到任意位置都行 INSTALLED_APPS {# ...corsheaders,# ... } 3. 设置中间层&#xff0c;在settings.py中添加中间层&#xff0c;放到最前面 MIDDLEWARE [c…

【设计模式】23种设计模式——原型模式Prototype(原理讲解+应用场景介绍+案例介绍+Java代码实现)

原型模式 介绍 原型模式指用通过拷贝原型实例创建新的实例&#xff0c;新实例和原型实例的属性完全一致原型模式是一种创建型设计模式工作原理是通过调用原型实例的 clone()方法来完成克隆&#xff0c;原型实例需要实现Cloneable接口&#xff0c;并重写clone()方法需要为每个…

WSR-88D天气雷达工作模式、监测目标、反射率含义讲解

一、WSR-88D 简介 WSR-88D是天气监视多普勒雷达之一。自 1988 年首次建造和测试以来,它已在包括阿拉斯加和夏威夷在内的美国 160 多个地点安装和使用。WSR-88D也已安装在波多黎各和太平洋的几个岛屿。 WSR-88D雷达发射功率为750000瓦(平均灯泡只有75瓦)!这种功率使雷达产…

03. 自定义镜像 Dockerfile

目录 1、前言 2、构建镜像的方式 2.1、docker commit 2.1.1、先查看下当前的容器 2.1.2、生成该容器镜像 2.1.3、查看镜像列表 2.2、Dockerfile 2.2.1、创建Dockerfile文件 2.2.2、编写Dockerfile文件 2.2.3、构建镜像 2.2.4、使用该镜像生成容器 3、Dockerfile 3…

Docker 网络、资源控制

Docker 网络、资源控制 一、Docker 网络1、Docker 网络实现原理2、Docker 的网络模式&#xff1a;1&#xff0e;host模式2&#xff0e;container模式3&#xff0e;none模式4&#xff0e;bridge模式5&#xff0e;自定义网络 二、资源控制1&#xff0e;CPU 资源控制&#xff08;1…

用echarts绘制流程图

getEchart1() {echarts.init(document.getElementById(echart1)).dispose();var chartDom document.getElementById(echart1);this.myChart echarts.init(chartDom);var charts {nodes: [ // 节点{name: 开始, value: [0, 500],label: {borderWidth: 1, // 边框宽度borderRa…

【CMU15-445 FALL 2022】Project #1 - Buffer Pool

About 实验官网 Project #1 - Buffer Pool在线评测网站 gradescope Lab Task #1 - Extendible Hash Table 详见——【CMU15-445 FALL 2022】Project #1 - Extendable Hashing 如果链接失效&#xff0c;请查看当前平台我之前发布的文章。 Task #2 - LRU-K Replacement Polic…

flink Mysql CDC(动态加表)、postgresqlCDC 和 CDC无锁算法

flinkCDC - 功能验证记录 flink 与cdc 版本使用搭配&#xff1a;flink cdc参数说明原理分析&#xff08;DBLog&#xff09;无锁算法论文 mysql cdccdc api 动态加表flink cdc sql 性能压测flink cdc api 性能压测 PostgreSqlCDC执行更新语句&#xff0c;会出现 2 种情况 cdc si…

【数据挖掘】bytewax 与 ydata工具可实时了解您的数据

一、说明 在这篇博文中&#xff0c;我们将介绍如何将开源流式处理解决方案 bytewax 与 ydata 分析相结合并加以利用&#xff0c;以提高流式处理流的质量。 STream 处理支持在传输中和存储之前对数据进行实时分析&#xff0c;并且可以是有状态的&#xff0c;也可以是无状态的。 …

[STL]vector使用介绍

[STL]vector使用介绍 注&#xff1a;文内代码均在Visual Studio 2013下进行测试&#xff0c;不同的编译器下在扩容大小等方面可能有所不同&#xff0c;但不影响各接口函数的使用。 文章目录 [STL]vector使用介绍1. vector介绍2. 构造函数3. 迭代器相关函数begin函数和end函数的…

实现点击复制到剪切板功能

该功能使用VueUse实现 什么是 VueUse VueUse不是Vue.use&#xff0c;它是为Vue 2和3服务的一套Vue Composition API的常用工具集&#xff0c;是目前世界上Star最高的同类型库之一。它的初衷就是将一切原本并不支持响应式的JS API变得支持响应式&#xff0c;省去程序员自己写相…