入门教程_python入门教程 - CSDN
精华内容
参与话题
  • Halcon 入门教程(01)

    万次阅读 多人点赞 2019-05-11 15:41:34
    Halcon 入门教程(01) 这篇教程很简单,实现的功能是计算下图中曲别针的数量和每个曲别针的朝向。主要内容是翻译自Halcon 的帮助文档 “Chapter 4 Programming HDevelop”。 使用的图像如下: 这篇教程中我们假设 ...

    Halcon 入门教程(01)

    这篇教程很简单,实现的功能是计算下图中曲别针的数量和每个曲别针的朝向。主要内容是翻译自Halcon 的帮助文档 “Chapter 4 Programming HDevelop”。

    使用的图像如下:
    在这里插入图片描述这篇教程中我们假设 HDevelop 的各个参数都为默认值,通常新安装好的 HDevelop 所有的参数就都是默认值。如果不是的话可以通过下面的命令行方式将 HDevelop 的各个参数重置为默认值。

    hdevelop -reset_preferences

    首先打开 HDevelop ,如果我们调整过各个窗口的位置,则可以通过菜单命令 Window ⇒ Organize Windows 将各个窗口恢复原始位置。

    加载图像

    加载图像有多重方式,最简单的方式是把图像拖拽到 HDevelop 中。这时会自动弹出一个 Read Image 窗口,在这个窗口中可以设置一些基本的参数。
    在这里插入图片描述加载完成后会在 Program window 中显示对应的语句。当然我们也可以直接在这个窗口中输入这个语句。或者在 Operator Window 中输入 read_image,这时这个窗口会提供这个函数的功能解释,在这个 window 中还可以设置每个输入输出参数。

    读取完图像后的第二个操作是阈值分割 threshold。同样在 Operator Window 中输入 threshold。按照下图设置参数,之后点击 apply 按钮。这时会直接执行这条语句,但是不会把这条语句加入到 Program Window 中。我们可以试着调整参数,通过 apply 按钮,直接获得当前参数的效果。在 graphics window 中可以很直观的看到结果,红色的区域就是通过 Threshold 选出的区域。确认参数之后点击 OK 按钮将该命令加入到 Program Window 中。

    下一步操作是获取连通区域。 Halcon 有个非常好的功能就是可以给出建议的操作。菜单 Suggestions ⇒ Successors 会提示出 Threshold 之后经常跟着的命令。可以看到第一个就是 connection。执行 connection 的结果是获得各个连通区域。graphics window 中会用不同的颜色显示不同的连通区域。
    在这里插入图片描述
    Graphics window 有许多参数可以设置,在这个窗口上单击邮件,弹出的对话框如下图所示。
    在这里插入图片描述点击 Set Parameters 后打开如下对话框:
    在这里插入图片描述
    大家可以随便试试,各个参数的含义都比较简单。

    鼠标放在 ConnectedRegions 变量上单击鼠标右键后会弹出如下的菜单。
    在这里插入图片描述
    点击 Select 可以看到每个 Region 的详细信息,总共有 98 个区域。
    在这里插入图片描述
    实际上我们没有这么多的曲别针,产生这么多的区域说明我们的 threshold 的参数不合适。下面就来研究如何能进一步优化 Threshold 参数。

    菜单 Visualization/Tools → Gray Histogram 会打开 Gray Histogram 窗口。我们调整 threshold 时选中的区域会跟着变化。
    在这里插入图片描述通过这个 Gray Histogram 可以比较容易的选择合适的 Threshold。

    调整 Threshold 参数后得到的区域少了很多,但是还是比曲别针的数量多。这就说明我们需要其他的方法了。 Halcon 提供了一个 Feature Histogram 功能,这个功能除了通过 Histogram 来划分区域还会使用 Region 的其他 Feature。对于我们这个 区别的需求来说,面积就是一个非常好用Feature,因为所有的曲别针都有几乎相同的面积。下面我们就来具体的操作。

    菜单 Visualization/Tools → Feature Histogram 可以打开 Feature Histogram 窗口。按照下图中的参数设置就好。需要注意的是我用红色框框起来的区域。这块如果不是打勾状态,则 Insert Code 按钮就无法点击。
    在这里插入图片描述点击 Insert Code 后就会生成实际的代码:

    select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 6302.75, 8541.28)
    

    我们还要计算每个曲别针的方向,这可以用下面这条语句:

    orientation_region (SelectedRegions, Phi)
    

    然后这条语句计算每个区域的面积和中心点坐标。

    area_center (SelectedRegions, Area, Row, Column)
    

    最后我们要把结果显示在屏幕上。首先在整个程序之前增加一条语句:

    dev_close_window ()
    

    这条语句的作用是关闭任何已经打开的图像窗口。再加一句:

    dev_open_window (0, 0, 512, 512, ‘black’, WindowHandle)

    这条语句新建一个窗口。我们后面可以通过 WindowHandle 来操作这个窗口。

    下面是显示每一个曲别针的方向:

    dev_disp_text (deg(Phi) + ' degrees', 'image', Row, Column, 'black', [], [])
    

    输出的结果如下:
    在这里插入图片描述

    展开全文
  • Hive教程(一) Hive入门教程

    万次阅读 多人点赞 2017-10-10 22:25:51
    Hive是基于Hadoop的一个数据仓库工具,...Hive是一个数据仓库基础工具在Hadoop中用来处理结构化数据。它架构在Hadoop之上,总归为大数据,并使得查询和分析方便。 在Hive中,Hive是SQL解析引擎,它将SQL语句转译成M/R

     

     

    Hive教程() Hive入门教程

     

    1 Hive入门教程

    Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供简单的sql查询功能,可以将sql语句转换为MapReduce任务进行运行。其优点是学习成本低,可以通过类SQL语句快速实现简单的MapReduce统计,不必开发专门的MapReduce应用,十分适合数据仓库的统计分析。Hive是一个数据仓库基础工具在Hadoop中用来处理结构化数据。它架构在Hadoop之上,总归为大数据,并使得查询和分析方便。

    Hive中,HiveSQL解析引擎,它将SQL语句转译成M/R Job然后在Hadoop执行。Hive的表其实就是HDFS的目录/文件,按表名把文件夹分开。如果是分区表,则分区值是子文件夹,可以直接在M/RJob里使用这些数据。

    最初,Hive是由Facebook开发,后来由Apache软件基金会开发,并作为进一步将它作为名义下ApacheHive为一个开源项目。它用在好多不同的公司。例如,亚马逊使用它在Amazon ElasticMapReduce 

    1.1 Hive原理图


    1-1 Hive系统架构图

    1.2 Hive系统架构

    Hive系统架构图:

    1、用户接口:

    CLI,即Shell命令行。

    JDBC/ODBC HiveJava,与使用传统数据库JDBC的方式类似。

    WebGUI是通过浏览器访问 Hive

    2、Thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++,Java, Go,Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript,Node.js, Smalltalk, and OCaml这些编程语言间无缝结合的、高效的服务。

    3、解释器、编译器、优化器完成HQL查询语句从词法分析、语法分析、编译、优化以及查询计划(plan)的生成。生成的查询计划存储在HDFS中,并在随后有MapReduce调用执行。

    4、Hive的数据存储在 HDFS中,大部分的查询由 MapReduce完成(包含 * 的查询,比如 select *from table不会生成 MapRedcue任务)。

    5、Hive将元数据存储在数据库中(metastore),目前只支持mysqlderbyHive中的元数据包括表的名字,表的列和分区及其属性,表的属性(是否为外部表等),表的数据所在目录等。

     

    Metastore组件:

    HiveMetastore组件是Hive元数据集中存放地。Metastore组件包括两个部分:Metastore服务和后台数据的存储。后台数据存储的介质就是关系数据库,例如Hive默认的嵌入式磁盘数据库derby,还有mysql数据库。Metastore服务是建立在后台数据存储介质之上,并且可以和Hive服务进行交互的服务组件,默认情况下,Metastore服务和Hive服务是安装在一起的,运行在同一个进程当中。我也可以把Metastore服务从Hive服务里剥离出来,Metastore独立安装在一个集群里,Hive远程调用Metastore服务,这样我们可以把元数据这一层放到防火墙之后,客户端访问Hive服务,就可以连接到元数据这一层,从而提供了更好的管理性和安全保障。使用远程的Metastore服务,可以让Metastore服务和hive服务运行在不同的进程里,这样也保证了Hive的稳定性,提升了Hive服务的效率。

     

    Hive的执行流程如下图所示:


    Hive的执行流程图

     

    1.3 前置条件

    Hive是建立Hadoop环境安装之上的,所以需要Hadoop的集群环境搭建,Hive即需要依赖于HDFS又需要依赖YARN。安装好Hadoop后需要进行启动HDFSYARN

    环境安装参考资料:

    1、安装《VMware安装Linux教程》地址:http://blog.csdn.net/yuan_xw/article/details/49827477

    2、安装《Linux网络配置与远程连接》地址:http://blog.csdn.net/yuan_xw/article/details/49945007

    3、安装《Hadoop教程()Hadoop分布式集群部署安装》

    地址:http://blog.csdn.net/yuan_xw/article/details/51175171

    4、安装《MySQL环境安装()》地址:http://blog.csdn.net/yuan_xw/article/details/77983704

     

    5、Hive规划图

    主机名

    IP

    安装软件

    运行进程

    Hadoop1

    192.168.197.128

    JdkHadoop

    NameNodeDFSZKFailoverController

    Hadoop2

    192.168.197.129

    JdkHadoop

    NameNodeDFSZKFailoverController

    Hadoop3

    192.168.197.130

    JdkHadoop

    ResourceManagerHiveMySQL

    Hadoop4

    192.168.197.131

    JdkHadoopZookeep

    DataNodeNodeManagerJournalNodeQuorumPeerMain

    Hadoop5

    192.168.197.132

    JdkHadoopZookeep

    DataNodeNodeManagerJournalNodeQuorumPeerMain

    Hadoop6

    192.168.197.133

    JdkHadoopZookeep

    DataNodeNodeManagerJournalNodeQuorumPeerMain

     

    环境安装参考资料:

    1、Hive下载地址:http://mirror.bit.edu.cn/apache/hive/hive-2.3.0/apache-hive-2.3.0-bin.tar.gz

    2、HadoopHbase版本关系表:

    Hive版本

    Hadoop版本

    Hive-2.3.0

    2.x.y

    Hive-2.2.0

    2.x.y

    Hive-2.1.1

    2.x.y

    Hive-2.1.0

    2.x.y

    Hive-2.0.0

    2.x.y

    Hive-1.2.2

    1.x.y2.x.y

    Hive-1.2.1

    1.x.y2.x.y

    Hive-1.0.1

    1.x.y2.x.y

    Hive-1.1.1

    1.x.y2.x.y

    Hive-1.0.1

    1.x.y2.x.y

    Hive-1.0.0

    1.x.y2.x.y

    Hive-0.13.1

    0.20.x 0.23.x.y1.x.y 2.x.y

    Hive-0.13.0

    0.20.x 0.23.x.y1.x.y 2.x.y

    Hive-0.12.0

    0.20.x 0.23.x.y1.x.y 2.x.y

    Hive-0.11.0

    0.20.x 0.23.x.y1.x.y 2.x.y

    Hive-0.10.0

    0.20.x 0.23.x.y1.x.y 2.x.y

     

    1.4 下载Hive

    1、Hive下载:

    执行命令:wget http://mirror.bit.edu.cn/apache/hive/hive-2.3.0/apache-hive-2.3.0-bin.tar.gz


     

    2、解压Hive

    bin:包含hive的命令shell脚本

    binary-package-licenses:包含了LICENSE说明文件

    conf:包含hive配置文件

    examples:包含了示例

    hcatalogMetastore操作的元数据目录

    jdbc:提供了hive-jdbc-2.3.0-standalone.jar

    scripts:提供了sql脚本


     

    3、修改环境变量:

    执行命令:vi /etc/profile

    export JAVA_HOME=/usr/local/software/jdk1.8.0_66

    export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

    export HADOOP_HOME=/usr/local/software/hadoop_2.7.1

    export HBASE_HOME=/usr/local/software/hbase_1.2.2

    export HIVE_HOME=/usr/local/software/apache-hive-2.3.0-bin

    export PATH=.:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HBASE_HOME/bin:$HIVE_HOME/bin:$PATH

    执行命令:source /etc/profile   刷新环境变量

    1.5 修改Hive配置文件

    1、修改hive-site.xml配置文件:

    执行命令:

    cd/usr/local/software/apache-hive-2.3.0-bin/conf/

    mv hive-default.xml.templatehive-site.xml


    2、新建 hdfs目录

    使用 hadoop新建 hdfs目录,因为在 hive-site.xml中有默认如下配置:

    <property>
    	<name>hive.metastore.warehouse.dir</name>
    	<value>/user/hive/warehouse</value>
    	<description>location of defaultdatabase for the warehouse</description>
    </property>

    3、进入 hadoop安装目录执行hadoop命令新建/user/hive/warehouse目录,并授权,用于存储文件

    hadoop fs -mkdir -p /user/hive/warehouse

    hadoop fs -mkdir -p /user/hive/tmp

    hadoop fs -mkdir -p /user/hive/log

    hadoop fs -chmod -R 777 /user/hive/warehouse

    hadoop fs -chmod -R 777 /user/hive/tmp

    hadoop fs -chmod -R 777 /user/hive/log

     

    # 用以下命令检查目录是否创建成功

    hadoop fs -ls /user/hive


     

    4、修改 hive-site.xml

    搜索hive.exec.scratchdir,将该name对应的value修改为/user/hive/tmp

    <property>
    	<name>hive.exec.scratchdir</name>
    	<value>/user/hive/tmp</value>
    </property>

    搜索hive.querylog.location,将该name对应的value修改为/user/hive/log/hadoop

    <property>
    	<name>hive.querylog.location</name>
    	<value>/user/hive/log/hadoop</value>
    	<description>Location of Hive run time structured logfile</description>
    </property>

    搜索javax.jdo.option.connectionURL,将该name对应的value修改为MySQL的地址

    <property>
    	<name>javax.jdo.option.ConnectionURL</name>
    	<value>jdbc:mysql://127.0.0.1:3306/hive?createDatabaseIfNotExist=true</value>
    	<description>
    		JDBC connectstring for a JDBC metastore.
    		To use SSL toencrypt/authenticate the connection, provide
    		database-specific SSL flag in theconnection URL.
    		For example,jdbc:postgresql://myhost/db?ssl=true for postgres database.
    	</description>
    </property>

    搜索javax.jdo.option.ConnectionDriverName,将该name对应的value修改为MySQL驱动类路径

    <property>
    	<name>javax.jdo.option.ConnectionDriverName</name>
    	<value>com.mysql.jdbc.Driver</value>
    	<description>Driverclass name for a JDBC metastore</description>
    </property>

    搜索javax.jdo.option.ConnectionUserName,将对应的value修改为MySQL数据库登录名

    <property>
    	<name>javax.jdo.option.ConnectionUserName</name>
    	<value>root</value>
    	<description>Username touse against metastore database</description>
    </property>

    搜索javax.jdo.option.ConnectionPassword,将对应的value修改为MySQL数据库的登录密码

    <property>
    	<name>javax.jdo.option.ConnectionPassword</name>
    	<value>root</value>
    	<description>password to useagainst metastore database</description>
    </property>

    创建tmp目录

    执行命令:mkdir -p/usr/local/software/apache-hive-2.3.0-bin/tmp


    5、修改 hive-site.xml

    ${system:java.io.tmpdir}改成/usr/local/software/apache-hive-2.3.0-bin/tmp

    ${system:user.name}改成${user.name}


    6、修改hive-env.sh

    mv hive-env.sh.template hive-env.sh

    HADOOP_HOME=/usr/local/software/hadoop_2.7.1

    export HIVE_CONF_DIR=/usr/local/software/apache-hive-2.3.0-bin/conf



    7、下载 mysql驱动包

    执行命令:

    cd/usr/local/software/apache-hive-2.3.0-bin/lib/

    wget http://central.maven.org/maven2/mysql/mysql-connector-java/5.1.38/mysql-connector-java-5.1.38.jar

     


    1.6 初始化MySQL

    1、MySQL数据库进行初始化,首先确保 mysql 中已经创建 hive库:

    执行命令:

    cd /usr/local/software/apache-hive-2.3.0-bin/bin

     ./schematool-initSchema -dbType mysql


                  看到红框的内容表示初始化成功。

    2、MySQL数据库进行初始化,首先确保 mysql 中已经创建 hive库:


    3、查看hive库中所有的表


     

    1.7 启动Hive

    1、启动Hive

    执行命令:/usr/local/software/apache-hive-2.3.0-bin/bin/hive


                  在命令行显示:OK表示已经查看数据库成功。

     

    1.8 学习Hive推荐书籍:

    1. Hive编程指南》

    2. Hadoop应用架构》

    3. Hadoop技术内幕:深入解析Hadoop CommonHDFS架构设计与实现原理》

    4. Hadoop技术内幕:深入解析MapReduce架构设计与实现原理》

    5. Hadoop技术内幕:深入解析YARN架构设计与实现原理》

     

     

                    --以上为《Hive教程(一) Hive入门教程》,如有不当之处请指出,我后续逐步完善更正,大家共同提高。谢谢大家对我的关注。

                                                                                                                                                                                          ——厚积薄发(yuanxw)


    展开全文
  • Go入门教程

    万次阅读 多人点赞 2020-02-26 10:24:52
    本人录制的Go入门视频 go语言开发实战:https://pan.baidu.com/s/1bqOR9qZ Go语言GUI编程:https://pan.baidu.com/s/13yoUhqEUyrT_9bpi7K0rYQ 基础编程 01、Go语言介绍 02、环境搭建 03、第一个Go程序 04、...

    基础编程

    01、Go语言介绍
    02、环境搭建
    03、第一个Go程序

    04、命名、变量、常量
    05、基础数据类型
    06、格式化输出、类型转换、类型别名
    07、运算符
    08、流程控制

    09、自定义函数
    10、递归函数、函数类型、匿名函数与闭包
    11、延迟调用defer
    12、获取命令行参数
    13、作用域

    14、包
    15、工程管理

    复合类型

    类型 名称 长度 默认值 说明
    pointer 指针 nil
    array 数组 0
    slice 切片 nil 引⽤类型
    map 字典 n il 引⽤类型
    struct 结构体



    16、指针
    17、数组
    18、slice
    19、map
    20、结构体

    面向对象

    对于面向对象编程的支持Go 语言设计得非常简洁而优雅。因为, Go语言并没有沿袭传统面向对象编程中的诸多概念,比如继承(不支持继承,尽管匿名字段的内存布局和行为类似继承,但它并不是继承)、虚函数、构造函数和析构函数、隐藏的this指针等。

    这里写图片描述

    尽管Go语言中没有封装、继承、多态这些概念,但同样通过别的方式实现这些特性:

    • 封装:通过方法实现
    • 继承:通过匿名字段实现
    • 多态:通过接口实现

    21、匿名组合
    22、方法
    23、接口
    24、异常处理(error接口、panic、recover)
    25、反射

    文本文件处理

    26、字符串处理
    27、正则表达式
    28、JSON处理
    29、文件操作

    并发编程

    30、什么是并发编程
    31、goroutine
    32、channel
    33、select

    网络编程

    34、网络概述
    35、Socket编程
    36、HTTP报文浅析
    37、HTTP编程

    20180210174507305
    展开全文
  • mfc最详细入门教程

    万次阅读 多人点赞 2017-11-24 10:07:52
    以下是我从其他网站中学的内容,后有相应的网站学习链接地址,可供学习 1.选择菜单项File->New->Project,弹出“New Project”对话框。  2.左侧面板中Installed Templated的Visual C++下选择MFC,中间窗口中...

    以下是我从其他网站中学的内容,后有相应的网站学习链接地址,可供学习

    1.选择菜单项File->New->Project,弹出“New Project”对话框。

     2.左侧面板中Installed Templated的Visual C++下选择MFC,中间窗口中选择MFC Application,然后在下面的Name编辑框中键入工程名称,本例取名“Addition”,在Location编辑框中设置工程的保存路径。点“OK”。

     3.点“Next”到“Application Type”对话框,在Application type下选择Dialog based,其他使用默认设置,点“Finish”。

     我们可以在Solution Explorer视图中看到,此工程的文件要比单文档应用程序少的多,在Class View中主要有三个类:CAboutDlg、CAdditionApp和CAdditionDlg。CAboutDlg是应用程序的“关于”对话框类,CAdditionApp是由CWinApp派生的类,CAdditionDlg是主对话框类,主对话框也就是此应用程序运行后显示的主要界面。

    在Resource View视图中可以看到工程Addition的资源树,展开Addition.rc,下面有四个子项:Dialog(对话框)、Icon(图标)、String Table(字符串表)和Version(版本)。然后展开Dialog项,下面有两个对话框模板,其ID分别为:IDD_ABOUTBOX和IDD_ADDITION_DIALOG,前者是“关于”对话框的模板,后者是主对话框的模板。ID是资源的唯一标识,本质上是一个无符号整数,一般ID代表的整数值由系统定义,我们无需干涉。

    可见对于主对话框来说,创建对话框第一步中的创建新的对话框模板已经由系统自动完成了。而如果是再添加对话框需要创建新的对话框模板时,需要在Resource View的“Dialog”节点上点右键,在右键菜单中选择“Insert Dialog”,就会生成新的对话框模板,并且会自动分配ID。

    在Resource View的资源树中双击某个ID,可在中间区域内显示相应的资源界面。双击IDD_ADDITION_DIALOG时,中间区域就会显示Addition对话框模板。如下图:

    VS2010/MFC编程入门之六(对话框:创建对话框模板和修改对话框属性)



    在Addition对话框模板上点右键,然后在右键菜单中选择Properties,则在右侧面板中会显示对话框的属性列表。如下图:

    VS2010/MFC编程入门之六(对话框:创建对话框模板和修改对话框属性)

      1.ID:对话框ID,唯一标识对话框资源,可以修改。此处为IDD_ADDITION_DIALOG,我们不修改它。

    2.Caption:对话框标题。此处默认为Addition,我们将其修改为“加法计算器”。

    3.Border:边框类型。有四种类型:None、Thin、Resizing和Dialog Frame。我们使用默认的Dialog Frame。

           4.Maximize:是否使用最大化按钮。我们使用默认的False。

           5.Minimize:是否使用最小化按钮。同样我们使用默认的False。

           6.Style:对话框类型。有三种类型:Overlapped(重叠窗口)、Popup(弹出式窗口)和Child(子窗口)。弹出式窗口比较常见。我们使用默认的Popup类型。

           7.System Menu:是否带有标题栏左上角的系统菜单,包括移动、关闭等菜单项。我们使用默认的True。

           8.Title Bar:是否带有标题栏。我们使用默认的True。

           9.Font(Size):字体类型和字体大小。如果将其修改为非系统字体,则Use System自动改为False。而如果Use System原来为False,将其修改为True,则Font(Size)自动设置为系统字体。这里我们使用默认的系统字体。

           根据以上说明,其实我们只修改了标题属性。这时我们运行此程序后的界面如下:

    VS2010/MFC编程入门之六(对话框:创建对话框模板和修改对话框属性)

     1.为对话框添加一个静态文本框(Static Text),用于显示字符串--“被加数”。

          对于自动添加的一个标题为“TODO:Place dialog controls here.”的静态文本框,这里将它删掉,继续添加新的静态文本框。

           删除控件时,可以使用鼠标左键点击选中它,选中后控件的周围会出现虚线框,然后按Delete键就可以将其删除了。在“Addition”工程的Resource View中打开上一讲中创建的对话框模板IDD_ADDITION_DIALOG,自动添加的静态文本框就可以使用这种方法删除。

           在添加新的静态文本框以前,先看看Toolbox视图是否显示了,如果没有显示,在菜单栏上点击View->Toolbox即可。Toolbox视图如下图:

    VS2010/MFC编程入门之七(对话框:为对话框添加控件)

           Toolbox中列出了一些常用控件,其中有一个是Static Text,即是我们要添加的控件。在Toolbox中的Static Text上点下鼠标左键不放开,并拖到IDD_ADDITION_DIALOG对话框模板上,模板上会出现一个虚线框,我们找到合适的位置松开鼠标左键放下它。

           用鼠标左键选中控件后周围出现虚线框,然后鼠标移到虚线框上几个黑点的位置会变成双向箭头的形状,此时就可以按下鼠标左键并拖动来改变控件大小了。我们可以这样改变新添加的静态文本框控件的大小,以更好的显示标题。当然,整个对话框模板也可以用这种方法改变大小。

           接下来就该修改静态文本框的文字了。鼠标右键点击静态文本框,在右键菜单中选择“Properties”,Properties面板就会显示出来,在面板上修改Caption属性为“被加数”,ID修改为IDC_SUMMAND_STATIC。此时模板如下图:

    VS2010/MFC编程入门之七(对话框:为对话框添加控件)

           2.为对话框添加一个编辑框(Edit Control),用来输入被加数。

           添加编辑框的过程与静态文本框类似,在Toolbox中选中Edit Control控件拖到对话框模板上,并使其与之前的静态文本框水平对齐(为了美观),然后调整其大小使之适合被加数的输入。

           在编辑框上点右键,仍然在右键菜单中选择“Properties”显示出属性(Properties)面板,修改其ID为IDC_SUMMAND_EDIT。此时模板如下图:

    VS2010/MFC编程入门之七(对话框:为对话框添加控件)

           3.按照1的方法添加一个标题为“加数”的静态文本框,用于显示字符串--“加数”。并将其ID改为IDC_ADDEND_STATIC。

           4.按照2的方法添加一个ID为IDC_ADDEND_EDIT的编辑框,用来输入加数。

           5.按照1的方法添加一个标题为“和”的静态文本框,用于显示文字--“和”。并修改其ID为IDC_SUM_STATIC。

           6.按照2的方法添加一个ID为IDC_SUM_EDIT的编辑框,用来显示最终的加和。

           7.类似的添加按钮(Button)控件到对话框模板,用于在被点击后触发加法计算。修改其标题为“计算”,ID为IDC_ADD_BUTTON。

           到此,对话框模板如图:

    VS2010/MFC编程入门之七(对话框:为对话框添加控件)

           8.删除OK按钮。打开Cancel按钮的属性面板,将标题改为“退出”,并使其与“计算”按钮水平对齐。

           9.根据控件的布局,适当调整整个对话框模板的大小,使其相对控件布局来说大小合适,界面美观。

           这样在对话框模板中就把我们在本例中需要用到的控件就添加完了。最终效果如下:

    VS2010/MFC编程入门之七(对话框:为对话框添加控件)

     因为例程Addition是基于对话框的程序,所以程序自动创建了对话框模板IDD_ADDITION_DIALOG,并自动生成了对话框类CAdditionDlg,它是从CDialogEx类派生的。大家用过VC++ 6.0的可能记得,我们定义的对话框类都是从CDialog类派生的,但在VS2010中,一般对话框类都是继承自CDialogEx类。

           创建对话框类

           如果是自己新添加的对话框模板,怎样为它创建对话框类呢?

           1.在Resource View的“Dialog”节点上右键,然后在右键菜单中选择“Insert Dialog”创建一个新的对话框模板,ID就使用默认的IDD_DIALOG1。

           2.在中间区域会显示新建的对话框模板,然后选中此对话框模板,点右键,在右键菜单中选择Add Class。

     VS2010/MFC编程入门之八(对话框:创建对话框类和添加控件变量)

           3.选择“Add Class”后会弹出一个对话框,在对话框中“Class name”下的编辑框中写入自定义的类名就可以了,例如CMyDialog。

           4.最后点“Finish”完成。

           最终你就可以在Class View中看到新生成的对话框类CMyDialog了,并且在Solution Explorer中有相应的MyDialog.h头文件和MyDialog.cpp源文件生成。CMyDialog类同样派生于CDialogEx类。

           注意,一般类名都以C打头,又比如,CTestDlg。


           为对话框中的控件添加变量

           在上一讲中为对话框添加了几个控件,包括三个静态文本框,三个编辑框,一个按钮控件。程序自动生成的Cancel按钮保留,作为退出按钮,而OK按钮删除掉了。

           静态文本框只是为了说明后面紧跟的编辑框中数据的意义,是被加数、加数还是和,所以它们是不会变的,我们就不为它们添加变量了。按钮控件是用来操作的,这里也不为它们添加变量。编辑框中的数据可能会经常变化,有必要为它们每个控件关联一个变量。

           首先为被加数的编辑框IDC_SUMMAND_EDIT添加变量。

           1.在编辑框上点右键,在右键菜单中选择“Add Variable”。弹出添加成员变量的向导对话框。

           2.我们想为其添加值变量而不是控件变量,所以对话框中“Category”下的组合框中选择Value。

           3.“Variable type”下的组合框此时默认选中的是“CString”,CString是字符串类,显然不能进行加法运算。我们可以选择double、float、int等。这里我们选择double,即编辑框关联一个double类型的变量。

           4.在“Variable name”中写入自定义的变量名。鸡啄米为其取名m_editSummand。

    VS2010/MFC编程入门之八(对话框:创建对话框类和添加控件变量)

           5.点“Finish”完成。

           注意,类的成员变量名一般以m_打头,以标识它是一个成员变量。

           参照此方法,再分别为加数的编辑框IDD_ADDEND_EDIT添加double型变量m_editAddend、和的编辑框IDD_SUM_EDIT添加double型变量m_editSum。

           对话框类的数据交换和检验

           在程序运行界面中,用户往往会改变控件的属性,例如,在编辑框中输入字符串,或者改变组合框的选中项,又或者改变复选框的选中状态等。控件的属性改变后MFC会相应修改控件关联变量的值。这种同步的改变是通过MFC为对话框类自动生成的成员函数DoDataExchange()来实现的,这也叫做对话框的数据交换和检验机制。

           我们为三个编辑框添加了变量以后,在AdditionDlg.cpp中CAdditionDlg的DoDataExchange()函数的函数体中多了三条DDX_Text调用语句。下面是函数体代码和鸡啄米添加的注释。

    C++代码
    1. void CAdditionDlg::DoDataExchange(CDataExchange* pDX)   
    2. {   
    3.     // 处理MFC默认的数据交换   
    4.     CDialogEx::DoDataExchange(pDX);   
    5.     // 处理控件IDC_SUMMAND_EDIT和变量m_editSummand之间的数据交换   
    6.     DDX_Text(pDX, IDC_SUMMAND_EDIT, m_editSummand);   
    7.     // 处理控件IDC_ADDEND_EDIT和变量m_editAddend之间的数据交换   
    8.     DDX_Text(pDX, IDC_ADDEND_EDIT, m_editAddend);   
    9.     // 处理控件IDC_SUM_EDIT和变量m_editSum之间的数据交换   
    10.     DDX_Text(pDX, IDC_SUM_EDIT, m_editSum);   
    11. }  

           再以Addition程序为例简单说下数据交换机制。如果我们在程序运行界面中输入被加数,则通过CAddition的DoDataExchange()函数可以将输入的值保存到m_editSummand变量中,反之如果程序运行中修改了变量m_editSummand的值,则通过CAddition的DoDataExchange()函数也可以将新的变量值显示到被加数的编辑框中。

           但是这种数据交换机制中,DoDataExchange()并不是被自动调用的,而是需要我们在程序中调用CDialogEx::UpdateData()函数,由UpdateData()函数再去自动调用DoDataExchange()的。

           CDialogEx::UpdateData()函数的原型为:

           BOOL UpdateData(BOOL bSaveAndValidate = TRUE);

           参数:bSaveAndValidate用于指示数据传输的方向,TRUE表示从控件传给变量,FALSE表示从变量传给控件。默认值是TRUE,即从控件传给变量。

           返回值:CDialogEx::UpdateData()函数的返回值表示操作是否成功,成功则返回TRUE,否则返回FALSE。

           在下一讲中将具体演示CDialogEx::UpdateData()函数如何使用。

           鸡啄米本节主要讲的是新建对话框类和添加控件变量,控件的消息处理函数将在下一讲详细介绍。

    *********************************************************************************************************************************************************************

     创建对话框类和添加控件变量在上一讲中已经讲过,这一讲的主要内容是如何为控件添加消息处理函数。

           MFC为对话框和控件等定义了诸多消息,我们对它们操作时会触发消息,这些消息最终由消息处理函数处理。比如我们点击按钮时就会产生BN_CLICKED消息,修改编辑框内容时会产生EN_CHANGE消息等。一般为了让某种操作达到效果,我们只需要实现某个消息的消息处理函数。

           一.添加消息处理函数

           鸡啄米仍以前面的加法计算器的程序为例,说明怎样为“计算”按钮控件添加消息处理函数。添加方法列出4种:

           1.使用Class Wizard添加消息处理函数

           用过的VC++ 6.0的朋友应该对Class Wizard很熟悉了,添加、消息处理函数等经常会用到它,可以说是一个很核心的功能。但从VS2002开始就见不到Class Wizard了,大部分功能都集成到对话框和控件等的属性中了,使用很方便。到VS2010,久违的Class Wizard又回来了。但鸡啄米已经习惯了使用属性中的功能了,对于从VC++ 6.0直接转VS2010的朋友可能觉得还是使用Class Wizard比较习惯。

    VS2010/MFC编程入门之九(对话框:为控件添加消息处理函数)

           大家应该记得,“计算”按钮的ID为IDC_ADD_BUTTON,上图中Commands标签下,Oject IDs列表中有此ID,因为我们是想实现点击按钮后的消息处理函数,所以在Messages列表中选择BN_CLICKED消息,然后点右上方的Add Handler就可以添加BN_CLICKED消息处理函数OnClickedAddButton了。当然你也可以改名,但一般用的默认的就可以。

           2.通过“Add Event Handler...”添加消息处理函数

           在“计算”按钮上点右键,然后在右键菜单中选择菜单项“Add Event Handler...”,弹出“Event Handler Wizard”对话框,如下图:

    VS2010/MFC编程入门之九(对话框:为控件添加消息处理函数)

           可见“Message type”中默认选中的就是BN_CLICKED消息,函数名和所在类都已经自动给出,直接点“Add and Edit”就可以了。

           3.在按钮的属性视图中添加消息处理函数

           上面说过,从VS2002开始就主要从属性视图添加消息处理函数了。我们在“计算”按钮上点右键,在右键菜单中选择“Properties”,右侧面板中会显示按钮的属性视图。

    VS2010/MFC编程入门之九(对话框:为控件添加消息处理函数)

           我们可以像上图中那样,点属性视图的“Control Events”按钮(类似闪电标志),下面列出了“计算”按钮的所有消息。我们要处理的是BN_CLICKED消息,点其右侧空白列表项,会出现一个带下箭头的按钮,再点此按钮会出现“<Add> OnBnClickedAddButton”选项,最后选中这个选项就会自动添加BN_CLICKED处理函数了。

           4.双击按钮添加消息处理函数

           最直接最简单的方法就是,双击“计算”按钮,MFC会自动为其在CAdditionDlg类中添加BN_CLICKED消息的处理函数OnBnClickedAddButton()。

           二.在消息处理函数中添加自定义功能

           在我们使用任意一种方法添加了消息处理函数以后,都只能得到一个空的OnBnClickedAddButton()函数的函数体,要实现我们想要的功能,还需要在函数体中加入自定义功能代码。

           在加法计算器程序中,我们想要“计算”按钮实现的功能是,获取被加数和加数的数值,然后计算它们的和并显示到和的编辑框里。那么,OnBnClickedAddButton()的函数体就应修改为:

    C++代码
    1. void CAdditionDlg::OnBnClickedAddButton()   
    2. {   
    3.     // TODO: Add your control notification handler code here   
    4.     // 将各控件中的数据保存到相应的变量   
    5.     UpdateData(TRUE);   
    6.   
    7.     // 将被加数和加数的加和赋值给m_editSum   
    8.     m_editSum = m_editSummand + m_editAddend;   
    9.   
    10.     // 根据各变量的值更新相应的控件。和的编辑框会显示m_editSum的值   
    11.     UpdateData(FALSE);   
    12. }  

           鸡啄米在上面的代码中已经添加注释,大家应该很容易理解了。对于UpdateData()函数的说明在上一讲中已经介绍过,如果忘了可以再回上一讲了解了解。

           接下来我们运行下此应用程序。在运行结果界面中,输入被加数5.1,加数2.3,然后点“计算”:

    VS2010/MFC编程入门之九(对话框:为控件添加消息处理函数)

           在上图中可以看到,点“计算”按钮后,和的编辑框中显示了正确结果:7.4。

           鸡啄米简单分析下运行过程:输入被加数和加数,点“计算”按钮后产生点击消息,从而调用OnBnClickedAddButton()函数。进入此函数后,首先由UpdateData(TRUE)函数将被加数的值5.1和加数的值2.3分别保存到变量m_editSummand和m_editAddend,然后通过语句m_editSum = m_editSummand + m_editAddend;计算出被加数和加数的和为7.4,并把7.4赋值给m_editSum。最后调用UpdateData(FALSE)根据被加数、加数、和的值更新三个编辑框的显示值,就得到了上图中的结果。

           到此,一个具有简单的加法运算功能的加法计算器应用程序就基本完成了。

    ************************************************************************************************************************************************************************

    本节主要讲对话框上控件的Tab顺序如何调整

           上一讲为“计算”按钮添加了消息处理函数后,加法计算器已经能够进行浮点数的加法运算。但是还有个遗留的小问题,就是对话框控件的Tab顺序问题。

           运行加法计算器程序,显示对话框后不进行任何操作,直接按回车,可以看到对话框退出了。这是因为“退出”按钮是Tab顺序为1的控件,也就是第一个接受用户输入的控件。但是按照我们的输入习惯,应该是被加数的编辑框首先接受用户输入,然后是加数编辑框,再接下来是“计算”按钮,最后才是“退出”按钮。

           我们先来直观的看看各个控件的Tab顺序吧。打开“Resource View”视图,然后在资源中找到对话框IDD_ADDITION_DIALOG,双击ID后中间客户区域出现其模板视图。在主菜单中选择“Format”->"Tab Order",或者按快捷键Ctrl+D,对话框模板上就会显示各个控件的Tab顺序数字。如下图:

    VS2010/MFC编程入门之十(对话框:设置对话框控件的Tab顺序)

           上图中每个控件左上角都有一个数字,这就是它的Tab响应顺序。对话框刚打开时输入焦点就在Tab顺序为1的“退出”按钮上,不做任何操作按下Tab键,输入焦点就会转移到Tab顺序为2的“被加数”静态文本框上,但是因为静态文本框不接受任何输入,所以输入焦点继续自动转移到Tab顺序为3的被加数编辑框,再按Tab键,输入焦点又会转移到Tab顺序为4的“加数”静态文本框上,同样由于它是静态文本框,输入焦点不停留继续转移到加数编辑框,后面的控件同理。

           我们认为这个顺序不合理,那怎么修改呢?很简单,从自己认为Tab顺序应该为1的控件开始依次单击,随着单击的完成,各控件的Tab响应顺序也按我们的想法设置好了。

           例如,此例中我们可以依次单击被加数编辑框、“被加数”静态文本框、加数编辑框、“加数”静态文本框、和编辑框、“和”静态文本框、“计算”按钮和“退出”按钮。设置完后如下图:

    VS2010/MFC编程入门之十(对话框:设置对话框控件的Tab顺序)

           最后按ESC键,确认设置并退出对话框模板的Tab顺序设置状态。

           现在我们再运行程序,可以看到对话框打开后最初的输入焦点在被加数编辑框上,然后我们按Tab键,输入焦点移到加数编辑框上,继续多次按Tab键时,输入焦点会按“和编辑框--‘计算’按钮--‘退出’按钮--被加数编辑框--加数编辑框--和编辑框......”的顺序循环转移。这样就达到了我们的目的。

    *******************************************************************************************************************************************************************************************

    加法计算器对话框程序大家照着做一遍后,相信对基于对话框的程序有些了解了,有个好的开始对于以后的学习大有裨益。趁热打铁,鸡啄米这一节讲讲什么是模态对话框和非模态对话框,以及模态对话框怎样弹出。

           一.模态对话框和非模态对话框

           Windows对话框分为两类:模态对话框和非模态对话框。

           模态对话框是这样的对话框,当它弹出后,本应用程序其他窗口将不再接受用户输入,只有该对话框响应用户输入,在对它进行相应操作退出后,其他窗口才能继续与用户交互。

           非模态对话框则是,它弹出后,本程序其他窗口仍能响应用户输入。非模态对话框一般用来显示提示信息等。

           大家对Windows系统很了解,相信这两种对话框应该都遇到过。之前的加法计算器对话框其实就是模态对话框。

           二.模态对话框是怎样弹出的

           毕竟加法计算器程序大部分都是MFC自动生成的,对话框怎么弹出来的大家可能还不是很清楚。鸡啄米下面简单说说它是在哪里弹出来的,再重新建一个新的对话框并弹出它,这样大家实践以后就能更灵活的使用模态对话框了。

           大家打开Addition.cpp文件,可以看到CAdditionApp类有个InitInstance()函数,在MFC应用程序框架分析中提到过此函数,不过那是单文档应用程序App类中的,函数体不太相同,但都是进行App类实例的初始化工作。

           InitInstance()函数的后半部分有一段代码就是定义对话框对象并弹出对话框的,鸡啄米下面给出这段代码并加以注释:

    C++代码
    1. CAdditionDlg dlg;        // 定义对话框类CAdditionDlg的对象dlg   
    2. m_pMainWnd = &dlg;       // 将dlg设为主窗口   
    3. INT_PTR nResponse = dlg.DoModal();   // 弹出对话框dlg,并将DoModal函数的返回值(退出时点击按钮的ID)赋值给nResponse   
    4. if (nResponse == IDOK)               // 判断返回值是否为OK按钮(其ID为IDOK,鸡啄米已经将它删除)   
    5. {   
    6.     // TODO: Place code here to handle when the dialog is   
    7.     //  dismissed with OK   
    8. }   
    9. else if (nResponse == IDCANCEL)      // 判断返回值是否为Cancel按钮(其ID为IDCANCEL,鸡啄米将它的Caption改为了“退出”)   
    10. {   
    11.     // TODO: Place code here to handle when the dialog is   
    12.     //  dismissed with Cancel   
    13. }  

           弹出对话框比较关键的一个函数,就是对话框类的DoModal()函数。CDialog::DoModal()函数的原型为:

           virtual INT_PTR DoModal();   

           返回值:整数值,指定了传递给CDialog::EndDialog(该函数用于关闭对话框)的nResult参数值。如果函数不能创建对话框,则返回-1;如果出现其它错误,则返回IDABORT。

           调用了它对话框就会弹出,返回值是退出对话框时所点的按钮的ID,比如,我们点了“退出”按钮,那么DoModal返回值为IDCANCEL。

           三.添加一个新对话框并弹出它

           鸡啄米再为加法计算器程序添加一个对话框,以在计算之前询问用户是否确定要进行计算。大家可以完整的看下对话框的添加和弹出过程。

           1.在Resource View中的“Dialog”上点右键选择“Insert Dialog”,创建一个新的对话框模板,修改其ID为IDD_TIP_DIALOG,Caption改为“提示”,然后参考“为对话框添加控件”中所讲,在对话框模板上添加一个静态文本框(static text),Caption改为“您确定要进行加法计算吗?”,接下来修改OK按钮的Caption为“确定”,Cancel按钮的Caption为“取消”,最后调整各个控件的位置和对话框的大小。最终的对话框模板如下图:

    VS2010/MFC编程入门之十一(对话框:模态对话框及其弹出过程)

           2.根据“创建对话框类和添加控件变量”中创建对话框类的方法,在对话框模板上点右键选择“Add Class...”,弹出添加类的对话框,设置“Class name”为CTipDlg,点“OK”。在Solution Explorer中可以看到生成了CTipDlg类的头文件TipDlg.h和源文件TipDlg.cpp。

           3.我们要在点“计算”按钮之后弹出此提示对话框,那么就要在“计算”按钮的消息处理函数OnBnClickedAddButton()中访问提示对话框类,所以为了访问CTipDlg类,在AdditionDlg.cpp中包含CTipDlg的头文件:#include "TipDlg.h"。

           4.修改OnBnClickedAddButton()的函数体,在所有代码前,构造CTipDlg类的对象tipDlg,并通过语句tipDlg.DoModal();弹出对话框,最后判断DoModal()函数的返回值是IDOK还是IDCANCEL来确定是否继续进行计算。OnBnClickedAddButton()函数修改后如下:

    C++代码
    1. void CAdditionDlg::OnBnClickedAddButton()   
    2. {   
    3.     // TODO: Add your control notification handler code here   
    4.     INT_PTR nRes;             // 用于保存DoModal函数的返回值   
    5.   
    6.     CTipDlg tipDlg;           // 构造对话框类CTipDlg的实例   
    7.     nRes = tipDlg.DoModal();  // 弹出对话框   
    8.     if (IDCANCEL == nRes)     // 判断对话框退出后返回值是否为IDCANCEL,如果是则return,否则继续向下执行   
    9.         return;   
    10.   
    11.     // 将各控件中的数据保存到相应的变量   
    12.     UpdateData(TRUE);   
    13.   
    14.     // 将被加数和加数的加和赋值给m_editSum   
    15.     m_editSum = m_editSummand + m_editAddend;   
    16.   
    17.     // 根据各变量的值更新相应的控件。和的编辑框会显示m_editSum的值   
    18.     UpdateData(FALSE);   
    19. }  

           5.测试。编译运行程序后,在对话框上输入被加数和加数,点“计算”,弹出提示对话框询问是否进行计算,如果选择“确定”,则提示对话框退出,并在主对话框上显示被加数和加数的和,而如果选择“取消”,则提示对话框也会退出,但主对话框显示的和不变,即没有进行加法计算。

    **********************************************************************************************************************************************************************

    本节接着讲另一种对话框--非模态对话框的创建及显示。

           鸡啄米已经说过,非模态对话框显示后,程序其他窗口仍能正常运行,可以响应用户输入,还可以相互切换。鸡啄米会将上一讲中创建的Tip模态对话框改为非模态对话框,让大家看下效果。

           非模态对话框的对话框资源对话框类

           实际上,模态对话框和非模态对话框在创建对话框资源和生成对话框类上是没有区别的,所以上一讲中创建的IDD_TIP_DIALOG对话框资源和CTipDlg类都不需要修改。

           创建及显示非模态对话框的步骤

           需要修改的是,对话框类实例的创建和显示,也就是之前在CAdditionDlg::OnBnClickedAddButton()函数体中添加的对话框显示代码。下面是具体步骤:

           1.在AdditionDlg.h中包含CTipDlg头文件并定义CTipDlg类型的指针成员变量。详细操作方法是,在AdditionDlg.cpp中删除之前添加的#include "TipDlg.h",而在AdditionDlg.h中添加#include "TipDlg.h",这是因为我们需要在AdditionDlg.h中定义CTipDlg类型的指针变量,所以要先包含它的头文件;然后在AdditionDlg.h中为CAdditionDlg类添加private成员变量CTipDlg  *m_pTipDlg;。

           2.在CAdditionDlg类的构造函数中初始化成员变量m_pTipDlg。如果cpp文件中函数太多,我们可以在Class View上半个视图中找到CAdditionDlg类,再在下半个视图中找到其构造函数双击,中间客户区域即可马上切到构造函数的实现处。在构造函数体中添加m_pTipDlg = NULL;,这是个好习惯,鸡啄米在C++编程入门系列的指针的赋值和指针运算中说到过,在任何指针变量使用前都初始化,可以避免因误访问重要内存地址而破坏此地址的数据。

           3.将上一讲中添加的模态对话框显示代码注释或删除掉,添加非模态对话框的创建和显示代码。VC++中注释单行代码使用“//”,注释多行代码可以在需注释的代码开始处添加“/*”,结束处添加“*/”。修改后的CAdditionDlg::OnBnClickedAddButton()函数如下:

    C++代码
    1. void CAdditionDlg::OnBnClickedAddButton()   
    2. {   
    3.     // TODO: Add your control notification handler code here   
    4.     /*INT_PTR nRes;             // 用于保存DoModal函数的返回值  
    5.  
    6.     CTipDlg tipDlg;           // 构造对话框类CTipDlg的实例  
    7.     nRes = tipDlg.DoModal();  // 弹出对话框  
    8.     if (IDCANCEL == nRes)     // 判断对话框退出后返回值是否为IDCANCEL,如果是则return,否则继续向下执行  
    9.         return;*/  
    10.   
    11.     // 如果指针变量m_pTipDlg的值为NULL,则对话框还未创建,需要动态创建   
    12.     if (NULL == m_pTipDlg)   
    13.     {   
    14.         // 创建非模态对话框实例   
    15.         m_pTipDlg = new CTipDlg();   
    16.         m_pTipDlg->Create(IDD_TIP_DIALOG, this);   
    17.     }   
    18.     // 显示非模态对话框   
    19.     m_pTipDlg->ShowWindow(SW_SHOW);   
    20.   
    21.     // 将各控件中的数据保存到相应的变量   
    22.     UpdateData(TRUE);   
    23.   
    24.     // 将被加数和加数的加和赋值给m_editSum   
    25.     m_editSum = m_editSummand + m_editAddend;   
    26.   
    27.     // 根据各变量的值更新相应的控件。和的编辑框会显示m_editSum的值   
    28.     UpdateData(FALSE);   
    29. }  

           4.因为此非模态对话框实例是动态创建的,所以需要手动删除此动态对象来销毁对话框。我们在CAdditionDlg类的析构函数中添加删除代码,但是MFC并没有自动给出析构函数,这时需要我们手动添加,在对话框对象析构时就会调用我们自定义的析构函数了。在AdditionDlg.h文件中为CAdditionDlg添加析构函数声明:~CAdditionDlg();,然后在AdditionDlg.cpp文件中添加析构函数的实现,函数体如下:

    C++代码
    1. CAdditionDlg::~CAdditionDlg()   
    2. {   
    3.     // 如果非模态对话框已经创建则删除它   
    4.     if (NULL != m_pTipDlg)   
    5.     {   
    6.         // 删除非模态对话框对象   
    7.         delete m_pTipDlg;   
    8.     }   
    9. }  

           这样,非模态对话框创建和显示的代码就添加修改完了。让我们运行下看看效果吧。

           在加法计算器对话框上输入被加数和加数,然后点“计算”按钮,依然像上节一样弹出了提示对话框,但是先不要关闭它,你可以拖动它后面的加法计算器对话框试试,我们发现加法计算器对话框竟然可以拖动了,而且“和”编辑框里已经显示了运算结果,这表明提示对话框显示以后还没有关闭,OnBnClickedAddButton() 就继续向下执行了,不仅如此,加法计算器的每个编辑框还都可以响应输入。

           这只是一个简单的例子,非模态对话框的用处有很多,以后大家在软件开发中会用到。

           本节教程就到这里了,相信大家对对话框的使用更上了一个台阶了,在不同的情况下可以选择使用模态对话框和非模态对话框了。鸡啄米欢迎大家留言讨论。

    ***************************************************************************************************************************************************************************

     前面讲了模态对话框非模态对话框,本节开始鸡啄米讲一种特殊的对话框--属性页对话框。另外,本套教程所讲大部分对VC++各个版本均可适用或者稍作修改即可,但考虑到终究还是基于VS2010版本的,所以将《VC++/MFC编程入门》改为《VS2010/MFC编程入门》。

           属性页对话框的分类

           属性页对话框想必大家并不陌生,XP系统中桌面右键点属性,弹出的就是属性页对话框,它通过标签切换各个页面。另外,我们在创建MFC工程时使用的向导对话框也属于属性页对话框,它通过点击“Next”等按钮来切换页面。

           属性页对话框就是包含一般属性页对话框和向导对话框两类。它将多个对话框集成于一身,通过标签或按钮来切换页面。

           属性页对话框相关类

          我们使用属性页对话框时,用到的类主要有两个:CPropertyPage类和CPropertySheet类。

           1.CPropertyPage类

           CPropertyPage类继承自CDialog类,它被用于处理某单个的属性页,所以要为每个属性页都创建一个继承自CPropertyPage的子类。大家可以在VS2010的MSDN中查找CPropertyPage类以及它的成员的详细说明。下面鸡啄米就为大家讲解MSDN中列出的CPropertyPage类的部分主要成员函数。

           (1)构造函数

            这里讲三个CProperty类的构造函数,函数原型为:

            CPropertyPage( );

            explicit CPropertyPage(
                    UINT nIDTemplate,
                    UINT nIDCaption = 0,
                    DWORD dwSize = sizeof(PROPSHEETPAGE)
            );

            explicit CPropertyPage(
                    LPCTSTR lpszTemplateName,
                    UINT nIDCaption = 0,
                    DWORD dwSize = sizeof(PROPSHEETPAGE)
            );

           第一个是没有任何参数的构造函数。

           第二个构造函数中,参数nIDTemplate是属性页的对话框资源ID,参数nIDCaption是属性页对话框选项卡的标题所用字符串资源的ID,若设为0,则选项卡标题就使用该属性页的对话框资源的标题。

           第三个构造函数中,参数lpszTemplateName为属性页的对话框资源的名称字符串,不能为NULL。参数nIDCaption同上。

          (2)CancelToClose()函数

           在模态属性页对话框的属性页进行了某不可恢复的操作后,使用CancelToClose()函数将“OK”按钮改为“Close”按钮,并禁用“Cancel”按钮。函数原型为:

           void CancelToClose( );

          (3)SetModified()函数

           调用此函数可激活或禁用“Apply”按钮,函数原型为:

           void SetModified(BOOL bChanged = TRUE);

          (4)可重载函数

           CPropertyPage类提供了一些消息处理函数,来响应属性页对话框的各种消息。我们重载这些消息处理函数,就可以自定义对属性页对话框操作的处理。可重载的消息处理函数包括:

           OnApply:处理属性页的“Apply”按钮被单击的消息
           OnCancel:处理属性页的“Cancel”按钮被单击的消息
           OnKillActive:处理属性页当前活动状态被切换的消息,常用于数据验证
           OnOK:处理属性页的“OK”按钮、“Apply”按钮或者“Close”按钮被单击的消息
           OnQueryCancel:处理属性页的“Cancel”按钮被单击前发出的消息
           OnReset:处理属性页的“Reset”按钮被单击的消息
           OnSetActive:处理属性页被切换为当前活动页的消息
           OnWizardBack:处理属性页的“Back”按钮被单击的消息,仅在向导对话框中有效
           OnWizardFinish:处理属性页的“Finish”按钮被单击的消息,仅在向导对话框中有效
           OnWizardNext:处理属性页的“Next”按钮被单击的消息,仅在向导对话框中有效

           2.CPropertySheet类

           CPropertySheet类继承自CWnd类,它是属性表类,负责加载、打开或删除属性页,并可以在属性页对话框中切换属性页。它跟对话框类似,也有模态和非模态两种。下面鸡啄米就讲解CPropertySheet类的部分成员函数。

          (1)构造函数

           这里依然列出CPropertySheet类的三个构造函数:

           CPropertySheet( );

           explicit CPropertySheet(
                   UINT nIDCaption,
                   CWnd* pParentWnd = NULL,
                   UINT iSelectPage = 0 
           );

           explicit CPropertySheet(
                   LPCTSTR pszCaption,
                   CWnd* pParentWnd = NULL,
                   UINT iSelectPage = 0 
           );

           参数nIDCaption:标题的字符串资源的ID。

           参数pParentWnd:属性页对话框的父窗口,若设为NULL,则父窗口为应用程序的主窗口。

           参数iSelectPage:初始状态时,活动属性页的索引,默认为第一个添加到属性表的属性页。

           参数pszCaption:标题字符串。

          (2)GetActiveIndex()函数

           获取当前活动属性页的索引。函数原型为:

           int GetActiveIndex( ) const;

           返回值:当前活动属性页的索引。

          (3)GetActivePage()函数

           获取当前活动属性页对象。函数原型为:

           CPropertyPage* GetActivePage( ) const;

           返回值:当前活动属性页对象的指针。

          (4)GetPage()函数

           获取某个属性页对象。函数原型为:

           CPropertyPage* GetPage(int nPage) const;

           参数nPage:目标属性页的索引。

           返回值:目标属性页对象的指针。

          (5)GetPageCount()函数

           获取属性页的数量。函数原型为:

           int GetPageCount( ) const;

           返回值:属性页的数量。

          (6)GetPageIndex()函数

           获取某属性页在属性页对话框中的索引。函数原型为:

           int GetPageIndex(CPropertyPage* pPage);

           参数pPage:要获取索引的属性页对象的指针。

           返回值:属性页对象在属性页对话框中的索引。

          (7)SetActivePage()函数

           设置某个属性页为活动属性页。函数原型为:   

           BOOL SetActivePage(
                     int nPage 
           );

           BOOL SetActivePage(
                     CPropertyPage* pPage 
           );

           参数nPage:要设置为活动属性页的索引。

           参数pPage:要设置为活动属性页的对象指针。

          (8)SetWizardButtons()函数

           在向导对话框上启用或禁用Back、Next或Finish按钮,应在调用DoModal之前调用此函数。函数原型为:

           void SetWizardButtons(
                    DWORD dwFlags 
           );

           参数dwFlags:设置向导按钮的外观和功能属性。可以是以下值的组合:

           PSWIZB_BACK                    启用“Back”按钮,如果不包含此值则禁用“Back”按钮。
           PSWIZB_NEXT                    启用“Next”按钮,如果不包含此值则禁用“Next”按钮。
           PSWIZB_FINISH                  启用“Finish”按钮。
           PSWIZB_DISABLEDFINISH   显示禁用的“Finish”按钮。

          (9)SetWizardMode()函数

           设置属性页对话框为向导对话框模式,应在调用DoModal之前调用此函数。函数原型为:

           void SetWizardMode( );

          (10)SetTitle()函数

           设置属性对话框的标题。函数原型为:

           void SetTitle(
                   LPCTSTR lpszText,
                   UINT nStyle = 0 
           );

           参数lpszText:标题字符串。

           参数nStyle:指定属性表标题的风格。应当为0或PSH_PROPTITLE。如果设为PSH_PROPTITLE,则单词“Properties”会出现在指定标题之后。例如,SetTitle("Simple",PSH_PROPTITLE)这种调用会使得属性表标题为“Simple Properties”。

          (11)AddPage()函数

           为属性对话框添加新的属性页。函数原型为:

           void AddPage(
                   CPropertyPage *pPage 
           );

           参数pPage:要添加的新的属性页的对象指针。

          (12)PressButton()函数

           模拟按下某指定的按钮。函数原型为:   

           void PressButton(
                   int nButton 
           );

           参数nButton:要模拟按下的按钮,它可以是下列值之一:

           PSBTN_BACK   选择“Back”按钮。 
           PSBTN_NEXT   选择“Next”按钮。
           PSBTN_FINISH   选择“Finish”按钮。
           PSBTN_OK   选择“OK”按钮。
           PSBTN_APPLYNOW   选择“Apply”按钮。
           PSBTN_CANCEL   选择“Cancel”按钮。
           PSBTN_HELP   选择“帮助”按钮。

          (13)RemovePage()函数

           删除某属性页。函数原型为:

           void RemovePage(
                   CPropertyPage *pPage 
           );

           void RemovePage(
                   int nPage 
           );

           参数pPage:要删除的属性页的对象指针。

           参数nPage:要删除的属性页的索引。

           属性对话框和相关的两个类鸡啄米就先介绍到这,主要是为后面使用属性页对话框做准备。有问题可以到鸡啄米博客交流。谢谢。

    *************************************************************************************************************************************************************************

    上一讲鸡啄米讲了属性页对话框和相关的两个类CPropertyPage类和CPropertySheet类,对使用属性页对话框做准备。本节将为大家演示如何创建向导对话框。

           仍然以前面的“加法计算器”的例子为基础,在其中加入向导对话框,我们可以用它来说明加法计算器的使用方法,一步一步引导用户操作,这也是比较常见的用法。

           加法计算器使用时大概可以分为三步:输入被加数、输入加数、点“计算”按钮。

           鸡啄米就详细说明向导对话框的创建步骤:

           1.创建属性页对话框资源

           根据创建对话框模板和修改对话框属性中所讲方法,在“Resource View”的Dialog”节点上点右键,然后在右键菜单中选择“Insert Dialog”创建第一个对话框模板,对话框的ID属性设置为IDD_SUMMAND_PAGE,Caption属性改为“被加数页”,Style属性在下拉列表中选择“Child”,Border属性在下拉列表中选择“Thin”。

           删除“OK”和“Cancel”按钮,再按照为对话框添加控件中所讲方法,添加一个静态文本框,并修改静态文本框的Caption属性为“请先输入double型被加数”。

           按照上述步骤,继续添加第二个和第三个对话框资源。第二个对话框模板的ID设为IDD_ADDEND_PAGE,Caption属性改为“加数页”,也添加一个静态文本框,Caption设为“请继续输入double型加数”,其他属性同第一个对话框。第三个对话框模板的ID设为IDD_ADD_PAGE,Caption属性改为“计算页”,添加静态文本框的Caption属性改为“最后请按下“计算”按钮”,其他属性也第一个对话框一样。

           2.创建属性页类

           按照创建对话框类和添加控件变量中的方法,在第一个对话框模板上点右键,在右键菜单中选择“Add Class”,弹出类向导对话框,在“Class name”编辑框中输入类名“CSummandPage”,与之前不同的是,因为属性页类都应继承于CPropertyPage类,所以要修改下面“Base class”的选项,在下拉列表中选择“CPropertyPage”。

           因为是第一个属性页,所以它应该有一个“下一步”按钮,在哪里添加呢?上一讲CPropertyPage类的可重载函数中提到,OnSetActive函数用于处理属性页被切换为当前活动页的消息,所以我们可以在OnSetActive函数中进行相关设置。

           那怎样重载OnSetActive函数呢?我们可以在“Class View”中找到“CSummandPage”节点,点右键弹出右键菜单,选择“Properties”,然后VS2010右侧面板上会显示对话框的属性列表,属性列表的工具栏上有个tip信息为“Overrides”的按钮,按下它,下方列表中就列出了重载函数,找到“OnSetActive”,点其右侧空白列表项出现向下箭头,再点箭头就在下面出现了“<Add>OnSetActive”的选项,选择它就会自动在CSummandPage类中添加函数OnSetActive。

     

           我们只需在OnSetActive函数体中添加相关代码就可以实现添加“下一步”按钮的效果了。新的函数体如下:

    C++代码
    1. BOOL CSummandPage::OnSetActive()   
    2. {   
    3.     // TODO: Add your specialized code here and/or call the base class  
    4.   
    5.     // 获得父窗口,即属性表CPropertySheet类   
    6.     CPropertySheet* psheet = (CPropertySheet*) GetParent();   
    7.     // 设置属性表只有“下一步”按钮   
    8.     psheet->SetWizardButtons(PSWIZB_NEXT);   
    9.   
    10.     return CPropertyPage::OnSetActive();   
    11. }  

           为第二个和第三个对话框也分别添加属性页类CAddendPage和CAddPage。但第二个对话框的属性页不需要重载OnSetActive函数。第三个对话框是最后一个对话框,所以不需要“下一步”按钮,而应该换成“完成”按钮,所以也需要重载OnSetActive函数设置“完成”按钮。重载后的OnSetActive如下:

    C++代码
    1. BOOL CAddPage::OnSetActive()   
    2. {   
    3.     // TODO: Add your specialized code here and/or call the base class  
    4.   
    5.     // 获得父窗口,即属性表CPropertySheet类   
    6.     CPropertySheet* psheet = (CPropertySheet*) GetParent();   
    7.     //设置属性表只有“完成”按钮   
    8.     psheet->SetFinishText(_T("完成"));   
    9.   
    10.     return CPropertyPage::OnSetActive();   
    11. }  

           上面的代码段中,字符串“完成”前加了个_T,这是因为本工程创建的时候用的默认的Unicode字符集,而如果“完成”前不加_T就是ASCII字符串。_T实际上是一个宏,工程的字符集选择为Unicode时字符串就转为Unicode字符串,选择为Muli-Byte时就转为ASCII字符串。我们可以在Solution Explorer的Addition根节点上点右键,在右键菜单上选择“Properties”,弹出工程的属性对话框,Configuration Properties->General右侧列表中的Character Set就显示选择的字符集。

           那点了第三个属性页上的“完成”按钮我们想进行某些处理的话,就重载OnWizardFinish函数,方法同OnSetActive函数。重载后的OnWizardFinish函数如下:

    C++代码
    1. BOOL CAddPage::OnWizardFinish()   
    2. {   
    3.     // TODO: Add your specialized code here and/or call the base class  
    4.   
    5.     // 提示向导完成   
    6.     MessageBox(_T("使用说明向导已阅读完!"));   
    7.   
    8.     return CPropertyPage::OnWizardFinish();   
    9. }  

            3.创建属性表类

           属性页资源和属性页类创建完以后,还不能生成向导对话框,我们还需要一个属性表类,来容纳这些属性页。

           在Solution Explorer视图中的根节点“Addition”上点右键,在右键菜单中选择Add->Class,弹出“Add Class”对话框,然后在中间区域中选择“MFC Class”,点“Add”按钮,弹出另一个类向导对话框,设置Class name为CAddSheet,Base class选择“CPropertySheet”,点“Finish”按钮,这样就属性表类就建好了。

           接下来,在新生成的AddSheet.h中包含三个属性页类的头文件:

           #include "SummandPage.h"
           #include "AddendPage.h"
           #include "AddPage.h"

           之后在AddSheet.h中添加private变量:

           CSummandPage    m_summandPage;C
           CAddendPage     m_addendPage;
           CAddPage        m_addPage;

           然后在AddSheet.cpp文件中修改CAddSheet的两个构造函数为:

    C++代码
    1. CAddSheet::CAddSheet(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage)   
    2.     :CPropertySheet(nIDCaption, pParentWnd, iSelectPage)   
    3. {   
    4.     // 添加三个属性页到属性表   
    5.     AddPage(&m_summandPage);   
    6.     AddPage(&m_addendPage);   
    7.     AddPage(&m_addPage);   
    8. }   
    9.   
    10. CAddSheet::CAddSheet(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage)   
    11.     :CPropertySheet(pszCaption, pParentWnd, iSelectPage)   
    12. {   
    13.     // 添加三个属性页到属性表   
    14.     AddPage(&m_summandPage);   
    15.     AddPage(&m_addendPage);   
    16.     AddPage(&m_addPage);   
    17. }  

            4.显示向导对话框

            我们在加法计算器对话框上添加一个按钮,点击它就打开向导对话框。此按钮的ID设为IDC_INSTRUCT_BUTTON,Caption属性设为“使用说明”。

            按照为控件添加消息处理函数中所讲方法,为IDC_INSTRUCT_BUTTON按钮在CAdditionDlg类中添加点击消息的处理函数OnBnClickedInstructButton。然后在AdditionDlg.cpp文件中包含CAddSheet的头文件:#include "AddSheet.h"。最后修改OnBnClickedInstructButton函数如下:

    C++代码
    1. void CAdditionDlg::OnBnClickedInstructButton()   
    2. {   
    3.     // TODO: Add your control notification handler code here   
    4.   
    5.     // 创建属性表对象   
    6.     CAddSheet sheet(_T(""));   
    7.     // 设置属性对话框为向导对话框   
    8.     sheet.SetWizardMode();   
    9.     // 打开模态向导对话框   
    10.     sheet.DoModal();   
    11. }  

           到此,向导对话框就完整的创建完成了,并可以在加法计算器对话框上点“使用说明”按钮显示出来。我们来看看效果吧:

           上图只是被加数页的效果,点其上“下一步”按钮就可以继续显示后面的两个页面。

           是不是向导对话框没有以前想象的那般复杂了?大家可以发挥想象,进行更复杂的修改,实现更完善的功能。依然欢迎朋友们到鸡啄米博客来交流学习。

    **********************************************************************************************************************************************************************************

    属性页对话框包括向导对话框和一般属性页对话框两类,上一节鸡啄米讲了如何创建并显示向导对话框,本节将继续介绍一般属性页对话框的创建和显示。

           实际上,一般属性页对话框的创建和显示过程和向导对话框是很类似的。鸡啄米将上一节中的向导对话框进行少量修改,使其成为一般属性页对话框。

           一般属性页对话框的创建步骤:

           1.创建属性页对话框资源

           属性页对话框资源的创建方法同向导对话框是一样的,上一讲中的对话框资源不需进行任何修改。

           2.创建属性页类

           属性页类的创建和向导对话框的属性页类也基本一样,只是一般属性页对话框中不需要“下一步”和“完成”等按钮,所以上一讲中属性页类的OnSetActive和OnWizardFinish等重载函数可以去掉。即CSummandPage类中的OnSetActive函数、CAddPage类中的OnSetActive函数和OnWizardFinish函数可以删除或注释掉。其他部分不需作任何修改。

           3.创建属性表类

           创建属性表类的过程同向导对话框属性表类也是一样的,所以上一讲中的CAddSheet类不需修改。

           4.显示一般属性页对话框

           上一讲向导对话框的显示是在OnBnClickedInstructButton函数中实现的,其中语句sheet.SetWizardMode();旨在设置属性表为向导对话框模式,所以显示一般属性页对话框时不需调用SetWizardMode成员函数。另外,我们可以将属性页对话框的标题设为“使用说明”,在构造属性表对象时将此字符串作为构造函数的参数传入。OnBnClickedInstructButton函数修改如下:

    C++代码
    1. void CAdditionDlg::OnBnClickedInstructButton()   
    2. {   
    3.     // TODO: Add your control notification handler code here   
    4.   
    5.     // 创建属性表对象   
    6.     CAddSheet sheet(_T("使用说明"));   
    7.        
    8.     // 打开模态一般属性页对话框   
    9.     sheet.DoModal();   
    10. }  

           这样一般属性页对话框的创建和显示就讲完了,我们运行下程序,在结果对话框上点“使用说明”按钮看看效果吧:

     VS2010/MFC编程入门之十五(对话框:一般属性页对话框的创建及显示)

           再总结下,一般属性页对话框和向导对话框的创建和显示的不同包括,是否需要OnSetActive和OnWizardFinish等重载函数,是否需要调用属性表类的SetWizardMode函数设置为向导对话框模式。

    展开全文
  • Python入门教程完整版(懂中文就能学会)

    万次阅读 多人点赞 2020-05-21 16:43:37
    今天本宝宝给大家带来了干货,Python入门教程完整版,...4-13天内容:为Python基础教程14-15 天内容:为飞机大战项目演练 第一阶段(1-3天): 该阶段首先通过介绍不同领域的三种操作系统,操作系统的发展简史以及...
  • oracle入门教程

    万次阅读 多人点赞 2019-07-11 14:14:02
    推荐一个Oracle入门学习教程 点击下面链接进入自学网站 学习网站:http://www.51zxw.net/study.asp?vip=16229363 点击图片箭头所指按钮——请点击进入学习 在下面方框里面搜索Oracle 第一个搜索结果就是小姐姐...
  • 【设计模式】策略模式

    万次阅读 多人点赞 2020-01-23 19:51:16
    博主声明: 转载请在开头附加本文链接及作者信息,并标记为转载。本文由博主威威喵原创,请多支持与指教。 ... 晚上的时候,抽了点时间看了一下设计模式相关书籍,毕竟有些东西还是得重温一下的,脑子不灵光,记住...
  • 2015年最新Android基础入门教程目录(完结版)

    万次阅读 多人点赞 2015-12-21 20:44:26
    2015年最新Android基础入门教程目录(完结版) 前言: 关于《2015年最新Android基础入门教程目录》终于在今天落下了帷幕,全套教程 共148节已编写完毕,附上目录,关于教程的由来,笔者的情况和自学心得,资源分享 ...
  • 最新Android基础入门教程目录(完结版)

    万次阅读 多人点赞 2018-03-29 19:17:14
    第一章:环境搭建与开发相关(已完结 10/10)https://blog.csdn.net/coder_pig/article/details/50000773Android基础入门教程——1.1 背景相关与系统架构分析Android基础入门教程——1.2 开发环境搭建Android基础入门...
  • office入门到精通基础教程视频415集百度云(15G大合集) 下载地址:https://pan.baidu.com/s/1HQQ_gFTU6hw_171o_Z2jYg(百度云下载)
  • Rstudio入门教程

    万次阅读 2018-11-01 11:21:01
    链接:Rstudio最基础(重要)入门命令_百度文库 https://wenku.baidu.com/view/2abdb95752ea551810a687f8.html
  • 转载:https://www.cnblogs.com/kscnchina/p/4570865.html 这篇文章写的很详细,很不错,特此转载,感谢博主。
  • c++入门全套视频教程

    万次阅读 多人点赞 2019-08-29 16:02:53
    注意: 1、如果链接失效可以联系我,重新发,QQ:940916081 版权出处:老九学堂,如有侵权请联系本人删除。 更多C++资源请访问:... ┎┄┄┄┄┄┄┄┒ ┆下载链接 ┆ ......
  • PS 零基础入门到精通视频教程

    千次阅读 2019-02-15 22:07:24
    PS 零基础入门到精通视频教程 百度网盘资源 https://pan.baidu.com/s/14toia-wTkPwZK3OagQ3MpQ
  • Premiere Pro CC 零基础剪辑教程 Premiere Pro CC 速成教程 第01课:新建一个项目和素材导入 第02课:如何对视!顷素材剪辐 第03课:特效的使用 第04课:如何加字幕 第05课:如何添加音乐 第06课:如何给视频...
  • QT零基础入门教程

    万次阅读 多人点赞 2018-09-01 13:37:25
    据说非常适合qt5入门学习,最近正在参考,转载希望更多人看到,也为自己以后找到本资料提供方便。   Qt 学习之路 目录   序 Qt 前言 Hello, world! 信号槽 自定义信号槽 Qt 模块简介 M...
  • http://c.biancheng.net/c/
  • PR菜鸟入门 -- PR基础教学

    万次阅读 多人点赞 2019-04-23 12:00:38
    现在终于有时间来写 PR 的基础教学了,首先视频教学,参看:[Pr教程]0基础急速上手视频制作!UP主必备! 一、快速认识 PR 主界面并导入素材 首先打开 PR 新建项目 修改 名称、位置,其他不用变,点击确定 ...
  • EmguCV视频,EmguCV基础入门到实战教程(C# OpenCV), 开发开发环境VS2017 + EmguCV3.4 1---40目录: 将会学会的内容: ...
  • 一些基础的solidworks入门教程

    千次阅读 2010-06-29 21:22:00
    一些基础的solidworks入门教程,比较适合新手 Solidworks入门——上Solidworks入门教程——中Solidworks入门教程入门课程——下 Solidworks入门教程三创建装配 Solidworks入门教程四工程图 Solidworks...
1 2 3 4 5 ... 20
收藏数 584,367
精华内容 233,746
关键字:

入门教程