• MFC_系统对话框(CFileDialog、字符编码转化ANSI-UTF8-Unicode、Window记事本demo练习)


    1. 系统文件对话框(CFileDialog

    CFileDialog类的构造函数如下:

    CFileDialog( BOOL bOpenFileDialog, 
    			LPCTSTR lpszDefExt = NULL, LPCTSTR lpszFileName = NULL, DWORD dwFlags = OFN_HIDEREADONLY |
    			OFN_OVERWRITEPROMPT, LPCTSTR lpszFilter = NULL, CWnd* pParentWnd = NULL 
    );
    
    • 1
    • 2
    • 3
    • 4

    其中处理第一个以外都是默认参数。
    第一个参数如果是TRUE就是系统打开对话框,带FALSE就是系统另存为对话框。

    这两个对话框属于模态对话框.

    系统打开对话框如下:

    void CSystemWinDlg::OnBnClickedBntChoice()
    {
    	// TODO: 在此添加控件通知处理程序代码
    	CFileDialog dlg(TRUE);
    	dlg.DoModal();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述
    系统另存为对话框如下:

    void CSystemWinDlg::OnBnClickedBntChoice()
    {
    	// TODO: 在此添加控件通知处理程序代码
    	CFileDialog dlg(FALSE);
    	dlg.DoModal();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述
    构造函数中:

    1. 第二个参数代表对话框默认打开的文件.
    2. 第三个参数代表默认文件名
    3. 第四个参数dwFlags代表了系统对话框的属性,eg(可以选择多个文件,文件必须存在等等)
    4. lpszFilter:是过滤器,代表对话框可以过滤掉一些文件。这个参数类型是字符串。
      这个字符串格式如下:文本|过滤类型(多个过滤类型用分号隔开)|文本|过滤类型||(||代表结束)
      eg:
    void CSystemWinDlg::OnBnClickedBntChoice()
    {
    	// TODO: 在此添加控件通知处理程序代码
    	CFileDialog dlg(FALSE, L"txt", L"Test", OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT
    		, L"文本文件(*.txt)|*.txt|音乐文件(*.mp3、*.wav)|(*.mp3;*.wav)|所有文件(*.*)|*.*||");
    	dlg.DoModal();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述


    成员函数:

    1. GetFileName:获取选择的文件名字
    2. GetPathName:获取选择文件的路径
    3. GetFileExt:获取文件拓展名
    4. GetFileTitle:获取文件名
    5. GetStartPosition:返回POSITION类型,返回文件首位置。适合用在系统对话框选择可以多选文件时。
    6. GetNextPathName:获得POSITION位置的文件名,同时会让POSITION自动+1。(类似迭代器)
    void CSystemWinDlg::OnBnClickedBntChoice()
    {
    	// TODO: 在此添加控件通知处理程序代码
    	CFileDialog dlg(TRUE, L"txt", L"Test", OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT| OFN_ALLOWMULTISELECT
    		, L"文本文件(*.txt)|*.txt|音乐文件(*.mp3、*.wav)|(*.mp3;*.wav)|所有文件(*.*)|*.*||");
    	dlg.DoModal();
    
    	POSITION pos = dlg.GetStartPosition();
    	while (pos) {
    		CString str = dlg.GetNextPathName(pos);
    		MessageBox(str);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2. 字符编码

    • 多字节编码:为了扩展编码可以表示的字符,引入了双字节字符集。如果第一个字节为0x81->0x9F之间 或 0xE0->0xFC之间需要检测下一个字节,拼接起来才能确定这个文字。

    • Unicode编码:在1988年创立。主要分为UTF-8、UTF-16、UTF-32

    1. UTF-8:有一些字符编码为一个字节,有些编码为二个字节,有些编码为三个字节
    2. UTF-16:将所有的字符编码为两个字节
    3. UTF-32:将所有字符编码为四个字节

    Unicode编码需要在字符串、字符前加L。代表宽字符类型wchar_t,Window默认按照UTF-16进行编码(Uncode)。每个宽字符两个字节。

    在MFC中
    CHAR=>char
    WCHAR=>wchar_t
    TCHAR:如果定义了Unicode编码TCHAR=>wchar_t
    如果没有定义Unicode编码这个工程是ANSI工程(多字节编码),TCHAR=>char
    在这里插入图片描述

    通用宏TEXT、_T

    1. TEXT在Unicode编码中:
      TEXT <=> __TEXT <=> L##quote

    2. TEXT在ANSI工程中:
      TEXT <=> __TEXT <=> quote

    所以采用TEXT宏可以自动适配工程使用的编码集
    在这里插入图片描述

    同样_T这个宏功能与TEXT宏作用相同。

    C语言对应宽字符函数对应:

    ANSI: strlen、strcpy、strcmp、strcat
    Unicode:wcslen、wcscpy、wcscmp、wcscat(宽字符)

    字符集转化

    字符集转化主要使用两个函数:WideCharToMultiByte和MultiByteToWideChar

    字符集转化大致分为如下部分,Unicode编码就是UTF-16编码

    1. ANSI <=> Unicode
    2. ANSI <=> UTF-8
    3. Unicode <=> UTF-8

    ANSI转化Unicode核心代码:

    #pragma once
    
    #include"framework.h"
    
    class ChangeCharSet{
    private:
    	wchar_t* w_charbuff;
    	char* charbuff;
    public:
    	ChangeCharSet()
    		:w_charbuff(nullptr), charbuff(nullptr)
    	{}
    	~ChangeCharSet() {
    		if (w_charbuff != nullptr) {
    			delete[] w_charbuff;
    			w_charbuff = nullptr;
    		}
    		if (charbuff != nullptr) {
    			delete[] charbuff;
    			charbuff = nullptr;
    		}
    	}
    
    	//ANSI=>Unicode
    	wchar_t* AnsiToUnicode(const char* str) {
    		//-1会自动推导字符串长度
    		if (w_charbuff != nullptr) {
    			delete[] w_charbuff;
    			w_charbuff = nullptr;
    		}
    		DWORD dsize = ::MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
    		w_charbuff = new wchar_t[dsize];
    		::MultiByteToWideChar(CP_ACP, 0, str, -1, w_charbuff, dsize);
    		return w_charbuff;
    	}
    
    	//Uncode=>ANSI
    	char* UnicodeToAnsi(const wchar_t* w_str) {
    		if (charbuff != nullptr) {
    			delete[] charbuff;
    			charbuff = nullptr;
    		}
    		DWORD dsize = ::WideCharToMultiByte(CP_ACP, 0, w_str, -1, NULL, 0, NULL, NULL);
    		charbuff = new char[dsize];
    		::WideCharToMultiByte(CP_ACP, 0, w_str, -1, charbuff, dsize, NULL, NULL);
    		return charbuff;
    	}
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    Unicode转化为UTF-8:

    class ChangeCharSet{
    private:
    	wchar_t* w_charbuff;
    	char* charbuff;
    public:
    	ChangeCharSet()
    		:w_charbuff(nullptr), charbuff(nullptr)
    	{}
    	~ChangeCharSet() {
    		if (w_charbuff != nullptr) {
    			delete[] w_charbuff;
    			w_charbuff = nullptr;
    		}
    		if (charbuff != nullptr) {
    			delete[] charbuff;
    			charbuff = nullptr;
    		}
    	}
    
    	//Unicode=>UTF-8
    	char* UnicodeToUTF_8(const wchar_t* w_str) {
    		if (charbuff != nullptr) {
    			delete[] charbuff;
    			charbuff = nullptr;
    		}
    		DWORD dsize = ::WideCharToMultiByte(CP_UTF8, 0, w_charbuff, -1, NULL, 0, NULL, NULL);
    		charbuff = new char[dsize];
    		::WideCharToMultiByte(CP_UTF8, 0, w_charbuff, -1, charbuff, dsize, NULL, NULL);
    		return charbuff;
    	}
    
    	//UTF-8=>Unicode
    	wchar_t* UTF_8ToUnicode(const char* str) {
    		if (w_charbuff != nullptr) {
    			delete[] w_charbuff;
    			w_charbuff = nullptr;
    		}
    		DWORD dsize = ::MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
    		w_charbuff = new wchar_t[dsize];
    		::MultiByteToWideChar(CP_UTF8, 0, str, -1, w_charbuff, dsize);
    		return w_charbuff;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    ANSI转化为UTF-8:

    ANSI不能直接转化为UTF-8、ANSI需要先转化为Unicode,再由Unicode转化为UTF-8。
    可以直接复用上面的成员函数。

    class ChangeCharSet{
    private:
    	wchar_t* w_charbuff;
    	char* charbuff;
    public:
    	ChangeCharSet()
    		:w_charbuff(nullptr), charbuff(nullptr)
    	{}
    	~ChangeCharSet() {
    		if (w_charbuff != nullptr) {
    			delete[] w_charbuff;
    			w_charbuff = nullptr;
    		}
    		if (charbuff != nullptr) {
    			delete[] charbuff;
    			charbuff = nullptr;
    		}
    	}
    
    	//ANSI=>Unicode
    	wchar_t* AnsiToUnicode(const char* str) {
    		//-1会自动推导字符串长度
    		if (w_charbuff != nullptr) {
    			delete[] w_charbuff;
    			w_charbuff = nullptr;
    		}
    		DWORD dsize = ::MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
    		w_charbuff = new wchar_t[dsize];
    		::MultiByteToWideChar(CP_ACP, 0, str, -1, w_charbuff, dsize);
    		return w_charbuff;
    	}
    
    	//Uncode=>ANSI
    	char* UnicodeToAnsi(const wchar_t* w_str) {
    		if (charbuff != nullptr) {
    			delete[] charbuff;
    			charbuff = nullptr;
    		}
    		DWORD dsize = ::WideCharToMultiByte(CP_ACP, 0, w_str, -1, NULL, 0, NULL, NULL);
    		charbuff = new char[dsize];
    		::WideCharToMultiByte(CP_ACP, 0, w_str, -1, charbuff, dsize, NULL, NULL);
    		return charbuff;
    	}
    
    	//Unicode=>UTF-8
    	char* UnicodeToUTF_8(const wchar_t* w_str) {
    		if (charbuff != nullptr) {
    			delete[] charbuff;
    			charbuff = nullptr;
    		}
    		DWORD dsize = ::WideCharToMultiByte(CP_UTF8, 0, w_charbuff, -1, NULL, 0, NULL, NULL);
    		charbuff = new char[dsize];
    		::WideCharToMultiByte(CP_UTF8, 0, w_charbuff, -1, charbuff, dsize, NULL, NULL);
    		return charbuff;
    	}
    
    	//UTF-8=>Unicode
    	wchar_t* UTF_8ToUnicode(const char* str) {
    		if (w_charbuff != nullptr) {
    			delete[] w_charbuff;
    			w_charbuff = nullptr;
    		}
    		DWORD dsize = ::MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
    		w_charbuff = new wchar_t[dsize];
    		::MultiByteToWideChar(CP_UTF8, 0, str, -1, w_charbuff, dsize);
    		return w_charbuff;
    	}
    
    	//ANSI=>UTF-8
    	char* AnsiToUTF_8(const char* str) {
    		//ANSI=>Uncode
    		w_charbuff = AnsiToUnicode(str);
    		//Unicode=>UTF-8
    		charbuff = UnicodeToUTF_8(w_charbuff);
    		return charbuff;
    	}
    
    	//UTF-8=>ANSI
    	char* UTF_8ToAnsi(const char* str) {
    		//UTF-8->Unicode
    		w_charbuff = UTF_8ToUnicode(str);
    		//Unicode->ANSI
    		charbuff = UnicodeToAnsi(w_charbuff);
    		return charbuff;
    	}
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86

    3. DEMO Windows记事本

    需要注意:
    记事本内的文字编码是Unicode,保存记事本内容后,保存文件编码为ANSI。

    平台:windows 10

    开发工具:Visual studio 2022

    核心功能:保存txt文件,读取txt文件。更改记事本内容的颜色,大小。替换查找记事本的文本

    核心功能代码:

    
    // NotePadeDemoDlg.cpp: 实现文件
    //
    #include "framework.h"
    #include "NotePadeDemo.h"
    #include "NotePadeDemoDlg.h"
    #include "afxdialogex.h"
    #include"ChangeCharSet.h"
    
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #endif
    
    //向系统注册消息
    static UINT NEAR WM_FINDREPLACE = ::RegisterWindowMessage(FINDMSGSTRING);
    
    
    // CNotePadeDemoDlg 对话框
    
    CNotePadeDemoDlg::CNotePadeDemoDlg(CWnd* pParent /*=nullptr*/)
    	: CDialogEx(IDD_NOTEPADEDEMO_DIALOG, pParent)
    {
    	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    	m_choice = RGB(0, 0, 0);//默认选择颜色是黑色
    	m_flag = FALSE;
    	nStartIndex = 0;
    	nEndIndex = 0;
    }
    
    void CNotePadeDemoDlg::DoDataExchange(CDataExchange* pDX)
    {
    	CDialogEx::DoDataExchange(pDX);
    }
    
    BEGIN_MESSAGE_MAP(CNotePadeDemoDlg, CDialogEx)
    	ON_WM_PAINT()
    	ON_WM_QUERYDRAGICON()
    	ON_BN_CLICKED(IDOK, &CNotePadeDemoDlg::OnBnClickedOk)
    	ON_WM_SIZE()
    	ON_COMMAND(ID_OPEN, &CNotePadeDemoDlg::OnMenuOpen)
    	ON_COMMAND(ID_SAVE_AS, &CNotePadeDemoDlg::OnMenuSaveAs)
    	ON_COMMAND(ID_CHANGE_COLOUR, &CNotePadeDemoDlg::OnChangeColour)
    	ON_WM_CTLCOLOR()
    	ON_COMMAND(ID_CHANGE_TITLE, &CNotePadeDemoDlg::OnChangeTitle)
    	ON_COMMAND(ID_EXIT, &CNotePadeDemoDlg::OnExit)
    	ON_COMMAND(ID_FIND, &CNotePadeDemoDlg::OnFind)
    	ON_COMMAND(ID_REPLACE, &CNotePadeDemoDlg::OnReplace)
    	ON_REGISTERED_MESSAGE(WM_FINDREPLACE, &CNotePadeDemoDlg::OnFindReplace)
    END_MESSAGE_MAP()
    
    
    // CNotePadeDemoDlg 消息处理程序
    
    BOOL CNotePadeDemoDlg::OnInitDialog()
    {
    	CDialogEx::OnInitDialog();
    
    	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
    	//  执行此操作
    	SetIcon(m_hIcon, TRUE);			// 设置大图标
    	SetIcon(m_hIcon, FALSE);		// 设置小图标
    
    	// TODO: 在此添加额外的初始化代码
    	// 
    	//设置字体
    	HFONT hfont = CreateFont(32, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET
    		, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH
    		, L"黑体");
    	//获取控件
    	HWND hwnd = ::GetDlgItem(this->m_hWnd, IDC_EDIT);
    
    	//设置字体大小
    	::SendMessage(hwnd, WM_SETFONT, WPARAM(hfont), 0);
    
    	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
    }
    
    // 如果向对话框添加最小化按钮,则需要下面的代码
    //  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
    //  这将由框架自动完成。
    
    void CNotePadeDemoDlg::OnPaint()
    {
    	if (IsIconic())
    	{
    		CPaintDC dc(this); // 用于绘制的设备上下文
    
    		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
    
    		// 使图标在工作区矩形中居中
    		int cxIcon = GetSystemMetrics(SM_CXICON);
    		int cyIcon = GetSystemMetrics(SM_CYICON);
    		CRect rect;
    		GetClientRect(&rect);
    		int x = (rect.Width() - cxIcon + 1) / 2;
    		int y = (rect.Height() - cyIcon + 1) / 2;
    
    		// 绘制图标
    		dc.DrawIcon(x, y, m_hIcon);
    	}
    	else
    	{
    		CDialogEx::OnPaint();
    	}
    }
    
    //当用户拖动最小化窗口时系统调用此函数取得光标
    //显示。
    HCURSOR CNotePadeDemoDlg::OnQueryDragIcon()
    {
    	return static_cast<HCURSOR>(m_hIcon);
    }
    
    
    void CNotePadeDemoDlg::OnBnClickedOk()
    {
    	// TODO: 在此添加控件通知处理程序代码
    	//CDialogEx::OnOK();
    }
    
    
    void CNotePadeDemoDlg::OnSize(UINT nType, int cx, int cy)
    {
    	CDialogEx::OnSize(nType, cx, cy);
    
    	// TODO: 在此处添加消息处理程序代码
    	//获取控件
    	CWnd* wnd = GetDlgItem(IDC_EDIT);
    	if (wnd != NULL) {
    		wnd->MoveWindow(0, 0, cx, cy);
    	}
    }
    
    
    //打开
    void CNotePadeDemoDlg::OnMenuOpen()
    {
    	// TODO: 在此添加命令处理程序代码
    	CFileDialog dlg(TRUE);
    	if (IDCANCEL == dlg.DoModal()) {
    		return;
    	}
    
    	CString strpath = dlg.GetPathName();
    
    	//打开文件,以读取的方式打开文件,读取文件编码为ANSI
    	CFile file;
    	if (FALSE == file.Open(strpath, CFile::modeRead)) {
    		MessageBox(TEXT("打开文件失败"), TEXT("警告"), MB_OK | MB_ICONWARNING);
    		return;
    	}
    	char buff[255] = { 0 };
    	CStringA msg;
    	//一次读取一个字符
    	while (file.Read(buff, 1)) {
    		msg += buff;
    	}
    
    	ChangeCharSet charset;
    	wchar_t* title_msg = charset.AnsiToUnicode(msg);
    	//设置窗口
    	SetDlgItemText(IDC_EDIT, title_msg);
    
    	//设置窗口标题
    	CString title;
    	title.Format(TEXT("NodePadeDemo ——%s[%d字节]"), dlg.GetFileName(), file.GetLength());
    	SetWindowText(title);
    
    	file.Close();
    }
    
    //另存为
    void CNotePadeDemoDlg::OnMenuSaveAs()
    {
    	// TODO: 在此添加命令处理程序代码
    	CFileDialog dlg(FALSE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, NULL);
    	if (IDCANCEL == dlg.DoModal()) {
    		return;
    	}
    	CString path = dlg.GetPathName();
    	CFile file;
    	if (IDCANCEL == file.Open(path, CFile::modeCreate | CFile::modeWrite)) {
    		MessageBox(TEXT("保存文件失败"), TEXT("警告"), MB_OK | MB_ICONWARNING);
    		return;
    	}
    
    	//读取控件上的所有文本
    	CString msg;
    	GetDlgItemText(IDC_EDIT, msg);
    
    	ChangeCharSet charset;
    	char* title_msg = charset.UnicodeToAnsi(msg);
    	//宽字符写入
    	file.Write(title_msg, strlen(title_msg));
    	file.Close();
    
    	//退出程序
    	CDialogEx::OnOK();
    }
    
    
    void CNotePadeDemoDlg::OnChangeColour()
    {
    	// TODO: 在此添加命令处理程序代码
    	//弹出颜色系统框
    	CColorDialog color;
    	if (IDCANCEL == color.DoModal()) {
    		return;
    	}
    	//获取选择的颜色
    	this->m_choice = color.GetColor();
    	//更改控件的颜色,通过发送WM_CTLCOLOR消息来改变颜色
    }
    
    
    HBRUSH CNotePadeDemoDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
    {
    	HBRUSH hbr = CDialogEx::OnCtlColor(pDC, pWnd, nCtlColor);
    
    	switch (pWnd->GetDlgCtrlID()){
    		case IDC_EDIT:
    		{
    			pDC->SetTextColor(m_choice);
    			break;
    		}
    		default:
    			break;
    	}
    	return hbr;
    }
    
    
    void CNotePadeDemoDlg::OnChangeTitle()
    {
    	// TODO: 在此添加命令处理程序代码
    	CFontDialog dlg;
    	if (IDCANCEL == dlg.DoModal()) {
    		return;
    	}
    
    	//创建选择的字体
    	CFont font;
    	font.CreatePointFont(dlg.GetSize(), dlg.GetFaceName());
    
    	//设置字体
    	GetDlgItem(IDC_EDIT)->SetFont(&font);
    }
    
    
    void CNotePadeDemoDlg::OnExit()
    {
    	//退出程序
    	CDialogEx::OnOK();
    }
    
    //查找对话框
    
    void CNotePadeDemoDlg::OnFind()
    {
    	//非模态对话框
    	CFindReplaceDialog* dlg = new CFindReplaceDialog;
    
    	//TRUE代表是查找框,FALSE代表是替换框
    	dlg->Create(TRUE, NULL, NULL);
    
    	dlg->ShowWindow(SW_SHOW);
    
    	//不需要delete,CFindReplaceDialog类内部处理了。不会导致内存泄漏
    
    	//此外,还需要向系统注册一个消息
    	this->m_flag = TRUE;
    }
    
    
    void CNotePadeDemoDlg::OnReplace()
    {
    	//非模态对话框
    	CFindReplaceDialog* dlg = new CFindReplaceDialog;
    
    	//TRUE代表是查找框,FALSE代表是替换框
    	dlg->Create(FALSE, NULL, NULL);
    
    	dlg->ShowWindow(SW_SHOW);
    
    	this->m_flag = FALSE;
    }
    
    //处理查找和替换操作
    LRESULT CNotePadeDemoDlg::OnFindReplace(WPARAM wparam, LPARAM lparam) {
    	CFindReplaceDialog* lpfindReplace = CFindReplaceDialog::GetNotifier(lparam);  
    	if (lpfindReplace == nullptr) {
    		return 0;
    	}
    	//如果要退出窗口
    	if (lpfindReplace->IsTerminating()) {
    		return 0;
    	}
    	//获取需要查找字符串
    	CString str_find = lpfindReplace->GetFindString();
    	//获取要替换的字符串
    	CString str_replaces = lpfindReplace->GetReplaceString();
    
    	BOOL SearchDownFlag = lpfindReplace->SearchDown();//判断是否向下查找,TRUE代表向下查找
    
    	BOOL MatchCass = lpfindReplace->MatchCase();//判断是否区分大小
    
    	//获取记事本内的文本
    	CString strContent;
    	GetDlgItemText(IDC_EDIT, strContent);
    
    	//获取记事本文本控件
    	CEdit* lpEdit = (CEdit*)GetDlgItem(IDC_EDIT);
    
    	//查找
    	if (this->m_flag == TRUE) {
    		//获取光标起始,结束位置
    		lpEdit->GetSel(this->nStartIndex, this->nEndIndex);
    
    		if (SearchDownFlag) {
    			//向下查找
    			//从结束位置开始向下找
    			this->nStartIndex = strContent.Find(str_find, this->nEndIndex);
    			if (this->nStartIndex != -1) {
    				//找到了,标记这个字符串
    				lpEdit->SetSel(this->nStartIndex, this->nStartIndex + str_find.GetLength());
    				lpEdit->SetFocus();
    			}
    			else {
    				从头开始找
    				//this->nStartIndex = strContent.Find(str_find, 0);
    					//文中没有这个字符串
    				CString msg;
    				msg.Format(L"在下文中没有找到%s这个字符串", str_find.GetString());
    				MessageBox(msg, L"警告", MB_OK|MB_ICONWARNING);
    				return 0;
    
    				//else {
    				//	//找到了,标记这个字符串
    				//	MessageBox(L"在上文中找到这个字符串", L"提示");
    				//	lpEdit->SetSel(this->nStartIndex, this->nStartIndex + str_find.GetLength());
    				//	lpEdit->SetFocus();
    				//}
    			}
    		}
    		else {
    			//向上查找,反转字符串
    			strContent = strContent.MakeReverse();
    			CString str_refind = str_find.MakeReverse();
    			this->nStartIndex = strContent.Find(str_refind, strContent.GetLength() - this->nStartIndex);
    
    			if (this->nStartIndex != -1) {
    				//设置光标
    				this->nEndIndex = strContent.GetLength() - this->nStartIndex;
    				lpEdit->SetSel(nEndIndex - str_find.GetLength(), nEndIndex);
    				lpEdit->SetFocus();
    			}
    			else {
    				CString msg;
    				msg.Format(L"在上文中没有找到%s这个字符串", str_find.GetString());
    				MessageBox(msg, L"警告", MB_OK | MB_ICONWARNING);
    				return 0;
    			}
    		}
    	}
    	//替换
    	else {
    		if (lpfindReplace->ReplaceCurrent()) {
    			this->nStartIndex = strContent.Find(str_find);
    			if (this->nStartIndex == -1) {
    				MessageBox(L"查不到这个字符串", L"警告", MB_OK);
    				return 0;
    			}
    			else {
    				this->nEndIndex = this->nStartIndex + str_find.GetLength();
    
    				//字符串剪切
    				CString left = strContent.Left(nStartIndex);
    				CString right = strContent.Right(strContent.GetLength() - nEndIndex);
    				strContent = left + str_replaces + right;
    				lpEdit->SetWindowText(strContent);
    			}
    		}
    
    		//替换全部
    		if (lpfindReplace->ReplaceAll()) {
    			int ntimes = strContent.Replace(str_find, str_replaces);
    			lpEdit->SetWindowText(strContent);
    			CString msg;
    			msg.Format(L"替换成功,替换了%d处", ntimes);
    			MessageBox(msg, L"提示", MB_OK);
    		}
    	}
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395

    运行效果:
    在这里插入图片描述
    在这里插入图片描述

    完整代码位置:
    Github

  • 相关阅读:
    上午面了个腾讯拿 38K 出来的,让我见识到了基础的天花
    vue脚手架安装及依赖
    【Call for papers】DSN-2023(CCF-B/截稿日期: 2022年12月7日)
    mycat实现分库分表小例子
    综合案例_文件上传的原理和综合案例_文件上传案例的客户端
    Zookeeper和Kafka安装
    如何高效利用阿里云Docker镜像仓库管理您的容器镜像
    23年秋招笔试算法题:美团蔚来
    互联网行业,常见含金量高的证书,看看你有几个?
    《优化接口设计的思路》系列:第三篇—留下用户调用接口的痕迹
  • 原文地址:https://blog.csdn.net/dodamce/article/details/126883417