文章目录
- CFont类与LOGFONT结构体
- CFontDialog
- 字体信息结构体与HFONT句柄的关系
- 记事本文件拖入、打开和保存及是否保存的逻辑流程分析
- 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 fontCString GetStyleName() const; // return the style name of the fontint GetSize() const; // return the pt size of the fontCOLORREF GetColor() const; // return the color of the fontint GetWeight() const; // return the chosen font weightBOOL IsStrikeOut() const; // return TRUE if strikeoutBOOL IsUnderline() const; // return TRUE if underlineBOOL IsBold() const; // return TRUE if bold fontBOOL IsItalic() const; // return TRUE if italic fontvoid GetCharFormat(CHARFORMAT& cf) const;LOGFONT m_lf; // default LOGFONT to store the infoDWORD 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;
示例代码:
void CMainDlg::OnFormatFont()
{CFontDialog dlg;if (dlg.DoModal() == IDCANCEL)return;LOGFONT lf;dlg.GetCurrentFont(&lf);m_font.DeleteObject();m_font.CreateFontIndirect(&lf);m_edit.SetFont(&m_font);
}
记事本文件拖入、打开和保存及是否保存的逻辑流程分析
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打开期间别的进程可以读。