孙鑫MFC第九章学习笔记

本章主要是学习窗口的创建,修改以及图标,菜单栏的等知识点。

首先:

1.修改外观和图标可以在MainFrm中进行,而修改背景和光标只能在View中进行。为什么?因为view的显示挡在了MainFrame的前面。

 a.MainFrame

     PreCreateWindow()中,在窗口创建之前,用重新注册窗口类的方法,这样比较麻烦:

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
 if( !CFrameWnd::PreCreateWindow(cs) )
  return FALSE;
 // TODO: Modify the Window class or styles here by modifying
 //  the CREATESTRUCT cs
 /*
 WNDCLASS CS;
 CS.cbClsExtra = 0;
 CS.cbWndExtra = 0;
 CS.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
 CS.hCursor = LoadCursor(NULL, IDC_CROSS);
 CS.hIcon = LoadIcon(NULL, IDI_ERROR);
 CS.lpszClassName = "sunxin.org";
 CS.hInstance = AfxGetInstanceHandle();
 CS.lpfnWndProc = ::DefWindowProc;
 CS.style = CS_VREDRAW | CS_HREDRAW;
 CS.lpszMenuName = NULL;
 RegisterClass(&CS);
 cs.lpszClass = "sunxin.org";

其中:preCreatWindow 是虚函数,且传递类型是引用,所以要修改窗口的大小和外观,只要改变对应的参数就可以。

但是这样比较麻烦,可以选择用全局函数AfxRegisterWndClass()来修改。

 //cs.lpszClass=AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,0,0,LoadIcon(NULL,IDI_WARNING));

其中的HCursor hCursor 和HBRUSH hbrbackgroud 表示的是光标和画布,只能是在view函数里面修改。

修改外观和图标可以在MainFrm中进行,而修改背景和光标只能在View中进行。为什么?因为view的显示挡在了MainFrame的前面。

在View中:

b.ViewPreCreateWindow()

 //cs.lpszClass=AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,

 // LoadCursor(NULL,IDC_CROSS),(HBRUSH)GetStockObject(BLACK_BRUSH),NULL);

在窗口创建之后,在OnCreate()中修改

 //SetWindowLong(m_hWnd,GWL_STYLE,WS_OVERLAPPEDWINDOW);

 //SetWindowLong(m_hWnd,GWL_STYLE,GetWindowLong(m_hWnd,GWL_STYLE) & ~WS_MAXIMIZEBOX);

// SetClassLong(m_hWnd,GCL_HICON,(LONG)LoadIcon(NULL,IDI_ERROR));

  OnCreate()

 SetClassLong(m_hWnd,GCL_HBRBACKGROUND,(LONG)GetStockObject(BLACK_BRUSH));

 SetClassLong(m_hWnd,GCL_HCURSOR,(LONG)LoadCursor(NULL,IDC_HELP));

由上可知;我们如果要修改弹出窗口的名称时,可以

 cs.lpszName = "sunxin.org";
 cs.style &= ~FWS_ADDTOTITLE;

但是

 

二:创建一个变化的图标

用函数setClassLong  和 setTimer两个函数

首先先在CMainFrame中新建个m_hIcons[n]数组。接着

m_hIcons[0] = LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_ICON1));//AfxGetInstanceHandle(),表示获取当前应用程序的实例句柄,MAKEINTRESOURCE是一个宏,它将实例句柄的地址整数转化为Win32的资源类型,简单的说它是一个类型转换#define

  m_hIcons[1] = LoadIcon(theApp.m_hInstance,MAKEINTRESOURCE(IDI_ICON2));//应用全局对象theAPP来获取句柄实例。但是前提是得在CMainFrame中添加外部变量的声明:extern style theAPP;  

m_hIcons[2] = LoadIcon(AfxGetApp()->m_hInstance, MAKEINTRESOURCE(IDI_ICON3));//应用全局变量AfxGetAPP来获取实例地址.

然后在int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)中添加

 SetClassLong(m_hWnd, GCL_HICON, (LONG)m_hIcons[0]);// 将第一个图标设置为弹出窗口的第一个显示。
 SetTimer(1, 1000,NULL);//时间设置为1S,其中NULL表示的是按照系统的。

然后在:新建个Timer宏变量:

void CMainFrame::OnTimer(UINT nIDEvent)
{
 // TODO: Add your message handler code here and/or call default
 static int index = 0;
 SetClassLong(m_hWnd, GCL_HICON, (LONG)m_hIcons[index]);
 index = ++index%3;//表示的是经过3S就自动循环

CFrameWnd::OnTimer(nIDEvent);
}

注:如果希望把某个数限定在一定的范围内,可以对此进行取模运算(%)实际上就是取余运算。

三:工具栏的编程

 3.1

 a.加入分隔符的方法,向右拖动即可;

 b.删除按纽的方法,拖出即可。

 3.2 创建工具栏

首先创建工具栏同时在新建个CToolBar    m_wndToolBar1;

在int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)中

 if (!m_wndToolBar1.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_RIGHT
  | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
  !m_wndToolBar1.LoadToolBar(IDR_TOOLBAR1))
 {
  TRACE0("Failed to create toolbar\n");
  return -1;      // fail to create
 }
 m_wndToolBar1.EnableDocking(CBRS_ALIGN_ANY);//第一个EnableDocking是工具看对象成员函数,允许工具栏对象停靠
EnableDocking(CBRS_ALIGN_ANY);//允许主对话框被停靠
 DockControlBar(&m_wndToolBar1);//让工具栏停靠在主窗口

但是这样的工具栏有个问题:怎样显示设置好的工具栏:

方法一:void CMainFrame::OnToolBar1()
{
 // TODO: Add your command handler code here

//第一种显示工具栏的方法,但是第一种有个缺陷是:工具栏出于悬浮时,就不能出现在原来的位置。
/*
 if (m_wndToolBar1.IsWindowVisible())//工具栏也是窗口,具有cwn窗口的属性
 {
  m_wndToolBar1.ShowWindow(SW_HIDE);
 
 }
 else
 {
  m_wndToolBar1.ShowWindow(SW_SHOW);
 }
 // 调用上面的显示和隐藏时,工具栏的工具条还在

// 改函数有一个BOOL类型参数:bNotify。如果该参数是真,则框架窗口上的活动对象会收到布局变动的通知。
// 如果为假,则不会。默认值为TRUE


 RecalcLayout();//调用框架类的函数,重新放置工具栏的位置
 DockControlBar(&m_wndToolBar1);//当工具栏被拖出来时,重新调用该函数,来重新放置

但是该方法是有个缺点:工具栏的位置隐藏后再次点击会出现在最上面
*/
 方法二:

 ShowControlBar(&m_wndToolBar1, !m_wndToolBar1.IsWindowVisible(), FALSE);

}

最后在菜单栏添加复选标记

void CMainFrame::OnUpdateToolBar1(CCmdUI* pCmdUI)
{
 // TODO: Add your command update UI handler code here
 pCmdUI->SetCheck(m_wndToolBar1.IsWindowVisible());
}

 

第四节:状态栏编程

状态栏的类: CStatusBar 也是个窗口类

 对应的状态栏地址

static UINT indicators[] =
{
 ID_SEPARATOR, // status line indicator状态栏
 IDS_TEMP,
 IDS_PROGRESS,
 ID_INDICATOR_CAPS,
 ID_INDICATOR_NUM,
 ID_INDICATOR_SCRL,
};

 

首先要新建个状态栏窗格,应在ResourceView类下面的String Table下面新建字符串ID

在此想在状态栏显示时间应在OnCreate()下面新建个

 //显示系统时间
 CTime t = CTime::GetCurrentTime();
 CString s = t.Format( "%H:%M:%S");

但是有个问题:不能完全显示时间。对此应该要重新设置窗格的大小

/ CClientDC:(客户区设备上下文)用于客户区的输出,与特定窗口关联,可以让
// 开发者访问目标窗口中客户区,其构造函数中包含了GetDC,析构函数中包含了ReleaseDC。

 CClientDC dc(this);
 CSize sz= dc.GetTextExtent(s);
 //获取当前索引的地址
 int index = m_wndStatusBar.CommandToIndex(IDS_TEMP);

 m_wndStatusBar.SetPaneInfo(index, IDS_TEMP, SBPS_NORMAL, sz.cx);//获取当前时间对应的宽度
 m_wndStatusBar.SetPaneText(index, s, TRUE);//显示时间窗格

如果可以知道index的值 就可以直接写数字就可以。

然后在void CMainFrame::OnTimer(UINT nIDEvent) 函数中设置时间栏

void CMainFrame::OnTimer(UINT nIDEvent)
{
 // TODO: Add your message handler code here and/or call default
 static int index = 0;
 SetClassLong(m_hWnd, GCL_HICON, (LONG)m_hIcons[index]);
 index = ++index%3;
 CTime s = CTime::GetCurrentTime();
 CString str = s.Format("%H:%M:%S");
 CClientDC dc(this);
 CSize sz = dc.GetTextExtent(str);
 m_wndStatusBar.SetPaneInfo(1, IDS_TEMP, SBPS_NORMAL, sz.cx);//重新设置时间栏

//原型为BOOL SetPaneText(int nIndex, LPCTSTR lpszNewText, BOOL bUpdate = TRUE)
// 其中的lpszNewText为指向新的窗格文本的指针 bUpdata是否立即更新?true
 m_wndStatusBar.SetPaneText(1, str);//设置显示状态栏窗格文本

 

 

设置进度栏:

 //设置进度栏,其中的CRect()分别表示的是左横坐标,左宗坐标,和右边的横纵坐标
// m_progress.Create(WS_CHILD|WS_VISIBLE|PBS_SMOOTH, CRect(100,100,300,115), this, 123);
// m_progress.SetPos(10);
 但是我们要在状态栏设置进度栏就应该要

先新建个CRect  rect,然后引用// m_progress.Create(WS_CHILD|WS_VISIBLE|PBS_SMOOTH, &rect, &m_wndStatusBar, 123);
 m_progress.SetPos(10);

 

 

 

接下来我们要让工具栏动起来。。具体必须调用CprogressCtrl::SetIt()函数,该函数表示进度栏以预先设定的速度增加,要设定预先的每步步长,可以用CprogressCtrl::stepSet()函数,默认值为10,这些必须是在CMainFrame::Ontimer()函数中设定。

 

 

 

 

 

 

五:在状态栏显示鼠标

首先调用捕获鼠标移动的消息:WM_MOUSEMOVE消息响应函数。

void CLesson9StyleView::OnMouseMove(UINT nFlags, CPoint point)

{

      // TODO: Add your message handler code here and/or call default   

CString str;

      str.Format("x = %d, y = %d", point.x, point.y);

      ((CMainFrame*)GetParent())->m_wndStatusBar.SetWindowText(str)

//    ((CMainFrame*)GetParent())->SetWindowText(str);这个是 

 

CView::OnMouseMove(nFlags, point);

}

注:

首先格式化当前的鼠标信息,然后为了将该信息显示在状态栏的第一个窗格上,需要捕获状态栏对象,捕获鼠标的可以调用SetWindowText()函数,但是,但是状态栏是在框架类中定义的,同时框架类窗口是视窗类的父窗口,因此在视窗类对象中调用GetParent()函数就可以得到视窗类的父窗口,即框架窗口。因此该函数返回的是一个CWnd的指针,而这里需要的是CMainFrame的指针,因此进行强制转化,然后在应用CMainFrame窗口类调用该对象内部的状态栏成员变量:

M_wndStatusBar(),但是要注意修改该对象的属性为Public

 

注意:状态栏不属于视类窗口,而是属于框架类窗口

 

 

六:启动画面

project下选择Add to Project 下面的

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值