MFC学习:设置窗口标题
作者:互联网
默认情况下,MFC的主窗口标题由文档标题和Frame标题组成,格式为:file - frame
。
设置标题
设置窗口标题用 CWnd::SetWindowText 方法。
设置文档标题
新建一个文档时,MFC 会使用字符串资源AFX_IDS_UNTITLED
作为文档的默认标题,接着会触发 CDocument::OnNewDocument 方法,我们可以在文件新建成功后使用 CDocument::SetTitle 方法来设置标题。
BOOL CMFCApplication2Doc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
this->SetTitle(_T("新文件"));
return TRUE;
}
如果是打开文档
就不能在 CDocument::OnOpenDocument 中处理,因为 MFC 在打开文档后会使用文件名作为标题
...
TCHAR szTitle[_MAX_FNAME];
if (AfxGetFileTitle(szFullPath, szTitle, _MAX_FNAME) == 0)
SetTitle(szTitle);
...
最早的修改时机是在 CDocument::SetPathName 中,我们可以重载它
void SetPathName(LPCTSTR lpszPathName, BOOL bAddToMRU) override
{
CDocument::SetPathName(lpszPathName, bAddToMRU);
this->SetTitle(_T("new title"));
}
但是更建议在 CDocument::OnDocumentEvent 中处理
void OnDocumentEvent(DocumentEvent deEvent) override
{
if (deEvent == onAfterNewDocument || deEvent == onAfterOpenDocument) {
this->SetTitle(_T("new title"));
}
}
固定窗口标题
我们有时候希望应用程序标题是固定的,不会随着文档变化,可以通过以下几种方式来做。
方式一
因为文档在设置标题后会触发 CFrameWndEx::OnUpdateFrameTitle 方法,而这个方法会改变窗口标题,所以我们覆盖它即可避免被影响。
在 CFrameWndEx::OnCreate 中设置固定标题
this->SetWindowText(_T("title"));
重载 CFrameWndEx::OnUpdateFrameTitle 方法,不调用父类操作。
void CMainFrame::OnUpdateFrameTitle(BOOL bAddToTitle)
{
// Ignore
}
方式二
跟进OnUpdateFrameTitle
后:
void CFrameWnd::OnUpdateFrameTitle(BOOL bAddToTitle)
{
if ((GetStyle() & FWS_ADDTOTITLE) == 0)
return; // leave it alone!
// allow hook to set the title (used for OLE support)
if (m_pNotifyHook != NULL && m_pNotifyHook->OnUpdateFrameTitle())
return;
CDocument* pDocument = GetActiveDocument();
if (bAddToTitle && pDocument != NULL)
UpdateFrameTitleForDocument(pDocument->GetTitle());
else
UpdateFrameTitleForDocument(NULL);
}
这里发现了一个新东西FWS_ADDTOTITLE
,如果窗口样式不包含它的话就退出函数了,所以我们也可以在创建Frame
时去除这个Flag
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
if (!CFrameWndEx::PreCreateWindow(cs))
return FALSE;
cs.style &= ~FWS_ADDTOTITLE;
return TRUE;
}
所以这个方式和方式一是一样的,本质上就是忽略OnUpdateFrameTitle
的默认行为。
方式三
继续跟进源码
void CFrameWnd::UpdateFrameTitleForDocument(LPCTSTR lpszDocName)
{
CString WindowText;
if (GetStyle() & FWS_PREFIXTITLE)
{
// get name of currently active view
if (lpszDocName != NULL)
{
WindowText += lpszDocName;
// add current window # if needed
if (m_nWindow > 0)
{
TCHAR szText[32];
// :%d will produce a maximum of 11 TCHARs
_stprintf_s(szText, _countof(szText), _T(":%d"), m_nWindow);
WindowText += szText;
}
WindowText += _T(" - ");
}
WindowText += m_strTitle;
}
else
{
// get name of currently active view
WindowText += m_strTitle;
if (lpszDocName != NULL)
{
WindowText += _T(" - ");
WindowText += lpszDocName;
// add current window # if needed
if (m_nWindow > 0)
{
TCHAR szText[32];
// :%d will produce a maximum of 11 TCHARs
_stprintf_s(szText, _countof(szText), _T(":%d"), m_nWindow);
WindowText += szText;
}
}
}
// set title if changed, but don't remove completely
// Note: will be excessive for MDI Frame with maximized child
AfxSetWindowText(m_hWnd, (LPCTSTR) WindowText);
}
逻辑很简单,只要我们将OnUpdateFrameTitle
方法唯一的参数设置为FALSE
,就可以让Frame
的 控件标题 作为窗口标题。
首先设置Frame
的控件标题,通过 CFrameWnd::SetTitle 方法。
this->SetTitle(_T("title"));
然后将OnUpdateFrameTitle
的参数设置为FALSE
void CMainFrame::OnUpdateFrameTitle(BOOL bAddToTitle)
{
__super::OnUpdateFrameTitle(FALSE);
}
Frame 默认标题从哪来?
如果我们不做任何设置,Frame 始终会有一个默认标题,这个标题字符串从哪来?还是看源码
BOOL CFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,
CWnd* pParentWnd, CCreateContext* pContext)
{
...
CString strFullString;
if (strFullString.LoadString(nIDResource))
AfxExtractSubString(m_strTitle, strFullString, 0); // first sub-string
...
}
原来在创建 MFC 工程时,资源文件中生成了它
STRINGTABLE
BEGIN
IDR_MAINFRAME "MFCApplication2\n\nMFCApplication2\n\n\nMFCApplication2.Document\nMFCApplication2.Document"
END
这是一个用\n
分隔的字符串列表,第一个子串就是默认标题。
关于其他子串的解释可以查看 CDocTemplate::GetDocString 的解释。
标签:OnUpdateFrameTitle,MFC,窗口,CDocument,SetTitle,标题,WindowText,szText 来源: https://www.cnblogs.com/cyds/p/16244353.html