windows开发记事本程序纪实(二)逻辑篇1

1. 主要内容

从本节开始介绍windows开发实现记事本程序的逻辑实现部分。本节的主要内容有以下3点:

1. 主窗口定义 —— 主要介绍记事本主界面窗口对应的窗口类及实现方案

2. RichEdit控件的选用及初始化 —— 记事本程序中编辑控件的选择及使用

3. 整个程序ICON的选择。—— 程序ICON设置

2. 实际开发

2.1 主窗口实现

在上一篇介绍界面的实现中只是给出了运行界面的效果,但是当时那个界面程序不能响应任何的windows消息,因为当时的窗口在创建时将窗口对应的过程处理函数设置为NULL。现在,我们需要将相应的过程处理函数添加上使得这个记事本应用程序可以响应我们发出的一系类操作指令。为此,本文在开发时,单独设计了一个用于保存主界面窗口的类CMainWnd。这个类定义了整个窗口的过程处理函数Main_Porc。在Main_Proc中可以对传入的任何消息进行处理(包括初始化窗口消息,窗口中其他控件的消息,关闭窗口消息等等)。以windows 自带记事本为例,如图1所示

图1 windows主窗口消息效应区域

如上图所示,在windows记事本主界面中,需要响应红色矩形区域内的菜单控件的各类消息、响应黄色矩形区域内系统按钮的相关消息,以及相应编辑控件Edit中的消息。对于主窗口中的各类控件的消息,windows会以WM_COMMAND消息进行传输,这也是整个程序的核心处理区域。系统按钮关闭的消息则是WM_CLOSE。窗口初始化消息WM_INITDIALOG则是构建对话框窗口前发出的初始化消息。为了能够响应上述各类消息,需要在CMainWnd中添加对于这几类消息的响应函数,因此整个CMainWnd的基本实现形式如下:

头文件声明:

/************************************************************************/
/* file  : CMainWnd.h
 * author : Huagang Li
 * date  : 2014-8-30 15:29:42
 * blogs : http://www.cnblogs.com/lhglihuagang/
 * tips  : 主窗口实现类, 实现窗口的过程函数,消息响应函数等
 */
/************************************************************************/
#ifndef _MAIN_WND_H
#define _MAIN_WND_H

#include <Windows.h>
//////////////////////////////////////////////////////////////////////////
// CMainWnd 主窗口类,提供

class CMainWnd
{
public:
  static BOOL WINAPI Main_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  static BOOL Main_OnInitDialog(HWND hWnd, HWND hWndFocus, LPARAM lParam);
  static void Main_OnCommand(HWND hWnd, int id, HWND hWndCtl, LPARAM lParam);
  static void Main_OnClose(HWND hWnd);

private:
  static HWND hMainWnd;  // 主窗口句柄
};

#endif

CMainWnd具体定义:

#include "MainWnd.h"
include <WindowsX.h>
//////////////////////////////////////////////////////////////////////////
// static data members
HWND CMainWnd::hMainWnd = NULL;
//////////////////////////////////////////////////////////////////////////
// static function members
// 主窗口的过程函数,根据消息类型处理各类消息
BOOL WINAPI CMainWnd::Main_Proc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
 switch (uMsg)
 {
 HANDLE_MSG(hWnd, WM_INITDIALOG, Main_OnInitDialog);
 HANDLE_MSG(hWnd, WM_COMMAND, Main_OnCommand);
 HANDLE_MSG(hWnd, WM_CLOSE, Main_OnClose);
 }
</span><span style="color: #0000ff">return</span><span style="color: #000000"> FALSE;
}
BOOL CMainWnd::Main_OnInitDialog( HWND hWnd, HWND hWndFocus, LPARAM lParam )
{
 return TRUE;
}
// id为具体空间的ID号,可以在resource中定义有意义的控件ID,如“打开文件”可以设置
// 为ID_FILE_OPEN
void CMainWnd::Main_OnCommand( HWND hWnd, int id, HWND hWndCtl, LPARAM lParam )
{
 switch (id)
 {
 //
 }
}
void CMainWnd::Main_OnClose( HWND hWnd )
{
 ::EndDialog(hWnd, NULL);
}

在定义了CMainWnd后,在main函数处的DialogBox处添加主窗口的过程处理函数

::DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, CMainWnd::Main_Proc);

完成上述步骤运行后,就可以看到启动后的主界面可以响应窗口上系统按钮“关闭”,但是对于菜单控件的消息,因为消息响应此还是函数中数什么都没有做,因此还是不会进行任何处理。

2.2 RichEdit控件的选用

对于一个记事本程序来说,主界面上核心区域还是编辑区域。但是当前记事本程序中还没有选择任何编辑控件。通过观察现有windows控件列表可以看出,适合编辑控件的有Edit Control以及Rich Edit2.0 Control。对于这两种编辑控件,Edit Control较为简单,但是响应的功能也较少。Rich Edit2.0 Control实现起来较为复杂,但是对应的功能也多了不少(例如可以改变字体颜色,字号等等)。本文希望能够实现一个功能较强的记事本,因此选择了Rich Edit2.0 Control进行后续开发。插入了Rich Edit2.0 Control后,主界面窗口对应的资源视图如图2所示:

图2 IDD_MAIN中插入Rich Edit2.0 Control

上述步骤运行后,本以为可以看到带有编辑界面的记事本程序,可是实际上程序运行后没有任何效果,甚至主界面都不能正常启动了。百度后发现,对于richedit启动失败的方法都是针对MFC程序来说的,需要添加初始化函数AfxInitRichEdit2。但是现在使用windows API 开发,并没有AfxInitRichEdit2这个函数,只能另寻他路了。终于在一篇博文中http://blog.csdn.net/dijkstar/article/details/7953816提到,原来上面那个初始化函数中主要是加载RichEdit依赖的dll,那么整个问题就豁然开朗了,我们只需要在主窗口启动前手动的载入这个dll就可以了。因此在主函数的DialogBox前添加了依据载入dll的操作如下:

::LoadLibrary(T("riched20.dll"));

MAIN的properties中:

此时再运行程序时,可以正常启动记事本了,且能够在richedit中进行编辑,效果如图3所示:

图3 手动加载Riched20.dll后出现主界面窗口

在启动主界面后,可以正常进行编辑。貌似这个控件可以正常工作了。但在实际测试时,发现了以下几个问题:

1. 界面运行后RichEdit边框棱角过于分明

处理方法: Richedit控件的properties  -> Boarder –> Flase

2.输入Enter 不能换行(手动输入时一直在同一行编辑)

处理方法: Richedit控件的properties  -> Multiline–> True

Richedit控件的properties  -> Want Return–> True

3. 没有滚动条(横向以及纵向的)

这个在主界面属性上,IDD

处理方法: IDD_MAIN-> properties  -> Horizontal Scrollbar–> True

IDD_MAIN –> properties  -> Vertical Scrollbar–> True

4. 不能随窗口大小伸缩

在对窗口进行伸缩时,RichEdit控件的大小还是保持原来的大小,如图4所示:

图4 主界面大小变化时RichEdit控件大小不变

这个问题其实很好理解,因为伸缩主界面窗口时,windows将发送WM_SIZE消息通知窗口。这个过程类似于windows对主界面窗口说“hi, 你的大小已经变了,你根据改变后的大小变一下”。现在我们的主窗口过程处理函数中并没有针对WM_SIZE消息对RichEdit进行特殊处理,因此主界面下面的RichEdit一直保持自己原来的大小,才会出现上面的情况。那么具体的解决方案为:在InitDialog中添加RichEdit大小自适应功能,同时针对WM_SIZE消息,添加Main_OnSize函数来处理这种独立的控件。具体的代码实现如下:

void CMainWnd::Main_OnSize( HWND hWnd, UINT state, int cx, int cy )
{
 RECT stRect;
 ::GetClientRect(hWnd, &stRect); // 获取窗口客户区大小
</span><span style="color: #008000">//</span><span style="color: #008000"> 将RichEdit大小调整为客户区大小</span>
 ::MoveWindow(::GetDlgItem(hWnd, IDC_RICHEDIT), stRect.left, stRect.top,
 stRect.right-stRect.left, stRect.bottom-stRect.top, TRUE);
}

这里只是在CMainWnd中添加了对于WM_SIZE的消息响应函数,要让RichEdit响应这个消息,还需要在Main_Proc中添加相应过程

HANDLE_MSG(hWnd, WM_SIZE, Main_OnSize);

这样,RichEdit也就可以跟着主窗口大小自由伸缩了。上述过程处理函数中,主要调用了三个基本的API接口。

1. GetClientRect,这个API用于获取客户区大小,RichEdit伸缩的大小就是这个大小值

2. GetDlgItem 获取窗口下某一个控件的句柄,例如GetDlgItem(hWnd, IDC_RICHEDIT),就可以获得主窗口下RichEdit控件对应的句柄。

3. MoveWindow。它的第一个参数就是需要进行位置大小变化的窗口句柄。我们这里将2中的RichEdit句柄传入,后面的参数分别是矩形区域的left点,top点,width值以及height值。最后一个参数用来表示大小改变后要不要重绘窗口。注意,这里选择了TRUE。如果选择FALSE,会出现以下这种情况:当将窗口变小后,在进行变大操作,RichEdit并没有立即适应变大后的区域,还是保留在原来变小的区域。效果如图5所示:

图5 MoveWindows中参数repaint设置为FALSE后潜在问题

基于此,我们在用MoveWindow改变窗口大小时,最好使得repaint为TRUE,保证实时改变。

2.3 主程序ICON设计

在上述截图中可以看出,主界面的左上角ICON一直是windows自带的ICON。为了与windows自带记事本做到类似,直接到网上找了一个类似的JPG图标转为ICO,然后设置了程序的ICON。具体的图标设置方法请参考http://www.cnblogs.com/lhglihuagang/p/3927283.html

在图标设置后,可以运行程序查看下最新的效果,如图6所示

图6 设置程序图标后的结果

最后,对话框窗口的标题Dialog实在显得有些另类,这里根据windows自带记事本的标题“无标题 - 记事本”,将这个值进行了相应的修改,具体为IDD_MAIN-> properties  -> Caption –> 无标题 - 记事本最后,对话框.

3. 运行结果

在添加了CMainWnd以及RichEdit后,整个程序的运行后效果如下图7所示:

图7 本节程序改动后的效果

4. 结论

1. 使用RichEdit控件时,需要手动加载riched20.dll,否则程序运行后没有任何界面效果

2. RichEdit换行、滚动条、边框都可以通过properties中相应字段进行设置

3. 需要在CMainWnd中添加WM_SIZE消息响应函数,保证RichEdit自由伸缩。

5. 参考链接

[1] http://blog.csdn.net/dijkstar/article/details/7953816

[2] http://www.cnblogs.com/lhglihuagang/p/3927283.html

[3] http://msdn.microsoft.com/en-us/library/ms633534(VS.85).aspx

6. 说明

这将是一个系列博文,后面会继续补充逻辑功能的开发的步骤。希望能与更多博友交流。 如果你觉得这篇文章还可以,请点赞,哈哈~~
      声明:未作说明,则本文为年糕原创。      注意:转载须保留全文,如需修改请 联系作者。

(0)

相关推荐

  • windows开发记事本程序纪实(一)界面篇

    前言 从毕业开始学习windows UI编程,工作中总是和一些API打交道,但是从没有做过一个完整的界面程序.因此打算自己利用空余时间做一个小的项目来总结自己所学的东西.在网上看到许多人建议自己动手写完整的项目才能快速提高,因此打算从仿照windows的记事本开始,真正实现一个基本的windows界面程序.考虑到编写一个完整的windows 记事本程序需要大量的工作,因此打算将每一个阶段的成果记录下来,一方面能够帮助自己进行总结,回顾已学的知识,另一方面也能够与其他网友一起讨论,从而可以在讨论中

  • windows开发记事本程序纪实(二)逻辑篇1

    1. 主要内容 从本节开始介绍windows开发实现记事本程序的逻辑实现部分.本节的主要内容有以下3点: 1. 主窗口定义 -- 主要介绍记事本主界面窗口对应的窗口类及实现方案 2. RichEdit控件的选用及初始化 -- 记事本程序中编辑控件的选择及使用 3. 整个程序ICON的选择.-- 程序ICON设置 2. 实际开发 2.1 主窗口实现 在上一篇介绍界面的实现中只是给出了运行界面的效果,但是当时那个界面程序不能响应任何的windows消息,因为当时的窗口在创建时将窗口对应的过程处理函数

  • C#开发Windows窗体应用程序的简单操作步骤

    使用C#开发应用程序时,一般包括创建项目.界面设计.设置属性.编写程序代码.保存项目.程序运行等6个步骤. 1.创建项目 在Visual Studio2017开发环境中选择"文件"→"新建"→"项目"菜单,弹出"新建项目"对话框,如图8.1所示. 图8.1 "新建项目"对话框 选择"Windows窗体应用(.NET Framework)".输入项目的名称.选择保存路径,然后单击"

  • 总结的一些PHP开发中的tips(必看篇)

    一.开发习惯和php代码 1.准确的理解各种概念.现在的新东西层出不穷,望文生义和一知半解对开发工作有害无益://比如我就碰到有人理解松散耦合(这个东西不新)的概念居然是要求代码不要有空行,否则你的程序就是"太松散"了 2.代码美观,适当的空行.缩进,空格,这样能更容易理解代码段的意思: 3.一定要写注释,而且要恰当的注释,要不然后面的维护工作或者接手代码的人会痛哭不已: 4.静态方法.类访问权限.接口.抽象类应该综合起来使用,发挥各自特点: 5.不要复制粘贴,即使是要用到现成的代码,

  • 用易语言开发Linux程序的方法

    易语言是一个跨平台的开发工具,支持Windows及Linux.使用易语言,您可以在Windows环境下编写基本于Windows的程序,及编写Linux下的程序,并且可分别发布于多个平台.分别发布时只需选择不同的操作系统即可. 在此,再次通知易语言用户,如果您编写的是基于Windows下的程序,可以使用易语言新版本直接编写,对跨平台没有丝毫影响,跟以前的操作没有两样.如果您想开发基于Linux系统下的程序,请参看以下的说明部分. 本章及以后所有叙述都假设您已安装了最新版本易语言. 一 界面 运行易

  • php微信开发之带参数二维码的使用

    最近做微信PC端网页微信相关功能的开发,从一个新手的角度来说,微信公众号的文档还是不好理解的,网上找的帖子大都也都基本上是复制微信公众平台上给的文档,开发微信带参数二维码过程中还是遇到不少坑的,在此把我的开发过程比较详细的记录下,希望对大家有所帮助. 我本次开发使用的是认证服务号. 1 接入 首先进入微信公众号 -> 基本配置  下面是基本配置的页面,在URL中填写服务器地址,这个地址就是接受微信推送事件的一个接口,我是使用thinkPHP框架开发的程序,在其中一个Module(Decorati

  • 微信小程序 获取二维码实例详解

     微信小程序 获取二维码实例详解 理论: 接口A: 适用于需要的码数量较少的业务场景 接口地址:(永久有效,数量有限,进入path对应的页面) https://api.weixin.qq.com/wxa/getwxacode?access_token=ACCESS_TOKEN path String 不能为空,最大长度 128 字节 width Int 430(默认) 二维码的宽度 auto_color .. line_color .. 接口B:适用于需要的码数量极多,或仅临时使用的业务场景(永

  • 使用apifm-wxapi快速开发小程序过程详解

    前言 我们要开发小程序,基本上都要涉及到以下几个方面的工作: 1.购买服务器,用来运行后台及接口程序: 2.购买域名,小程序中需要通过域名来调用服务器的数据: 3.购买 SSL 证书,小程序强制需要 https 的地址,传统无证书不加密的 http 请求微信不支持: 4.后台程序员开发后台程序,这样才能登录后台进行商品管理.订单维护.资金财务管理等等: 5.后台程序员开发小程序可用的 restfull api 接口或者是 websocket 接口: 6.开发的后台及接口程序的安全性.功能性.稳定

  • 如何基于JavaFX开发桌面程序

    基于JavaFX开发桌面程序 注:我也是JAVA FX的初学者之一,自己在学习的时候踩了许多的坑,中文英文的资料查了不少,但是觉得FX技术和其他热门技术相比,教程还是太少了.这里就尽量做一点微小的贡献吧 使用环境 注:写这个只是为了说明我的环境,使用和我的不一样的环境在理解这篇教程的时候并没有什么问题,例如使用Windows平台.使用Oracle JDK(这样就不需要再单独安装FX组件了,可以不用MAVEN).使用Oracle的SceneBuilder.可能唯一一个比较影响体验的就是不使用IDE

  • Taro UI框架开发小程序实现左滑喜欢右滑不喜欢效果

    Taro 就是可以用 React 语法写小程序的框架,拥有多端转换能力,一套代码可编译为微信小程序.百度小程序.支付宝小程序.H5.RN等 摘要: 年后入职了一家新公司,与前同事交接完之后,发现公司有一个四端的项目(iOS,Android,H5,小程序),iOS和安卓都实现了左滑右滑的效果,而h5和小程序端没实现,询问得知前同事因网上没找到对应的插件,相关博客也特别少,所以没做就搁置下来了. 趁这段时间相对来说比较富裕,于是乎在网上也搜索了一下,发现确实很少,但是有人提到可以用小程序可拖动组件m

随机推荐