MFC第十七天 CFont类与LOGFONT结构体(字体选择与注册表保存)、记事本文件打开和保存及是否保存的逻辑流程分析、PreTranslateMessage虚函数与快捷键

CFont类与LOGFONT结构体

CFontDialog

构造函数介绍

public:
//用于指定字体对话框的初始字体属性,可以是一个LOGFONT结构体指针。如果指定了这个参数,字体对话框将会显示该初始字体属性。 如果为NULL则使用默认字体样式
	CFontDialog(LPLOGFONT lplfInitial = NULL,
		DWORD dwFlags = CF_EFFECTS | CF_SCREENFONTS,
		CDC* pdcPrinter = NULL,
		CWnd* pParentWnd = NULL);
	CFontDialog(const CHARFORMAT& charformat,
		DWORD dwFlags = CF_SCREENFONTS,
		CDC* pdcPrinter = NULL,
		CWnd* pParentWnd = NULL);
//用于指定字体对话框的父窗口指针。如果指定了这个参数,字体对话框将作为该窗口的子窗口显示;如果为NULL,则字体对话框将作为顶级窗口显示。

CFontDialog是一个对话框类,用于显示字体选择对话框,并允许用户选择字体的样式。

class CFontDialog : public CCommonDialog{
	// Get the selected font (works during DoModal displayed or after)
	void GetCurrentFont(LPLOGFONT lplf);
	CString GetFaceName() const;  // return the face name of the font
	CString GetStyleName() const; // return the style name of the font
	int GetSize() const;          // return the pt size of the font
	COLORREF GetColor() const;    // return the color of the font
	int GetWeight() const;        // return the chosen font weight
	BOOL IsStrikeOut() const;     // return TRUE if strikeout
	BOOL IsUnderline() const;     // return TRUE if underline
	BOOL IsBold() const;          // return TRUE if bold font
	BOOL IsItalic() const;        // return TRUE if italic font
	void GetCharFormat(CHARFORMAT& cf) const;

	LOGFONT m_lf; // default LOGFONT to store the info
	DWORD FillInLogFont(const CHARFORMAT& cf);
};

字体信息结构体与HFONT句柄的关系

a)CFont类有两个重要的函数是关于两者的转换。
b)如果你有句柄就可以调用CWnd::SetFont设置字体。
c)如果你有字体信息结构体对象,调用CFont::CreateFontIndirect来在CFont对象中产生句柄。
(有点类似于struct tm{年月日时分秒}转为time_t句柄)
d)如果你有句柄,可以调用CFont::GetLogFont获取这个字体的信息(通过LOGFONT对象)

使用句柄生成详细信息
CFont* pFont = m_edit.GetFont();//获取了字体的详细信息
if (!pFont)
	return;
LOGFONT lf{};
pFont->GetLogFont(&lf);
使用信息结构体生成句柄
LOGFONT lf{21};
lf.lfWeight = 400;//700是粗体 400正常
lf.lfCharSet = GB2312_CHARSET;
_tcscpy_s(lf.lfFaceName, _countof(lf.lfFaceName), _T("楷体"));
m_font.DeleteObject();//摧毁句柄
m_font.CreateFontIndirect(&lf);
m_edit.SetFont(&m_font);
typedef struct tagLOGFONTW{
    LONG      lfHeight; 字体大小
    LONG      lfWidth; 拉宽(揪脸蛋子),默认用0代表自然高宽。
    LONG      lfEscapement;   LONG      lfOrientation;
    LONG      lfWeight; 粗体:700 正常:400 
    BYTE      lfItalic; 斜体    //那个年代没有bool型
    BYTE      lfUnderline; 下划线
    BYTE      lfStrikeOut; 删除线(横穿)
    BYTE      lfCharSet; 字符集(ANSI_CHARSET)
    BYTE      lfOutPrecision;
    BYTE      lfClipPrecision;
    BYTE      lfQuality;
    BYTE      lfPitchAndFamily;
    WCHAR     lfFaceName[LF_FACESIZE]; //字体名
} LOGFONTW, *PLOGFONTW, NEAR *NPLOGFONTW, FAR *LPLOGFONTW;

字体选择与注册表保存

在初始化时加载 LoadSetting()函数读取注册表信息

void CMainDlg::LoadSetting()
{
	LPLOGFONT p = NULL;
	UINT nLen = sizeof(LOGFONT);
	theApp.GetProfileBinary(_T("SETTINGS"), _T("FONT"), (LPBYTE*)&p, &nLen);
}

OnFormatFont()

void CMainDlg::OnFormatFont(){
	LOGFONT lf;
	CFont* pFont = m_edit.GetFont();  //用于获取特定窗口或控件的字体
	pFont->GetLogFont(&lf); 
	//获取一个指定字体的LOGFONT结构,该结构包含了字体的各种属性,如字体名称、字号、加粗、斜体等
	CFontDialog dlg(&lf);
	if (dlg.DoModal() == IDCANCEL)
		return;
	dlg.GetCurrentFont(&lf);
	m_font.DeleteObject();
	m_font.CreateFontIndirect(&lf); // 根据 LOGFONT 结构创建字体
	m_edit.SetFont(&m_font);
	
	theApp.WriteProfileBinary(_T("SETTINGS"), _T("FONT"), (LPBYTE)&lf, sizeof(lf));
}	

记事本文件拖入、打开和保存及是否保存的逻辑流程分析

在这里插入图片描述

 void CMainDlg::OnDropFiles(HDROP hDrop)
{
	TCHAR s[MAX_PATH];
	int nCount = DragQueryFile(hDrop, 0, s, _countof(s));

	ReadText(s);
	DragFinish(hDrop);

	CDialog::OnDropFiles(hDrop);
}
BOOL CMainDlg::Prompt() {		//FALSE代表放弃
	if (m_edit.GetModify())	
	{
		CString str = m_sFile;
		if (str.IsEmpty())
			str = _T("无标题");
		int nRes = AfxMessageBox(_T("你想要更改保存文件") + str + _T(":吗?"), MB_YESNOCANCEL);
		if (nRes == IDCANCEL)
			return FALSE;
		if (nRes == IDYES)
			if (!SelectFile())
				return FALSE;
	}
	return TRUE;
}
void CMainDlg::UpdateTitle()
{
	CString str;
	int n = m_sFile.ReverseFind(_T('\\'));
	if (n > 0)
	{
		str = m_sFile.Mid(1 + n);
	}
	if (str.IsEmpty())
		str = _T("无标题");

	str += _T(" - 记事本");

	SetWindowText(str);
}
void CMainDlg::OnFileOpen()
{
	if (m_edit.GetModify())
		if (!Prompt())
			return;
	CFileDialog dlg(TRUE,_T("txt"),NULL,0,m_szFilter);
	if (IDCANCEL == dlg.DoModal())
		return;
	ReadText(dlg.GetPathName());
	UpdateTitle();
}
BOOL CMainDlg::SelectFile()
{
	if (m_sFile.IsEmpty())
	{
		CFileDialog dlg(FALSE, _T("txt"), NULL, OFN_OVERWRITEPROMPT,m_szFilter);
		if (IDCANCEL == dlg.DoModal())
			return FALSE;
		m_sFile = dlg.GetPathName();
		OnFileSave();
	}
	return TRUE;
}
void CMainDlg::OnFileSave(){
	if (!SelectFile())
		return;
	ASSERT(!m_sFile.IsEmpty());
	CFile file;
	if (!file.Open(m_sFile,CFile::modeCreate| CFile::modeWrite))	{
		AfxMessageBox(_T("保存文件失败!"));
		return;	}
	CString str;
	m_edit.GetWindowText(str);
	WORD w{ 0xFEFF };		file.Write(&w,sizeof(w));
	file.Write(str, sizeof(TCHAR) * str.GetLength());
	file.Close();
	UpdateTitle();
	m_edit.SetModify(FALSE);	}
void CMainDlg::OnFileSaveAs()
{
	CFileDialog dlg(FALSE,_T("txt"), NULL,OFN_OVERWRITEPROMPT);
	if (IDCANCEL == dlg.DoModal())
		return;
	m_sFile =dlg.GetPathName();

	OnFileSave();
}

PreTranslateMessage虚函数与快捷键

a)我们经常看到消息被控件拐走了,所以好多消息包括:WM_MOUSEMOVE和WM_KEYDOWN等在消息都在主窗口不能用;
b)当然如果你做控件的派生类再进行子类化,是可以到控件类中去截获这些消息。比如:CEyeCtrl类。
c)预先翻译消息是什么意思?所有的消息被分配到控件或者主窗口之前的入口检查。

PreTranslateMessage函数允许我们在消息到达窗口过程之前对消息进行预处理和转换。通过重写这个函数,我们可以实现对消息的拦截、修改和处理,从而实现一些高级的交互功能,比如处理键盘快捷键。

定义句柄
	HACCEL m_hAccel;
初始化对话框时候加载
m_hAccel = LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ACCEL));
BOOL CMainDlg::PreTranslateMessage(MSG* pMsg)  //消息预处理函数  皇军的岗楼  
{
	if (m_hAccel)
	{
		if (TranslateAccelerator(m_hWnd, m_hAccel, pMsg)) //快捷键的处理
			return TRUE;
	}
	return CDialog::PreTranslateMessage(pMsg);
}

在这里插入图片描述
在这里插入图片描述

附录

CFile类的share模式:

enum OpenFlags {
		modeRead =         (int) 0x00000,
		modeWrite =        (int) 0x00001,
		modeReadWrite =    (int) 0x00002,
		shareCompat =      (int) 0x00000,
		shareExclusive =   (int) 0x00010, 拒绝共享执行
		shareDenyWrite =   (int) 0x00020, 拒绝共享写
		shareDenyRead =    (int) 0x00030, 拒绝共享读
		shareDenyNone =    (int) 0x00040, 不拒绝(可以共享读写都行)
		modeNoInherit =    (int) 0x00080,
		}

比如:shareDenyWrite 拒绝共享写,那么就是CFile打开期间别的进程可以读。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Jcrry

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

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

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

打赏作者

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

抵扣说明:

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

余额充值