文章目录
- 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 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;
示例代码:
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打开期间别的进程可以读。