├── .gitignore
├── .gitlab-ci.yml
├── LICENSE.rst
├── Makefile
├── README.rst
├── TODO.rst
├── _static
├── css
│ └── custom.css
├── html
│ └── index.html
└── images
│ ├── embedfire.png
│ ├── emgui.JPG
│ ├── firebbs.png
│ ├── gitee.png
│ ├── github.png
│ ├── logo-1.png
│ ├── logo.ico
│ ├── pdf.png
│ └── product.png
├── _templates
├── footer.html
├── head.html
├── index.html
└── layout.html
├── about_us.rst
├── conf.py
├── contribute
└── quick-contribute.rst
├── convert_docx.rst
├── faq
└── index.rst
├── index.rst
├── latexbuild.py
├── latexbuild2.py
├── latexfile
├── logo.eps
├── sphinx.sty
└── sphinxmanual.cls
├── make.bat
├── media
├── docx002.png
├── docx003.png
├── docx004.png
├── docx005.png
├── docx006.png
├── docx007.png
├── docx008.png
├── docx009.png
├── docx010.png
├── docx011.png
├── docx012.png
├── docx013.png
├── docx014.png
├── docx015.png
├── docx016.png
├── docx017.png
├── docx018.jpg
├── docx019.jpeg
├── docx020.jpg
├── docx021.jpg
├── docx022.jpg
├── docx023.jpg
├── docx024.jpg
├── docx025.jpg
├── docx026.jpg
├── docx027.jpg
├── docx028.jpg
├── docx029.jpg
├── docx030.jpg
├── docx031.jpg
├── docx032.jpg
├── docx033.jpg
├── docx034.jpg
├── docx035.jpg
├── docx036.jpg
├── docx037.jpg
├── docx038.jpg
├── docx039.jpg
├── docx040.jpg
├── docx041.jpg
├── docx042.jpg
├── docx043.jpg
├── docx044.jpg
├── docx045.jpg
├── docx046.jpg
├── docx047.jpg
├── docx048.jpg
├── docx049.jpg
├── docx050.jpg
├── docx051.jpg
├── docx052.jpg
├── docx053.jpg
├── docx054.jpg
├── docx055.jpg
├── docx056.jpg
├── docx057.jpg
├── docx058.jpg
├── docx059.jpg
├── docx060.jpg
├── docx061.jpg
├── docx062.png
├── docx063.png
├── docx064.png
├── docx065.png
├── docx066.png
├── docx067.png
├── docx068.png
├── docx069.png
├── docx070.png
├── docx071.png
├── docx072.png
├── docx073.png
├── docx074.png
├── docx075.png
├── docx076.png
├── docx077.png
├── docx078.png
├── docx079.png
├── docx080.png
├── docx081.jpg
├── docx082.jpg
├── docx083.jpg
├── docx084.jpg
├── docx085.jpg
├── docx086.jpg
├── docx087.jpg
├── docx088.jpg
├── docx089.jpg
├── docx090.jpg
├── docx091.jpg
├── docx092.jpg
├── docx093.jpg
├── docx094.png
├── docx095.jpg
├── docx096.jpg
├── docx097.jpg
├── docx098.jpg
├── docx099.jpg
├── docx100.jpg
├── docx101.jpg
├── docx102.jpg
├── docx103.bmp
├── docx104.jpg
├── docx105.jpg
├── docx106.jpg
├── docx107.jpg
├── docx108.png
├── docx109.jpg
├── docx110.jpg
├── docx111.jpg
├── docx112.gif
├── docx112.jpg
├── docx113.jpg
├── docx114.jpg
├── docx115.jpg
├── docx116.jpg
├── docx117.jpg
├── docx118.jpg
├── docx119.jpeg
├── docx120.jpg
├── docx121.jpg
├── docx122.jpg
├── docx123.jpg
├── docx124.jpeg
├── docx125.jpg
├── docx126.jpg
├── docx127.jpg
├── docx128.jpg
├── docx129.jpg
├── docx130.jpg
├── docx131.jpg
├── docx132.jpg
├── docx133.jpg
├── docx134.jpg
├── docx135.jpeg
├── docx136.jpeg
├── docx137.jpeg
├── docx138.jpeg
├── docx139.jpg
├── docx140.jpg
├── docx141.jpg
├── docx142.jpg
├── docx143.jpg
├── docx144.jpg
├── docx145.jpg
├── docx146.jpeg
├── docx147.jpg
├── docx148.jpg
├── docx149.jpg
├── docx150.jpeg
├── docx151.jpg
├── docx152.jpg
├── docx153.jpg
├── docx154.jpg
├── docx155.jpg
├── docx156.jpeg
├── docx157.jpg
├── docx158.jpg
├── docx159.jpg
├── docx160.jpg
├── docx161.jpg
├── docx162.jpg
├── docx163.jpg
├── docx164.jpg
├── docx165.png
└── image165.png
├── requirements.txt
├── section_one
├── section0.rst
├── section1.rst
├── section10.rst
├── section11.rst
├── section12.rst
├── section13.rst
├── section14.rst
├── section15.rst
├── section16.rst
├── section17.rst
├── section18.rst
├── section19.rst
├── section2.rst
├── section20.rst
├── section21.rst
├── section22.rst
├── section23.rst
├── section24.rst
├── section25.rst
├── section26.rst
├── section27.rst
├── section28.rst
├── section3.rst
├── section4.rst
├── section5.rst
├── section6.rst
├── section7.rst
├── section8.rst
└── section9.rst
├── section_two
└── section2_1.rst
└── 目录结构及文件说明.txt
/.gitignore:
--------------------------------------------------------------------------------
1 | _build
2 | .vscode
3 | docx_convert
4 |
--------------------------------------------------------------------------------
/.gitlab-ci.yml:
--------------------------------------------------------------------------------
1 | variables:
2 | #要上传的PDF仓库地址,注意格式,使用ssh地址,(不传的话注释掉后面的上传指令"gitlab PDF文档仓库")
3 | GIT_ADDRESS: ssh://git@EmbedfireNAS:30001/emxgui/emxgui_tutorial_pdf.git
4 | #gitlab 邮箱
5 | GIT_USEREMAIL: hjw0415@outlook.com
6 | #gitlab 用户名
7 | GIT_USERNAME: hejiawen
8 | #OSS 主地址 index.html所在的地址,末尾必须带 "/"
9 | OSS_URL: oss://ebf-doc/gui/emXGUI/
10 | #OSS HTML地址 html文件夹相对index的地址,一般不更改
11 | OSS_HTML_URL: zh/latest/
12 | #OSS PDF地址 pdf文件夹相对于index的地址,一般不更改
13 | OSS_PDF_URL: pdf/
14 | #NAS地址 数量不匹配需要删改PDF-files任务中的内容,(不传的话注释掉后面的上传指令"网盘同步")
15 | NAS_URL1: /home/flyleaf/ebf_nas/公司共享/百度云对外发布资料/野火开源图书专栏/[野火]《emXGUI实战指南》系列/
16 |
17 | # 分段,若不想运行某些分段,在后面分段名的定义前加两点,如 ..make-html,
18 | # 但不要注释此处的声明
19 | stages:
20 | - html
21 | - htmloutput
22 | - latex
23 | - pdf
24 | - pdfoutput
25 |
26 | cache: # 缓存路径,根据.git文件夹作为根目录确定,下同
27 | paths:
28 | - _build
29 |
30 | # 若不想运行整个分段,在前面加两点, 如 ..make-html
31 | make-html:
32 | tags:
33 | - ENABLE
34 | stage: html
35 | script:
36 | #如果conf.py不在根目录,使用cd命令跳转到conf.py所在的目录
37 | #删除以前的缓存文件
38 | - make clean
39 | #rst转html
40 | - make html
41 |
42 | html-output:
43 | tags:
44 | - ENABLE
45 | stage: htmloutput
46 | script:
47 | #如果conf.py不在根目录,使用cd命令跳转到conf.py所在的目录
48 | #添加index.html
49 | - ossutil64 cp _templates/index.html $OSS_URL --update
50 | #删除oss html文件夹
51 | - ossutil64 rm $OSS_URL$OSS_HTML_URL -rf
52 | #同步到doc.embedfire.com
53 | - ossutil64 cp -r _build/html/ $OSS_URL$OSS_HTML_URL
54 |
55 | make-latex:
56 | tags:
57 | - ENABLE
58 | stage: latex
59 | script:
60 | #如果conf.py不在根目录,使用cd命令跳转到conf.py所在的目录
61 | #删除以前的缓存文件
62 | - make clean
63 | #rst转latex文件
64 | - make latex
65 |
66 | make-pdf:
67 | tags:
68 | - ENABLE
69 | stage: pdf
70 | script:
71 | #如果conf.py不在根目录,使用cd命令跳转到conf.py所在的目录
72 | #复制相关资源文件
73 | - cp -r latexfile/* _build/latex/
74 | #使用python脚本处理latex文件
75 | - python3 latexbuild.py
76 | #latex文件生成pdf
77 | - cd _build/latex/ && latexmk -r latexmkrc -pdf -f -dvi- -ps- -interaction=nonstopmode
78 | #允许错误运行
79 | #allow_failure: true
80 |
81 | pdf-output:
82 | tags:
83 | - ENABLE
84 | stage: pdfoutput
85 | before_script:
86 | - git config --global user.email "$GIT_USEREMAIL"
87 | - git config --global user.name "$GIT_USERNAME"
88 | script:
89 | #如果conf.py不在根目录,使用cd命令跳转到conf.py所在的目录
90 | #修改文件名称
91 | - python3 latexbuild2.py
92 | #移动文件到指定位置
93 | - cp _build/latex/*.pdf ./
94 |
95 | #删除oss文件夹
96 | - ossutil64 rm $OSS_URL$OSS_PDF_URL -rf
97 | #同步到doc.embedfire.com
98 | - ossutil64 cp -r _build/*.pdf $OSS_URL$OSS_PDF_URL
99 | - ossutil64 cp -r _build/index.html $OSS_URL$OSS_PDF_URL
100 |
101 | #网盘同步,在不同的仓库中都需要修改,不传的话注释掉
102 | #F407骄阳
103 | - find "$NAS_URL1" -name "*.pdf" -print0 | xargs -0 rm -f
104 | - cp _build/latex/*.pdf "$NAS_URL1"
105 |
106 |
107 | #上传到gitlab PDF文档仓库,不传的话注释掉
108 | #克隆仓库
109 | - git clone $GIT_ADDRESS /docs/workdir
110 | #修改复制pdf文件到拉取的git仓库
111 | - cd _build/latex/ && rename 's/\.pdf/.pdf_bak/' *.pdf
112 | - cp ./*.pdf_bak /docs/workdir/
113 | - cd /docs/workdir/
114 | #从git删除原来的pdf文件,并将新文件添加
115 | - git rm --ignore-unmatch *.pdf
116 | - rename 's/\.pdf_bak/.pdf/' *.pdf_bak
117 | - git add *.pdf
118 | #提交推送
119 | - git commit -m "gitlab-ci自动提交"
120 | - git push
121 |
122 | artifacts:
123 | name: 'PDFfile' #下载压缩包文件名
124 | paths: #文件路径
125 | - ./*.pdf
126 | expire_in: 1 day #保存时间
127 | when: on_success #仅在job成功后上传
128 |
--------------------------------------------------------------------------------
/LICENSE.rst:
--------------------------------------------------------------------------------
1 | 版权说明
2 | ====================================
3 |
4 |
5 | 野火电子保留本项目的所有版权。
6 |
7 | 公司组织有生存的压力,因为开源而导致生存不下去,是有GEEK精神的人不愿看到的事情。
8 | 由于我们还不熟悉各种版权条例,所以关于版权的问题还在选择中。
9 |
10 | 目前我们保留本项目的所有版权,但我们秉承开源的心是不变的。
11 | 如果你使用本项目不是用于商业目的,基本不需要考虑版权问题。
12 |
13 | 我们主要担忧的商业目的如下,列出来的意思是如果用于以下目的,我们极有可能会追究版权。
14 |
15 | - 同业竞争,目前开发板是我们主要的盈利来源,禁止把本项目用于其它开发板项目。
16 | - 文档出版,项目中包含的文档我们随时会提交至出版社出版,所以我们保留文档出版的权利。
17 | 如果你只是在自己的文章中使用了本项目文档中的内容,需要注明来源。
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line, and also
5 | # from the environment for the first two.
6 | SPHINXOPTS ?=
7 | SPHINXBUILD ?= sphinx-build
8 | SOURCEDIR = .
9 | BUILDDIR = _build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
21 |
--------------------------------------------------------------------------------
/README.rst:
--------------------------------------------------------------------------------
1 | .. vim: syntax=rst
2 |
3 | 关于本项目
4 | ==============
5 |
6 | 本项目的github地址:https://github.com/Embdefire/emXGUI_tutorial_doc.git
7 |
8 | 本项目的gitee 地址:https://gitee.com/wildfireteam/emXGUI_tutorial_doc.git
9 |
10 | 点击右侧链接可在线阅读本项目文档:《 `[野火]emXGUI应用开发实战指南 `_ 》
11 |
12 |
13 | 本文档是关于如何使用emXGUI开发嵌入式图形界面的应用教程。
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/TODO.rst:
--------------------------------------------------------------------------------
1 | .. vim: syntax=rst
2 |
3 | TODO和悬赏任务
4 | ==============
5 |
6 | 本页记录待改进的事项,以后会在此页发布任务清单,完成部分任务可获得 **奖励** ,敬请期待!
7 |
8 | 如果您想参与到项目,可按《 :doc:`contribute/quick-contribute` 》的说明操作。
9 |
10 | 文档任务
11 | ----------------------------
12 |
13 | - 修改文档的格式
14 | - 调整每个章节一个rst文档
15 |
16 |
--------------------------------------------------------------------------------
/_static/css/custom.css:
--------------------------------------------------------------------------------
1 | @import "theme.css";
2 |
3 |
4 | .wy-side-nav-search img {
5 | display: block;
6 | margin: 0px auto 0px auto;
7 | padding: 0px;
8 | height: 30px;
9 | width: 30px;
10 | border-radius: unset
11 | }
12 |
13 | .wy-side-nav-search>a img.logo{
14 | display:block;
15 | margin:0 auto;
16 | height:30%;
17 | width:30%;
18 | border-radius:0;
19 | max-width:30%;
20 | background:transparent
21 | }
22 |
23 |
24 |
--------------------------------------------------------------------------------
/_static/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
47 | {% else %}
48 |
49 | {% endif %}
50 | {% include "breadcrumbs.html" %}
51 |
52 | {%- block document %}
53 |
54 | {% block body %}{% endblock %}
55 |
56 | {% if self.comments()|trim %}
57 |
58 | {% block comments %}{% endblock %}
59 |
60 | {% endif%}
61 |
62 | {%- endblock %}
63 | {% include "footer.html" %}
64 |
65 | {%- endblock %}
66 |
67 |
--------------------------------------------------------------------------------
/about_us.rst:
--------------------------------------------------------------------------------
1 | .. vim: syntax=rst
2 |
3 | .. _about_embedfire:
4 |
5 | 关于野火
6 | ==============
7 |
8 |
9 | 开源共享,共同进步
10 | ----------------------------------
11 |
12 | 野火在发布第一块STM32开发板之初,就喊出 **开源共享,共同进步** 的口号,
13 | 把代码和文档教程都免费提供给用户下载,而我们也一直把这个理念贯穿至今。
14 |
15 | 目前我们的产品已经包括 *STM32、i.MX RT系列、GD32V、FPGA、Linux、emXGUI、
16 | 操作系统、网络、下载器* 等分支,覆盖电子工程应用领域的各种常用技术,
17 | 其中教学类产品的代码和文档一直保持着开源的姿态发布到网络上,
18 | 为电子工程师排忧解难,让嵌入式没有难用的技术是我们最大的愿望。
19 |
20 | 联系方式
21 | -----------------------------
22 |
23 | - 官网: http://www.embedfire.com
24 | - 论坛: http://www.firebbs.cn
25 | - github主页:https://github.com/Embdefire
26 | - gitee主页: https://gitee.com/wildfireteam
27 | - 淘宝: https://yehuosm.tmall.com
28 | - 邮箱: embedfire@embedfire.com
29 | - 电话: 0769-33894118
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/conf.py:
--------------------------------------------------------------------------------
1 | #关于新建文档时配置文件的修改说明
2 | #必须要修改的部分使用#&&&&&&&&&&&&&&&标记
3 | #酌情修改的部分使用#*****************#标记
4 | #详细的修改说明见对应位置
5 |
6 | # Configuration file for the Sphinx documentation builder.
7 | #
8 | # This file only contains a selection of the most common options. For a full
9 | # list see the documentation:
10 | # https://www.sphinx-doc.org/en/master/usage/configuration.html
11 |
12 | # -- Path setup --------------------------------------------------------------
13 |
14 | # If extensions (or modules to document with autodoc) are in another directory,
15 | # add these directories to sys.path here. If the directory is relative to the
16 | # documentation root, use os.path.abspath to make it absolute, like shown here.
17 | #
18 | # import os
19 | # import sys
20 | # sys.path.insert(0, os.path.abspath('.'))
21 |
22 |
23 | # -- Project information -----------------------------------------------------
24 |
25 | #&&&&&&&&&&&&&&&&&&&& START &&&&&&&&&&&&&&&&&&&&&&
26 | #html页面显示的文档标题,注意文档的命名格式
27 | project = '[野火]emXGUI应用开发实战—基于STM32'
28 | #&&&&&&&&&&&&&&&&&&&&& END &&&&&&&&&&&&&&&&&&&&&&&
29 |
30 | copyright = '2020, embedfire-野火 www.embedfire.com'
31 | author = 'embedfire-野火 www.embedfire.com'
32 |
33 |
34 | # -- General configuration ---------------------------------------------------
35 | # The master toctree document.
36 | master_doc = 'index'
37 |
38 | # Add any Sphinx extension module names here, as strings. They can be
39 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
40 | # ones.
41 | extensions = ['recommonmark',
42 | 'sphinx_markdown_tables',
43 | ]
44 |
45 | # The suffix(es) of source filenames.
46 | # You can specify multiple suffix as a list of string:
47 | source_suffix = ['.rst', 'rest', '.md']
48 |
49 | # Add any paths that contain templates here, relative to this directory.
50 | templates_path = ['_templates']
51 |
52 | # The language for content autogenerated by Sphinx. Refer to documentation
53 | # for a list of supported languages.
54 | #
55 | # This is also used if you do content translation via gettext catalogs.
56 | # Usually you set "language" from the command line for these cases.
57 | language = 'zh_CN'
58 |
59 | # List of patterns, relative to source directory, that match files and
60 | # directories to ignore when looking for source files.
61 | # This pattern also affects html_static_path and html_extra_path.
62 | exclude_patterns = []
63 |
64 |
65 | # -- Options for HTML output -------------------------------------------------
66 | import subprocess
67 |
68 | html_theme = 'sphinx_rtd_theme'
69 |
70 | highlight_language = "sh"
71 |
72 | html_static_path = ['_static']
73 | #是否添加 View page source
74 | html_show_sourcelink = False
75 | #是否显示使用Sphinx创建
76 | html_show_sphinx = False
77 | #search 上方的图片
78 | html_logo = u'./_static/images/logo-1.png'
79 |
80 | html_last_updated_fmt = '%Y-%m-%d, %H:%M:%S — %Z '
81 |
82 | html_search_language = 'zh'
83 |
84 | def placeholderReplace(app, docname, source):
85 | result = source[0]
86 | for key in app.config.placeholder_replacements:
87 | result = result.replace(key, app.config.placeholder_replacements[key])
88 | source[0] = result
89 |
90 | def setup(app):
91 | app.add_css_file('css/custom.css')
92 | app.add_config_value('placeholder_replacements', {}, True)
93 | app.connect('source-read', placeholderReplace)
94 |
95 | version = subprocess.getoutput("git rev-parse --short HEAD")
96 | print('commit:', version)
97 |
98 |
99 | ###########################################################################
100 | # embedfire pdf - configuration #
101 | ###########################################################################
102 |
103 | project_language = 'zh_CN'
104 | latex_use_xindy = True
105 | latex_engine = 'xelatex'
106 |
107 | #&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& START &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
108 | # (源文件, '输出文档名称', u'封面标题', u'作者', '主题')
109 | # 此处仅修改封面标题即可,与上方 “project = ‘’ ”保持一致,其他参数请勿修改
110 | latex_documents = [
111 | (master_doc, 'output.tex_bak', u'[野火]emXGUI应用开发实战\\\\—基于STM32',
112 | u'EmbedFire\\\野火电子', 'manual'),
113 | ]
114 | #&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& END &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
115 |
116 | #****************************** START **********************************#
117 | #详细修改说明文中有标注,其中%为注释符号,
118 | #可修改的部分为页面边距、目录深度、章节编号深度
119 | #页眉的设定为必改项
120 | latex_elements = {
121 | 'preamble': r'''
122 | \def\pageautorefname{page}
123 | \usepackage{geometry}%用于设置页面上下左右页边距
124 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% start %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
125 | \geometry{left=2cm,right=2cm,top=3cm,bottom=4cm}%页边距具体数值
126 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
127 |
128 | \PassOptionsToPackage{silence}{xeCJK}
129 | \PassOptionsToPackage{silence}{fontspec}
130 | \usepackage{xeCJK}%设置中文字体
131 | \setCJKfamilyfont{hei}{SimHei} %黑体hei
132 | \setCJKfamilyfont{sun}{SimSun} %宋体hei
133 | \newcommand{\hei}{\CJKfamily{hei}} %黑体(Windows自带simhei.ttf,linux上需要安装字体)
134 | \newcommand{\sun}{\CJKfamily{sun}} %宋(Windows自带simsun.ttf,linux上需要安装字体)
135 | \xeCJKsetup{SlantFont}
136 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% start %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
137 | \setcounter{tocdepth}{2} %目录深度
138 | \setcounter{secnumdepth}{4} %章节编号深度
139 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
140 |
141 | %生成的PDF标签带序号
142 | %\hypersetup{bookmarksnumbered=true}
143 |
144 | \usepackage{titlesec}
145 | \usepackage{CJKnumb}
146 | \usepackage{titletoc}
147 | %修改文档中的章节名使用中文
148 | \titleformat{\chapter}{\centering\Huge\bfseries}{}{1em} {}
149 | %修改文档中的章节名前面空出的距离
150 | \titlespacing{\chapter}{0cm}{0cm}{1em}
151 | %修改目录的章节名使用中文
152 | \titlecontents{chapter}[0pt]{\addvspace{1.5pt}\filright\bf}%
153 | {\contentspush{\color{TitleColor} }}%
154 | {}{\titlerule*[8pt]{.}\contentspage}
155 |
156 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% start %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
157 | %修改页眉设置,页眉分为两种格式
158 | %一种是教程类:页眉右侧文字部分为标题和副标题
159 | %另一类是手册类:页眉右侧文字部分只有主标题
160 | %下面两种配置二选一,不使用的配置用‘%’屏蔽
161 | %可根据生成的PDF来调整页眉字体,使观感协调
162 | %字体大小:\tiny \scriptsize \footnotesize \small \normalsize \large \Large \LARGE \huge \Huge
163 | %字体加粗:\textbf{} 括号内为加粗文本,可直接使用 \upname 的定义
164 | %*******************************************%
165 | %\newcommand\upname{[野火]emXGUI应用开发实战}
166 | %\newcommand\downname{基于STM32}
167 | %\newcommand\fancyheadstyle{\fancyhead[R]{\LARGE \textbf{\upname} \\ \normalsize \downname}}
168 | %*******************************************%
169 | \newcommand\upname{[野火]emXGUI应用开发实战}
170 | \newcommand\fancyheadstyle{\fancyhead[R]{\Large \textbf{\upname}}}
171 | %*******************************************%
172 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
173 |
174 | \usepackage[UTF8]{ctex}
175 | ''',
176 |
177 | }
178 |
179 | #******************************* END **********************************#
--------------------------------------------------------------------------------
/contribute/quick-contribute.rst:
--------------------------------------------------------------------------------
1 | .. vim: syntax=rst
2 |
3 | 快速参与本项目(提交bug或文档修改)
4 | ==========================================
5 |
6 | 开源代码和文档最重要的初衷是让大家参与进来,一起来找茬。
7 |
8 | 无论你是觉得代码写得不够漂亮、有bug,或是文档小到有错别字,大到有原理性的描述错误,
9 | 都可以直接通过项目的github提交给我们,我们会视具体的情况进行审核处理加入到主线或特性分支。
10 |
11 |
12 |
13 | 野火的每个项目的《 :doc:`../README` 》文件中都包含有项目的git仓库地址,
14 | 通过git提交 **issue** 、**pull request** 的方式可参与到项目。
15 |
16 | 我们主要使用github仓库进行维护和更新,gitee仓库用于方便用户快速下载,
17 | 我们一般只在gitee上同步github的master分支,所以参与项目时请尽量使用github。
18 |
19 |
20 | 轻度参与,提交issue
21 | -------------------------
22 | 如果你发现了一些bug或小问题,而自己暂时没时间帮助我们修改的话,
23 | 可以直接在项目的github中提交issue告诉我们,我们会适时进行处理。
24 |
25 |
26 |
27 |
28 |
29 | 深度参与,提交pull request
30 | -----------------------------
31 | 如果你想深度参与本项目,可以先克隆或fork项目的仓库到本地,
32 | 修改编辑后向我们提交pull request,我们会审核处理。
33 |
34 |
35 |
--------------------------------------------------------------------------------
/convert_docx.rst:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/convert_docx.rst
--------------------------------------------------------------------------------
/faq/index.rst:
--------------------------------------------------------------------------------
1 | .. vim: syntax=rst
2 |
3 |
4 | 常见问题
5 | ============================
6 |
7 |
8 |
--------------------------------------------------------------------------------
/index.rst:
--------------------------------------------------------------------------------
1 | .. [野火]emXGUI应用开发实战指南 documentation master file, created by
2 | sphinx-quickstart on Thu Nov 21 10:50:33 2019.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | .. 这一页是目录树
7 |
8 | [野火]emXGUI应用开发实战指南
9 | ======================================================
10 |
11 | .. toctree::
12 | :maxdepth: 1
13 | :caption: 关于本项目
14 |
15 | README
16 | about_us
17 | contribute/quick-contribute
18 | TODO
19 | section_one/section0
20 |
21 | .. toctree::
22 | :maxdepth: 2
23 | :caption: 第一部分 emXGUI控件应用开发
24 | :numbered:
25 |
26 | section_one/section1
27 | section_one/section2
28 | section_one/section3
29 | section_one/section4
30 | section_one/section5
31 | section_one/section6
32 | section_one/section7
33 | section_one/section8
34 | section_one/section9
35 | section_one/section10
36 | section_one/section11
37 | section_one/section12
38 | section_one/section13
39 | section_one/section14
40 | section_one/section15
41 | section_one/section16
42 | section_one/section17
43 | section_one/section18
44 | section_one/section19
45 | section_one/section20
46 | section_one/section21
47 | section_one/section22
48 | section_one/section23
49 | section_one/section24
50 | section_one/section25
51 | section_one/section26
52 | section_one/section27
53 | section_one/section28
54 | .. convert_docx
55 |
56 | .. toctree::
57 | :maxdepth: 2
58 | :caption: 第二部分 emXGUI实战开发
59 | :titlesonly:
60 | :numbered:
61 |
62 | section_two/section2_1
63 |
64 |
65 | .. toctree::
66 | :maxdepth: 2
67 | :caption: 常见问题
68 |
69 | faq/index
70 |
71 | .. toctree::
72 | :maxdepth: 1
73 | :caption: 版权
74 |
75 | LICENSE
76 |
77 | .. toctree::
78 | :maxdepth: 1
79 | :caption: 发布文档到readthedoc
80 |
--------------------------------------------------------------------------------
/latexbuild.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 |
4 | #***************************************************************#
5 | # 需要替换的内容
6 | #***************************************************************#
7 | new_str = []
8 | old_str = []
9 |
10 | old_str.append("\\documentclass[letterpaper,10pt,english]{sphinxmanual}\n")
11 | new_str.append("\\documentclass[12pt,english,oneside,AutoFakeBold]{sphinxmanual}\n")
12 |
13 | old_str.append('\\addto\captionsenglish{\\renewcommand{\\contentsname}{关于本项目}}\n')
14 | new_str.append("\n")
15 |
16 | old_str.append('\\usepackage{cmap}\n')
17 | new_str.append("\n")
18 | #生成的tex文档中需要替换的行,使用list.append方法将需要替换的行内容
19 | #成对添加到new_str = []和old_str = []
20 |
21 | #*******************************end*****************************#
22 |
23 | #***************************************************************#
24 | # 不生成序号的章节
25 | #***************************************************************#
26 | chapter_str = ['关于本项目','关于野火','修订历史','如何参与项目','常见问题','版权说明',
27 | '快速参与本项目(提交bug或文档修改)','TODO和悬赏任务','联系我们'
28 | ]
29 |
30 | #*******************************end*****************************#
31 |
32 | chapter_num = 0
33 | f = open("_build/latex/output.tex_bak", "r", encoding="utf-8")
34 | line = f.readline()
35 | f_new = open("_build/latex/output.tex", "w", encoding="utf-8")
36 |
37 | while line:
38 | if line in old_str:
39 | print("origin line: ",line)
40 | line_num = old_str.index(line)
41 | line = new_str[line_num]
42 | print("change line: ",line)
43 | else :
44 | if line[1:8] == "chapter":
45 | if line[line.find('{')+1:line.find('}')] in chapter_str:
46 | print("origin line: ",line)
47 | line = line[:line.find('{')] + '*' + line[line.find('{'):] + '\\addcontentsline{toc}{chapter}' + line[line.find('{'):line.find('}')+1] + '\n'
48 | print("change line: ",line,'\n')
49 | section = 1
50 | else:
51 | section = 0
52 | chapter_num = chapter_num + 1
53 | print("origin line: ",line)
54 | line = line[:line.find('{')+1] + '第' + str(chapter_num) + '章 \\quad ' + line[line.find('{')+1:]
55 | print("change line: ",line,'\n')
56 |
57 | if line[1:8] == "section":
58 | if section == 1:
59 | print("origin line: ",line)
60 | line = line[:line.find('{')] + '*' + line[line.find('{'):] + '\\addcontentsline{toc}{section}' + line[line.find('{'):line.find('}')+1] + '\n'
61 | print("change line: ",line,'\n')
62 |
63 |
64 | f_new.write(line)
65 | line = f.readline()
66 |
67 | f.close()
68 | f_new.close()
69 |
70 |
--------------------------------------------------------------------------------
/latexbuild2.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import datetime, os, sys, shutil
4 |
5 | name = "[野火]emXGUI应用开发实战—基于STM32"
6 | #输出PDF文档 名称格式 type = 1:手册 type = 0:教程
7 | type = 0
8 |
9 | time = datetime.datetime.now().year * 10000 + datetime.datetime.now().month * 100 + datetime.datetime.now().day
10 |
11 |
12 |
13 | if type == 1:
14 | pdfname_time = '[野火] ' + name + str(time) + '.pdf'
15 | pdfname = '[野火] ' + name + '.pdf'
16 | else:
17 | pdfname_time = '[野火EmbedFire]《' + name + '》—' + str(time) + '.pdf'
18 | pdfname = '[野火EmbedFire]《' + name + '》' + '.pdf'
19 |
20 | print(pdfname_time)
21 | print(pdfname)
22 |
23 | os.rename('_build/latex/output.pdf', '_build/latex/' + pdfname_time)
24 | shutil.copy('_build/latex/' + pdfname_time, '_build/' + pdfname)
25 |
26 |
27 | #-------------------------------------------------------------------------------#
28 | old_str = '
\n'
29 |
30 | f = open("_static/html/index.html", "r", encoding="utf-8")
31 | line = f.readline()
32 | f_new = open("_build/index.html", "w", encoding="utf-8")
33 |
34 | while line:
35 | if line == old_str:
36 | line = '
\n'
37 | print("change line: ",line)
38 |
39 | f_new.write(line)
40 | line = f.readline()
41 |
42 | f.close()
43 | f_new.close()
44 |
--------------------------------------------------------------------------------
/latexfile/sphinxmanual.cls:
--------------------------------------------------------------------------------
1 | %
2 | % sphinxmanual.cls for Sphinx (http://sphinx-doc.org/)
3 | %
4 |
5 | \NeedsTeXFormat{LaTeX2e}[1995/12/01]
6 | \ProvidesClass{sphinxmanual}[2018/12/22 v1.8.3 Document class (Sphinx manual)]
7 |
8 | % chapters starting at odd pages (overridden by 'openany' document option)
9 | \PassOptionsToClass{openright}{\sphinxdocclass}
10 |
11 | % 'oneside' option overriding the 'twoside' default
12 | \newif\if@oneside
13 | \DeclareOption{oneside}{\@onesidetrue}
14 | % Pass remaining document options to the parent class.
15 | \DeclareOption*{\PassOptionsToClass{\CurrentOption}{\sphinxdocclass}}
16 | \ProcessOptions\relax
17 |
18 | % Defaults two-side document
19 | \if@oneside
20 | % nothing to do (oneside is the default)
21 | \else
22 | \PassOptionsToClass{twoside}{\sphinxdocclass}
23 | \fi
24 |
25 | \LoadClass{\sphinxdocclass}
26 |
27 | % Set some sane defaults for section numbering depth and TOC depth. You can
28 | % reset these counters in your preamble.
29 | %
30 | \setcounter{secnumdepth}{2}
31 | \setcounter{tocdepth}{1}
32 |
33 | % Change the title page to look a bit better, and fit in with the fncychap
34 | % ``Bjarne'' style a bit better.
35 | %
36 | \newcommand{\sphinxmaketitle}{%
37 | \let\spx@tempa\relax
38 | \ifHy@pageanchor\def\spx@tempa{\Hy@pageanchortrue}\fi
39 | \hypersetup{pageanchor=false}% avoid duplicate destination warnings
40 | \begin{titlepage}%
41 | \let\footnotesize\small
42 | \let\footnoterule\relax
43 | \noindent\rule{\textwidth}{0.5pt}\par
44 | \begingroup % for PDF information dictionary
45 | \def\endgraf{ }\def\and{\& }%
46 | \pdfstringdefDisableCommands{\def\\{, }}% overwrite hyperref setup
47 | \hypersetup{pdfauthor={\@author}, pdftitle={\@title}}%
48 | \endgroup
49 | \begin{flushright}%
50 | \sphinxlogo
51 | \py@HeaderFamily
52 | {\Huge \@title \par}
53 | {\itshape\LARGE \py@release\releaseinfo \par}
54 | \vfill
55 | {\LARGE
56 | \begin{tabular}[t]{c}
57 | \@author
58 | \end{tabular}\kern-\tabcolsep
59 | \par}
60 | \vfill\vfill
61 | {\large
62 | \@date \par
63 | \vfill
64 | \py@authoraddress \par
65 | }%
66 | \end{flushright}%\par
67 | \@thanks
68 | \end{titlepage}%
69 | \setcounter{footnote}{0}%
70 | \let\thanks\relax\let\maketitle\relax
71 | %\gdef\@thanks{}\gdef\@author{}\gdef\@title{}
72 | \clearpage
73 | \ifdefined\sphinxbackoftitlepage\sphinxbackoftitlepage\fi
74 | \if@openright\cleardoublepage\else\clearpage\fi
75 | \spx@tempa
76 | }
77 |
78 | \newcommand{\sphinxtableofcontents}{%
79 | \pagenumbering{roman}%
80 | \begingroup
81 | \parskip \z@skip
82 | \tableofcontents
83 | \endgroup
84 | % before resetting page counter, let's do the right thing.
85 | \if@openright\cleardoublepage\else\clearpage\fi
86 | \pagenumbering{arabic}%
87 | }
88 |
89 | % This is needed to get the width of the section # area wide enough in the
90 | % library reference. Doing it here keeps it the same for all the manuals.
91 | %
92 | \renewcommand*\l@section{\@dottedtocline{1}{1.5em}{2.6em}}
93 | \renewcommand*\l@subsection{\@dottedtocline{2}{4.1em}{3.5em}}
94 |
95 | % Fix the bibliography environment to add an entry to the Table of
96 | % Contents.
97 | % For a report document class this environment is a chapter.
98 | % 将章节添加到目录
99 | \newenvironment{sphinxthebibliography}[1]{%
100 | \if@openright\cleardoublepage\else\clearpage\fi
101 | \phantomsection % not needed here since TeXLive 2010's hyperref
102 | \begin{thebibliography}{#1}%
103 | \addcontentsline{chapter}{\bibname}}{\end{thebibliography}}
104 |
105 | % Same for the indices.
106 | % The memoir class already does this, so we don't duplicate it in that case.
107 | %
108 | \@ifclassloaded{memoir}
109 | {\newenvironment{sphinxtheindex}{\begin{theindex}}{\end{theindex}}}
110 | {\newenvironment{sphinxtheindex}{%
111 | \if@openright\cleardoublepage\else\clearpage\fi
112 | \phantomsection % needed as no chapter, section, ... created
113 | \begin{theindex}%
114 | \addcontentsline{toc}{chapter}{\indexname}}{\end{theindex}}}
115 |
--------------------------------------------------------------------------------
/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=.
11 | set BUILDDIR=_build
12 |
13 | if "%1" == "" goto help
14 |
15 | %SPHINXBUILD% >NUL 2>NUL
16 | if errorlevel 9009 (
17 | echo.
18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
19 | echo.installed, then set the SPHINXBUILD environment variable to point
20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
21 | echo.may add the Sphinx directory to PATH.
22 | echo.
23 | echo.If you don't have Sphinx installed, grab it from
24 | echo.http://sphinx-doc.org/
25 | exit /b 1
26 | )
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/media/docx002.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx002.png
--------------------------------------------------------------------------------
/media/docx003.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx003.png
--------------------------------------------------------------------------------
/media/docx004.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx004.png
--------------------------------------------------------------------------------
/media/docx005.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx005.png
--------------------------------------------------------------------------------
/media/docx006.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx006.png
--------------------------------------------------------------------------------
/media/docx007.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx007.png
--------------------------------------------------------------------------------
/media/docx008.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx008.png
--------------------------------------------------------------------------------
/media/docx009.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx009.png
--------------------------------------------------------------------------------
/media/docx010.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx010.png
--------------------------------------------------------------------------------
/media/docx011.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx011.png
--------------------------------------------------------------------------------
/media/docx012.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx012.png
--------------------------------------------------------------------------------
/media/docx013.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx013.png
--------------------------------------------------------------------------------
/media/docx014.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx014.png
--------------------------------------------------------------------------------
/media/docx015.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx015.png
--------------------------------------------------------------------------------
/media/docx016.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx016.png
--------------------------------------------------------------------------------
/media/docx017.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx017.png
--------------------------------------------------------------------------------
/media/docx018.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx018.jpg
--------------------------------------------------------------------------------
/media/docx019.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx019.jpeg
--------------------------------------------------------------------------------
/media/docx020.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx020.jpg
--------------------------------------------------------------------------------
/media/docx021.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx021.jpg
--------------------------------------------------------------------------------
/media/docx022.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx022.jpg
--------------------------------------------------------------------------------
/media/docx023.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx023.jpg
--------------------------------------------------------------------------------
/media/docx024.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx024.jpg
--------------------------------------------------------------------------------
/media/docx025.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx025.jpg
--------------------------------------------------------------------------------
/media/docx026.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx026.jpg
--------------------------------------------------------------------------------
/media/docx027.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx027.jpg
--------------------------------------------------------------------------------
/media/docx028.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx028.jpg
--------------------------------------------------------------------------------
/media/docx029.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx029.jpg
--------------------------------------------------------------------------------
/media/docx030.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx030.jpg
--------------------------------------------------------------------------------
/media/docx031.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx031.jpg
--------------------------------------------------------------------------------
/media/docx032.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx032.jpg
--------------------------------------------------------------------------------
/media/docx033.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx033.jpg
--------------------------------------------------------------------------------
/media/docx034.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx034.jpg
--------------------------------------------------------------------------------
/media/docx035.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx035.jpg
--------------------------------------------------------------------------------
/media/docx036.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx036.jpg
--------------------------------------------------------------------------------
/media/docx037.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx037.jpg
--------------------------------------------------------------------------------
/media/docx038.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx038.jpg
--------------------------------------------------------------------------------
/media/docx039.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx039.jpg
--------------------------------------------------------------------------------
/media/docx040.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx040.jpg
--------------------------------------------------------------------------------
/media/docx041.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx041.jpg
--------------------------------------------------------------------------------
/media/docx042.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx042.jpg
--------------------------------------------------------------------------------
/media/docx043.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx043.jpg
--------------------------------------------------------------------------------
/media/docx044.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx044.jpg
--------------------------------------------------------------------------------
/media/docx045.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx045.jpg
--------------------------------------------------------------------------------
/media/docx046.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx046.jpg
--------------------------------------------------------------------------------
/media/docx047.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx047.jpg
--------------------------------------------------------------------------------
/media/docx048.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx048.jpg
--------------------------------------------------------------------------------
/media/docx049.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx049.jpg
--------------------------------------------------------------------------------
/media/docx050.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx050.jpg
--------------------------------------------------------------------------------
/media/docx051.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx051.jpg
--------------------------------------------------------------------------------
/media/docx052.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx052.jpg
--------------------------------------------------------------------------------
/media/docx053.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx053.jpg
--------------------------------------------------------------------------------
/media/docx054.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx054.jpg
--------------------------------------------------------------------------------
/media/docx055.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx055.jpg
--------------------------------------------------------------------------------
/media/docx056.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx056.jpg
--------------------------------------------------------------------------------
/media/docx057.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx057.jpg
--------------------------------------------------------------------------------
/media/docx058.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx058.jpg
--------------------------------------------------------------------------------
/media/docx059.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx059.jpg
--------------------------------------------------------------------------------
/media/docx060.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx060.jpg
--------------------------------------------------------------------------------
/media/docx061.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx061.jpg
--------------------------------------------------------------------------------
/media/docx062.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx062.png
--------------------------------------------------------------------------------
/media/docx063.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx063.png
--------------------------------------------------------------------------------
/media/docx064.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx064.png
--------------------------------------------------------------------------------
/media/docx065.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx065.png
--------------------------------------------------------------------------------
/media/docx066.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx066.png
--------------------------------------------------------------------------------
/media/docx067.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx067.png
--------------------------------------------------------------------------------
/media/docx068.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx068.png
--------------------------------------------------------------------------------
/media/docx069.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx069.png
--------------------------------------------------------------------------------
/media/docx070.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx070.png
--------------------------------------------------------------------------------
/media/docx071.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx071.png
--------------------------------------------------------------------------------
/media/docx072.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx072.png
--------------------------------------------------------------------------------
/media/docx073.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx073.png
--------------------------------------------------------------------------------
/media/docx074.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx074.png
--------------------------------------------------------------------------------
/media/docx075.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx075.png
--------------------------------------------------------------------------------
/media/docx076.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx076.png
--------------------------------------------------------------------------------
/media/docx077.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx077.png
--------------------------------------------------------------------------------
/media/docx078.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx078.png
--------------------------------------------------------------------------------
/media/docx079.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx079.png
--------------------------------------------------------------------------------
/media/docx080.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx080.png
--------------------------------------------------------------------------------
/media/docx081.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx081.jpg
--------------------------------------------------------------------------------
/media/docx082.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx082.jpg
--------------------------------------------------------------------------------
/media/docx083.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx083.jpg
--------------------------------------------------------------------------------
/media/docx084.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx084.jpg
--------------------------------------------------------------------------------
/media/docx085.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx085.jpg
--------------------------------------------------------------------------------
/media/docx086.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx086.jpg
--------------------------------------------------------------------------------
/media/docx087.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx087.jpg
--------------------------------------------------------------------------------
/media/docx088.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx088.jpg
--------------------------------------------------------------------------------
/media/docx089.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx089.jpg
--------------------------------------------------------------------------------
/media/docx090.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx090.jpg
--------------------------------------------------------------------------------
/media/docx091.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx091.jpg
--------------------------------------------------------------------------------
/media/docx092.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx092.jpg
--------------------------------------------------------------------------------
/media/docx093.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx093.jpg
--------------------------------------------------------------------------------
/media/docx094.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx094.png
--------------------------------------------------------------------------------
/media/docx095.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx095.jpg
--------------------------------------------------------------------------------
/media/docx096.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx096.jpg
--------------------------------------------------------------------------------
/media/docx097.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx097.jpg
--------------------------------------------------------------------------------
/media/docx098.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx098.jpg
--------------------------------------------------------------------------------
/media/docx099.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx099.jpg
--------------------------------------------------------------------------------
/media/docx100.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx100.jpg
--------------------------------------------------------------------------------
/media/docx101.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx101.jpg
--------------------------------------------------------------------------------
/media/docx102.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx102.jpg
--------------------------------------------------------------------------------
/media/docx103.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx103.bmp
--------------------------------------------------------------------------------
/media/docx104.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx104.jpg
--------------------------------------------------------------------------------
/media/docx105.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx105.jpg
--------------------------------------------------------------------------------
/media/docx106.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx106.jpg
--------------------------------------------------------------------------------
/media/docx107.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx107.jpg
--------------------------------------------------------------------------------
/media/docx108.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx108.png
--------------------------------------------------------------------------------
/media/docx109.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx109.jpg
--------------------------------------------------------------------------------
/media/docx110.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx110.jpg
--------------------------------------------------------------------------------
/media/docx111.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx111.jpg
--------------------------------------------------------------------------------
/media/docx112.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx112.gif
--------------------------------------------------------------------------------
/media/docx112.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx112.jpg
--------------------------------------------------------------------------------
/media/docx113.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx113.jpg
--------------------------------------------------------------------------------
/media/docx114.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx114.jpg
--------------------------------------------------------------------------------
/media/docx115.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx115.jpg
--------------------------------------------------------------------------------
/media/docx116.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx116.jpg
--------------------------------------------------------------------------------
/media/docx117.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx117.jpg
--------------------------------------------------------------------------------
/media/docx118.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx118.jpg
--------------------------------------------------------------------------------
/media/docx119.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx119.jpeg
--------------------------------------------------------------------------------
/media/docx120.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx120.jpg
--------------------------------------------------------------------------------
/media/docx121.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx121.jpg
--------------------------------------------------------------------------------
/media/docx122.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx122.jpg
--------------------------------------------------------------------------------
/media/docx123.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx123.jpg
--------------------------------------------------------------------------------
/media/docx124.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx124.jpeg
--------------------------------------------------------------------------------
/media/docx125.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx125.jpg
--------------------------------------------------------------------------------
/media/docx126.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx126.jpg
--------------------------------------------------------------------------------
/media/docx127.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx127.jpg
--------------------------------------------------------------------------------
/media/docx128.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx128.jpg
--------------------------------------------------------------------------------
/media/docx129.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx129.jpg
--------------------------------------------------------------------------------
/media/docx130.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx130.jpg
--------------------------------------------------------------------------------
/media/docx131.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx131.jpg
--------------------------------------------------------------------------------
/media/docx132.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx132.jpg
--------------------------------------------------------------------------------
/media/docx133.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx133.jpg
--------------------------------------------------------------------------------
/media/docx134.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx134.jpg
--------------------------------------------------------------------------------
/media/docx135.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx135.jpeg
--------------------------------------------------------------------------------
/media/docx136.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx136.jpeg
--------------------------------------------------------------------------------
/media/docx137.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx137.jpeg
--------------------------------------------------------------------------------
/media/docx138.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx138.jpeg
--------------------------------------------------------------------------------
/media/docx139.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx139.jpg
--------------------------------------------------------------------------------
/media/docx140.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx140.jpg
--------------------------------------------------------------------------------
/media/docx141.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx141.jpg
--------------------------------------------------------------------------------
/media/docx142.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx142.jpg
--------------------------------------------------------------------------------
/media/docx143.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx143.jpg
--------------------------------------------------------------------------------
/media/docx144.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx144.jpg
--------------------------------------------------------------------------------
/media/docx145.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx145.jpg
--------------------------------------------------------------------------------
/media/docx146.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx146.jpeg
--------------------------------------------------------------------------------
/media/docx147.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx147.jpg
--------------------------------------------------------------------------------
/media/docx148.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx148.jpg
--------------------------------------------------------------------------------
/media/docx149.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx149.jpg
--------------------------------------------------------------------------------
/media/docx150.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx150.jpeg
--------------------------------------------------------------------------------
/media/docx151.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx151.jpg
--------------------------------------------------------------------------------
/media/docx152.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx152.jpg
--------------------------------------------------------------------------------
/media/docx153.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx153.jpg
--------------------------------------------------------------------------------
/media/docx154.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx154.jpg
--------------------------------------------------------------------------------
/media/docx155.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx155.jpg
--------------------------------------------------------------------------------
/media/docx156.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx156.jpeg
--------------------------------------------------------------------------------
/media/docx157.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx157.jpg
--------------------------------------------------------------------------------
/media/docx158.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx158.jpg
--------------------------------------------------------------------------------
/media/docx159.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx159.jpg
--------------------------------------------------------------------------------
/media/docx160.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx160.jpg
--------------------------------------------------------------------------------
/media/docx161.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx161.jpg
--------------------------------------------------------------------------------
/media/docx162.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx162.jpg
--------------------------------------------------------------------------------
/media/docx163.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx163.jpg
--------------------------------------------------------------------------------
/media/docx164.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx164.jpg
--------------------------------------------------------------------------------
/media/docx165.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/docx165.png
--------------------------------------------------------------------------------
/media/image165.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Embedfire-emxgui/emXGUI_tutorial_code/65d71b2c0ab5eee84aa7c1e3029f8784e2025931/media/image165.png
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | # markdown suport
2 | recommonmark
3 | # markdown table suport
4 | sphinx-markdown-tables
5 |
6 | # theme default rtd
7 |
8 | # crate-docs-theme
9 | sphinx-rtd-theme
--------------------------------------------------------------------------------
/section_one/section0.rst:
--------------------------------------------------------------------------------
1 | .. vim: syntax=rst
2 |
3 | 前言
4 | ----
5 |
6 | 如何学习本书
7 | ~~~~~~~~~~~~~~
8 |
9 | 本书是首本系统讲解emXGUI应用的中文书籍,共分为两个部分,第一部分为“emXGUI控件应用开发”,即重点讲解emXGUI的每个控件如何使用,并将控件的显示效果在野火STM32开发板上面的液晶显示出来,让你有客观的视觉感受,而不单单是停留在代码层面。
10 |
11 | 第二部分是综合例程实战,即在第一部分学会了如何使用emXGUI控件的基础上,利用这些控件制作各种界面,控制开发板上面的外设,比如制作音乐播放器、视频播放器、万年历和图片浏览器等具有实际项目意义的实战例程。
12 |
13 | 由于第一部分是第二部分的基础,所以学习的时候,必须先学习第一部分,然后再学习第二部分,不能进行跳跃式的阅读。如果第一部分的知识没有掌握好,贸贸然就进入第二部分的实战,出现问题了,定会让你焦头烂额,正所谓基础不牢,地动山摇。
14 |
15 | 本书的参考资料
16 | ~~~~~~~~~~~~~~
17 |
18 | 1. emXGUI 官方作者刘巍手把手指导
19 |
20 | 2. emXGUI API编程手册(电子版)
21 |
22 | 3. 《STM32库开发实战指南》(电子版)
23 |
24 | 本书的配套硬件
25 | ~~~~~~~~~~~~~~
26 |
27 | 本书支持野火STM32开发板全套系列,具体型号见表格 表0-1_,具体图片见 图0-1_、图0-2_、图0-3_、图0-4_ 和 图0-5_ 。
28 | 学习的时候如果配套这些硬件平台做实验,学习必会达到事半功倍的效果,可以省去中间硬件不一样时移植遇到的各种问题。
29 |
30 | .. list-table:: 表格 0‑1 野火STM32开发板型号汇总.
31 | :widths: auto
32 | :header-rows: 1
33 | :name: 表0-1
34 |
35 | * - 型号
36 | - 区别
37 | - \
38 | - \
39 | - \
40 | * - \
41 | - 内核
42 | - 引脚
43 | - RAM
44 | - ROM
45 | * - MINI
46 | - Cortex-M3
47 | - 64
48 | - 48KB
49 | - 256KB
50 | * - 指南者
51 | - Cortex-M3
52 | - 100
53 | - 64KB
54 | - 512KB
55 | * - 霸道
56 | - Cortex-M3
57 | - 144
58 | - 64KB
59 | - 512KB
60 | * - 霸天虎
61 | - Cortex-M4
62 | - 144
63 | - 192KB
64 | - 1MB
65 | * - 挑战者
66 | - Cortex-M4
67 | - 176
68 | - 256KB
69 | - 1MB
70 |
71 | .. image:: /media/docx002.png
72 | :align: center
73 | :alt: 图 0‑1 野火【MINI】STM32F103RCT6 开发板
74 | :name: 图0-1
75 |
76 | 野火【MINI】STM32F103RCT6 开发板
77 |
78 | .. image:: /media/docx003.png
79 | :align: center
80 | :alt: 图 0‑2 野火【指南者】STM32F103VET6 开发板
81 | :name: 图0-2
82 |
83 | 野火【指南者】STM32F103VET6 开发板
84 |
85 | .. image:: /media/docx004.png
86 | :align: center
87 | :alt: 图 0‑3 野火【霸道】STM32F103ZET6 开发板
88 | :name: 图0-3
89 |
90 | 野火【霸道】STM32F103ZET6 开发板
91 |
92 | .. image:: /media/docx005.png
93 | :align: center
94 | :alt: 图 0‑4 野火【霸天虎】STM32F407ZGT6 开发板
95 | :name: 图0-4
96 |
97 | 野火【霸天虎】STM32F407ZGT6 开发板
98 |
99 | .. image:: /media/docx006.png
100 | :align: center
101 | :alt: 图 0‑5 野火【挑战者】STM32F429IGT6 开发板
102 | :name: 图0-5
103 |
104 | 野火【挑战者】STM32F429IGT6 开发板
105 |
106 | 本书的技术论坛
107 | ~~~~~~~~~~~~~~
108 |
109 | 如果在学习过程中遇到问题,可以到野火电子论坛emXGUI专区: `http://www.firebbs.cn/forum.php?mod=forumdisplay&fid=149\ 发帖交流
`__ ,开源共享,共同进步。
110 |
111 | 鉴于水平有限,本书难免有纰漏,热心的读者也可把勘误发到论坛好让我们改进做得更好,祝您学习愉快,emXGUI的世界,野火与您同行。
112 |
--------------------------------------------------------------------------------
/section_one/section1.rst:
--------------------------------------------------------------------------------
1 | .. vim: syntax=rst
2 |
3 | 初识emXGUI
4 | ----------------
5 |
6 | emXGUI是什么
7 | ~~~~~~~~~~~~~~~~~~
8 |
9 | 简而言之,emXGUI(是Embed X Graphics User Interface的缩写)是针对嵌入式平台开发的图形软件库,包含
10 | 各种常用图形控件,通过调用emXGUI提供的函数接口,开发嵌入式图形界面应用变得简单而快捷。
11 |
12 | 而图形软件库究竟是什么?就是一些与图形界面相关的函数,它提供接口给用户调用。例如,在没有使用图形软件库时,要控制LCD显示一个圆,需要用户自行根据LCD驱动编写
13 | 画圆的函数,而使用图形界面软件库的话,这个画圆函数已经由该软件库提供给用户,用户只需要调用这个函数,设置圆的半径、圆心、颜色就可以画出自己想
14 | 要的圆,不需要再考虑画圆的算法。
15 |
16 | emXGUI的应用场合
17 | ~~~~~~~~~~~~~~~~~~~~
18 |
19 | emXGUI并不只是提供了画圆之类的基本绘图函数库,它的主要功能如下:
20 |
21 | - 绘制2-D图形:绘制圆、椭圆、多边形、弧线、线图和饼形图等;
22 |
23 | - 显示位图文件:显示BMP、JPEG、GIF及PNG格式的图片文件;
24 |
25 | - 显示文字:支持显示多国语言的文字,如中英文、越南语、西班牙语等等;
26 |
27 | - 处理用户输入:如键盘、鼠标及电阻/电容触摸屏的人机交互输入处理;
28 |
29 | - 提供各种窗口对象:这些窗口对象也被称为图形控件,最常见的如菜单控件、窗口控件、按键控件、复选框及框架窗口控件等,有了这些控件,就非常容易地制作出类似Windows系统的控制界面了。
30 |
31 | emXGUI的这些功能,就是为了解决人机交互应用的设计难题。而它对ROM和RAM的消耗相对来说并不高。最低推荐配置为:Cortex-M0 ,50MHZ ,32KB RAM ,128KB
32 | ROM。这在当前大多数嵌入式平台都是可以接受的。又因为emXGUI可以在多任务系统及裸机的平台上运行,尤其适合嵌入式乱七八糟的开发要求,自然使得emXGUI在嵌入式人机交互场合中大放异彩。一些使用emXGUI制作出来的效果,见下。
33 |
34 | .. image:: /media/docx007.png
35 | :align: center
36 | :alt: 图 1‑1 emXGUI效果演示效果图
37 |
38 | emXGUI版本说明
39 | ~~~~~~~~~~~~~~~~~~~
40 |
41 | 表格 1‑1 emXGUI版本说明
42 |
43 | ======== ============ ===================================== ============
44 | 版本号 时间 更新说明 作者
45 | ======== ============ ===================================== ============
46 | V1.0.0 2008-07-06 首发(公司内部产品使用至今2020-1-1) AATECH刘巍
47 | \
48 | \
49 | \
50 | \
51 | \
52 | \
53 | \
54 | \
55 | ======== ============ ===================================== ============
56 |
57 | emXGUI版权
58 | ~~~~~~~~~~~~~~~~
59 |
60 | emXGUI由AATECH公司的刘巍编写,拥有完全自主的知识产权(包括emXGUI商标和软件著作权)。于2008年发布V1版本开始,十年深度优化,一直在公司产品中使用至今。
61 |
62 | emXGUI收费
63 | ~~~~~~~~~~~~~~~~
64 |
65 | emXGUI V1 版本商用免费,无论是个人还是公司均可免费使用。但是技术支持收费,即针对使用emXGUI开发产品的公司或者个人提供收费的技术支持。
66 |
67 | emXGUI源码
68 | ~~~~~~~~~~~~~~~~
69 |
70 | emXGUI不开源源代码,但提供多平台的LIB文件,提供完善的API手册,提供配套书籍《emXGUI应用开发实战指南》无论是个人还是公司都可以很快的上手。
71 |
72 | emXGUI支持平台
73 | ~~~~~~~~~~~~~~~~~~
74 |
75 | emXGUI目前测试过的平台如下,但主要目标还是针对M3、M4、M7、ARM9和A5这些内核的处理器,这个才是emXGUI的阵地,A8、A9等
76 | 高端性能的处理器虽然能支持,但不是重点,不会花过多的精力去维护,毕竟这是安卓和QT的阵地。
77 |
78 | - ST:STM32F1、STM32F4、STM32F7、STM32H7
79 |
80 | - GD:GD32F207、GD32F407、GD32F450
81 |
82 | - NXP:i.MX RT1052、I.MX RT1020
83 |
84 | - ATMEL:SAMA5D3
85 |
86 | - 三星:s3c2440、s3c2416、s3c6410
87 |
88 | - 芯唐:N32903、N32905、N32926、NUC972
89 |
90 | - Cortex-A系列:S5PV210、Exynos4412、IMX6Q
91 |
92 | emXGUI特色功能
93 | ~~~~~~~~~~~~~~~~~~
94 |
95 | 这个是重点,目前你们所能见到的GUI有的功能,emXGUI几乎都有,下面简单介绍几个emXGUI的特色:
96 |
97 | 1、占用资源少,效率高,在STM32F103不外扩RAM的情况下可以流畅运行,最低推荐配置为:Cortex-M0 ,50MHZ ,32KB RAM ,128KB ROM。
98 |
99 | 2、控件风格支持用户复位义,如果你想改成扁平化的控件,只需几行代码即可搞定,emXGUI默认是WIN 风格。
100 |
101 | 3、友好地支持矢量字体,提供矢量字体制作工具,除了制作矢量字体外,还可以制作矢量的符号。
102 |
103 | 4、使用unicode字符编码支持多国语言,中文,英文,越南语,西班牙语等等,如果你的产品有界面且需要销往国外,那么emXGUI将是你不二之选。
104 |
105 | 5、支持鼠标,支持触摸(电阻屏和电容屏)。
106 |
107 | 5、自带滑动控件,非常方便,即在液晶屏上可以实现类似现在手机界面滑动的效果。
108 |
109 | 6、高性能的绘图引擎+高效的Z序剪切策略,双管齐下,自带瓦伦增压。
110 |
111 | emXGUI资料获取
112 | ~~~~~~~~~~~~~~~~~~~~
113 |
114 | emXGUI的资料均可从emXGUI官网和野火电子论坛emXGUI专区获取。
115 |
116 | - emXGUI官网:\ `www.emxgui.com `__
117 |
118 | - 野火电子论坛emXGUI专区:\ `http://www.firebbs.cn/forum.php?mod=forumdisplay&fid=149 `__
119 |
120 | emXGUI配套书籍
121 | ~~~~~~~~~~~~~~~~~~~~
122 |
123 | emXGUI的配套书籍由野火电子编写,书名为《emXGUI应用开发实战指南》,会有两本,分别基于STM32和i.MX RT 这两个平台处理器,会适配野火STM32和i.MX RT全系列的开发板。该书会编写边开源电子版,写完届时由机械工业出版社出版。
124 |
125 | emXGUI配套的软件工具
126 | ~~~~~~~~~~~~~~~~~~~~~~~
127 |
128 | - emXGUI Font Creater:用于制作emXGUI字体,格式为xft格式;也可将ttf矢量字体转换成可以抗锯齿的字体,外观上和矢量字体一样,这样就可以不使用freetype库。
129 |
130 | - 模拟器:暂时没有,但是以后会发布。
131 |
--------------------------------------------------------------------------------
/section_one/section10.rst:
--------------------------------------------------------------------------------
1 | .. vim: syntax=rst
2 |
3 |
4 | 进度条控件
5 | ---------------
6 |
7 | 计算机在处理任务时,任务的进度经常采用进度条来显示,还可以表示处理任务的速度,完成度,剩余未完成任务量和可能需要处理时间,一般以长方形条状显示。如 图10_1_。
8 |
9 | .. image:: /media/docx041.jpg
10 | :align: center
11 | :alt: 图 10‑1 进度条示例
12 | :name: 图10_1
13 |
14 | 创建进度条控件
15 | ~~~~~~~~~~~~~~~~~~~~~
16 |
17 | .. _标准消息类型及参数说明-5:
18 |
19 | 标准消息类型及参数说明
20 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
21 |
22 | 本章使用的消息类型常用的有WM_CREATE、WM_TIMER、WM_NOTIFY和WM_CTLCOLOR。WM_CREATE消息用于创建控件;这里使用WM_TIMER,是用了修改进度值。WM_NOTIFY消息用来处理
23 | EXIT按钮消息。使用WM_CTLCOLOR消息来改变控件的外观颜色。下面介绍一个新的消息类型:
24 |
25 | WM_CLOSE消息:之前讲过,当用户按下EXIT按钮后,会调用PostCloseMessage发送关闭主窗口消息,这个消息就是WM_CLOSE。默认情况下,是执行emXGUI的关闭操作,这样就会导致进度条的进度值没有清零,计数依然从上一次的计数值开始。所以我需要在关闭主窗口之前做清零操作。利用窗口
26 | 关闭时,会接收到WM_CLOSE消息。在该消息中,对变量进行清零。
27 |
28 | 进度条配置结构体
29 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30 |
31 | emXGUI使用PROGRESSBAR_CFG结构体来管理进度条。创建进度条完成后,需要发送PBM_SET_CFG消息,来初始化该结构体所有的参数。相关的成员变量,见 代码清单10_1_。
32 |
33 | .. code-block:: c
34 | :caption: 代码清单 10_1 进度条配置结构体PROGRESSBAR_CFG(文件emXGUI.h)
35 | :linenos:
36 | :name: 代码清单10_1
37 |
38 | typedef struct{
39 | u16 cbSize; //结构体的大小
40 | u16 fMask; //功能选择
41 | u32 Rangle; //进度值的最大值
42 | u32 Value; //当前的进度值
43 | u32 TextFlag; //文字格式
44 | }PROGRESSBAR_CFG;
45 |
46 | 1) cbSize:用来存放结构体的大小。用户提供的 PROGRESSBAR_CFG , 必须要将 cbSize 值设置成 sizeof(PROGRESSBAR_CFG)。
47 |
48 | 2) fMask:功能选择位。只有相应的 MASK 位置1,才会更新到 进度条控件的内部数据结构体。
49 |
50 | 3) Rangle:进度值的最大值。默认是100。
51 |
52 | 4) Value:当前的进度值。可以发送PBM_GET_VALUE,来获取当前的进度值。
53 |
54 | 5) TextFlag:文字格式。可以是DT_BOTTOM(垂直底部对齐)、DT_RIGHT(水平居右对齐)、DT_SINGLELINE(单行模式)等等。还有其他的参数,可以参考emXGUI.h的注释来使用。
55 |
56 | 创建进度条控件函数
57 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
58 |
59 | .. code-block:: c
60 | :caption: 代码清单 10_2 创建窗口函数(文件emXGUI.h)
61 | :linenos:
62 | :name: 代码清单10_2
63 |
64 | HWND CreateWindowEx( U32 dwExStyle, LPCVOID lpClass, LPCWSTR lpWindowName,
65 | U32 dwStyle, int x, int y, int nWidth, int nHeight,
66 | HWND hwndParent, UINT WinId,HINSTANCE hInstance,LPVOID lpParam);
67 |
68 | 1) lpClass:窗口类。进度条控件,这里选择PROGRESSBAR。
69 |
70 | 2) dwStyle:进度条的风格。进度条控件支持窗口风格参数,还可以使用以下参数:PBS_TEXT(显示文字)、PBS_3D(立体风格)、PBS_FLAT(平面风格)、PBS_ALIGN_LEFT(从左往右增长)、PBS_ALIGN_RIGHT(从右往左增长)、PBS_ALIGN_TOP(从上往下
71 | 增长)和PBS_ALIGN_BOTTOM(从下往上增长)
72 |
73 | 至于其他的参数,也是同样的用法,这里不作描述。我们创建控件调用的CreateWindow函数,实际上就是CreateWindowEx函数。
74 |
75 | 创建进度条控件实验
76 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
77 |
78 | .. _设计要求-5:
79 |
80 | 设计要求
81 | ^^^^^^^^^^^^
82 |
83 | 图10_2_ 是本章节的设计要求,利用进度条实时显示进度条的进度值。下面看看,如何用代码实现该界面。
84 |
85 | .. image:: /media/docx042.jpg
86 | :align: center
87 | :alt: 图 10‑2 设计要求
88 | :name: 图10_2
89 |
90 | .. _代码分析-5:
91 |
92 | 代码分析
93 | ^^^^^^^^^^^^
94 |
95 | (1) 创建父窗口
96 |
97 | .. code-block:: c
98 | :caption: 代码清单 10‑3 GUI_DEMO_Progressbar函数(文件GUI_DEMO_Progressbar.c)
99 | :linenos:
100 | :name: 代码清单10_3
101 |
102 | void GUI_DEMO_Progressbar(void)
103 | {
104 | HWND hwnd;
105 | WNDCLASS wcex;
106 | MSG msg;
107 | ////第1部分:配置wcex参数。
108 | wcex.Tag = WNDCLASS_TAG;
109 | wcex.Style = CS_HREDRAW | CS_VREDRAW;
110 | wcex.lpfnWndProc = win_proc;
111 | wcex.cbClsExtra = 0;
112 | wcex.cbWndExtra = 0;
113 | wcex.hInstance = 0;//hInst;
114 | wcex.hIcon = 0;//LoadIcon(hInstance, (LPCTSTR)IDI_WIN32_APP_TEST);
115 | wcex.hCursor = 0;//LoadCursor(NULL, IDC_ARROW);
116 | //第2部分:创建主窗口
117 | hwnd =CreateWindowEx(NULL,
118 | &wcex,
119 | _T("GUI Demo - Progressbar"),
120 | WS_CAPTION| WS_DLGFRAME| WS_BORDER| WS_CLIPCHILDREN,
121 | 0,0,GUI_XSIZE,GUI_YSIZE,
122 | NULL,NULL,NULL,NULL);
123 | //第3部分:显示主窗口
124 | ShowWindow(hwnd,SW_SHOW);
125 | //窗口消息循环(窗口关闭并销毁时,GetMessage将返回FALSE,退出本消息循环)。
126 | while(GetMessage(&msg,hwnd))
127 | {
128 | TranslateMessage(&msg);
129 | DispatchMessage(&msg);
130 | }
131 | }
132 |
133 | 创建父窗口,标题栏为“GUI Demo - Progressbar”,带有大小边框,设置win_proc作为窗口回调函数。
134 |
135 | (2) 窗口回调函数
136 |
137 | 1. WM_CREATE
138 |
139 | .. code-block:: c
140 | :caption: 代码清单 10‑4 WM_CREATE消息响应(文件GUI_DEMO_Progressbar.c)
141 | :linenos:
142 | :name: 代码清单10_4
143 |
144 | case WM_CREATE:
145 | {
146 | GetClientRect(hwnd,&rc);
147 | if(1)
148 | {
149 | //PROGRESSBAR_CFG结构体的大小
150 | cfg.cbSize = sizeof(PROGRESSBAR_CFG);
151 | //开启所有的功能
152 | cfg.fMask = PB_CFG_ALL;
153 | //文字格式水平,垂直居中
154 | cfg.TextFlag = DT_VCENTER|DT_CENTER;
155 | // 创建自绘制的进度条VProgressbar
156 | wnd = CreateWindow(PROGRESSBAR,L"VProgressbar",
157 | WS_OWNERDRAW|PBS_ALIGN_BOTTOM|WS_VISIBLE,
158 | 20,20,48,320,hwnd,ID_PROGBAR1,NULL,NULL);
159 | //初始化PROGRESSBAR_CFG结构体
160 | SendMessage(wnd,PBM_GET_CFG,TRUE,(LPARAM)&cfg);
161 | SendMessage(wnd,PBM_SET_CFG,TRUE,(LPARAM)&cfg);
162 | // 创建从右往左增长的进度条VProgressbar
163 | wnd = CreateWindow(PROGRESSBAR,L"PROGBAR2 & Right align",
164 | PBS_TEXT|PBS_ALIGN_RIGHT|WS_VISIBLE,
165 | 100,100,280,48,hwnd,ID_PROGBAR2,NULL,NULL);
166 | SendMessage(wnd,PBM_GET_CFG,TRUE,(LPARAM)&cfg);
167 | SendMessage(wnd,PBM_SET_CFG,TRUE,(LPARAM)&cfg);
168 | //创建从左往右增长的进度条VProgressbar
169 | wnd = CreateWindow(PROGRESSBAR,L"PROGBAR3 & Left align",
170 | PBS_TEXT|PBS_ALIGN_LEFT|WS_VISIBLE,
171 | 100,200,280,48,hwnd,ID_PROGBAR3,NULL,NULL);
172 | SendMessage(wnd,PBM_GET_CFG,TRUE,(LPARAM)&cfg);
173 | SendMessage(wnd,PBM_SET_CFG,TRUE,(LPARAM)&cfg);
174 | }
175 | //创建EXIT按钮
176 | CreateWindow(BUTTON,L"EXIT",WS_VISIBLE,rc.w-100,8,80,48,hwnd,ID_EXIT,NULL,NULL);
177 | //创建200ms定时器
178 | SetTimer(hwnd,1,200,TMR_START,NULL);
179 | return TRUE;
180 | }
181 |
182 | 调用CreateWindow函数创建进度条控件,发送PBM_SET_CFG消息来配置进度条。cbSize的值必须为sizeof(PROGRESSBAR_CFG)。创建EXIT按钮,用来关闭窗口以及创建200ms定时器。
183 |
184 | 2. WM_TIMER
185 |
186 | .. code-block:: c
187 | :caption: 代码清单 10‑5 WM_TIMER消息响应(文件GUI_DEMO_Progressbar.c)
188 | :linenos:
189 | :name: 代码清单10_5
190 |
191 | case WM_TIMER:
192 | {
193 | pb1_val +=1;
194 | if(pb1_val > 100)
195 | {
196 | pb1_val =0;
197 | }
198 | wnd =GetDlgItem(hwnd,ID_PROGBAR1);
199 | //设置进度值
200 | SendMessage(wnd,PBM_SET_VALUE,TRUE,pb1_val);
201 | pb2_val +=2;
202 | if(pb2_val > 100)
203 | {
204 | pb2_val =0;
205 | }
206 | //获取窗口句柄
207 | wnd =GetDlgItem(hwnd,ID_PROGBAR2);
208 | SendMessage(wnd,PBM_SET_VALUE,TRUE,pb2_val);
209 |
210 | wnd =GetDlgItem(hwnd,ID_PROGBAR3);
211 | SendMessage(wnd,PBM_SET_VALUE,TRUE,pb2_val);
212 | return TRUE;
213 | }
214 |
215 | 每当200ms计时结束时,就会将pb1_val值加1,pb2_val的值加2。调用GetDlgItem获取进度条控件的窗口句柄,同时将进度值发送给窗口,来实现实时更新进度条的进度值。
216 |
217 | 3. WM_CLOSE
218 |
219 | .. code-block:: c
220 | :caption: 代码清单 10‑6 WM\_ CLOSE消息响应(文件GUI_DEMO_Progressbar.c)
221 | :linenos:
222 | :name: 代码清单10_6
223 |
224 | case WM_CLOSE:
225 | {
226 | pb1_val=0;
227 | pb2_val=0;
228 | break;
229 | }
230 |
231 | 在WM_CLOSE中,对两个变量的值进行清零操作。
232 |
233 | 4. WM_CTLCOLOR
234 |
235 | .. code-block:: c
236 | :caption: 代码清单 10‑7 WM\_ CTLCOLOR消息响应(文件GUI_DEMO_Progressbar.c)
237 | :linenos:
238 | :name: 代码清单10_7
239 |
240 | case WM_CTLCOLOR:
241 | {
242 | u16 id;
243 | CTLCOLOR *cr;
244 |
245 | id =wParam;
246 | cr =(CTLCOLOR*)lParam;
247 | if(id==ID_PROGBAR3)
248 | {
249 | cr->TextColor =RGB888(250,250,250);
250 | cr->BackColor =RGB888(0,0,0);
251 | cr->BorderColor =RGB888(130,30,130);
252 | cr->ForeColor =RGB888(200,0,200);
253 | return TRUE;
254 | }
255 | return FALSE;
256 | }
257 |
258 | 在WM_CTLCOLOR消息中,改变进度条控件PROGBAR3 的外观颜色。
259 |
260 | 5. WM_NOTIFY
261 |
262 | .. code-block:: c
263 | :caption: 代码清单 10‑8 WM\_ NOTIFY消息响应(文件GUI_DEMO_Progressbar.c)
264 | :linenos:
265 | :name: 代码清单10_8
266 |
267 | case WM_NOTIFY:
268 | {
269 | u16 code,id;
270 | id =LOWORD(wParam);
271 | code=HIWORD(wParam);
272 | if(id== ID_EXIT && code==BN_CLICKED)
273 | { // EXIT按钮弹起
274 | PostCloseMessage(hwnd); //产生WM_CLOSE消息关闭主窗口
275 | }
276 | }
277 |
278 | 按下EXIT按键,产生WM_CLOSE消息关闭主窗口。
279 |
280 | 6. WM_DRAWITEM
281 |
282 | .. code-block:: c
283 | :caption: 代码清单 10‑9 WM_DRAWITEM消息响应(文件GUI_DEMO_Progressbar.c)
284 | :linenos:
285 | :name: 代码清单10_9
286 |
287 | case WM_DRAWITEM:
288 | {
289 | DRAWITEM_HDR *ds;
290 |
291 | ds =(DRAWITEM_HDR*)lParam;
292 | progressbar_owner_draw(ds);
293 | return TRUE;
294 | }
295 |
296 | 进度条控件PROGBAR1拥有自定义绘制属性WS_OWNERDRAW,在绘制前都会给父窗口发送WM_DRAWITEM消息。在WM_DRAWITEM消息中,调用函数progressbar_owner_draw实现控件自定义,最后返回TURE。这里必须返回TURE,否则会按照默认方案进行配置。
297 |
298 | .. code-block:: c
299 | :caption: 代码清单 10‑10 progressbar_owner_draw函数(文件GUI_DEMO_Progressbar.c)
300 | :linenos:
301 | :name: 代码清单10_10
302 |
303 | static void progressbar_owner_draw(DRAWITEM_HDR *ds)
304 | {
305 | HWND hwnd;
306 | HDC hdc;
307 | RECT rc,m_rc[2];
308 | // int range,val;
309 | WCHAR wbuf[128];
310 | PROGRESSBAR_CFG cfg;
311 | hwnd =ds->hwnd;
312 | hdc =ds->hDC;
313 | /* 第一步 */
314 | //获取客户区矩形位置,大小
315 | GetClientRect(hwnd,&rc);
316 | //设置进度条的背景颜色
317 | SetBrushColor(hdc,MapRGB(hdc,150,200,250));
318 | //填充进度条的背景
319 | FillRect(hdc,&ds->rc);
320 | //绘制进度条的背景边框
321 | DrawRect(hdc,&rc);
322 | /* 第二步 */
323 | cfg.cbSize =sizeof(cfg);
324 | cfg.fMask =PB_CFG_ALL;
325 | SendMessage(hwnd,PBM_GET_CFG,0,(LPARAM)&cfg);
326 | //生成进度条矩形
327 | MakeProgressRect(m_rc,&rc,cfg.Rangle,cfg.Value,PB_ORG_BOTTOM);
328 | //设置进度条的颜色
329 | SetBrushColor(hdc,MapRGB(hdc,250,10,10));
330 | //填充进度条
331 | FillRoundRect(hdc,&m_rc[0],2);
332 | //设置画笔颜色
333 | SetPenColor(hdc,MapRGB(hdc,100,10,10));
334 | //绘制进度条的边框,采用圆角边框
335 | DrawRoundRect(hdc,&m_rc[0],2);
336 | /* 显示进度值 */
337 | x_wsprintf(wbuf,L"%d",cfg.Value);
338 | //InflateRect(&rc,40,0);
339 | DrawText(hdc,wbuf,-1,&rc,DT_VCENTER|DT_CENTER);
340 | }
341 |
342 | 进度条,其实是由两个部分构成,如 图10_3_ ,是进度度条的背景,是已经完成的进度。只要我们可以绘制这样的两个矩形,同时将它俩叠加到一块的话,就可以得到处的进度条了。
343 |
344 | .. image:: /media/docx043.jpg
345 | :align: center
346 | :alt: 图 10‑3 原理绘制原理
347 | :name: 图10_3
348 |
349 | 图 10‑3 原理绘制原理
350 |
351 | 代码清单10_10_ 中的第一步,就是绘制一个处的矩形框框。调用GetClientRect函数获取子控件的位置,大小。使用SetBrushColor和SetPenColor来设置背景和边框的颜色,最后调用FillRect和DrawRect来绘制成。
352 |
353 | 代码清单10_10_ 中的第二步,对应上图的处。发送消息PBM_GET_CFG,来获得进度条的配置参数,主要是当前的进度值。发送消息前,必须要将cbSize值设置成
354 | sizeof(PROGRESSBAR_CFG),同时将fMask设置为PB_CFG_ALL,才可以得到正确的参数值。调用MakeProgressRect函数,最终输出时,m_rc[0]为已完成的进度矩形 。调用SetBrushColor、FillRoundRect和DrawRoundRect来绘制的
355 | 矩形。处的叠加过程,实际上在调用MakeProgressRect函数的时候,就已经完成了。因为MakeProgressRect函数的第二个参数的作用是,使输出m_rc的矩形位置和大小限定在控件的范围中。关于MakeProgressRect函数的具体说明,请参考《emXGUI
356 | API编程手册》的章节:位置及区域操作运算API。
357 |
358 | 最后,将GUI_DEMO_Progressbar加入到GUI_AppMain中,见 代码清单10_11_。
359 |
360 | .. code-block:: c
361 | :caption: 代码清单 10‑11 GUI_AppMain函数(文件GUI_AppMain.c)
362 | :linenos:
363 | :name: 代码清单10_11
364 |
365 | void GUI_AppMain(void)
366 | {
367 | while(1)
368 | {
369 | GUI_DEMO_Hello();
370 | GUI_DEMO_Button();
371 | GUI_DEMO_Checkbox();
372 | GUI_DEMO_Radiobox();
373 | GUI_DEMO_Textbox();
374 |
375 | GUI_DEMO_Progressbar();
376 | }
377 | }
378 |
379 | .. _实验现象-5:
380 |
381 | 实验现象
382 | ^^^^^^^^^^^^
383 |
384 | 实验结果,如图 10‑4所示。最左边的是PROGBAR1,是在progressbar_owner_draw函数绘制的进度条。PROGBAR2和PROGBAR3是系统自带的进度条,它们的增长方式相反,同时我们还通过WM_CTLCOLOR消息改变了PROGBAR3的外观颜色。
385 |
386 | .. image:: /media/docx044.jpg
387 | :align: center
388 | :alt: 图 10‑4 实验结果
389 | :name: 图10_4
390 |
--------------------------------------------------------------------------------
/section_one/section11.rst:
--------------------------------------------------------------------------------
1 | .. vim: syntax=rst
2 |
3 | 对话框控件
4 | ---------------
5 |
6 | 对话框一般情况下,用于确认信息。最简单的对话框是警告,当我们关闭窗口时,为了确认用户是有意或无意的关闭动作,会弹出一个对话框进行简单的确认,如 图11_1_,弹出对话框,是否需要进行文档的保存。
7 |
8 | .. image:: /media/docx045.jpg
9 | :align: center
10 | :alt: 图 11‑1 对话框
11 | :name: 图11_1
12 |
13 | 创建对话框控件
14 | ~~~~~~~~~~~~~~~~~~~~~
15 |
16 | .. _标准消息类型及参数说明-6:
17 |
18 | 标准消息类型及参数说明
19 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
20 |
21 | 本章使用的消息类型常用的有WM_CREATE、WM_NOTIFY。WM_CREATE消息用于创建控件; WM_NOTIFY消息用来处理按钮消息。还有一个新的消息类型:WM_DESTROY。
22 |
23 | 我们常常在EXIT按键的WM_NOTIFY中调用PostCloseMessage来关闭窗口。当PostCloseMessage产生 WM_CLOSE 消息时,这时用户还可以"选择"是否真正要关闭窗口,如果是,则调用DestroyWindow函数。DestroyWindows函数会再产生
24 | WM_DESTROY消息。当收到WM_DESTROY时,说明窗口已经执行"注销"并结束了,在WM_DESTROY消息中可以做一些资源释放的操作。
25 |
26 | 对话框配置结构体
27 | ^^^^^^^^^^^^^^^^^^^^^^^^
28 |
29 | emXGUI可以通过配置__MSGBOXOPTIONS结构体,来改变对话框内部的控件,如按键的个数,文字等,结构体__MSGBOXOPTIONS,见 代码清单11_1_。
30 |
31 | .. code-block:: c
32 | :caption: 代码清单 11‑1 对话框配置结构体__MSGBOXOPTIONS
33 | :linenos:
34 | :name: 代码清单11_1
35 |
36 | typedef struct __MSGBOXOPTIONS
37 | {
38 | const WCHAR **pButtonText; //按键文字
39 | int ButtonCount; //按键个数
40 | u32 Flag; //消息框的图标
41 | }MSGBOX_OPTIONS;
42 |
43 | 1) pButtonText:存放按键显示文字,有几个按键,就需要几个字符串。
44 |
45 | 2) ButtonCount:对话框内按键的个数。
46 |
47 | 3) Flag:消息框的标志位。用来控制消息框的图标以及按钮宽度。可以是
48 |
49 | 显示 "出错" 图标(MB_ICONERROR)、"询问" 图标(MB_ICONQUESTION)、"警告" 图标(MB_ICONWARNING)和"信息"
50 | 图标(MB_ICONINFORMATION)。按钮宽度可以通过MB_BTN_WIDTH来设置,也可以由系统自动设置按钮宽度(MB_BTN_AUTOSIZE)。
51 |
52 | 创建对话框控件函数
53 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
54 |
55 | emXGUI调用MessageBox函数创建对话框控件,同时会返回一个int类型的数据,用户可以通过该返回值,来确认对话框的哪一个按钮被按下。见 代码清单11_2_
56 |
57 | .. code-block:: c
58 | :caption: 代码清单 11‑2创建对话框控件函数MessageBox
59 | :linenos:
60 | :name: 代码清单11_2
61 |
62 | int MessageBox(HWND hwndParent,int x,int y,int w,int h,
63 | const WCHAR *pText,const WCHAR *pCaption,
64 | const MSGBOX_OPTIONS *opt);
65 |
66 | 1. hwndParent:对话框所属的父窗口。控件不可以脱离窗口而存在,通过该成员来指定该控件是属于哪一个父窗口。
67 |
68 | 2. x, y,w,h:分别是对话框的起点坐标(x,y)以及对话框的宽w,高h。
69 |
70 | 3. pText:对话框显示的内容,使用宽字符型字符串。
71 |
72 | 4. pCaption:对话框的标题,同样使用宽字符型字符串。
73 |
74 | 5. opt:对话框配置结构体。调用MessageBox函数创建对话框时,作为参数,来配置对话框的布局。
75 |
76 | 创建对话框控件实验
77 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
78 |
79 | .. _设计要求-6:
80 |
81 | 设计要求
82 | ^^^^^^^^^^^^
83 |
84 | 图11_2_ 是本章的设计要求。解释一下:这里的三个对话框,是分别对于三个按钮,且只有按下按钮,对话框才会出现。为了节约篇幅,所以将三个对话框,放在一张图片中。通过点击对话框内的按钮,会返回相应的值,例程中只实现了将返回值输出到串口。
85 |
86 | .. image:: /media/docx046.jpg
87 | :align: center
88 | :alt: 图 11‑2 设计要求
89 | :name: 图11_2
90 |
91 | .. _代码分析-6:
92 |
93 | 代码分析
94 | ^^^^^^^^^^^^
95 |
96 | (1) 创建父窗口
97 |
98 | .. code-block:: c
99 | :caption: 代码清单 11‑3 GUI_DEMO_Messagebox函数(文件GUI_DEMO_Messagebox.c)
100 | :linenos:
101 | :name: 代码清单11_3
102 |
103 | void GUI_DEMO_Messagebox(void)
104 | {
105 | HWND hwnd;
106 | WNDCLASS wcex;
107 | MSG msg;
108 | //
109 | wcex.Tag = WNDCLASS_TAG;
110 | wcex.Style = CS_HREDRAW | CS_VREDRAW;
111 | wcex.lpfnWndProc = WinProc; //设置主窗口消息处理的回调函数.
112 |
113 | wcex.cbClsExtra = 0;
114 | wcex.cbWndExtra = 0;
115 | wcex.hInstance = NULL;//hInst;
116 | wcex.hIcon = NULL;//LoadIcon(hInstance, (LPCTSTR)IDI_WIN32_APP_TEST);
117 | wcex.hCursor = NULL;//LoadCursor(NULL, IDC_ARROW);
118 | //创建主窗口
119 | hwnd =CreateWindowEx( NULL,
120 | &wcex,
121 | _T("GUI_DEMO-Messagebox"),
122 | WS_CAPTION|WS_DLGFRAME|WS_BORDER|WS_CLIPCHILDREN,
123 | 10,20,440,240,
124 | NULL,NULL,NULL,NULL);
125 | //显示主窗口
126 | ShowWindow(hwnd,SW_SHOW);
127 | //开始窗口消息循环(窗口关闭并销毁时,GetMessage将返回FALSE,退出本消息循环)。
128 | while(GetMessage(&msg,hwnd))
129 | {
130 | TranslateMessage(&msg);
131 | DispatchMessage(&msg);
132 | }
133 | }
134 |
135 | 创建父窗口,标题栏为“GUI Demo - Messagebox”,带有大小边框,设置WinProc作为窗口回调函数。
136 |
137 | (2) 窗口回调函数
138 |
139 | 1. WM_CREATE
140 |
141 | .. code-block:: c
142 | :caption: 代码清单 11‑4 WM_CREATE消息响应(文件GUI_DEMO_Messagebox.c)
143 | :linenos:
144 | :name: 代码清单11_4
145 |
146 | case WM_CREATE: //窗口创建时,会自动产生该消息,在这里做一些初始化的操作或创建子窗口
147 | {
148 | GetClientRect(hwnd,&rc); //获得窗口的客户区矩形
149 | CreateWindow(BUTTON,L"OK",WS_VISIBLE,
150 | rc.w-80,8,68,32,hwnd,ID_OK,NULL,NULL);
151 | rc.x =20;
152 | rc.y =30;
153 | rc.w =100;
154 | rc.h =40;
155 |
156 | //创建按钮
157 | CreateWindow(BUTTON,L"Msgbox-1",WS_VISIBLE,
158 | rc.x,rc.y,rc.w,rc.h,hwnd,ID_BTN1,NULL,NULL);
159 | //往下移动矩形位置(X轴增加rc.w+10个像素)
160 | OffsetRect(&rc,rc.w+10,0);
161 | CreateWindow(BUTTON,L"Msgbox-2",WS_VISIBLE,
162 | rc.x,rc.y,rc.w,rc.h,hwnd,ID_BTN2,NULL,NULL);
163 | OffsetRect(&rc,rc.w+10,0);
164 | CreateWindow(BUTTON,L"Msgbox-3",WS_VISIBLE,
165 | rc.x,rc.y,rc.w,rc.h,hwnd,ID_BTN3,NULL,NULL);
166 | return TRUE;
167 | }
168 |
169 | 代码清单11_4_ 中,创建了四个按钮。点击BTN1、BTN2和BTN3按钮,会弹出相应的对话框。OK按钮用来关闭父窗口。
170 |
171 | 2. WM_DESTROY
172 |
173 | .. code-block:: c
174 | :caption: 代码清单 11‑5 WM_DESTROY消息响应(文件GUI_DEMO_Messagebox.c)
175 | :linenos:
176 | :name: 代码清单11_5
177 |
178 | case WM_DESTROY: //窗口销毁时,会自动产生该消息,在这里做一些资源释放的操作.
179 | {
180 | return PostQuitMessage(hwnd); //调用PostQuitMessage,使用主窗口结束并退出消息循环.
181 | }
182 |
183 | 调用PostQuitMessage,使用主窗口结束并退出消息循环。具体说明,可以参考《emXGUI API编程手册》的章节:标准消息类型及参数说明。
184 |
185 | 3. WM_NOTIFY
186 |
187 | .. code-block:: c
188 | :caption: 代码清单 11‑6 WM_NOTIFY消息响应(文件GUI_DEMO_Messagebox.c)
189 | :linenos:
190 | :name: 代码清单11_6
191 |
192 | //WM_NOTIFY消息:wParam低16位为发送该消息的控件ID,高16位为通知码;lParam指向了一个NMHDR结构体.
193 | case WM_NOTIFY:
194 | {
195 | u16 code,id;
196 | int ret=0;
197 | code =HIWORD(wParam); //获得通知码类型.
198 | id =LOWORD(wParam); //获得产生该消息的控件ID.
199 | if(id==ID_OK && code==BN_CLICKED)
200 | {
201 |
202 | PostCloseMessage(hwnd); //产生WM_CLOSE消息关闭窗口
203 | }
204 | if(id==ID_BTN1 && code==BN_CLICKED)
205 | {
206 | ret=MessageBox(hwnd,10,20,200,120,L"Hello!",L"MsgBox-1",NULL);
207 | }
208 | if(id==ID_BTN2 && code==BN_CLICKED)
209 | {
210 | const WCHAR *btn[] ={L"YES",L"NO",}; //对话框内按钮的文字
211 | MSGBOX_OPTIONS mb;
212 | mb.Flag =MB_BTN_WIDTH(80)|MB_ICONWARNING; //按钮的宽度为80px,使用警告图标
213 | mb.pButtonText =btn;
214 | mb.ButtonCount=2; //对话框内创建两个按钮
215 | ret=MessageBox(hwnd,10,20,320,150,
216 | L"MB_YESNO + MB_ICON\r\nABCDEFG",L"MsgBox-2",&mb);
217 | }
218 | if(id==ID_BTN3 && code==BN_CLICKED)
219 | {
220 | const WCHAR *btn[] ={L"Yes to all",L"取消",L"确认>>"};
221 | MSGBOX_OPTIONS mb;
222 | mb.Flag =MB_ICONINFORMATION; //使用信息图标
223 | mb.pButtonText =btn;
224 | mb.ButtonCount=3;
225 | ret=MessageBox(hwnd,10,20,360,180,
226 | L"Auto size + MB_ICON\r\nMulti-Line",L"MsgBox-3",&mb);
227 | }
228 | GUI_Printf("Messagebox Return:%d\r\n",ret);
229 | break;
230 | }
231 |
232 | 利用HIWORD和LOWORD函数来获取控件的ID和通知码。对于BTN2,定义了一个MSGBOX_OPTIONS类型的变量mb,使用警告图标,对话框内创建两个按钮,宽度为80px,显示的文字为“YES”和“NO”。我们点击其中一个按钮,MessageBox函数会有返回值,存放在ret中。这个值就是按
233 | 钮对应的文字下标,如点击YSE,会返回0;点击NO,则会返回1
234 |
235 | BTN3使用信息图标,对话框内有三个按钮,显示的文字为“YES to all”、“取消”和“确认”,最后把ret的值打印到串口。
236 |
237 | 这样窗口就设计完成了,将GUI_DEMO_Messagebox函数加入到GUI_AppMain中,见 代码清单11_7_
238 |
239 | .. code-block:: c
240 | :caption: 代码清单 11‑7 GUI_AppMain函数(文件GUI_AppMain.c)
241 | :linenos:
242 | :name: 代码清单11_7
243 |
244 | void GUI_AppMain(void)
245 | {
246 | while(1)
247 | {
248 | GUI_DEMO_Button();
249 | GUI_DEMO_Checkbox();
250 | GUI_DEMO_Radiobox();
251 | GUI_DEMO_Textbox();
252 | GUI_DEMO_Progressbar();
253 |
254 | GUI_DEMO_Messagebox();
255 | }
256 | }
257 |
258 | .. _实验现象-6:
259 |
260 | 实验现象
261 | ^^^^^^^^^^^^
262 |
263 | 如 图11_3_ ,我们点击Msgbox-2按钮,此时,会弹出Msgbox-2的对话框。点击YSE的的时候,串口会输出0,见 图11_4_。
264 |
265 | .. image:: /media/docx047.jpg
266 | :align: center
267 | :alt: 图 11‑3 实验结果
268 | :name: 图11_3
269 |
270 | 图 11‑3 实验结果
271 |
272 | .. image:: /media/docx048.jpg
273 | :align: center
274 | :alt: 图 11‑4串口输出结果
275 | :name: 图11_4
276 |
277 | 图 11‑4串口输出结果
278 |
279 |
--------------------------------------------------------------------------------
/section_one/section12.rst:
--------------------------------------------------------------------------------
1 | .. vim: syntax=rst
2 |
3 | 滚动条控件
4 | ---------------
5 |
6 | 在我们使用WINDOWS的软件的时候,右侧有一个条,用于翻页,他就是滚动条,如 图12_1_,由滚动滑块和滚动箭头组成。滚动条可以用于滚动列表框或任何其他类型的窗口。滚动条的方向确定用户操作滚动条时滚动的方向。水平滚动条只允许用户向左或向右滚动窗口的内容,垂直滚动条允许用户向上或向下滚动内容。
7 |
8 | .. image:: /media/docx049.jpg
9 | :align: center
10 | :alt: 图 12‑1滚动条
11 | :name: 图12_1
12 |
13 | 创建滚动条
14 | ~~~~~~~~~~~~~~~
15 |
16 | .. _标准消息类型及参数说明-7:
17 |
18 | 标准消息类型及参数说明
19 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
20 |
21 | 本章使用的消息类型有:WM_CREATE、WM_NOTIFY、WM_CTLCOLOR和WM_DRAWITEM。这些消息的参数及作用,前面已经解释得很详细了。这里只讲解一下,WM_NOTIFY在滚动条中的用法。
22 |
23 | WM_NOTIFY的wParam低16位存放着发送该消息的控件ID,lParam参数是以NMHDR结构体开头,实际为 NM_SCROLLBAR扩展结构,里面附带了更多的信息,见 代码清单12_1_。
24 | 一般采用NMHDR结构体的code来判断是否发生单击事件,是的话则通过NM_SCROLLBAR的cmd成员判断用户单击的位置。
25 |
26 | .. code-block:: c
27 | :caption: 代码清单 12‑1 滚动条通知命令(文件emXGUI.h)
28 | :linenos:
29 | :name: 代码清单12_1
30 |
31 | #define SB_TRACK (0) //点击滑块
32 | #define SB_ARROWUP (1) //单击上箭头
33 | #define SB_ARROWDOWN (2) //单击上箭头
34 | #define SB_PAGEUP (3) //单击滚动条的上半部分(空白区域)
35 | #define SB_PAGEDOWN (4) //单击滚动条的下半部分(空白区域)
36 |
37 | #define SB_ARROWLEFT (5) //单击左箭头
38 | #define SB_ARROWRIGHT (6) //单击右箭头
39 | #define SB_PAGELEFT (7) //单击滚动条的左半部分(空白区域)
40 |
41 | #define SB_PAGERIGHT (8) //单击滚动条的右半部分(空白区域)
42 |
43 | 以水平滚动条为例,见 图12_2_ ,讲解一下上面的命令。
44 |
45 | .. image:: /media/docx050.jpg
46 | :align: center
47 | :alt: 图 12‑2 滚动条命令
48 | :name: 图12_2
49 |
50 | 代码清单12_2_ 中的SB_ARROWLEFT及SB_ARROWRIGHT就是 图12_2_ 中的最左端和最右端的箭头。而SB_PAGELEFT对应的是 图12_2_ 中处,SB_PAGERIGHT对应的 是 图12_2_ 中处。
51 |
52 | 滚动条配置结构体
53 | ^^^^^^^^^^^^^^^^^^^^^^^^
54 |
55 | 创建滚动条之后,需要发送SBM_SETSCROLLINFO消息,来配置滚动条的参数,这些参数都存放在SCROLLINFO结构体中,见代码清单 12‑2。
56 |
57 | .. code-block:: c
58 | :caption: 代码清单 12‑2 SCROLLINFO结构体(文件emXGUI.h)
59 | :linenos:
60 | :name: 代码清单12_2
61 |
62 | typedef struct tagSCROLLINFO
63 | {
64 | u16 cbSize; //SCROLLINFO结构体大小
65 | u16 fMask; //功能选择位
66 | s32 nMin; //最小值
67 | s32 nMax; //最大值
68 | s32 nValue; //当前值
69 | u16 TrackSize; //滑块大小
70 | u16 ArrowSize; //箭头框的大小
71 | }SCROLLINFO,SCROLLBAR_CFG;
72 |
73 | 1) cbSize:用来存放结构体的大小。必须要将cbSize值设置成 sizeof(SCROLLINFO)。
74 |
75 | 2) fMask:功能选择位。只有相应的 MASK 位置1,才会更新到滚动条控件的内部数据结构体。
76 |
77 | 3) nMin、nMax、nValue:滚动条的最小值,最大值和当前值。
78 |
79 | 4) TrackSize:滑块的大小。对于水平滚动条,这里指的是滑块的宽度,而垂直滚动条,则是滑块的高度。
80 |
81 | 5) ArrowSize:箭头框的大小。对于水平滚动条,指的是箭头框的水平宽度,高度就是控件的客户区高度。对于垂直滚动条,是箭头框"的垂直高度,宽度就是控件的客户区宽度。
82 |
83 | 以水平滚动条为例,如 图12_3_。
84 |
85 | .. image:: /media/docx051.jpg
86 | :align: center
87 | :alt: 图 12‑3 SCROLLINFO结构体
88 | :name: 图12_3
89 |
90 | 创建滚动条控件函数
91 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
92 |
93 | .. code-block:: c
94 | :caption: 代码清单 12‑3创建窗口函数(文件emXGUI.h)
95 | :linenos:
96 | :name: 代码清单12_3
97 |
98 | HWND CreateWindowEx( U32 dwExStyle, LPCVOID lpClass, LPCWSTR lpWindowName,
99 | U32 dwStyle, int x, int y, int nWidth, int nHeight,
100 | HWND hwndParent, UINT WinId,HINSTANCE hInstance,LPVOID lpParam);
101 |
102 | 1) lpClass:窗口类。对于系统标准控件,可以为:BUTTON(常规按钮,复选框,单选框,组合框),SCROLLBAR(水平/垂直滚动条), LISTBOX(列表框)。TEXTBOX(文本框)…等等。这里选择SCROLLBAR。
103 |
104 | 2) dwStyle:滚动条的风格。参数SBS_VERT代表垂直风格类型。参数SBS_HORZ表示水平风格类型。SBS_LEFT_ALIGN表示左对齐增长方式,如果向左增长方式,往左移动滑块,数值就是增大,往右就减小。SBS_RIGHT_ALIGN表示右对齐增长方式。滚动条控件支持窗口风格参数。
105 |
106 | 至于其他的参数,也是同样的用法,这里不作描述。我们创建控件调用的CreateWindow函数,实际上就是CreateWindowEx函数
107 |
108 | 创建滚动条控件实验
109 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
110 |
111 | .. _设计要求-7:
112 |
113 | 设计要求
114 | ^^^^^^^^^^^^
115 |
116 | 设计一个窗口,如 图12_4_ 所示。有三个滚动条,分别是垂直风格,自绘制外观风格、水平风格(从左往右,从上到下)。
117 |
118 | .. image:: /media/docx052.jpg
119 | :align: center
120 | :alt: 图 12‑4 设计要求
121 | :name: 图12_4
122 |
123 | .. _代码分析-7:
124 |
125 | 代码分析
126 | ^^^^^^^^^^^^
127 |
128 | (1) 创建父窗口
129 |
130 | .. code-block:: c
131 | :caption: 代码清单 12‑4 GUI_DEMO\_ Scrollbar函数(文件GUI_DEMO\_ Scrollbar.c)
132 | :linenos:
133 | :name: 代码清单12_4
134 |
135 | void GUI_DEMO_Scrollbar(void)
136 | {
137 | HWND hwnd;
138 | WNDCLASS wcex;
139 | MSG msg;
140 | wcex.Tag = WNDCLASS_TAG;
141 | wcex.Style = CS_HREDRAW | CS_VREDRAW;
142 | wcex.lpfnWndProc = win_proc;
143 | wcex.cbClsExtra = 0;
144 |
145 | wcex.cbWndExtra = 0;
146 | wcex.hInstance = 0;//hInst;
147 | wcex.hIcon = 0;//LoadIcon(hInstance, (LPCTSTR)IDI_WIN32_APP_TEST);
148 | wcex.hCursor = 0;//LoadCursor(NULL, IDC_ARROW);
149 | hwnd =CreateWindowEx( NULL,
150 | &wcex,
151 | _T("GUI Demo - Scrollbar"),
152 | /*WS_MEMSURFACE|*/WS_CAPTION|WS_DLGFRAME|WS_BORDER|WS_CLIPCHILDREN,
153 | 0,0,GUI_XSIZE,GUI_YSIZE,
154 | NULL,NULL,NULL,NULL);
155 | ShowWindow(hwnd,SW_SHOW);
156 | while(GetMessage(&msg,hwnd))
157 | {
158 | TranslateMessage(&msg);
159 | DispatchMessage(&msg);
160 | }
161 | }
162 |
163 | 创建父窗口,标题栏为“GUI Demo - Scrollbar”,带有大小边框,设置WinProc作为窗口回调函数。
164 |
165 | (2) 窗口回调函数
166 |
167 | 1. WM_CREATE
168 |
169 | .. code-block:: c
170 | :caption: 代码清单 12‑5 WM_CREATE消息响应(文件GUI_DEMO\_ Scrollbar.c)
171 | :linenos:
172 | :name: 代码清单12_5
173 |
174 | case WM_CREATE:
175 | {
176 | GetClientRect(hwnd,&rc);
177 | if(1)
178 | {
179 | //滚动条参数结构体
180 | SCROLLINFO sif;
181 | sif.cbSize =sizeof(sif);//结构体大小
182 | sif.fMask =SIF_ALL; //使能所有功能
183 |
184 | //取值范围:-50~50
185 | sif.nMin =-50;
186 | sif.nMax =+50;
187 | //当前值为0
188 | sif.nValue =0;
189 | //滑块的大小为60
190 | sif.TrackSize =60;
191 | //两端的大小为60
192 | sif.ArrowSize =60;
193 | //创建垂直风格滑动条
194 | wnd = CreateWindow(SCROLLBAR,L"VScroll",SBS_VERT|WS_VISIBLE,
195 | 40,20,40,400,hwnd,ID_SCROLLBAR1,NULL,NULL);
196 | //配置滑动条的属性
197 | SendMessage(wnd,SBM_SETSCROLLINFO,TRUE,(LPARAM)&sif);
198 | //创建自绘制滑动条
199 | wnd = CreateWindow(SCROLLBAR,L"HScroll",WS_OWNERDRAW|WS_VISIBLE,
200 | 130,120,400,40,hwnd,ID_SCROLLBAR2,NULL,NULL);
201 | SendMessage(wnd,SBM_SETSCROLLINFO,TRUE,(LPARAM)&sif);
202 | //创建滑动条
203 | wnd = CreateWindow(SCROLLBAR,L"HScroll",WS_VISIBLE,
204 | 130,240,400,40,hwnd,ID_SCROLLBAR3,NULL,NULL);
205 | SendMessage(wnd,SBM_SETSCROLLINFO,TRUE,(LPARAM)&sif);
206 | }
207 | return TRUE;
208 | }
209 |
210 | 设置滚动条的取值范围在-50~50,滑块的大小为60px,初始位置位于0处,箭头框的大小为60px。调用CreateWindow函数来创建滚动条。创建完成后,发送消息SBM_SETSCROLLINFO来设置滚动条的属性。这里创建了三个滚动条,分别是SCROLLBAR1、SCROLLBAR2和SCROLLBAR3。
211 |
212 | 2. WM_CTLCOLOR
213 |
214 | .. code-block:: c
215 | :caption: 代码清单 12‑6 WM_CTLCOLOR消息响应(文件GUI_DEMO\_ Scrollbar.c)
216 | :linenos:
217 | :name: 代码清单12_6
218 |
219 | case WM_CTLCOLOR:
220 | {
221 | u16 id;
222 | id =LOWORD(wParam);
223 | if(id== ID_SCROLLBAR3)
224 | {
225 | CTLCOLOR *cr;
226 | cr =(CTLCOLOR*)lParam;
227 | cr->TextColor =RGB888(100,255,255);
228 |
229 | cr->BackColor =RGB888(100,100,150);
230 | cr->BorderColor =RGB888(50,50,150);
231 | cr->ForeColor =RGB888(50,150,250);
232 | return TRUE;
233 | }
234 | else
235 | {
236 | return FALSE;
237 | }
238 | }
239 |
240 | 在WM_CTLCOLOR中,对SCROLLBAR3滚动条的外观颜色进行更改,并返回TRUE。其余两个滚动条按照系统默认方案来配置。
241 |
242 | 3. WM_DRAWITEM
243 |
244 | .. code-block:: c
245 | :caption: 代码清单 12‑7 WM_DRAWITEM消息响应(文件GUI_DEMO\_ Scrollbar.c)
246 | :linenos:
247 | :name: 代码清单12_7
248 |
249 | case WM_DRAWITEM:
250 | {
251 | DRAWITEM_HDR *ds;
252 | ds =(DRAWITEM_HDR*)lParam;
253 | {
254 | scrollbar_owner_draw(ds);
255 | return TRUE;
256 | }
257 | }
258 |
259 | 滚动条控件SCROLLBAR2拥有自定义绘制属性WS_OWNERDRAW,在绘制前都会给父窗口发送WM_DRAWITEM消息。在WM_DRAWITEM消息中,调用函数scrollbar_owner_draw实现控件自定义,最后返回TURE。
260 |
261 | .. code-block:: c
262 | :caption: 代码清单 12‑8 scrollbar_owner_draw函数(文件GUI_DEMO\_ Scrollbar.c)
263 | :linenos:
264 | :name: 代码清单12_8
265 |
266 | static void scrollbar_owner_draw(DRAWITEM_HDR *ds)
267 | {
268 | HWND hwnd;
269 | HDC hdc;
270 | RECT rc;
271 | WCHAR wbuf[128];
272 | SCROLLINFO sif;
273 | hwnd =ds->hwnd;
274 | hdc =ds->hDC;
275 |
276 | //绘制滚动条的背景(第一步)
277 | SetBrushColor(hdc,MapRGB(hdc,150,200,250));
278 | FillRect(hdc,&ds->rc);
279 | sif.fMask =SIF_ALL;
280 | SendMessage(hwnd,SBM_GETSCROLLINFO,0,(LPARAM)&sif);
281 | //得到滑块的大小(第二步)
282 | SendMessage(hwnd,SBM_GETTRACKRECT,0,(LPARAM)&rc);
283 | //滑块被选中
284 | if(ds->State & SST_THUMBTRACK)
285 | {
286 | SetPenColor(hdc,MapRGB(hdc,250,50,50));
287 | }
288 | else//滑块未被选中
289 | {
290 | SetPenColor(hdc,MapRGB(hdc,50,50,50));
291 | }
292 | DrawRect(hdc,&rc);
293 | //显示滑块的位置
294 | x_wsprintf(wbuf,L"%d",sif.nValue);
295 |
296 | DrawText(hdc,wbuf,-1,&rc,DT_VCENTER|DT_CENTER);
297 | }
298 |
299 | 图12_4_ 的中滚动条SCROLLBAR2重绘,就是在窗口处绘制两个矩形,一个作为滚动条的背景,另一个则作为滑块。如 图12_5_ 所示。
300 |
301 | .. image:: /media/docx053.jpg
302 | :align: center
303 | :alt: 图 12‑5滚动条重绘
304 | :name: 图12_5
305 |
306 | 滚动条的背景重绘,通过调用SetBrushColor函数设置背景颜色,同时使用FillRect函数绘制一个矩形,如 图12_5_ 的处。
307 |
308 | 滚动条的滑块重绘,滑块的大小,受到滚动条控件的影响,对于本例程,不可以超过控件的高度。
309 | 发送SBM_GETSCROLLINFO消息来获得滚动条的配置信息,在发送消息之前,需要将成员fMask的值设置为SIF_ALL,否则的话,获取的内容不完整。
310 | 通过发送SBM_GETTRACKRECT消息来获得滑块的大小,这里指的是创建滚动条时,配置的TrackSize参数,保存到rc中。
311 | 判断滑块当前的状态,设置滑块边框的颜色,调用DrawRect来绘制边框,同时将滑块的当前显示出来,得到 图12_5_ 的处。
312 |
313 | 由于 图12_5_ 的处是处进行绘制,受到滚动条控件的位置以及大小的影响,所以绘制完成后,就可以得到的滚动条。图12_5_ 拆开,只是为了方便读者理解。
314 |
315 | 这样窗口就设计完成了,将GUI_DEMO_Scrollbar函数加入到GUI_AppMain中,见 代码清单12_9_
316 |
317 | .. code-block:: c
318 | :caption: 代码清单 12_9 GUI_AppMain函数(文件GUI_AppMain.c)
319 | :linenos:
320 | :name: 代码清单12_9
321 |
322 | void GUI_AppMain(void)
323 | {
324 | while(1)
325 | {
326 | GUI_DEMO_Button();//需要修改教程
327 | GUI_DEMO_Checkbox();
328 | GUI_DEMO_Radiobox();
329 | GUI_DEMO_Textbox();
330 | GUI_DEMO_Progressbar();//有瑕疵
331 |
332 | GUI_DEMO_Scrollbar();
333 | }
334 | }
335 |
336 | 实验结果
337 | ^^^^^^^^^^^^^^^^
338 |
339 | 实验结果如 图12_6_,单击SCROLLBAR1和SCROLLBAR2,会在串口输出单击的位置。当我们移动滑块SCROLLBAR2时,滑块的数字会发送改变,默认是右增长模式。
340 |
341 | .. image:: /media/docx054.jpg
342 | :align: center
343 | :alt: 图 12‑6 实验结果
344 | :name: 图12_6
345 |
346 | 图 12‑6 实验结果
347 |
--------------------------------------------------------------------------------
/section_one/section14.rst:
--------------------------------------------------------------------------------
1 | .. vim: syntax=rst
2 |
3 | 添加示例应用
4 | ------------------
--------------------------------------------------------------------------------
/section_one/section15.rst:
--------------------------------------------------------------------------------
1 | .. vim: syntax=rst
2 |
3 | 添加滑动窗口界面
4 | ------------------------
5 |
--------------------------------------------------------------------------------
/section_one/section18.rst:
--------------------------------------------------------------------------------
1 | .. vim: syntax=rst
2 |
3 |
4 | 野火GUI应用
5 | ---------------------
6 |
7 | 野火计划后续会推出基于STM32-ISO的emXGUI小程序,以独立的小程序讲解emXGUI的使用方式,让读者更加熟悉emXGUI,敬请期待。
8 |
9 | RTT系统初始化
10 | ~~~~~~~~~~~~~~~~~~~~~~~~
11 |
12 | RT-Thread在进行main函数前,在component.c文件中的rtthread_startup函数通过调用rt_hw_board_init初始化了systick、SDRAM、LED以及串口等外设。
13 |
14 | 初始化GUI
15 | ~~~~~~~~~~~~~~~~~~
16 |
17 | 操作系统运行后创建一个GUI专用任务,任务中调用GUI_Startup函数,它的执行流程如下:
18 |
19 | GUI低级初始化GUI_LowLevelInit
20 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
21 |
22 | GUI_LowLevelInit函数主要初始化分配给x_heap的堆空间、位置以及分配内存时的最小粒度,初始化后GUI可从x_heap中分配内存空间。用来管理SDRAM的空间
23 |
24 | GUI架构层初始化GUI_Arch_Init
25 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
26 |
27 | GUI_Arch_Init初始化GUI架构相关的内容,包含内核动态矩形链表初始化,它用于多窗口叠加时的Z序管理;还包含了不同的绘图对象,如使用8/16/32位像素格式时都有专门的内存操作函数。
28 |
29 | GUI内核初始化X_GUI_Init
30 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
31 |
32 | X_GUI_Init会初始化GUI内核,在使用GUI前必须调用它。
33 |
34 | 初始化液晶硬件GUI_DisplayInit
35 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
36 |
37 | GUI_DisplayInit函数初始化显示屏,用户需要自己根据外接的液晶屏初始化相应的硬件,并且需要在该函数内初始化绘图表面,初始化后把SURFACE返回。
38 |
39 | 设置绘图表面GUI_SetScreenSurface
40 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
41 |
42 | GUI_SetScreenSurface使用GUI_DisplayInit函数返回的绘图表面SURFACE进行初始化,设置屏幕对象。
43 |
44 | 初始化字体GUI_FontInit和GUI_SetDefFont
45 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
46 |
47 | GUI_FontInit函数初始化字体,使用初始化字体得到的HFONT作为函数GUI_SetDefFont的输入,可设置为默认字体。在GUI_FontInit函数中,可以设置字体的来源,如主控芯片的内部FLASH、外部的SPI-FLASH或SD卡等。
48 |
49 | 创建桌面GUI_DesktopStartup
50 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
51 |
52 | 以上一切准备就绪后,可通过调用GUI_DesktopStartup创建桌面。
53 |
54 | 在桌面回调函数的示例代码进行了如下操作:
55 |
56 | - WM_CREATE:初始化输入设备,如触摸屏、鼠标等;创建定时器;创建APP线程,APP线程包含各个应用。
57 |
58 | - WM_TIMER:定时器的处理消息,它会根据WM_CREATE中设置的定时器周期执行此处的内容,示例代码中在此处理触摸信息。
59 |
60 | - WM_ERASEBKGND:擦除背景,当需要绘制桌面背景时会进入此消息处理,示例代码中通过_EraseBackgnd绘制该背景。
61 |
--------------------------------------------------------------------------------
/section_one/section19.rst:
--------------------------------------------------------------------------------
1 | .. vim: syntax=rst
2 |
3 | 文本显示
4 | ------------
5 |
6 | 窗口显示文字的方式,前面讲过一个TEXTBOX文本框,下面讲解一下另一种方式。这种方式之前我们也稍微接触过,就是在WM_PAINT消息,调用TextOut函数绘制文本。
7 |
8 | .. _文本显示-1:
9 |
10 | 文本显示
11 | ~~~~~~~~~~~~
12 |
13 | 文本显示相关的函数
14 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
15 |
16 | x_wsprintf函数
17 | ''''''''''''''''''''''''''''''''''''
18 |
19 | 为了适应各种平台,emXGUI自带了C标准库的函数,这些库函数都带了个“x\_”的前缀,它们的函数功能与 C 标准库函数的一样。本章使用的函数x_wsprintf就是其中之一,代码清单19_1_。x_wsprintf是字符串格式化命令,主要功能是把格式化的数据写入某个缓冲区中。
20 |
21 | .. code-block:: c
22 | :caption: 代码清单 19_1 x_wsprintf函数(文件x_libc.h)
23 | :linenos:
24 | :name: 代码清单19_1
25 |
26 | int x_wsprintf(WCHAR *dest, const WCHAR *format, ...);
27 |
28 | (1) dest:WCHAR型指针,指向将要写入的字符串的缓冲区。
29 |
30 | (2) format:格式化字符串。
31 |
32 | emXGUI中WCHAR型是unsigned short类型,这与C库的sprintf有点区别。因此,我们传入的format实参应该是一个unsigned short类型的字符串,否则,则会出现Error。
33 |
34 | 在C语言中,我们使用char来定义字符,占用一个字节,最多只能表示128个字符,也就是ASCII码中的字符。中文则需要用多个字节来表示,可以通过用字母 L 作为 ASCII 字符串的前缀将任何 ASCII
35 | 字符串表示为宽字符字符串形式,例如,L"野火"。L与字符串之间没有空格,这样编译器才知道每个字符占用两个字节,即宽字符。
36 |
37 | TextOut函数
38 | ''''''''''''''''''
39 |
40 | 在指定位置显示字符串,使用的是函数TextOut。与DrawText的区别在于:TextOut可以在窗口的任何位置显示字符串。但是却不可以设置文字的格式,如居中对齐,左对齐等,见 代码清单19_2_。
41 |
42 | .. code-block:: c
43 | :caption: 代码清单 19‑2 TextOut函数
44 | :linenos:
45 | :name: 代码清单19_2
46 |
47 | BOOL TextOut(HDC hdc,int x,int y,LPCWSTR lpString,int nCount);
48 |
49 | (1) hdc:绘图上下文。
50 |
51 | (2) x,y:文字显示的起点坐标。
52 |
53 | (3) lpString:字符串(Unicode-UCS2格式),传入的实参需是宽字符型,支持换行’\r’和回车符’\n’。
54 |
55 | (4) nCount:要显示字符的字符数, 当设置小于0时, 将显示整个字符串文本的内容。
56 |
57 | 文本显示实验
58 | ~~~~~~~~~~~~~~~~~~
59 |
60 | .. _设计要求-9:
61 |
62 | 设计要求
63 | ^^^^^^^^^^^^
64 |
65 | 在窗口中输出文字,在首行的位置显示所需的时长。
66 |
67 | .. image:: /media/docx081.jpg
68 | :align: center
69 | :alt: 图 19‑1 设计要求
70 | :name: 图19_1
71 |
72 | 图 19‑1 设计要求
73 |
74 | .. _代码分析-9:
75 |
76 | 代码分析
77 | ^^^^^^^^^^^^
78 |
79 | (1) 创建父窗口
80 |
81 | .. code-block:: c
82 | :caption: 代码清单 19‑3 GUI_DEMO_Listbox函数(GUI_DEMO_Listbox.c)
83 | :linenos:
84 | :name: 代码清单19_3
85 |
86 | void GUI_DEMO_TextOut(void)
87 | {
88 | HWND hwnd;
89 | WNDCLASS wcex;
90 | MSG msg;
91 |
92 | wcex.Tag = WNDCLASS_TAG;
93 | wcex.Style = CS_HREDRAW | CS_VREDRAW;
94 | wcex.lpfnWndProc = WinProc; //设置主窗口消息处理的回调函数.
95 |
96 | wcex.cbClsExtra = 0;
97 | wcex.cbWndExtra = 0;
98 | wcex.hInstance = NULL;
99 | wcex.hIcon = NULL;
100 | wcex.hCursor = NULL;
101 |
102 | //创建主窗口
103 | hwnd =CreateWindowEx( NULL,
104 | &wcex,
105 | _T("GUI_DEMO - TextOut"), //窗口名称
106 | WS_CAPTION|WS_DLGFRAME|WS_BORDER|WS_CLIPCHILDREN,
107 | 0,0,GUI_XSIZE,GUI_YSIZE, //窗口位置和大小
108 | NULL,NULL,NULL,NULL);
109 |
110 | //显示主窗口
111 | ShowWindow(hwnd,SW_SHOW);
112 |
113 | //开始窗口消息循环(窗口关闭并销毁时,GetMessage将返回FALSE,退出本消息循环)。
114 | while(GetMessage(&msg,hwnd))
115 | {
116 | TranslateMessage(&msg);
117 | DispatchMessage(&msg);
118 | }
119 | }
120 |
121 | 创建父窗口,标题栏为“GUI_DEMO_TextOut”,带有大小边框,设置winProc作为窗口回调函数。
122 |
123 | (2) 窗口回调函数
124 |
125 | 1. WM_CREATE
126 |
127 | .. code-block:: c
128 | :caption: 代码清单 19‑4 WM_CREATE消息响应(文件GUI_DEMO_TextOut.c)
129 | :linenos:
130 | :name: 代码清单19_4
131 |
132 | case WM_CREATE: //窗口创建时,会自动产生该消息,在这里做一些初始化的操作或创建子窗口.
133 | {
134 | GetClientRect(hwnd,&rc); //获得窗口的客户区矩形.
135 |
136 | CreateWindow(BUTTON,L"OK",WS_VISIBLE,
137 | rc.w-80,8,68,32,hwnd,ID_OK,NULL,NULL); //创建一个按钮(示例).
138 | }
139 |
140 | WM_CREATE消息中,在坐标(rc.w-80,8)处创建了一个OK按键。用来退出该界面。
141 |
142 | 2. WM_NOTIFY
143 |
144 | .. code-block:: c
145 | :caption: 代码清单 19‑5 WM_NOTIFY消息响应(文件GUI_DEMO_TextOut.c)
146 | :linenos:
147 | :name: 代码清单19_5
148 |
149 | case WM_NOTIFY: //WM_NOTIFY消息:wParam低16位为发送该消息的控件ID,高16位为通知码;
150 | lParam指向了一个NMHDR结构体.
151 | {
152 | u16 code,id;
153 |
154 | code =HIWORD(wParam); //获得通知码类型.
155 | id =LOWORD(wParam); //获得产生该消息的控件ID.
156 |
157 | if(id==ID_OK && code==BN_CLICKED) // 按钮“单击”了.
158 |
159 | {
160 | PostCloseMessage(hwnd); //使产生WM_CLOSE消息关闭窗口.
161 | }
162 | break;
163 | }
164 |
165 | WM_NOTIFY消息用来检测OK键是否被按下。使用HIWORD和LOWORD函数读取控件的ID和通知码。如果OK键被按下,则发送WM_CLOSE消息关闭窗口。
166 |
167 | 3. WM_PAINT
168 |
169 |
170 | .. code-block:: c
171 | :caption: 代码清单 19‑6 WM_PAINT消息响应
172 | :linenos:
173 | :name: 代码清单19_6
174 |
175 | case WM_PAINT: //窗口需要绘制时,会自动产生该消息.
176 | {
177 | PAINTSTRUCT ps;
178 | HDC hdc;
179 | RECT rc;
180 | int i,t,y;
181 | WCHAR wbuf[128];
182 | POINT Point;
183 | GetClientRect(hwnd,&rc);
184 |
185 | hdc =BeginPaint(hwnd,&ps); //开始绘图
186 |
187 | ////用户的绘制内容...
188 | SetTextColor(hdc,MapRGB(hdc,10,10,100));
189 | t=GUI_GetTickCount();
190 | y=24;
191 | i=0;
192 | Point.x = 0;
193 | while(y 480) break;
198 | TextOut(hdc,10,y,L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ",-1);
199 | y+=20;
200 | i++;
201 | }
202 | t =GUI_GetTickCount()-t;
203 | SetTextColor(hdc,MapRGB(hdc,250,10,10));
204 | x_wsprintf(wbuf,L"TextOut Time used:%dms; %.1fms/line",t,(float)t/(float)i);
205 | TextOut(hdc,10,4,wbuf,-1);
206 | EndPaint(hwnd,&ps); //结束绘图
207 | break;
208 | }
209 |
210 | 在WM_PAINT消息中,绘制显示的文字。绘制过程中,需要调用BeginPaint来获取绘图上下文和EndPaint函数结束绘图。使用GUI_GetTickCount函数来得到当前系统的时间,存放到变量t中。TextOut函数用来输出文本,这里显示的内容为:0123456789ABCDEFGHIJK
211 | LMNOPQRSTUVWXYZ。我们使用的字体为GB2312_20_4BPP,字体高是20,所以使每行的文本的起点y坐标偏移20个像素。
212 |
213 | 调用ClientToScreen函数,将每行的起点坐标,转换为屏幕坐标,这里的起点坐标指的是客户区里面的坐标。这样的话,一旦起点坐标超出了屏幕的高度,就会停止显示文字。ClientToScreen函数的具体说明,可以查阅《emXGUI API 编程手册》章节:窗口/消息系统API。
214 |
215 | 变量i记录行数,耗费的时间=总时间t/总行数i。x_wsprintf函数的用法,与C语言的sprintf用法一致。以x_w开头的函数,都是emXGUI封装的C库函数。最后,将耗费的时间显示在(10,4)处。
216 |
217 |
218 | .. code-block:: c
219 | :caption: 代码清单 19‑7 GUI_AppMain函数(文件GUI_AppMain.c)
220 | :linenos:
221 | :name: 代码清单19_7
222 |
223 | void GUI_AppMain(void)
224 | {
225 | while(1)
226 | {
227 | GUI_DEMO_Button();
228 | GUI_DEMO_Checkbox();
229 | GUI_DEMO_Radiobox();
230 | GUI_DEMO_Textbox();
231 | GUI_DEMO_Progressbar();
232 |
233 | GUI_DEMO_Scrollbar();
234 | GUI_DEMO_Listbox();
235 | GUI_DEMO_Messagebox();
236 | GUI_DEMO_TextOut();
237 | }
238 | }
239 |
240 | 将GUI_DEMO_TextOut函数创建的窗口,加入到GUI_AppMain中,如 代码清单19_7_。
241 |
242 | .. _实验现象-9:
243 |
244 | 实验现象
245 | ^^^^^^^^^^^^
246 |
247 | 实验结果如 图19_2_ 所示。图19_2_ 是在Textout窗口中显示整个屏幕的文字,所花费的时间为200ms。图19_3_ 是拖动窗口到屏幕底端,刚刚好显示3行文字。可以看到耗费的时间大大减少,如果将行数输出到串口的话,串口会输出3。
248 |
249 | .. image:: /media/docx082.jpg
250 | :align: center
251 | :alt: 图 19‑2 实验结果
252 | :name: 图19_2
253 |
254 | 图 19‑2 实验结果
255 |
256 | .. image:: /media/docx083.jpg
257 | :align: center
258 | :alt: 图 19‑3 实验结果
259 | :name: 图19_3
260 |
261 | 图 19‑3 实验结果
262 |
--------------------------------------------------------------------------------
/section_one/section2.rst:
--------------------------------------------------------------------------------
1 | .. vim: syntax=rst
2 |
3 | emXGUI文件和应用架构
4 | --------------------------
5 |
6 | emXGUI目录简介
7 | ~~~~~~~~~~~~~~~~~~~~
8 |
9 | 解压下载得的emXGUI文件后,进入到emXGUI目录见 图2_1_。
10 |
11 | .. image:: /media/docx008.png
12 | :align: center
13 | :alt: 图 2‑1emXGUI文件说明
14 | :name: 图2_1
15 |
16 | 图 2_1emXGUI文件说明
17 |
18 | emXGUI库包含了如下内容:
19 |
20 | - arch文件夹:主要包含架构相关的内容,如不同类型液晶屏的绘图引擎示例以及不同操作系统平台下的信号量、延时接口。
21 |
22 | - drv文件夹:包含了emXGUI使用的驱动接口文件,如液晶、触摸、内存管理接口的初始化,这是移植emXGUI主要修改的内容;
23 | 其中还包含有gui_drv_cfg.h文件用于定制驱动的各项配置;
24 | gui_startup.c包含初始化emXGUI的示例;gui_desktop.c包含使用emXGUI建立桌面的示例。
25 |
26 | - inc文件夹:它包含了全部的emXGUI库核心的头文件,各种关于库函数的声明、定义都在这些文件里面。
27 |
28 | - libs文件夹:它包含了emXGUI的代码库文件,针对Cortex-M0、M3和M4这些不同 CPU内核以及在GCC、MDK这些不同编译环境,
29 | 都有一个相对应的emXGUI库,在使用的时候要根据自己的平台选择合适的库文件。
30 |
31 | - resource文件夹:包含emXGUI可能使用的资源文件,如字体数据、图片数据等。
32 |
33 | - tools文件夹:它包含了bin2c.exe、XBF字体生成器等软件工具。
34 |
35 | 文件说明
36 | ~~~~~~~~
37 |
38 | 下面的针对具体的文件进行介绍。
39 |
40 | 表格 2‑1 emXGUI具体文件说明
41 |
42 | ======================================================= =============================================================================================================================================================
43 | 目录/文件名 说明
44 | ======================================================= =============================================================================================================================================================
45 | libs emXGUI核心库文件
46 | emXGUI100_MDK_xxx.lib emXGUI核心API库文件,MDK版,XXX内核
47 | x_libc_MDK_xxx.lib 重实现的C标准库文件,MDK版,XXX内核,
48 | 为方便移植至不同平台,emXGUI使用的C库都是x_libc中实现的
49 | arch目录 主要包含emXGUI架构相关的文件,如液晶类型、操作系统接口
50 | GUI_Arch.c 架构相关的总文件
51 | GUI_TouchPanel_Calibration.c 电阻屏使用的校准接口
52 | GUI_TouchPanel.c 触摸屏控制接口,包含初始化,坐标处理以及校准
53 | arch/GAL目录 本目录包含绘图引擎相关的文件
54 | GL_Cursor.c 包含光标的外观及控制接口,可修改本文件定制光标的外观
55 | GL_MEM_xBPP.c x(8/16/32)位的内存绘图接口,适用于显存型液晶屏,往显存写入数据即可直接显示,如STM32F429使用LTDC驱动的液晶屏
56 | GL_MPU_16Bit.c 16位MPU通用绘图接口,适用于自带液晶驱动的液晶屏,显示时需要使用特定命令与驱动寄存器进行交互,如自带ILI9341驱动器的液晶
57 | arch/inc目录 包含架构相关的主要头文件
58 | gui_drv.h 驱动头文件
59 | GUI_Font_Freetype.h 自定义字体头文件
60 | arch/Options目录 包含各种操作系统的接口文件
61 | X_GUI_xxxx.c 操作系统接口,包含互斥锁、信号量、线程句柄、系统时间和延时等操作
62 | resource/xft_font目录 emXGUI可能使用到的XBF字体资源文件
63 | ASCII_x_yBPP.c 示例ASCII编码的xft字体数组文件,其中x为字体宽高,y为抗锯齿参数(数值越大越平滑,占用空间越大),C数组文件适用于直接添加至工程并作为程序数据烧录到MCU内部FLASH
64 | ASCII_x_yBPP.bm_info 示例ASCII编码的xft字体bin文件,与同名的C文件功能类似,主要用于作为资源文件烧录到外部SPI-FLASH、SD卡等存储器上
65 | GB2312_x_yBPP.c 示例GB2312编码的xft字体数组文件,由于GB2312编码数据文件较大,不建议直接存储在MCU的内部FLASH
66 | GB2312_x_yBPP.bin 示例GB2312编码的xft字体bin文件
67 | drv目录 包含emXGUI驱动接口文件
68 | gui_drv_cfg.h 驱动配置,包含是否使用鼠标、键盘、触摸屏等输入设备;使用的字体类型;液晶的分辨率和像素格式等内容。
69 | gui_startup.c emXGUI初始化和启动的示例文件
70 | gui_desktop.c 使用emXGUI创建桌面的示例文件
71 | gui_lcd_port.c/h 液晶驱动接口
72 | gui_mem_port.c/h 内存管理接口
73 | gui_log_port.c/h 日志输出接口
74 | gui_font_port.c/h 字体管理接口
75 | gui_input_port.c/h 输入设备接口(可选,可在gui_drv_cfg.h文件关闭输入设备配置,不使输入设备时可不添加本文件到工程)
76 | gui_touch_port.c/h 触摸设备接口,使用触摸屏时在此添加驱动(可选)
77 | gui_resource_port.c/h 资源设备读写接口,如把资源文件存储在外部SPI-FLASH可使用该接口进行访问(可选)
78 | gui_picture_port.c/h 图片读写接口,显示外部资源图片时可在此编写访问资源设备的接口(可选)
79 | inc目录
80 | def.h 一些类型和常用函数定义
81 | emXGUI_Arch.h emXGUI架构头文件
82 | emXGUI.h emXGUI总的头文件,包含emxGUI上层API的声明
83 | GUI_Font_XFT.h 字体配置头文件
84 | x_libc.h 重实现的C库x_libc相关头文件
85 | x_obj.c/h 链表相关代码
86 | ======================================================= =============================================================================================================================================================
87 |
88 | emXGUI核心库文件
89 | ~~~~~~~~~~~~~~~~~~~~~~
90 |
91 | emXGUI核心库文件(如emXGUI100_MDK_CM4.lib)提供了emXGUI所有可用的API,它所提供的API函数声明都可在emXGUI.h文件找到,在编写界面应用程序时,也只需要包含emXGUI.h这一个头文件。
92 |
93 | C标准库x_libc
94 | ~~~~~~~~~~~~~~~~~~~~
95 |
96 | 为适应不同的平台,emXGUI自带了C标准库的函数,如字符串处理strlen、strcpy等,为进行区分,这些重新实现的库函数都带了个“x\_”前缀,如x_strlen、x_strcpy等,这些函数与C标准库函数的功能一样,整个库被称为x_libc(如x_libc_MDK_CM4.lib)。使用时可通
97 | 过x_libc.h文件查看x_libc中提供的函数声明。
98 |
99 | 特别地,x_libc中还包含了内存堆管理函数,如x_heap_init、x_heap_alloc、x_heap_realloc、x_heap_free等,使用这些函数可管理多个x_heap内存堆。
100 |
101 | emXGUI 应用的软件架构
102 | ~~~~~~~~~~~~~~~~~~~~~~~~
103 |
104 | 典型的emXGUI构建程序其架构见 图2_2_ 。
105 |
106 | .. image:: /media/docx008.png
107 | :align: center
108 | :alt: 图 2_2emXGUI软件架构图
109 | :name: 图2_2
110 |
111 | 图 2_2
112 |
113 | 该架构看起来并不复杂,从最底层看起,
114 | 首先是硬件层,硬件层就是指最基本的板级支持软件包(BSP),也就是我们常说的底层驱动,它提供了对硬件平台资源最直接的访问;emXGUI软件库承上启下,它运行在硬件层之上,与硬件层之间主要靠液晶驱动和输入设备连接起来,向应用层则提供了各种便于用户制作GUI应用的接口。
115 |
116 | 在没有使用emXGUI的软件架构中,很可能就是由硬件层直接过渡到应用层,甚至根本没有分层的概念,这样的应用程序将十分依赖于某个特定的硬件平台,不容易迁移到其它设备之中。从这个架构图可以看出,只需要编写好液晶驱动这个粘合emXGUI库和硬件BSP层的中间件,就可以正常使用emXGUI了,迁移应用到不同的平台也简单得多。
--------------------------------------------------------------------------------
/section_one/section23.rst:
--------------------------------------------------------------------------------
1 | .. vim: syntax=rst
2 |
3 | 显示png图片
4 | --------------
5 |
6 | PNG(Portable Network Graphics)是一种新兴的网络图像格式。1999年,Unisys公司进一步中止了对自由软件和非商用软件开发者的GIF专利免费许可,从而使PNG格式获得了更多的关注。PNG是目前保证最不失真的格式,采用LZ77算法的派生算法进行压缩,能把图像文件压缩到极限
7 | 以利于网络传输,但又能保留所有与图像品质有关的信息。 PNG同样支持透明图片的制作,图23_1_ 就是一种透明的png格式的图片。
8 |
9 | .. image:: /media/docx108.png
10 | :align: center
11 | :alt: 图 23‑1 png图片
12 | :name: 图23_1
13 |
14 | 图 23‑1 png图片
15 |
16 | 显示png图片(数据在内部存储空间)
17 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
18 |
19 | 下表列出了PNG 绘制API函数。
20 |
21 | 表格 23‑1 PNG 绘制API
22 |
23 | =============== ==================
24 | 函数 描述
25 | =============== ==================
26 | PNG_Open() 获取PNG_DEC句柄
27 | PNG_GetBitmap() 把图片转换成bitmap
28 | PNG_Close() 释放绘图句柄
29 | =============== ==================
30 |
31 | PNG 绘制API
32 | ^^^^^^^^^^^^^^^^^^
33 |
34 | PNG_Open
35 | ''''''''''''''''
36 |
37 | PNG_Open来获取PNG_DEC句柄,函数原型见 代码清单23_1_。
38 |
39 | .. code-block:: c
40 | :caption: 代码清单 23‑1 PNG_Open函数(文件emxgui_png.h)
41 | :linenos:
42 | :name: 代码清单23_1
43 |
44 | PNG_DEC* PNG_Open(const u8 *png_dat,int png_size);
45 |
46 | 1) png_dat:图片所在的缓冲区,使用软件生成的图片数组的数组名;
47 |
48 | 2) png_size:图片数组的大小,可以使用sizeof获取数组的大小。
49 |
50 | PNG_GetBitmap
51 | '''''''''''''
52 |
53 | emXGUI显示PNG图片的方式,是通过将PNG格式的图片,转换成BMP格式,利用显示位图的API函数来显示图片,函数原型,见 代码清单23_2_。
54 |
55 | .. code-block:: c
56 | :caption: 代码清单 23‑2 PNG_GetBitmap函数(文件emxgui_png.h)
57 | :linenos:
58 | :name: 代码清单23_2
59 |
60 | BOOL PNG_GetBitmap(PNG_DEC *png_dec,BITMAP *bm);
61 |
62 | 1) png_dec:PNG_DEC句柄,由PNG_Open函数生成;
63 |
64 | 2) bm:位图结构体,存放着位图数据的大小,格式、图像数据等;
65 |
66 | PNG_Close
67 | '''''''''
68 |
69 | PNG_Close用来释放绘图句柄,函数原型见 代码清单23_3_。
70 |
71 | .. code-block:: c
72 | :caption: 代码清单 23‑3 PNG_Close函数(文件emxgui_png.h)
73 | :linenos:
74 | :name: 代码清单23_3
75 |
76 | void PNG_Close(PNG_DEC *png_dec);
77 |
78 | 1) png_dec:要释放的PNG_DEC句柄。
79 |
80 | 注意,这个函数操作与JPG的释放绘图句柄有所不同,只有当读者不再使用与PNG_DEC句柄相关的操作,包括不再使用PNG_GetBitmap函数生成的位图结构体,才可以释放绘图句柄,因此,该函数只有在窗口退出时进行调用,即放在WM_DESTROY消息中使用。
81 |
82 | 显示png图片实验
83 | ^^^^^^^^^^^^^^^^^^
84 |
85 | 学习了绘制上述的PNG图片绘制API之后,我们开始编写代码,将 图23_1_ 显示在屏幕上。
86 |
87 | .. _代码分析-17:
88 |
89 | 代码分析
90 | ''''''''''''
91 |
92 | (1) 窗口回调函数
93 |
94 | - WM_CREATE
95 |
96 | .. code-block:: c
97 | :caption: 代码清单 23‑4 WM_CREATE消息(文件GUI_DEMO_DrawPNG.c)
98 | :linenos:
99 | :name: 代码清单23_4
100 |
101 | case WM_CREATE: //窗口创建时,会自动产生该消息,在这里做一些初始化的操作或创建子窗口
102 | {
103 | u8 *jpeg_buf;
104 | u32 jpeg_size;
105 | JPG_DEC *dec;
106 |
107 | GetClientRect(hwnd,&rc); //获得窗口的客户区矩形
108 | /* 根据图片数据创建PNG_DEC句柄 */
109 | png_dec = PNG_Open((u8 *)redfish, redfish_size());
110 |
111 | /* 把图片转换成bitmap */
112 | PNG_GetBitmap(png_dec, &png_bm);
113 |
114 | res = FS_Load_Content(DEMO_JPEG_FILE_NAME, (char **)&jpeg_buf, &jpeg_size);
115 | if(res)
116 | {
117 | /* 根据图片数据创建JPG_DEC句柄 */
118 | dec = JPG_Open(jpeg_buf, jpeg_size);
119 | /* 读取图片文件信息 */
120 | JPG_GetImageSize(&pic_width, &pic_height,dec);
121 |
122 | /* 创建内存对象 */
123 | hdc_mem =CreateMemoryDC(SURF_SCREEN,pic_width,pic_height);
124 |
125 | /* 绘制至内存对象 */
126 | JPG_Draw(hdc_mem, 0, 0, dec);
127 |
128 | /* 关闭JPG_DEC句柄 */
129 | JPG_Close(dec);
130 | }
131 | /* 释放图片内容空间 */
132 | RES_Release_Content((char **)&jpeg_buf);
133 | return TRUE;
134 | }
135 |
136 | 在WM_CREATE消息中,调用PNG_Open创建PNG_DEC句柄,以后的一切操作都可以使用PNG_DEC句柄来实现,同时通过PNG_GetBitmap将图片转换成bitmap,存放在png_bm结构体变量中。
137 | 这里我们使用JPG图片作为背景,更好地突出 图23_1_ 是张带透明度的图片。
138 | 使用FS_Load_Content函数从SD卡读取sea.jpg的图片数据。JPG_Open创建一个新的图片句柄,同时绘制图片数组到MemoryDC中。
139 |
140 | - WM_ERASEBKGND
141 |
142 | .. code-block:: c
143 | :caption: 代码清单 23‑5 WM_ERASEBKGND消息(文件GUI_DEMO_DrawPNG.c)
144 | :linenos:
145 | :name: 代码清单23_5
146 |
147 | case WM_ERASEBKGND:
148 | {
149 | HDC hdc=(HDC)wParam;
150 | BitBlt(hdc,0,0,pic_width,pic_height,hdc_mem,0,0,SRCCOPY); //将MEMDC输出到窗口中。
151 | return TRUE;
152 | }
153 |
154 | WM_ERASEBKGND消息中,使用BitBlt块传输函数将背景图片,绘制到屏幕HDC上。
155 |
156 | - WM_PAINT
157 |
158 | .. code-block:: c
159 | :caption: 代码清单 23‑6 WM_PAINT消息(文件GUI_DEMO_DrawPNG.c)
160 | :linenos:
161 | :name: 代码清单23_6
162 |
163 | case WM_PAINT: //窗口需要绘制时,会自动产生该消息.
164 | {
165 | PAINTSTRUCT ps;
166 | HDC hdc;
167 | RECT rc0;
168 | int x=0,y=0;
169 | hdc =BeginPaint(hwnd,&ps);
170 | ////用户的绘制内容...
171 | GetClientRect(hwnd,&rc0);
172 |
173 | for(y=0; y=frame_num)
234 | {
235 | i=0;
236 | }
237 | /* 绘制图片至MemoryDC */
238 | GIF_DrawFrame(hdc_mem,0,0,MapRGB(hdc_mem,255,255,255),hgif,i);
239 | BitBlt(hdc,rc.x,rc.y,img_info.Width,img_info.Height,hdc_mem,0,0,SRCCOPY); //将MEMDC输出到窗口中。
240 | /* 获取当前帧的延时值 */
241 | delay=GIF_GetFrameDelay(hgif,i);
242 | i++;
243 | }
244 | /* 释放MemoryDC */
245 | DeleteDC(hdc_mem);
246 |
247 | ResetTimer(hwnd,0,delay,TMR_SINGLE|TMR_START,NULL);
248 | EndPaint(hwnd,&ps);
249 | break;
250 | }
251 |
252 | 代码清单24_9_ 负责绘制GIF图片的每一帧,CreateMemoryDC函数创建MemoryDC,调用GIF_DrawFrame将每一帧图片绘制到MemoryDC,
253 | 然后使用BitBlt块传输输出到窗口HDC,绘制完成后,释放MemoryDC。调用GIF_GetFrameDelay获取GIF当前帧需
254 | 要延时的时间,使用ResetTimer函数,来重新设置延时时间,以及定时器的功能。
255 |
256 | - WM_TIMER
257 |
258 | .. code-block:: c
259 | :caption: 代码清单 24‑10 WM_TIMER消息(文件GUI_DEMO_DrawGIF.c)
260 | :linenos:
261 | :name: 代码清单24_10
262 |
263 | case WM_TIMER:
264 | InvalidateRect(hwnd,NULL,FALSE);
265 | break;
266 |
267 | WM_TIMER消息中,当超过延时时间时,调用InvalidateRect函数重绘窗口,实际上就是给窗口发送WM_PAINT消息。
268 |
269 | 最后,设计的GUI_DEMO_DrawGIF界面函数加入到GUI_AppMain函数中即可。
270 |
271 | .. _实验结果-10:
272 |
273 | 实验结果
274 | ''''''''
275 |
276 | 实验结果如 图24_4_ 所示,这是GIF图片中的某一帧。具体的实验效果,读者可以下载本章的例程进行观看。
277 |
278 | .. image:: /media/docx113.jpg
279 | :align: center
280 | :alt: 图 24‑4 实验结果
281 | :name: 图24_4
282 |
283 | 图 24‑4 实验结果
284 |
285 | 显示外部gif图片
286 | ~~~~~~~~~~~~~~~~~~
287 |
288 | 从外部读取图片数据,使用RES_Load_Content函数或者是FS_Load_Content函数。RES_Load_Content函数是从SPI_FLASH中读取图片,读取之前需要将图片烧写至SPI_FLASH中;而FS_Load_Content则是从SD卡中读取图片数据。这两个在前面章节已经讲
289 | 解过了,这里不进行过多的描述。使用两者中哪一个,由宏定义RES_PIC_DEMO决定。
290 |
291 | .. code-block:: c
292 | :caption: 代码清单 24‑11 宏定义RES_PIC_DEMO(文件GUI_DEMO_DrawGIF_Extern.c)
293 | :linenos:
294 | :name: 代码清单24_11
295 |
296 | /* 为1时显示RES FLASH资源文件,为0时显示SD卡的文件 */
297 | #define RES_PIC_DEMO 0
298 |
299 | #if(RES_PIC_DEMO)
300 | /* FLASH资源文件加载 */
301 | #define DEMO_GIF_FILE_NAME "king.gif"
302 | #else
303 | /* SD文件系统加载 */
304 | #define DEMO_GIF_FILE_NAME "0:srcdata/king.gif"
305 |
306 | #endif
307 |
308 | 显示外部gif图片实验
309 | ^^^^^^^^^^^^^^^^^^^^^^
310 |
311 | .. _实验要求-1:
312 |
313 | 实验要求
314 | ''''''''''''
315 |
316 | 实验要求和上一小节一样,区别在于上一小节图片是存放在内部FLASH中,而本节实验的图片数据是存放在SPI_FLASH或者是SD卡中,使用RES_Load_Content或者是FS_Load_Content函数来获得图片数据。
317 |
318 | .. _代码分析-20:
319 |
320 | 代码分析
321 | ''''''''''''
322 |
323 | (1) 窗口回调函数
324 |
325 | - WM_CREATE
326 |
327 | .. code-block:: c
328 | :caption: 代码清单 24‑12 WM_CREATE消息(文件GUI_DEMO_DrawGIF_Extern.c)
329 | :linenos:
330 | :name: 代码清单24_12
331 |
332 | case WM_CREATE: //窗口创建时,会自动产生该消息,在这里做一些初始化的操作或创建子窗口
333 | {
334 | GetClientRect(hwnd,&rc);
335 | #if(RES_PIC_DEMO)
336 | /* 资源设备中加载 */
337 | res = RES_Load_Content(DEMO_GIF_FILE_NAME, (char **)&gif_buf, &gif_size);
338 | #else
339 | /* SD文件系统加载 */
340 | res = FS_Load_Content(DEMO_GIF_FILE_NAME, (char **)&gif_buf, &gif_size);
341 |
342 | #endif
343 | /* 获取GIF句柄 */
344 | hgif = GIF_Open(gif_buf);
345 | /* 获取GIF图片信息 */
346 | GIF_GetInfo(hgif,&img_info);
347 | /* 获取GIF图片的帧数 */
348 | frame_num = GIF_GetFrameCount(hgif);
349 | CreateWindow(BUTTON,L"OK",WS_VISIBLE,rc.w-70,rc.h-40,68,32,hwnd,ID_OK,NULL,NULL);
350 | SetTimer(hwnd,0,0,TMR_SINGLE,NULL);
351 | return TRUE;
352 | }
353 |
354 | 代码清单24_12_ WM_CREATE消息(文件GUI_DEMO_DrawGIF_Extern.使用FS_Load_Content函数从SD卡中读取图片数据,存放在数组gif_buf中。
355 | 调用GIF_Open函数来创建一个GIF图片句柄,图片数组gif_buf作为函数的实参。通过GIF_GetInfo函数来得到图片的尺寸,存放在img_info变量中,这里尺寸大小主要用于创建MemoryDC的大小。调用GIF_GetFrameCount函数来得到GIF图片的总帧数,读者可以将frame_num通过串口打印出来,可以看到刚刚好是16帧。创建定时器,定时时间设置为0,定时器主要用于实现GIF图片的
356 | 每一帧图片的延时,也就是 图24_2_ 的箭头。当超过设定时间时,就会发送WM_TIMER消息。在WM_TIMER消息中,调用InvalidateRect函数来实现窗口重绘,也就是绘制下一帧图片。
357 |
358 | - WM_PAINT
359 |
360 | .. code-block:: c
361 | :caption: 代码清单 24‑13 WM_PAINT消息(文件GUI_DEMO_DrawGIF_Extern.c)
362 | :linenos:
363 | :name: 代码清单24_13
364 |
365 | case WM_PAINT: //窗口需要绘制时,会自动产生该消息.
366 | {
367 | PAINTSTRUCT ps;
368 | HDC hdc;
369 | hdc =BeginPaint(hwnd,&ps);
370 | GetClientRect(hwnd,&rc);
371 | if(hgif)
372 | {
373 | /* 创建MemoryDC */
374 |
375 | hdc_mem = CreateMemoryDC(SURF_SCREEN,img_info.Width,img_info.Height);
376 | /* 清除窗口显示内容 */
377 | ClrDisplay(hdc_mem,NULL,MapRGB(hdc_mem,255,255,255));
378 | if(i>=frame_num)
379 | {
380 | i=0;
381 | }
382 | /* 绘制GIF图片 */
383 | GIF_DrawFrame(hdc_mem,0,0,MapRGB(hdc_mem,255,255,255),hgif,i);
384 | BitBlt(hdc,rc.x,rc.y,img_info.Width,img_info.Height,hdc_mem,0,0,SRCCOPY); //将MEMDC输出到窗口中。
385 | /* 获取GIF图片的延时值 */
386 | delay=GIF_GetFrameDelay(hgif,i);
387 | i++;
388 | }
389 | /* 释放MemoryDC */
390 | DeleteDC(hdc_mem);
391 | /*设置延时值,开启定时器 */
392 | ResetTimer(hwnd,0,delay,TMR_SINGLE|TMR_START,NULL);
393 | EndPaint(hwnd,&ps);
394 | break;
395 | }
396 |
397 | CreateMemoryDC函数用于创建MemoryDC,将GIF图片的每一帧绘制到MemoryDC,使用BitBlt函数将MEMDC输出到窗口HDC中,最后需要释放MemoryDC。
398 | 图24_1_ 帧与帧之间存在一些重叠的内容,这里调用ClrDisplay函数,将上一帧的内容清除,再绘制下一帧。GIF_GetFrameDelay得到当前帧的延时值,
399 | 使用ResetTimer来设置定时器的延时值,开启定时器。对于例程的GIF图来说, 这个过程需要执行16次。
400 |
401 | - WM_DESTROY
402 |
403 | .. code-block:: c
404 | :caption: 代码清单 24‑14 WM_DESTROY消息(文件GUI_DEMO_DrawGIF_Extern.c)
405 | :linenos:
406 | :name: 代码清单24_14
407 |
408 | case WM_DESTROY: //窗口销毁时,会自动产生该消息,在这里做一些资源释放的操作.
409 | {
410 | GIF_Close(hgif);
411 | return PostQuitMessage(hwnd); //调用PostQuitMessage,使用主窗口结束并退出消息循环.
412 | }
413 |
414 | 当窗口退出时,调用GIF_Close函数来释放GIF图片句柄。
415 |
416 | 最后,将设计好的GUI_DEMO_DrawGIF_Extern函数加入到GUI_AppMain中即可。
417 |
418 | .. _实验结果-11:
419 |
420 | 实验结果
421 | ''''''''
422 |
423 | 图24_5_ 是GIF图片中的某一帧,具体的实验效果,读者可以下载本章的例程进行观看。
424 |
425 | .. image:: /media/docx114.jpg
426 | :align: center
427 | :alt: 图 24‑5 实验结果
428 | :name: 图24_5
429 |
430 | 图 24‑5 实验结果
431 |
--------------------------------------------------------------------------------
/section_one/section26.rst:
--------------------------------------------------------------------------------
1 | .. vim: syntax=rst
2 |
3 | 如何制作字库
4 | ------------------
5 |
6 | 熟悉字符的编码后,我们学习如何制作字库文件。emXGUI支持的字库文件为*.xft类型的文件,可以使用XBF字体制作工具X_GUI_SIM.exe(位于过程目录下\\ \\emxgui\tools),这里我们以simfang.ttf为例。
7 |
8 | .. image:: /media/docx116.jpg
9 | :align: center
10 | :alt: 图 26‑1 文件目录
11 | :name: 图26_1
12 |
13 | 图 26‑1 文件目录
14 |
15 | 工具介绍
16 | ~~~~~~~~~~~~
17 |
18 | .. image:: /media/docx117.jpg
19 | :align: center
20 | :alt: 图 26‑2 工具界面图
21 | :name: 图26_2
22 |
23 | 图 26‑2 工具界面图
24 |
25 | 运行X_GUI_SIM.exe程序,会得到 图26_2_ 的界面图片。具体操作步骤:
26 |
27 | 1. 选择字体文件
28 |
29 | 这里我们以simfang.ttf文件为例,该文件存放在XBF字体制作工具\font目录下,见 图26_3_ 的处。单击处按键,选择simfang.ttf,如 图26_3_ 的处所示。
30 |
31 | .. image:: /media/docx118.jpg
32 | :align: center
33 | :alt: 图 26‑3 选择字体文件
34 | :name: 图26_3
35 |
36 | 图 26‑3 选择字体文件
37 |
38 | 2. 生成的字体范围
39 |
40 | 假如现在只需要使用字母Q,W,E,R,我们可以只生成一个只含有字母Q,W,E,R的xft文件,具体做法:新建一个txt文件,内容为
41 | QWER。注意,Q前面有一个空格,一般情况下,会保留空格的编码。另外,索引文件要使用ucs-2_little_edition编码。我们可以使用Notepad++来进行设置,
42 | .如 图26_5_ 。最后在 图26_2_ 的处选择刚刚新建的txt文件。
43 |
44 | 本章使用的simfang.ttf,这里以所有的字符编码为例,其txt文档(位于XBF字体制作工具\font目录下),如 图26_4_ 所示,包含了所有的数字,字母还有中文等编码
45 |
46 | .. image:: /media/docx119.jpeg
47 | :align: center
48 | :alt: 图 26‑4 txt文档内容
49 | :name: 图26_4
50 |
51 | 图 26‑4 txt文档内容
52 |
53 | .. image:: /media/docx120.jpg
54 | :align: center
55 | :alt: 图 26‑5设置编码
56 | :name: 图26_5
57 |
58 | 图 26‑5设置编码
59 |
60 | 单击处的按键,选择生成的字体范围,如 图26_6_。
61 |
62 | .. image:: /media/docx121.jpg
63 | :align: center
64 | :alt: 图 26‑6 选择生成的字体范围
65 | :name: 图26_6
66 |
67 | 图 26‑6 选择生成的字体范围
68 |
69 | 3. 选择输出路径
70 |
71 | 点击 图26_7_ 的 1 处,选择输出的xft文件的保存路径,注意,在处输入文件名时,需要手动输入.
72 | xft后缀。
73 |
74 | .. image:: /media/docx122.jpg
75 | :align: center
76 | :alt: 图 26‑7 选择路径
77 | :name: 图26_7
78 |
79 | 图 26‑7 选择路径
80 |
81 | 4. 设置输出的格式
82 |
83 | 点击 图26_8_ 的 1 处,弹出选项框Setting。处用来设置字体的大小,处主要是设置字体抗锯齿度,emXGUI最高可提供8 BPP,我们通常选择4BPP,处都是些默认参数,不需要修改。Xoff和Yoff负责字体的偏移。DPI代表图像每英寸面积内的像素点数。
84 |
85 | .. image:: /media/docx123.jpg
86 | :align: center
87 | :alt: 图 26‑8 选择字体格式
88 | :name: 图26_8
89 |
90 | 图 26‑8 选择字体格式
91 |
92 | 这里解释一下什么叫抗锯齿?在这之前,需要先知道什么叫锯齿现象。图26_9_ 是图像的原始尺寸。当图像放大时,由于图像的像素点与图像的尺寸是相关的,因此就出现了锯齿现象,类似于楼梯的形状,如 图26_10_ 的下半部分。
93 |
94 | .. image:: /media/docx124.jpeg
95 | :align: center
96 | :alt: 图 26‑9 原始尺寸“印刷”
97 | :name: 图26_9
98 |
99 | 图 26‑9 原始尺寸“印刷”
100 |
101 | .. image:: /media/docx125.jpg
102 | :align: center
103 | :alt: 图 26‑10 放大的“印刷”
104 | :name: 图26_10
105 |
106 | 图 26‑10 放大的“印刷”
107 |
108 | 抗锯齿是一种消除图物边缘出现凹凸锯齿的技术,就是将图像边缘及其两侧的像素颜色进行混合得到的新点,用来替换原来位置上的点以达到平滑边缘,达到消除锯齿的效果。抗锯齿程度越高 ,计算时间越长,但是效果越好。如 图26_11_ 的下半部分,这是设置抗锯齿(边缘平滑化)之后放大的效果图。
109 |
110 | .. image:: /media/docx126.jpg
111 | :align: center
112 | :alt: 图 26‑11 抗锯齿效果图
113 | :name: 图26_11
114 |
115 | 图 26‑11 抗锯齿效果图
116 |
117 | 5. 开始生成
118 |
119 | 经过前四步的设置之后,单击 图26_2_ 的 5 处,就可以生成xft文件了,操作成功的结果,如图 26‑12所示。在输出文件夹下,会有一个新的xft文件。这里我选择的输出路径是XBF字体制作工具\Out中,xft文件的名字为wildfire.xtf,注意输入xft文件时,一定要自己输入xft后缀。
120 |
121 | .. image:: /media/docx127.jpg
122 | :align: center
123 | :alt: 图 26‑12 txt文档内容
124 | :name: 图26_12
125 |
126 | 图 26‑12 生成结果
127 |
128 | 6. 测试生成的字体
129 |
130 | X_GUI_SIM.exe提供测试生成字体的功能,使用方法如 图26_13_ 所示。单击 图26_13_ 处的Test按键,在弹出的对话框中选择刚刚生成的xft文件。这里我们选择的上面生成的wildfire.
131 | xft文件。测试的结果如 图26_14_ 所示,读者可以和 图26_2_ 对比一下。
132 |
133 | .. image:: /media/docx128.jpg
134 | :align: center
135 | :alt: 图 26‑13 测试方法
136 | :name: 图26_13
137 |
138 | 图 26‑13 测试方法
139 |
140 | .. image:: /media/docx129.jpg
141 | :align: center
142 | :alt: 图 26‑14测试结果
143 | :name: 图26_14
144 |
145 | 图 26‑14测试结果
146 |
147 | 最后,将我们生成的xft文件,放到我们的SD卡中,如 图26_15_ 。这里统一放到根目录下的文件夹srcdata中。读者也可以选择其他的文件夹,但是程序需要进行修改,建议初学者依葫芦画瓢。
148 |
149 | .. image:: /media/docx130.jpg
150 | :align: center
151 | :alt: 图 26‑15 添加字库文件至SD卡中
152 | :name: 图26_15
153 |
154 | 图 26‑15 添加字库文件至SD卡中
155 |
156 | 到这里为止,就完成字库的制作,接下来,我们看一下如何在emXGUI使用我们刚刚生成的字库。
157 |
158 | 使用字库
159 | ~~~~~~~~~~~~
160 |
161 | 相关函数API
162 | ^^^^^^^^^^^^^^
163 |
164 | SetFont
165 | ''''''''''''''
166 |
167 | SetFont函数用来设置显示的字体格式,我们通过调用这个函数,可以切换至我们生成的字体,函数原型见 代码清单26_1_ SetFont函数(文件emXGUI.h)。
168 |
169 | .. code-block:: c
170 | :caption: 代码清单 26‑1 SetFont函数(文件emXGUI.h)
171 | :linenos:
172 | :name: 代码清单26_1
173 |
174 | HFONT SetFont(HDC hdc,HFONT hFont);
175 |
176 | 1) hdc:绘图上下文;
177 |
178 | 2) hFont:字体句柄。字体句柄是通过XFT_CreateFontEx函数来创建;
179 |
180 | 此外,该函数还会返回旧的字体句柄,我们可以利用这个返回值,进行两种字体的切换。
181 |
182 | GetFont
183 | '''''''
184 |
185 | 调用GetFont函数会返回当前正在使用的字体,函数原型,见代码清单 26‑2 GetFont函数(文件emXGUI.h)。
186 |
187 | .. code-block:: c
188 | :caption: 代码清单 26‑2 GetFont函数(文件emXGUI.h)
189 | :linenos:
190 | :name: 代码清单26_2
191 |
192 | HFONT GetFont(HDC hdc);
193 |
194 | 1) hdc:绘图上下文;
195 |
196 | XFT_CreateFont
197 | ''''''''''''''
198 |
199 | .. code-block:: c
200 | :caption: 代码清单 26‑3 XFT_CreateFont函数(文件GUI_Font_XFT.h)
201 | :linenos:
202 | :name: 代码清单26_3
203 |
204 | HFONT XFT_CreateFont(const void *xft_dat);
205 |
206 | 1) xft_dat:字体数据,可以使用bin2c工具可以将字库文件(.xtf后缀文件)生成C语言的数组,可以放在内部FLASH中。
207 |
208 | font_read_data_SDCARD
209 | '''''''''''''''''''''
210 |
211 | font_read_data_SDCARD函数从SD卡读取字库文件,得到的字体数组存放在buf中。
212 |
213 | .. code-block:: c
214 | :caption: 代码清单 26‑4 font_read_data_SDCARD函数(文件gui_font_port.c)
215 | :linenos:
216 | :name: 代码清单26_4
217 |
218 | BOOL font_read_data_SDCARD(char** buf, u32 size)
219 |
220 | {
221 | /* file objects */
222 | FIL *file;
223 | FRESULT fresult;
224 | BOOL result = TRUE;
225 | UINT br;
226 | file =(FIL*)GUI_VMEM_Alloc(sizeof(FIL));
227 |
228 | fresult = f_open(file, GUI_DEFAULT_SDCARD_FONT, FA_OPEN_EXISTING | FA_READ );
229 |
230 | size = f_size(file);
231 | /* 文件内容空间 */
232 | *buf = (char *)GUI_VMEM_Alloc(size);
233 | fresult = f_read(file, *buf, size, &br);
234 | /* 关闭文件 */
235 | f_close(file);
236 |
237 | /* 释放空间 */
238 | GUI_VMEM_Free(file);
239 |
240 | return result;
241 | }
242 |
243 | f_open函数的参数GUI_DEFAULT_SDCARD_FONT是我们的字库文件名字,见 代码清单26_5_。如果我们存放的字库文件不是这个文件的话, 则需要修改该宏定义。
244 |
245 | .. code-block:: c
246 | :caption: 代码清单26_5 GUI_DEFAULT_SDCARD_FONT宏定义(文件gui_drv_cfg.h)
247 | :linenos:
248 | :name: 代码清单26_5
249 |
250 | #define GUI_DEFAULT_SDCARD_FONT "0:srcdata/GB2312_16_4BPP.xft"
251 |
252 | 调用f_read函数,读取字库文件数据,需要读取的数据大小,为整个文件的的大小,通过f_size函数可以得到文件的大小。最后f_close函数关闭文件,同时释放文件句柄的空间。
253 |
254 | 使用字库实验
255 | ^^^^^^^^^^^^^^^^^^
256 |
257 | .. _实验要求-2:
258 |
259 | 实验要求
260 | ''''''''''''
261 |
262 | 本章节的例程代码与Textout类似,区别在于WM_PAINT消息的处理:在一个窗口中,同一个文本,使用两种字体进行显示,如 图26_16_ 实验要求。
263 |
264 | .. image:: /media/docx131.jpg
265 | :align: center
266 | :alt: 图 26‑16 实验要求
267 | :name: 图26_16
268 |
269 | 图 26‑16 实验要求
270 |
271 | .. _代码分析-21:
272 |
273 | 代码分析
274 | ''''''''''''
275 |
276 | (1) 创建字体句柄
277 |
278 | .. code-block:: c
279 | :caption: 代码清单 26‑6 GUI_Default_FontInit (文件gui_font_port.c)
280 | :linenos:
281 | :name: 代码清单26_6
282 |
283 | HFONT GUI_Default_FontInit(void)
284 | {
285 |
286 | HFONT hFont=NULL;
287 | //此处省略一些代码
288 | #elif (GUI_USE_SDCARD_FONT)
289 | {
290 | /* 指向缓冲区的指针 */
291 | static u8 *pFontData_XFT=NULL;
292 |
293 | u32 fsize;
294 |
295 | if(hFont==NULL)
296 | {
297 | res = font_read_data_SDCARD((char **)&pFontData_XFT, fsize);
298 | hFont_SDCARD = XFT_CreateFont(pFontData_XFT);
299 | }
300 |
301 | }
302 | #endif
303 | /* 若前面的字体加载失败,使用内部FLASH中的数据(工程中的C语言数组)
304 | * 添加字体数据时,把数组文件添加到工程,在本文件头添加相应字体数组的声明,
305 | * 然后调用XFT_CreateFont函数创建字体即可
306 | */
307 | if(hFont==NULL)
308 | {
309 | /* 从本地加载(本地数组数据) */
310 | hFont =XFT_CreateFont(GUI_DEFAULT_FONT); /* ASCii字库,20x20,4BPP抗锯齿*/
311 | /* 中文字库存储占用空间非常大,不推荐放在内部FLASH */
312 | //hFont =XFT_CreateFont(GB2312_16_2BPP); /* GB2312字库,16x16,2BPP抗锯齿*/
313 | //hFont =XFT_CreateFont(GB2312_20_4BPP); /* GB2312字库,20x20,4BPP抗锯齿*/
314 | }
315 | return hFont;
316 | }
317 |
318 | 这里使用了条件编译,只有打开GUI_USE_SDCARD_FONT这个宏,见 代码清单26_7_,emXGUI才会从SD卡读取字库文件。
319 |
320 | .. code-block:: c
321 | :caption: 代码清单 26_7 GUI_USE_SDCARD_FONT宏定义(文件gui_drv_cfg.h)
322 | :linenos:
323 | :name: 代码清单26_7
324 |
325 | #define GUI_USE_SDCARD_FONT 1
326 |
327 | 例程中创建了两种字体句柄,见 代码清单26_8_ 。默认的字体是由XFT_CreateFont函数创建的,而字体wildfire是由font_read_data_SDCARD函数从SD卡中读取的字库文件之后,调用XFT_CreateFont函数创建。
328 |
329 | .. code-block:: c
330 | :caption: 代码清单 26_8 字体类型(文件gui_drv_cfg.h)
331 | :linenos:
332 | :name: 代码清单26_8
333 |
334 | #define GUI_DEFAULT_SDCARD_FONT "0:srcdata/wildfire.xft"
335 |
336 | /* 默认内部字体数组名,USE_EXTERN_FONT为0或 外部字体加载失败时会采用的字体 */
337 |
338 | #define GUI_DEFAULT_FONT ASCII_20_4BPP
339 |
340 | (2) 窗口回调函数
341 |
342 | - WM_PAINT
343 |
344 | .. code-block:: c
345 | :caption: 代码清单 26‑9 WM_PAINT消息(文件GUI_DEMO_TextOut.c)
346 | :linenos:
347 | :name: 代码清单26_9
348 |
349 | case WM_PAINT: //窗口需要绘制时,会自动产生该消息.
350 | {
351 | PAINTSTRUCT ps;
352 | HDC hdc;
353 | RECT rc;
354 | int i,t,y;
355 | WCHAR wbuf[128];
356 |
357 | GetClientRect(hwnd,&rc);
358 |
359 | hdc =BeginPaint(hwnd,&ps); //开始绘图
360 |
361 | ////用户的绘制内容...
362 | SetTextColor(hdc,MapRGB(hdc,10,10,100));
363 | t=GUI_GetTickCount();
364 | y=24;
365 | i=0;
366 | while(y新建,选择新建一个字体文件,命名为firelogo,然后点击“确定”,操作流程如 图27_4_。
43 |
44 | .. image:: /media/docx136.jpeg
45 | :align: center
46 | :alt: 图 27‑4 新建文件
47 | :name: 图27_4
48 |
49 | 图 27‑4 新建文件
50 |
51 | 2. 选择替换的字符编码
52 |
53 | 所谓的APP图标,只是将该字库的某个字符编码替换为我们的图标,假如我们将A换成某个图标,当我们使用这个字库,显示字符A,就会显示我们的图标。我们切换会普通的字库,字符A就还是字符 A。下面我们将 A替换为野火的logo,双击 图27_5_ 的框框处,会出现一个新的界面,如 图27_6_。
54 |
55 | .. image:: /media/docx137.jpeg
56 | :align: center
57 | :alt: 图 27‑5 选择替换的字符 A
58 | :name: 图27_5
59 |
60 | 图 27‑5 选择替换的字符 A
61 |
62 | .. image:: /media/docx138.jpeg
63 | :align: center
64 | :alt: 图 27‑6字符A的界面
65 | :name: 图27_6
66 |
67 | 图 27‑6字符A的界面
68 |
69 | .. image:: /media/docx139.jpg
70 | :align: center
71 | :alt: 图 27‑7 字体的设置
72 | :name: 图27_7
73 |
74 | 图 27‑7 字体的设置
75 |
76 | 图27_7_ 的 1 处,用来设置字体的宽度,我们在设计的时候,尽量使每个图标都是等宽的。处是我们图标的设计区,从WinAscent到WinDescent。如果设计的图标超过这两条边线,则超出的部分不会显示,在设计图标的时候,最好使图标位于处的中间。
77 |
78 | FontCreator提供两种设计方式:有图片加载方式以及手动绘制,图27_8_ 的处是图片加载,支持多种格式,包括.gif,.jpg,.png,.ai等格式 ;处是手工绘制。这里就不讲手动绘制了,有兴趣的,绘画功底强的读者,可以尝试一下第二种绘制方式。
79 |
80 | .. image:: /media/docx140.jpg
81 | :align: center
82 | :alt: 图 27‑8 绘制方式
83 | :name: 图27_8
84 |
85 | 图 27‑8 绘制方式
86 |
87 | 点击 图27_8_ 的处,选择野火的logo,如 图27_9_ 所示,这里使用的是.ai格式的文件。(这里也可以选择一张普通格式的图片,没有什么影响)
88 |
89 | .. image:: /media/docx141.jpg
90 | :align: center
91 | :alt: 图 27‑9 选择图标
92 | :name: 图27_9
93 |
94 | 图 27‑9 选择图标
95 |
96 | 打开之后,如 图27_10_ 所示,之后,我们就需要调整图标的位置,大小,使它位于WinAscent到WinDescent之间,调整后的结果如 图27_11_ 所示,图标位于两个阴影区域的交界区。
97 |
98 | .. image:: /media/docx142.jpg
99 | :align: center
100 | :alt: 图 27‑10 选中图标
101 | :name: 图27_10
102 |
103 | 图 27‑10 选中图标
104 |
105 | .. image:: /media/docx143.jpg
106 | :align: center
107 | :alt: 图 27‑11 调整之后的结果
108 | :name: 图27_11
109 |
110 | 图 27‑11 调整之后的结果
111 |
112 | 点击 图27_12_ 的处,回到最开始的界面,我们可以看到A字符变成野火的logo了。这就说明我们的制作完成了。
113 |
114 | .. image:: /media/docx144.jpg
115 | :align: center
116 | :alt: 图 27‑12 完成制作
117 | :name: 图27_12
118 |
119 | 图 27‑12 完成制作
120 |
121 | 3. 保存字库
122 |
123 | 点击图 27‑13的处,保存字库,在处选择保存的路径,最后点击“保存”按键保存。
124 |
125 | .. image:: /media/docx145.jpg
126 | :align: center
127 | :alt: 图 27‑13 保存字库
128 | :name: 图27_13
129 |
130 | 图 27‑13 保存字库
131 |
132 | 4. 测试生成的字体
133 |
134 | 我们可以在电脑上使用刚刚生成的字体,具体的操作方法:双击刚刚生成的firelogo.ttf文件,安装该字体,如 图27_14_。
135 |
136 | .. image:: /media/docx146.jpeg
137 | :align: center
138 | :alt: 图 27‑14 安装字体
139 | :name: 图27_14
140 |
141 | 图 27‑14 安装字体
142 |
143 | 打开一个新建的word文档,在字体设置处,选择firelogo,然后输入A,就可以打出野火的logo了,是不是很神奇,如 图27_15_。
144 |
145 | .. image:: /media/docx147.jpg
146 | :align: center
147 | :alt: 图 27‑15 测试结果
148 | :name: 图27_15
149 |
150 | 图 27‑15 测试结果
151 |
152 | 到此为止,制作APP图标就结束了。利用上一章的软件和方法,将刚刚生成的字体制作成emXGUI支持的格式xft即可。这样,我们就可以在emXGUI上使用我们刚刚的图标字体,下面我们一起学习如何在emXGUI上显示刚刚制作完成的图标。
153 |
154 | 显示APP图标实验
155 | ~~~~~~~~~~~~~~~~~~
156 |
157 | 在emXGUI上显示APP图标,实际上就是切换到字体类型,然后显示图标对应的字符。使用的函数API与上一章相同。实验的设计要求如 图27_16_。处使用的是logo字体,主要为野火的图标;处为控制图标字体,是常见的一些图标,例如返回,上翻,下翻,保存等图标;处使用的图标字体。
158 |
159 | .. image:: /media/docx148.jpg
160 | :align: center
161 | :alt: 图 27‑16 设计要求
162 | :name: 图27_16
163 |
164 | 图 27‑16 设计要求
165 |
166 | .. _代码分析-22:
167 |
168 | 代码分析
169 | ^^^^^^^^
170 |
171 | (1) 创建字体句柄
172 |
173 | .. code-block:: c
174 | :caption: 代码清单 27‑1 三种字体类型(文件gui_font_port.c)
175 | :linenos:
176 | :name: 代码清单27_1
177 |
178 | #if(GUI_ICON_LOGO_EN)
179 | /* logo字体 */
180 | HFONT logoFont =NULL;
181 | /* 图标字体 */
182 | HFONT iconFont =NULL;
183 | /* 控制图标字体 */
184 | HFONT controlFont =NULL;
185 | #endif
186 |
187 | 创建三种字体类型,用来存放字体句柄。
188 |
189 | .. code-block:: c
190 | :caption: 代码清单 27‑2创建字体句柄(文件gui_font_port.c)
191 | :linenos:
192 | :name: 代码清单27_2
193 |
194 | /**
195 | * @brief GUI默认字体初始化
196 | * @param 无
197 | * @retval 返回默认字体的句柄
198 | */
199 | HFONT GUI_Default_FontInit(void)
200 | {
201 | //省略一些代码
202 | #if(GUI_ICON_LOGO_EN)
203 |
204 | /* 创建logo字体 */
205 | logoFont = XFT_CreateFont(GUI_LOGO_FONT);
206 | /* 创建图标字体 */
207 | iconFont = XFT_CreateFont(GUI_ICON_FONT);
208 | /* 创建控制图标字体 */
209 | controlFont = XFT_CreateFont(GUI_CONTROL_FONT);
210 |
211 | if(logoFont==NULL)
212 | GUI_ERROR("logoFont create failed");
213 |
214 | if(iconFont ==NULL)
215 | GUI_ERROR("iconFont create failed");
216 |
217 | if(controlFont ==NULL)
218 | GUI_ERROR("controlFont create failed");
219 | #endif
220 |
221 | return defaultFont;
222 | }
223 |
224 | GUI_Default_FontInit函数中,调用XFT_CreateFont函数来创建字体,GUI_LOGO_FONT、GUI_ICON_FONT以及GUI_CONTROL_FONT是我们使用bin2c软件生成的图标字体数组,以logo图标字体为例,
225 | 见 代码清单27_3_ 。就这样我们就在emXGUI上“安装”了三种字体,需要使用什么字体,只需要调用SetFont函数即可。
226 |
227 | .. code-block:: c
228 | :caption: 代码清单 27‑3 字库数组(文件LOGO_50_4BPP.c)
229 | :linenos:
230 | :name: 代码清单27_3
231 |
232 | #define GUI_LOGO_FONT LOGO_50_4BPP
233 | const char LOGO_50_4BPP[]={88,70,84,0,88,71,85,73,32,70,111,110,116,0,0,0,
234 | 0,0,0,0,232,19,0,0,232,51,0,0,64,0,0,0,
235 | 234,4,0,0,2,0,4,0,50,0,50,0,4,0,0,0,
236 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
237 | 0,42,0,0,25,4,0,0,0,0,0,0,0,0,0,0,
238 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
239 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
240 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
241 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
242 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
243 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,
244 |
245 | (2) 窗口回调函数
246 |
247 | - WM_PAINT
248 |
249 | .. code-block:: c
250 | :caption: 代码清单 27‑4 WM_PAINT消息(文件GUI_DEMO_LogoIconFont.c)
251 | :linenos:
252 | :name: 代码清单27_4
253 |
254 | case WM_PAINT: //窗口需要绘制时,会自动产生该消息.
255 | {
256 | PAINTSTRUCT ps;
257 | HDC hdc;
258 |
259 | RECT rc0;
260 |
261 | hdc =BeginPaint(hwnd,&ps);
262 |
263 | ////用户的绘制内容...
264 | GetClientRect(hwnd,&rc0);
265 | SetPenColor(hdc,MapRGB(hdc,200,200,220));
266 | SetTextColor(hdc,MapRGB(hdc,250,250,250));
267 | /* 使用图标字体*/
268 | SetFont(hdc, logoFont);
269 | DrawText(hdc,L" A B C ",-1,&rc0,DT_LEFT);
270 | /* 使用控制图标字体*/
271 | SetFont(hdc, controlFont);
272 | SetTextColor(hdc,MapRGB(hdc,0,0,0));
273 | rc0.y += 80;
274 | DrawText(hdc,L" A B C D E F G H \\r\n I J K L M N O P",-1,&rc0,DT_LEFT);
275 | /* 使用图标字体*/
276 | SetFont(hdc, iconFont);
277 | SetTextColor(hdc,MapRGB(hdc,238,142,0));
278 | rc0.y += 120;
279 | DrawText(hdc,L" A B C D E ",-1,&rc0,DT_LEFT);
280 |
281 | SetTextColor(hdc,MapRGB(hdc,100,149,237));
282 | rc0.y += 120;
283 | DrawText(hdc,L" F G H I J",-1,&rc0,DT_LEFT);
284 | /* 恢复默认字体 */
285 | SetFont(hdc, defaultFont);
286 | SetTextColor(hdc,MapRGB(hdc,250,250,250));
287 |
288 | EndPaint(hwnd,&ps);
289 | break;
290 | }
291 |
292 | 由于图标实际上就是字符,所以颜色受TextColor的影响,调用SetTextColor函数来选择图标的颜色,logoFont字体中的内容如 图27_17_ 所示。
293 | 调用SetFont函数切换字体,使用DrawText函数来显示A B C对应的图标。
294 |
295 | .. image:: /media/docx149.jpg
296 | :align: center
297 | :alt: 图 27‑17 logoFont字体
298 | :name: 图27_17
299 |
300 | 图 27‑17 logoFont字体
301 |
302 | controlFont字体中的内容如 图27_18_, 图标是从字符A到P,设置图标的颜色为RGB(0,0,0),调用DrawText显示字符串“A B C D E F G H \\r\n I J K L M N O P”,就可以显示相应的图标。
303 |
304 | .. image:: /media/docx150.jpeg
305 | :align: center
306 | :alt: 图 27‑18 控制图标字体
307 | :name: 图27_18
308 |
309 | 图 27‑18 控制图标字体
310 |
311 | iconFont字体中的内容如 图27_19_,使用RGB(238,142,0)的颜色来显示头五个图标,矩形变量用来控制显示的位置,调用DrawText函数来显示前五个字符。设置颜色为RGB(100,149,237),显示后五个字符,起点的y坐标偏移120个像素。
312 |
313 | .. image:: /media/docx151.jpg
314 | :align: center
315 | :alt: 图 27‑19 图标字体
316 | :name: 图27_19
317 |
318 | 图 27‑19 图标字体
319 |
320 | - WM_ERASEBKGND
321 |
322 | .. code-block:: c
323 | :caption: 代码清单 27‑5 WM_ERASEBKGND消息(文件GUI_DEMO_LogoIconFont.c)
324 | :linenos:
325 | :name: 代码清单27_5
326 |
327 | case WM_ERASEBKGND:
328 | {
329 | HDC hdc=(HDC)wParam;
330 |
331 | GetClientRect(hwnd,&rc);
332 | SetBrushColor(hdc,MapRGB(hdc,215,61,50));
333 | FillRect(hdc,&rc);
334 | return TRUE;
335 | }
336 |
337 | 使用FillRect来绘制客户区的背景,颜色调用SetBrushColor函数来设置,此处为RGB(215,61,50),最后要返回TRUE,这样在WM_PAINT消息,才不会重绘客户区背景。
338 |
339 | 最后,将GUI_DEMO_LogoIconFont函数添加到AppMain函数中。
340 |
341 | .. _实验结果-13:
342 |
343 | 实验结果
344 | ^^^^^^^^
345 |
346 | .. image:: /media/docx152.jpg
347 | :align: center
348 | :alt: 图 27‑20 实验结果
349 | :name: 图27_20
350 |
351 | 图 27‑20 实验结果
352 |
353 |
--------------------------------------------------------------------------------
/section_one/section3.rst:
--------------------------------------------------------------------------------
1 | .. vim: syntax=rst
2 |
3 | 新建工程—RT-Thread+STM32固件库
4 | ----------------------------------------------
5 |
6 | 本章内容待添加…
7 |
--------------------------------------------------------------------------------
/section_one/section7.rst:
--------------------------------------------------------------------------------
1 | .. vim: syntax=rst
2 |
3 | 复选框控件
4 | ----------
5 |
6 | 前面我们已经讲过按钮控件,下面我们开始学习 图7_1_ 处的复选框控件。
7 |
8 | .. image:: /media/docx024.jpg
9 | :align: center
10 | :alt: 图 7‑1 各种按钮
11 | :name: 图7_1
12 |
13 | 复选框是一种可同时选中多项的基础控件。假设我们现在做一个电子调查问卷,了解大家的爱好,有些人的爱好很广泛,如唱歌,骑车,旅游,美食等等,我们就可以使用复选框来完成。
14 |
15 | 创建复选框控件
16 | ~~~~~~~~~~~~~~~~~~~~~
17 |
18 | .. _标准消息类型及参数说明-2:
19 |
20 | 标准消息类型及参数说明
21 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
22 |
23 | 复选框也是按钮控件的一种,使用的消息和处理方式也都大同小异。有什么不懂的地方,可以参考上一章的标准消息类型及参数说明。
24 |
25 | 创建复选框控件函数
26 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
27 |
28 | 复选框属于子控件(子窗口),可以通过调用CreateWindow函数来创建。实际上,无论什么控件,都是调用CreateWindow函数来创建的,下面重点讲解一下差异之处。
29 |
30 | .. code-block:: c
31 | :caption: 代码清单 7‑1 创建窗口函数(文件emXGUI.h)
32 | :linenos:
33 | :name: 代码清单7_1
34 |
35 | HWND CreateWindowEx( U32 dwExStyle, LPCVOID lpClass, LPCWSTR lpWindowName,
36 | U32 dwStyle, int x, int y, int nWidth, int nHeight,
37 | HWND hwndParent, UINT WinId,HINSTANCE hInstance,LPVOID lpParam);
38 |
39 | 1) lpClass:复选框属于按钮控件中的一类,这里应该选择BUTTON类。
40 |
41 | 2) lpWindowName:复选框项目的名称,可以是中文。注意,这里也是使用的宽字符串,一个字符占两个字节。
42 |
43 | 3) dwStyle:复选框的风格。参数BS_CHECKBOX代表该控件为复选框。当使用复选框这个控件时,这个参数是必须的,否则就和普通按钮一样了。还可以使用按钮控件的风格(BS_NOTIFY),只有控件拥有该属性,才可以接收到控件被按下(未松手)的消息。以及窗口风格。
44 |
45 | ..
46 |
47 | 至于其他的参数,和创建按钮一样,也是同样的用法,这里不作描述。
48 |
49 | 创建复选框控件实验
50 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
51 |
52 | .. _设计要求-2:
53 |
54 | 设计要求
55 | ^^^^^^^^^^^^
56 |
57 | 图7_2_ 是excel设计的复选框界面的内容,比较简单,容易理解。下面通过代码讲解如何实现这个界面。
58 |
59 | .. image:: /media/docx032.jpg
60 | :align: center
61 | :alt: 图 7‑2 复选框界面
62 | :name: 图7_2
63 |
64 | .. _代码设计-2:
65 |
66 | 代码设计
67 | ^^^^^^^^^^^^
68 |
69 | .. _编程要点-2:
70 |
71 | 编程要点
72 | ''''''''''''
73 |
74 | 1) 配置WNDCLASS窗口结构体,调用CreateWindowEx创建父窗口;
75 |
76 | 2) 实现消息循环
77 |
78 | 3) 编写窗口回调函数,完成对消息的处理。
79 |
80 | .. _代码分析-2:
81 |
82 | 代码分析
83 | ''''''''''''
84 |
85 | (1) 创建父窗口代码分析
86 |
87 | .. code-block:: c
88 | :caption: 代码清单 7‑2 创建父窗口(文件GUI_DEMO_Checkbox.c)
89 | :linenos:
90 | :name: 代码清单7_2
91 |
92 | void GUI_DEMO_Checkbox(void)
93 | {
94 | HWND hwnd;
95 | WNDCLASS wcex;
96 | MSG msg;
97 |
98 | wcex.Tag = WNDCLASS_TAG;
99 | wcex.Style = CS_HREDRAW | CS_VREDRAW;
100 | wcex.lpfnWndProc = win_proc;
101 | wcex.cbClsExtra = 0;
102 | wcex.cbWndExtra = 0;
103 | wcex.hInstance = 0;//hInst;
104 | wcex.hIcon = 0;//LoadIcon(hInstance, (LPCTSTR)IDI_WIN32_APP_TEST);
105 | wcex.hCursor = 0;//LoadCursor(NULL, IDC_ARROW);
106 |
107 | hwnd =CreateWindowEx( NULL,
108 | &wcex,
109 | _T("GUI Demo - Checkbox"),
110 | WS_CAPTION| WS_DLGFRAME| WS_BORDER|WS_CLIPCHILDREN,
111 | 0,0,GUI_XSIZE,GUI_YSIZE,
112 | NULL,NULL,NULL,NULL);
113 |
114 | ShowWindow(hwnd,SW_SHOW);
115 | while(GetMessage(&msg,hwnd))
116 | {
117 | TranslateMessage(&msg);
118 | DispatchMessage(&msg);
119 | }
120 | }
121 |
122 | 每一个控件都是在父窗口上显示,调用CreateWindowEx创建父窗口,设置win_proc作为窗口回调函数,详细解释可以参考,按钮控件章节的代码分析。
123 |
124 | (2) 窗口回调函数
125 |
126 | .. code-block:: c
127 | :caption: 代码清单 7‑3 窗口回调函数win_proc(文件GUI_DEMO_Checkbox.c)
128 | :linenos:
129 | :name: 代码清单7_3
130 |
131 | static LRESULT win_proc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
132 | {
133 | // HDC hdc;
134 | // PAINTSTRUCT ps;
135 | RECT rc;
136 | // WCHAR wbuf[128];
137 | //int i,x,y;
138 | // HWND wnd;
139 |
140 | switch(msg)
141 | {
142 | case WM_CREATE:
143 | GetClientRect(hwnd,&rc);
144 | //创建按钮(EXIT)
145 | CreateWindow(BUTTON,L"EXIT",WS_VISIBLE,
146 | rc.w-100,8,80,48,hwnd,ID_EXIT,NULL,NULL);
147 | rc.x =20;
148 | rc.y =40;
149 | rc.w =128;
150 | rc.h =30;
151 | //创建复选框Checkbox1(BS_CHECKBOX)
152 | CreateWindow(BUTTON,L"Checkbox1",BS_CHECKBOX|WS_VISIBLE,
153 | rc.x,rc.y,rc.w,rc.h,hwnd,ID_CB1,NULL,NULL);
154 | //往下移动矩形位置(X轴不变,Y轴位置增加rc.h+10个像素)
155 | OffsetRect(&rc,0,rc.h+10);
156 | //创建复选框Checkbox2(BS_CHECKBOX)
157 | CreateWindow(BUTTON,L"Checkbox2",BS_CHECKBOX|WS_VISIBLE,
158 | rc.x,rc.y,rc.w,rc.h,hwnd,ID_CB2,NULL,NULL);
159 | OffsetRect(&rc,0,rc.h+10);
160 | //创建复选框Checkbox3--不响应输入设备(WS_DISABLED)
161 | CreateWindow(BUTTON,L"Checkbox3",WS_DISABLED|BS_CHECKBOX|WS_VISIBLE,
162 | rc.x,rc.y,rc.w,rc.h,hwnd,ID_CB3,NULL,NULL);
163 | OffsetRect(&rc,0,rc.h+10);
164 | //创建复选框Checkbox4--类似按钮,当被按下时,该按钮下沉(BS_PUSHLIKE)
165 | CreateWindow(BUTTON,L"Checkbox4",BS_PUSHLIKE|BS_CHECKBOX|WS_VISIBLE,
166 | rc.x,rc.y,rc.w,rc.h,hwnd,ID_CB4,NULL,NULL);
167 | rc.x =160;
168 | rc.y =40;
169 | rc.w =128;
170 | rc.h =30;
171 | //创建复选框Checkbox5--检测BN_CHECKED消息(BS_NOTIFY)
172 | CreateWindow(BUTTON,L"Checkbox5",BS_NOTIFY|BS_CHECKBOX|WS_VISIBLE,
173 | rc.x,rc.y,rc.w,rc.h,hwnd,ID_CB5,NULL,NULL);
174 | return TRUE;
175 | case WM_NOTIFY: //WM_NOTIFY消息:wParam低16位为发送该消息的控件ID,高16位为通知码;
176 | lParam指向了一个NMHDR结构体.
177 | {
178 | u16 code,id;
179 | NMHDR *nr=(NMHDR*)lParam;
180 | id =LOWORD(wParam);
181 | code=HIWORD(wParam);
182 | if(id >= ID_CB1 && id<= ID_CB5)
183 | {
184 | if(code == BN_CLICKED) //被点击了
185 | {
186 | if(SendMessage(nr->hwndFrom,BM_GETSTATE,0,0)&BST_CHECKED) //获取当前状态
187 | { //复选框选中.
188 | GUI_Printf("Checkbox Checked: ID:%04XH\r\n",id);
189 | }
190 | else
191 | {//复选未框选中.
192 | GUI_Printf("Checkbox Unchecked: ID:%04XH\r\n",id);
193 | }
194 | }
195 |
196 | if(code == BN_CHECKED) //指定了BS_NOTIFY,才会产生该消息.
197 | { //复选框被选中.
198 | GUI_Printf("Checkbox Checked: ID:%04XH\r\n",id);
199 | }
200 |
201 | }
202 | if(id == ID_EXIT && code == BN_CLICKED)
203 | {
204 | PostCloseMessage(hwnd); //产生WM_CLOSE消息关闭主窗口
205 | }
206 |
207 | }
208 | break;
209 | case WM_CTLCOLOR:
210 | {
211 | u16 id;
212 |
213 | id =LOWORD(wParam);
214 |
215 | if(id== ID_CB5)
216 | {
217 | CTLCOLOR *cr;
218 | cr =(CTLCOLOR*)lParam;
219 |
220 | if(SendMessage(GetDlgItem(hwnd,id),BM_GETSTATE,0,0)&BST_CHECKED)
221 | {
222 | //设置文字颜色
223 | cr->TextColor =RGB888(250,0,0);
224 | //设置背景颜色
225 | cr->BackColor =RGB888(220,200,200);
226 | //设置边框颜色
227 | cr->BorderColor =RGB888(30,30,230);
228 | //设置前景颜色
229 | cr->ForeColor =RGB888(100,250,100);
230 | }
231 | else
232 | {
233 | cr->TextColor =RGB888(10,150,10);
234 | cr->BackColor =RGB888(200,220,200);
235 | cr->BorderColor =RGB888(50,50,50);
236 | cr->ForeColor =RGB888(180,200,230);
237 | }
238 | return TRUE;
239 | }
240 | else
241 | {
242 | return FALSE;
243 | }
244 |
245 | }
246 | default:
247 | return DefWindowProc(hwnd,msg,wParam,lParam);
248 | }
249 | return WM_NULL;
250 | }
251 |
252 | 1. WM_CREATE
253 |
254 | 在WM_CREATE消息创建控件,如 表格7_1_ 所示。
255 |
256 | 表格 7_1 控件的具体信息
257 |
258 | .. _表格7_1:
259 |
260 | ======== ========= ======= ==================================
261 | 控件类型 名称 ID值 风格
262 | ======== ========= ======= ==================================
263 | BUTTON EXIT ID_EXIT WS_VISIBLE
264 | \ Checkbox1 ID_CB1 BS_CHECKBOX|WS_VISIBLE
265 | \ Checkbox2 ID_CB2 BS_CHECKBOX|WS_VISIBLE
266 | \ Checkbox3 ID_CB3 WS_DISABLED|BS_CHECKBOX|WS_VISIBLE
267 | \ Checkbox4 ID_CB4 BS_PUSHLIKE|BS_CHECKBOX|WS_VISIBLE
268 | \ Checkbox5 ID_CB5 BS_NOTIFY|BS_CHECKBOX|WS_VISIBLE
269 | ======== ========= ======= ==================================
270 |
271 | 每一个复选框各自的ID号。复选框的风格可以使用窗口类和按钮的风格,但是都必须要有BS_CHECKBOX的属性值 。调用OffsetRect函数来移动控件的位置:X轴不变,Y轴位置增加rc.h+10个像素。
272 |
273 | 2. WM_NOTIFY
274 |
275 | WM_NOTIFY消息用来处理控件的动作响应,该消息的参数wParam低16位为发送该消息的控件ID,高16位为通知码,即控件的动作。可以利用LOWORD函数和HIWORD函数来读取控件的ID和通知码。根据通知码,来实现控件的动作响应。代码清单7_3_ 中,调用SendMessage给复选框控件发送消息BM_GETSTATE,实现检测复选框是否被选中。并输出到串口助手。
276 |
277 | 既然已经知道控件被点击了,为什么还要发送消息,去获取控件的当前状态呢?可能会有人有这个疑问。举个例子,电源开关。你拨了一下,你怎么知道电路有没有电?是不是要看电源指示灯亮不亮。亮了,说明开关是由断开到闭合。灭了,说明开关是由闭合到断开。这里也是一样的道理:你点击控件,至于控件是由选中到未选中,还是由
278 | 未选中到选中,就是通过发送消息BM_GETSTATE来检测的。
279 |
280 | 注意,只有拥有BS_NOTIFY的控件,才可以发送BN_CHECKED的消息,用于检测控件是否被按下(未松开)。
281 |
282 | 按钮控件EXIT,是用来关闭父窗口的。单击时,会发送关闭消息。
283 |
284 | 3. WM_CTLCOLOR
285 |
286 | 控件在绘制前,会向其父窗口发送WM_CTLCOLOR消息,该消息的参数wParm低16位产生该消息的窗口ID。参数lParam指向一个CTLCOLOR的结构体指针地址。代码清单7_4_ 。
287 |
288 | .. code-block:: c
289 | :caption: 代码清单 7‑4 CTLCOLOR的结构体(文件emXGUI.h)
290 | :linenos:
291 | :name: 代码清单7_4
292 |
293 | typedef struct
294 | {
295 | COLOR_RGB32 TextColor; //文字颜色
296 | COLOR_RGB32 BorderColor; //边框颜色。
297 | COLOR_RGB32 BackColor; //背景颜色。
298 | COLOR_RGB32 ForeColor; //前景颜色。
299 | }CTLCOLOR;
300 |
301 | 在 代码清单7_3_ 中,调用GetDlgItem来获取父窗口中CheckBox5的句柄,向CheckBox5发送消息BM_GETSTATE,来获取CheckBox5的状态值。GetDlgItem的用法,可以查阅《emXGUI API编程手册》的窗口/消息系统API。
302 |
303 | 根据控件的状态值,设置控件窗口的文字颜色(TextColor),边框颜色(BorderColor),
304 | 背景颜色(BackColor),前景颜色(ForeColor),改变控件窗口的外观颜色。一定要返回TRUE,否则的话,则按照默认方案来配置。前景颜色指的是选中后,CheckBox框框,也就是平时打钩的地方,显示的颜色。
305 |
306 | 4. default—用户不关心的消息
307 |
308 | 调用DefWindowProc来处理。
309 |
310 | 为什么没有重绘消息呢?是窗口不用重绘吗?答案是肯定的,不是说任何窗口在移动和创建的过程中,都需要进行重绘吗。这是没有错的,不过因为在图 7‑2我们并没有在客户区显示内容,而控件的重绘是由emXGUI内部完成的,因此,这里没有WM_PAINT也是可以的。
311 |
312 | 最后,将函数GUI_DEMO_Checkbox加入到GUI_AppMain函数中。
313 |
314 | .. code-block:: c
315 | :caption: 代码清单 7_5 GUI_AppMain函数(文件GUI_AppMain.c)
316 | :linenos:
317 | :name: 代码清单7_5
318 |
319 | void GUI_AppMain(void)
320 | {
321 | while(1)
322 | {
323 | GUI_DEMO_Button();
324 | GUI_DEMO_Checkbox();
325 | }
326 | }
327 |
328 | .. _实验现象-2:
329 |
330 | 实验现象
331 | ^^^^^^^^^^^^
332 |
333 | 实验结果如 图7_3_ 和 图7_4_。图7_3_ 是界面的初始化状态,图7_4_ 是界面的CheckBox被选中状态。当CheckBox4被选中时,CheckBox4会像按钮一样下沉。CheckBox5在选中状态下的文字,边框, 背景和前景的颜色发生了改变。
334 |
335 | .. image:: /media/docx033.jpg
336 | :align: center
337 | :alt: 图 7‑3 实验结果
338 | :name: 图7_3
339 |
340 | 图 7‑3 实验结果
341 |
342 | .. image:: /media/docx034.jpg
343 | :align: center
344 | :alt: 图 7‑4 实验结果(选中状态)
345 | :name: 图7_4
346 |
347 | 图 7‑4 实验结果(选中状态)
348 |
--------------------------------------------------------------------------------
/section_one/section8.rst:
--------------------------------------------------------------------------------
1 | .. vim: syntax=rst
2 |
3 | 单选按钮控件
4 | ------------------
5 |
6 | 最后,我们学习 图8_1_ 处的单选按钮控件。顾名思义,单选按钮,就是只可以选择一个选项。例如串口收发的停止位,只可以是1、1.5、2位中的某一个值。
7 |
8 | .. image:: /media/docx024.jpg
9 | :align: center
10 | :alt: 图 8‑1 各种按钮
11 | :name: 图8_1
12 |
13 | 创建单选按钮控件
14 | ~~~~~~~~~~~~~~~~~~~~~~~~
15 |
16 | .. _标准消息类型及参数说明-3:
17 |
18 | 标准消息类型及参数说明
19 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
20 |
21 | 单选按钮需要用到的消息和处理方式,也没有什么变化。有什么不懂的地方,可以参考按钮控件章节的标准消息类型及参数说明。
22 |
23 | 创建单选按钮控件函数
24 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
25 |
26 | .. code-block:: c
27 | :caption: 代码清单 8‑1 创建窗口函数(文件emXGUI.h)
28 | :linenos:
29 | :name: 代码清单8_1
30 |
31 | HWND CreateWindowEx( U32 dwExStyle, LPCVOID lpClass, LPCWSTR lpWindowName,
32 | U32 dwStyle, int x, int y, int nWidth, int nHeight,
33 | HWND hwndParent, UINT WinId,HINSTANCE hInstance,LPVOID lpParam);
34 |
35 | 1) lpClass:单选按钮属于按钮控件中的一类,这里选择BUTTON类。
36 |
37 | 2) dwStyle:单选按钮的风格。参数BS_RADIOBOX代表该控件为单选按钮。当使用单选按钮时,这个参数是必须的。单选按钮控件也支持窗口以及按钮的风格参数。
38 |
39 | 3) WinId:控件的ID值。单选按钮控件的ID值高16位为GroupID号,只有在同一组内的单选按钮,才会有“多选一"的效果。
40 |
41 | 至于其他的参数,和创建按钮一样,也是同样的用法,这里不作描述。
42 |
43 | 创建单选按钮控件实验
44 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
45 |
46 | .. _设计要求-3:
47 |
48 | 设计要求
49 | ^^^^^^^^^^^^
50 |
51 | 图8_2_ 只是简单地展示了单选按钮控件,下面通过代码讲解如何实现这个界面。
52 |
53 | .. image:: /media/docx035.jpg
54 | :align: center
55 | :alt: 图8_2 设计要求
56 | :name: 图8_2
57 |
58 | .. _代码分析-3:
59 |
60 | 代码分析
61 | ^^^^^^^^^^^^
62 |
63 | (1) 创建父窗口
64 |
65 | .. code-block:: c
66 | :caption: 代码清单 8‑2 GUI_DEMO_Radiobox函数(文件GUI_DEMO_Radiobox.c)
67 | :linenos:
68 | :name: 代码清单8_2
69 |
70 | void GUI_DEMO_Radiobox(void)
71 | {
72 | HWND hwnd;
73 | WNDCLASS wcex;
74 | MSG msg;
75 | /////
76 | wcex.Tag = WNDCLASS_TAG;
77 | wcex.Style = CS_HREDRAW | CS_VREDRAW;
78 | wcex.lpfnWndProc = win_proc;
79 | wcex.cbClsExtra = 0;
80 | wcex.cbWndExtra = 0;
81 | wcex.hInstance = 0;//hInst;
82 | wcex.hIcon = 0;//LoadIcon(hInstance,(LPCTSTR)IDI_WIN32_APP_TEST);
83 | wcex.hCursor = 0;//LoadCursor(NULL, IDC_ARROW);
84 |
85 | hwnd =CreateWindowEx( NULL,
86 | &wcex,
87 | _T("GUI Demo - Radiobox"),
88 | WS_CAPTION| WS_DLGFRAME| WS_BORDER|WS_CLIPCHILDREN,
89 | 0,0,GUI_XSIZE,GUI_YSIZE,
90 | NULL,NULL,NULL,NULL);
91 | ShowWindow(hwnd,SW_SHOW);
92 | while(GetMessage(&msg,hwnd))
93 | {
94 | TranslateMessage(&msg);
95 | DispatchMessage(&msg);
96 | }
97 | }
98 |
99 | 创建父窗口,标题栏为“GUI Demo - Radiobox”,带有大小边框,设置win_proc作为窗口回调函数。
100 |
101 | (2) 窗口回调函数
102 |
103 | 1. WM_CREATE消息
104 |
105 | .. code-block:: c
106 | :caption: 代码清单 8‑3 WM_CREATE消息响应(文件GUI_DEMO_Radiobox.c)
107 | :linenos:
108 | :name: 代码清单8_3
109 |
110 | case WM_CREATE:
111 | {
112 | //获得客户区的大小
113 | GetClientRect(hwnd,&rc);
114 |
115 | CreateWindow(BUTTON,L"EXIT",WS_VISIBLE,rc.w-100,8,80,48,hwnd,ID_EXIT,NULL,NULL);
116 |
117 | //创建第1组单选按钮(窗口ID的高16位为GroupID号,只有在同一组内的单选按钮,才会有"多选一"的效果)
118 |
119 | rc.x =20;
120 | rc.y =30;
121 | rc.w =120;
122 | rc.h =32;
123 | CreateWindow(BUTTON,L"Radiobox1",BS_RADIOBOX|WS_VISIBLE,
124 | rc.x,rc.y,rc.w,rc.h,hwnd,(1<<16)|ID_RB1,NULL,NULL);
125 | OffsetRect(&rc,0,rc.h+10);
126 | CreateWindow(BUTTON,L"Radiobox2",WS_DISABLED|BS_RADIOBOX|WS_VISIBLE,
127 | rc.x,rc.y,rc.w,rc.h,hwnd,(1<<16)|ID_RB2,NULL,NULL);
128 |
129 | //创建第2组单选按钮(GroupID号为2,使用常规按钮风格(BS_PUSHLIKE)).
130 | OffsetRect(&rc,0,rc.h+10);
131 | CreateWindow(BUTTON,L"Radiobox3",BS_RADIOBOX|BS_PUSHLIKE|WS_VISIBLE,
132 | rc.x,rc.y,rc.w,rc.h,hwnd,(2<<16)|ID_RB3,NULL,NULL);
133 | OffsetRect(&rc,0,rc.h+10);
134 | CreateWindow(BUTTON,L"Radiobox4",BS_RADIOBOX|BS_PUSHLIKE|WS_VISIBLE,
135 | rc.x,rc.y,rc.w,rc.h,hwnd,(2<<16)|ID_RB4,NULL,NULL);
136 |
137 | //创建第3组单选按钮(GroupID号为3).
138 | rc.x =160;
139 | rc.y =30;
140 | rc.w =120;
141 | rc.h =32;
142 | CreateWindow(BUTTON,L"Radiobox5",BS_RADIOBOX|WS_VISIBLE,
143 | rc.x,rc.y,rc.w,rc.h,hwnd,(3<<16)|ID_RB5,NULL,NULL);
144 | OffsetRect(&rc,0,rc.h+10);
145 | CreateWindow(BUTTON,L"Radiobox6",BS_RADIOBOX|WS_VISIBLE,
146 | rc.x,rc.y,rc.w,rc.h,hwnd,(3<<16)|ID_RB6,NULL,NULL);
147 | return TRUE;
148 | }
149 |
150 | WM_CREATE消息创建的控件,如 表格8_1_ 所示。
151 |
152 | 表格 8‑1 控件的具体信息
153 |
154 | .. _表格8_1:
155 |
156 | ======== ======== ========= ============== ==================================
157 | 控件类型 名称 ID值 风格
158 | ======== ======== ========= ============== ==================================
159 | BUTTON EXIT ID_EXIT WS_VISIBLE
160 | \ RADIOBOX Radiobox1 (1<<16)|ID_RB1 BS_RADIOBOX|WS_VISIBLE
161 | \ Radiobox2 (1<<16)|ID_RB2 WS_DISABLED|BS_RADIOBOX|WS_VISIBLE
162 | \ Radiobox3 (2<<16)|ID_RB3 BS_RADIOBOX|BS_PUSHLIKE|WS_VISIBLE
163 | \ Radiobox4 (2<<16)|ID_RB4 BS_RADIOBOX|BS_PUSHLIKE|WS_VISIBLE
164 | \ Radiobox5 (3<<16)|ID_RB5 BS_RADIOBOX|WS_VISIBLE
165 | \ Radiobox6 (3<<16)|ID_RB6 BS_RADIOBOX|WS_VISIBLE
166 | ======== ======== ========= ============== ==================================
167 |
168 | 所有单选按钮控件都是BS_RADIOBOX 属性。Radiobox3和Radiobox4的属性BS_PUSHLIKE,表示控件的外观是一个按键,当被选中时,控件会下沉。
169 |
170 | .. code-block:: c
171 | :caption: 代码清单 8‑4控件ID值(文件GUI_DEMO_Radiobox.c)
172 | :linenos:
173 | :name: 代码清单8_4
174 |
175 | #define ID_RB1 0x1101
176 | #define ID_RB2 0x1102
177 | #define ID_RB3 0x1103
178 | #define ID_RB4 0x1104
179 | #define ID_RB5 0x1105
180 | #define ID_RB6 0x1106
181 |
182 | 代码清单8_4_ 控件ID值(文件GUI_DEMO_Radiobox.罗列了所有单选按钮的ID值。其高16位代表所属Group的ID号。以组3为例,组1、组2都是一样的道理。3<<16等价于\ :math:`3*2^{16}`\
183 | ,转换为十六进制,就是0x00030000,再通过与ID_RB5进行或运算,得到结果为0x00031105,最前面的四位数就是Group的ID号。
184 |
185 | 2. WM_NOTIFY消息
186 |
187 | .. code-block:: c
188 | :caption: 代码清单 8_5 WM_NOTIFY消息响应(文件GUI_DEMO_Radiobox.c)
189 | :linenos:
190 | :name: 代码清单8_5
191 |
192 | case WM_NOTIFY: //WM_NOTIFY消息:wParam低16位为发送该消息的控件ID,高16位为通知码;
193 | lParam指向了一个NMHDR结构体.
194 | {
195 | u16 code,id;
196 |
197 | id =LOWORD(wParam);
198 | code=HIWORD(wParam);
199 | if(id >= ID_RB1 && id<= ID_RB6)
200 | {
201 | if(code == BN_CHECKED)
202 | { //单选框选中.
203 | GUI_Printf("Radiobox Checked: ID:%04XH\r\n",id);
204 | }
205 | }
206 | if(id == ID_EXIT && code == BN_CLICKED)
207 | {
208 | PostCloseMessage(hwnd);//产生WM_CLOSE消息关闭主窗口
209 | }
210 | break;
211 | }
212 |
213 | 调用LOWORD和HIWORD读取控件的ID和通知码。单选按钮选中,则在串口输出控件的ID号。单击EXIT按钮,则会发送WM_CLOSE消息关闭主窗口。
214 |
215 | 3. WM_CTLCOLOR消息
216 |
217 | .. code-block:: c
218 | :caption: 代码清单 8‑6 WM_CTLCOLOR消息响应(文件GUI_DEMO_Radiobox.c)
219 | :linenos:
220 | :name: 代码清单8_6
221 |
222 | case WM_CTLCOLOR:
223 | {
224 | u16 id;
225 | id =LOWORD(wParam);
226 | if(id== ID_RB5 || id == ID_RB6) //只改变 RB5,RB6的颜色.
227 | {
228 | CTLCOLOR *cr;
229 | cr =(CTLCOLOR*)lParam;
230 | if(SendMessage(GetDlgItem(hwnd,id),BM_GETSTATE,0,0)&BST_CHECKED)
231 | {
232 | cr->TextColor =RGB888(250,0,0); //文字颜色(RGB32颜色格式)
233 | cr->BackColor =RGB888(220,200,200); //背景颜色(RGB32颜色格式)
234 | cr->BorderColor =RGB888(30,30,230); //边框颜色(RGB32颜色格式)
235 | cr->ForeColor =RGB888(100,250,100); //前景颜色(RGB32颜色格式)
236 | }
237 | else
238 | {
239 | cr->TextColor =RGB888(20,20,250);
240 | cr->BackColor =RGB888(200,220,200);
241 | cr->BorderColor =RGB888(50,50,50);
242 | cr->ForeColor =RGB888(180,200,230);
243 | }
244 | return TRUE;
245 | }
246 | else
247 | {
248 | return FALSE;
249 | }
250 | }
251 |
252 | WM_CTLCOLOR消息的lParam参数为产生该消息的窗口ID。这里只改变组3成员的外观,最后返回TRUE,否则将按照系统默认的样式来配置。
253 |
254 | 通过发送消息BM_GETSTATE,来得到当前控件是否被选中,同时改变控件的外观颜色。前景颜色,就是控件在选中状态,显示的颜色。
255 |
256 | 4. WM_PAINT消息
257 |
258 | .. code-block:: c
259 | :caption: 代码清单 8_7 WM_PAINT消息响应(文件GUI_DEMO_Radiobox.c)
260 | :linenos:
261 | :name: 代码清单8_7
262 |
263 | case WM_PAINT: //窗口需要重绘制时,会自动收到该消息.
264 | {
265 | PAINTSTRUCT ps;
266 | HDC hdc;
267 | hdc =BeginPaint(hwnd,&ps);
268 | SetTextColor(hdc,MapRGB(hdc,0,0,255));
269 | TextOut(hdc,8,4,L"Radiobox Test:",-1);
270 | EndPaint(hwnd,&ps);
271 | return TRUE;
272 | }
273 |
274 | 窗口重绘时,在客户区(8,4)处绘制蓝色的字符串:Radiobox Test:。
275 |
276 | 5. default消息
277 |
278 | .. code-block:: c
279 | :caption: 代码清单 8‑8 default消息响应(文件GUI_DEMO_Radiobox.c)
280 | :linenos:
281 | :name: 代码清单8_8
282 |
283 | default:
284 | return DefWindowProc(hwnd,msg,wParam,lParam);
285 |
286 | 调用DefWindowProc函数来处理用户不关心的消息。
287 |
288 | 最后,将GUI_DEMO_Radiobox加入到GUI_AppMain中,见 代码清单8_9_ GUI_AppMain函数(文件GUI_AppMain.。
289 |
290 | .. code-block:: c
291 | :caption: 代码清单 8‑9 GUI_AppMain函数(文件GUI_AppMain.c)
292 | :linenos:
293 | :name: 代码清单8_9
294 |
295 | void GUI_AppMain(void)
296 | {
297 | while(1)
298 | {
299 | GUI_DEMO_Button();
300 | GUI_DEMO_Checkbox();
301 | GUI_DEMO_Radiobox();
302 | }
303 | }
304 |
305 | .. _实验现象-3:
306 |
307 | 实验现象
308 | ^^^^^^^^^^^^
309 |
310 | 除了尺寸有些改变,在LCD显示的控件较大,其余的差不多是一模一样。见 图8_3_ 和 图8_4_ 。
311 |
312 | .. image:: /media/docx036.jpg
313 | :align: center
314 | :alt: 图 8_3 窗口客户区设计效果
315 | :name: 图8_3
316 |
317 | 图 8‑3 实验结果
318 |
319 | .. image:: /media/docx037.jpg
320 | :align: center
321 | :alt: 图 8‑4 实验结果(选中状态)
322 | :name: 图8_4
323 |
324 | 图 8‑4 实验结果(选中状态)
--------------------------------------------------------------------------------
/section_one/section9.rst:
--------------------------------------------------------------------------------
1 | .. vim: syntax=rst
2 |
3 | 文本框控件
4 | ---------------
5 |
6 | 文本框控件在我们生活中,并不少见。如 图9_1_,这是一个登录界面。我们输入账号和密码处,其实就是文本框控件。emXGUI也提供这样的功能,需要用户外加键盘作为输入设备。
7 |
8 | .. image:: /media/docx038.jpg
9 | :align: center
10 | :alt: 图 9‑1 常见的文本框控件
11 | :name: 图9_1
12 |
13 | 图 9_1 常见的文本框控件
14 |
15 | 创建文本框控件
16 | ~~~~~~~~~~~~~~~~~~~~~
17 |
18 | .. _标准消息类型及参数说明-4:
19 |
20 | 标准消息类型及参数说明
21 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
22 |
23 | 本章只是大致上讲解如何创建文本框控件,修稿控件的外观颜色,是禁止用户输入的。键盘输入,Emmmmm…
24 |
25 | 本章使用的消息类型,有WM_CREATE、WM_TIMER、WM_NOTIFY和WM_CTLCOLOR。WM_CREATE消息用于创建控件;这里使用WM_TIMER,主要是给大家演示一下, 如何在文本框显示变量。WM_NOTIFY消息用来处理
26 | EXIT按钮消息。使用WM_CTLCOLOR消息来改变控件的外观颜色。
27 |
28 | 创建文本框控件函数
29 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30 |
31 | .. code-block:: c
32 | :caption: 代码清单 9‑1 创建窗口函数(文件emXGUI.h)
33 | :linenos:
34 | :name: 代码清单9_1
35 |
36 | HWND CreateWindowEx( U32 dwExStyle, LPCVOID lpClass, LPCWSTR lpWindowName,
37 | U32 dwStyle, int x, int y, int nWidth, int nHeight,
38 | HWND hwndParent, UINT WinId,HINSTANCE hInstance,LPVOID lpParam);
39 |
40 | 1) lpClass:窗口类。对于系统标准控件,可以为:BUTTON(常规按钮,复选框,单选框,组合框),SCROLLBAR(水平/垂直滚动条), LISTBOX(列表框)。TEXTBOX(文本框)…等等。这里选择PROGRESSBAR。
41 |
42 | 2) dwStyle:文本框的风格。参数TBS_SUNK表示该控件具有凹下边框样式。文本框控件支持窗口风格参数。
43 |
44 | 至于其他的参数,也是同样的用法,这里不作描述。我们创建控件调用的CreateWindow函数,实际上就是CreateWindowEx函数。
45 |
46 | 创建文本框控件实验
47 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~
48 |
49 | .. _设计要求-4:
50 |
51 | 设计要求
52 | ^^^^^^^^^^^^^^^^
53 |
54 | 图9_2_ ,是本章节的设计要求。左边这一列文本框显示的文本内容格式不同。右边的文本框第一个是显示变量,变量值实时更新。后两个是多行显示。下面看看,如何用代码实现该界面。
55 |
56 | .. image:: /media/docx039.jpg
57 | :align: center
58 | :alt: 图 9‑2 设计要求
59 | :name: 图9_2
60 |
61 | 图 9-2 设计要求
62 |
63 | .. _代码分析-4:
64 |
65 | 代码分析
66 | ^^^^^^^^^^^^
67 |
68 | (1) 创建父窗口
69 |
70 | .. code-block:: c
71 | :caption: 代码清单 9_2 GUI_DEMO_Textbox函数(文件GUI_DEMO_Textbox.c)
72 | :linenos:
73 | :name: 代码清单9_2
74 |
75 | void GUI_DEMO_Textbox(void)
76 | {
77 | HWND hwnd;
78 | WNDCLASS wcex;
79 | MSG msg;
80 | //配置wcex参数
81 | wcex.Tag = WNDCLASS_TAG;
82 | wcex.Style = CS_HREDRAW | CS_VREDRAW;
83 | wcex.lpfnWndProc = win_proc;
84 | wcex.cbClsExtra = 0;
85 | wcex.cbWndExtra = 0;
86 | wcex.hInstance = NULL;//hInst;
87 | wcex.hIcon = NULL;//LoadIcon(hInstance,(LPCTSTR)IDI_WIN32_APP_TEST);
88 | wcex.hCursor = NULL;//LoadCursor(NULL, IDC_ARROW);
89 | //创建主窗口
90 | hwnd =CreateWindowEx( NULL,
91 | &wcex,
92 | L"GUI Demo - Textbox",
93 | WS_CAPTION| WS_DLGFRAME| WS_BORDER|WS_CLIPCHILDREN,
94 | 0,0,GUI_XSIZE,GUI_YSIZE,
95 | NULL,NULL,NULL,NULL);
96 | //显示主窗口
97 | ShowWindow(hwnd,SW_SHOW);
98 | //开始窗口消息循环(窗口关闭并销毁时,GetMessage将返回FALSE,退出本消息循环)
99 | while(GetMessage(&msg,hwnd))
100 | {
101 | TranslateMessage(&msg);
102 | DispatchMessage(&msg);
103 | }
104 | }
105 |
106 | 创建父窗口,标题栏为“GUI Demo - Textbox”,带有大小边框,设置win_proc作为窗口回调函数。
107 |
108 | (2) 窗口回调函数
109 |
110 | 1. WM_CREATE
111 |
112 | .. code-block:: c
113 | :caption: 代码清单 9‑3 WM_CREATE消息响应(文件GUI_DEMO_Textbox.c)
114 | :linenos:
115 | :name: 代码清单9_3
116 |
117 | case WM_CREATE:
118 | {
119 | GetClientRect(hwnd,&rc);
120 |
121 | CreateWindow(BUTTON,L"EXIT",WS_VISIBLE,rc.w-100,8,80,48,hwnd,ID_EXIT,NULL,NULL);
122 | rc.x =20;
123 | rc.y =30;
124 | rc.w =200;
125 | rc.h =80;
126 | //创建文本框控件,返回控件句柄wnd
127 | wnd=CreateWindow(TEXTBOX,L"Text1",WS_VISIBLE,
128 | rc.x,rc.y,rc.w,rc.h,hwnd,ID_TB1,NULL,NULL);
129 | //发送TBM_SET_TEXTFLAG,设置文本框的内容,lParam参数代表显示内容的格式
130 | SendMessage(wnd,TBM_SET_TEXTFLAG,0,DT_SINGLELINE| DT_LEFT| DT_VCENTER| DT_BKGND|DT_BORDER);
131 | //往下移动矩形位置(X轴不变,Y轴位置增加rc.h+10个像素)
132 | OffsetRect(&rc,0,rc.h+10);
133 | //创建文本框控件(可见,具有凹下边框样式),返回控件句柄wnd
134 | wnd=CreateWindow(TEXTBOX,L"Text2",TBS_SUNK|WS_VISIBLE,
135 | rc.x,rc.y,rc.w,rc.h,hwnd,ID_TB2,NULL,NULL);
136 | SendMessage(wnd,TBM_SET_TEXTFLAG,0,DT_SINGLELINE| DT_CENTER| DT_VCENTER|DT_BKGND);
137 |
138 | OffsetRect(&rc,0,rc.h+10);
139 | wnd=CreateWindow(TEXTBOX,L"Text3",WS_VISIBLE,
140 | rc.x,rc.y,rc.w,rc.h,hwnd,ID_TB3,NULL,NULL);
141 | SendMessage(wnd,TBM_SET_TEXTFLAG,0,DT_SINGLELINE| DT_RIGHT| DT_VCENTER| DT_BKGND|DT_BORDER);
142 |
143 | OffsetRect(&rc,0,rc.h+10);
144 | wnd=CreateWindow(TEXTBOX,L"Text4",WS_DISABLED|WS_VISIBLE,
145 | rc.x,rc.y,rc.w,rc.h,hwnd,ID_TB4,NULL,NULL);
146 | SendMessage(wnd,TBM_SET_TEXTFLAG,0,DT_SINGLELINE| DT_VCENTER| DT_BOTTOM| DT_BKGND|DT_BORDER);
147 |
148 | rc.x =250;
149 | rc.y =30;
150 | rc.w =200;
151 | rc.h =80;
152 | wnd=CreateWindow(TEXTBOX,L"Text5",WS_VISIBLE,
153 | rc.x,rc.y,rc.w,rc.h,hwnd,ID_TB5,NULL,NULL);
154 | SendMessage(wnd,TBM_SET_TEXTFLAG,0,DT_SINGLELINE| DT_CENTER| DT_VCENTER|DT_BKGND);
155 | OffsetRect(&rc,0,rc.h+10);
156 | rc.w =320;
157 | rc.h =140;
158 | //创建文本框控件Text6,返回控件句柄wnd
159 | wnd=CreateWindow(TEXTBOX,L"Text6\r\nMulti-Line\r\nVCENTER+CENTER",WS_VISIBLE,
160 | rc.x,rc.y,rc.w,rc.h,hwnd,ID_TB6,NULL,NULL);
161 | //发送TBM_SET_TEXTFLAG,设置文本框的内容,多行显示
162 | SendMessage(wnd,TBM_SET_TEXTFLAG,0,DT_VCENTER| DT_CENTER| DT_BKGND|DT_BORDER);
163 |
164 | OffsetRect(&rc,0,rc.h+10);
165 |
166 | wnd=CreateWindow(TEXTBOX,L"Text7\r\nMulti-Line\r\nBOTTOM+RIGHT",TBS_SUNK|WS_VISIBLE,
167 | rc.x,rc.y,rc.w,rc.h,hwnd,ID_TB7,NULL,NULL);
168 | SendMessage(wnd,TBM_SET_TEXTFLAG,0,DT_BOTTOM| DT_RIGHT| DT_BKGND|DT_BORDER);
169 |
170 | SetTimer(hwnd,ID_TMR1,200,TMR_START,NULL); //创建一个200ms定时器
171 | return TRUE;
172 | }
173 |
174 | WM_CREATE消息创建的控件,如 表格9_1_ 所示。
175 |
176 | 表格 9_1 控件的具体信息
177 |
178 | .. _表格9_1:
179 |
180 | ======== ====== ======== ============================================ ============================================================================================================
181 | 控件类型 名称 ID值 窗口风格 文本格式
182 | ======== ====== ======== ============================================ ============================================================================================================
183 | BUTTON EXIT ID_EXIT WS_VISIBLE 无
184 | TEXTBOX Text1 ID_TB1 WS_VISIBLE DT_SINGLELINE|DT_LEFT|DT_VCENTER|DT_BKGND|DT_BORDER
185 | \ Text2 ID_TB2 TBS_SUNK|WS_VISIBLE DT_SINGLELINE|DT_CENTER\|DT_VCENTER|DT_BKGND
186 | \ Text3 ID_TB3 WS_VISIBLE DT_SINGLELINE|DT_RIGHT|DT_VCENTER\|DT_BKGND|DT_BORDER
187 | \ Text4 ID_TB4 WS_DISABLED|WS_VISIBLE DT_SINGLELINE|DT_VCENTER|DT_BOTTOM\|DT_BKGND|DT_BORDER
188 | \ Text5 ID_TB5 WS_VISIBLE DT_SINGLELINE|DT_CENTER\|DT_VCENTER|DT_BKGND
189 | \ Text6 ID_TB6 WS_VISIBLE DT_VCENTER|DT_CENTER\|DT_BKGND|DT_BORDER
190 | \ Text7 ID_TB7 TBS_SUNK|WS_VISIBLE DT_BOTTOM|DT_RIGHT\|DT_BKGND|DT_BORDER
191 | ======== ====== ======== ============================================ ============================================================================================================
192 |
193 | 点击EXIT按钮,产生WM_CLOSE消息关闭主窗口。调用CreateWindow函数,创建7个文本框,文本框的文本格式,见 表格9_2_。
194 |
195 | .. _表格9_2:
196 |
197 | 表格 9_2 文本框的文本格式说明
198 |
199 | ============= ==================================
200 | 属性值 文本格式
201 | ============= ==================================
202 | DT_SINGLELINE 单行模式。没有该参数时,为多行模式
203 | DT_CENTER 水平居中对齐
204 | DT_LEFT 水平居左对齐
205 | DT_RIGHT 水平居右对齐
206 | DT_BOTTOM 垂直底部对齐
207 | DT_VCENTER 垂直中间对齐
208 | DT_BORDER 是否绘制边框
209 | DT_BKGND 是否绘制背景
210 | ============= ==================================
211 |
212 | 2. WM_NOTIFY
213 |
214 |
215 | .. code-block:: c
216 | :caption: 代码清单 9‑4 WM_NOTIFY消息响应(文件GUI_DEMO_Textbox.c)
217 | :linenos:
218 | :name: 代码清单9_4
219 |
220 | case WM_NOTIFY:
221 | {
222 | u16 id, code;
223 | id =LOWORD(wParam);
224 | code = HIWORD(wParam);
225 | //EXIT按钮弹起
226 | if(id == ID_EXIT && code == BN_CLICKED)
227 | {
228 | count = 0;
229 | PostCloseMessage(hwnd);//产生WM_CLOSE消息关闭主窗口
230 | }
231 | }
232 |
233 | ID_EXIT单击时,会调用PostCloseMessage发送窗口关闭消息WM_CLOSE,来关闭主窗口。
234 |
235 | 3. WM_TIMER
236 |
237 | .. code-block:: c
238 | :caption: 代码清单 9‑5 WM_TIMER消息响应(文件GUI_DEMO_Textbox.c)
239 | :linenos:
240 | :name: 代码清单9_5
241 |
242 | case WM_TIMER:
243 | {
244 | u16 id;
245 | //读取控件ID值
246 | id =LOWORD(wParam);
247 |
248 | if(id==ID_TMR1)
249 | {
250 | count++;
251 |
252 | x_wsprintf(wbuf,L"%04d",count);
253 | //获取控件句柄
254 | wnd =GetDlgItem(hwnd,ID_TB5);
255 | //设置控件显示文本框
256 | SetWindowText(wnd,wbuf);
257 | }
258 | }
259 | return TRUE;
260 |
261 | WM_CREATE消息中,创建了ID为ID_TMR1的定时器。定时器到达设定值时,发送WM_TIMER消息。在WM_TIMER消息中,实现count变量自加,同时调用SetWindowText函数将变量值在文本框Text5显示。
262 |
263 | 4. WM_CTLCOLOR
264 |
265 | .. code-block:: c
266 | :caption: 代码清单 9‑6 WM_CTLCOLOR消息响应(文件GUI_DEMO_Textbox.c)
267 | :linenos:
268 | :name: 代码清单9_6
269 |
270 | case WM_CTLCOLOR:
271 | {
272 | /* 控件在绘制前,会发送 WM_CTLCOLOR到父窗口.
273 | * wParam参数指明了发送该消息的控件ID;lParam参数指向一个CTLCOLOR的结构体指针.
274 | * 用户可以通过这个结构体改变控件的颜色值.
275 | 用户修改颜色参数后,需返回TRUE,否则,系统
276 | * 将忽略本次操作,继续使用默认的颜色进行绘制.
277 | *
278 | */
279 | u16 id;
280 | id =LOWORD(wParam);
281 | if(id== ID_TB5 || id== ID_TB6)
282 | {
283 | CTLCOLOR *cr;
284 | cr =(CTLCOLOR*)lParam;
285 | cr->TextColor =RGB888(255,180,180);//文字颜色(RGB888颜色格式)
286 | cr->BackColor =RGB888(100,0,0);//背景颜色(RGB888颜色格式)
287 | cr->BorderColor =RGB888(255,10,10);//边框颜色(RGB888颜色格式)
288 | return TRUE;
289 | }
290 | else
291 | {
292 | return FALSE;
293 | }
294 | }
295 |
296 | 改变控件窗口的文字颜色(TextColor),边框颜色(BorderColor), 背景颜色(BackColor),一定要返回TRUE,否则的话,则按照默认方案来配置。
297 |
298 | 最后,将GUI_DEMO_Textbox加入到GUI_AppMain中,见 代码清单9_7_。
299 |
300 | .. code-block:: c
301 | :caption: 代码清单9_7_ GUI_AppMain函数(文件GUI_AppMain.c)
302 | :linenos:
303 | :name: 代码清单9_7
304 |
305 | void GUI_AppMain(void)
306 | {
307 | while(1)
308 | {
309 | GUI_DEMO_Button();
310 | GUI_DEMO_Checkbox();
311 | GUI_DEMO_Radiobox();
312 | GUI_DEMO_Textbox();
313 | }
314 | }
315 |
316 | .. _实验现象-4:
317 |
318 | 实验现象
319 | ^^^^^^^^^^^^
320 |
321 | 如 图9_3_ 除了控件的尺寸有些变化,布局和 图9_2_ 差不多是一模一样的。
322 |
323 | .. image:: /media/docx040.jpg
324 | :align: center
325 | :alt: 图 9_3 实验结果
326 | :name: 图9_3
327 |
328 | 图 9‑3 实验结果
329 |
--------------------------------------------------------------------------------
/section_two/section2_1.rst:
--------------------------------------------------------------------------------
1 | .. vim: syntax=rst
2 |
3 | 第二部分 emXGUI综合例程实战
4 | ==================================
5 |
6 | 音乐播放器
7 | ---------------
8 |
9 | 视频播放器
10 | ---------------
11 |
12 | 万年历
13 | -------------
14 |
15 | NES游戏
16 | ---------------
17 |
18 | 二维码识别
19 | ---------------
20 |
21 | 摄像头图像显示
22 | -----------------
23 |
24 | 图片浏览器
25 | ---------------
26 |
27 | 矢量字体测试
28 | ------------------
29 |
30 | 控件的滑动与旋转
31 | ------------------------
32 |
33 | 联系野火
34 | ========
35 |
36 | **东莞野火电子技术有限公司**
37 |
38 | 官网:`www.embedfire.com `_
39 |
40 | 论坛:`www.firebbs.cn `_
41 |
42 | 淘宝:`fire-stm32.taobao.com `_
43 |
44 | 邮箱: firege@embedfire.com
45 |
46 | 电话:0769-33894118
47 |
48 | |image0|
49 |
50 | 关注野火公众号,可下载野火全部产品的资料(书籍、视频、程序)
51 |
52 | |image1|
53 |
54 | 野火STM32系列图书,关注公众号即可下载电子版
55 |
56 | .. |image0| image:: /media/docx164.jpg
57 | :width: 1.38611in
58 | :height: 1.38611in
59 | .. |image1| image:: /media/docx165.png
60 | :width: 5.76806in
61 | :height: 2.01597in
--------------------------------------------------------------------------------
/目录结构及文件说明.txt:
--------------------------------------------------------------------------------
1 | 本文件用于对本目录下的相关文件和自动构建过程进行说明,
2 | 建议在进行文档编写之前先进行阅读,注意格式等相关问题
3 |
4 | 文件说明:
5 |
6 |
7 | .
8 | │ .gitignore
9 | │ .gitlab-ci.yml gitlab自动构建配置文件,根据不同的工程需要按需修改
10 | │ .tgitconfig
11 | │ about_us.rst
12 | │ conf.py sphinx配置文件,对html和pdf的编译选项做配置
13 | │ index.rst 文件索引,调整章节顺序
14 | │ latexbuild.py 用于生成的latex文件的内容的自动修改,如果发现生成的pdf索引和章节标题序号有误,或者设置部分章节不生成序号可以在此文件修改
15 | │ latexbuild2.py 用于自动修改生成pdf的名称,如果自动生成的pdf名称有误,在这里修改
16 | │ LICENSE.rst
17 | │ make.bat
18 | │ Makefile
19 | │ README.rst git页面说明文件,需要修改文档的git地址和在线文档名称及地址
20 | │ requirements.txt python依赖包设置
21 | │
22 | ├─latexfile 构建PDF所需的latex风格配置文件
23 | │ logo.eps
24 | │ sphinx.sty
25 | │ sphinxmanual.cls
26 | │
27 | ├─Module_Manual 正文
28 | │ │ users_manual.rst
29 | │ │
30 | │ └─media 正文媒体文件
31 | │ AD7192.jpg
32 | │
33 | ├─_build 构建生成的文件
34 | │
35 | ├─_static 生成HTML所需的静态文件
36 | │ ├─css
37 | │ │ custom.css
38 | │ │
39 | │ └─images html中用到的图片资源
40 | │ ad7192.png 产品图片
41 | │ embedfire.png
42 | │ firebbs.png
43 | │ gitee.png
44 | │ github.png
45 | │ logo-1.png
46 | │ logo.ico 浏览器顶部图片,16x16像素ico图片
47 | │
48 | └─_templates html各区块的自定义文件,如果要修改生成html以下3栏的内容,在对应文件中修改
49 | footer.html 底部栏:© Copyright commit用release替代了,在conf.py中读取,如果目录层级变化,可能会读不到commit id,需要在conf.py中排名个修改路径
50 | head.html 顶部栏:矩形产品介绍,产品相关情况在这里设定
51 | layout.html 侧边栏:四个图片链接
52 |
53 |
54 |
55 |
56 | 对于文档书写格式的说明:
57 | 1.确保使用格式化符号的正确性
58 | 2.确保文档编译为网页过程零错误,尽量少的警告
59 |
60 | 对于生成pdf文件的说明:
61 | 0.自动构建过程要求较严格,只要有一个错误都无法成功
62 | 1.文档编写过程中不使用动图或视频
63 | 2.在正式上传服务器进行自动自动编译之前,先在本地编译无错误后再进行
64 | 3.在进行文档编写过程中,将.gitlab-ci.yml文件中的'tags'字段标记为rst,
65 | 在文档编写完成,要进行pdf自动编译的前一次推送再将'tags'字段标记为pdf
66 | 4.编译过程中可能存在错误,在gitlab对应仓库的流水线选项中寻找自动构建
67 | 失败的位置,并分析log信息解决错误。
68 |
69 |
--------------------------------------------------------------------------------