您的位置:首页 > 其它

MFC原创教程:5.0 Style 窗口风格

2013-01-13 15:39 387 查看
VC++/MFC Window编程原创教程目录

1:窗口创建之前改变外观

修改大小、标题,代码添加在: BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

{

if( !CFrameWndEx::PreCreateWindow(cs) )

return FALSE;

// TODO: 在此处通过修改

// CREATESTRUCT cs 来修改窗口类或样式

cs.cx=800; //修改宽度

cs.cy=800;

cs.style &= ~FWS_ADDTOTITLE; //取反减去“或”运算;默认cs.style=WS_OVERLAPPEDWINDOW || FWS_ADDTOTITLE(增加文档标题到窗口标题)

cs.lpszName="窗口标题修改";

return TRUE;

}

2:窗口创建之后改变外观。

代码添加在CMainFrame::OnCreate (该函数先调用了基类,所以创建了窗口了)

//SetWindowLong(m_hWnd,GWL_STYLE,WS_OVERLAPPEDWINDOW);

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

//改变窗口属性。参数(窗口句柄,设一新的风格,替换的值:获取旧分割“减去”窗口最大化属性)

3:使用窗口类修改。

代码添加在MainFrame::PreCreateWindow(把之前写的代码注释了吧)

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

{

if( !CFrameWndEx::PreCreateWindow(cs) )

return FALSE;

// TODO: 在此处通过修改

// CREATESTRUCT cs 来修改窗口类或样式

WNDCLASS wndcls; //设计窗口类

wndcls.cbClsExtra=0;

wndcls.cbWndExtra=0;

//额外空间暂不需要http://topic.csdn.net/u/20080304/15/c9c072d3-a996-4f20-90cd-817bc13cc8d7.html

wndcls.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH); //背景颜色

wndcls.hCursor=LoadCursor(NULL,IDC_HELP); //光标。NULL表选用标准。

wndcls.hIcon=LoadIcon(NULL,IDI_ERROR);

wndcls.hInstance=AfxGetInstanceHandle(); //获取应用程序的句柄

wndcls.lpfnWndProc=::DefWindowProc; //窗口过程。::表调用全局API函数。

wndcls.lpszClassName="类名字";

wndcls.lpszMenuName=NULL; //单文档EXE已经默认加载菜单了,此处可为NULL。

wndcls.style=CS_HREDRAW | CS_VREDRAW; //窗口类类型。水平重画 | 垂直重画

RegisterClass(&wndcls); //注册窗口类

return TRUE;

}

//因为VIEW覆盖在框架类上,所以使用窗口类要在VIEW中使用。

BOOL CStyleView::PreCreateWindow(CREATESTRUCT& cs)

{

// TODO: 在此处通过修改

// CREATESTRUCT cs 来修改窗口类或样式

cs.lpszClass="类名字";

return CView::PreCreateWindow(cs);

}

第3步的代码其实只要用一行代码就能代替, 代码放在:CStyleView::PreCreateWindow

cs.lpszClass=AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,LoadCursor(NULL,IDC_HELP),(HBRUSH)GetStockObject(BLACK_BRUSH), LoadIcon(NULL,IDI_ERROR));
//若cs.lpszClass=AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW);,则得一个透明窗口,但VS2010貌似不是这样。

4:循环变化icon图标。

右键点击资源面板的Style.rc--添加资源--导入--下拉列表选择图标文件--选择3个ico格式的文件导入。

在CMainFrame添加私有数组HICON m_hIcon[3],使其分别成为3 个ICO文件关联变量。

在CMainFrame::OnCreate添加以下代码:

m_hIcon[0]=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_ICON1));
//加载图标。参数(三种方式获取当前程序句柄:之前是使用标准图标故此参数不用设置,图标字符串指针:MAKEINTRESOURCE宏将一个整型值转换成和资源管理函数兼容的资源类型 )

m_hIcon[1]=LoadIcon(theApp.m_hInstance,MAKEINTRESOURCE(IDI_ICON2)); //其它类的变量,需要extern CStyleApp theApp;

m_hIcon[2]=LoadIcon(AfxGetApp()->m_hInstance,MAKEINTRESOURCE(IDI_ICON3));

SetTimer(1,1000,NULL);
//定时器(标识,毫秒,回调函数)

添加一个Timer消息

void CMainFrame::OnTimer(UINT_PTR nIDEvent)

{

// TODO: 在此添加消息处理程序代码和/或调用默认值

static int index=0; //作为数组下标

SetClassLong(m_hWnd,GCL_HICON,(LONG)m_hIcon[index]); //改变窗口图标

index=++index%3; //0~2循环公式

CFrameWndEx::OnTimer(nIDEvent);

}

参考:http://blog.sina.com.cn/s/blog_69e905cd0100kk53.html

5.1:显示新工具栏

资源视图--Toolbar,图标ID号与对应菜单栏的选项ID相同。在菜单(IDR_MAINFRAME_256)添加一个ID号为IDM_TEXT的菜单项,添加按钮消息,弹出MessageBox,然后在工具栏视图画个新的工具(若没有关联消息,则是灰色显示),修改其ID为IDM_TEXT。运行时,两处的点击效果一样。(画图要使用:图像编辑器)删除按钮的方法:将按钮拖离工具栏,用Delete键不管用,Delete只是删除了按钮上的图像;插入分隔符的方法(S2010貌似不能实现,暂时找不到解决方法):横向右拖动按钮一定距离,就会插入分隔符,反方向再拖一下,就删除分隔符了。

VS2010的CMFCToolbar实现真彩色工具栏:http://blog.sina.com.cn/s/blog_6d4b374e01015hhd.html

插入新的ToolBar(IDR_TOOLBAR1),画三、四个图标。

新工具栏的显示方法1:教程里使用的是CToolBar,但在VS2010不奏效,需要用到CMFCToolBar。http://www.cnblogs.com/luoshupeng/archive/2011/08/15/2139645.html

首先在MainFrm.h,加入一个CMFCToolBar变量



CMainFrame::OnCreate末端添加以下代码:

if (!m_newToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_RIGHT | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS | !m_newToolBar.LoadToolBar(IDR_TOOLBAR1))
//该OnCreate函数开头有创建主工具栏的代码,模仿即可。

{

TRACE0("未能创建工具栏\n");

return -1; // 未能创建

}

m_newToolBar.EnableDocking(CBRS_ALIGN_ANY); //设置工具栏可以停靠(任意地方)

DockPane(&m_newToolBar); //工具栏停靠在主框架窗口上

//VS2010的工具栏要浮动,听说是要用到FloatPane(),但我不知道后面怎么搞了,工具栏都是默认浮动。。。

5.21:显示、隐藏工具栏

菜单栏资源的视图子菜单添加一个菜单项:新工具栏,ID修改为:IDM_VIEW_NEWTOOL。右键--添加处理函数(COMMAND,CMainFrame)。

void CMainFrame::OnViewNewtool()

{

// TODO: 在此添加命令处理程序代码

if(m_newToolBar.IsWindowVisible())

m_newToolBar.ShowWindow(SW_HIDE);

else

m_newToolBar.ShowWindow(SW_SHOW);

//RecalcLayout(); //重新调整。经测试,VS2010好像不需要这段代码

DockPane(&m_newToolBar); //VC6.0使用的代码是DockControlBar(&m_newToolBar);

ShowPane(&m_newToolBar,!m_newToolBar.IsWindowVisible(),0,0); //VS2010显示工具栏的另一种方法(前面代码都注释掉)。VC6.0代码是:ShowControlBar(&m_newToolBar,!m_newToolBar.IsWindowVisible(),FALSE);

http://technet.microsoft.com/zh-cn/library/bb983173(v=vs.110).aspx

}

5.22:添加复选标记

右键点击
菜单栏资源的视图子菜单 新工具栏--添加事件处理--(UPDATE_COMMAND_UI ,CMainFrame)

void
CMainFrame::OnUpdateViewNewtool(CCmdUI *pCmdUI)

{

// TODO: 在此添加命令更新用户界面处理程序代码

pCmdUI->SetCheck(m_newToolBar.IsWindowVisible());

}



5.31:状态栏右下角窗格。

资源视图--StringTable-StringTable-添加(IDS_TIME,时间)(IDS_PROGRESS,进度栏)

CMainFrame::OnCreate



(在MainFrm.h可以找到m_wndStatusBar,看看他的引用)

5.311:显示系统时间

在CMainFrame::OnTimer(之前已经添加过这个消息了)添加以下代码:

CTime t=CTime::GetCurrentTime(); //获取系统时间

CString str=t.Format("%H:%M:%S"); //格式化输出

CClientDC dc(this);

CSize sz=dc.GetTextExtent(str); //为了获取宽度

m_wndStatusBar.SetPaneInfo(1,IDS_TIME,SBPS_NORMAL,sz.cx); //设置区域宽度

m_wndStatusBar.SetPaneText(1,str); //显示时间



5.312:进度栏

类似5.1的新工具栏变量创建方法,加上:CProgressCtrl m_progress; //进度条控件

这一小节主要是学“用户消息”。首先在MainFrm.h定义一个消息(加在#pragma once之后)

#define UM_PROGRESS WM_USER+1 //UM约定为用户的消息,WM是系统的消息,系统定义消息的值在WM_USER以下,故用户消息取值为...然后是消息响应函数原型的声明

afx_msg void OnProgress();



最后是在CPP加上消息映射和函数


void CMainFrame::OnProgress() //VS2010需加两参数(WPARAM wParam,LPARAM lParam)

{

CRect rect; //用来接收右下角窗格的矩形

m_wndStatusBar.GetItemRect(2,&rect);

m_progress.Create(WS_CHILD | WS_VISIBLE,

rect,&m_wndStatusBar,123); //创建窗格

m_progress.SetPos(50);

}

以上代码不能在VS2010生效,详见:http://blog.163.com/chenpeijie0_0/blog/static/183094571201161304437752/

实现效果:


但当窗口发生重绘,进度栏并不会随窗格移动(造成错位),完善方法:添加WM_POINT消息

void CMainFrame::OnPaint()

{

CPaintDC dc(this); // device context for painting

// TODO: 在此处添加消息处理程序代码

CRect rect;

m_wndStatusBar.GetItemRect(2,&rect);

if(!m_progress.m_hWnd)

m_progress.Create(WS_CHILD | WS_VISIBLE,

rect,&m_wndStatusBar,123);

else

m_progress.MoveWindow(rect); //移动进度条

m_progress.SetPos(50);

// 不为绘图消息调用 CFrameWndEx::OnPaint()

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: