【开源项目SugarSite】ASP.NET MVC+ Layui+ SqlSugar+RestSharp项目讲解 - WebEnh - 博客园

mikel阅读(1721)

来源: 【开源项目SugarSite】ASP.NET MVC+ Layui+ SqlSugar+RestSharp项目讲解 – WebEnh – 博客园

SugarSite一个前端支持移动端的企业网站,目前只支持了简单功能,后续还会加上论坛等。

源码GIT地址:

 https://github.com/sunkaixuan/SugarSite

技术介绍

Layui

个人而言不喜欢引用一堆东西,越简洁越好,layui正好能够满足我的这种需求,它是一款轻量级UI,JS部分都是采用模块化设计(AMD) ,对移动端支持比较不错。

唯 一不足是目前支持的组件有些少,需要有一定前端扩展能力的人才可以顺心使用。

用法:

例如我想用form.js和uploda.js我只需要写use(form,upload)(如下例代码所示),而不是引用两个JS文件

复制代码
复制代码
/*
  Demo1.js
  使用Layui的form和upload组件
*/
layui.use(['form', 'upload'], function(){  //如果只加载一个组件,可以不填数组。如:layui.use('form')
  var form = layui.form() //获取form组件
  ,upload = layui.uplaod; //获取upload组件
  
  //监听提交按钮
 
});
复制代码
复制代码

 

SQLSugar

一款高性能轻量级并且功能强大的ORM框架,支持多种数据库,支持.NET CORE 。MySQL版支持了读写分离,SQL版支持了并行计算。

ASP.NET 4.+ ASP.NET Core 说明 依赖
SqlSugar.dll SqlSugarCore.dll SQLServer ORM
MysqlSugar.dll MysqlSugarCore.dll MySql ORM MySql.Data.dll
SqliteSugar.dll SqliteSugarCore.dll Sqlite ORM System.Data.SQLite.dll

SQLite.Interop.dll(Core版不需要)

OracleSugar.dll Oracle ORM Oracle.ManagedDataAccess.dll
SqlSugarRepository.dll SQLServer MySql Sqlite Oracle 四合一 MySql.Data.dll

System.Data.SQLite.dll

Oracle.ManagedDataAccess.dll

SQLite.Interop.dll

 

 

RestSharp

在我项目中作用与WCF相近,面向服务编程的一个核心要素,相比WCF更为简单更为轻量,只支持HTTP协议

复制代码
复制代码
var client = new RestClient("http://localhost/home/getjson");
// client.Authenticator = new HttpBasicAuthenticator(username, password);

var request = new RestRequest("resource/{id}", Method.POST);
request.AddParameter("name", "value"); // 添加请求参数
request.AddUrlSegment("id", "123"); // 添加 token 

//添加HTTP头
request.AddHeader("header", "value");

// 添加文件
request.AddFile(path);

// 执行请求
IRestResponse response = client.Execute(request);
var content = response.Content; // 返回请求对象

// or automatically deserialize result
// return content type is sniffed but can be explicitly set via RestClient.AddHandler();
RestResponse<Person> response2 = client.Execute<Person>(request);
var name = response2.Data.Name;

//异步支持
client.ExecuteAsync(request, response => {
    Console.WriteLine(response.Content);
});


var asyncHandle = client.ExecuteAsync<Person>(request, response => {
    Console.WriteLine(response.Data.Name);
});

asyncHandle.Abort();
复制代码
复制代码

 

采用的设计思想

从古至今设计模式都是越复杂的大家越喜欢学,哪怕是学了完全都看不懂是个什么东西,就认为这技术高明,可能写的人自个都没明白,而相反代码写的越多的人越想写的简单。

模式这种东西就没有好坏之分:

不同人用不同的模式发挥出来的水平也不一样

 

我的领悟

嵌套逻辑不能超过3层,如果不符合这个约束在美的写法都要让步

1.冗余代码只要好维护也是可以接受的,复制粘贴一把凌,因为简单的逻辑而导致了代码的冗余,如果要做的不冗余那写法就要复杂的多,根据情况不同利弊自已选择,鱼和熊掌很多时候是不能兼得的。

2.一定要以业务为核心分层

3.易读的代码和改动少的写法有冲突的时候我会采用易读写法(别人都看不懂,还谈什么可维护性,自已做那是无所谓)

 

代码讲解

代码结构图:

我称这种模式为:指挥官模式

 

称词解释:

ViewAction :类型为 ActionResult类型的Action

ApiAction: 类型为JsonResult类型的Action,在这里作为一个业务接口使用

Pack: 为一个业务块,并且业务块和业务块之间是隔离的,每个业务块有多个 ApiAction 和多个ViewAction,

业务块与业务块之间的通信用的是RestSharp调用其它Pack的

Outsourcing:业务块中的一些公用代码,可以是一个类也可以是一个文件夹,根据项目复杂度而定

 

这种架构模式和传统三层比起来有3大优势

1.分层容易并且代码更清晰

以前写法是以数据表作为服务,如果是SOA架构还要在抽象一层,当然一个复杂业务会有十张以上的表处理,便会出现这种垃机代码有几张表会出现几个Service

复制代码
复制代码
        private x1 X1Service;
        private x2 X2Service;
        private X3 X3Service;
        public DocContentController(x1 X1Service, x3 X1Service, x4X1Service) {
            this.X1Service = X1Service;
            this.X2Service = X2Service;
            this.X3Service = X4Service;
        }
复制代码
复制代码

现在写法,直接获取一个处理完的业务接口便可以,而不是获取每个细的表服务。

_service.Command<HomeOutsourcing, ResultModel<DocResult>>((o, api) =>
{
                var DocLIST= api.Get(Url.Action("GetDoc"), new { typeId = typeId });
 });

 

2.可以一套代码多平台使用

因为都是基于ApiAction如果权限合理完全可以当移动端接口,无形中已经是SOA架构。

 

 3.层次简单

简单到比三层更精简

 

完成功能预览

前端

前端完美支持了所有主流移动端

后台

后台简单大方,没有为UI去设计,实用为主,发布IIS后能够验出不错的流畅感

 

目前只完成了基本的功能,后续会将这个开源项目一直写下去

 

喜欢就推荐一下

 

源码GIT地址:

 https://github.com/sunkaixuan/SugarSite

thinkphp3.x中session方法的用法分析

mikel阅读(698)

本文实例讲述了thinkphp3.x中session方法的用法。分享给大家供大家参考,具体如下:

一、Session方法用于Session 设置、获取、删除和管理操作。 Session 用于Session 设置、获取、删除和管理操作

用法 session($name, $value=”)

参数 name(必须):如果传入数组 则表示进行session初始化,如果传入null表示清空当前session,如果是字符串则表示session赋值、获取或者操作。

Value(可选):要设置的session值,如果传入null表示删除session,默认为空字符串

返回值 根据具体的用法返回不同的值

session函数是一个多元化操作函数,传入不同的参数调用可以完成不同的功能操作,包括下面一些功能。

二、session初始化设置

如果session方法的name参数传入数组则表示进行session初始化设置,例如:

1
session(array('name'=>'session_id','expire'=>3600));

支持传入的session参数包括:

id session_id值
name session_name 值
path session_save_path 值
prefix session 本地化空间前缀
expire session.gc_maxlifetime 设置值
domain session.cookie_domain 设置值
use_cookies session.use_cookies 设置值
use_trans_sid session.use_trans_sid 设置值
cache_limiter session_cache_limiter设置值
cache_expire session_cache_expire设置值
type session hander类型,可以使用hander驱动扩展

Session初始化设置方法无需手动调用,在App类的初始化工作结束后会自动调用,通常项目只需要配置SESSION_OPTIONS参数即可,SESSION_OPTIONS参数的设置是一个数组,支持的索引名和前面的session初始化参数相同。

默认情况下,初始化之后系统会自动启动session,如果不希望系统自动启动session的话,可以设置SESSION_AUTO_START为false,例如:

1
'SESSION_AUTO_START' =>false

关闭自动启动后可以项目的公共文件或者在控制器中通过手动调用session_start或者session(‘[start]’) 启动session。

三、session赋值

Session赋值比较简单,直接使用:

1
session('name','value'); //设置session

相当于:

1
$_SESSION['name'] = 'value';

四、session取值

Session取值使用:

1
$value = session('name');

相当于使用:

1
$value = $_SESSION['name'];

五、session删除

1
session('name',null); // 删除name

相当于:

1
unset($_SESSION['name']);

要删除所有的session,可以使用:

1
session(null); // 清空当前的session

相当于:

1
$_SESSION = array();

六、session判断

要判断一个session值是否已经设置,可以使用

1
session('?name');

用于判断名称为name的session值是否已经设置

相当于:

1
isset($_SESSION['name']);

七、session管理

session方法支持一些简单的session管理操作,用法如下:

1
session('[操作名]');

支持的操作名包括:

start 启动session
pause 暂停session写入
destroy 销毁session
regenerate 重新生成session id

使用示例如下:

1
2
3
4
session('[pause]'); // 暂停session写入
session('[start]'); // 启动session
session('[destroy]'); // 销毁session
session('[regenerate]'); // 重新生成session id

八、本地化支持

如果在初始化session设置的时候传入prefix参数或者单独设置了SESSION_PREFIX参数的话,就可以启用本地化session管理支持。启动本地化session后,所有的赋值、取值、删除以及判断操作都会自动支持本地化session。

本地化session支持开启后,生成的session数据格式由原来的 $_SESSION[‘name’] 变成 $_SESSION[‘前缀’][‘name’]
假设前缀设置为think,则

赋值操作:

1
session('name','value'); //设置session

相当于:

1
$_SESSION['think']['name'] = 'value';

取值操作:

1
$value = session('name');

相当于使用:

1
$value = $_SESSION['think']['name'];

删除操作:

1
session('name',null);

相当于:

1
unset($_SESSION['think']['name']);

清空操作:

1
session(null);

相当于:

1
unset($_SESSION['think']);

判断操作:

1
session('?name');

相当于:

1
isset($_SESSION['think']['name']);

thinkphp无法登陆,session跨页后值为空-代潇瑞博客

mikel阅读(1217)

 

来源: thinkphp无法登陆,session跨页后值为空-代潇瑞博客

我已经出现过两次这种问题了,出现了两次就说明第一次没有解决彻底,所以表示thinkphp这个跨页后session为空而无法登陆的问题牵扯很多方面的问题了。经过这两次的研究,我觉得基本上能真正解决它了。

第一次出现的时候,我以为是目录不可写,检查了半天没发现问题,于是各种百度,才发现别人也有遇得类似问题,就是跨页传递session为空。(温馨提示:不喜欢听流水账的可以略过以下两段,直接看下面的解决措施。)我调试了一下程序,将登陆跳转后的页面print_r($_SESSION),果然为空值。最后查找资料说是要把 use_trans_sid 的值改为 1,于是在配置文件中加了一行:’SESSION_OPTIONS’ => array(‘use_trans_sid’=>1),然后再登陆的时候就好了。

第二次,换到另一个环境的时候又出现问题了,于是我又到网上查资料,很可惜,这次找了半天都没有解决,瞬间感慨国内编程这一块的资源匮乏程度还是挺严重的啊,所以我只有自己摸索了。首先排除目录权限和其他一系列问题后,我意识到这次的问题应该也是php设置的问题。于是我把本地的phpinfo和出问题那台虚拟空间的phpinfo输出来,一行一行比较session那块选项。最后我发现有一行配置不一样,如下图:

phpinfo

这里的session.use_only_cookies的值是on,也就是1,而我本地的是off。我马上意识到是这里的问题了,于是又在配置文件中加了一个参数 ‘SESSION_OPTIONS’ => array(‘use_trans_sid’=>1,’use_only_cookies’=>0),同时还要在thinkphp/Common/functions.php的550行左右加上一句if(isset($name[‘use_only_cookies’]))  ini_set(‘session.use_only_cookies’, $name[‘use_only_cookies’]?1:0); 因为thinkphp默认没有定义这个选项。瞬间,又能登陆了。

session.use_only_cookies

经过这两次的问题,最后,代潇瑞博客总结出一下几点导致不能正常登陆、session传值为空的原因:

1. 首先检查存放session的目录是否可写。

2. 如果您用的是空间的话,有些空间文件数目上线也有限制,比如一个200MB的空间,空间单个文件数不能超过45000,当文件满后,就不能在写入文件了,如果你session路径设置在web目录下,也就会影响session无法写入了。

3. 就是将“use_trans_sid”的值设为1,可以在配置文件中加入“SESSION_OPTIONS’ => array(‘use_trans_sid’=>1)”这行代码,让session可以跨页传值。

4. 这个是最不容易发现的,我找了好半天,网上也没有提到这个。也是session的设置选项问题,在第3点的基础上加一个“’use_only_cookies’=>0”选项,即:“SESSION_OPTIONS’ => array(‘use_only_cookies’=>0,’use_trans_sid’=>1)”,同时还要在thinkphp/Common/functions.php的550行左右加上一句if(isset($name[‘use_only_cookies’]))  ini_set(‘session.use_only_cookies’, $name[‘use_only_cookies’]?1:0); 因为thinkphp默认没有定义这个选项。

不能正常登陆、session传值为空的问题大概就是这几个因素了,如果还有其他原因,我会再次的补充完善。如果您有什么不清楚的,也欢迎与代潇瑞博客交流。

 

文章出自:http://www.daixiaorui.com/read/99.html 本站所有文章,除注明出处外皆为原创,转载请注明本文地址,版权所有。

 

sql2008“备份集中的数据库备份与现有的xx数据库不同”解决方法 - DeepSky_ - 博客园

mikel阅读(916)

来源: sql2008“备份集中的数据库备份与现有的xx数据库不同”解决方法 – DeepSky_ – 博客园

因为是在另一台电脑对同名数据库做的备份,用常规方法还原,提示不是相同数据库,不让还原,在网上找到下面的方法解决了:

一、右击系统数据库master,新建查询

执行以下SQL代码:


RESTORE DATABASE xxx
FROM DISK = 'E:\DB\xxx.bak' --bak文件路径
with replace,
MOVE 'xxx' TO 'D:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLServer\MSSQL\DATA\xxx.mdf', --mdf文件路径
MOVE 'xxx_log' TO 'D:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLServer\MSSQL\DATA\xxx.ldf' --ldf文件路径

注释:xxx是你需要还原的数据库名称,xxx.bak是你需要还原的备份文件。

二、上面方法执行成功后,只有部分的表结构已经还原,而且表中没有数据,这时就可以用系统默认的方法再用xxx.bak文件还原一次数据库就大功告成了,必须要选中覆盖还原哦。

thinkphp设置session无效的问题 - CSDN博客

mikel阅读(1207)

 

来源: thinkphp设置session无效的问题 – CSDN博客

thinkphp的session设置周期是无效的;

直接的影响就是无法保留用户的登陆状态;

用thinkphp开发的项目;关闭浏览器后用户就退出了;

即便设置了session周期也没作用;

这个bug存在很久了;但是thinkphp官网一直没处理更新;

吐槽完毕;下面来解决这个bug;

首先需要在 /Thinkphp/Common/funtion.php 公告函数的第1213行添加如下内容;

如果不是在1213行;就搜索gc_maxlifetime

1
2
3
4
5
// 1213行原代码
if(isset($name['expire']))          ini_set('session.gc_maxlifetime'$name['expire']);
// 改成如下代码
if(isset($name['expire']))          ini_set('session.gc_maxlifetime'$name['expire']);ini_set('session.cookie_lifetime'$name['expire']);

原代码:

白俊遥博客

更改后的代码:

白俊遥博客

然后在配置项/Application/Common/conf/config.php中添加如下代码

1
2
3
4
5
6
7
//***********************************SESSION设置**********************************
    'SESSION_OPTIONS'         =>  array(
        'name'                =>  'BJYSESSION',                    //设置session名
        'expire'              =>  24*3600*15,                      //SESSION保存15天
        'use_trans_sid'       =>  1,                               //跨页传递
        'use_only_cookies'    =>  0,                               //是否只开启基于cookies的session的会话方式
    ),

ok;大功告成;

//***********************************不怎么华丽的分割线**********************************

后来还是不断有亲们的session周期失效;

特贴一份设置正确的项目连接;

bjyadmin:http://git.oschina.net/shuaibai123/thinkphp-bjyadmin

可以尝试下载bjyadmin到本地;然后在bjyadmin上测试;

如果bjyadmin的session也失效;那可能是本地环境有问题;

如果bjyadmin的session正常;而自己的项目session失效;

那就可以确认是自己项目的session配置有错误的地方;

照着bjyadmin抄配置即可;

ThinkPHP5在WAMP环境下Session无法跨页传递的问题 - CSDN博客

mikel阅读(1532)

在用ThinkPHP5的过程中,要用到Session。 但是我的项目出现了如下问题,在http://localhost/index/index/index页面下,提交表单,表单操作是在http://localhost/index/index/dosubmit.html?fname=123123&lname=123123下完成的,在表单提交的处理方法里用Session::set()方法保存了一个数据

来源: ThinkPHP5在WAMP环境下Session无法跨页传递的问题 – CSDN博客

在用ThinkPHP5的过程中,要用到Session。
但是我的项目出现了如下问题,在http://localhost/index/index/index页面下,提交表单,表单操作是在http://localhost/index/index/dosubmit.html?fname=123123&lname=123123下完成的,在表单提交的处理方法里用Session::set()方法保存了一个数据。
很奇怪的是,两个页面中获取Session_id,都是一样的ID,但是在http://localhost/index/index/dosubmit.html这个页面下,我是能从Session中取出数据的,但是在http://localhost/index/index/index页面下,使用Session::get()方法,就什么也取不出来。

这个问题的解决主要参考了
http://www.daixiaorui.com/read/99.html
但是按照他的方法我没有解决,但是他给了我思路,就是用查看phpinfo。
创建一下文件phpinfo.php

<?php
phpinfo();
?>
  • 1
  • 2
  • 3

把这个文件放到thinkphp5框架下的public文件夹下,然后就能够在浏览器中访问这个页面了,我的访问路径是(我配置了url,如果thinkphp5没配置过,访问路径应该是http://localhost/tp5/public/phpinfo.php):
http://localhost/phpinfo.php
然后搜Session,我能正确跨页获取Session,修改了以下配置
这里写图片描述
我觉得主要是最优一个use_trans_id这个属性改为1以后生效的。
至于如何修改use_trans_id,我不是在ThinkPHP5的配置文件里改的,我直接去修改了WAMP中PHP的php.ini文件。
修改方法:

这里写图片描述
然后用ctrl+F的方式,找到要修改的属性,改完之后,重启所有服务。
然后THinkPHP5就可以跨页面读取Session了。

后记:我在另一台机器上没有修改那么多属性,就是把php.ini的Session.auto_start给设置成1了,Session就能够跨页传递了。

.Net Winform开发笔记(三) 谈谈自制控件 - 周见智 - 博客园

mikel阅读(1009)

来源: .Net Winform开发笔记(三) 谈谈自制控件 – 周见智 – 博客园

末日这天写篇博客吧,既然没来,那就纪念一下。

这次谈谈自制控件,也就是自定义控件,先上图,再说

1.扩展OpenFileDialog,在OpenFileDialog中添加各种文件(.txt,.jpg,.excel等等)的预览功能

2.重写ListBox,增加折叠、鼠标背影、分类等功能

—————————–分割线————————————————————–

一、扩展OpenFileDialog

许多软件的打开对话框都有预览功能,最常见的就是图片预览,用鼠标选择一个图片文件后,右侧或者下侧就会有该图片的缩略图(photoshop中属于后者)。在winform编程中,有专门的打开文件对话框的类OpenFileDialog,但是他不提供文件预览功能,封装得实在太好。看看它公开那些接口

提到扩展,很多人可能想到继承它就可以扩展它,可惜OpenFileDialog声明为sealed,不允许从他继承。稍微底层一点的,想到可以通过Win32 API来修改它的显示方式,只可惜,如你所见,它根本没提供Handle属性,更别说HandleCreated、HandleDestroyed等事件了。那么怎么样子搞呢?其实答案还是通过Win32 API,只是我们取得它的句柄的方式要复杂一点而且调用API的时机隐晦了一点。

提示:

1.Win32 API操作窗体需要知道窗体的句柄;

2.不熟悉Win32编程的同学可以先上网查查资料,特别是不知道SetParent、SetWindowPos等API是干嘛的,我觉得以下的看不懂。

为什么说取得它的句柄复杂了一点?难道不是用“FindWindow”、“FindWindowEx”、“ EnumChildWindows”等获取OpenFileDialog的句柄,再用“SetParent”、“SetWindowPos”等API将.net控件(本例中是DataGridView控件,当然可以使其他任何一种)添加到OpenFileDialog中去?没错,以上列举出来的API都是基本要用到的,“只是用在什么地方、什么时候用”是个比较麻烦的问题,原因如下:

1)我们知道OpenfileDialog显示的是模式对话框,也就是说,一旦它ShowDialog(),它以下的代码是不会再执行的,具体原因是什么(我以后的博客会专门讲为什么),你现在可以理解为OpenFileDialog()方法会阻塞调用线程,既然阻塞了调用线程,那么我们再无法控制程序了(直到它返回),根本谈不上再调用API获取OpenFileDialog的句柄然后去操作它。如果有人会说,“我可以另开辟线程去取OpenFileDialog得句柄再操作它”,恩,我不否定这个方法,只是我想说,如果你真的按照这个方法去试,那么肯定会陷入泥潭。因为你不仅要取它的句柄,你还要监视OpenFIleDialog的一举一动,移动、缩放、用户鼠标点击选择文件、更改目录等,然后再操作.net控件(本例中是DataGridView控件,下同),让.net控件去适应OpenFileDialog的大小等等,你会发现你忙死了,甚至有的你根本监视不了,比如用户点击选择文件、更改目录。

2)就算我们能够在OpenFIleDialog显示之后,取得它的句柄,那么什么时候再调用其他API呢?比如什么时候调用SetWindowPos,让.net控件适应OpenFileDialog的大小变化?什么时候知道用户选择文件发生了变化?

所以,API方法什么时候用?用在什么地方?就是接下来要讨论的东西。

我不知道各位在使用各种框架的时候,对“框架”的理解到什么程度,我觉得可以总结成一句话“跟个2b似地注册一些事件,然后苦逼地去写好每一个回调方法,我们却不知道为啥要这样写”,不是么?既然这样,那么我们的API方法只要写在了正确的回调方法中,我们就能到达想要的目的了。考虑几个问题:

1)OpenFileDialog显示,我们向其中添加.net控件。我们什么时候知道它显示?

2)OpenFileDialog大小发生变化时,我们要更新.net控件以适应新的大小。我们什么时候知道OpenFileDialog的大小发生了变化?

3)OpenFileDialog中用户选择的文件发生了变化,我们需要知道新选择的文件路径,用来显示在.net控件中。我们怎么知道选择了什么文件?(这里选择文件指用户用鼠标在OpenFileDialog中单击选取,不是点击“确定”后。)

以上所有的问题,其实在一个地方都可以知道,那就是监听OpenFileDialog窗体的Windows消息,因为一个窗体的任何一个动作都伴随着一系列的Windows消息(这个可以用Spy++查看)。既然这样,那么我们可以在窗体处理Windows消息的回调方法中调用API方法了,也就是窗体的Control.WndProc方法中。之前已经说过了,OpenFileDialog声明为Sealed,提供的接口少之又少,我们几乎根本不可能接触到OpenFileDialog的WndProc,更谈不上监听Windows消息,然后调用API去操作它。这时候,NativeWindow该出场了,先来引用一下MSDN上对NativeWindow的解释:

“提供窗口句柄和窗口过程的低级封装。”

说了像没说一样,其实就是说,将一个窗口句柄与NativeWindow对象绑定后,该NativeWindow对象就能接收到这个窗体的所有消息。说到Windows消息,我想说一下Windows桌面应用程序的运行流程,其实如果看了我前一篇博客的同学应该有些了解,.Net Winform开发笔记(二)中基本提到了一些。为了配合本次讲解,我再次画了一张图

上图中,虚线框可以看做是一个.net中的Control类对象(或者其派生类,下同,控件即窗体、窗体即控件),正常情况下,Winform程序会按照1->2->3的步骤运行,当我们将Control类对象的Handle(就是我们常说的窗口句柄,做了一下封装)与一个NativeWIndow对象绑定后,程序不再按照1->2->3这样的顺序运行了,他会按照1->2-1->2-2->3这样运行,也就是说,NativeWindow对象可以拦截Control类对象的WIndows消息,我们完全可以在NativeWIndow中重写他的WndProc方法,像处理自己的Windows消息一样去处理Control类对象的消息。所以,我们就可以在NativeWindow对象的WndProc中调用我们的API方法。

接下来,上代码(代码只提供大概思路)

1.扩展对话框

View Code

复制代码
 1     public class MultiOpenFileDialog
 2     {
 3         #region fields
 4         private const SetWindowPosFlags UFLAGSHIDE =
 5         SetWindowPosFlags.SWP_NOACTIVATE |
 6         SetWindowPosFlags.SWP_NOOWNERZORDER |
 7         SetWindowPosFlags.SWP_NOMOVE |
 8         SetWindowPosFlags.SWP_NOSIZE |
 9         SetWindowPosFlags.SWP_HIDEWINDOW;
10         #endregion
11         public string FileName;
12         #region public methods
13         public DialogResult ShowDialog()
14         {
15             return ShowDialog(null);
16         }
17         public DialogResult ShowDialog(IWin32Window owner)
18         {
19             using (OpenFileDialog open = new OpenFileDialog())
20             {
21                 MedianForm median = new MedianForm(open);
22                 median.Show(owner);
23                 Win32.SetWindowPos(median.Handle, IntPtr.Zero, 0, 0, 0, 0, UFLAGSHIDE); //隐藏中间窗体
24                 DialogResult dialogresult = open.ShowDialog(median); //将median作为openfileDialog的owner
25                 median.Close();
26                 if (dialogresult == DialogResult.OK)
27                 {
28                     FileName = open.FileName;
29                 }
30                 return dialogresult;
31             }
32         }
33         #endregion
34     }
复制代码

 

2.监听Dialog的NativeWindow

View Code

 

3.监听子控件的NativeWindow

View Code

复制代码
 1     class ChildControlNativeWindow : NativeWindow,IDisposable
 2     {
 3         IntPtr handle; //需要被监听消息的子控件句柄
 4         public ChildControlNativeWindow(IntPtr handle)
 5         {
 6             this.handle = handle;
 7             AssignHandle(handle);
 8         }
 9 
10         #region override methods
11         protected override void WndProc(ref Message m)
12         {
13             switch (m.Msg)
14             {
15                 case (int)Msg.WM_NOTIFY:
16                     OFNOTIFY ofNotify = (OFNOTIFY)Marshal.PtrToStructure(m.LParam, typeof(OFNOTIFY));
17                     if (ofNotify.hdr.code == (uint)DialogChangeStatus.CDN_SELCHANGE) //openfileDialog选择文件发生变化
18                     {
19                         StringBuilder file = new StringBuilder(256);
20                         Win32.SendMessage(Win32.GetParent(handle), (int)DialogChangeProperties.CDM_GETFILEPATH, (int)256, file);
21                         if (SelectFileChanged != null)
22                             SelectFileChanged(file); //通知注册者
23                     }
24                     else if (ofNotify.hdr.code == (uint)DialogChangeStatus.CDN_FOLDERCHANGE) //openfileDialog选择目录发生变化
25                     {
26                         StringBuilder path = new StringBuilder(256);
27                         Win32.SendMessage(Win32.GetParent(handle), (int)DialogChangeProperties.CDM_GETFOLDERPATH, (int)256, path);
28                         if (SelectPathChanged != null)
29                             SelectPathChanged(path); //通知注册者
30                     }
31                     break;
32             }
33             base.WndProc(ref m);
34         }
35         #endregion
36 
37         #region delegate
38         public delegate void SelectFileChangedEventHandler(StringBuilder file); 
39         public delegate void SelectPathChangedEventHandler(StringBuilder path);
40         #endregion
41 
42         #region events
43         public event SelectFileChangedEventHandler SelectFileChanged; //当openfileDialog的选择文件发生变化时发生
44         public event SelectPathChangedEventHandler SelectPathChanged; //当openfileDialog的选择目录发生变化时发生
45         #endregion
46 
47         #region IDisposable 成员
48 
49         public void Dispose()
50         {
51             ReleaseHandle(); //终止与子控件句柄的关联
52         }
53 
54         #endregion
55     }
复制代码

 

4.中间过渡窗体,用来获取OpenFileDialog的句柄

View Code

复制代码
 1     class MedianForm : Form
 2     {
 3         OpenFileDialog open = null; 
 4         DialogNativeWindow dialognative;
 5 
 6         public MedianForm(OpenFileDialog open)
 7         {
 8             this.open = open;
 9             StartPosition = FormStartPosition.Manual;
10             Location = new System.Drawing.Point(-1000, -1000); //避免界面闪烁
11         }
12         protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
13         {
14             if (dialognative != null)
15             {
16                 dialognative.Dispose(); //释放资源
17             }
18             base.OnClosing(e);
19         }
20         protected override void WndProc(ref Message m)
21         {
22             if (m.Msg == (int) Msg.WM_ACTIVATE)
23             {
24                 dialognative = new DialogNativeWindow(m.LParam, open); //m.LParam为要打开的窗口句柄,开始监听OpenFileDialog的Windows消息
25             }
26             base.WndProc(ref m);
27         }
28     }
复制代码

 

5.访问Excel文件的类

View Code

复制代码
 1     class OledbManager
 2     {
 3         OleDbConnection conn;
 4         /// <summary>
 5         /// 连接excel文件
 6         /// </summary>
 7         /// <param name="connstr"></param>
 8         /// <returns></returns>
 9         public bool Connect(string connstr)
10         {
11             try
12             {
13                 conn = new OleDbConnection(connstr);
14                 conn.Open();
15                 return true;
16             }
17             catch
18             {
19                 return false;
20             }
21         }
22         /// <summary>
23         /// 查找第一张表中的数据
24         /// </summary>
25         /// <returns></returns>
26         public DataTable SearchTable()
27         {
28             try
29             {
30                 DataTable tb = new DataTable();
31                 string sql = "select * from [Sheet1$]";
32                 OleDbCommand com = new OleDbCommand(sql, conn);
33                 OleDbDataAdapter adp = new OleDbDataAdapter(com);
34                 adp.Fill(tb);
35                 return tb;
36             }
37             catch
38             {
39                 return null;
40             }
41         }
42     }
复制代码

 

6.几个Win32结构体、枚举类型以及API声明(本代码参考CodeProject上的一篇文章)

View Code

复制代码
  1     public static class Win32
  2     {
  3         #region Delegates
  4         public delegate bool EnumWindowsCallBack(IntPtr hWnd, int lParam);
  5         #endregion
  6 
  7         #region USER32
  8         [DllImport("user32.dll", CharSet = CharSet.Auto)]
  9         public static extern IntPtr GetParent(IntPtr hWnd);
 10         [DllImport("User32.Dll")]
 11         public static extern int GetDlgCtrlID(IntPtr hWndCtl);
 12         [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
 13         public static extern int MapWindowPoints(IntPtr hWnd, IntPtr hWndTo, ref POINT pt, int cPoints);
 14         [DllImport("user32.dll", SetLastError = true)]
 15         public static extern bool GetWindowInfo(IntPtr hwnd, out WINDOWINFO pwi);
 16         [DllImport("User32.Dll")]
 17         public static extern void GetWindowText(IntPtr hWnd, StringBuilder param, int length);
 18         [DllImport("User32.Dll")]
 19         public static extern void GetClassName(IntPtr hWnd, StringBuilder param, int length);
 20         [DllImport("user32.Dll")]
 21         public static extern bool EnumChildWindows(IntPtr hWndParent, EnumWindowsCallBack lpEnumFunc, int lParam);
 22         [DllImport("user32.Dll")]
 23         public static extern bool EnumWindows(EnumWindowsCallBack lpEnumFunc, int lParam);
 24         [DllImport("User32.dll", CharSet = CharSet.Auto)]
 25         public static extern bool ReleaseCapture();
 26         [DllImport("user32.dll", CharSet = CharSet.Auto)]
 27         public static extern IntPtr SetCapture(IntPtr hWnd);
 28         [DllImport("user32.dll", CharSet = CharSet.Auto)]
 29         public static extern IntPtr ChildWindowFromPointEx(IntPtr hParent, POINT pt, ChildFromPointFlags flags);
 30         [DllImport("user32.dll", EntryPoint = "FindWindowExA", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
 31         public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
 32         [DllImport("user32.dll")]
 33         public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
 34         [DllImport("user32.dll", CharSet = CharSet.Auto)]
 35         public static extern int PostMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
 36         [DllImport("user32.dll", CharSet = CharSet.Auto)]
 37         public static extern int PostMessage(IntPtr hWnd, int msg, int wParam, int lParam);
 38         [DllImport("user32.dll", CharSet = CharSet.Auto)]
 39         public static extern int SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
 40         [DllImport("user32.dll", CharSet = CharSet.Auto)]
 41         public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);
 42         [DllImport("user32.dll", CharSet = CharSet.Auto)]
 43         public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, StringBuilder param);
 44         [DllImport("user32.dll", CharSet = CharSet.Auto)]
 45         public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, char[] chars);
 46         [DllImport("user32.dll", CharSet = CharSet.Auto)]
 47         public static extern IntPtr BeginDeferWindowPos(int nNumWindows);
 48         [DllImport("user32.dll", CharSet = CharSet.Auto)]
 49         public static extern IntPtr DeferWindowPos(IntPtr hWinPosInfo, IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int Width, int Height, SetWindowPosFlags flags);
 50         [DllImport("user32.dll", CharSet = CharSet.Auto)]
 51         public static extern bool EndDeferWindowPos(IntPtr hWinPosInfo);
 52         [DllImport("user32.dll", CharSet = CharSet.Auto)]
 53         public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int Width, int Height, SetWindowPosFlags flags);
 54         [DllImport("user32.dll")]
 55         public static extern bool GetWindowRect(IntPtr hwnd, ref RECT rect);
 56         [DllImport("user32.dll")]
 57         public static extern bool GetClientRect(IntPtr hwnd, ref RECT rect);
 58         #endregion
 59     }
 60 
 61     #region SWP_Flags
 62     [Flags]
 63     public enum SWP_Flags
 64     {
 65         SWP_NOSIZE = 0x0001,
 66         SWP_NOMOVE = 0x0002,
 67         SWP_NOZORDER = 0x0004,
 68         SWP_NOACTIVATE = 0x0010,
 69         SWP_FRAMECHANGED = 0x0020, /* The frame changed: send WM_NCCALCSIZE */
 70         SWP_SHOWWINDOW = 0x0040,
 71         SWP_HIDEWINDOW = 0x0080,
 72         SWP_NOOWNERZORDER = 0x0200, /* Don't do owner Z ordering */
 73 
 74         SWP_DRAWFRAME = SWP_FRAMECHANGED,
 75         SWP_NOREPOSITION = SWP_NOOWNERZORDER
 76     }
 77     #endregion
 78 
 79     #region DialogChangeStatus
 80     public enum DialogChangeStatus : long
 81     {
 82         CDN_FIRST = 0xFFFFFDA7,
 83         CDN_INITDONE = (CDN_FIRST - 0x0000),
 84         CDN_SELCHANGE = (CDN_FIRST - 0x0001),
 85         CDN_FOLDERCHANGE = (CDN_FIRST - 0x0002),
 86         CDN_SHAREVIOLATION = (CDN_FIRST - 0x0003),
 87         CDN_HELP = (CDN_FIRST - 0x0004),
 88         CDN_FILEOK = (CDN_FIRST - 0x0005),
 89         CDN_TYPECHANGE = (CDN_FIRST - 0x0006),
 90     }
 91     #endregion
 92 
 93     #region DialogChangeProperties
 94     public enum DialogChangeProperties
 95     {
 96         CDM_FIRST = (0x400 + 100),
 97         CDM_GETSPEC = (CDM_FIRST + 0x0000),
 98         CDM_GETFILEPATH = (CDM_FIRST + 0x0001),
 99         CDM_GETFOLDERPATH = (CDM_FIRST + 0x0002),
100         CDM_GETFOLDERIDLIST = (CDM_FIRST + 0x0003),
101         CDM_SETCONTROLTEXT = (CDM_FIRST + 0x0004),
102         CDM_HIDECONTROL = (CDM_FIRST + 0x0005),
103         CDM_SETDEFEXT = (CDM_FIRST + 0x0006)
104     }
105     #endregion
106 
107     #region ImeNotify
108     public enum ImeNotify
109     {
110         IMN_CLOSESTATUSWINDOW = 0x0001,
111         IMN_OPENSTATUSWINDOW = 0x0002,
112         IMN_CHANGECANDIDATE = 0x0003,
113         IMN_CLOSECANDIDATE = 0x0004,
114         IMN_OPENCANDIDATE = 0x0005,
115         IMN_SETCONVERSIONMODE = 0x0006,
116         IMN_SETSENTENCEMODE = 0x0007,
117         IMN_SETOPENSTATUS = 0x0008,
118         IMN_SETCANDIDATEPOS = 0x0009,
119         IMN_SETCOMPOSITIONFONT = 0x000A,
120         IMN_SETCOMPOSITIONWINDOW = 0x000B,
121         IMN_SETSTATUSWINDOWPOS = 0x000C,
122         IMN_GUIDELINE = 0x000D,
123         IMN_PRIVATE = 0x000E
124     }
125     #endregion
126 
127     #region FolderViewMode
128     public enum FolderViewMode
129     {
130         Default = 0x7028,
131         Icon = Default + 1,
132         SmallIcon = Default + 2,
133         List = Default + 3,
134         Details = Default + 4,
135         Thumbnails = Default + 5,
136         Title = Default + 6,
137         Thumbstrip = Default + 7,
138     }
139     #endregion
140 
141     #region Enum DialogViewProperty
142     public enum DefaultViewType
143     {
144         Icons = 0x7029,
145         List = 0x702b,
146         Details = 0x702c,
147         Thumbnails = 0x702d,
148         Tiles = 0x702e,
149     }
150     #endregion
151 
152     #region ButtonStyle
153     public enum ButtonStyle : long
154     {
155         BS_PUSHBUTTON = 0x00000000,
156         BS_DEFPUSHBUTTON = 0x00000001,
157         BS_CHECKBOX = 0x00000002,
158         BS_AUTOCHECKBOX = 0x00000003,
159         BS_RADIOBUTTON = 0x00000004,
160         BS_3STATE = 0x00000005,
161         BS_AUTO3STATE = 0x00000006,
162         BS_GROUPBOX = 0x00000007,
163         BS_USERBUTTON = 0x00000008,
164         BS_AUTORADIOBUTTON = 0x00000009,
165         BS_PUSHBOX = 0x0000000A,
166         BS_OWNERDRAW = 0x0000000B,
167         BS_TYPEMASK = 0x0000000F,
168         BS_LEFTTEXT = 0x00000020,
169         BS_TEXT = 0x00000000,
170         BS_ICON = 0x00000040,
171         BS_BITMAP = 0x00000080,
172         BS_LEFT = 0x00000100,
173         BS_RIGHT = 0x00000200,
174         BS_CENTER = 0x00000300,
175         BS_TOP = 0x00000400,
176         BS_BOTTOM = 0x00000800,
177         BS_VCENTER = 0x00000C00,
178         BS_PUSHLIKE = 0x00001000,
179         BS_MULTILINE = 0x00002000,
180         BS_NOTIFY = 0x00004000,
181         BS_FLAT = 0x00008000,
182         BS_RIGHTBUTTON = BS_LEFTTEXT
183     }
184     #endregion
185 
186     #region ZOrderPos
187     public enum ZOrderPos
188     {
189         HWND_TOP = 0,
190         HWND_BOTTOM = 1,
191         HWND_TOPMOST = -1,
192         HWND_NOTOPMOST = -2
193     }
194     #endregion
195 
196     #region Static Control Styles
197     public enum StaticControlStyles : long
198     {
199         SS_LEFT = 0x00000000,
200         SS_CENTER = 0x00000001,
201         SS_RIGHT = 0x00000002,
202         SS_ICON = 0x00000003,
203         SS_BLACKRECT = 0x00000004,
204         SS_GRAYRECT = 0x00000005,
205         SS_WHITERECT = 0x00000006,
206         SS_BLACKFRAME = 0x00000007,
207         SS_GRAYFRAME = 0x00000008,
208         SS_WHITEFRAME = 0x00000009,
209         SS_USERITEM = 0x0000000A,
210         SS_SIMPLE = 0x0000000B,
211         SS_LEFTNOWORDWRAP = 0x0000000C,
212         SS_OWNERDRAW = 0x0000000D,
213         SS_BITMAP = 0x0000000E,
214         SS_ENHMETAFILE = 0x0000000F,
215         SS_ETCHEDHORZ = 0x00000010,
216         SS_ETCHEDVERT = 0x00000011,
217         SS_ETCHEDFRAME = 0x00000012,
218         SS_TYPEMASK = 0x0000001F,
219         SS_REALSIZECONTROL = 0x00000040,
220         SS_NOPREFIX = 0x00000080, /* Don't do "&" character translation */
221         SS_NOTIFY = 0x00000100,
222         SS_CENTERIMAGE = 0x00000200,
223         SS_RIGHTJUST = 0x00000400,
224         SS_REALSIZEIMAGE = 0x00000800,
225         SS_SUNKEN = 0x00001000,
226         SS_EDITCONTROL = 0x00002000,
227         SS_ENDELLIPSIS = 0x00004000,
228         SS_PATHELLIPSIS = 0x00008000,
229         SS_WORDELLIPSIS = 0x0000C000,
230         SS_ELLIPSISMASK = 0x0000C000
231     }
232     #endregion
233 
234     #region Combo Box styles
235     public enum ComboBoxStyles : long
236     {
237         CBS_SIMPLE = 0x0001,
238         CBS_DROPDOWN = 0x0002,
239         CBS_DROPDOWNLIST = 0x0003,
240         CBS_OWNERDRAWFIXED = 0x0010,
241         CBS_OWNERDRAWVARIABLE = 0x0020,
242         CBS_AUTOHSCROLL = 0x0040,
243         CBS_OEMCONVERT = 0x0080,
244         CBS_SORT = 0x0100,
245         CBS_HASSTRINGS = 0x0200,
246         CBS_NOINTEGRALHEIGHT = 0x0400,
247         CBS_DISABLENOSCROLL = 0x0800,
248         CBS_UPPERCASE = 0x2000,
249         CBS_LOWERCASE = 0x4000
250     }
251     #endregion
252 
253     #region Window Styles
254     public enum WindowStyles : long
255     {
256         WS_OVERLAPPED = 0x00000000,
257         WS_POPUP = 0x80000000,
258         WS_CHILD = 0x40000000,
259         WS_MINIMIZE = 0x20000000,
260         WS_VISIBLE = 0x10000000,
261         WS_DISABLED = 0x08000000,
262         WS_CLIPSIBLINGS = 0x04000000,
263         WS_CLIPCHILDREN = 0x02000000,
264         WS_MAXIMIZE = 0x01000000,
265         WS_CAPTION = 0x00C00000,
266         WS_BORDER = 0x00800000,
267         WS_DLGFRAME = 0x00400000,
268         WS_VSCROLL = 0x00200000,
269         WS_HSCROLL = 0x00100000,
270         WS_SYSMENU = 0x00080000,
271         WS_THICKFRAME = 0x00040000,
272         WS_GROUP = 0x00020000,
273         WS_TABSTOP = 0x00010000,
274         WS_MINIMIZEBOX = 0x00020000,
275         WS_MAXIMIZEBOX = 0x00010000,
276         WS_TILED = 0x00000000,
277         WS_ICONIC = 0x20000000,
278         WS_SIZEBOX = 0x00040000,
279         WS_POPUPWINDOW = 0x80880000,
280         WS_OVERLAPPEDWINDOW = 0x00CF0000,
281         WS_TILEDWINDOW = 0x00CF0000,
282         WS_CHILDWINDOW = 0x40000000
283     }
284     #endregion
285 
286     #region Window Extended Styles
287     public enum WindowExStyles
288     {
289         WS_EX_DLGMODALFRAME = 0x00000001,
290         WS_EX_NOPARENTNOTIFY = 0x00000004,
291         WS_EX_TOPMOST = 0x00000008,
292         WS_EX_ACCEPTFILES = 0x00000010,
293         WS_EX_TRANSPARENT = 0x00000020,
294         WS_EX_MDICHILD = 0x00000040,
295         WS_EX_TOOLWINDOW = 0x00000080,
296         WS_EX_WINDOWEDGE = 0x00000100,
297         WS_EX_CLIENTEDGE = 0x00000200,
298         WS_EX_CONTEXTHELP = 0x00000400,
299         WS_EX_RIGHT = 0x00001000,
300         WS_EX_LEFT = 0x00000000,
301         WS_EX_RTLREADING = 0x00002000,
302         WS_EX_LTRREADING = 0x00000000,
303         WS_EX_LEFTSCROLLBAR = 0x00004000,
304         WS_EX_RIGHTSCROLLBAR = 0x00000000,
305         WS_EX_CONTROLPARENT = 0x00010000,
306         WS_EX_STATICEDGE = 0x00020000,
307         WS_EX_APPWINDOW = 0x00040000,
308         WS_EX_OVERLAPPEDWINDOW = 0x00000300,
309         WS_EX_PALETTEWINDOW = 0x00000188,
310         WS_EX_LAYERED = 0x00080000
311     }
312     #endregion
313 
314     #region ChildFromPointFlags
315     public enum ChildFromPointFlags
316     {
317         CWP_ALL = 0x0000,
318         CWP_SKIPINVISIBLE = 0x0001,
319         CWP_SKIPDISABLED = 0x0002,
320         CWP_SKIPTRANSPARENT = 0x0004
321     }
322     #endregion
323 
324     #region HitTest
325     public enum HitTest
326     {
327         HTERROR = (-2),
328         HTTRANSPARENT = (-1),
329         HTNOWHERE = 0,
330         HTCLIENT = 1,
331         HTCAPTION = 2,
332         HTSYSMENU = 3,
333         HTGROWBOX = 4,
334         HTSIZE = HTGROWBOX,
335         HTMENU = 5,
336         HTHSCROLL = 6,
337         HTVSCROLL = 7,
338         HTMINBUTTON = 8,
339         HTMAXBUTTON = 9,
340         HTLEFT = 10,
341         HTRIGHT = 11,
342         HTTOP = 12,
343         HTTOPLEFT = 13,
344         HTTOPRIGHT = 14,
345         HTBOTTOM = 15,
346         HTBOTTOMLEFT = 16,
347         HTBOTTOMRIGHT = 17,
348         HTBORDER = 18,
349         HTREDUCE = HTMINBUTTON,
350         HTZOOM = HTMAXBUTTON,
351         HTSIZEFIRST = HTLEFT,
352         HTSIZELAST = HTBOTTOMRIGHT,
353         HTOBJECT = 19,
354         HTCLOSE = 20,
355         HTHELP = 21
356     }
357     #endregion
358 
359     #region Windows Messages
360     public enum Msg
361     {
362         WM_NULL = 0x0000,
363         WM_CREATE = 0x0001,
364         WM_DESTROY = 0x0002,
365         WM_MOVE = 0x0003,
366         WM_SIZE = 0x0005,
367         WM_ACTIVATE = 0x0006,
368         WM_SETFOCUS = 0x0007,
369         WM_KILLFOCUS = 0x0008,
370         WM_ENABLE = 0x000A,
371         WM_SETREDRAW = 0x000B,
372         WM_SETTEXT = 0x000C,
373         WM_GETTEXT = 0x000D,
374         WM_GETTEXTLENGTH = 0x000E,
375         WM_PAINT = 0x000F,
376         WM_CLOSE = 0x0010,
377         WM_QUERYENDSESSION = 0x0011,
378         WM_QUIT = 0x0012,
379         WM_QUERYOPEN = 0x0013,
380         WM_ERASEBKGND = 0x0014,
381         WM_SYSCOLORCHANGE = 0x0015,
382         WM_ENDSESSION = 0x0016,
383         WM_SHOWWINDOW = 0x0018,
384         WM_CTLCOLOR = 0x0019,
385         WM_WININICHANGE = 0x001A,
386         WM_SETTINGCHANGE = 0x001A,
387         WM_DEVMODECHANGE = 0x001B,
388         WM_ACTIVATEAPP = 0x001C,
389         WM_FONTCHANGE = 0x001D,
390         WM_TIMECHANGE = 0x001E,
391         WM_CANCELMODE = 0x001F,
392         WM_SETCURSOR = 0x0020,
393         WM_MOUSEACTIVATE = 0x0021,
394         WM_CHILDACTIVATE = 0x0022,
395         WM_QUEUESYNC = 0x0023,
396         WM_GETMINMAXINFO = 0x0024,
397         WM_PAINTICON = 0x0026,
398         WM_ICONERASEBKGND = 0x0027,
399         WM_NEXTDLGCTL = 0x0028,
400         WM_SPOOLERSTATUS = 0x002A,
401         WM_DRAWITEM = 0x002B,
402         WM_MEASUREITEM = 0x002C,
403         WM_DELETEITEM = 0x002D,
404         WM_VKEYTOITEM = 0x002E,
405         WM_CHARTOITEM = 0x002F,
406         WM_SETFONT = 0x0030,
407         WM_GETFONT = 0x0031,
408         WM_SETHOTKEY = 0x0032,
409         WM_GETHOTKEY = 0x0033,
410         WM_QUERYDRAGICON = 0x0037,
411         WM_COMPAREITEM = 0x0039,
412         WM_GETOBJECT = 0x003D,
413         WM_COMPACTING = 0x0041,
414         WM_COMMNOTIFY = 0x0044,
415         WM_WINDOWPOSCHANGING = 0x0046,
416         WM_WINDOWPOSCHANGED = 0x0047,
417         WM_POWER = 0x0048,
418         WM_COPYDATA = 0x004A,
419         WM_CANCELJOURNAL = 0x004B,
420         WM_NOTIFY = 0x004E,
421         WM_INPUTLANGCHANGEREQUEST = 0x0050,
422         WM_INPUTLANGCHANGE = 0x0051,
423         WM_TCARD = 0x0052,
424         WM_HELP = 0x0053,
425         WM_USERCHANGED = 0x0054,
426         WM_NOTIFYFORMAT = 0x0055,
427         WM_CONTEXTMENU = 0x007B,
428         WM_STYLECHANGING = 0x007C,
429         WM_STYLECHANGED = 0x007D,
430         WM_DISPLAYCHANGE = 0x007E,
431         WM_GETICON = 0x007F,
432         WM_SETICON = 0x0080,
433         WM_NCCREATE = 0x0081,
434         WM_NCDESTROY = 0x0082,
435         WM_NCCALCSIZE = 0x0083,
436         WM_NCHITTEST = 0x0084,
437         WM_NCPAINT = 0x0085,
438         WM_NCACTIVATE = 0x0086,
439         WM_GETDLGCODE = 0x0087,
440         WM_SYNCPAINT = 0x0088,
441         WM_NCMOUSEMOVE = 0x00A0,
442         WM_NCLBUTTONDOWN = 0x00A1,
443         WM_NCLBUTTONUP = 0x00A2,
444         WM_NCLBUTTONDBLCLK = 0x00A3,
445         WM_NCRBUTTONDOWN = 0x00A4,
446         WM_NCRBUTTONUP = 0x00A5,
447         WM_NCRBUTTONDBLCLK = 0x00A6,
448         WM_NCMBUTTONDOWN = 0x00A7,
449         WM_NCMBUTTONUP = 0x00A8,
450         WM_NCMBUTTONDBLCLK = 0x00A9,
451         WM_NCXBUTTONDOWN = 0x00AB,
452         WM_NCXBUTTONUP = 0x00AC,
453         WM_NCXBUTTONDBLCLK = 0x00AD,
454         WM_KEYDOWN = 0x0100,
455         WM_KEYUP = 0x0101,
456         WM_CHAR = 0x0102,
457         WM_DEADCHAR = 0x0103,
458         WM_SYSKEYDOWN = 0x0104,
459         WM_SYSKEYUP = 0x0105,
460         WM_SYSCHAR = 0x0106,
461         WM_SYSDEADCHAR = 0x0107,
462         WM_KEYLAST = 0x0108,
463         WM_IME_STARTCOMPOSITION = 0x010D,
464         WM_IME_ENDCOMPOSITION = 0x010E,
465         WM_IME_COMPOSITION = 0x010F,
466         WM_IME_KEYLAST = 0x010F,
467         WM_INITDIALOG = 0x0110,
468         WM_COMMAND = 0x0111,
469         WM_SYSCOMMAND = 0x0112,
470         WM_TIMER = 0x0113,
471         WM_HSCROLL = 0x0114,
472         WM_VSCROLL = 0x0115,
473         WM_INITMENU = 0x0116,
474         WM_INITMENUPOPUP = 0x0117,
475         WM_MENUSELECT = 0x011F,
476         WM_MENUCHAR = 0x0120,
477         WM_ENTERIDLE = 0x0121,
478         WM_MENURBUTTONUP = 0x0122,
479         WM_MENUDRAG = 0x0123,
480         WM_MENUGETOBJECT = 0x0124,
481         WM_UNINITMENUPOPUP = 0x0125,
482         WM_MENUCOMMAND = 0x0126,
483         WM_CTLCOLORMSGBOX = 0x0132,
484         WM_CTLCOLOREDIT = 0x0133,
485         WM_CTLCOLORLISTBOX = 0x0134,
486         WM_CTLCOLORBTN = 0x0135,
487         WM_CTLCOLORDLG = 0x0136,
488         WM_CTLCOLORSCROLLBAR = 0x0137,
489         WM_CTLCOLORSTATIC = 0x0138,
490         WM_MOUSEMOVE = 0x0200,
491         WM_LBUTTONDOWN = 0x0201,
492         WM_LBUTTONUP = 0x0202,
493         WM_LBUTTONDBLCLK = 0x0203,
494         WM_RBUTTONDOWN = 0x0204,
495         WM_RBUTTONUP = 0x0205,
496         WM_RBUTTONDBLCLK = 0x0206,
497         WM_MBUTTONDOWN = 0x0207,
498         WM_MBUTTONUP = 0x0208,
499         WM_MBUTTONDBLCLK = 0x0209,
500         WM_MOUSEWHEEL = 0x020A,
501         WM_XBUTTONDOWN = 0x020B,
502         WM_XBUTTONUP = 0x020C,
503         WM_XBUTTONDBLCLK = 0x020D,
504         WM_PARENTNOTIFY = 0x0210,
505         WM_ENTERMENULOOP = 0x0211,
506         WM_EXITMENULOOP = 0x0212,
507         WM_NEXTMENU = 0x0213,
508         WM_SIZING = 0x0214,
509         WM_CAPTURECHANGED = 0x0215,
510         WM_MOVING = 0x0216,
511         WM_DEVICECHANGE = 0x0219,
512         WM_MDICREATE = 0x0220,
513         WM_MDIDESTROY = 0x0221,
514         WM_MDIACTIVATE = 0x0222,
515         WM_MDIRESTORE = 0x0223,
516         WM_MDINEXT = 0x0224,
517         WM_MDIMAXIMIZE = 0x0225,
518         WM_MDITILE = 0x0226,
519         WM_MDICASCADE = 0x0227,
520         WM_MDIICONARRANGE = 0x0228,
521         WM_MDIGETACTIVE = 0x0229,
522         WM_MDISETMENU = 0x0230,
523         WM_ENTERSIZEMOVE = 0x0231,
524         WM_EXITSIZEMOVE = 0x0232,
525         WM_DROPFILES = 0x0233,
526         WM_MDIREFRESHMENU = 0x0234,
527         WM_IME_SETCONTEXT = 0x0281,
528         WM_IME_NOTIFY = 0x0282,
529         WM_IME_CONTROL = 0x0283,
530         WM_IME_COMPOSITIONFULL = 0x0284,
531         WM_IME_SELECT = 0x0285,
532         WM_IME_CHAR = 0x0286,
533         WM_IME_REQUEST = 0x0288,
534         WM_IME_KEYDOWN = 0x0290,
535         WM_IME_KEYUP = 0x0291,
536         WM_MOUSEHOVER = 0x02A1,
537         WM_MOUSELEAVE = 0x02A3,
538         WM_CUT = 0x0300,
539         WM_COPY = 0x0301,
540         WM_PASTE = 0x0302,
541         WM_CLEAR = 0x0303,
542         WM_UNDO = 0x0304,
543         WM_RENDERFORMAT = 0x0305,
544         WM_RENDERALLFORMATS = 0x0306,
545         WM_DESTROYCLIPBOARD = 0x0307,
546         WM_DRAWCLIPBOARD = 0x0308,
547         WM_PAINTCLIPBOARD = 0x0309,
548         WM_VSCROLLCLIPBOARD = 0x030A,
549         WM_SIZECLIPBOARD = 0x030B,
550         WM_ASKCBFORMATNAME = 0x030C,
551         WM_CHANGECBCHAIN = 0x030D,
552         WM_HSCROLLCLIPBOARD = 0x030E,
553         WM_QUERYNEWPALETTE = 0x030F,
554         WM_PALETTEISCHANGING = 0x0310,
555         WM_PALETTECHANGED = 0x0311,
556         WM_HOTKEY = 0x0312,
557         WM_PRINT = 0x0317,
558         WM_PRINTCLIENT = 0x0318,
559         WM_THEME_CHANGED = 0x031A,
560         WM_HANDHELDFIRST = 0x0358,
561         WM_HANDHELDLAST = 0x035F,
562         WM_AFXFIRST = 0x0360,
563         WM_AFXLAST = 0x037F,
564         WM_PENWINFIRST = 0x0380,
565         WM_PENWINLAST = 0x038F,
566         WM_APP = 0x8000,
567         WM_USER = 0x0400,
568         WM_REFLECT = WM_USER + 0x1c00
569     }
570     #endregion
571 
572     #region SetWindowPosFlags
573     public enum SetWindowPosFlags
574     {
575         SWP_NOSIZE = 0x0001,
576         SWP_NOMOVE = 0x0002,
577         SWP_NOZORDER = 0x0004,
578         SWP_NOREDRAW = 0x0008,
579         SWP_NOACTIVATE = 0x0010,
580         SWP_FRAMECHANGED = 0x0020,
581         SWP_SHOWWINDOW = 0x0040,
582         SWP_HIDEWINDOW = 0x0080,
583         SWP_NOCOPYBITS = 0x0100,
584         SWP_NOOWNERZORDER = 0x0200,
585         SWP_NOSENDCHANGING = 0x0400,
586         SWP_DRAWFRAME = 0x0020,
587         SWP_NOREPOSITION = 0x0200,
588         SWP_DEFERERASE = 0x2000,
589         SWP_ASYNCWINDOWPOS = 0x4000
590     }
591     #endregion
592 }
593 
594     #region WINDOWINFO
595     [StructLayout(LayoutKind.Sequential)]
596     public struct WINDOWINFO
597     {
598         public UInt32 cbSize;
599         public RECT rcWindow;
600         public RECT rcClient;
601         public UInt32 dwStyle;
602         public UInt32 dwExStyle;
603         public UInt32 dwWindowStatus;
604         public UInt32 cxWindowBorders;
605         public UInt32 cyWindowBorders;
606         public UInt16 atomWindowType;
607         public UInt16 wCreatorVersion;
608     }
609     #endregion
610 
611     #region POINT
612     [StructLayout(LayoutKind.Sequential)]
613     public struct POINT
614     {
615         public int x;
616         public int y;
617 
618         #region Constructors
619         public POINT(int x, int y)
620         {
621             this.x = x;
622             this.y = y;
623         }
624 
625         public POINT(Point point)
626         {
627             x = point.X;
628             y = point.Y;
629         }
630         #endregion
631     }
632     #endregion
633 
634     #region RECT
635     [StructLayout(LayoutKind.Sequential)]
636     public struct RECT
637     {
638         public uint left;
639         public uint top;
640         public uint right;
641         public uint bottom;
642 
643         #region Properties
644         public POINT Location
645         {
646             get { return new POINT((int)left, (int)top); }
647             set
648             {
649                 right -= (left - (uint)value.x);
650                 bottom -= (bottom - (uint)value.y);
651                 left = (uint)value.x;
652                 top = (uint)value.y;
653             }
654         }
655 
656         public uint Width
657         {
658             get { return right - left; }
659             set { right = left + value; }
660         }
661 
662         public uint Height
663         {
664             get { return bottom - top; }
665             set { bottom = top + value; }
666         }
667         #endregion
668 
669         #region Overrides
670         public override string ToString()
671         {
672             return left + ":" + top + ":" + right + ":" + bottom;
673         }
674         #endregion
675     }
676     #endregion
677 
678     #region WINDOWPOS
679     [StructLayout(LayoutKind.Sequential)]
680     public struct WINDOWPOS
681     {
682         public IntPtr hwnd;
683         public IntPtr hwndAfter;
684         public int x;
685         public int y;
686         public int cx;
687         public int cy;
688         public uint flags;
689 
690         #region Overrides
691         public override string ToString()
692         {
693             return x + ":" + y + ":" + cx + ":" + cy + ":" + ((SWP_Flags)flags).ToString();
694         }
695         #endregion
696     }
697     #endregion
698 
699     #region NCCALCSIZE_PARAMS
700     [StructLayout(LayoutKind.Sequential)]
701     public struct NCCALCSIZE_PARAMS
702     {
703         public RECT rgrc1;
704         public RECT rgrc2;
705         public RECT rgrc3;
706         public IntPtr lppos;
707     }
708     #endregion
709 
710     #region NMHDR
711     [StructLayout(LayoutKind.Sequential)]
712     public struct NMHDR
713     {
714         public IntPtr hwndFrom;
715         public uint idFrom;
716         public uint code;
717     }
718     #endregion
719 
720     #region OFNOTIFY
721     [StructLayout(LayoutKind.Sequential)]
722     public struct OFNOTIFY
723     {
724         public NMHDR hdr;
725         public IntPtr OPENFILENAME;
726         public IntPtr fileNameShareViolation;
727     }
728     #endregion
复制代码

 

补充一下

1.代码只提供思路,不能拿来继承一下,就能实现自己想要的功能。

2.可以自己将代码中DialogNativeWindow类的addControl替换为其他控件,比如PictureBox用来预览图片、TextBox用来预览txt文件、RichTextBox用来预览代码文件等等,还可自由组合。

3.可以自己将代码中DialogNativeWindow类的两个事件(SelectedFileChanged、SelectPathChanged)移到MultiOpenFileDialog中,并使其对外开放,外部程序可以监听该事件。

4.如果想做成通用类,拿过来继承一下就可以实现自己想要的效果,建议使MultiOpenFileDialog从UserControl,并将addControl设为自己。也就是说将自己添加到OpenFileDialog中去,MultiOpenFileDialog的派生类就可以在VS中设计自己想要的效果。

5.一个窗体新建显示时,它的拥有者会接收许多消息,包括WM_ACTIVATE、WM_IDLE等等,并且Lparam参数为新建窗体的句柄。

View Code

复制代码
 1 class Form1:Form
 2 {
 3       private void Form1_Load(Object sender,EventArgs e)
 4       {
 5              using(OpenFileDialog dia = new OpenFileDialog())
 6              {
 7                     dia.ShowDialog(this);
 8              }
 9       }
10       protected override void WndProc(ref Message m)
11      {
12              //当dia显示时,它的拥有者即为this,这里会接受一连串的Window消息,并且它的Lparam参数为dia的句柄
13             base.WndProc(ref m);
14      }
15 }
复制代码

6.Windows中窗体和所谓的控件(button、textbox)本质上没有区别,任务栏与QQ聊天框或者Chrome浏览器的地址栏对我们程序员来讲,是同一个东西。

7.与窗体有关的Win32 API基本都需要窗体句柄,其实任何一个API几乎都需要知道操作对象的句柄(不一定是窗体)。

8.Windows中任何一个窗体(控件)理论上都是平级的,不管是否同一进程,也就是说,我的winform应用程序只要知道了Chrome浏览器窗体的句柄,就可以控制Chrome浏览器,监听Chrome窗体的Windows消息(除非Chrome程序本身禁止了此操作)。

9.Windows桌面应用程序开发中,(部分平台、语言)理解四个东西,即进程、线程 、窗体(已经说了,是广义上的窗体)、消息。

10.查看系统中以上四个东西,可以使用Spy++工具。

完了,剩下那个下次再写了,太多了。希望有帮助~

.Net WInform开发笔记(二)Winform程序运行结构图 - 周见智 - 博客园

mikel阅读(988)

来源: .Net WInform开发笔记(二)Winform程序运行结构图 – 周见智 – 博客园

中午没事,把去年刚毕业那会画的几张图翻出来了,大概介绍Winform应用程序运行的过程,以及TCP协议在Winform中的应用。如果有Windows消息机制等基础,很好理解这两张图。

(1)Winform应用程序运行结构图

(2)TCP通讯协议在Winform程序中的应用示意图

熟悉整个程序的来龙去脉,编程的时候就会很轻松,不会云里雾里。

另附公司招聘面试题一份,用了几次,发现效果不好,不知啥原因

1.简述接口、抽象类的区别。

2.简述重载(overload)与重写(override)的区别。

3.对OO思想的理解。

4.简述对象“线程安全”是什么意思。

5.跨线程访问控件的方法?简述该方法的原理。

6.简述Socket通讯原理,简述怎样处理数据包不完整问题。

7..Net Winform编程中最常用的设计模式有哪些?

8.能否自己写一个类似ListBox功能的控件?简述其原理。

9.简述在windows操作系统中,窗体与按钮的区别。

10.简述用C#(或者VB)将Excel中的数据导入数据库的方法。简述用C#(或者VB)将数据库中的数据导入到一个新的Excel文件打方法。

11.两个Winform桌面应用程序A与B,各有一个主窗体,列举A程序关闭B程序的方法。

12情景:.Net Winform程序设计中,用鼠标点击按钮“Button1”,弹出一个MessageBox消息提示框。

问题:请从Windows操作系统消息层次描述以上情景发生的过程。

.Net Winform开发笔记(一) - 周见智 - 博客园

mikel阅读(1142)

来源: .Net Winform开发笔记(一) – 周见智 – 博客园

1.  理解“Windows 窗体应用程序”项目中Program.cs文件中的main方法与传统C++Console控制台程序中的main方法的区别。从程序运行层次上讲,两者无区别,都是程序的入口点,属于进程中的第一个线程。前者隐藏了UI应用程序必需的消息循环,后者没有。

2.  每个Windows桌面应用程序都必须包含至少一个UI线程,所谓UI线程,就是可以响应Windows消息的线程。通常情况下,除非特别需要,一个Windows桌面应用程序只包含一个UI线程。

3.  UI线程本质上跟普通线程一样,一般为程序的入口线程,比如Program.cs文件中的main方法,就是UI线程,而Application.Run()方法中封装了消息循环。如果没有Application.Run()方法,那么它跟其他线程一模一样。之所以叫做UI线程,是因为它之中包含一个类似

1 While(GetMessage(…))//取Windows消息

2 {
3     //处理windows消息,调用开发者编写的回调方法,如事件处理程序 等。
4 }

的循环。

4. 有关Windows消息机制等内容,请上网Google或者百度。

5.  UI线程主要负责界面的实时更新,所以开发人员编写代码时,请遵守以下规律:

1) 不要在控件的事件处理程序中编写(或者调用)耗时的代码块;

2) 不要在控件的事件处理程序中调用阻塞方法;阻塞与非阻塞应参见13.

6.  明白程序设计中的 委托、事件、事件处理程序的区别

1) Publicdelegate void KeyPressEventHandler(KeyPressEventArgse);

2) Public eventKeyPressEventHandler KeyPress;

3)  Public void Textbox1_KeyPress(objectsender,KeyPressEventArgs e)

{

//….

}

其中:

1为委托 2为事件 3为事件处理程序

7.  所有的事件处理程序都是在UI线程中调用,又因为UI线程负责更新界面,所以UI线程始终必须保持顺畅(表现为3中的while循环体不能耗时太长),即不能出现长时间执 行一个方法不返回的情况。所以,请遵守5中的规律。

8.  同一个方法,可以运行在多个线程之中,方法跟线程没有一对一的原则

Private void  thread_pro()  //

{

}

1) privatebutton1_click(object sender,EventArgs e)

{

thread_pro();  //thread_pro运行在UI线程中

}

2)private button1_click(object sender,EventArgs e)

{

Thread t = new Thread(newThreadStart(thread_pro));

Thread t1 = new Thread(new ThreadStart(thread_pro));

Thread t2 = newThread(new ThreadStart(thread_pro));

 

t.start();  //thread_pro运行在t线程中

t1.start();  //thread_pro运行在t1线程中

t.2.start();  //thread_pro运行在t2线程中

}

3) 还可以通过Control.Invoke() 或者BenginInvoke方法将方法投递到创建该控件的线程中执行。

以上所有情况,请注意线程共享数据。

9.   多线程编程中,请注意“线程安全”问题,对于一些具备“非原子”操作的对象,必须采取措施避免发生错误。

UI控件(Button、datagridview等等)、集合(List、ArrayList)等属于此类对象,控件任何时间都不能多线程访问。

10. 坚决杜绝跨线程访问UI控件,原因见9。跨线程访问控件的方法见8中的3)。

11. 除了.Net Winform中的事件处理程序是在UI线程中调用以外,其它的回调方法几乎所有都不会在UI线程中执行,所以,开发人员在编写回调方法时,请遵守第9,10两大规律。

12.  明白什么叫回调方法。回调方法一般由开发者编写,但不由开发者调用,由系统(或者说框架)调用。在Windows桌面应用程序开发过程中,控件的事件处理程序都属于回调方法,回调方法一般用在“观察者”设计模式中,当事件的激发者激发一个事件时,它就会调用回调方法。控件的所有事件都属于此类。

另外一种常见为,异步执行某个操作,譬如,socket.BeginAccept()中的AsyncCallBack类型参数。

在框架横行的时代,一般开发者编写的代码都属于回调代码。因为程序的主要结构都由先辈们在框架中集成好了。开发者们只需要像填空一样完善空缺的部分。

13.  阻塞方法指,由于方法体内包含耗时较长的操作,所以方法不能及时返回。

所谓“及时”与“非及时”没有绝对界限,示例如下:

复制代码
      int func1()     //及时返回
{
Int index = 0;
For(int i=0;i<100;i++)
{
Index ++;
}
Return index;
}
Int func2()   //非及时返回
{
Int index = 0;
For(int i=0;i<1000;i++)
{
For(int j=0;j<1000;++j)
{
Index ++;
}
}
Return index;
}
复制代码

上述func1相对而言,属于非阻塞方法,func2属于阻塞方法。

 

14.  Windows窗体应用程序不会直接跟键盘、鼠标等硬件设备交互,它只与Windows消息有直接交互。虽然表面上鼠标键盘等硬件设备是操作在窗体之上的,但实质上,你        编写的桌面应用程序是不会理解这些硬件设备的一举一动。他们是通过操作系统(驱动程序)进行桥接的,操作系统先将硬件设备的一举一动翻译成windows消息(一种数据结构,程序可以理解),然后供程序理解,作出相应的反应。

15.  所谓“阻塞调用线程”,是指在某一个线程中调用了阻塞方法,从而使该线程不能及时执行以后的代码。

复制代码
 1      Void func()
2      {
3          Int index=0;
4          For(int i=0;i<10000;++i)
5          {
6               For(int j=0;j<10000;++j)
7              {
8                    I ndex++;
9               }
10           }
11      }
12      Thread t = newThread(new ThreadStart(func));
13       t.Start();       //线程t中调用了阻塞方法func,因此线程t会被阻塞
14
复制代码

在介绍func方法时,可以这样描述:该方法会阻塞调用线程。

16. 同一个方法可以被多个线程调用,既可被UI线程调用,也可被非UI线程调用,那么在方法体内怎么编写访问UI控件(UI元素)的代码呢?(跨线程访问UI控件会引发异常)

Void func()

{

Textbox1.Text=”测试”;

PictureBox1.Image = Image.FromFile(“a.jpg”);

}

1)以上func方法可能运行在UI线程中,如下:

Private voidbutton1_Click(object sender,EventArgs e)

{

func();  //调用func方法

}

 

2)有如下,func方法可能运行在其他非UI线程中

Private void button1_Click(object sender,EventArgs e)

{

Thread t = new Thread(newThreadStart(func));

t.Start();  //func访问运行在t线程中

}

在2)中,可能引发异常。

以上问题的解决方案为:

修改func代码为:

Func()

{

If(this.InvokeRequired)

{

This.BeginInvoke((Action)delegate(){func()});

}

Else

{

Textbox1.Text=”测试”;

PictureBox1.Image = Image.FromFile(“a.jpg”);

}

}

有关BeginInvoke或者Invoke方法的使用,请上网Google或者百度。

17. 有关“跨线程访问UI控件可能引发异常”的原因,跟多线程访问集合可能出现错误的原因基本相似。下面列举一段代码说明情况

复制代码
 1    ClassMyControl
2    {
3        Object root;
4        Public Draw()
5        {
6            GetRoot(root);
7            // 一系列操作…
8            ReleaseRoot(root);
9         }
10        Public OtherDraw()
11       {
12           GetRoot(root);
13           // 一系列操作 …
14            ReleaseRoot(root);
15        }
16    }
复制代码

其中root变量同时只能被占用一次,GetRoot()获取root的访问权,如果root已经被占用,则抛出异常。ReleaseRoot()释放root占用。

当在一个线程中(比如UI线程中)访问MyControl类对象A,调用A.Draw()方法,执行到GetRoot(root)方法后,该线程失去控制权,暂停运行一下的代码,即此时root已被占用。而另一线程中如果也要访问同一对象A的Draw()方法,那么就会引发异常。

18.在.Net Winform应用程序中,程序与用户的交互主要包含两个方面,一是用户用鼠标、键盘灯硬件设备进行操作,程序响应操作,然后进行反馈(比如更新界面、刷新数据等),二是不需要用户用鼠标等硬件设备进行操作,程序自己自动进行反馈(比如QQ弹出新闻窗体、360弹窗等)。

第一种情况是我们所熟知的,比如用户用鼠标点击按钮(button1),程序则弹出一个MessageBox,我们在程序中是这样子写的:事件处理程序如下

1    Private voidbutton1_Click(object sender,EventArgs e)
2    {
3           MessageBox.Show(“弹出对话框,或者其他操作”);
4    }

再来理一下这个过程,首先用户拿起鼠标点击button1,操作系统(鼠标驱动)会捕获这个事件,经过分析,操作系统得知用户点击的是哪个窗体(按钮)、点击的位置(坐标),点击类型(左键还是右键或者其他),以及其他信息,之后,将这些信息封装成一个类型(即windows消息)发送给创建该窗体(控件)的线程中的消息队列,之后,操作系统(鼠标驱动)就不在负责了。接着,UI线程从线程消息队列中获取该消息(注意:这个过程是一直存在的),分析消息,调用开发人员编写的一些回调方法,如button1_Click()方法,从而到达相应鼠标键盘操作的目的。从上面分析过程来看,再一次说明,程序是不会直接跟鼠标等硬件设备交互的,与它直接交互的只有Windows消息,而这个过程需要Windows操作系统起着重要作用。

第二种情况一般用在多线程编程中,当程序有耗时操作、或者需要一直监听等情况的时候,是不能放在UI线程之中的,这时候就需要另外开辟线程,在另外的线程中处理。这种情况中,另外开辟的线程有时候需要反馈跟用户一些信息,即更新UI界面或者弹出一个窗体等,这就涉及到跨线程访问UI元素的问题了,详见5和16.

以上代码部分均为现写的,可能出现拼写错误,包涵!

另外,请配合笔记(二)中的“DOT NETWinform应用程序运行结构图”阅读。

Delphi连接mysql数据库的三种方式 - CSDN博客

mikel阅读(2339)

(1)通过ODBC+ADO的方式连:    with ADOCon1 do    begin       Close;      ConnectionString:=( DRIVER={MySQL ODBC 5.1 Driver}; +                                  SERVER=192.168.1.107; +

来源: Delphi连接mysql数据库的三种方式 – CSDN博客

(1)通过ODBC+ADO的方式连:

with ADOCon1 do

begin
Close;
ConnectionString:=( ‘DRIVER={MySQL ODBC 5.1 Driver}; ‘+
‘SERVER=192.168.1.107; ‘+
‘DATABASE=test; ‘+
‘USER=root; ‘+
‘PASSWORD=root; ‘+
‘PORT=3406; ‘+
‘OPTION=3; ‘);
try

Open;
application.MessageBox( ‘连接成功!’, ‘提示 ‘,MB_ICONINFORMATION);

except
application.MessageBox( ‘无法连接数据库服务器.请与管理员联系 ‘, ‘提示 ‘,MB_ICONINFORMATION);
end;  //try

end;  //with

 

(2)通过DBExpress连:

SQLConnection1.Connected:= false;

with SQLConnection1.Params do
begin
Text:=’DriverName=MSSQL’+#13+
‘ServerPort=’ + 3406 + #13+
‘HostName=’ + ‘192.168.1.107’+ #13+
‘DataBase= test’ +#13+
‘User_Name=root’+#13+
‘Password=root’+#13+
‘BlobSize=-1’+#13+
‘ErrorResourceFile=’+#13+
‘LocaleCode=0000’+#13+
‘ServerCharset=gb2312’+#13+
‘MSSQL   TransIsolation=ReadCommited’+ #13+
‘OS   Authentication=False’;
end;
try
SQLConnection1.Connected:=true;

application.MessageBox( ‘连接成功!’, ‘提示 ‘,MB_ICONINFORMATION);
except
application.MessageBox( ‘无法连接数据库服务器.请与管理员联系 ‘, ‘提示 ‘,MB_ICONINFORMATION);

end;

注:在delphi7及以下版本,ServerPort设置无效

 

(3)通过MyDAC连(

Delphi的MySQL连接控件(mydac)http://download.csdn.net/download/fionwang/9733663

):

with ADOCon1 do
begin
Close;

Server:= ‘192.168.1.107’;
Port:= 3406;
Username:= ‘root’;
Password:= ‘root’;
Database:= ‘test’;
Options.Charset:= ‘gb2312’;

try
Open();

application.MessageBox( ‘连接成功!’, ‘提示 ‘,MB_ICONINFORMATION);

except
application.MessageBox( ‘无法连接数据库服务器.请与管理员联系 ‘, ‘提示 ‘,MB_ICONINFORMATION);
end;  //try
end;   //with