diff --git "a/2020302111103\350\265\265\346\227\255-\347\254\254\344\270\203\345\221\250\344\275\234\344\270\232.md" "b/2020302111103\350\265\265\346\227\255-\347\254\254\344\270\203\345\221\250\344\275\234\344\270\232.md" new file mode 100644 index 0000000000000000000000000000000000000000..3012436e0356d82d76d5578851ff26336b1186f9 --- /dev/null +++ "b/2020302111103\350\265\265\346\227\255-\347\254\254\344\270\203\345\221\250\344\275\234\344\270\232.md" @@ -0,0 +1,132 @@ +#Windows课后作业1 + +## MVVM基本思想 + +1. 概念: +MVVM,是Model-View-ViewModel的简写,是M-V-VM三部分组成。它本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,其中ViewModel将视图 UI 和业务逻辑分开,它可以取出 Model 的数据同时帮忙处理 View 中由于需要展示内容而涉及的业务逻辑。 + +2. 原理: +MVVM采用双向数据绑定,view中数据变化将自动反映到viewmodel上,反之,model中数据变化也将会自动展示在页面上。把Model和View关联起来的就是ViewModel。ViewModel负责把Model的数据同步到View显示出来,还负责把View的修改同步回Model。 + +3. 核心思想: +MVVM核心思想,是关注model的变化,让MVVM框架利用自己的机制自动更新DOM,也就是所谓的数据-视图分离,数据不会影响视图。 +![](https://img-blog.csdnimg.cn/3a913bac879b4c18b02ec83cbcc4397c.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5pil6aOO5YyW5L2c56eL6Zuo,size_20,color_FFFFFF,t_70,g_se,x_16) + +4. 实现方式: +a、**发布者-订阅者模式:** 一般通过sub, pub的方式实现数据和视图的绑定监听,更新数据方式通常做法是 vm.set('property', value)。 +b、**脏值检查:** angular.js 是通过脏值检测的方式比对数据是否有变更,来决定是否更新视图,在指定的事件触发时进入脏值检测。 +c、**数据劫持:** vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。 + +5. 实现: +MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。 +```js +class MVVM { + constructor(options) { + this.$options = options + this.$el = options.el + this.$data = options.data + // 属性代理,实现 vm.xxx -> vm._data.xxx + for (let key in this.$data) { + this.$proxy(key) + } + observer(this.$data) + this.$compile = new Compile(this.$el || document.body, this) + } + $proxy(key) { + Object.defineProperty(this, key, { + configurable: false, + enumerable: true, + get() { + return this.$data[key] + }, + set(newVal) { + this.$data[key] = newVal + } + }) + } + } +``` + +6. 优点: +a. 分离视图(View)和模型( Model ),降低代码耦合,提高视图或者逻辑的重用性:比如视图(View)可以独立于 Model变化和修改,一个 ViewModel 可以绑定不同的 "View" 上,当 View 变化的时候 Model 不可以不变,当 Model 变化 的时候View 也可以不变。你可以把一些视图逻辑放在一个 ViewModel 里面,让很多 view 重用这段视图逻辑。 +b. 提高可测试性 : ViewModel 的存在可以帮助开发者更好地编写测试代码。 +c. 自动更新 dom: 利用双向绑定 , 数据更新后视图自动更新 , 让开发者从繁琐的手动 dom 中解放。 + +7. 缺点: +a. Bug 很难被调试 : 因为使用双向绑定的模式,当你看到界面异常了,有可能是你 View 的代码有 Bug ,也可能是 Model 的代码有问题。数据绑定使得一个位置的Bug 被快速传递到别的位置,要定位原始出问题的地方就变得不那么容易了。另外,数据绑定的声明是指令式地写在View 的模版当中的,这些内容是没办法去打断点 debug 的。 +b. 一个大的模块中 model 也会很大,虽然使用方便了也很容易保证了数据的一致性,但是长期持有,不释放内存就造成了花费更多的内存。 +c. 对于大型的图形应用程序,视图状态较多, ViewModel 的构建和维护的成本都会比较高。 + + +## WPF窗体应用程序创建流程(VS2019) +1. 点击创建新项目,项目类型选择桌面,选择WPF应用,点击下一步按钮 + +![](WPF1.png) +2. 新创建的项目引用了PresentationCore、PresentationFramework、WindowsBase三大核心程序集。 + +![](WPF2.png) +3. App.xaml:设置应用程序的起始文件与资源 + +![](https://img2020.cnblogs.com/blog/513752/202007/513752-20200705181301034-370338140.png) +4. MainWindows.xaml:程序界面与XAML设计文件 + +![](https://img2020.cnblogs.com/blog/513752/202007/513752-20200705182613022-206887400.png) + +## WPF基本控件使用 +1.button:按钮控件 + +2.label:一般用户描述性文字显示 +在Label控件使用时,一般给予用户提示。用法上没有什么很特殊的,label控件的值记住:不是Text 而是 Content属性。 + +3.textbox:支持编辑的基本控件 + +![](https://images.cnblogs.com/cnblogs_com/hegezhou_hot/201210/201210231340312306.png) + +4.listbox:下拉列表控件 + +![](https://images.cnblogs.com/cnblogs_com/hegezhou_hot/201210/201210231340477209.png) + +5.dataGrid:WPF中最常用的列表数据显示控件 + +![](https://images.cnblogs.com/cnblogs_com/hegezhou_hot/201210/201210231340343372.png) +![](https://images.cnblogs.com/cnblogs_com/hegezhou_hot/201210/201210231340353862.png) + +6.combox:与ListBox基本上差别不大 + +## 搭建VS下python调试环境及机器学习平台pytorch +--- +###(由于本电脑没有独立显卡,GPU版本PyTorch安装不成功,于是尝试安装了CPU版本PyTorch) +1.下载anaconda3 + +![](https://img-blog.csdnimg.cn/ff5d00648a074567bc8b758911270e9e.png) + +2.创建conda虚拟环境 +```conda create -n newpytorch python=3.6.5 +``` + +3.安装pytorch +在anaconda中添加镜像源 +```conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ +conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge +conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/ +conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/ +conda config --set show_channel_urls yes +``` + +![](https://img-blog.csdnimg.cn/c98833ea8fdd4b07b02d9027618e9687.png) + +4.激活虚拟环境 +``` +activate newpytorch +python +``` + +5.在python中输入 +``` +import torch +import torchvision +``` + +![](https://img-blog.csdnimg.cn/210e2c79e86b4f9f942a261dd24aec27.png) + + diff --git a/2_7&2_8cn.md b/2_7&2_8cn.md new file mode 100644 index 0000000000000000000000000000000000000000..9b23b72f91d8fe956d972c87940223b586158ed0 --- /dev/null +++ b/2_7&2_8cn.md @@ -0,0 +1,179 @@ +#2_7注册表结构和注册表值类型 +>https://docs.microsoft.com/en-us/windows/win32/api/winreg/ns-winreg-valenta +>https://docs.microsoft.com/en-us/windows/win32/sysinfo/registry-value-types +>https://docs.microsoft.com/en-us/windows/win32/sysinfo/registry-value-types + +##1.注册表结构 +``` +typedef struct value_entW { + LPWSTR ve_valuename; + DWORD ve_valuelen; + DWORD_PTR ve_valueptr; + DWORD ve_type; +} VALENTW, *PVALENTW; +``` + +ve_valuename +要检索的值的名称。要在调用RegQueryMultipleValues之前设置该成员 + +ve_valuelen +ve_valueptr所指向的数据大小,以字节为单位 + +ve_valueptr +指向value项数据的指针。这是一个指针,指向由RegQueryMultipleValues填充的lpValueBuf缓冲区中返回的值的数据 + +ve_type +ve_valueptr指向数据的数据类型 + + +##2.注册表值类型 +下面的示例遍历一个REG_MULTI_SZ字符串 +``` +#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; +} +``` + + +#2_8枚举注册表子键 +>https://docs.microsoft.com/en-us/windows/win32/sysinfo/enumerating-registry-subkeys + +本实验示例使用RegQueryInfoKey、RegEnumKeyEx和RegEnumValue函数枚举指定键的子键。传递给每个函数的hKey参数是一个打开键的句柄。此键必须在函数调用之前打开,然后关闭。 + +``` +// QueryKey -枚举key及其相关值的子键。 +// 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; + + // Get the class name and the value count. + retCode = RegQueryInfoKey( + hKey, // 键柄 + achClass, // 类名缓冲区 + &cchClassName, // 类字符串的大小 + NULL, // 保留 + &cSubKeys, // 子键数 + &cbMaxSubKey, // 最长子键大小 + &cchMaxClass, // 最长的类字符串 + &cValues, // 此键值的数目 + &cchMaxValue, // 最长的值名 + &cbMaxValueData, // 最长值数据 + &cbSecurityDescriptor, // 安全描述项 + &ftLastWriteTime); // 最后写入时间 + + // Enumerate the subkeys, until RegEnumKeyEx fails. + + if (cSubKeys) + { + printf( "\nNumber of subkeys: %d\n", cSubKeys); + + for (i=0; i +#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; +} +``` \ No newline at end of file diff --git "a/\350\265\265\346\227\255-2020302111103-lab2-8.md" "b/\350\265\265\346\227\255-2020302111103-lab2-8.md" new file mode 100644 index 0000000000000000000000000000000000000000..2ba7829c7e62ab1a8157cf4c65f79f63d1d37c13 --- /dev/null +++ "b/\350\265\265\346\227\255-2020302111103-lab2-8.md" @@ -0,0 +1,114 @@ +# 枚举注册表子键 + +```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