VC++中使用用户自定义消息及自定制窗口技巧
Windows 应用程序所要做的每项工作几乎都是基于消息处理的, Windows 系统消息分为常用 Windows 消息,控件通知消息和命令。然而,有时我们需要定义自己的消息来通知程序什么事情发生了,这就是用户自定义消息。 ClassWizard 并没有提供增加用户自定义消息的功能,所以要使用用户自定义消息,必须手工编写代码。然后 ClassWizard 才可以象处理其它消息一样处理你自定义的消息。具体做法如下详解:
第一步:定义消息。一个消息实际上是开发 Windows95 应用程序时, Microsoft 推荐用户自定义消息至少是 WM_USER+100 ,因为很多新控件也要使用 WM_USER 消息。
第二步:实现消息处理函数。该函数使用 WPRAM 和 LPARAM 参数并返回 LPESULT 。
LPESULT CMainFrame::OnMyMessage(WPARAM wParam, LPARAM lParam){// TODO: 处理用户自定义消息 AfxMessageBox(" 处理用户自定义消息 "); return 0;}
第三步:在类头文件的 AFX_MSG 块中说明消息处理函数:
class CMainFrame:public CMDIFrameWnd{
...
// 一般消息映射函数
protected:
// {{AFX_MSG(CMainFrame)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnTimer(UINT nIDEvent);
afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()}
第四步:在用户类的消息块中,使用 ON_MESSAGE 宏指令将消息映射到消息处理函数中。
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_CREATE()
ON_WM_TIMER()
ON_MESSAGE(WM_MY_MESSAGE, OnMyMessage)
//}}AFX_MSG_MAPEND_MESSAGE_MAP()
这样,一个用户自定义消息就可以使用了,如果用户需要一个整个系统唯一的消息,可以调用 SDK 函数 RegisterWindowMessage 并使用 ON_REGISTER_MESSAGE 宏指令取代 ON_MESSAGE 宏指令,其余步骤同上。
VC++ 为程序员提供了一套功能强大、方便快捷的编程工具,它可以帮你方便的生成窗口、菜单等用户界面,可惜就是做出来的东西都一样,没有一点个性。下面,就介绍一些方法,让我们可以按照自己的设计定制出更加符合自己程序风格的窗口。
一、如何在多文档界面下去掉开始的子窗口
在多文档界面程序中,程序刚启动的时候会自动打开一个新的子窗口,而一个实际的应用系统往往是由用户操作后再生成新的窗口。下面是如何去掉开始的子窗口。
首先在应用程序的 App 类里找到
BOOL CMyMDIApp::InitInstance() 下面有:
// Parse command line for standard shell commands, DDE, file open
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
这是在处理命令行参数,在这几句话后面加一行:
cmdInfo.m_nShellCommand=CCommandLineInfo::FileNothing; 就可以了。再运行程序,就会发现程序并没有自动开启一个子窗口,而只剩下主框架窗口了。
二、修改窗口标题栏
在缺省情况下,窗口标题栏中显示的标题为程序名 + 当前文档的文件名。比如 " MyProgram - 文档 1 . t x t "
,那若要在标题栏显示一个自己定义的字符串,而不是程序名,可以通过在程序里调用 CWnd::SetWindowText()
方法来实现,而如果我们还想要后面的文档名自动显示,这么做就不行了,这时可以用资源编辑器编辑字符串表( StringTable )资源,在
StringTable 中双击 IDR-MAIN-FRAME 项, caption 中显示一字符串 xx\n\yy......
,将第一个参数修改为用户自己希望见到的主窗口标题即可。
如果你不想让系统自动帮你把文档的文件名添加到标题栏中,需要在 CMainFram 的 PreCreateWindow 函数中删除 FWS_ADDTOTITLE 标志的窗口样式:
cs.style &= ~FWS_ADDTOTITLE ;
这样,程序运行起来,窗口标题就是 "MyProgram" 而没有后面的 "- 文档 1.txt" 这样的字符串了。
三、修改主框架窗口、子窗口及其显示风格
MFC 的 CWnd 类会在调用 CWnd::Create() 方法前先调用一下 PreCreateWindo() 方法,其参数是
CREATESTRUCT cs ,其中包括了创建窗口时各参数,例如大小,风格等等,我们可以通过重载这个成员函数来修改主窗口和子窗口的风格等属性。
PreCreateWindow 函数的原型为: Virtual BOOL PreCreateWindow ( CREATESTRUCT cs
)。重载 PreCreateWindow 函数以后,则在创建窗口前可以修改 CREATESTRUCT 结构以替换缺省参数。
CREATESTRUCT 结构存放窗口特征,如窗口坐标、风格等,还可以定义新窗口风格。
若想修改主框架窗口,则可以在 MainFrm.cpp 的下列成员函数中加入待修改的内容。例如:
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT&cs)
{
// 通过修改 CREATESTRUCT 结构来修改窗口类或风格
cs.cx=450;
cs.cy=300;
// 定义新窗口的高度、宽度
// 定义新窗口风格为去掉主窗口名及最大化等按钮
cs.style=ws-POPWINDO;
return CFrameWnd::PreCreateWindow(cs); }
定制子窗口的操作与上述主窗口相同,可在 ChildFrame.cpp 中加入以下内容:
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT&cs)
{
// 通过修改 CREATESTRUCT 结构来修改窗口类或风格
return CMDIChildWnd::PreCreateWindow(cs);
}
要修改视图窗口的显示性质,则可在视图文件 MyView.cpp 的下述成员函数中加入以下语句:
BOOL MyView::PreCreateWindow(CREATESTRUCT&cs)
{
// 在这里修改 cs 结构,改变 View 的风格。
cs.lpszClass=AfxRegisterWndClass(cs-HREDRAW|CS-VREDRAW,0,(HBRUSH))::GetStockObject(WHITE-BRUSH),0);
return CScrollView::PreCreateWindow(cs);
}
其中, cs 的参数 pszClass 用于存放 Windows 窗口类名称。要想注册 Windows 窗口类,则必须调用全局函数 AfxRegisterWndClass 。该函数原型为:
LPCTSTR AFXAPI AfxRegisterWndClass(UINTnClassStyle,HCURSOR hCursor=0,HBRUSH hbrBackground=0,HICON hIcon=0)
上述各参数用于定义风格,其含义分别为光标资源句柄、背景资源句柄、图标资源句柄。上述增加的语句的作用是:改变窗口大小时重画窗口、不显示光标图标、设置白色背景。
四、窗口的滚动
MFC 中的 CScrollView 可以帮助你自动实现窗口滚动的决大部分功能,使用 CscrollView 时, ClassWizard 生成 OnInitialUpdate() 成员函数为:
void CMyScrollView::OnInitialUpdat()
{
CScrollView::OnIntialUpdate();
CSize sizePage;
sizePage.cs=sizePage.cy=400;
SetScrollSizes(MM-TEXT,sizePage);
}
其中, cs 和 cy 分别为滚动窗口的水平、垂直分量,表明窗口的水平、垂直方向尺寸小于 400
像素单位时将出现水平方向滚动条和垂直方向滚动条。通过修改滚动尺寸,可改变出现滚动条的最小窗口。例如,若
sizePage.cx=600;sizePage.cy=800; ,则当窗口尺寸小于 600*800 时,就会出现滚动条。
五、窗口分割
该功能可将窗口分割成多个可滚动的帧,帧之间的边界称为分割条,可用分割条来调整每个帧的相对大小。要想增加窗口分割功能,则必须修改主窗口类。首先,在主窗口类的头文件 MainFrm.h 中添加以下代码:
CSplitterWnd m-SWnd;
Virtual BOOL OnCreateClient (LPCREATESTRUCTcs,CcreateContext *pContext);
再在 MainFrm.cpp 中添加成员函数 OnCreateClient 的定义:
BOOL CmainFrame::OnCreateCline(LPCREATESTRUCTcs,CcreateContext *p Context)
{
return m-SWnd.Creat(this,2,2,Csize(20,20),pContext);
}
新的 CSplitterWnd 类对象 m-SWnd
用于创建和管理分割窗口,该窗口中可以包含一个或多个帧。首次创建主窗口时,将调用成员函数 OnCreateClient
。在缺省情况下,该函数创建一个填充主框窗口客户区的视图窗口。覆盖该函数后,将调用 CsplitterWnd 的成员函数 Create
来创建分割窗口。其中,第一个参数用于指定分割的父窗口(主窗口);第二个参数指定垂直方向上的帧个数为 2
;第三个参数指定水平方向上的帧的个数;第四个参数用于设置每个帧的最小尺寸;第五个参数传递描述信息。上述分割窗口的每个帧都是由视图类对象管理的,当
用户在某一帧内显示文档和图形时,必须在其它帧中重新绘制,从而在多个帧中均显示相同的内容。为此,必须调用显示文档类的 UpdateALLView
成员函数来更新其它帧。此时,只需加入 pdoc- > UpdataALLView(NULL) 即可
VC++中使用用户自定义消息及自定制窗口技巧的更多相关文章
- 在MFC中添加用户自定义消息
1.定义一个宏 (用户自定义消息从WM_USER开始) #define WM_XXXXX WM_USER+数值 2.声明一个函数并实现 afx_msg LRESULT OnXXXXX( WPARAM ...
- MFC中添加用户自定义消息
1.定义一个宏(用户自定义消息从WM_USER开始) #define WM_XXXXX WM_USER+数值 2.声明一个成员函数并实现 afx_msg LRESULT OnXXXXX( WPARAM ...
- 【转】vc中使用SendMessage正确发送自定义消息的方法--不错
原文网址:http://zhoumf1214.blog.163.com/blog/static/5241940200910265532959/ 最近在用VC2008做开发,后来由于要用到消息的发送,而 ...
- vc中使用SendMessage正确发送自定义消息的方法
最近在用VC2008做开发,后来由于要用到消息的发送,而且需要自定义消息,在网上查找了很多例子,根据他们所说的,虽然大致都差不多,但是基本上没有 一个能完全做出来的.要知道VC编程有一个小地方出错,都 ...
- C++ vc中怎么使用SendMessage自定义消息函数
vc中怎么使用SendMessage自定义消息函数: SendMessage的基本结构如下:SendMessage( HWND hWnd, //消息传递的目标窗口或线程的句柄. UINT ...
- VC++学习之VC中常见问题
VC++学习之VC中常见问题 (1)为什么某个类突然在工作区间里面突然看不见了? 只是类隐藏了,打开FILEVIEW,找到隐藏类的头文件,随便敲一下键盘的空格键,类就会在CLASSVIEW中显示了 ( ...
- MFC用户自定义消息
之前做过佳能相机和位移平台的额二次开发,当时遇到一个棘手的问题,就是位移平台如何知道相机已经拍完照了,或者相机如何知道位移平台已经运行到指定位置,当时为了方便采用了定时器来定时检测位移平台的位置,结果 ...
- VC++中开发汇编语言(转)
汇编程序结构 一个显示字符串的汇编程序 程序格式 一.模式定义 二.includelib语句 三.函数声明语句 四.数据和代码部分 Visual C/C++环境 建立工程 汇编程序的调试 一.设置断点 ...
- VC中基于 Windows 的精确定时[转]
在工业生产控制系统中,有许多需要定时完成的操作,如定时显示当前时间,定时刷新屏幕上的进度条,上位 机定时向下位机发送命令和传送数据等.特别是在对控制性能要求较高的实时控制系统和数据采集系统中,就更需要 ...
随机推荐
- day89 DjangoRsetFramework学习---restful规范,解析器组件,Postman等
DjangoRsetFramework学习---restful规范,解析器组件,Postman等 本节目录 一 预备知识 二 restful规范 三 DRF的APIView和解析 ...
- Home Assistant系列 -- 设置界面语言与地理位置
Home Assistant 安装的时候会自动根据你的系统语言设置默认语言,安装完成以后也可以根据需要自己设置选择语言.启动 Home Assistant ,浏览器打开web 界面,点击左上角的用户图 ...
- C语言顺序队列
顺序队列是一种只能在一头进和另一头出的数据结构,所以结构体里设2个指针分别指向头部和尾部,用数组来存储数据. #define MAXSIZE 1024 typedef int elemtype; ty ...
- Go语言中结构体的使用-第2部分OOP
1 概述 结构体的基本语法请参见:Go语言中结构体的使用-第1部分结构体.结构体除了是一个复合数据之外,还用来做面向对象编程.Go 语言使用结构体和结构体成员来描述真实世界的实体和实体对应的各种属性. ...
- DP_最长公共子序列/动规入门
学自:https://open.163.com/movie/2010/12/L/4/M6UTT5U0I_M6V2U1HL4.html 最长公共子序列:(本文先谈如何求出最长公共子序列的长度,求出最长公 ...
- # 2017-2018-1 20155232《信息安全技术》实验二——Windows口令破解
2017-2018-1 20155232<信息安全技术>实验二--Windows口令破解 [实验目的] 了解Windows口令破解原理 对信息安全有直观感性认识 能够运用工具实现口令破解 ...
- 2016-2017-20155329 《Java程序设计》第十周学习总结
学号 2016-2017-20155329 <Java程序设计>第十周学习总结 教材学习内容总结 学习目标 了解计算机网络基础 OSI分层(7层):物理层.数据链路层.网络层.传输层.会话 ...
- Docker入门篇(一)之docker基础
1.Docker 架构 http://blog.csdn.net/u012562943/article/category/6048991/1Docker 使用客户端-服务器 (C/S) 架构模式,使用 ...
- .NET core 项目部署在windows 服务器方法以及iis 访问报 500.19错误的解决办法
将本地发布的服务本地运行没问题,发布上云windows 服务器就报 500.19 0x8007000d 是因为云服务器没有安装.net core相关的插件,比如.NET CORE sdk等,请按照该文 ...
- Entity Framework中执行Sql语句
如果想在EF框架中执行Sql语句,其实很简单,EF里面已经提供了相关的方法(此处使用的EF为EF4.1版本). EF中提供了两个方法,一个是执行查询的Sql语句SqlQue ...