From 1c440e5394cc6c4a4251b1c55f398c12b3c16543 Mon Sep 17 00:00:00 2001 From: Yolanda_Leo <1959563205@qq.com> Date: Sat, 22 Oct 2022 09:43:11 +0000 Subject: [PATCH 1/5] =?UTF-8?q?2020302111184=E9=AA=86=E9=9B=A8=E5=A9=95?= =?UTF-8?q?=E7=AC=AC=E4=B8=83=E5=91=A8=E4=BD=9C=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Yolanda_Leo <1959563205@qq.com> --- ...4-\351\252\206\351\233\250\345\251\225.md" | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 "\347\254\254\344\270\203\345\221\250\344\275\234\344\270\232-2020302111184-\351\252\206\351\233\250\345\251\225.md" diff --git "a/\347\254\254\344\270\203\345\221\250\344\275\234\344\270\232-2020302111184-\351\252\206\351\233\250\345\251\225.md" "b/\347\254\254\344\270\203\345\221\250\344\275\234\344\270\232-2020302111184-\351\252\206\351\233\250\345\251\225.md" new file mode 100644 index 0000000..707a628 --- /dev/null +++ "b/\347\254\254\344\270\203\345\221\250\344\275\234\344\270\232-2020302111184-\351\252\206\351\233\250\345\251\225.md" @@ -0,0 +1,99 @@ +# 一、查找并阅读MVVM有关思想 + +## (1) 什么是MVVM + +MVVM是Model-View-ViewModel的简写。它本质上就是MVC的改进版。MVVM +就是将其中的View 的状态和行为抽象化,让我们将视图 UI +和业务逻辑分开。当然这些事 ViewModel 已经帮我们做了,它可以取出 Model +的数据同时帮忙处理 View +中由于需要展示内容而涉及的业务逻辑。微软的WPF带来了新的技术体验,如Silverlight、音频、视频、3D、动画......,这导致了软件UI层更加细节化、可定制化。同时,在技术层面,WPF也带来了 +诸如Binding、Dependency Property、Routed +Events、Command、DataTemplate、ControlTemplate等新特性。MVVM(Model-View-ViewModel)框架的由来便是MVP(Model-View-Presenter)模式与WPF结合的应用方式时发展演变过来的一种新型架构框架。它立足于原有MVP框架并且把WPF的新特性糅合进去,以应对客户日益复杂的需求变化。MVVM核心思想,是关注model的变化,让MVVM框架利用自己的机制自动更新DOM,也就是所谓的数据-视图分离,数据不会影响视图。 + +在MVVM架构中,是不允许数据和视图直接通信的,只能通过ViewModel来通信,而ViewModel就是定义了一个Observer观察者。ViewModel是连接View和Model的中间件。 +MVVM源自于经典的MVC(Model-View-Controller)模式。MVVM的核心是ViewModel层,负责转换Model中的数据对象来让数据变得更容易管理和使用,其作用如下: +该层向上与视图层进行双向数据绑定。 +向下与Model层通过接口请求进行数据交互。 +MVVM已经相当成熟了,主要运用但不仅仅在网络应用程序开发中。当下流向的MVVM框架有Vue.js、AugularJS等。 + +## (2) MVVM优点和缺点 + +优点: + +1. 低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的\"View\"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。 + +2. 可重用性。你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。 + +3. Controller简洁清晰。ViewModel分离出来大部分的Controller代码,更加清晰和容易维护。 + +4. 独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression + Blend可以很容易设计界面并生成xaml代码。 + +5. 方便测试。大部分Bug来自于逻辑处理,由于ViewModel把逻辑分离出来,可对ViewModel构造单元测试。 + 缺点: + +6. Bug 很难被调试 : + 因为使⽤双向绑定的模式,当你看到界⾯异常了,有可能是你 View 的代码有 + Bug ,也可能是 Model 的代码有问题。数据绑定使得⼀个位置的Bug + 被快速传递到别的位置,要定位原始出问题的地⽅就变得不那么容易 + 了。另外,数据绑定的声明是指令式地写在View + 的模版当中的,这些内容是没办法去打断点 debug 的。 + +7. ⼀个⼤的模块中 model + 也会很⼤,虽然使⽤⽅便了也很容易保证了数据的⼀致性,当时⻓期持有,不释放内存就造 + 成了花费更多的内存。 + +8. 对于⼤型的图形应⽤程序,视图状态较多, ViewModel + 的构建和维护的成本都会⽐较⾼。 + +## (3) MVVM的组成部分 + +模型 +模型是指代表真实状态内容的领域模型(面向对象),或指代表内容的数据访问层(以数据为中心)。 + +视图 +就像在MVC和MVP模式中一样,视图是用户在屏幕上看到的结构、布局和外观(UI)。 + +视图模型 +视图模型是暴露公共属性和命令的视图的抽象。MVVM没有MVC模式的控制器,也没有MVP模式的presenter,有的是一个绑定器。在视图模型中,绑定器在视图和数据绑定器之间进行通信。 + +绑定器 +声明性数据和命令绑定隐含在MVVM模式中。在Microsoft解决方案堆中,绑定器是一种名为XAML的标记语言。绑定器使开发人员免于被迫编写样板式逻辑来同步视图模型和视图。在微软的堆之外实现时,声明性数据绑定技术的出现是实现该模式的一个关键因素。 + +## (4) MVVM的理论基础 + +MVVM旨在利用WPF中的数据绑定函数,通过从视图层中几乎删除所有GUI代码(代码隐藏),更好地促进视图层开发与模式其余部分的分离。不需要用户体验(UX)开发人员编写GUI代码,他们可以使用框架标记语言(如XAML),并创建到应用程序开发人员编写和维护的视图模型的数据绑定。角色的分离使得交互设计师可以专注于用户体验需求,而不是对业务逻辑进行编程。这样,应用程序的层次可以在多个工作流中进行开发以提高生产力。即使一个开发人员在整个代码库上工作,视图与模型的适当分离也会更加高效,因为基于最终用户反馈,用户界面通常在开发周期中经常发生变化,而且处于开发周期后期。 +MVVM模式试图获得MVC提供的功能性开发分离的两个优点,同时利用数据绑定的优势和通过绑定数据的框架尽可能接近纯应用程序模型。它使用绑定器、视图模型和任何业务层的数据检查功能来验证传入的数据。结果是模型和框架驱动尽可能多的操作,消除或最小化直接操纵视图的应用程序逻辑(如代码隐藏)。 + +# 二、熟悉WPF窗体 + +WPF是 Windows Presentation Foundation +的英文缩写,意为"窗体呈现基础",是微软基于.NET Framework 3.0 +推出的新一代构建窗体程序的框架。不同于WinForm,WPF实现了界面和开发分离,它的界面是由Xaml语言构建的,这种形式对前端开发人员非常友好,使初步进入WPF页面开发的前端开发人员可以很轻松的上手并开发出绚丽的界面(并且还有一个UI编辑利器:VS +Blend来辅助界面的开发)。另外,WPF还具有强大的图形绘制功能,以及自带MVVM框架。 + +通过创建一个小项目来熟悉WPF窗体的控件的应用: + +在 Visual Studio 2022 Community 中创建一个 WPF +窗体应用程序,添加基本控件 button, label, textbox, +listbox,完成一个熟悉控件应用的小型WPF项目,项目内容是会显示用户选择的对应的晚餐。 + +![](media/image1.png){width="5.769444444444445in" +height="1.4361111111111111in"} + +![](media/image2.png){width="5.7652777777777775in" +height="3.252083333333333in"} + +# 三、实验准备 + +1. 安装Windows11 Professional Edition,校园网有正版下载。 + +2. 安装Office 中的 Word 和 Excel,安装专业增强版2021 + +3. 另必须安装 Visual Studio 2022 Community, 并且安装 + git,根据PPT内容安装VS相关扩展。 + +4. -申请好 gitee 和github 账号,同时Visual Studio + 也注册账号。在github及gitee上各建立一个空仓库。 + +5. 学会建立 SSH 连接及推送到远程仓库的方法。 -- Gitee From 19959cb99c88702476604ab0296fd0d9140cb445 Mon Sep 17 00:00:00 2001 From: Yolanda_Leo <1959563205@qq.com> Date: Mon, 14 Nov 2022 04:42:00 +0000 Subject: [PATCH 2/5] =?UTF-8?q?=E7=AC=AC=E5=85=AB=E5=91=A8=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Yolanda_Leo <1959563205@qq.com> --- ...1\233\250\345\251\225(lab_2_7&lab_2_8).md" | 190 ++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 "\347\254\254\344\270\203\345\221\250\344\275\234\344\270\232-2020302111184-\351\252\206\351\233\250\345\251\225(lab_2_7&lab_2_8).md" diff --git "a/\347\254\254\344\270\203\345\221\250\344\275\234\344\270\232-2020302111184-\351\252\206\351\233\250\345\251\225(lab_2_7&lab_2_8).md" "b/\347\254\254\344\270\203\345\221\250\344\275\234\344\270\232-2020302111184-\351\252\206\351\233\250\345\251\225(lab_2_7&lab_2_8).md" new file mode 100644 index 0000000..9caeb24 --- /dev/null +++ "b/\347\254\254\344\270\203\345\221\250\344\275\234\344\270\232-2020302111184-\351\252\206\351\233\250\345\251\225(lab_2_7&lab_2_8).md" @@ -0,0 +1,190 @@ +# 注册表结构和注册表值类型 + + + + + +*** + +## 1 结构 + +包含关于一个注册表值的信息。列表中的RegQueryMultipleValues函数使用此结构。 + +```cpp +typedef struct value_entW { + LPWSTR ve_valuename; + DWORD ve_valuelen; + DWORD_PTR ve_valueptr; + DWORD ve_type; +} VALENTW, *PVALENTW; +``` + +**ve_valuename** +要检索的值的名称。请确保在调用RegQueryMultipleValues之前设置此成员然后再调用RegQueryMultipleValues。 + +**ve_valuelen** +ve_valueptr所指向的数据的大小,以字节为单位。 + +**ve_valueptr** +一个指向值输入数据的指针。这是一个指针,指向在lpValueBuf缓冲区中返回的值的数据的指针,由RegQueryMultipleValues填写的缓冲区中的值的指针。 + +**ve_type** +ve_valueptr所指向的数据类型。关于可能的类型列表可能的类型,请看注册表值类型。 + + +## 2 值的类型 + +下面的例子是走一个REG_MULTI_SZ字符串。 +```cpp +#include +#include +#include + +void SampleSzz(PTSTR pszz) +{ + _tprintf(_TEXT("\tBegin multi-sz string\n")); + while (*pszz) + { + _tprintf(_TEXT("\t\t%s\n"), pszz); + pszz = pszz + _tcslen(pszz) + 1; + } + _tprintf(_TEXT("\tEnd multi-sz\n")); +} + +int __cdecl main(int argc, char **argv) +{ + // Because the compiler adds a \0 at the end of quoted strings, + // there are two \0 terminators at the end. + + _tprintf(_TEXT("Conventional multi-sz string:\n")); + SampleSzz(_TEXT("String1\0String2\0String3\0LastString\0")); + + _tprintf(_TEXT("\nTest case with no strings:\n")); + SampleSzz(_TEXT("")); + + return 0; +} +``` + + +# 枚举注册表子键 + + + + +*** + +这个经验样本使用RegQueryInfoKey、RegEnumKeyEx,和RegEnumValue函数来列举指定键的子键。传递给每个函数的hKey参数是一个打开的钥匙的句柄。这个键必须在函数调用前被打开调用之前打开之后关闭。 + +```cpp +// QueryKey - 枚举键的子键及其相关值。 +// hKey - 要列举其子键和值的键。 + +#include +#include +#include + +#define MAX_KEY_LENGTH 255 +#define MAX_VALUE_NAME 16383 + +void QueryKey(HKEY hKey) +{ + TCHAR achKey[MAX_KEY_LENGTH]; // 子键名称的缓冲区 + DWORD cbName; // 名称字符串的大小 + TCHAR achClass[MAX_PATH] = TEXT(""); // 类名的缓冲区 + DWORD cchClassName = MAX_PATH; // 类字符串的大小 + DWORD cSubKeys=0; // 子密钥的数量 + DWORD cbMaxSubKey; // 最大的子键尺寸 + DWORD cchMaxClass; // 最长级别的字符串 + DWORD cValues; // 键值的数量 + DWORD cchMaxValue; // 最长的值名称 + DWORD cbMaxValueData; // 最长值数据 + DWORD cbSecurityDescriptor; // 安全描述符的大小 + FILETIME ftLastWriteTime; // 最后写入时间 + + DWORD i, retCode; + + TCHAR achValue[MAX_VALUE_NAME]; + DWORD cchValue = MAX_VALUE_NAME; + + // 获取类的名称和值的数量。 + retCode = RegQueryInfoKey( + hKey, // 钥匙柄 + achClass, // 类名的缓冲区 + &cchClassName, // 类字符串的大小 + NULL, // 保留 + &cSubKeys, // 子密钥的数量 + &cbMaxSubKey, // 最长的子键尺寸 + &cchMaxClass, // 最长级别的字符串 + &cValues, // 这个键的值的数量 + &cchMaxValue, // 最长的值名称 + &cbMaxValueData, // 最长值数据 + &cbSecurityDescriptor, //安全描述符 + &ftLastWriteTime); // 最后写作时间 + + //枚举子键,直到RegEnumKeyEx失败。 + + if (cSubKeys) + { + printf( "\nNumber of subkeys: %d\n", cSubKeys); + + for (i=0; i Date: Mon, 14 Nov 2022 04:42:28 +0000 Subject: [PATCH 3/5] =?UTF-8?q?=E9=87=8D=E5=91=BD=E5=90=8D=20=E7=AC=AC?= =?UTF-8?q?=E4=B8=83=E5=91=A8=E4=BD=9C=E4=B8=9A-2020302111184-=E9=AA=86?= =?UTF-8?q?=E9=9B=A8=E5=A9=95(lab=5F2=5F7&lab=5F2=5F8).md=20=E4=B8=BA=20?= =?UTF-8?q?=E7=AC=AC=E5=85=AB=E5=91=A8=E4=BD=9C=E4=B8=9A-2020302111184-?= =?UTF-8?q?=E9=AA=86=E9=9B=A8=E5=A9=95(lab=5F2=5F7&lab=5F2=5F8).md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...1184-\351\252\206\351\233\250\345\251\225(lab_2_7&lab_2_8).md" | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename "\347\254\254\344\270\203\345\221\250\344\275\234\344\270\232-2020302111184-\351\252\206\351\233\250\345\251\225(lab_2_7&lab_2_8).md" => "\347\254\254\345\205\253\345\221\250\344\275\234\344\270\232-2020302111184-\351\252\206\351\233\250\345\251\225(lab_2_7&lab_2_8).md" (100%) diff --git "a/\347\254\254\344\270\203\345\221\250\344\275\234\344\270\232-2020302111184-\351\252\206\351\233\250\345\251\225(lab_2_7&lab_2_8).md" "b/\347\254\254\345\205\253\345\221\250\344\275\234\344\270\232-2020302111184-\351\252\206\351\233\250\345\251\225(lab_2_7&lab_2_8).md" similarity index 100% rename from "\347\254\254\344\270\203\345\221\250\344\275\234\344\270\232-2020302111184-\351\252\206\351\233\250\345\251\225(lab_2_7&lab_2_8).md" rename to "\347\254\254\345\205\253\345\221\250\344\275\234\344\270\232-2020302111184-\351\252\206\351\233\250\345\251\225(lab_2_7&lab_2_8).md" -- Gitee From ae31b7238b7c676a7887f43d33e54fd3b91e086f Mon Sep 17 00:00:00 2001 From: Yolanda_Leo <1959563205@qq.com> Date: Mon, 14 Nov 2022 04:42:44 +0000 Subject: [PATCH 4/5] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?=E7=AC=AC=E5=85=AB=E5=91=A8=E4=BD=9C=E4=B8=9A-2020302111184-?= =?UTF-8?q?=E9=AA=86=E9=9B=A8=E5=A9=95(lab=5F2=5F7&lab=5F2=5F8).md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...1\233\250\345\251\225(lab_2_7&lab_2_8).md" | 190 ------------------ 1 file changed, 190 deletions(-) delete mode 100644 "\347\254\254\345\205\253\345\221\250\344\275\234\344\270\232-2020302111184-\351\252\206\351\233\250\345\251\225(lab_2_7&lab_2_8).md" diff --git "a/\347\254\254\345\205\253\345\221\250\344\275\234\344\270\232-2020302111184-\351\252\206\351\233\250\345\251\225(lab_2_7&lab_2_8).md" "b/\347\254\254\345\205\253\345\221\250\344\275\234\344\270\232-2020302111184-\351\252\206\351\233\250\345\251\225(lab_2_7&lab_2_8).md" deleted file mode 100644 index 9caeb24..0000000 --- "a/\347\254\254\345\205\253\345\221\250\344\275\234\344\270\232-2020302111184-\351\252\206\351\233\250\345\251\225(lab_2_7&lab_2_8).md" +++ /dev/null @@ -1,190 +0,0 @@ -# 注册表结构和注册表值类型 - - - - - -*** - -## 1 结构 - -包含关于一个注册表值的信息。列表中的RegQueryMultipleValues函数使用此结构。 - -```cpp -typedef struct value_entW { - LPWSTR ve_valuename; - DWORD ve_valuelen; - DWORD_PTR ve_valueptr; - DWORD ve_type; -} VALENTW, *PVALENTW; -``` - -**ve_valuename** -要检索的值的名称。请确保在调用RegQueryMultipleValues之前设置此成员然后再调用RegQueryMultipleValues。 - -**ve_valuelen** -ve_valueptr所指向的数据的大小,以字节为单位。 - -**ve_valueptr** -一个指向值输入数据的指针。这是一个指针,指向在lpValueBuf缓冲区中返回的值的数据的指针,由RegQueryMultipleValues填写的缓冲区中的值的指针。 - -**ve_type** -ve_valueptr所指向的数据类型。关于可能的类型列表可能的类型,请看注册表值类型。 - - -## 2 值的类型 - -下面的例子是走一个REG_MULTI_SZ字符串。 -```cpp -#include -#include -#include - -void SampleSzz(PTSTR pszz) -{ - _tprintf(_TEXT("\tBegin multi-sz string\n")); - while (*pszz) - { - _tprintf(_TEXT("\t\t%s\n"), pszz); - pszz = pszz + _tcslen(pszz) + 1; - } - _tprintf(_TEXT("\tEnd multi-sz\n")); -} - -int __cdecl main(int argc, char **argv) -{ - // Because the compiler adds a \0 at the end of quoted strings, - // there are two \0 terminators at the end. - - _tprintf(_TEXT("Conventional multi-sz string:\n")); - SampleSzz(_TEXT("String1\0String2\0String3\0LastString\0")); - - _tprintf(_TEXT("\nTest case with no strings:\n")); - SampleSzz(_TEXT("")); - - return 0; -} -``` - - -# 枚举注册表子键 - - - - -*** - -这个经验样本使用RegQueryInfoKey、RegEnumKeyEx,和RegEnumValue函数来列举指定键的子键。传递给每个函数的hKey参数是一个打开的钥匙的句柄。这个键必须在函数调用前被打开调用之前打开之后关闭。 - -```cpp -// QueryKey - 枚举键的子键及其相关值。 -// hKey - 要列举其子键和值的键。 - -#include -#include -#include - -#define MAX_KEY_LENGTH 255 -#define MAX_VALUE_NAME 16383 - -void QueryKey(HKEY hKey) -{ - TCHAR achKey[MAX_KEY_LENGTH]; // 子键名称的缓冲区 - DWORD cbName; // 名称字符串的大小 - TCHAR achClass[MAX_PATH] = TEXT(""); // 类名的缓冲区 - DWORD cchClassName = MAX_PATH; // 类字符串的大小 - DWORD cSubKeys=0; // 子密钥的数量 - DWORD cbMaxSubKey; // 最大的子键尺寸 - DWORD cchMaxClass; // 最长级别的字符串 - DWORD cValues; // 键值的数量 - DWORD cchMaxValue; // 最长的值名称 - DWORD cbMaxValueData; // 最长值数据 - DWORD cbSecurityDescriptor; // 安全描述符的大小 - FILETIME ftLastWriteTime; // 最后写入时间 - - DWORD i, retCode; - - TCHAR achValue[MAX_VALUE_NAME]; - DWORD cchValue = MAX_VALUE_NAME; - - // 获取类的名称和值的数量。 - retCode = RegQueryInfoKey( - hKey, // 钥匙柄 - achClass, // 类名的缓冲区 - &cchClassName, // 类字符串的大小 - NULL, // 保留 - &cSubKeys, // 子密钥的数量 - &cbMaxSubKey, // 最长的子键尺寸 - &cchMaxClass, // 最长级别的字符串 - &cValues, // 这个键的值的数量 - &cchMaxValue, // 最长的值名称 - &cbMaxValueData, // 最长值数据 - &cbSecurityDescriptor, //安全描述符 - &ftLastWriteTime); // 最后写作时间 - - //枚举子键,直到RegEnumKeyEx失败。 - - if (cSubKeys) - { - printf( "\nNumber of subkeys: %d\n", cSubKeys); - - for (i=0; i Date: Mon, 14 Nov 2022 04:43:21 +0000 Subject: [PATCH 5/5] =?UTF-8?q?=E7=AC=AC=E5=85=AB=E5=91=A8=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Yolanda_Leo <1959563205@qq.com> --- ...1\233\250\345\251\225(lab_2_7&lab_2_8).md" | 190 ++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 "\347\254\254\345\205\253\345\221\250\344\275\234\344\270\232-2020302111184-\351\252\206\351\233\250\345\251\225(lab_2_7&lab_2_8).md" diff --git "a/\347\254\254\345\205\253\345\221\250\344\275\234\344\270\232-2020302111184-\351\252\206\351\233\250\345\251\225(lab_2_7&lab_2_8).md" "b/\347\254\254\345\205\253\345\221\250\344\275\234\344\270\232-2020302111184-\351\252\206\351\233\250\345\251\225(lab_2_7&lab_2_8).md" new file mode 100644 index 0000000..9caeb24 --- /dev/null +++ "b/\347\254\254\345\205\253\345\221\250\344\275\234\344\270\232-2020302111184-\351\252\206\351\233\250\345\251\225(lab_2_7&lab_2_8).md" @@ -0,0 +1,190 @@ +# 注册表结构和注册表值类型 + + + + + +*** + +## 1 结构 + +包含关于一个注册表值的信息。列表中的RegQueryMultipleValues函数使用此结构。 + +```cpp +typedef struct value_entW { + LPWSTR ve_valuename; + DWORD ve_valuelen; + DWORD_PTR ve_valueptr; + DWORD ve_type; +} VALENTW, *PVALENTW; +``` + +**ve_valuename** +要检索的值的名称。请确保在调用RegQueryMultipleValues之前设置此成员然后再调用RegQueryMultipleValues。 + +**ve_valuelen** +ve_valueptr所指向的数据的大小,以字节为单位。 + +**ve_valueptr** +一个指向值输入数据的指针。这是一个指针,指向在lpValueBuf缓冲区中返回的值的数据的指针,由RegQueryMultipleValues填写的缓冲区中的值的指针。 + +**ve_type** +ve_valueptr所指向的数据类型。关于可能的类型列表可能的类型,请看注册表值类型。 + + +## 2 值的类型 + +下面的例子是走一个REG_MULTI_SZ字符串。 +```cpp +#include +#include +#include + +void SampleSzz(PTSTR pszz) +{ + _tprintf(_TEXT("\tBegin multi-sz string\n")); + while (*pszz) + { + _tprintf(_TEXT("\t\t%s\n"), pszz); + pszz = pszz + _tcslen(pszz) + 1; + } + _tprintf(_TEXT("\tEnd multi-sz\n")); +} + +int __cdecl main(int argc, char **argv) +{ + // Because the compiler adds a \0 at the end of quoted strings, + // there are two \0 terminators at the end. + + _tprintf(_TEXT("Conventional multi-sz string:\n")); + SampleSzz(_TEXT("String1\0String2\0String3\0LastString\0")); + + _tprintf(_TEXT("\nTest case with no strings:\n")); + SampleSzz(_TEXT("")); + + return 0; +} +``` + + +# 枚举注册表子键 + + + + +*** + +这个经验样本使用RegQueryInfoKey、RegEnumKeyEx,和RegEnumValue函数来列举指定键的子键。传递给每个函数的hKey参数是一个打开的钥匙的句柄。这个键必须在函数调用前被打开调用之前打开之后关闭。 + +```cpp +// QueryKey - 枚举键的子键及其相关值。 +// hKey - 要列举其子键和值的键。 + +#include +#include +#include + +#define MAX_KEY_LENGTH 255 +#define MAX_VALUE_NAME 16383 + +void QueryKey(HKEY hKey) +{ + TCHAR achKey[MAX_KEY_LENGTH]; // 子键名称的缓冲区 + DWORD cbName; // 名称字符串的大小 + TCHAR achClass[MAX_PATH] = TEXT(""); // 类名的缓冲区 + DWORD cchClassName = MAX_PATH; // 类字符串的大小 + DWORD cSubKeys=0; // 子密钥的数量 + DWORD cbMaxSubKey; // 最大的子键尺寸 + DWORD cchMaxClass; // 最长级别的字符串 + DWORD cValues; // 键值的数量 + DWORD cchMaxValue; // 最长的值名称 + DWORD cbMaxValueData; // 最长值数据 + DWORD cbSecurityDescriptor; // 安全描述符的大小 + FILETIME ftLastWriteTime; // 最后写入时间 + + DWORD i, retCode; + + TCHAR achValue[MAX_VALUE_NAME]; + DWORD cchValue = MAX_VALUE_NAME; + + // 获取类的名称和值的数量。 + retCode = RegQueryInfoKey( + hKey, // 钥匙柄 + achClass, // 类名的缓冲区 + &cchClassName, // 类字符串的大小 + NULL, // 保留 + &cSubKeys, // 子密钥的数量 + &cbMaxSubKey, // 最长的子键尺寸 + &cchMaxClass, // 最长级别的字符串 + &cValues, // 这个键的值的数量 + &cchMaxValue, // 最长的值名称 + &cbMaxValueData, // 最长值数据 + &cbSecurityDescriptor, //安全描述符 + &ftLastWriteTime); // 最后写作时间 + + //枚举子键,直到RegEnumKeyEx失败。 + + if (cSubKeys) + { + printf( "\nNumber of subkeys: %d\n", cSubKeys); + + for (i=0; i