设为首页收藏本站

中国膜结构网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

膜结构车棚
膜结构车棚膜结构资质国产膜材 膜结构网中国膜结构协会
查看: 474|回复: 19

MFC 控件大全

[复制链接]
  • TA的每日心情
    开心
    2021-6-19 14:40
  • 签到天数: 1539 天

    [LV.Master]伴坛终老

    发表于 2021-2-1 15:58 | 显示全部楼层 |阅读模式

    0、开发环境:
    操作系统:Microsoft Windows 7 Ultimate Sp1 x64
    编译工具:Microsoft Visual Studio 2013 Professional 中文版(其实 VS2010、VS2012、VS2013、VS2015、VS2017 都可以的,操作基本相同)

    1、简介:
    之前VC驿站给大家推出了《实用C++》的新手入门教程,可以说把我们平时针对C++语言经常用到的知识点都做了讲解。不知道大家学习的怎么样?课后有没有真正的去敲代码练习。光看教程是不行的哦~

    那么之前啊主要给大家讲解的是C++的基础语言,所以呢主要是在黑窗口的这种命令行控制台下操作的,跟界面没什么关联。但是作为C++新手来说肯定都是对于UI界面比较感兴趣,毕竟我也是从新手阶段过来的。写好了的软件执行起来能看到界面也很有成就感。可以激发大家学习VC++编程的积极性。所以从本节课开始给大家讲解下VC++中的界面开发技术。

    2、Windows程序简介:
    实际上Windows系统大家应该再熟悉不过了,Windows程序呢也主要分那么几种,例如:exe的可执行程序,dll的动态链接库程序,lib的静态库程序,sys的驱动类型程序等等。这些都可以用VC++来开发。

    Exe类的程序从操作界面的使用角度来说又分成两种:
    第一种就是我们之前一直使用的黑窗口的控制台下的程序,这种程序一般没有什么界面,都是使用命令行进行操作,比如:ipconfig、ping 之类的。使用系统提供的cmd控制台进行加载。入口点函数是 main。
    第二种就是我们接下来要讲解的非控制台类型的程序,这种程序可以有界面,也可以没有界面。想要界面就调用创建窗口的API函数去创建个界面出来,不想要界面呢不创建就可以了。所以呢比较灵活。入口点函数是 WinMain。

    3、Windows编程开发相关概念:
    Windows API:Windows操作系统应用程序接口(Windows API),有非正式的简称法为WinAPI,是微软对于Windows操作系统中可用的核心应用程序编程接口的称法。它被设计为各种语言的程序调用,也是应用软件与Windows系统最直接的交互方式。大多数驱动程序需要对Windows系统更底层次访问接口,由所用版本的Windows的Native API来提供接口。
    Windows有一个软件开发包(SDK, software development kit)提供相应的文档和工具,以使程序员开发使用Windows API的软件和利用Windows技术。

    说了这么多,对于新手来说可能还是不太理解,我用通俗一点的话来解释下!
    有人会问了我都学完了C++,难道还不能编写Windows系统下的应用程序吗?我还得学其他的东西吗?答案是:能,但是只能编写一些简单的控制台下的黑窗口程序。或者说只能调用C++基本语言内部的函数。

    如果你要创建一个窗口,如果你要创建一个按钮,如果你要创建一个菜单,如果你要创建一个进程,如果你要做一个带界面的任务管理器,以上这些单纯使用C++语言能做到吗?答案是:肯定做不到了。
    那么如何来做呢,就是要调用windows系统提供给我们的API接口,大家可以把API接口看作是系统提供给我们的工具,使用这些工具就可以做出我们想要的东西来。再举个现实生活中的例子,你学会了C++语言就好比你有了一些简单的工具,C++语言就好比是螺丝刀,扳手,钳子等等,用这些工具你可以做些简单的事情,可如果要让你造出一台汽车,你单纯使用螺丝刀、扳手一类的工具可能造出来吗?答案是:不可能。所以你还需要制造汽车的更高级的东西,比如:车床、工厂、车间等等大型的机械化设备,这些设备是制造汽车的必须品,API就好比这些设备。所以你要在windows系统上开发出更高级的软件,那么就必须调用其系统提供的API接口。这么打比方大家明白了吗?

    4、基本的Win32程序:
    接下来就教大家如何创建一个Win32类型的Exe程序,具体见视频教程演示。。。
    怎么样大家看到了吧,代码量不少,而且操作来说比较复杂,又是初始化,又是注册窗口类,又是窗口函数什么的,一堆东西。更重要的是我们使用这个模版工程继续开发的话会越来越麻烦,比如添加个基本的按钮响应函数,这个还算是简单的了,当对一些比较复杂的控件操作时就更复杂了,比如:ListCtrl 高级列表控件,TreeCtrl 树形控件等等。

    另外,当前工程模版默认创建出来的这个窗口不是对话框,所以是没办法进行拖拽控件的,对于小白来说想快速的拖拽控件做出一个窗口看来是有点麻烦了。
    实际上Win32类型的工程就是调用基本的系统提供的API函数来写程序的。

    5、解决方案:
    既然Win32类型的工程这么麻烦,要记的东西也这么多,以后开发起来岂不是很费事儿?这个微软早想到了,其他很多公司也想到了。本身C++就是一门面相对象的,可封装的语言,所以能不能对系统提供的API函数以及复杂的开发流程进行一下封装呢,这样我们以后使用起来就能方便不少?答案是:当然可以了。所以现在市面上有很多封装好的C++库,或者说框架,比如:MFC、QT,这两个算是比较有名的,而且他们两个不仅仅是界面库,还包括很多其他的操作,比如文件管理,字符串操作,网络管理,多线程,数据库操作,注册表操作等等吧,很多方面。

    那么他们两个有什么区别,我们该选用哪个呢?其实这个话题从古至今很多人在讨论。个人观点,感觉两个框架都有优缺点,大家根据自己的需要进行选择:

    MFC:微软基础类库(英语:Microsoft Foundation Classes,简称MFC)是一个微软公司提供的类库(class libraries),以C++类的形式封装了Windows API,并且包含一个(也是微软产品的唯一一个)应用程序框架,以减少应用程序开发人员的工作量。其中包含的类包含大量Windows句柄封装类和很多Windows的内建控件和组件的封装类。

    优点:MFC说白了就是微软自家的东西,所以VC自带MFC工程向导,VC对MFC支持的也很好。对于界面方面实现起来简单,易于上手,能快速的制作简单的UI界面,执行效率高,生成的EXE或者其他程序可以直接在Windows系统上执行,生成的文件体积也比较小;

    缺点:这东西对于新手来说学起来还是有点复杂,因为是对WinApi的封装,里面用到了大量的宏,所以有时候是基于面向过程的,有时候是基于面向对象的,内部也是使用基于Windows系统的消息机制,所以学起来不是那么容易,学习周期长。如果要做成比较美观的界面,类似我们使用的QQ、迅雷、YY等软件的UI界面的话,使用MFC实现起来就比较费时费力,做起来比较麻烦倒不是说做不了,只是比较费劲而已。另外,因为是微软自己的东西,所以不能跨平台,在 Linux、Mac 系统上是别想用了。

    总结:所以MFC适合开发对界面美化要求不高软件。

    Qt:是一个跨平台的C++应用程序开发框架。广泛用于开发GUI程序,这种情况下又被称为部件工具箱。也可用于开发非GUI程序,比如控制台工具和服务器。Qt使用于OPIE、Skype、VLC media player、Adobe Photoshop Elements、VirtualBox与Mathematica以及被Autodesk、欧洲空间局、梦工厂、Google、HP、KDE、卢卡斯影业、西门子公司、沃尔沃集团, 华特迪士尼动画制作公司、三星集团、飞利浦、Panasonic所使用。

    它是Digia公司的产品。Qt使用标准的C++和特殊的代码生成扩展(称为元对象编译器(Meta Object Compiler, moc))以及一些宏。通过语言绑定,其他的编程语言也可以使用Qt。
    Qt是自由且开放源代码的软件,在GNU宽通用公共许可证(LGPL)条款下发布。所有版本都支持广泛的编译器,包括GCC的C++编译器和Visual Studio。

    优点:Qt是一个开源的项目,可以跨平台使用,在 Linux、Mac 系统下一样可以使用。使用完全面向对象的封装机制,内部使用信号与槽机制,易于上手。开发文档丰富,支持VS插件的形式进行开发。可以制作漂亮精美的软件UI界面。省时省力。

    缺点:Qt有点过度封装,而且体积也稍大,执行效率没有MFC高,程序分发打包的时候需要将Qt的核心DLL一起随程序打包,不然程序跑步起来。当然也可以用静态库的方式编译,默认只生成一个Exe文件,但这样的话程序的体积会变的很大,不管怎么说Qt生成的文件在分发携带方面的方便性上赶不上Windows的原生程序或者MFC的程序。当然如果是类似YY这种产品级的软件倒也无所谓多带几个DLL了。


    总结:所以Qt适合开发对界面美化要求较高的软件。

    MFC 和 QT 就好比 手动档车与自动档车一样,前者开发软件太累,但可控性更加高些。

    综合以上吧,毕竟我们不是开发什么大型的软件产品,但也为了让大家以后转型方便,所以本套教程界面UI方面使用MFC来开发,除界面外的其他逻辑部分我们全用 原生CPP + SDK API 的方式来做。
    这种方式目前来说我想是最好的。同时呢,大家不要着急,以后我们VC驿站会给大家出几套Qt方面的教程,让想学Qt方面的学员也有机会!

    从下节课开始,我们就逐一讲解MFC控件工具箱中提供的基础的那15个控件,以及每个控件如何进行美化,如何使用开源类进行更多功能的操作等等,大家好好学习吧~

    6、相关控件:
    Button                按钮控件
    CheckBox        复选框控件
    Edit                        编辑框控件
    ComboBox        下拉控件
    ListBox                列表控件
    GroupBox        分组控件
    Radio Button        单选框控件
    Static Text        静态文本框控件
    Picture Control        图像控件
    Slider Control        滑块控件
    Spin Control        数值调节钮控件
    Progress Control        进度条控件
    List Control        高级列表控件
    Tree Control        树形控件
    Tab Control        标签控件

    7、本套课程力求:
    如何通过百度、谷歌搜索引擎找技术资料,当场演示;
    如何查看并翻译Msdn,找到对我们有用的资料;
    当场一行一行敲代码,发现问题并解决问题;
    当场调试代码,如何解决问题的,GetLastError 的使用等等;
    主要还是一些动手的细节吧,多在课堂上演示;
    多用C++本身的东西,或者 C++和 SDK Api 的东西,方便大家以后转型。








    回复


    http://www.mjgw.org/ 专业从事膜结构设计、制作加工、施工安装的膜结构工程服务,能够为客户提供专业的膜结构整体解决方案。做中国最好的膜结构综合服务平台。欢迎大家联系电话:198-7840-1958,QQ:463017170.
    相关关键词:膜结构车棚,膜结构车棚覆盖,膜结构车棚公司,膜结构车棚多少钱,膜结构车棚厂家,膜结构车棚价格,社区膜结构车棚,膜结构车棚膜布厂家 ,膜结构车棚哪家好,膜结构车棚多少钱一米,膜结构车棚报价,膜结构车棚哪里有,膜结构车棚定制,膜结构车棚安装,膜结构车棚设计,膜结构车棚电话,膜结构车棚加工,膜结构车棚膜布价格,膜结构车棚批发,膜结构车棚制造商,膜结构车棚生产厂家,膜结构车棚设计,膜结构车棚施工,膜结构车棚多少钱一平米,膜结构车棚订制,张拉膜车棚,张拉膜车棚覆盖,张拉膜车棚公司,张拉膜车棚多少钱,张拉膜车棚厂家,张拉膜车棚价格,社区张拉膜车棚,张拉膜车棚膜布厂家 ,张拉膜车棚哪家好,张拉膜车棚多少钱一米,张拉膜车棚报价,张拉膜车棚哪里有,张拉膜车棚定制,张拉膜车棚安装,张拉膜车棚设计,张拉膜车棚电话,张拉膜车棚加工,张拉膜车棚膜布价格,张拉膜车棚批发,张拉膜车棚制造商,张拉膜车棚生产厂家,张拉膜车棚设计,张拉膜车棚施工,张拉膜车棚多少钱一平米,张拉膜车棚订制,常用膜材品牌:德国杜肯、法国法拉利、德国海德斯、德国米乐、日本平岗、韩国秀博、比利时希运、美国赫虏伯、中国科宝、上海慧遥。

    使用道具 举报

  • TA的每日心情
    开心
    2021-6-19 14:40
  • 签到天数: 1539 天

    [LV.Master]伴坛终老

     楼主| 发表于 2021-2-1 16:00 | 显示全部楼层
    1、新建对话框工程:
    让我们建立一个生成EXE体积比较小的对话框工程,具体看教程讲解与演示!
    https://www.cctry.com/thread-290056-1-1.html

    2、工程中的类讲解:
    主线程类:CXXXApp
    对的画框类:CXXXDlg

    其中 XXX 一般为项目的名称,主线程类初始化函数中创建主对话框类的对象,之后对话框显示出来,就是我们见到的样子了。
    作为新手来说,我们不可能一下子把当前建立好的工程源码都看明白,先找几个主要的点,知道怎么用,比如对话框是从哪里建立起来的,对话框的初始化函数等等 就可以了,等以后功力加强了,再去理解也不迟!

    3、对话框类的初始化函数:
    BOOL CXXXDlg::OnInitDialog() 可以把一些对话框的初始化代码放在这个函数中,但要记得,一定要放在 CDialog::OnInitDialog(); 的下面!

    4、对话框模版资源:
    默认情况下:IDD_XXX_DIALOG 为主对话框资源,我们可以自定义的往界面上拖拽各种控件。具体细节见视频教程讲解与演示!
    详细讲解对话框模版的各个属性选项。

    5、都是窗口:
    我们的Windows系统为什么叫Windows呢?Window这个单词的本意是什么?是窗口,对吧,所以Windows系统中的各个大家能看到的小界面都可以看做是窗口,一个对话框是个窗口,对话框上面的按钮控件也同样可以看做个一个小窗口,针对于窗口的任何操作都适用于对话框,也适用于按钮、编辑框、下拉选择框 等等各个控件。因为他们都是窗口。所有的窗口都有个标识窗口的变量类型,叫做窗口句柄:HWND,实际上他就是个指针。不同的窗口这个值都是不一样的。以后会经常用到HWND这个类型。
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2021-6-19 14:40
  • 签到天数: 1539 天

    [LV.Master]伴坛终老

     楼主| 发表于 2021-2-1 16:00 | 显示全部楼层
    第3课:Button按钮控件

    1、按钮控件的基本使用:
    新建对话框工程,拖拽按钮控件,添加点击事件响应函数!
    a、双击模版进行添加;
    b、事件方式进行添加;

    具体细节见视频教程讲解与演示!

    2、删除按钮的点击响应函数:
    一共要删除3个地方:
    a、h头文件中的函数声明;
    b、cpp文件中的函数定义;
    c、cpp文件中的ON_BN_CLICKED宏绑定代码。

    具体细节见视频教程讲解与演示!

    3、按钮控件属性中的常用项讲解:
    Disabled、ID、Visable

    4、控件的启用与禁用:
    HWND hBtn = ::GetDlgItem(m_hWnd, IDC_BTN_1);
    ::EnableWindow(hBtn, FALSE);

    5、绑定控件类型变量:
    刚刚我们想对按钮控件启用或者禁用之前必须先获得按钮控件的窗口句柄,也就是说如果以后要对这个按钮控件进行任何操作,都得先获取他的窗口句柄,之后才能操作,也就是都得调用这句话:HWND hBtn = ::GetDlgItem(m_hWnd, IDC_BTN_1);

    比较麻烦是吧?有什么简单点的办法吗?答案是当然有了:就是绑定控件类型变量,具体绑定操作过程详见视频演示!
    按钮控件在MFC中的关联类是:CButton

    这样以后要进行按钮的禁用直接调用这句就可以了:
    ::EnableWindow(m_Btn.m_hWnd, FALSE);
    或者
    m_Btn.EnableWindow(FALSE);

    6、控件的美化:
    本身Windows自带的按钮控件就很普通,也不是很丑,但如果大家都一样就没什么意思了,况且有部分界面漂亮的软件放个普通的按钮在上面也显得不搭。所以很多人想着美化下控件。
    微软也提供给我们控件的美化接口,那就是自绘,就是自己完全重新绘制控件的样子。其实控件的重绘是件非常麻烦的事情,类似按钮的倒还好,如果是类似列表控件那就更麻烦了。所以对于新手而言,或者说对于我们这种个人开发者没必要自己去从头重绘,如果是为了学习重绘的技术或者一款企业级的产品,那倒是可以使用重绘的方式来美化控件。而且这个美化控件这个东西一般都要有漂亮的图片为基础,所以有个会PS的同伴会比较好。

    如果不想这么麻烦的重绘控件,还想要有效果的按钮控件怎么办?答案是:站在巨人的肩膀上,用现成的呗。肯定有高手事先都做好了,咱们直接拿过来用就可以了。具体我们可以在 codeproject 上面找开源的控件类,一般这些开源的控件类都是基于MFC中已有的各种控件的类,比如按钮的就是 CButton 的派生类,美化后的按钮效果如图
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2021-6-19 14:40
  • 签到天数: 1539 天

    [LV.Master]伴坛终老

     楼主| 发表于 2021-2-1 16:01 | 显示全部楼层
    第4课:单选框与复选框控件

    1、单选框控件的基本使用:

    a、要求一组内的单选框按钮控件ID必须由小到大排列,中间不能夹杂其他组的单选框按钮;
    b、若有多组,则组内第一个单选框按钮的Group属性为True,其他为False;
    c、选中组内某个单选框按钮:CheckRadioButton(IDC_RADIO1, IDC_RADIO3, IDC_RADIO2);
    d、获得当前当前选中的单选框按钮控件:int nCheckId = GetCheckedRadioButton(IDC_RADIO1, IDC_RADIO3);

    具体操作见视频教程讲解与演示!

    2、复选框控件的基本使用:

    a、勾选复选框控件:
    ::SendMessage(::GetDlgItem(m_hWnd, IDC_CHECK1), BM_SETCHECK, BST_CHECKED, 0);
    GetDlgItem(IDC_CHECK1)->SendMessage(BM_SETCHECK, BST_CHECKED, 0);
    m_Check.SetCheck(BST_CHECKED);
    三种方法任意一种都可以!

    备注:取消勾选的话只需要把 BST_CHECKED 改成 BST_UNCHECKED 就可以了!

    b、获取复选框的勾选状态:
    UINT nCheckState = ::SendMessage(::GetDlgItem(m_hWnd, IDC_CHECK1), BM_GETCHECK, 0, 0);
    nCheckState = GetDlgItem(IDC_CHECK1)->SendMessage(BM_GETCHECK, 0, 0);
    nCheckState = m_Check.GetCheck();
    三种方法任意一种都可以!

    如果返回值 nCheckState 的值为 BST_CHECKED,那么就是勾选状态。如果值为 BST_UNCHECKED,那么就是非勾选状态。
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2021-6-19 14:40
  • 签到天数: 1539 天

    [LV.Master]伴坛终老

     楼主| 发表于 2021-2-1 16:01 | 显示全部楼层
    第5课:Edit编辑框控件

    1、设置编辑框控件内的文本内容:
    任意一种方法都可以实现。

    2、获取编辑框控件内的文本内容:
    任意一种方法都可以实现。

    3、编辑框控件的属性介绍:
    a、让编辑框文本为只读模式;
    b、让编辑框文本为密码模式;
    d、让编辑框支持多行显示,即:自动换行;
    e、让编辑框显示滚动条;
    f、让编辑框只能接受数字输入;
    g、让编辑框只能输入指定范围的数组;
    h、如果还有其他方面的限制要求,那只能是利用接下来要讲解的事件通知的方式来处理了。

    4、事件通知:
    a、当编辑框内的文本内容发生变化时通知我,响应 EN_CHANGE 事件;

    5、向编辑框的结尾增加数据:

    6、始终显示最新的数据(光标定位到文本结尾):
    m_Edit.SetFocus();
    m_Edit.SetSel(-1);
    复制代码


    7、编辑框控件的长度限制:
    默认情况下编辑框控件的文本长度有限制,大家可以调用这个函数获取一下:
    UINT nLimitLen = m_Edit.GetLimitText();
    看到多少了吧?要解除这个限制呢,或者改成更大一些?
    m_Edit.SetLimitText(0);

    8、小作业:
    只读属性的编辑框是灰色的,如何搞成是只读但不是灰色的呢?
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2021-6-19 14:40
  • 签到天数: 1539 天

    [LV.Master]伴坛终老

     楼主| 发表于 2021-2-1 16:02 | 显示全部楼层
    第6课:ComboBox下拉框控件

    1、向下拉框控件添加数据:
    a、通过Data属性添加,以分号间隔;
    b、向下拉框的结尾添加数据:

    添加完成后,大家发现点什么问题没有?数据的顺序并不是我们添加时候的顺序,不是逐一往尾部添加吗,为什么顺序不对呢?
    答案是:调整下控件的 Sort 自动排序属性就可以了。

    c、自定义位置插入数据:

    这种插入方式不受 Sort 属性的影响,但是需要提供插入的索引位置。

    2、从下拉框删除数据:
    m_ComboBox.DeleteString(0);    //删除指定索引的数据
    m_ComboBox.ResetContent();    //删除全部数据
    复制代码


    3、设置下拉框选中某条数据:
    m_ComboBox.SetCurSel(1);
    复制代码

    参数传递要设置的索引序号,如果不想选中任何一条,那么就传递 -1.

    4、获得下拉框当前选中的是哪条数据:
    int idx = m_ComboBox.GetCurSel();
    复制代码

    返回以0开始的选中的数据索引,如果没选中任何一条数据,则返回 -1.

    5、获得指定数据的字符串内容:
    TCHAR szText[100] = { 0 };
    m_ComboBox.GetLBText(idx, szText);
    复制代码

    这样就知道选中的是哪个了,不然告诉你 0,1,2,你怎么知道是什么!

    6、下拉控件的类型:
    Dropdown:可以从下拉列表中选择一项,也可以自己输入;
    Drop List:只能从下拉列表中选择一项,不能修改。

    7、控制下拉列表的高度:
    a、控件模版中,点击一下 ComboBox 的下拉箭头,此时出现的调整框就是 ComboBox 的下拉框的高度;
    b、控件属性中有个 No Integral Height 选项,表示最大高度为设计长度,如果实际内容比设计长度多,就出现滚动条,少就以实际长度显示。
    可以将该选项设置为默认的FALSE,即表示最大高度不是设计的高度,而是根据实际内容的高度来决定。

    8、下拉框选择改变事件:
    响应 CBN_SELCHANGE 事件,在其响应函数中判断当前选中的是哪个!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2021-6-19 14:40
  • 签到天数: 1539 天

    [LV.Master]伴坛终老

     楼主| 发表于 2021-2-1 16:02 | 显示全部楼层
    第7课:ListBox 列表控件

    1、向列表框控件添加数据:
    a、向列表框的结尾添加数据:

    跟下拉框控件一样,添加完成后,数据的顺序并不是我们添加时候的顺序,调整下控件的 Sort 自动排序属性就可以了。

    b、自定义位置插入数据:
    这种插入方式不受 Sort 属性的影响,但是需要提供插入的索引位置。

    2、获得列表框中总共有多少条目:
    int nCount = m_ListBox.GetCount();
    复制代码


    3、从列表框删除数据:
    m_ListBox.DeleteString(0);    //删除指定索引的数据
    m_ListBox.ResetContent();    //删除全部数据
    复制代码


    4、设置列表框选中某条数据:
    m_ListBox.SetCurSel(1);
    复制代码

    参数传递要设置的索引序号,如果不想选中任何一条,那么就传递 -1.

    5、获得列表框当前选中的是哪条数据:
    int idx =m_ListBox.GetCurSel();
    复制代码

    返回以0开始的选中的数据索引,如果没选中任何一条数据,则返回 -1.

    6、列表框的多选模式:
    刚才给大家讲解的 SetCurSel 和 GetCurSel 都是针对列表框的单选模式进行的,大家在使用其他软件的时候也注意过有的列表框控件是支持多选的,还支持 Ctrl、Shift 键快捷操作,那么应该怎么做呢?
    答案是:控件的 Selection 属性进行修改。默认是 Single,也就是单选。我们可以改成 Multiple、Extended,都是多选的意思。其中 Extended 支持 Ctrl、Shift 键操作。None:选中item,但是不高亮,只显示该item上交点(item外有矩形框)。

    a、多选模式下的选中操作:
    b、多选模式下的获取选中操作:
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2021-6-19 14:40
  • 签到天数: 1539 天

    [LV.Master]伴坛终老

     楼主| 发表于 2021-2-1 16:03 | 显示全部楼层
    第8课:GroupBox 分组控件

    其实这个控件没什么可讲的,拖拽到界面上之后,对其他各个控件进行分组用的。
    本身默认的控件ID就是 IDC_STATIC,所以没什么过多的属性可设置。那么既然没什么可讲的为什么我们还要单独出一课教程来讲解呢?
    这里我告诉大家实际上 GroupBox 控件也可以玩出花样的,例如下面的截图大家可以看看:
    https://www.codeproject.com/Articles/7063/CGroupCheckBox-control


    https://www.codeproject.com/Arti ... rol-to-display-text


    那么类似这样的 GroupBox 控件 是如何做到的呢?codeproject 上面默认的地方也找不到关于 groupbox 的资料啊!
    我们要如何通过关键字搜索来找资料呢?接下来给大家演示下!
    其实很多时候,同样是用百度,同样是用谷歌,不同的搜索方法,不同的关键词,找到的结果往往有很大的区别
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2021-6-19 14:40
  • 签到天数: 1539 天

    [LV.Master]伴坛终老

     楼主| 发表于 2021-2-1 16:03 | 显示全部楼层
    第9课:StaticText静态文本框控件

    跟 GroupBox 控件类似,静态文本框控件的ID也是 IDC_STATIC,所以默认的情况下他也是没有什么属性可修改的,拖拽到对话框上面之后,只是作为默认的显示提示文本信息的作用了。
    那么这个控件可不可以自定义呢?可不可以玩出点花样呢?答案是当然可以了,其实关于这个控件还是有点需求的,比如在界面上显示一个类似URL的网址链接,点击就启动默认的浏览器访问网页的,或者默认的字体,默认的颜色发生变化的,等等吧,还是有不少自定义的需求的,例如,如下的截图:
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2021-6-19 14:40
  • 签到天数: 1539 天

    [LV.Master]伴坛终老

     楼主| 发表于 2021-2-1 16:04 | 显示全部楼层
    第10课:Picture图像控件

    Picture图像控件顾名思义,是用来显示图片用的,那么很多新手学员在拖拽了一个Picture控件到对话框界面上之后不知道怎么使用了。接下来就给大家介绍一下!


    1、Picture控件加载静态BMP图片资源:
    a、向工程中插入一个BMP类型的图片资源,例如,ID为:IDC_BITMAP1
    b、在Picture控件的Type属性下拉框中选择Bitmap;
    c、在Picture控件的Image属性下拉框中选择BMP资源ID为IDC_BITMAP1即可。

    Type属性下拉列表中有8种类型,下面分别介绍下:
    Frame:显示一个无填充的矩形框,边框颜色可以通过Color属性的下拉列表设定
    Etched Horz:显示一条横分割线
    Etched Vert:显示一条竖分割线
    Rectangle:显示一个填充的矩形框,矩形颜色可通过Color属性的下拉列表设定
    Icon:显示一个图标(Icon),图标通过Image下拉列表来设置图标资源ID
    Bitmap:显示一个位图(Bitmap),位图通过Image下拉列表来设置位图资源ID
    Enhanced Metafile:显示一个加强的元数据文件(Metafile)
    Owner Draw:自绘

    2、Picture控件通过代码的方式动态加载BMP图片资源:
    3、Picture控件加载磁盘上面的BMP图片:

    分析:
    加载的图片在当前EXE的模块外
    可以指定图片大小,如上图中的50, 50,若实际大小和此不相符,会自动缩放图片
    LR_DEFAULTCOLOR — 指定按照原图的颜色加载图片,不可少
    LR_LOADFROMFILE — 加载外部的Bitmap,一定要指定
    LR_CREATEDIBSECTION — 一般会指定
    如若按照图片本身的大小加载,则设置cx,cy为0,0,并且在最后的标志位加上|LR_DEFAULTSIZE
    注意:从网上下载的Bitmap图片可能用上面的方法加载失败,返回的HBITMAP为NULL,GetLastError()返回0,这个一般是图片格式的问题,可以用Windows的画图程序打开Bitmap再另存为24位位图的bmp格式就可以了。

    4、Picture控件加载 png、jpg 等常用格式图片:
    默认情况下,Picture控件只能显示BMP类型的图像,因为BMP文件格式是微软自家的。但是bmp这个确实不是很常用,或者说针对 png、jpg、gif 等文件类型来说 bmp 不常用。那么Picture控件如何来显示我们常用的 png、jpg 等图像格式呢?这里要借助微软的ATL中的一个类:CImage(VC6用不了,VC6可以考虑使用开源的 CxImage)
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2021-6-19 14:40
  • 签到天数: 1539 天

    [LV.Master]伴坛终老

     楼主| 发表于 2021-2-1 16:05 | 显示全部楼层
    第11课:Spin数值调节控件

    1、控件简介:
    Spin数值调节控件也是Windows中比较常用的控件之一。样子上是一对上下的箭头按钮,用户可单击它来增加或减少控件的设定值。通常,紧靠着Spin数值调节控件有一个编辑框控件,称为伙伴编辑控件或伙伴控件,用于显示用户输出的值。例如这个帖子中的样式,大家看下:https://www.cctry.com/thread-9450-1-1.html


    接下来教大家怎么用!

    2、控件的使用:
    a、分别拖拽一个Spin数值调节控件和一个编辑框控件到对话框界面上,挨着摆放;
    b、设置Spin数值调节控件的属性如下:
            Set Buddy Interger(使控件设置关联控件数值,这个值可以是十进制或十六进制) - True
            Wrap(数值超过范围时循环) - True
            Arrow keys(当按下向上和向下方向键时,控件可以增加或减小) - True
            Alignlent - Right Alient    //右侧嵌入到编辑框中

    c、给Spin数值调节控件绑定一个 CSpinButtonCtrl 类型的控件类型变量 m_Spin;
    d、在对话框的初始化函数 BOOL CMFCTestDlg::OnInitDialog() 中设置 Spin数值调节控件:

    3、控件的美化与扩展:
    说实话,美化方面关于这个控件还真没什么,codeproject上面也没几个关于这个控件的类,所以本身也不需要什么美化
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2021-6-19 14:40
  • 签到天数: 1539 天

    [LV.Master]伴坛终老

     楼主| 发表于 2021-2-1 16:05 | 显示全部楼层
    第12课:Slider滑块控件

    1、控件简介:
    Slider滑块控件,也是VC中比较常用的一个控件。一般而言它是由一个滑动条,一个滑块和可选的刻度组成。用户可以通过移动滑块在相应的控件中显示对应的值。
    通常,在滑动控件附近一定有静态文本框控件或编辑框控件,用于显示相应的值。


    接下来教大家如何使用这个控件!

    2、控件的使用:
    a、拖拽Slider滑块控件到对话框界面上,调整其大小!
    b、给Slider控件绑定一个CSliderCtrl类型的控件类型变量 m_Slider;
    c、Slider控件属性中的

    Tick Marks 为是否显示刻度线
    Auto Ticks 是否显示每个增量的刻度线
    大家可以根据自己的需要来设定!

    3、控件的相关操作:
    a、设置滑动范围:m_Slider.SetRange(0, 100);
    b、设置当前位置:m_Slider.SetPos(50);
    c、获取当前位置:int pos = m_Slider.GetPos();
    d、获取和设置按一下左或右箭头时滑块的移动量,默认为1个单位:
        int ret = m_Slider.SetLineSize(1);
        ret = m_Slider.GetLineSize();
    复制代码


    e、获取和设置当按下PgUp或PgDown时滑块的移动量:
        ret = m_Slider.SetPageSize(10);
        ret = m_Slider.GetPageSize();
    复制代码


    4、关联显示控件:
    响应Slider控件的 NM_CUSTOMDRAW 事件,在其中获取Slider控件的滑块位置,之后设置到静态文本框上面:
        int pos = m_Slider.GetPos();
        CString strText;
        strText.Format(_T("%d"), pos);
        SetDlgItemText(IDC_STATIC_SLIDER, strText);
    复制代码


    5、Slider滑块控件的扩展与美化:
    在codeproject上面找到了不少不错的Slider控件,给大家列出来,大家看看有没有需要的?
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2021-6-19 14:40
  • 签到天数: 1539 天

    [LV.Master]伴坛终老

     楼主| 发表于 2021-2-1 16:05 | 显示全部楼层
    第13课:Progress进度条控件

    1、控件简介:
    Progress进度条控件,也是VC中很常用的一个控件。Slider滑块控件用于控制数值的多少,而Progress进度条控件一般用于显示当前进度的多少,用来展示用的。跟Slider滑块控件相比一个用于输出,一个用于输入。


    接下来教大家如何使用这个控件!

    2、控件的使用:
    a、拖拽Progress进度条控件到对话框界面上,调整其大小!
    b、给Progress进度条控件绑定一个CProgressCtrl类型的控件类型变量m_ProgressCtrl;
    c、Progress控件属性中的选项:
    大家可以根据自己的需要来设定!


    3、控件的相关操作:
    a、设置滑动范围:m_ProgressCtrl.SetRange32(0, 100);
    b、设置每次步进的长度:m_ProgressCtrl.SetStep(1);
    c、设置当前位置:m_ProgressCtrl.SetPos(50);
    d、获取当前位置:int pos =m_ProgressCtrl.GetPos();
    e、让进度条控件步进一次:m_ProgressCtrl.StepIt();

    4、利用定时器让进度条控件动起来:
    a、为对话框类添加 WM_TIMER 定时器消息的响应函数;
    b、在响应函数中添加:m_ProgressCtrl.StepIt(); 步进;
    c、在对话框的初始化函数中启动定时器:SetTimer(1, 500, NULL); //500ms 执行一次

    5、小作业:
    大家看到现象了吧?进度条控件不停的往前走,当走到100%的时候,再从0开始。那么本次的作业就是如何让进度条控件走到100%之后不再从头开始走了,就保持100%的状态。大家试试吧!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2021-6-19 14:40
  • 签到天数: 1539 天

    [LV.Master]伴坛终老

     楼主| 发表于 2021-2-1 16:06 | 显示全部楼层
    第14课:Tab标签控件

    1、控件简介:
    一个对话框界面的空间有限,如果需要放置很多控件的话恐怕摆不下而且也比较乱,这时候就可以使用 TabCtrl 标签页控件了。每个标签页下都可以作为一个单独的页面,对控件进行分组摆放。TabCtrl 控件也是其他很多软件经常用的一个控件。

    2、控件类的封装:
    正常来说Tab标签控件使用起来还是有点麻烦的,比如我们通过搜索几篇文章来看下:关键字:VC tab控件 使用
    实际上TabCtrl标签页控件这东西就是用了一个障眼法,控件只是控件,只是进行切换用的,真正每个页面的东西是需要我们自己手动添加对话框资源来进行的。当点击标签页进行切换的时候,我们要用代码控制每个页面对话框的显示与隐藏。

    大家看到了吧,又得创建子对话框,又得调整子对话框的坐标,每次切换标签的时候又得进行显示与隐藏,所以挺麻烦的。那么有什么简单的办法吗?答案就是封装啊!
    这里我找到了好多年前我封装的一个Tab控件类,派生自 CTabCtrl,这几天我又针对已有代码优化了一下,拿出来与大家分享,这样封装完之后使用起来就简单很多了,接下来就教大家如何使用!

    3、控件的使用:
    a、将 TabSheet.h 和 TabSheet.cpp 这两个文件放到 MFCTest 工程目录下,并导入到vs工程中;
    b、拖拽Tab控件到对话框模版上;
    c、为Tab控件绑定一个 CTabCtrl 控件类型变量m_Tab;
    d、对话框类头文件中的 CTabCtrl m_Tab; 声明更改为:CTabSheet m_Tab; 即更改控件变量的类型,如果编译不通过,需要包含 TabSheet.h;
    e、添加一个对话框资源作为第一子页,并绑定派生自 CDialog 的子对话框类:CPage1;
    f、修改 CPage1 的对话框资源属性:Border:None,Style:Child
    g、在主对话框类声明中加入第一子页的实例化对象:CPage1 m_page_1;
    h、在主对话框的初始化函数中加入加载子页的代码:
        m_Tab.AddPage(_T("第一页"), &m_page_1, IDD_DIALOG1);
        m_Tab.Show();
    i、添加第二个子页,以此类推!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2021-6-19 14:40
  • 签到天数: 1539 天

    [LV.Master]伴坛终老

     楼主| 发表于 2021-2-1 16:07 | 显示全部楼层
    第15课:Tree树形控件

    1、控件简介:
    Tree树形控件也是我们编程过程中比较常用的一个控件,而且在其他软件中也经常能看到,比如Windows系统中的资源管理器:


    所以,接下来我就教大家如何来使用这个控件!

    2、控件的使用:
    a、拖拽Tree树形控件到对话框模版上;
    b、一些常用的属性:
    Check Boxes:结点前是否带有复选框;
    Edit Labels:结点名字是否可编辑;
    Has Buttons:父节点是否有+号可供展开;
    Has Lines:父子结点之间是否有连接线;
    Lines At Root:是否从根节点开始就带有虚线;
    等等吧,大家可以根据自己的需要设置相关的属性。

    c、为Tree树形控件绑定一个 CTreeCtrl 控件类型变量m_Tree;

    3、控件的操作:
    在树形控件中每一个结点都有一个句柄(HTREEITEM),同时插入结点时必须提供父结点句柄,(其中根Root结点只有一个,既不可以添加也不可以删除)利用
    HTREEITEM InsertItem( LPCTSTR lpszItem, HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter = TVI_LAST );
    可以插入一个结点,pszItem为显示的字符,hParent代表父结点的句柄,当前添加的结点会排在hInsertAfter表示的结点的后面,返回值为当前创建的结点的句柄。

    a、添加结点(有多种重载方式,先介绍第一种):
        HTREEITEM hRoot = m_Tree.InsertItem(_T("父1"));
        HTREEITEM hSub1 = m_Tree.InsertItem(_T("子1"), hRoot);
        HTREEITEM hSub2 = m_Tree.InsertItem(_T("子2"), hRoot);

        HTREEITEM hSub3 = m_Tree.InsertItem(_T("子子1"), hSub2);
    复制代码



    就这样,可以一层一层的向树形控件中插入节点。

    b、获得节点的文本:m_Tree.GetItemText(hSub3);
    c、设置节点的文本:m_Tree.SetItemText(hSub3, _T("abc"));

    d、获得当前选中的节点:HTREEITEM hSelItem = m_Tree.GetSelectedItem();
    e、设置当前选中的节点:m_Tree.SelectItem(hTreeItem);
    f、默认上面的情况都是针对单选,那么Tree树形控件支不支持多选呢?答案是:默认不支持
    不过可以通过给节点前面加上 CheckBox 复选框来解决!下个知识点举例讲解!
    备注:那么不通过CheckBox 能不能实现多选呢?答案也是可以的,不过要写很多自定义代码,大家感兴趣的话可以看看这几篇文章,课堂上咱们就不讲解了:
    http://www.codeguru.com/cpp/cont ... d/article.php/c629/
    http://www.codeguru.com/cpp/cont ... d/article.php/c723/
    http://www.codeguru.com/cpp/cont ... /article.php/c9219/

    g、遍历子节点:
    需要用到的相关函数:
    HTREEITEM GetRootItem( ); //得到根结点。
    HTREEITEM GetChildItem(HTREEITEM hItem); //得到子结点。
    HTREEITEM GetPrevSiblingItem/GetNextSiblingItem(HTREEITEM hItem); //得到指明结点的上/下一个兄弟结点。
    HTREEITEM GetParentItem(HTREEITEM hItem); //得到父结点。
    复制代码



    从根节点开始遍历所有节点,判断 CheckBox 是否勾选:

    h、删除节点、删除所有节点:
    m_Tree.DeleteItem(hSub2); //删除节点
    m_Tree.DeleteAllItems();    //删除所有节点
    复制代码


    i:展开/收起所有节点:

    j:编辑节点文本:
    ①、控件的 Edit Labels 属性设置为 True;
    ②、响应控件的 TVN_BEGINLABELEDIT 事件:
    ③、响应控件的 TVN_ENDLABELEDIT 事件:

    k、插入带图标的节点:
    这里面给大家准备几个ico图标,供程序使用,见附件!

    ①、将几个ico图标文件添加到工程资源中,ID分别为:IDI_ICON1、IDI_ICON2、IDI_ICON3
    ②、在对话框类类的头文件中加入对象声明:CImageList m_TreeImage;
    ③、在对话框的初始化函数中创建图像列表:BOOL bRet = m_TreeImage.Create(16, 16, ILC_MASK | ILC_COLOR32, 1, 1);
    ④、添加图标资源到图像列表:
    ⑤、关联Tree树形控件和图像列表:m_Tree.SetImageList(&m_TreeImage, TVSIL_NORMAL);
    ⑥、将InsertItem插入节点的代码进行修改:


    这样就可以啦~!

    其中 InsertItem 的第二个参数0和第三个参数1是ico图标在ImageList中的索引,第二个参数是节点默认的图标,第三个参数是节点被选中后的图标。

    4、开源控件类:
    codeproject 上面关于 Tree树形控件 的开源控件类可谓是很多啊,这里面给大家分享一下,需要哪种自己直接拿过去用就行了:
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2021-6-19 14:40
  • 签到天数: 1539 天

    [LV.Master]伴坛终老

     楼主| 发表于 2021-2-1 16:07 | 显示全部楼层
    第16课:ListCtrl高级列表控件

    1、控件简介:
    ListCtrl 高级列表控件也是我们平时编程过程中很常用的一个控件,一般涉及到报表展示、记录展示之类的,都需要ListCtrl 高级列表控件。例如:任务管理器啊,文件列表啊,等等都是ListCtrl 高级列表控件来实现的。

    2、控件的风格样式:
    LVS_ICON: 为每个item显示大图标
    LVS_SMALLICON: 为每个item显示小图标
    LVS_LIST: 显示一列带有小图标的item
    LVS_REPORT: 显示item详细资料

    直观的理解:Windows资源管理器,“查看” 标签下的 “大图标,小图标,列表,详细资料”
    具体可以通过代码指定控件的风格样式,也可以方便点,从控件的属性中直接修改:
    对应控件的 View 属性:Icon、Small Icon、List、Report 四项。





    大家看到了吧,主要就是针对这四种风格样式!
    比较常用的还是第四种:报表样式!

    3、动态设定 ListCtrl 的风格样式:
    ①、拖动ListCtrl控件到对话框界面上面;
    ②、绑定CListCtrl类型的控件类型变量:m_List;
    ③、样式设定:

    我们教程中重点讲解 LVS_REPORT 报表样式的 ListCtrl,其他风格,大家课后自行研究吧,网上也有不少这方面的文章!

    4、动态设定 ListCtrl 的扩展风格:


    5、插入列信息:
    使用 InsertColumn 插入列信息:


    InsertColumn 各个参数的讲解,详见视频教程!

    6、插入行信息:


    InsertItem 各个参数的讲解,详见视频教程!

    7、设置行文本信息:


    8、选中和取消选中一行:
    9、遍历控件的所有行条目:
    10、遍历获得当前选中的行:

    大家课后找资料,看看如何能根据第9点的遍历方式,获得当前选中的行号!

    11、遍历获得当前CheckBox选中的行:
    12、删除行:
    删除指定的行:m_List.DeleteItem(1);
    删除所有的行:m_List.DeleteAllItems();
    大家课后试试:如果我想删除列表控件中索引为0和2的行,怎么删除呢?大家试试
    用for循环的话,如何来写代码呢?大家课后试试!

    13、编辑指定的行文本:(其实这个跟之前讲解的TreeCtrl很像)
    ①、将ListCtrl控件的 Edit Labels 设置为 True;
    ②、响应ListCtrl控件的 LVN_BEGINLABELEDIT 和 LVN_ENDLABELEDIT
    ③、在 LVN_ENDLABELEDIT 响应函数中加入:
    NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);
    m_List.SetItemText(pDispInfo->item.iItem, pDispInfo->item.iSubItem, pDispInfo->item.pszText);
    备注:这里只能编辑(索引为0的)第1列的文本,其他列的没办法编辑,要想编辑也不是不能,就得自己来搞了!
    其实有很多写好的开源控件类,大家直接拿过来用就可以了,多了很多功能。

    14、插入图标:跟树形控件 TreeCtrl 的用法基本一致,算是给大家留一个小作业了,自己搞定吧!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2021-6-19 14:40
  • 签到天数: 1539 天

    [LV.Master]伴坛终老

     楼主| 发表于 2021-2-1 16:14 | 显示全部楼层
    MFC CComboBox 的Owner Draw属性

    当中的Fixed和Variable有什么区别
    Fixed:创建一个自制组合框,其中的项目具有相同的高度;
    Variable:创建一个自制组合框,其中的项目高度不同
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2021-6-19 14:40
  • 签到天数: 1539 天

    [LV.Master]伴坛终老

     楼主| 发表于 2021-2-1 16:16 | 显示全部楼层
    知识点:
    Picture Control 控件属性
    CStatic类
    图片控件
    图片控件使用

    一、图片控件属性
    Picture Control 属性:
    Type:Frame //框架
    Type:Etched Horz水平蚀刻线条
    Type:Etched Vert垂真蚀刻线条
    Type:Rectangle实心矩形
    Type:Bitmap位图
    Type:Icon  图标
    Type:Enhanced Metafile 增强图元 支持wmf格式图片
    Type:Owner Draw   自绘图
    Color:颜色
        Black:黑
        Gray:灰色
        White:白色
        Etched:蚀刻

    二、Picture Control 控件类
    CStatic::
    SetBitmap
    Specifies a bitmap to be displayed in the static control.
    GetBitmap
    Retrieves the handle of the bitmap previously set with SetBitmap.

    SetIcon
    Specifies an icon to be displayed in the static control.
    GetIcon
    Retrieves the handle of the icon previously set with SetIcon.

    SetCursor
    Specifies a cursor image to be displayed in the static control.
    GetCursor
    Retrieves the handle of the cursor image previously set with SetCursor.

    SetEnhMetaFile
    Specifies an enhanced metafile to be displayed in the static control.
    GetEnhMetaFile
    Retrieves the handle of the enhanced metafile previously set with SetEnhMetaFile
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2021-6-19 14:40
  • 签到天数: 1539 天

    [LV.Master]伴坛终老

     楼主| 发表于 2021-2-1 16:18 | 显示全部楼层
    MFC在Picture控件上显示图像、保存图像

    //选择图片
        CFileDialog fileDlg(TRUE, _T("png"), NULL, 0, _T("image Files(*.bmp; *.jpg;*.png)|*.JPG;*.PNG;*.BMP|All Files (*.*) |*.*||"), this);
        //打开文件选择窗体
        if (fileDlg.DoModal() == IDCANCEL) return; //如果点击“取消”按钮,直接退出
        //获取图片路径(包含名称)
        CString strFilePath = fileDlg.GetPathName();//既有路径又有文件名,如D:/lena.jpg
        //CString strFileName = fileDlg.GetFileName();//只获取文件名,如lena.jpg
        //判断路径不为空
        if (strFilePath == _T(""))
        {
            return;
        }
        //使用CImage的Load、Draw函数显示图像
        CImage image;
        image.Load(strFilePath);

        //int x = image.GetWidth(); //学习下CImage的属性,无其他意义
        //int y = image.GetHeight();

        //获取控件的矩形
        CRect rectControl;  //控件矩形对象
        CWnd  *pWnd = GetDlgItem(IDC_IMAGE); //Picture Control的ID为IDC_IMAGE
        pWnd->GetClientRect(&rectControl);

        //以控件为画布,在其上画图
        CDC *pDc = GetDlgItem(IDC_IMAGE)->GetDC();
        SetStretchBltMode(pDc->m_hDC, STRETCH_HALFTONE);//绘图前必须调用此函数(设置缩放模式),否则失真严重

        //画图(以下两种方法都可)
        //image.StretchBlt(pDc->m_hDC, rectPicture, SRCCOPY); //将图片绘制到Picture控件表示的矩形区域
        image.Draw(pDc->m_hDC, rectControl);                //将图片绘制到Picture控件表示的矩形区域

        image.Destroy();
        pWnd->ReleaseDC(pDc);




    // **************** 获取图片
        CFileDialog fileDlg(TRUE, _T("bmp"), NULL, 0, _T("image Files(*.bmp; *.jpg;*.png)|*.JPG;*.PNG;*.BMP|All Files (*.*) |*.*||"), this);
        fileDlg.DoModal();
        //获取图片路径和图片名称
        CString strFilePath = fileDlg.GetPathName(); //"D:\1.jpg"
        //CString strFileName = fileDlg.GetFileName(); //"1.jpg"
        //判断路径是否为空
        if (strFilePath == _T(""))
        {
            return;
        }
        //CImage image; //使用图片类,已放到头文件中(全局变量)
        if(!image.IsNull())
            image.Destroy(); //如果已有,先清空。否则重新加载会报错。
        image.Load(strFilePath); //装载路径下图片信息到图片类
        //******************* 图片缩放适应控件大小
        CRect rectControl;                        //控件矩形对象   
        m_PictureControl.GetClientRect(&rectControl);//控件区域
        //图片不缩放
        //int imageWidth = image.GetWidth();
        //int imageHeight = image.GetHeight();
        //rectControl = CRect(rectControl.TopLeft(), CSize(imageWidth, imageHeight)); //显示未缩放原图,超出控件区域不显示
       
        //显示
        CDC *pDc = m_PictureControl.GetWindowDC();//获得显示控件的DC
        SetStretchBltMode(pDc->m_hDC, STRETCH_HALFTONE); //设置缩放,否则图片显示会失真
        image.Draw(pDc->m_hDC, rectControl);   //将图片绘制到Picture控件表示的矩形区域

        //释放资源
        ReleaseDC(pDc);


    if (image.IsNull())
        {
            MessageBox(_T("你还没有打开一个要保存的图像文件!"));
            return;
        }
        CString strFilter;
        strFilter = _T("位图文件|*.bmp|JPEG 图像文件|*.jpg|PNG 图像文件|*.png||");
        CFileDialog dlg(FALSE,_T("bmp"),_T("untitled.bmp"),NULL,strFilter);
        if ( IDOK != dlg.DoModal())
            return;
       
        // 文件名
        CString strFileName;
        strFileName = dlg.m_ofn.lpstrFile;// 如"D:\1.jpg"

        // 图像保存
        HRESULT hResult = image.Save(strFileName);
        if (FAILED(hResult))
            MessageBox(_T("保存图像文件失败!"));
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2021-6-19 14:40
  • 签到天数: 1539 天

    [LV.Master]伴坛终老

     楼主| 发表于 2021-2-1 16:32 | 显示全部楼层
    void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)
    {
            //MessageBox(L"Button Clicked !");  //unicode
            //MessageBox("Button Clicked !");     //使用多字节

            m_ptOrign=point;
            m_ptOld=point;
            m_bDraw=true;
            CView::OnLButtonDown(nFlags, point);
    }


    void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
    {
            获得窗口的设备描述表
            /*HDC hdc;
            hdc=::GetDC(m_hWnd);
            MoveToEx(hdc,m_ptOrign.x,m_ptOrign.y,NULL);
            LineTo(hdc,point.x,point.y);
            ::ReleaseDC(m_hWnd,hdc);*/
            //使用CDC类
            /*CDC *pDC=GetDC();
            pDC->MoveTo(m_ptOrign);
            pDC->LineTo(point);
            ReleaseDC(pDC);*/

            //使用画笔、画刷
            /*CPen pen(PS_SOLID,1,RGB(234,23,53));
            //定义一个CPen类对象,并利用RGB宏改变其颜色
            CClientDC dc(this);
            CPen *pOldPen=dc.SelectObject(&pen); //将其选入设备表
            dc.MoveTo(m_ptOrign);
            dc.LineTo(point);
            dc.SelectObject(pOldPen); */
            /
            /*CBrush brush(RGB(0,255,0));
            CClientDC dc(this);
            CRect rect(m_ptOrign,point);
            //dc.FillRect(&rect,&brush);
            dc.SelectObject(&brush);
            dc.Rectangle(m_ptOrign.x,m_ptOrign.y,point.x,point.y);
            */
            m_ptEnd=point;
            m_bDraw=false;

            CView::OnLButtonUp(nFlags, point);
    }


    void CDrawView::OnMouseMove(UINT nFlags, CPoint point)
    {
            /*CClientDC dc(this);
            CPen pen(PS_SOLID,1,RGB(255,0,0));
            CPen *poldPen=dc.SelectObject(&pen); //将其选入设备表
            //if (m_bDraw==TRUE)
            //{
            //        dc.MoveTo(m_ptOrign);
            //        dc.LineTo(point);
            //        //m_ptOrign=point;  //注释掉就变成扇形曲线       
            //}
            if (m_bDraw==TRUE)      //带外包线的扇形
            {
                    dc.MoveTo(m_ptOrign);
                    dc.LineTo(m_ptOld);
                    dc.MoveTo(m_ptOld);
                    dc.LineTo(point);
                    m_ptOld=point;
            }*/

            //画无边框矩形,利用FillRect函数填充矩形。填充内容为画刷的内容,即画刷对象的指针。
            /*CClientDC dc(this);
            CBrush brush(RGB(5,255,255));
            dc.FillRect(CRect(m_ptOrign,point),&brush);*/

            //以位图作为画刷的资源
            /*CClientDC dc(this);
            CBitmap bitmap;
            bitmap.LoadBitmap(IDB_FILE_VIEW);
            CBrush brush(&bitmap);
            dc.FillRect(CRect(m_ptOrign,point),&brush);*/

            //画有边框的矩形,方法说明:利用Rectangle方法来画矩形。其中CBrush与CPen类分别负责矩形内部和矩形边框的属性
            //画中心为白色的矩形
            /*CClientDC dc(this);
            //dc.Rectangle(CRect(m_ptOrign,point));
            dc.Rectangle(m_ptOrign.x,m_ptOrign.y,point.x,point.y);
            */

            //画中心为透明的矩形
            /*CClientDC dc(this);
            CBrush *pbrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
            CBrush *pOldbrush=dc.SelectObject(pbrush);  //将其选入设备表
            //dc.Rectangle(CRect(m_ptOrign,m_ptEnd));
            dc.Rectangle(CRect(m_ptOrign,point));
            pOldbrush=pbrush;*/

            //画中心为透明边为任意颜色的矩形
            /*CClientDC dc(this);
            CBrush *pbrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
            CBrush *pOldbrush=dc.SelectObject(pbrush);  //将其选入设备表
            CPen pen(PS_SOLID,1,RGB(234,23,53));
            CPen *poldpen=dc.SelectObject(&pen);  //将其选入设备表
            dc.Rectangle(CRect(m_ptOrign,point));
            dc.SelectObject(poldpen);
            dc.SelectObject(pOldbrush);
            */
            CView::OnMouseMove(nFlags, point);
    }

    http://blog.csdn.net/muzi9_17/article/details/6376922
    绘制任意线条:

    1、创建基于单文档工程:Draw

    CDrawView类中添加成员变量:

    CPoint m_ptOrigin;

    BOOL m_bDraw;

    2、CDrawView()中初始化:

    m_ptOrigin = point;

    m_bDraw = false;

    3、添加消息响应函数:

    WM_LBUTTONDOWN    WM_LBUTTONUP  WM_MOUSEMOVE

    4、左键按下时:

    m_ptOrigin = point;

    m_bDraw = true;

    5、左键抬起:

    m_bDraw = false;

    6、鼠标移动时:

        //画连续线条

    CClientDC dc(this);

    if(m_bDraw)

        {
           dc.MoveTo(m_ptOrigin);

           dc.LineTo(point);

           m_ptOrigin = point;

        }

        //画扇形线条

    CClientDC dc(this);

        if(m_bDraw)

        {
           dc.MoveTo(m_ptOrigin);

           dc.LineTo(point);

        }

        //画带外包线的扇形线条

    析:画带外包线的扇形线条,不光记录初始位置,还要记录鼠标移动上一位置。

    添加成员变量:

    CPoint m_ptOld;

    在鼠标左键按下时初始化:

    m_ptOld = point;

    在鼠标移动时进行改变:

    CClientDC dc(this);

        if(m_bDraw)

        {
           dc.MoveTo(m_ptOrigin);

           dc.LineTo(m_ptOld);

           dc.MoveTo(m_ptOld);

           dc.LineTo(point);

           m_ptOld = point;

        }

    画矩形:

    画无边框的矩形

    方法说明:利用FillRect函数填充矩形。填充内容为画刷的内容,即画刷对象的指针。

         CBrush brush(RGB(5,255,255));

         CClientDC dc(this);

         dc.FillRect(CRect(m_ptOrigin,point),&brush);

    以位图作为画刷的资源

         CBitmap bitmap;

         bitmap.LoadBitmap(IDB_BITMAP1);

         CBrush brush(&bitmap);

         CClientDC dc(this);

         dc.FillRect(CRect(m_ptOrigin,point),&brush);

    画有边框的矩形

    方法说明:利用Rectangle方法来画矩形。其中CBrush与CPen类分别负责矩形内部和矩形边框的属性

         //画中心为白色的矩形

         CClientDC dc(this);

         dc.Rectangle(CRect(m_ptOrigin,point));



         //画中心为透明的矩形

         CClientDC dc(this);

    CBrush *pBrush=CBrush::FromHandle((HBRUSH)

    GetStockObject(NULL_BRUSH));

         CBrush *pOldBrush=dc.SelectObject(pBrush);

         dc.Rectangle(CRect(m_ptOrigin,point));

         pOldBrush=pBrush;



    //画中心为透明边为任意颜色的矩形

         CClientDC dc(this);

         CPen pen(PS_SOLID,1,RGB(234,23,53));

         CPen *pOldPen=dc.SelectObject(&pen);

         CBrush *pBrush=CBrush::FromHandle((HBRUSH)

    GetStockObject(NULL_BRUSH))

         CBrush *pOldBrush=dc.SelectObject(pBrush);

         dc.Rectangle(CRect(m_ptOrigin,point));

         dc.SelectObject(pOldPen);

         dc.SelectObject(pOldBrush);



    使用画笔、画刷

    在OnLButtonUp函数中:

    /

    CPen pen(PS_SOLID,1,RGB(234,23,53));

    //定义一个CPen类对象,并利用RGB宏改变其颜色

    CClientDC dc(this);

    CPen *pOldPen=dc.SelectObject(&pen); //将其选入设备表

    dc.MoveTo(m_ptOrigin);

    dc.LineTo(point);

    dc.SelectObject(pOldPen);

    /

    CBrush brush(RGB(0,255,0));

    CClientDC dc(this);

    CRect rect(m_ptOrigin,point);

    dc.FillRect(&rect,&brush);

    /

    使用位图创建画刷:

    插入->资源->位图->引入,可以引入位图,初始一般命名为:IDB_BITMAP1

    CBitmap bitmap;

    bitmap.LoadBitmap(IDB_BITMAP1);

    CBrush brush(&bitmap);

    CClientDC dc(this);

    CRect rect(m_ptOrigin,point);

    dc.FillRect(&rect,&brush);

    /

    CBrush *brush;

    brush = CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));

    CClientDC dc(this);

    CBrush *pOldBrush =dc.SelectObject(brush) ;  

    dc.Rectangle(CRect(m_ptOrigin,point));

    dc.SelectObject(pOldBrush) ;

    注:

    常用的绘图设备类对象的创建和将其引入到设备环境中的方法

    在选择绘图设备类对象(GDI对象)进行绘图时,一般可按下列步骤进行:

    (1)定义一个GDI对象,然后调用相应的函数(如CreatePen、CreateSolidBrush等)创建此GDI对象。

    (2)将已构造出的GDI对象利用设备环境类对象的成员函数SelectObject选入到当前环境中,并同时将原来的GDI对象保存起

    来。

    (3)绘图结束后,恢复当前设备环境中原来的GDI对象。

    注意:在Windows系统中包含了一些库存的GDI对象,在第(3)步中可直接利用设备环境类(CDC)的成员函数

    SelectStockObject将一个Windows库存的GDI对象选入,系统可自动将原来选入的GDI对象从设备环境中分离出来。
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    关闭

    推荐膜材品牌上一条 /6 下一条

    进口膜材 国产膜材 pvdf膜材ptfe膜材ETFE膜材
    最好的膜结构公司 一级膜结构资质 膜结构一级资质
    膜结构设计-膜结构十大品牌-etfe设计-充气膜结构
    诺科膜结构
    遨都膜结构设计
    中国膜结构网
    中国空间膜结构

    QQ|申请友链|手机版|中国膜结构论坛