📄 mfc_api.txt
字号:
以利用CStatusBar::SetPaneInfo函数来规定pane的大小。
2.编辑MAINFRM.CPP文件,将ID_INDICATOR_TIME插入indicators[]数组。
这个数组用于定义状态条的各pane。如果这时编译运行程序,会看到多了
一个pane,但什么内容都没有。
3.增加一个消息映射,如
ON_UPDATE_COMMAND_UI(ID_INDICATOR_TIME,OnUpdateTime)
但要注意,这一行代码要放在AFX_MSG_MAP注释之外,因为Class Wizard
不能识别它。
4.为CMainFrame增加OnUpdateTime成员函数:
void CMainFrame::OnUpdateTime(CCmdUI *pCmdUI)
{
CTime t = CTime::GetCurrentTime();
char szTime[6];
int nHour = t.GetHour();
int nMinute = t.GetMinute();
if (nHour > 12)
nHour = nHour - 12;
wsprintf(szTime, "%i:%02i", nHour, nMinute);
m_wndStatusBar.SetPaneText(m_wndStatusBar.CommandToIndex \
(ID_INDICATOR_TIME), LPCSTR(szTime));
pCmdUI->Enable();//这是必须的,否则不会显示任何内容
}
由于应用程序空闲时,应用程序会向各个控制条发送一条WM_IDLEUPDATECMDUI
消息,这会导致OnUpdateTime被调用。
如果这是工作的全部,那么时间显示会不同步,因为只有应用程序的消息队列
中的所有消息被处理过后才会发送一条WM_IDLEUPDATECMDUI消息,之后如果消
息队列中如果再没有其它消息的话,WM_IDLEUPDATECMDUI消息就无被发送的机
会。为了使状态条能时刻显示时间的变化,就必须避免应用程序的消息队列长
时间为空。这就需要第五步。
5.为框架窗口建立一个一秒间隔的计时器。
<1.36>如何在SDI应用中生成多个视?
1.在应用类对象的InitInstance函数中生成一个新视并把它与文档类对象联系
起来。这个新视对象的构造函数、析构函数衿ONInitialUpdate函数都必须是
public的而不是protected的。
在InitInstance函数中,在OnFileNew函数的下面可插入以下代码来生成新的视:
注意:要包含AFXPRIV.H文件。
...
CView* pActiveView = ((CFrameWnd*) m_pMainWnd)->GetActiveView();
m_pOldView = pActiveView;
m_pNewView = (CView*) new CNewView;
CDocument* pCurrentDoc =((CFrameWnd*) m_pMainWnd)->GetActiveDocument();
//下面的代码初始化指向当前活动文档对象的创建上下文,以便将
//新生成的视对象加入到文档对象的视列表中。
CCreateContext newContext;
newContext.m_pNewViewClass = NULL;
newContext.m_pNewDocTemplate = NULL;
newContext.m_pLastView = NULL;
newContext.m_pCurrentFrame = NULL;
newContext.m_pCurrentDoc = pCurrentDoc;
UINT viewID = AFX_IDW_PANE_FIRST + 1;//默认状态下第一个生成的视ID
//为AFX_IDW_PANE_FIRST,这里新生成的视ID要与之区别开
CRect rect(0, 0, 0, 0); // gets resized later
m_pNewView->Create(NULL, "AnyWindowName", WS_CHILD,
rect,m_pMainWnd, viewID, &newContext);//创建视窗口对象
//如果视对象由文档模板生成,模板对象会自动向视窗口
//发送WM_INITIALUPDATE消息。这里必须主动发送这个消息
m_pNewView->SendMessage(WM_INITIALUPDATE, 0, 0);
...
这里m_pOldView和m_pNewView都是应用类对象的成员变量。
2.增加SwitchView函数,用于视间的切换
CView* CMyWinApp::SwitchView(CView* pNewView)
{
CView* pActiveView =((CFrameWnd*) m_pMainWnd)->GetActiveView();
//下面这些代码用于将这两个视的ID交换,以便使框架窗口的RecalcLayout
//函数能正确显示适当的视窗口
//因为RecalcLayout函数将ID为AFX_IDW_PANE_FIRST的视作为唯一的视来
//参与客户区域的布局。
UINT temp = ::GetWindowWord(pActiveView->m_hWnd, GWW_ID);
::SetWindowWord(pActiveView->m_hWnd, GWW_ID,
::GetWindowWord(pNewView->m_hWnd, GWW_ID));
::SetWindowWord(pNewView->m_hWnd, GWW_ID, temp);
//将当前活动的视隐藏并显示另外一个视窗口
pActiveView->ShowWindow(SW_HIDE);
pNewView->ShowWindow(SW_SHOW);
//正确设置当前活动的视对象
((CFrameWnd*) m_pMainWnd)->SetActiveView(pNewView);
//强制框架窗口重新进行客户区域的布局
((CFrameWnd*) m_pMainWnd)->RecalcLayout();
pNewView->Invalidate();//强制当前的视重画
return pActiveView;
}
对于这个函数返回的视对象可在适当的时候删除掉,但在删除之前别忘了
调用CDocument::RemoveView函数将这个视对象从文档对象的视列表中删掉。
这个函数可以在响应某个菜单命令时调用。
<1.37>如何使对话框在生成时位于父窗口客户区的正中间?
下面定义的CenterDialog函数用于将对话框定位于父窗口客户区的正中,
这个函数一般在OnInitDialog中调用。
如果使用MFC2.0以上版本,可以使用CenterWindow函数来完成这个功能。
void CMyDialog::CenterDialog(CWnd *MyDialogPtr)
{
CPoint Point;
CRect DialogRect;
CRect ParentRect;
int nWidth;
int nHeight;
CWnd *DesktopWindow = NULL;
CWnd *MainWindow;
// 获取对话框窗口的大小
MyDialogPtr->GetWindowRect(DialogRect);
// 获取主框架窗口,如果不存在则参照桌面进行居中定位
MainWindow = AfxGetApp()->m_pMainWnd;
if (MainWindow != NULL)
MainWindow->GetClientRect(ParentRect);
else
{
DesktopWindow = MyDialogPtr->GetDesktopWindow();
DesktopWindow->GetWindowRect(ParentRect);
}
nWidth = DialogRect.Width();
nHeight = DialogRect.Height();
Point.x = ParentRect.Width() / 2;
Point.y = ParentRect.Height() / 2;
if (MainWindow)
MainWindow->ClientToScreen(&Point);
else
DesktopWindow->ClientToScreen(&Point);
Point.x -= nWidth / 2;
Point.y -= nHeight / 2;
MyDialogPtr->MoveWindow(Point.x, Point.y, nWidth, nHeight, FALSE);
}
<1.38>如何改变CView,CFrameWnd以及CWnd类对象的背景颜色?
除了改变窗口类中的背景刷子的句柄外,适当处理WM_ERASEBKGND消息
也是一种好方法。
如:
BOOL CMyView::OnEraseBkgnd(CDC* pDC)
{
// 定义特定颜色的刷子
CBrush backBrush(RGB(255, 128, 128));
CBrush* pOldBrush = pDC->SelectObject(&backBrush);
CRect rect;
pDC->GetClipBox(&rect);// 获取需要用背景刷子涂抹的区域
pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(),PATCOPY);
pDC->SelectObject(pOldBrush);
return TRUE;
}
<1.39>如何在MFC中subclass一个窗口?
CWnd::SubclassWindow函数可以用于这一目的,但要注意的是,我们要
在CWnd的派生类中重载GetSuperWndProcAddr函数提供一个存放
被subclassed的窗口的窗口函数指针的地方。
如:
WNDPROC* CMyWnd::GetSuperWndProcAddr()
{
static WNDPROC NEAR pfnSuper = NULL;
//这个变量也可说明为CMyWnd的成员变量
return &pfnSuper;
}
如果我们想subclass一个窗口对象pWnd,可以调用:
pMyWnd -> SubclassWindow ( pWnd ->GetSafeHwnd())
其中pMyWnd是CMyWnd类对象的指针。
BOOL CWordWin::Create(CWnd *Parent,int x,int y,int width,int height)
{
BOOL bRet=CWnd::CreateEx(WS_EX_TOPMOST,AfxRegisterWndClass(0),"Word",WS_POPUP|WS_CHILD,0,0,100,50,Parent->GetSafeHwnd(),NULL,NULL);
if (!bRet) return false;
//SetParent(Parent);
MoveWindow(x,y,width,height,TRUE);
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -