能否在OpenFileDialog对话框添加输入栏,按钮之类的东西?

sandywing 2003-09-14 07:18:06
具体要怎样编程?
...全文
39 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
menuvb 2003-09-14
  • 打赏
  • 举报
回复
跟上面的朋友意见相同,自己建一个对话框来实际openfiledialog功能
sandywing 2003-09-14
  • 打赏
  • 举报
回复
可以自己编一个form,但我想在用OpenFileDialog打开的对话框中增加一些功能
xz_king 2003-09-14
  • 打赏
  • 举报
回复
VC中的做法是自己重写一个类来实现。.net的还没试过。
saucer 2003-09-14
  • 打赏
  • 举报
回复
参考
http://msdnaa.com/Resources/display.aspx?ResID=1863

http://www.c-sharpcorner.com/Code/2002/Feb/FileDialogCB.asp
封面 1 书名 2 版权 3 前言 8 目录 10 第一部份:Visual Basic 2010 环境 18 第一章 全身心投入:Visual Basic 2010 编程之旅 19 1.1 开始使用Visual Basic 2010 20 1.2 新建项目 20 1.3 理解 Visual Studio 2010 22 1.4 修改对象的属性 23 1.4.1 对象的命名 23 1.4.2 设置窗体的Text属性 24 1.4.3 保存项目 25 1.4.4 为窗体添加图标 25 1.4.5 改变窗体的大小 26 1.5 在窗体中添加控件 27 1.6 设计界面 27 1.6.1 在窗体中添加可见控件 28 1.6.2 在窗体中添加不可见控件 29 1.7 编写界面后面的代码 30 1.7.1 让用户浏览文件 30 1.7.2 使用代码终止程序 32 1.8 运行项目 33 1.9 总结 34 1.10 问与答 34 1.11 作业 35 1.11.1 测验 35 1.11.2 答案 35 1.11.3 练习 35 第二章 Visual Basic 2010导航 36 2.1 使用Visual Basic 2010起始页 36 2.1.1 创建新项目 37 2.1.2 打开现有项目 38 2.2 导航和定制Visual Basic环境 38 1. 显示和隐藏设计窗口 39 2. 浮动设计窗口 39 3. 停靠设计窗口 40 4. 自动隐藏设计窗口 41 2.3 使用工具 41 2.3.1 显示和隐藏工具 42 2.3.2 停靠工具及调整其大小 42 2.4 使用工具箱将控件添加到窗体 43 2.5 使用“属性”窗口设置对象属性 44 2.5.1 选择对象并查看其属性 44 2.5.2 查看和修改属性 44 2.5.3 使用颜色属性 45 2.5.4 查看属性说明 47 2.6 管理项目 47 2.6.1 使用“解决方案资源管理器”管理项目文件 47 2.6.2 使用解决方案 48 2.6.3 理解项目组件 49 2.6.4 设置项目属性 50 2.6.5 添加和删除项目文件 50 2.7 快速而简单的编程入门指南 51 2.7.1 用变量存储值 51 2.7.2 使用过程来编写代码功能单元 52 2.8 获取帮助 52 2.9 总结 53 2.10 问与答 53 2.11 作业 54 2.11.1 测验 54 2.11.2 答案 54 2.11.3 练习 54 第三章 理解对象和集合 55 3.1 理解对象 56 3.2 理解属性 56 3.2.1 获取和设置属性 57 3.2.2 使用对象及其属性 58 3.3 理解方法 61 3.3.1 触发方法 61 3.3.2 理解方法的动态性 61 3.4 创建简单的对象示例项目 62 3.4.1 为绘图项目创建界面 62 3.4.2 编写基于对象的代码 62 3.4.3 测试对象示例项目 65 3.5 理解集合 65 3.6 使用对象浏览器 67 3.7 总结 68 3.8 问与答 68 3.9 作业 69 3.9.1 测试 69 3.9.2 答案 69 3.9.3 练习 69 第四章 理解事件 70 4.1 理解事件驱动的编程 70 4.1.1 触发事件 71 4.1.2 避免递归事件 72 4.1.3 访问对象的事件 73 4.1.4 使用事件参数 74 4.2 创建事件示例项目 76 4.2.1 创建用户界面 76 4.2.2 创建事件处理程序 77 4.3 更新事件名 79 4.4 总结 79 4.5 问与答 80 4.6 作业 80 4.6.1 测试 80 4.6.2 答案 80 4.6.3 练习 81 第二部份 创建用户界面 82 第五章 创建窗体:基础知识 83 5.1 修改窗体的名称 84 5.2 改变窗体的外观 85 5.2.1 在窗体的标题中显示文本 85 5.2.2 改变窗体的背景色 86 5.2.3 将图像添加到窗体背景中 87 5.2.4 为窗体添加图标 88 5.2.5 为窗体添加最小化、最大化和控制框按钮 89 5.2.6 修改窗体边框的外观和行为 90 5.2.7 控制窗体最小化和最大化时的大小 91 5.3 显示和隐藏窗体 92 5.3.1 显示窗体 92 5.3.2 理解窗体的模态性 92 5.3.3 以正常、最大化或最小化状态显示窗体 93 5.3.4 指定窗体的初始显示位置 94 5.3.5 防止窗体在任务中出现 95 5.3.6 卸载窗体 95 5.4 总结 96 5.5 问与答 96 5.6 作业 96 5.6.1 测验 96 5.6.2 答案 97 5.6.3 练习 97 第六章 创建窗体:高级技能 98 6.1 使用控件 98 6.1.1 将控件添加到窗体中 98 6.1.2 操纵控件 99 6.1.3 创建Tab顺序 107 6.1.4 堆叠控件 109 6.2 创建位于最前面的非模态窗口 109 6.3 创建透明窗体 109 6.4 创建可滚动窗体 110 6.5 创建多文档界面 111 6.6 设置启动窗体 113 6.7 总结 114 6.8 问与答 114 6.9 作业 114 6.9.1 测验 114 6.9.2 答案 115 6.9.3 练习 115 第七章 使用传统控件 116 7.1 使用Lable控件显示静态文本 116 7.2 通过文本框让用户输入文本 117 7.2.1 指定文本对齐方式 118 7.2.2 创建多行文本框 118 7.2.3 添加滚动条 119 7.2.4 限制用户可输入的字符数 120 7.2.5 创建密码框 120 7.2.6 理解文本框的常用事件 121 7.3 创建按钮 121 7.3.1 接受按钮和取消按钮 122 7.3.2 使用复选框提供是/否选项 123 7.4 创建容器和单选按钮组 124 7.4.1 使用面板和分组框 124 7.4.2 使用单选按钮 125 7.5 使用列表框显示列表 126 7.5.1 在设计时操纵Items 127 7.5.2 在运行时操纵Items 127 7.5.3 对列表进行排序 131 7.6 使用组合框创建下?131 7.7 总结 132 7.8 问与答 133 7.9 作业 133 7.9.1 测验 133 7.9.2 答案 134 7.9.3 练习 134 第八章 使用高级控件 135 8.1 创建定时器 135 8.2 创建带选项卡的对话框 137 8.3 在图像列表(Image List)控件中存储图片 140 8.4 使用列表视图(List View)控件创建增强的列表 141 8.4.1 创建列 141 8.4.2 添加列表项 142 8.4.3 使用代码操纵List View 143 8.5 使用Tree View创建层次列表 144 8.5.1 在Tree View中添加节点 145 8.5.2 删除节点 146 8.5.3 清除所有节点 147 8.6 总结 147 8.7 问与答 147 8.8 作业 148 8.8.1 测验 148 8.8.2 答案 148 8.8.3 练习 148 第九章 给窗体添加菜单和工具 149 9.1 创建菜单 149 9.1.1 创建顶级菜单项 150 9.1.2 为顶级菜单创建菜单项 152 9.1.3 移动和删除菜单项 153 9.1.4 创建复选菜单项 153 9.1.5 对菜单进行编程 154 9.1.6 实现上下文菜单 156 9.1.7 为菜单项指定快捷键 157 9.2 使用Toolbar(工具)控件 158 9.2.1 使用按钮集合添加工具按钮 159 9.2.2 对工具进行编程 161 9.2.3 为工具按钮创建下?161 9.3 创建状态 162 9.4 总结 163 9.5 问与答 163 9.6 作业 163 9.6.1 测验 163 9.6.2 答案 164 9.6.3 练习 164 第三部份 编程 166 第十章 创建和调用过程 167 10.1 创建Visual Basic代码模块 167 10.2 编写过程 169 10.2.1 声明不返回值的过程 169 10.2.2 声明返回值的过程 172 10.3 调用过程 173 10.4 退出过程 177 10.5 避免无限递归 177 10.6 总结 178 10.7 问与答 179 10.8 作业 179 10.8.1 测验 179 10.8.2 答案 179 10.8.3 练习 180 第十一章 使用常量、数据类型、变量和数组 181 11.1 理解数据类型 182 11.1.1 确定数据类型 182 11.1.2 将数据从一种类型转换为另一种数据类型 184 11.2 定义和使用常量 185 11.3 声明和引用变量 186 11.3.1 声明变量 186 11.3.2 将字面值赋给变量 187 11.3.3 在表达式中使用变量 188 11.3.4 强制变量声明和数据类型检查 188 11.3.5 显式变量声明 188 11.3.6 严格类型检查 189 11.4 使用数组 191 11.4.1 声明数组 191 11.4.2 引用数组变量 191 11.4.3 创建多维数组 192 11.5 确定作用域 193 11.5.1 理解块作用域 193 11.5.2 理解过程级(局部)作用域 194 11.5.3 理解模块级作用域 194 11.5.4 使用全局(命名空间级)作用域 195 11.5.5 名称冲突 196 11.6 声明静态变量 196 11.7 命名规范 197 11.7.1 使用前缀表示数据类型 197 11.7.2 使用变量前缀表示作用域 198 11.7.3 其他前缀 198 11.8 在Picture Viewer项目中使用变量 198 11.8.1 为选项创建变量 198 11.8.2 初始化和使用选项变量 199 11.9 总结 201 11.10 问与答 202 11.11 作业 202 11.11.1 测验 202 11.11.2 答案 203 11.11.3 练习 203 第十二章 执行算术运算、字符串操作和日期/时间调整 204 12.1 使用Visual Basic执行基本的算术运算 204 12.1.1 执行加法运算 205 12.1.2 执行减法和求负运算 205 12.1.3 执行乘法运算 205 12.1.4 执行除法运算 205 12.1.5 执行乘方运算 206 12.1.6 执行取模算术运算 206 12.1.7 判断运算符优先级顺序 206 12.2 比较 207 12.3 理解布尔逻?208 12.3.1 使用And运算符 209 12.3.2 使用Not运算符(!) 209 12.3.3 使用Or运算符 209 12.3.4 使用Xor运算符 210 12.4 操纵字符串 210 12.4.1 连接字符串 210 12.4.2 使用基本的字符串函数 211 12.5 使用日期和时间 214 12.5.1 理解Date数据类型 214 12.5.2 增加或减少日期或时间 215 12.5.3 确定两个日期或时间之间的间隔 216 12.5.4 获取日期的组成部份 216 12.5.5 格式化日期和时间 217 12.5.6 获取当前的系统日期和时间 217 12.5.7 判断值是否为Date 218 12.6 总结 218 12.7 问与答 218 12.8 作业 219 12.8.1 测验 219 12.8.2 答案 219 12.8.3 练习 219 第十三章 使用Visual Basic代码做出决策 220 13.1 使用If...Then进行决策 220 13.1.1 当表达式为False时执行代码 222 13.1.2 使用ElseIf进行复杂的决策 223 13.1.3 嵌套的If...Else结构 224 13.1.4 在一条Case语句中考虑多个可能的值 225 13.1.5 创建Select Case示例 225 13.1.6 创造性地使用Select Case 227 13.2 在过程中使用GoTo实现分支 228 13.3 总结 230 13.4 问与答 230 13.5 作业 230 13.5.1 测验 230 13.5.2 答案 231 13.5.3 练习 231 第十四章 使用循环提高效率 232 14.1 使用For...Next执行确定次数的循环 232 14.1.1 使用Next语句结束循环 233 14.1.2 使用Step指定每次增加的值 233 14.1.3 提早结束循环 234 14.1.4 到达Next之前进入下一次循环 234 14.1.5 创建For...Next示例 235 14.2 使用Do...Loop执行次数不确定的循环 237 14.2.1 创建Do...Loop 237 14.2.2 终止Do...Loop循环 237 14.2.3 创建Do...Loop示例 238 14.3 总结 240 14.4 问与答 240 14.5 作业 241 14.5.1 测验 241 14.5.2 答案 241 14.5.3 练习 241 第十五章 调试代码 242 15.1 在代码中添加注释 243 15.2 识别两种基本的错误 244 15.3 使用Visual Basic的调试工具 246 15.3.1 使用断点 246 15.3.2 使用“即时”窗口 248 15.4 使用Try...Catch...Finally创建结构化错误处理程序 251 15.4.1 处理异常 253 15.4.2 处理预期的异常 254 15.5 总结 256 15.6 问与答 256 15.7 作业 257 15.7.1 测验 257 15.7.2 答案 257 15.7.3 练习 257 第十六章 使用类设计对象 258 16.1 理解类 259 16.1.1 使用类来封装数据和代码 259 16.1.2 比较类和标准模块 259 16.1.3 创建对象接口 260 16.2 根据类实例化对象 265 16.2.1 将对象引用绑定到变量 265 16.2.2 解除对象引用 269 16.2.3 理解对象的生命周期 269 16.3 总结 270 16.4 问与答 270 16.5 作业 270 16.5.1 测验 270 16.5.2 答案 271 16.5.3 练习 271 第十七章 与用户交互 272 17.1 使用MessageBox.Show()函数显示消息 272 17.1.1 指定按钮和图标 273 17.1.2 判断单击的是哪个按钮 275 17.1.3 创建好的消息 276 17.2 创建自定义对话框 276 17.3 使用InputBox()从用户那里获取信息 279 17.4 用键盘交互 280 17.5 使用常见的鼠标事件 282 17.6 总结 284 17.7 问与答 285 17.8 作业 285 17.8.1 测验 285 17.8.2 答案 285 17.8.3 练习 286 第十八章 使用图形 287 18.1 理解Graphics对象 287 18.1.1 为窗体或控件创建Graphics对象 288 18.1.2 为新位图创建Graphics对象 288 18.2 使用?289 18.3 使用系统颜色 290 18.4 使用矩形 292 18.5 绘制形状 293 18.5.1 绘制线条 293 18.5.2 绘制矩形 293 18.5.3 绘制圆形和椭圆 293 18.5.3 清除绘图表面 294 18.6 绘制文本 294 18.7 持久化窗体上的图形 295 18.8 创建绘图示例项目 295 18.9 总结 299 18.10 问与答 300 18.11 作业 300 18.11.1 测验 300 18.11.2 答案 300 18.11.3 练习 301 第四部份 使用数据 302 第十九章 执行文件操作 303 19.1 使用OpenFileDialog和SaveFileDialog控件 303 19.1.1 使用OpenFileDialog控件 304 19.1.2 使用SaveFileDialog控件 306 19.2 使用File对象对文件进行操作 308 19.2.1 判断文件是否存在 308 19.2.2 复制文件 308 19.2.3 移动文件 309 19.2.4 重命名文件 310 19.2.5 删除文件 310 19.2.6 获取文件属性 311 19.3 使用Directory对象对目录进行操作 314 19.4 总结 315 19.5 问与答 315 19.6 作业 315 19.6.1 测验 315 19.6.2 答案 316 19.6.3 练习 316 第二十章 使用注册表和文本文件 317 20.1 使用注册表 317 20.1.1 理解Windows注册表的结构 318 20.1.2 使用My.Computer.Registry访问注册表 319 20.1.3 修改Picture Viewer项目以使用注册表 322 20.2 读写文本文件 326 20.2.1 写入文本文件 326 20.2.2 读取文本文件 328 20.2.3 修改Picture Viewer项目以使用文本文件 329 20.3 总结 332 20.4 问与答 333 20.5 作业 333 20.5.1 测验 333 20.5.2 答案 333 20.5.3 练习 334 第二十一章 使用数据库 335 21.1 ADO.NET简介 336 21.1.1 连接到数据库 337 21.1.2 关闭到数据源的连接 338 21.2 操作数据 338 21.2.1 理解DataTable 339 21.2.2 创建DataAdapter 339 21.2.3 创建和填充DataTable 340 21.2.4 引用DataRow中的字段 341 21.2.5 导航数据 342 21.2.6 编?344 21.2.7 创建新记录 344 21.2.8 删除记录 346 21.2.9 运行数据库示例 346 21.3 总结 346 21.4 问与答 347 21.5 作业 347 21.5.1 测验 347 21.5.2 答案 347 21.5.3 练习 348 第二十二章 使用自动化控制其他应用程序 349 22.1 自动化Microsoft Excel 350 22.1.1 创建指向自动化库的引用 350 22.1.2 创建自动化服务器实例 351 22.1.3 对服务器进行操作 352 22.2 自动化Microsoft Word 354 22.2.1 创建指向自动化库的引用 355 22.2.2 创建自动化服务器实例 355 22.3 总结 356 22.4 问与答 357 22.5 作业 357 22.5.1 测验 357 22.5.2 答案 357 22.5.3 练习 358 第五部份 部署应用程序及其他 360 第二十三章 部署应用程序 361 23.1 理解ClickOnce技术 361 23.2 使用发布向导来创建ClickOnce程序 362 23.3 测试Picture Viewer的ClickOnce安装程序 364 23.4 卸载已安装的应用程序 365 23.5 为创建ClickOnce程序设置高级选项 366 23.6 总结 367 23.7 问与答 367 23.8 作业 367 23.8.1 测验 367 23.8.2 答案 367 23.8.3 练习 368 第二十四章 广阔的视野 369 24.1 .NET Framework 369 24.2 公共语言运行时 370 24.3 微软中间语言 370 24.4 命名空间 371 24.5 通用类型系统 372 24.6 垃圾回收 372 24.7 进一步的阅读 373 24.8 总结 373 封底 374
封面 1 书名 2 版权 3 前言 8 目录 10 第一部份:Visual Basic 2010 环境 18 第一章 全身心投入:Visual Basic 2010 编程之旅 19 1.1 开始使用Visual Basic 2010 20 1.2 新建项目 20 1.3 理解 Visual Studio 2010 22 1.4 修改对象的属性 23 1.4.1 对象的命名 23 1.4.2 设置窗体的Text属性 24 1.4.3 保存项目 25 1.4.4 为窗体添加图标 25 1.4.5 改变窗体的大小 26 1.5 在窗体中添加控件 27 1.6 设计界面 27 1.6.1 在窗体中添加可见控件 28 1.6.2 在窗体中添加不可见控件 29 1.7 编写界面后面的代码 30 1.7.1 让用户浏览文件 30 1.7.2 使用代码终止程序 32 1.8 运行项目 33 1.9 总结 34 1.10 问与答 34 1.11 作业 35 1.11.1 测验 35 1.11.2 答案 35 1.11.3 练习 35 第二章 Visual Basic 2010导航 36 2.1 使用Visual Basic 2010起始页 36 2.1.1 创建新项目 37 2.1.2 打开现有项目 38 2.2 导航和定制Visual Basic环境 38 1. 显示和隐藏设计窗口 39 2. 浮动设计窗口 39 3. 停靠设计窗口 40 4. 自动隐藏设计窗口 41 2.3 使用工具 41 2.3.1 显示和隐藏工具 42 2.3.2 停靠工具及调整其大小 42 2.4 使用工具箱将控件添加到窗体 43 2.5 使用“属性”窗口设置对象属性 44 2.5.1 选择对象并查看其属性 44 2.5.2 查看和修改属性 44 2.5.3 使用颜色属性 45 2.5.4 查看属性说明 47 2.6 管理项目 47 2.6.1 使用“解决方案资源管理器”管理项目文件 47 2.6.2 使用解决方案 48 2.6.3 理解项目组件 49 2.6.4 设置项目属性 50 2.6.5 添加和删除项目文件 50 2.7 快速而简单的编程入门指南 51 2.7.1 用变量存储值 51 2.7.2 使用过程来编写代码功能单元 52 2.8 获取帮助 52 2.9 总结 53 2.10 问与答 53 2.11 作业 54 2.11.1 测验 54 2.11.2 答案 54 2.11.3 练习 54 第三章 理解对象和集合 55 3.1 理解对象 56 3.2 理解属性 56 3.2.1 获取和设置属性 57 3.2.2 使用对象及其属性 58 3.3 理解方法 61 3.3.1 触发方法 61 3.3.2 理解方法的动态性 61 3.4 创建简单的对象示例项目 62 3.4.1 为绘图项目创建界面 62 3.4.2 编写基于对象的代码 62 3.4.3 测试对象示例项目 65 3.5 理解集合 65 3.6 使用对象浏览器 67 3.7 总结 68 3.8 问与答 68 3.9 作业 69 3.9.1 测试 69 3.9.2 答案 69 3.9.3 练习 69 第四章 理解事件 70 4.1 理解事件驱动的编程 70 4.1.1 触发事件 71 4.1.2 避免递归事件 72 4.1.3 访问对象的事件 73 4.1.4 使用事件参数 74 4.2 创建事件示例项目 76 4.2.1 创建用户界面 76 4.2.2 创建事件处理程序 77 4.3 更新事件名 79 4.4 总结 79 4.5 问与答 80 4.6 作业 80 4.6.1 测试 80 4.6.2 答案 80 4.6.3 练习 81 第二部份 创建用户界面 82 第五章 创建窗体:基础知识 83 5.1 修改窗体的名称 84 5.2 改变窗体的外观 85 5.2.1 在窗体的标题中显示文本 85 5.2.2 改变窗体的背景色 86 5.2.3 将图像添加到窗体背景中 87 5.2.4 为窗体添加图标 88 5.2.5 为窗体添加最小化、最大化和控制框按钮 89 5.2.6 修改窗体边框的外观和行为 90 5.2.7 控制窗体最小化和最大化时的大小 91 5.3 显示和隐藏窗体 92 5.3.1 显示窗体 92 5.3.2 理解窗体的模态性 92 5.3.3 以正常、最大化或最小化状态显示窗体 93 5.3.4 指定窗体的初始显示位置 94 5.3.5 防止窗体在任务中出现 95 5.3.6 卸载窗体 95 5.4 总结 96 5.5 问与答 96 5.6 作业 96 5.6.1 测验 96 5.6.2 答案 97 5.6.3 练习 97 第六章 创建窗体:高级技能 98 6.1 使用控件 98 6.1.1 将控件添加到窗体中 98 6.1.2 操纵控件 99 6.1.3 创建Tab顺序 107 6.1.4 堆叠控件 109 6.2 创建位于最前面的非模态窗口 109 6.3 创建透明窗体 109 6.4 创建可滚动窗体 110 6.5 创建多文档界面 111 6.6 设置启动窗体 113 6.7 总结 114 6.8 问与答 114 6.9 作业 114 6.9.1 测验 114 6.9.2 答案 115 6.9.3 练习 115 第七章 使用传统控件 116 7.1 使用Lable控件显示静态文本 116 7.2 通过文本框让用户输入文本 117 7.2.1 指定文本对齐方式 118 7.2.2 创建多行文本框 118 7.2.3 添加滚动条 119 7.2.4 限制用户可输入的字符数 120 7.2.5 创建密码框 120 7.2.6 理解文本框的常用事件 121 7.3 创建按钮 121 7.3.1 接受按钮和取消按钮 122 7.3.2 使用复选框提供是/否选项 123 7.4 创建容器和单选按钮组 124 7.4.1 使用面板和分组框 124 7.4.2 使用单选按钮 125 7.5 使用列表框显示列表 126 7.5.1 在设计时操纵Items 127 7.5.2 在运行时操纵Items 127 7.5.3 对列表进行排序 131 7.6 使用组合框创建下?131 7.7 总结 132 7.8 问与答 133 7.9 作业 133 7.9.1 测验 133 7.9.2 答案 134 7.9.3 练习 134 第八章 使用高级控件 135 8.1 创建定时器 135 8.2 创建带选项卡的对话框 137 8.3 在图像列表(Image List)控件中存储图片 140 8.4 使用列表视图(List View)控件创建增强的列表 141 8.4.1 创建列 141 8.4.2 添加列表项 142 8.4.3 使用代码操纵List View 143 8.5 使用Tree View创建层次列表 144 8.5.1 在Tree View中添加节点 145 8.5.2 删除节点 146 8.5.3 清除所有节点 147 8.6 总结 147 8.7 问与答 147 8.8 作业 148 8.8.1 测验 148 8.8.2 答案 148 8.8.3 练习 148 第九章 给窗体添加菜单和工具 149 9.1 创建菜单 149 9.1.1 创建顶级菜单项 150 9.1.2 为顶级菜单创建菜单项 152 9.1.3 移动和删除菜单项 153 9.1.4 创建复选菜单项 153 9.1.5 对菜单进行编程 154 9.1.6 实现上下文菜单 156 9.1.7 为菜单项指定快捷键 157 9.2 使用Toolbar(工具)控件 158 9.2.1 使用按钮集合添加工具按钮 159 9.2.2 对工具进行编程 161 9.2.3 为工具按钮创建下?161 9.3 创建状态 162 9.4 总结 163 9.5 问与答 163 9.6 作业 163 9.6.1 测验 163 9.6.2 答案 164 9.6.3 练习 164 第三部份 编程 166 第十章 创建和调用过程 167 10.1 创建Visual Basic代码模块 167 10.2 编写过程 169 10.2.1 声明不返回值的过程 169 10.2.2 声明返回值的过程 172 10.3 调用过程 173 10.4 退出过程 177 10.5 避免无限递归 177 10.6 总结 178 10.7 问与答 179 10.8 作业 179 10.8.1 测验 179 10.8.2 答案 179 10.8.3 练习 180 第十一章 使用常量、数据类型、变量和数组 181 11.1 理解数据类型 182 11.1.1 确定数据类型 182 11.1.2 将数据从一种类型转换为另一种数据类型 184 11.2 定义和使用常量 185 11.3 声明和引用变量 186 11.3.1 声明变量 186 11.3.2 将字面值赋给变量 187 11.3.3 在表达式中使用变量 188 11.3.4 强制变量声明和数据类型检查 188 11.3.5 显式变量声明 188 11.3.6 严格类型检查 189 11.4 使用数组 191 11.4.1 声明数组 191 11.4.2 引用数组变量 191 11.4.3 创建多维数组 192 11.5 确定作用域 193 11.5.1 理解块作用域 193 11.5.2 理解过程级(局部)作用域 194 11.5.3 理解模块级作用域 194 11.5.4 使用全局(命名空间级)作用域 195 11.5.5 名称冲突 196 11.6 声明静态变量 196 11.7 命名规范 197 11.7.1 使用前缀表示数据类型 197 11.7.2 使用变量前缀表示作用域 198 11.7.3 其他前缀 198 11.8 在Picture Viewer项目中使用变量 198 11.8.1 为选项创建变量 198 11.8.2 初始化和使用选项变量 199 11.9 总结 201 11.10 问与答 202 11.11 作业 202 11.11.1 测验 202 11.11.2 答案 203 11.11.3 练习 203 第十二章 执行算术运算、字符串操作和日期/时间调整 204 12.1 使用Visual Basic执行基本的算术运算 204 12.1.1 执行加法运算 205 12.1.2 执行减法和求负运算 205 12.1.3 执行乘法运算 205 12.1.4 执行除法运算 205 12.1.5 执行乘方运算 206 12.1.6 执行取模算术运算 206 12.1.7 判断运算符优先级顺序 206 12.2 比较 207 12.3 理解布尔逻?208 12.3.1 使用And运算符 209 12.3.2 使用Not运算符(!) 209 12.3.3 使用Or运算符 209 12.3.4 使用Xor运算符 210 12.4 操纵字符串 210 12.4.1 连接字符串 210 12.4.2 使用基本的字符串函数 211 12.5 使用日期和时间 214 12.5.1 理解Date数据类型 214 12.5.2 增加或减少日期或时间 215 12.5.3 确定两个日期或时间之间的间隔 216 12.5.4 获取日期的组成部份 216 12.5.5 格式化日期和时间 217 12.5.6 获取当前的系统日期和时间 217 12.5.7 判断值是否为Date 218 12.6 总结 218 12.7 问与答 218 12.8 作业 219 12.8.1 测验 219 12.8.2 答案 219 12.8.3 练习 219 第十三章 使用Visual Basic代码做出决策 220 13.1 使用If...Then进行决策 220 13.1.1 当表达式为False时执行代码 222 13.1.2 使用ElseIf进行复杂的决策 223 13.1.3 嵌套的If...Else结构 224 13.1.4 在一条Case语句中考虑多个可能的值 225 13.1.5 创建Select Case示例 225 13.1.6 创造性地使用Select Case 227 13.2 在过程中使用GoTo实现分支 228 13.3 总结 230 13.4 问与答 230 13.5 作业 230 13.5.1 测验 230 13.5.2 答案 231 13.5.3 练习 231 第十四章 使用循环提高效率 232 14.1 使用For...Next执行确定次数的循环 232 14.1.1 使用Next语句结束循环 233 14.1.2 使用Step指定每次增加的值 233 14.1.3 提早结束循环 234 14.1.4 到达Next之前进入下一次循环 234 14.1.5 创建For...Next示例 235 14.2 使用Do...Loop执行次数不确定的循环 237 14.2.1 创建Do...Loop 237 14.2.2 终止Do...Loop循环 237 14.2.3 创建Do...Loop示例 238 14.3 总结 240 14.4 问与答 240 14.5 作业 241 14.5.1 测验 241 14.5.2 答案 241 14.5.3 练习 241 第十五章 调试代码 242 15.1 在代码中添加注释 243 15.2 识别两种基本的错误 244 15.3 使用Visual Basic的调试工具 246 15.3.1 使用断点 246 15.3.2 使用“即时”窗口 248 15.4 使用Try...Catch...Finally创建结构化错误处理程序 251 15.4.1 处理异常 253 15.4.2 处理预期的异常 254 15.5 总结 256 15.6 问与答 256 15.7 作业 257 15.7.1 测验 257 15.7.2 答案 257 15.7.3 练习 257 第十六章 使用类设计对象 258 16.1 理解类 259 16.1.1 使用类来封装数据和代码 259 16.1.2 比较类和标准模块 259 16.1.3 创建对象接口 260 16.2 根据类实例化对象 265 16.2.1 将对象引用绑定到变量 265 16.2.2 解除对象引用 269 16.2.3 理解对象的生命周期 269 16.3 总结 270 16.4 问与答 270 16.5 作业 270 16.5.1 测验 270 16.5.2 答案 271 16.5.3 练习 271 第十七章 与用户交互 272 17.1 使用MessageBox.Show()函数显示消息 272 17.1.1 指定按钮和图标 273 17.1.2 判断单击的是哪个按钮 275 17.1.3 创建好的消息 276 17.2 创建自定义对话框 276 17.3 使用InputBox()从用户那里获取信息 279 17.4 用键盘交互 280 17.5 使用常见的鼠标事件 282 17.6 总结 284 17.7 问与答 285 17.8 作业 285 17.8.1 测验 285 17.8.2 答案 285 17.8.3 练习 286 第十八章 使用图形 287 18.1 理解Graphics对象 287 18.1.1 为窗体或控件创建Graphics对象 288 18.1.2 为新位图创建Graphics对象 288 18.2 使用?289 18.3 使用系统颜色 290 18.4 使用矩形 292 18.5 绘制形状 293 18.5.1 绘制线条 293 18.5.2 绘制矩形 293 18.5.3 绘制圆形和椭圆 293 18.5.3 清除绘图表面 294 18.6 绘制文本 294 18.7 持久化窗体上的图形 295 18.8 创建绘图示例项目 295 18.9 总结 299 18.10 问与答 300 18.11 作业 300 18.11.1 测验 300 18.11.2 答案 300 18.11.3 练习 301 第四部份 使用数据 302 第十九章 执行文件操作 303 19.1 使用OpenFileDialog和SaveFileDialog控件 303 19.1.1 使用OpenFileDialog控件 304 19.1.2 使用SaveFileDialog控件 306 19.2 使用File对象对文件进行操作 308 19.2.1 判断文件是否存在 308 19.2.2 复制文件 308 19.2.3 移动文件 309 19.2.4 重命名文件 310 19.2.5 删除文件 310 19.2.6 获取文件属性 311 19.3 使用Directory对象对目录进行操作 314 19.4 总结 315 19.5 问与答 315 19.6 作业 315 19.6.1 测验 315 19.6.2 答案 316 19.6.3 练习 316 第二十章 使用注册表和文本文件 317 20.1 使用注册表 317 20.1.1 理解Windows注册表的结构 318 20.1.2 使用My.Computer.Registry访问注册表 319 20.1.3 修改Picture Viewer项目以使用注册表 322 20.2 读写文本文件 326 20.2.1 写入文本文件 326 20.2.2 读取文本文件 328 20.2.3 修改Picture Viewer项目以使用文本文件 329 20.3 总结 332 20.4 问与答 333 20.5 作业 333 20.5.1 测验 333 20.5.2 答案 333 20.5.3 练习 334 第二十一章 使用数据库 335 21.1 ADO.NET简介 336 21.1.1 连接到数据库 337 21.1.2 关闭到数据源的连接 338 21.2 操作数据 338 21.2.1 理解DataTable 339 21.2.2 创建DataAdapter 339 21.2.3 创建和填充DataTable 340 21.2.4 引用DataRow中的字段 341 21.2.5 导航数据 342 21.2.6 编?344 21.2.7 创建新记录 344 21.2.8 删除记录 346 21.2.9 运行数据库示例 346 21.3 总结 346 21.4 问与答 347 21.5 作业 347 21.5.1 测验 347 21.5.2 答案 347 21.5.3 练习 348 第二十二章 使用自动化控制其他应用程序 349 22.1 自动化Microsoft Excel 350 22.1.1 创建指向自动化库的引用 350 22.1.2 创建自动化服务器实例 351 22.1.3 对服务器进行操作 352 22.2 自动化Microsoft Word 354 22.2.1 创建指向自动化库的引用 355 22.2.2 创建自动化服务器实例 355 22.3 总结 356 22.4 问与答 357 22.5 作业 357 22.5.1 测验 357 22.5.2 答案 357 22.5.3 练习 358 第五部份 部署应用程序及其他 360 第二十三章 部署应用程序 361 23.1 理解ClickOnce技术 361 23.2 使用发布向导来创建ClickOnce程序 362 23.3 测试Picture Viewer的ClickOnce安装程序 364 23.4 卸载已安装的应用程序 365 23.5 为创建ClickOnce程序设置高级选项 366 23.6 总结 367 23.7 问与答 367 23.8 作业 367 23.8.1 测验 367 23.8.2 答案 367 23.8.3 练习 368 第二十四章 广阔的视野 369 24.1 .NET Framework 369 24.2 公共语言运行时 370 24.3 微软中间语言 370 24.4 命名空间 371 24.5 通用类型系统 372 24.6 垃圾回收 372 24.7 进一步的阅读 373 24.8 总结 373 封底 374
 数据的加密与解密  文件的加密与解密 第 章 加密与解密技术 第19章 加密与解密技术 829 19.1 数据的加密与解密 实例571 异或算法对数字进行加密与解密 光盘位置:光盘\MR\19\571 中级 趣味指数: 实 例说明 在实现本实例之前先来简要了解一下加密的概念,加密是指通过 某种特殊的方法,更改已有信息的内容,使得未授权的用户即使得到 了加密信息,如果没有正确解密的方法,也无法得到信息的内容。谈 到加密的话题,一些读者一定非常感兴趣,而且会联想到复杂的加密 算法,本实例主要使用异或“^”运算符简单地实现了对数字加密的 功能。实例运行效果如图19.1 所示。 关 键技术 本实例实现时主要使用了“异或”运算符对数字进行“异或”运 算,以达到简单加密数字的目的,下面对其进行详细讲解。 “异或”运算符“^”用于比较两个二进制数的相应位。在执行按位“异或”运算时,如果两个二进制数的 相应位都为1 或两个二进制数的相应位都为0,则返回0;如果两个二进制数的相应位其中一个为1 一个为0, 则返回1。 现在来了解一下使用“异或”加密或解密的执行过程,数值23 转换为二进制为10111,加密数字的数值15 转换为二进制为1111。对比两个二进制的值,从右向左按位对比,如果两个二进制数的相应位都为1 或两个二 进制数的相应位都为0,则返回0;如果两个二进制数的相应位中一个为1 一个为0,则返回1,最后得到的结 果为二进制值11000,该值转换为十进制为24,所以得到的加密结果为24。而解密过程也很简单,只是将加密 结果24与加密数字15 进行“异或”运算,将24 转换为二进制值11000,将15 转换为二进制值1111,进行“异 或”运算后,得到结果为23,这样又还原了加密的数据。  说明:本实例只是简单地使用了“异或”运算符计算两个整型数值以达到加密的目的,所以本实例只可以 对整型数值进行加密运算,并不适合其他数据的加密。 设 计过程 (1)打开Visual Studio 2008 开发环境,新建一个Windows窗体应用程序,并将其命名为Encrypt。 (2)更改默认窗体Form1 的Name 属性为Frm_Main,在该窗体中添加两个GroupBox 容器控件,其中, 在第一个GroupBox 中放入3 个TextBox 控件和一个Button 按钮,分别用于输入数字、输入加密数字、显示加 密后的数字和计算加密信息;在第二个GroupBox 中放入一个TextBox 控件和一个Button 按钮,分别用于显示 解密后的信息和计算解密信息。 (3)程序主要代码如下: private void btn_Encrypt_Click(object sender, EventArgs e) { int P_int_Num, P_int_Key; //定义两个值类型变量 if (int.TryParse(txt_Num.Text, out P_int_Num) //判断输入是否是数值 && int.TryParse(txt_Key.Text, out P_int_Key)) { txt_Encrypt.Text = (P_int_Num ^ P_int_Key).ToString(); //加密数值 } else 图19.1 异或算法对数字进行加密与解密 C#开发实战1200 例(第II卷) 830 { MessageBox.Show("请输入数值", "出现错误!"); //提示输入信息不正确 } } private void btn_Revert_Click(object sender, EventArgs e) { int P_int_Key, P_int_Encrypt; //定义两个值类型变量 if (int.TryParse(txt_Encrypt.Text, out P_int_Key) //判断输入是否是数值 && int.TryParse(txt_Key.Text, out P_int_Encrypt)) { txt_Revert.Text = (P_int_Encrypt ^ P_int_Key).ToString(); //解密数值 } else { MessageBox.Show("请输入数值", "出现错误!"); //提示输入信息不正确 } } 秘 笈心法 心法领悟571:简述“异或”运算符。 本实例使用了“异或”运算符,但是在使用“异或”运算符之前,有必要了解“异或”运算符所做的“异 或”运算的机制,“异或”运算符“^”用于比较两个二进制数的相应位。在执行按位“异或”运算时,如果两 个二进制数的相应位都为1 或两个二进制数的相应位都为0,则返回0;如果两个二进制数的相应位中一个为1 一个为0,则返回1。 实例572 使用MD5算法加密数据 光盘位置:光盘\MR\19\572 中级 趣味指数: 实 例说明 MD5(Message-Digest Algorithm 5)是一种被广泛使用的“消息-摘要 算法”。“消息-摘要算法”实际上就是一个单项散列函数,数据块通过单 向散列函数得到一个固定长度的散列值,数据块的签名就是计算数据块的散 列值,MD5 算法的散列值为128 位。本实例演示如何使用MD5 算法对用户 输入的密码进行加密,实例运行效果如图19.2 所示。 关 键技术 本实例在实现时主要用到了MD5类的ComputeHash 方法,下面对其进行详细讲解。 MD5 类表示MD5 哈希算法的所有实现均从中继承的抽象类,该类位于System.Security.Cryptography 命名 空间下,其ComputeHash 方法有3种重载形式,分别介绍如下。  计算指定字节数组的哈希值,语法格式如下: public byte[] ComputeHash(byte[] buffer) 参数说明  buffer:要计算其哈希代码的输入。  返回值:计算所得的哈希代码。  计算指定Stream 对象的哈希值,语法格式如下: public byte[] ComputeHash(Stream inputStream) 参数说明  inputStream:要计算其哈希代码的输入。  返回值:计算所得的哈希代码。 图19.2 使用MD5 算法加密数据 第19章 加密与解密技术 831  计算指定字节数组的指定区域的哈希值,语法格式如下: public byte[] ComputeHash(byte[] buffer,int offset,int count) ComputeHash 方法中的参数及说明如表19.1 所示。 表19.1 ComputeHash方法中的参数及说明 参 数 说 明 buffer 要计算其哈希代码的输入 offset 字节数组中的偏移量,从该位置开始使用数据 count 数组中用作数据的字节数 返回值 计算所得的哈希代码  说明:本实例用到了ComputeHash 方法的第一种重载形式。 设 计过程 (1)打开Visual Studio 2008 开发环境,新建一个Windows窗体应用程序,并将其命名为MD5Arithmetic。 (2)更改默认窗体Form1 的Name 属性为Frm_Main,在该窗体中添加两个TextBox 控件,分别用来输入 要加密的数据和显示加密后的字符串;添加一个Button 控件,用来使用MD5算法对输入的数据进行加密。 (3)程序主要代码如下: public string Encrypt(string strPwd) { MD5 md5 = new MD5CryptoServiceProvider(); //创建MD5 对象 byte[] data = System.Text.Encoding.Default.GetBytes(strPwd); //将字符编码为一个字节序列 byte[] md5data = md5.ComputeHash(data); //计算data字节数组的哈希值 md5.Clear(); //清空MD5 对象 string str = ""; //定义一个变量,用来记录加密后的密码 for (int i = 0; i < md5data.Length - 1; i++) //遍历字节数组 { str += md5data[i].ToString("x").PadLeft(2, '0'); //对遍历到的字节进行加密 } return str; //返回得到的加密字符串 } private void button1_Click(object sender, EventArgs e) { string P_str_Code = textBox1.Text; //记录要加密的密码 textBox2.Text = Encrypt(P_str_Code); //显示加密后的字符串 } 秘 笈心法 心法领悟572:如何判断是否为数字? 开发程序时,经常需要判断输入的字符串是否为数字,如判断输入的电话号码、货币金额和邮编等。在程 序中判断是否为数字的方法有很多种,可以使用正则表达式、int.Parse 方法和double.Parse 方法等。下面的代码 通过double.Parse 方法判断textBox1 文本框中的输入是否为数字。 double.Parse(textBox1.Text); 实例573 使用ROT13算法加密解密数据 光盘位置:光盘\MR\19\573 中级 趣味指数: 实 例说明 文件加密可以避免造成重要信息的泄漏,复杂的加密算法可以将信息加密得非常繁杂,但是对于一般的应 用,没有必要作类似于PGP、RSA 或DES 等复杂的加密算法。本实例介绍如何使用ROT13 算法加密和解密数 C#开发实战1200 例(第II卷) 832 据。实例运行效果如图19.3 所示。 图19.3 使用ROT13算法加密解密数据 关 键技术 本实例实现时,主要是用Convert 类的ToChar 方法来获取单个字符的Unicode 编码,然后将字母的前13 个和后13 个对调,从而实现加密的功能。下面对Convert类的ToChar 方法进行详细讲解。 ToChar 方法返回指定的Unicode字符值,并且不执行任何实际的转换,其语法格式如下: public static char ToChar (char value) 参数说明 value:一个Unicode 字符。 设 计过程 (1)打开Visual Studio 2008 开发环境,新建一个Windows窗体应用程序,并将其命名为ROT13Encrypt。 (2)更改默认窗体Form1 的Name 属性为Frm_Main,在该窗体中添加两个TextBox 控件,分别用来显示 原始数据和解密后的数据;添加两个Button 控件,分别用来实现利用ROT13算法加密和解密数据的功能。 (3)程序主要代码如下: public string ROT13Encode(string InputText) { char tem_Character; //存储临时字符 int UnicodeChar; //存储临时字符的字节值 string EncodedText = ""; //存储加密或解密后的字符串 for (int i = 0; i = 97 && UnicodeChar = 110 && UnicodeChar = 65 && UnicodeChar = 78 && UnicodeChar <= 90) //对字符进行解密 { UnicodeChar = UnicodeChar - 13; } EncodedText = EncodedText + (char)UnicodeChar; //得到加密或解密字符串 } return EncodedText; //返回加密或解密后的字符串 } 秘 笈心法 心法领悟573:如何在字符串中查找指定字符? 在字符串中查找指定字符时,可以先将字符串显示在richTextBox 控件中,然后利用richTextBox 类的Find 方法在该控件中查找指定字符。在字符串中查找指定字符的代码如下: 第19章 加密与解密技术 833 M_int_index = richTextBox1.Find(textBox1.Text.Trim(), M_int_index, RichTextBoxFinds.MatchCase); if (M_int_index == -1) { MessageBox.Show("没有要查找的字符串", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); M_int_index = 0; } else M_int_index = M_int_index + textBox1.Text.Trim().Length; richTextBox1.Focus(); 实例574 使用恺撒密码算法加密密码 光盘位置:光盘\MR\19\574 中级 趣味指数: 实 例说明 恺撒密码据传是古罗马恺撒大帝用来保护重要军情的加密系统,它 是一种置换密码,通过将字母顺序推后起到加密作用。例如,将字母顺 序推后3 位,字母A 将被推作为字母D,字母B 将被推作字母E。本实 例使用C#实现了恺撒加密的算法,实例运行效果如图19.4 所示。 关 键技术 本实例实现时主要用到了string 类的ToCharArray 方法和Convert 类的ToChar 方法,下面分别对它们进行 详细介绍。 (1)string类的ToCharArray 方法 string类的ToCharArray 方法用来将字符串中的字符复制到Unicode 字符数组,该方法有两种重载形式,本 实例中用到的它的重载形式如下: public char[] ToCharArray() 参数说明 返回值:元素为此字符串的各字符的Unicode 字符数组。如果此字符串是空字符串,则返回的数组为空且 长度为零。 (2)Convert 类的ToChar 方法 Convert 类的ToChar 方法用来将指定的值转换为Unicode 字符,该方法为可重载方法,本实例中用到的它 的重载形式如下: public static char ToChar(int value) 参数说明  value:32 位有符号整数。  返回值:等效于value 的值的Unicode 字符。 设 计过程 (1)打开Visual Studio 2008开发环境,新建一个Windows窗体应用程序,并将其命名为CaesarArithmetic。 (2)更改默认窗体Form1 的Name 属性为Frm_Main,在该窗体中添加两个TextBox 控件,分别用来输入 要加密的数据和显示加密后的字符串;添加一个Button 控件,用来使用恺撒密码算法对输入的数据进行加密。 (3)程序主要代码如下: public int AscII(string str) //获取字符的ASCII 码 { byte[] array = new byte[1]; //创建字节数组 array = System.Text.Encoding.ASCII.GetBytes(str); //为字节数组赋值 int asciicode = (short)(array[0]); //获取字节数组的第一项 return asciicode; //返回字节数组的第一项 } 图19.4 使用恺撒密码算法加密密码 C#开发实战1200 例(第II卷) 834 public string Caesar(string str) //凯撒加密算法的实现 { char[] c = str.ToCharArray(); //创建字符数组 string strCaesar = ""; //定义一个变量,用来存储加密后的字符串 for (int i = 0; i < str.Length; i++) //遍历字符串中的每一个字符串 { string ins = c[i].ToString(); //记录遍历到的字符 string outs = ""; //定义一个变量,用来记录加密后的字符串 bool isChar = "0123456789abcdefghijklmnopqrstuvwxyz".Contains(ins.ToLower()); //判断指定的字符串中是否包含遍历到的字符 bool isToUpperChar = isChar && (ins.ToUpper() == ins); //判断遍历到的字符是否是大写 ins = ins.ToLower(); //将遍历到的字符转换为小写 if (isChar) //判断指定的字符串中是否包含遍历到的字符 { int offset = (AscII(ins) + 5 - AscII("a")) % (AscII("z") - AscII("a") + 1); //获取字符的ASCII 码 outs = Convert.ToChar(offset + AscII("a")).ToString(); //转换为字符并记录 if (isToUpperChar) //判断是否大写 { outs = outs.ToUpper(); //全部转换为大写 } } else { outs = ins; //记录遍历的字符 } strCaesar += outs; //添加到加密字符串中 } return strCaesar; //返回加密后的字符串 } 秘 笈心法 心法领悟574:如何将新字符串添加到已有字符串中? 将新字符串添加到已有字符串中时,可以先声明一个StringBuilder类对象,以指定已有字符串的长度可变, 然后利用该对象的Append方法在字符串中添加指定字符串。将新字符串添加到已有字符串的代码如下: StringBuilder strbuilder = new StringBuilder(textBox1.Text.Trim()); strbuilder.Append(textBox2.Text.Trim()); textBox3.Text = strbuilder.ToString(); 实例575 对数据报进行加密保障通信安全 光盘位置:光盘\MR\19\575 高级 趣味指数: 实 例说明 网络传输数据时,有时候传输信息容易被不法分子截获而 用作其他用途。这样,如果传输的数据中包含有重要秘密,将 会造成非常严重的后果。为了防止这种情况的发生,可以对网 络中传输的数据进行加密,用户接收到数据后再进行解密查看, 这样可以更好地保障网络通信安全。运行本实例,首先设置端 口号,然后在窗体左下方的文本框中输入聊天信息,单击“发 送”按钮,向局域网中发送聊天信息,同时在右侧的“数据传 输信息”中显示数据报的发送、接收及丢失情况。实例运行 效果如图19.5 所示。 关 键技术 本实例获取数据报信息时主要用到IPGlobalProperties和UdpStatistics类,而在对数据报加密时用到DESCrypto 图19.5 对数据报进行加密保障通信安全 第19章 加密与解密技术 835 ServiceProvider 和CryptoStream 类,其中DESCryptoServiceProvider 继承于DES 类。下面对本实例中用到的关 键技术进行详细讲解。 (1)IPGlobalProperties 类 IPGlobalProperties 类提供有关本地计算机的网络连接的信息,本实例中用到它的GetIPGlobalProperties 和 GetUdpIPv4Statistics 方法,下面分别进行介绍。 GetIPGlobalProperties 为静态方法,主要用来获取一个对象,该对象提供有关本地计算机的网络连接和通信 统计数据的信息,其语法格式如下: public static IPGlobalProperties GetIPGlobalProperties() 参数说明 返回值:IPGlobalProperties 对象,该对象包含有关本地计算机的信息。 GetUdpIPv4Statistics 方法主要用来提供本地计算机的用户数据报协议/Internet 协议版本4 (UDP/IPv4)统 计数据,其语法格式如下: public abstract UdpStatistics GetUdpIPv4Statistics() 参数说明 返回值:UdpStatistics 对象,提供本地计算机的UDP/IPv4通信统计数据。 例如,本实例中创建IPGlobalProperties 对象,及调用其GetUdpIPv4Statistics 方法创建UdpStatistics 对象的 代码如下: IPGlobalProperties NetInfo = IPGlobalProperties.GetIPGlobalProperties(); UdpStatistics myUdpStat = null; myUdpStat = NetInfo.GetUdpIPv4Statistics(); (2)UdpStatistics类 UdpStatistics 类提供用户数据报协议(UDP)统计数据,本实例中主要用到其DatagramsSent 属性、 DatagramsReceived属性和IncomingDatagramsDiscarded 属性,其中,DatagramsSent 属性用来获取已发送的用户 数据报协议(UDP)数据报的数量,DatagramsReceived 属性用来获取已接收的用户数据报协议(UDP)数据报 的数量,IncomingDatagramsDiscarded 属性用来获取已收到但因端口错误而丢弃的用户数据报协议(UDP)数据 报的数量。 例如,本实例中初始化已发送、已接收和丢失数据报的实现代码如下: SendNum1 = Int32.Parse(myUdpStat.DatagramsSent.ToString()); //记录发送的数据报 ReceiveNum1 = Int32.Parse(myUdpStat.DatagramsReceived.ToString()); //记录接收的数据报 DisNum1 = Int32.Parse(myUdpStat.IncomingDatagramsDiscarded.ToString()); //记录丢失的数据报  说明:IPGlobalProperties 类和UdpStatistics 类位于System.Net.NetworkInformation 命名空间下。 (3)DES 类 DES 类表示所有DES 实现都必须从中派生的数据加密标准(DES)算法的基类,其CreateEncryptor 方法和 CreateDecryptor 方法分别用来加密和解密。 CreateEncryptor 方法使用指定的Key属性和初始化向量(IV)创建对称加密器对象,其语法格式如下: public abstract ICryptoTransform CreateEncryptor(byte[] rgbKey,byte[] rgbIV) 参数说明  rgbKey:用于对称算法的密钥。  rgbIV:用于对称算法的初始化向量。  返回值:对称加密器对象。 CreateDecryptor 方法使用指定的Key属性和初始化向量(IV)创建对称解密器对象,其语法格式如下: public abstract ICryptoTransform CreateDecryptor(byte[] rgbKey,byte[] rgbIV) 参数说明  rgbKey:用于对称算法的密钥。  rgbIV:用于对称算法的初始化向量。  返回值:对称解密器对象。 C#开发实战1200 例(第II卷) 836 (4)CryptoStream 类 CryptoStream 类定义将数据流链接到加密转换的流,其构造函数的语法格式如下: public CryptoStream(Stream stream,ICryptoTransform transform,CryptoStreamMode mode) 参数说明  stream:对其执行加密转换的流。  transform:要对流执行的加密转换。  mode:CryptoStreamMode 枚举值之一,CryptoStreamMode 枚举值及说明如表19.2 所示。 表19.2 CryptoStreamMode枚举值及说明 枚 举 值 说 明 Read 对加密流的读访问 Write 对加密流的写访问 另外,在向加密或解密流中写入数据时用到CryptoStream 类的Write 方法,该方法将一个字节序列写入当 前CryptoStream,并将流中的当前位置提升写入的字节数,其语法格式如下: public override void Write(byte[] buffer,int offset,int count) 参数说明  buffer:字节数组,此方法将count 个字节从buffer 复制到当前流。  offset:buffer 中的字节偏移量,从此偏移量开始将字节复制到当前流。  count:要写入当前流的字节数。  说明:DES 类和CryptoStream 类位于System.Security.Cryptography 命名空间下。 设 计过程 (1)打开Visual Studio 2008开发环境,新建一个Windows窗体应用程序,并将其命名为EncryptDataReport。 (2)更改默认窗体Form1 的Name 属性为Frm_Main,在该窗体中添加两个RichTextBox 控件,分别用来 输入聊天信息和显示聊天信息;添加4 个TextBox 控件,分别用来输入端口号和显示已发送数据报、已接收数 据报、丢失数据报;添加4 个Button 控件,分别用来执行设置端口号、发送聊天信息、清空聊天信息和关闭应 用程序操作。 (3)程序主要代码如下。 Frm_Main 窗体的后台代码中,首先创建程序所需要的.NET 对象及公共变量,代码如下: #region 定义全局对象及变量 private IPEndPoint Server; //服务器端 private IPEndPoint Client; //客户端 private Socket mySocket; //套接字 private EndPoint ClientIP; //IP地址 byte[] buffer, data; //接收缓存 bool blFlag = true; //标识是否第一次发送信息 bool ISPort = false; //判断端口打开 int SendNum1, ReceiveNum1, DisNum1; //记录窗体加载时的已发送\已接收\丢失的数据报 int SendNum2, ReceiveNum2, DisNum2; //记录当前已发送\已接收\丢失的数据报 int SendNum3, ReceiveNum3, DisNum3; //缓存已发送\已接收\丢失的数据报 int port; //端口号 #endregion Frm_Main 窗体加载时,初始化已发送、已接收和丢失的数据报,并使用全局变量记录,实现代码如下: //初始化已发送、已接收和丢失的数据报 private void Form1_Load(object sender, EventArgs e) { if (blFlag == true) { IPGlobalProperties NetInfo = IPGlobalProperties.GetIPGlobalProperties(); //创建一个IPGlobalProperties 对象 UdpStatistics myUdpStat = null; //声明UdpStatistics 对象 myUdpStat = NetInfo.GetUdpIPv4Statistics(); //创建UdpStatistics 对象 第19章 加密与解密技术 837 SendNum1 = Int32.Parse(myUdpStat.DatagramsSent.ToString()); //记录发送的数据报 ReceiveNum1 = Int32.Parse(myUdpStat.DatagramsReceived.ToString()); //记录接收的数据报 DisNum1 = Int32.Parse(myUdpStat.IncomingDatagramsDiscarded.ToString()); //记录丢失的数据报 } } 单击“设置”按钮,使用指定的端口号连接服务器端与客户端,并开始接收消息。“设置”按钮的Click 事件的代码如下: private void button4_Click(object sender, EventArgs e) //设置端口号 { try { port = Convert.ToInt32(textBox4.Text); //记录端口号 CheckForIllegalCrossThreadCalls = false; //指定线程中可以调用窗体的控件对象 buffer = new byte[1024]; data = new byte[1024]; Server = new IPEndPoint(IPAddress.Any, port); //创建服务器端 Client = new IPEndPoint(IPAddress.Broadcast, port); //创建客户端 ClientIP = (EndPoint)Server; //获取服务器端IP 地址 //创建Socket 对象 mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); //设置Socket 网络操作 mySocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1); mySocket.Bind(Server); //绑定服务器端 //开始接收消息 mySocket.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref ClientIP, new AsyncCallback(StartLister), null); ISPort = true; //打开指定端口号 } catch { } } 单击“发送”按钮,首先判断是否有打开的端口,如果没有,弹出提示信息,否则根据发送和接收的消息 计算已发送、已接收和丢失的数据报,并显示在相应的文本框中,然后使用DES对要发送的消息进行加密发送。 “发送”按钮的Click事件的代码如下: //发送信息 private void button2_Click(object sender, EventArgs e) { if (ISPort == true) //判断是否有打开的端口号 { IPGlobalProperties NetInfo = IPGlobalProperties.GetIPGlobalProperties(); UdpStatistics myUdpStat = null; myUdpStat = NetInfo.GetUdpIPv4Statistics(); try { if (blFlag == false) //非第一次发送 { SendNum2 = Int32.Parse(myUdpStat.DatagramsSent.ToString()); ReceiveNum2 = Int32.Parse(myUdpStat.DatagramsReceived.ToString()); DisNum2 = Int32.Parse(myUdpStat.IncomingDatagramsDiscarded.ToString()); textBox1.Text = Convert.ToString(SendNum2 - SendNum3); textBox2.Text = Convert.ToString(ReceiveNum2 - ReceiveNum3); textBox3.Text = Convert.ToString(DisNum2 - DisNum3); } SendNum2 = Int32.Parse(myUdpStat.DatagramsSent.ToString()); ReceiveNum2 = Int32.Parse(myUdpStat.DatagramsReceived.ToString()); DisNum2 = Int32.Parse(myUdpStat.IncomingDatagramsDiscarded.ToString()); SendNum3 = SendNum2; //记录本次的发送数据报 ReceiveNum3 = ReceiveNum2; //记录本次的接收数据报 DisNum3 = DisNum2; //记录本次的丢失数据报 if (blFlag == true) //第一次发送 { textBox1.Text = Convert.ToString(SendNum2 - SendNum1); textBox2.Text = Convert.ToString(ReceiveNum2 - ReceiveNum1); textBox3.Text = Convert.ToString(DisNum2 - DisNum1); blFlag = false; C#开发实战1200 例(第II卷) 838 } } catch (Exception ex) { MessageBox.Show(ex.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Information); } string str = EncryptDES(rtbSend.Text, "mrsoftxk"); //加密要发送的信息 data = Encoding.Unicode.GetBytes(str); mySocket.SendTo(data, data.Length, SocketFlags.None, Client); //发送消息 rtbSend.Text = ""; } else { MessageBox.Show("请首先打开端口!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); button4.Focus(); } } 上面的代码中用到了EncryptDES 方法,该方法为自定义的、返回值类型为string 的方法,主要用来使用 DES 加密数据报,它有两个string 类型的参数,分别用来表示待加密的字符串和加密密钥,返回值为加密后的 字符串。EncryptDES 方法的实现代码如下: #region DES 加密字符串 /// ///DES 加密字符串 /// ///待加密的字符串 ///加密密钥,要求为8 位 ///加密成功返回加密后的字符串,失败返回源字符串 public string EncryptDES(string str, string key) { try { byte[] rgbKey = Encoding.UTF8.GetBytes(key.Substring(0, 8)); //将加密密钥转换为字节数组 byte[] rgbIV = Keys; //记录原始密钥数组 byte[] inputByteArray = Encoding.UTF8.GetBytes(str); //将加密字符串转换为字节数组 DESCryptoServiceProvider myDES = new DESCryptoServiceProvider(); //创建加密对象 MemoryStream MStream = new MemoryStream(); //创建内存数据流 //创建加密流对象 CryptoStream CStream = new CryptoStream(MStream, myDES.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write); CStream.Write(inputByteArray, 0, inputByteArray.Length); //向加密流中写入数据 CStream.FlushFinalBlock(); //释放加密流对象 return Convert.ToBase64String(MStream.ToArray()); //返回内存流中的数据 } catch { return str; } } #endregion 秘 笈心法 心法领悟575:如何根据标点符号分行? 根据标点符号分行时,首先要使用string 类的Split 方法分割字符串,然后再通过“\n”回车换行符将分割 的字符串换行显示。根据标点符号分行的代码如下: string oldstr = textBox1.Text.Trim(); string[] newstr = oldstr.Split('。'); for (int i = 0; i < newstr.Length; i++) { if (richTextBox1.Text == "") richTextBox1.Text = newstr[i].ToString(); else richTextBox1.Text += "\n" + newstr[i].ToString(); } 第19章 加密与解密技术 839 实例576 使用one-time pad算法加密数据 光盘位置:光盘\MR\19\576 高级 趣味指数: 实 例说明 在密码学里,有一种理想的加密方案,叫做一次一密乱码本,即 one-time pad 算法,该算法是最安全的加密算法,双方一旦安全交换 了密钥,之后交换信息的过程就可以保证绝对安全。本实例使用C# 实现了one-time pad 加密算法,实例运行效果如图19.6 所示。  注意:程序中使用one-time pad 算法时,一定要保证密钥和密文 的长度是一样的。 关 键技术 本实例在实现one-time pad 加密算法时,主要用到了Encoding 类的GetBytes 方法和GetString 方法,下面 分别对它们进行详细介绍。 (1)Encoding 类的GetBytes方法 Encoding 类表示字符编码,其GetBytes方法主要用来将一组字符编码为一个字节序列,该方法为可重载方 法,本实例中用到的它的重载形式如下: public virtual byte[] GetBytes(string s) 参数说明  s:字符串。  返回值:一个字节数组,包含对指定的字符集进行编码的结果。  说明:Encoding 类位于System.Text 命名空间下。 (2)Encoding 类的GetString方法 Encoding 类的GetString方法主要用来将一个字节序列解码为一个字符串,该方法为可重载方法,本实例中 用到的它的重载形式如下: public virtual string GetString(byte[] bytes) 参数说明  bytes:包含要解码的字节序列的字节数组。  返回值:包含指定字节序列解码结果的字符串。 设 计过程 (1) 打开Visual Studio 2008开发环境,新建一个Windows窗体应用程序,并将其命名为OneTimePadArithmetic。 (2)更改默认窗体Form1 的Name 属性为Frm_Main,在该窗体中添加4 个TextBox 控件,分别用来输入 要加密的数据和密钥,以及显示加密后的数据和解密后的数据;添加两个Button控件,分别用来实现使用one-time pad 算法加密数据和解密数据的功能。 (3)程序主要代码如下。 在Frm_Main 窗体中输入要加密的数据和密钥后,单击“加密”按钮,使用one-time pad 算法对输入的数据 进行加密,实现代码如下: private void button1_Click(object sender, EventArgs e) { textBox2.Text = ""; //清空文本框 Encoding encoding = Encoding.Default; //获取字符编码 byte[] btData = encoding.GetBytes(textBox1.Text); //将要加密的数据转换为字节数组 byte[] btKey = encoding.GetBytes(textBox4.Text); //将密钥转换为字节数组 图19.6 使用one-time pad 算法加密数据 C#开发实战1200 例(第II卷) 840 if (btData.Length == btKey.Length) //判断长度是否相等 { byte[] btEncrypt = Encrypt(btData, btKey); //加密数据 for (int i = 0; i < btEncrypt.Length; i++) //遍历加密后的字节数组 { textBox2.Text += btEncrypt[i]; //显示在文本框中 } } } 上面的代码中用到了Encrypt 方法,该方法为自定义的、返回值类型为byte[]的方法,主要用来对指定的数 据使用one-time pad 算法进行加密。Encrypt方法的实现代码如下: public static byte[] Encrypt(byte[] btData, byte[] btKey) { if (btKey.Length != btData.Length) //判断长度是否相等 { MessageBox.Show("请确保要加密数据的长度与密钥的长度一致!"); } byte[] btResult = new byte[btData.Length]; //声明一个字节数组,用来存储加密数据 for (int i = 0; i < btResult.Length; ++i) //遍历字节数组 { btResult[i] = (byte)(btKey[i] ^ btData[i]); //为字节数组赋值 } return btResult; //返回得到的加密数据 } 单击“解密”按钮,调用Encrypt 方法对加密过的数据进行逆向加密,并返回一个byte[]数组,然后使用 Encoding 类的GetString方法从该数组中获取解密字符串。“解密”按钮的Click事件的代码如下: private void button2_Click(object sender, EventArgs e) { Encoding encoding = Encoding.Default; //获取字符编码 byte[] btData = encoding.GetBytes(textBox1.Text); //将要加密的数据转换为字节数组 byte[] btKey = encoding.GetBytes(textBox4.Text); //将密钥转换为字节数组 if (btData.Length == btKey.Length) //判断长度是否相等 { byte[] btDecrypt = Encrypt(Encrypt(btData, btKey), btKey); //解密数据 textBox3.Text = encoding.GetString(btDecrypt); //将解密后的字节数组转换为字符串并显示 } } 秘 笈心法 心法领悟576:如何在字符串中添加多个空格? 开发程序时,有时会根据需要在字符串中添加一些空格,这时可以使用string 类的Insert方法,该方法可以 在字符串中的指定位置插入一个新的字符串(包括空格)。在字符串中添加空格的代码如下: textBox3.Text = textBox1.Text.Insert(Convert.ToInt32(textBox2.Text.Trim()), " "); 实例577 使用伪随机数加密技术加密用户登录密码 光盘位置:光盘\MR\19\577 高级 趣味指数: 实 例说明 为了保障用户登录密码的安全,本实例使用伪随机数技术对用 户的登录密码进行加密,运行本实例,当用户在“登录密码”文本 框中输入登录密码时,程序会自动将使用过伪随机数加密技术加密 过的登录密码显示在下面的“加密密码”文本框中,单击“登录” 按钮,程序对“加密密码”文本框中的加密数据进行解密,然后再 与用户输入的登录密码相比较,如果相同,则登录成功;否则,登 录失败。实例运行效果如图19.7 所示。 图19.7 使用伪随机数加密技术 加密用户登录密码 第19章 加密与解密技术 841 关 键技术 本实例对用户登录密码加密时用到伪随机数加密技术,伪随机数加密技术实质上就是通过伪随机数序列使 登录密码字符串的字节值发生变化而产生密文,由于相同的初值能得到相同的随机数序列,因此,可以采用同 样的伪随机数序列来对密文进行解密。产生伪随机数时主要用到Random 类,该类表示伪随机数生成器,它是 一种能够产生满足某些随机性统计要求的数字序列的设备,其Next方法用来返回随机数,语法格式如下: public virtual int Next(int maxValue) 参数说明  maxValue:要生成的随机数的上界(随机数不能取该上界值),maxValue 必须大于等于零。  返回值:大于等于零且小于maxValue 的32 位带符号整数,即返回值的范围通常包括零但不包括 maxValue;不过,如果maxValue 等于零,则返回maxValue。 设 计过程 (1)打开Visual Studio 2008开发环境,新建一个Windows窗体应用程序,并将其命名为PRanDataEncrypt。 (2)更改默认窗体Form1 的Name属性为Frm_Main,在该窗体中添加3 个TextBox 控件,分别用来输入 登录用户、登录密码和显示加密密码;添加两个Button 控件,分别用来执行用户登录和清空文本框操作。 (3)程序主要代码如下。 Frm_Main 窗体的后台代码中,首先定义加密用户密码所用的伪随机数,代码如下: //定义加密用户密码所用的伪随机数 private string randStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"; 当在“登录密码”文本框中输入登录密码时,实时将使用伪随机数加密过的登录密码显示在“加密密码” 文本框中,实现代码如下: private void textBox2_TextChanged(object sender, EventArgs e) { textBox3.Text = EncryptPwd(textBox2.Text); //显示加密后的用户登录密码 } 上面的代码中用到EncryptPwd 方法,该方法为自定义的、返回值类型为string 的方法,主要用来使用伪随 机数技术加密用户登录密码,它有一个参数,用来表示用户登录密码。EncryptPwd 方法的实现代码如下: /// /// 使用伪随机数加密用户登录密码 /// /// 用户登录密码 /// 加密后的用户登录密码 private string EncryptPwd(string str) { byte[] btData = Encoding.Default.GetBytes(str); //将登录密码转换为字节数组 int j, k, m; int len = randStr.Length; //记录伪随机数长度 StringBuilder sb = new StringBuilder(); //创建StringBuilder对象 Random rand = new Random(); //创建Random 对象 for (int i = 0; i < btData.Length; i++) { j = (byte)rand.Next(6); //产生伪随机数 btData[i] = (byte)((int)btData[i] ^ j); //使用伪随机数对密码字节数组进行移位 k = (int)btData[i] % len; m = (int)btData[i] / len; m = m * 8 + j; sb.Append(randStr.Substring(k, 1) + randStr.Substring(m, 1)); //组合加密字符串 } return sb.ToString(); //返回生成的加密字符串 } 单击“登录”按钮,判断“加密密码”文本框是否为空。如果不为空,调用DecryptPwd 方法解密“加密 密码”文本框中的字符串;然后使用解密后的字符串与“登录密码”文本框中的字符串相比较,如果相同,则 用户登录成功;否则,弹出提示信息。“登录”按钮的Click事件代码如下: C#开发实战1200 例(第II卷) 842 private void button1_Click(object sender, EventArgs e) { if (textBox3.Text != "") { if (DecryptPwd(textBox3.Text) == textBox2.Text) //对加密过的登录密码进行解密 MessageBox.Show("用户登录成功!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); else MessageBox.Show("用户密码错误!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } 上面的代码中用到了DecryptPwd 方法,该方法为自定义的、返回值类型为string 的方法,主要用来解密用 户登录密码,它有一个参数,主要用来表示经过加密的用户登录密码。DecryptPwd 方法的实现代码如下: /// /// 解密用户登录密码 /// /// 经过加密的用户登录密码 /// 解密后的用户登录密码 private string DecryptPwd(string str) { try { int j, k, m, n = 0; int len = randStr.Length; //获取伪随机数长度 byte[] btData = new byte[str.Length / 2]; //定义一个字节数组,并指定长度 for (int i = 0; i < str.Length; i += 2) //对登录密码进行解密 { k = randStr.IndexOf(str[i]); m = randStr.IndexOf(str[i + 1]); j = m / 8; m = m - j * 8; btData[n] = (byte)(j * len + k); btData[n] = (byte)((int)btData[n] ^ m); n++; } return Encoding.Default.GetString(btData); //返回解密后的登录密码 } catch { return ""; } } 秘 笈心法 心法领悟577:如何将字符串颠倒输出? 颠倒输出字符串时,可以先将要输出的字符串保存到一个char 类型的数组中,然后使用Array 类的Reverse 方法。将字符串颠倒输出的代码如下: string str1 = textBox1.Text.Trim(); char[] charstr = str1.ToCharArray(); Array.Reverse(charstr); string str2 = new string(charstr); textBox2.Text = str2; 实例578 以XML格式导入导出密钥 光盘位置:光盘\MR\19\578 高级 趣味指数: 实 例说明 本实例主要实现以XML 格式导入导出密钥,从而实现对数据进行加密和解密的功能。运行本实例,首先 在窗体中显示生成的公钥和私钥,然后输入明文数据,单击“加密”按钮,对输入的明文数据进行加密;单击 “解密”按钮,对加密后的数据进行解密。实例运行效果如图19.8 所示。 第19章 加密与解密技术 843 图19.8 以XML 格式导入导出密钥 关 键技术 本实例实现时主要用到了RSACryptoServiceProvider 类的ToXmlString方法、Encrypt 方法和Decrypt 方法, 下面对本实例中用到的关键技术进行详细讲解。 (1)RSACryptoServiceProvider 类的ToXmlString方法 RSACryptoServiceProvider 类用来使用加密服务提供程序(CSP)提供的RSA 算法的实现执行不对称加密和 解密,其ToXmlString 方法主要用来创建并返回包含当前RSA 对象的密钥的XML 字符串,该方法的语法格式 如下: public override string ToXmlString(bool includePrivateParameters) 参数说明  includePrivateParameters:true 表示同时包含RSA公钥和私钥,false 表示仅包含公钥。  返回值:包含当前RSA对象的密钥的XML字符串。  说明:RSACryptoServiceProvider 类位于System.Security.Cryptography 命名空间下。 (2)RSACryptoServiceProvider 类的Encrypt方法 该方法主要使用RSA算法对数据进行加密,其语法格式如下: public byte[] Encrypt(byte[] rgb,bool fOAEP) 参数说明  rgb:要加密的数据。  fOAEP:如果为true,则使用OAEP 填充(仅在运行Microsoft Windows XP 或更高版本的计算机上可用) 执行直接的RSA 加密;如果为false,则使用PKCS#1 1.5 版填充。  返回值:字节数组,表示已加密的数据。 (3)RSACryptoServiceProvider 类的Decrypt方法 该方法主要使用RSA算法对数据进行解密,其语法格式如下: public byte[] Decrypt(byte[] rgb,bool fOAEP) 参数说明  rgb:要解密的数据。  fOAEP:如果为true,则使用OAEP 填充(仅在运行Microsoft Windows XP 或更高版本的计算机上可用) 执行直接的RSA 解密;如果为false,则使用PKCS#1 1.5 版填充。  返回值:字节数组,表示已解密的数据,它是加密前的原始纯文本。 设 计过程 (1)打开Visual Studio 2008 开发环境,新建一个Windows窗体应用程序,并将其命名为KeyToXML。 (2)更改默认窗体Form1 的Name 属性为Frm_Main,在该窗体中添加5 个TextBox 控件,分别用来显示 C#开发实战1200 例(第II卷) 844 公钥、显示私钥、输入明文数据、显示加密后的数据和显示解密后的数据;添加两个Button 控件,分别用来执 行数据加密和解密操作。 (3)程序主要代码如下。 在Frm_Main 窗体的后台代码中,首先创建RSACryptoServiceProvider 对象,并且定义一个字节数组,用来 存储临时数据,代码如下: RSACryptoServiceProvider RSACrypto = new RSACryptoServiceProvider(); //创建RSA 算法加密解密对象 byte[] M_bt_Data; //定义一个字节数组,用来存储临时数据 Frm_Main 窗体加载时,在文本框中显示程序自动生成的公钥和私钥数据,代码如下: private void Frm_Main_Load(object sender, EventArgs e) { this.textBox1.Text = RSACrypto.ToXmlString(true); //显示生成的公钥 this.textBox2.Text = RSACrypto.ToXmlString(false); //显示生成的私钥 } 当用户输入明文数据之后,单击“加密”按钮,调用RSACryptoServiceProvider 类的Encrypt方法对数据进 行加密,并且使用Encoding 类的UTF8 编码方式的GetString 方法得到加密后的数据,显示在文本框中。“加密” 按钮的Click事件代码如下: private void button1_Click(object sender, EventArgs e) { if (textBox3.Text != "") //判断是否输入了要加密的数据 { byte[] P_bt_Encrypt = Encoding.UTF8.GetBytes(textBox3.Text); //将要加密的数据转换为字节数组 M_bt_Data = RSACrypto.Encrypt(P_bt_Encrypt, false); //加密数据 textBox4.Text = Encoding.UTF8.GetString(M_bt_Data); //显示加密数据 } } 单击“解密”按钮,调用RSACryptoServiceProvider 类的Decrypt方法对加密过的数据进行解密,并且使用 Encoding 类的UTF8 编码方式的GetString 方法得到解密后的数据,显示在文本框中。“解密”按钮的Click 事 件代码如下: private void button2_Click(object sender, EventArgs e) { if (textBox4.Text != "") //判断是否有加密过的数据 { byte[] P_bt_Decrypt = RSACrypto.Decrypt(M_bt_Data, false); //对数据进行解密 textBox5.Text = Encoding.UTF8.GetString(P_bt_Decrypt); //显示解密数据 } } 秘 笈心法 心法领悟578:如何判断字符串是否为日期格式? 判断字符串是否为日期格式时,可以使用正则表达式。验证日期格式的正则表达式主要有以下3 种: \b(?\d{2,4})/(?\d{1,2})/(?\d{1,2})\b 或 \b(?\d{2,4})-(?\d{1,2})-(?\d{1,2})\b 或 \b(?\d{2,4})年(?\d{1,2})月(?\d{1,2})日\b 实例579 以参数格式导入导出密钥 光盘位置:光盘\MR\19\579 高级 趣味指数: 实 例说明 本实例主要实现以参数格式导入导出密钥,从而实现对数据进行加密和解密的功能。运行本实例,在窗体 第19章 加密与解密技术 845 中输入明文数据,单击“加密”按钮,对输入的明文数据进行加密;单击“解 密”按钮,对加密后的数据进行解密。实例运行效果如图19.9 所示。 关 键技术 本实例实现时主要用到了RSACryptoServiceProvider 类的ExportParameters 方法、ImportParameters 方法、Encrypt 方法和Decrypt 方法,下面对本实例 中用到的关键技术进行详细讲解。 (1)RSACryptoServiceProvider 类的ExportParameters 方法 该方法主要用来导出RSAParameters标准参数,其语法格式如下: public override RSAParameters ExportParameters(bool includePrivateParameters) 参数说明  includePrivateParameters:如果要包括私有参数,则为true;否则为false。  返回值:RSA 算法的标准参数。 (2)RSACryptoServiceProvider 类的ImportParameters 方法 该方法主要用来导入指定的RSAParameters标准参数,其语法格式如下: public override void ImportParameters(RSAParameters parameters) 参数说明 parameters:RSA 算法的标准参数。  说明:关于RSACryptoServiceProvider 类的Encrypt 方法和Decrypt 方法的详细讲解,请参见实例578 中的 关键技术。 设 计过程 (1)打开Visual Studio 2008 开发环境,新建一个Windows窗体应用程序,并将其命名为KeyToParameter。 (2)更改默认窗体Form1 的Name 属性为Frm_Main,在该窗体中添加3 个TextBox 控件,分别用来输入 明文数据、显示加密后的数据和解密后的数据;添加两个Button 控件,分别用来执行数据加密和解密操作。 (3)程序主要代码如下。 Frm_Main 窗体的后台代码中,首先创建RSACryptoServiceProvider 对象和RSAParameters 标准参数对象, 并且定义一个字节数组,用来存储临时数据,代码如下: RSACryptoServiceProvider RSACrypto; //声明RSA 算法加密解密对象 RSAParameters RSAParame; //声明RSAParameters 参数对象 byte[] M_bt_Data; //定义一个字节数组,用来存储临时数据 在Frm_Main 窗体的构造函数中,调用RSACryptoServiceProvider 类的ImportParameters 方法导入 RSAParameters标准参数,实现代码如下: public Frm_Main() { InitializeComponent(); RSACrypto = new RSACryptoServiceProvider(); //初始化RSA 算法加密解密对象 RSAParame = RSACrypto.ExportParameters(true); //初始化RSAParameters 参数 RSACrypto.Clear(); //清空RSACryptoServiceProvider 对象 RSACrypto = new RSACryptoServiceProvider(); //初始化RSA 算法加密解密对象 RSACrypto.ImportParameters(RSAParame); //导入密钥 } 当用户输入明文数据之后,单击“加密”按钮,调用RSACryptoServiceProvider 类的Encrypt方法对数据进 行加密,并且使用Encoding 类的UTF8 编码方式的GetString 方法得到加密后的数据,显示在文本框中。“加密” 按钮的Click事件代码如下: private void button1_Click(object sender, EventArgs e) { if (textBox1.Text != "") //判断是否输入了要加密的数据 { 图19.9 以参数格式导入导出密钥 C#开发实战1200 例(第II卷) 846 byte[] P_bt_Encrypt = Encoding.UTF8.GetBytes(textBox1.Text); //将要加密的数据转换为字节数组 M_bt_Data = RSACrypto.Encrypt(P_bt_Encrypt, false); //加密数据 textBox2.Text = Encoding.UTF8.GetString(M_bt_Data); //显示加密数据 } } 单击“解密”按钮,调用RSACryptoServiceProvider 类的Decrypt方法对加密过的数据进行解密,并且使用 Encoding 类的UTF8 编码方式的GetString 方法得到解密后的数据,显示在文本框中。“解密”按钮的Click 事 件代码如下: private void button2_Click(object sender, EventArgs e) { if (textBox2.Text != "") //判断是否有加密过的数据 { byte[] P_bt_Decrypt = RSACrypto.Decrypt(M_bt_Data, false); //对数据进行解密 textBox3.Text = Encoding.UTF8.GetString(P_bt_Decrypt); //显示解密数据 } } 秘 笈心法 心法领悟579:巧截字符串中的数字。 截取字符串中的数字时,可以先使用CharEnumerator 对象的MoveNext 方法循环访问字符串中的每个字符, 并将字符用System.Text.Encoding 类中ASCII 编码方式的GetBytes 方法进行编码,然后判断经过编码之后的字符 的ASCII码值是否介于48和57之间,如果是,则将其显示在textBox文本框中。截取字符串中数字的代码如下: CharEnumerator CEnumerator = textBox1.Text.GetEnumerator(); while (CEnumerator.MoveNext()) { byte[] array = new byte[1]; array = System.Text.Encoding.ASCII.GetBytes(CEnumerator.Current.ToString()); int asciicode = (short)(array[0]); if (asciicode >= 48 && asciicode <= 57) { textBox2.Text += CEnumerator.Current.ToString(); } } 19.2 文件的加密与解密 实例580 文本文件加密与解密 光盘位置:光盘\MR\19\580 高级 趣味指数: 实 例说明 在本实例的窗体中,首先选择要加密或解密的文本文件,然后单击“加 密”或“解密”按钮对文本文件进行加密或解密。实例运行效果如图19.10 所示。 关 键技术 本实例实现时主要用到了System.Security.Cryptography命名空间下的 RijndaelManaged 类的CreateDecryptor 方法、CreateEncryptor 方法和CryptoStream 类的Write 方法,下面对本实 例中用到的关键技术进行详细讲解。 (1)RijndaelManaged 类 该类是访问System.Security.Cryptography.Rijndael 对称加密算法的托管版本,其语法格式如下: public sealed class RijndaelManaged : Rijndael 图19.10 文本文件加密与解密 第19章 加密与解密技术 847  注意:此算法支持128、192或256 位的密钥长度。 (2)CreateDecryptor 方法 该方法位于RijndaelManaged 类中,使用指定的Key和初始化向量(IV)创建对称的Rijndael 解密器对象, 其语法格式如下: public override IcryptoTransform CreateDecryptor (byte[] rgbKey,byte[] rgbIV) 参数说明  rgbKey:用于对称算法的机密密钥。  rgbIV:用于对称算法的IV。  返回值:对称的Rijndael 解密器对象。 (3)CreateEncryptor 方法 该方法位于RijndaelManaged 类中,使用指定的Key和初始化向量(IV)创建对称的Rijndael 加密器对象, 其语法格式如下: public override ICryptoTransform CreateEncryptor (byte[] rgbKey,byte[] rgbIV) 参数说明  rgbKey:用于对称算法的机密密钥。  rgbIV:用于对称算法的IV。  返回值:对称的Rijndael 加密器对象。  说明:关于CryptoStream 类的Write 方法的详细讲解,请参见实例575中的关键技术。 设 计过程 (1) 打开Visual Studio 2008开发环境,新建一个Windows窗体应用程序,并将其命名为EncryptTextFileOne。 (2)更改默认窗体Form1 的Name 属性为Frm_Main,在该窗体中添加一个TextBox 控件,用来显示文本 文件路径;添加一个OpenFileDialog 控件,用来选择要加密或解密的文本文件;添加3 个Button 控件,用来执 行选择文本文件、加密和解密操作。 (3)程序主要代码如下。 单击“加密”按钮实现对选择的文本文件进行加密,“加密”按钮的Click事件的代码如下: private void button2_Click(object sender, EventArgs e) { if (textBox1.Text == "") //若未选择要加密的文本文件 { MessageBox.Show("请选择要加密的文件"); } //如果没有选择则弹出提示 else { try{ string strPath = textBox1.Text; //加密文件的路径 int intLent=strPath.LastIndexOf("\\")+1; //设置截取的起始位置 int intLong = strPath.Length; //设置截取的长度 string strName = strPath.Substring(intLent,intLong-intLent); //要加密的文件名称 int intTxt = strName.LastIndexOf("."); //设置截取的起始位置 int intTextLeng = strName.Length; //设置截取的长度 string strTxt = strName.Substring(intTxt,intTextLeng-intTxt); //取出文件的扩展名 strName = strName.Substring(0,intTxt); //加密后的文件名及路径 string strOutName = strPath.Substring(0, strPath.LastIndexOf("\\") + 1) + strName + "Out" + strTxt; //加密文件密钥 byte[] key = { 24, 55, 102, 24, 98, 26, 67, 29, 84, 19, 37, 118, 104, 85, 121, 27, 93, 86, 24, 55, 102, 24, 98, 26, 67, 29, 9, 2, 49, 69, 73, 92 }; byte[] IV ={ 22, 56, 82, 77, 84, 31, 74, 24, 55, 102, 24, 98, 26, 67, 29, 99 }; RijndaelManaged myRijndael = new RijndaelManaged(); FileStream fsOut = File.Open(strOutName, FileMode.Create, FileAccess.Write); FileStream fsIn = File.Open(strPath, FileMode.Open, FileAccess.Read); //写入加密文本文件 CryptoStream csDecrypt = new CryptoStream(fsOut, myRijndael.CreateEncryptor(key, IV), CryptoStreamMode.Write); BinaryReader br = new BinaryReader(fsIn); //创建阅读器来读加密文本 csDecrypt.Write(br.ReadBytes((int)fsIn.Length), 0, (int)fsIn.Length); //将数据写入加密文本 C#开发实战1200 例(第II卷) 848 csDecrypt.FlushFinalBlock(); csDecrypt.Close(); //关闭CryptoStream 对象 fsIn.Close(); //关闭FileStream 对象 fsOut.Close(); //关闭FileStream 对象 if (MessageBox.Show("加密成功!加密后的文件名及路径为:\n" + strOutName + ",是否删除源文件", "信息提示", MessageBoxButtons. YesNo) == DialogResult.Yes) { File.Delete(strPath); //删除指定文件 textBox1.Text = ""; //清空文本框 }else { textBox1.Text = ""; } } catch (Exception ee) //如果出现异常 { MessageBox.Show(ee.Message); //输出异常信息 } } } 单击“解密”按钮实现对加密的文本文件进行解密,“解密”按钮的Click事件代码如下: private void button3_Click(object sender, EventArgs e) { if (textBox1.Text == "") //若未选择要解密的文件 { MessageBox.Show("请选择要解密的文件路径"); //如果没有选择则弹出提示 } else { string strPath = textBox1.Text; //加密文件的路径 int intLent = strPath.LastIndexOf("\\") + 1; //设置截取字符串的起始位置 int intLong = strPath.Length; //设置截取长度 string strName = strPath.Substring(intLent, intLong - intLent); //要加密的文件名称 int intTxt = strName.LastIndexOf("."); //截取字符串的起始位置 int intTextLeng = strName.Length; //截取长度 strName = strName.Substring(0, intTxt); //获取扩展名 if (strName.LastIndexOf("Out") != -1) { strName = strName.Substring(0, strName.LastIndexOf("Out")); } else { strName = strName + "In"; } //加密后的文件名及路径 string strInName = strPath.Substring(0, strPath.LastIndexOf("\\") + 1) + strName + ".txt"; //解密文件密钥 byte[] key = { 24, 55, 102, 24, 98, 26, 67, 29, 84, 19, 37, 118, 104, 85, 121, 27, 93, 86, 24, 55, 102, 24, 98, 26, 67, 29, 9, 2, 49, 69, 73, 92 }; byte[] IV ={ 22, 56, 82, 77, 84, 31, 74, 24, 55, 102, 24, 98, 26, 67, 29, 99 }; RijndaelManaged myRijndael = new RijndaelManaged(); //创建RijndaelManaged 对象 //创建FileStream 对象 FileStream fsOut = File.Open(strPath, FileMode.Open, FileAccess.Read); CryptoStream csDecrypt = new CryptoStream(fsOut, myRijndael.CreateDecryptor(key, IV), CryptoStreamMode.Read); StreamReader sr = new StreamReader(csDecrypt); //把文件读出来 StreamWriter sw = new StreamWriter(strInName); //解密后写入一个新文件 sw.Write(sr.ReadToEnd()); sw.Flush(); sw.Close(); sr.Close(); fsOut.Close(); if (MessageBox.Show("解密成功!解密后的文件名及路径为:"+strInName+",是否删除源文件", "信息提示", MessageBoxButtons.YesNo) == DialogResult.Yes) { File.Delete(strPath); //删除指定文件 textBox1.Text = ""; //清空文本框 } else { 第19章 加密与解密技术 849 textBox1.Text = ""; } } } 秘 笈心法 心法领悟580:如何存储变长字符串? 在程序中存储变长字符串时,需要使用StringBuilder对象。相对于string 对象来说,StringBuilder 对象是可 变的,不用生成中间对象,因此,在连接的字符串较多或字符串长度较长时,通常都使用StringBuilder 对象。 实例581 利用图片加密文件 光盘位置:光盘\MR\19\581 高级 趣味指数: 实 例说明 本实例在加密时,使用指定的图片生成加密密钥,然后对文本文件进 行加密;在解密时,使用加密时的图片生成解密密钥,然后对加密的文本 文件进行解密。运行本实例,首先打开一张图片,用来生成加密或解密的 密钥,然后选择要加密或解密的文本文件,最后单击“加密”或“解密” 按钮,实现对文本文件的加密或解密。实例运行效果如图19.11 所示。 关 键技术 本实例实现时主要用到了RC2CryptoServiceProvider 类、BinaryWriter 类的Write 方法、File 类的Delete 方法和Copy 方法,下面对本实例中用到 的关键技术进行详细讲解。 (1)RC2CryptoServiceProvider 类 该类定义访问RC2算法的加密服务提供程序(CSP)实现的包装对象,无法继承此类。 (2)BinaryWriter 类 该类以二进制形式将基元类型写入流,并支持用特定的编码写入字符串,其构造器的语法格式如下: public BinaryWriter (Stream output) 参数说明 output:表示输出流。 (3)BinaryWriter 类的Write 方法 该方法将一个无符号字节写入当前流,并将流的位置提升一个字节,其语法格式如下: public virtual void Write (byte value) 参数说明 value:表示要写入的无符号字节。 (4)File 类的Delete 方法 File 类提供用于创建、复制、删除、移动和打开文件的静态方法,并协助创建FileStream 对象,该类是个 静态类,其Delete方法用于删除指定的文件,如果指定的文件不存在,则引发异常。该方法的语法格式如下: public static void Delete (string path) 参数说明 path:表示要删除的文件的名称。 (5)File 类的Copy 方法 该方法将现有文件复制到新文件,不允许改写同名的文件,其语法格式如下: public static void Copy (string sourceFileName,string destFileName) 图19.11 利用图片加密文件 C#开发实战1200 例(第II卷) 850 参数说明  sourceFileName:要复制的文件。  destFileName:目标文件的名称,不能是一个目录或现有文件。 设 计过程 (1) 打开Visual Studio 2008开发环境,新建一个Windows窗体应用程序,并将其命名为EncryptTextFileTwo。 (2)更改默认窗体Form1 的Name 属性为Frm_Main,在该窗体中添加一个TextBox 控件,用来显示加密 或解密文件的路径;添加一个OpenFileDialog 控件,用来选择要加密或解密的文件和打开密钥的图片;添加4 个Button 控件,分别用来执行加密、解密、打开文件和打开图片操作;添加一个PictureBox 控件,用于显示密 钥图片。 (3)程序主要代码如下。 单击“加密”按钮,实现利用图片对文本文件进行加密的功能,“加密”按钮的Click 事件的代码如下: private void button3_Click(object sender, EventArgs e) { try { if (pictureBox1.ImageLocation==null) //判断是否选择了图片 { MessageBox.Show("请选择一幅图片用于加密"); return; } //如果没有选择则弹出提示 if (textBox1.Text == "") //若未选择需要加密的文件 { MessageBox.Show("请选择加密文件路径"); return; } //如果没有选择则弹出提示 //图片流 FileStream fsPic = new FileStream(pictureBox1.ImageLocation, FileMode.Open, FileAccess.Read); //加密文件流 FileStream fsText = new FileStream(textBox1.Text, FileMode.Open, FileAccess.Read); //初始化对称算法的密钥和向量 byte[] bykey = new byte[16]; //定义存储密钥的字节数组 byte[] byIv = new byte[8]; //定义存储向量的字节数组 fsPic.Read(bykey, 0, 16); //把图片流写入密钥缓冲区 fsPic.Read(byIv, 0, 8); //把图片流写入向量缓冲区 //临时加密文件 string strPath = textBox1.Text; //加密文件的路径 int intLent = strPath.LastIndexOf("\\") + 1; int intLong = strPath.Length; string strName = strPath.Substring(intLent, intLong - intLent); //要加密的文件名称 string strLinPath = "C:\\" + strName; //临时加密文件路径 FileStream fsOut = File.Open(strLinPath, FileMode.Create, FileAccess.Write); //开始加密,首先创建RC2CryptoServiceProvider 对象 RC2CryptoServiceProvider desc = new RC2CryptoServiceProvider(); BinaryReader br = new BinaryReader(fsText); //创建BinaryReader 对象 //创建CryptoStream 对象,用于写入临时加密文件 CryptoStream cs = new CryptoStream(fsOut, desc.CreateEncryptor(bykey, byIv), CryptoStreamMode.Write); cs.Write(br.ReadBytes((int)fsText.Length), 0, (int)fsText.Length); //写入加密流 cs.FlushFinalBlock(); cs.Flush(); cs.Close(); fsPic.Close(); fsText.Close(); fsOut.Close(); File.Delete(textBox1.Text.TrimEnd()); //删除原文件 File.Copy(strLinPath, textBox1.Text); //复制加密文件 File.Delete(strLinPath); //删除临时文件 MessageBox.Show("加密成功"); pictureBox1.ImageLocation = null; textBox1.Text = ""; } catch (Exception ee) { MessageBox.Show(ee.Message); } } 第19章 加密与解密技术 851 单击“解密”按钮,实现利用图片对加密的文本文件进行解密的功能,“解密”按钮的Click事件的代码如下: private void button4_Click(object sender, EventArgs e) { try { //图片流 FileStream fsPic = new FileStream(pictureBox1.ImageLocation, FileMode.Open, FileAccess.Read); //解密文件流 FileStream fsOut = File.Open(textBox1.Text, FileMode.Open, FileAccess.Read); //初始化对称算法的密钥和向量 byte[] bykey = new byte[16]; //定义存储密钥的字节数组 byte[] byIv = new byte[8]; //定义存储向量的字节数组 fsPic.Read(bykey, 0, 16); //把图片流写入密钥缓冲区 fsPic.Read(byIv, 0, 8); //把图片流写入向量缓冲区 //创建临时解密文件 string strPath = textBox1.Text; //加密文件的路径 int intLent = strPath.LastIndexOf("\\") + 1; //获取不含文件名的路径长度 int intLong = strPath.Length; //获取含文件名的路径长度 //获取要解密文件的名称,即加密文件的名称 string strName = strPath.Substring(intLent, intLong - intLent); string strLinPath = "C:\\" + strName; //临时解密文件路径 FileStream fs = new FileStream(strLinPath, FileMode.Create, FileAccess.Write); //开始解密,首先创建RC2CryptoServiceProvider 对象 RC2CryptoServiceProvider desc = new RC2CryptoServiceProvider(); //创建CryptoStream 对象,用于读取加密文件 CryptoStream csDecrypt = new CryptoStream(fsOut, desc.CreateDecryptor(bykey, byIv), CryptoStreamMode.Read); BinaryReader sr = new BinaryReader(csDecrypt); //创建BinaryReader 对象 BinaryWriter sw = new BinaryWriter(fs); //创建BinaryWriter 对象 sw.Write(sr.ReadBytes(Convert.ToInt32(fsOut.Length))); //写入解密流 sw.Flush(); sw.Close(); sr.Close(); fs.Close(); fsOut.Close(); fsPic.Close(); csDecrypt.Flush(); File.Delete(textBox1.Text.TrimEnd()); //删除原文件 File.Copy(strLinPath, textBox1.Text); //复制加密文件 File.Delete(strLinPath); //删除临时文件 MessageBox.Show("解密成功"); //弹出提示信息 pictureBox1.ImageLocation = null; //清空图片 textBox1.Text = ""; //清空文本框 } catch (Exception ee) //如果出现异常 { MessageBox.Show(ee.Message); //输出异常 } } 秘 笈心法 心法领悟581:如何去除字符串尾空格? 去除字符串尾空格需要使用string 类的Trim 方法,该方法用来从字符串的开始和末尾处移除空白字符的所 有匹配项。例如,下面的代码用来去掉textBox1 文本框中字符串的尾空格,并将结果显示在textBox2 文本框中: textBox2.Text = textBox1.Text.Trim(); 实例582 对文件进行加密保护 光盘位置:光盘\MR\19\582 高级 趣味指数: 实 例说明 随着计算机的普及,文件的安全越来越重要,本实例使用C#制作了一个对文件进行加密保护的实例。运行 C#开发实战1200 例(第II卷) 852 本实例,选择要加密或解密的文件,用程序来判断是否是加密过的文件, 如果不是,输入加密密码,单击“加密”按钮,加密已选择的文件;如果 是,输入解密密码,单击“解密”按钮,解密选择的加密文件。实例运行 效果如图19.12 所示。 关 键技术 本实例制作对文件进行加密保护程序时,首先选择要加密或解密的文 件,并输入加密或解密密码,然后启动一个新的线程,使用输入的密码对 指定的文件进行加密或解密操作。另外,如果对文件执行的是加密操作,则加密成功后删除原文件。具体实现 过程中,主要用到了DES 类的CreateEncryptor 和CreateDecryptor 方法、CryptoStream 类的构造函数及其Write 方法。  说明:关于DES 类的CreateEncryptor 方法和CreateDecryptor 方法、CryptoStream 类的构造函数及其Write 方法的详细讲解,请参见实例575中的关键技术。 设 计过程 (1)打开Visual Studio 2008 开发环境,新建一个Windows窗体应用程序,并将其命名为ProtectFile。 (2)更改默认窗体Form1 的Name 属性为Frm_Main,在该窗体中添加一个OpenFileDialog 控件,用来显 示“打开”对话框添加两个TextBox 控件,分别用来显示选择的文件路径和输入加密、解密密码;添加3 个 Button控件,分别用来执行选择加密或解密的文件、加密文件和解密文件操作;添加一个ProgressBar控件,用 来显示加密或解密的进度。 (3)程序主要代码如下。 Frm_Main 窗体加载时,首先将加密文件
没法下载,到这里折腾一把试试。 本文由abc2253130贡献 doc文档可能在WAP端浏览体验不佳。建议您优先选择TXT,或下载源文件到本机查看。 C#(WINFORM)学习 一、 C#基础 基础 类型和变量 类型和变量 类型 C# 支持两种类型:“值类型”和“引用类型”。值类型包括简单类型(如 char、int 和 float 等)、枚举类型和结构类型。引用类型包括类 (Class)类 型、接口类型、委托类型和数组类型。 变量的类型声明 变量的类型声明 每个变量必须预先声明其类型。如 int a; int b = 100; float j = 4.5; string s1; 用 object 可以表示所有的类型。 预定义类型 下表列出了预定义类型,并说明如何使用。 类型 object 说明 所有其他类型的最终 基类型 字符串类型; 字符串是 Unicode 字符序列 8 位有符号整型 16 位有符号整型 32 位有符号整型 64 位有符号整型 示例 object o = null; 范围 string sbyte short int long string s = "hello"; sbyte val = 12; short val = 12; int val = 12; long val1 = 12; -128 到 127 -32,768 到 32,767 -2,147,483,648 2,147,483,647 -9,223,372,036,854,775,808 到 第1页 C#(WINFORM)学习 long val2 = 34L; 到 9,223,372,036,854,775,807 byte ushort 8 位无符号整型 16 位无符号整型 byte val1 = 12; ushort val1 = 12; uint val1 = 12; uint 32 位无符号整型 uint val2 = 34U; ulong val1 = 12; ulong val2 = 34U; ulong 64 位无符号整型 ulong val3 = 56L; ulong val4 = 78UL; float 单精度浮点型 float val = 1.23F;7 位 double val1 = 1.23; double 双精度浮点型 double val2 = ±5.0 × 10?324 ±1.7 × 10 308 0 到 255 0 到 65,535 0 到 4,294,967,295 0 到 18,446,744,073,709,551,615 ±1.5 × 10?45 ±3.4 × 10 38 到 到 4.56D;15-16 布尔型;bool 值或为 真或为假 字符类型;char 值是 一个 Unicode 字符 精确的小数类型, 具有 28 个有效数字 bool val1 = true; bool val2 = false; char val = 'h'; decimal val = bool char decimal DateTime ±1.0 × 10?28 ±7.9 × 10 28 到 1.23M;28-29 变量转换 简单转换: float f = 100.1234f; 可以用括号转换: short s = (short)f 也可以利用 Convert 方法来转换: string s1; s1=Convert.ToString(a); MessageBox.Show(s1); 常用 Convert 方法有: 第2页 C#(WINFORM)学习 C# Convert.ToBoolean Convert.ToByte Convert.ToChar Convert.ToDateTime Convert.ToDecimal Convert.ToDouble Convert.ToInt16 Convert.ToInt32 Convert.ToInt64 Convert.ToSByte Convert.ToSingle Convert.ToString Convert.ToUInt16 Convert.ToUInt32 Convert.ToUInt64 备注 Math 类 常用科学计算方法: C# Math.Abs Math.Sqrt Math.Ro

16,554

社区成员

发帖
与我相关
我的任务
社区描述
VB技术相关讨论,主要为经典vb,即VB6.0
社区管理员
  • VB.NET
  • 水哥阿乐
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧