[转载]简单爬虫-抓取博客园文章列表 - 成天 - 博客园

mikel阅读(1300)

[转载]简单爬虫-抓取博客园文章列表 – 成天 – 博客园.

    如果使用对方网站数据,而又没有响应的接口,或者使用接口不够灵活的情况下,使用爬虫在合适不过了。爬虫有几种,对方网站展示形式有几种都是用分析,每个网站展示有相似的地方,有不同的地方。

    大部分使用httpRequst就能完成,不管是否添加了口令、随即码、请求参数、提交方式get或者post、地址来源、多次响应等等。但是有些网站使 用ajax如果是返回json或固定格式的也好处理,如果是很复杂的,可以使用webbrower控件进行抓取,最后正则解析,获取所需要的数据即可。

     那我们来抓取去首页网站列表 文章标题、文章摘要、文章发布时间、文章作者、文章评论次数、文章浏览次数。看下结构图。

  get请求返回静态html附代码如下

public class HttpCnblogs
{
public static List HttpGetHtml()
{

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://www.cnblogs.com/");
request.Method = "GET";
request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
request.UserAgent = " Mozilla/5.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream stream = response.GetResponseStream();
StreamReader sr = new StreamReader(stream);
string articleContent = sr.ReadToEnd();

List list = new List();

#region 正则表达式
//div post_item_body列表
Regex regBody = new Regex(@"<div\sclass=""post_item_body"">([\s\S].*?)

", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace);
//a标签 文章标题 作者名字 评论 阅读
Regex regA = new Regex("<a[^>]*?>(.*?)", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace);
//p标签 文章内容
Regex regP = new Regex(@"<p\sclass=""post_item_summary"">(.*?)

", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace);
//提取评论 阅读次数如:评论(10)-》10
Regex regNumbernew = new Regex(@"\d+", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace);
//提取时间
Regex regTime = new Regex(@"\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.IgnorePatternWhitespace);
#endregion
MatchCollection mList = regBody.Matches(articleContent);
CnblogsModel model = null;
String strBody = String.Empty;
for (int i = 0; i < mList.Count; i++)
{
model = new CnblogsModel();
strBody = mList[i].Groups[1].ToString();
MatchCollection aList = regA.Matches(strBody);
int aCount = aList.Count;
model.ArticleTitle = aList[0].Groups[1].ToString();
model.ArticleAutor = aCount == 5 ? aList[2].Groups[1].ToString() : aList[1].Groups[1].ToString();
model.ArticleComment = Convert.ToInt32(regNumbernew.Match(aList[aCount-2].Groups[1].ToString()).Value);
model.ArticleTime = regTime.Match(strBody).Value;
model.ArticleView = Convert.ToInt32(regNumbernew.Match(aList[aCount-1].Groups[1].ToString()).Value);
model.ArticleContent = regP.Matches(strBody)[0].Groups[1].ToString();
list.Add(model);
}
return list;
}
}

public class CnblogsModel
{
///
/// 文章标题
///

public String ArticleTitle { get; set; }
///
/// 文章内容摘要
///

public String ArticleContent { get; set; }
///
/// 文章作者
///

public String ArticleAutor { get; set; }
///
/// 文章发布时间
///

public String ArticleTime { get; set; }
///
/// 文章评论量
///

public Int32 ArticleComment { get; set; }
///
/// 文章浏览量
///

public Int32 ArticleView { get; set; }
}

最后看看获取的文章model

写的不好,还请见谅,准备下面试去。。

[转载]编写高质量代码改善C#程序的157个建议[C#闭包的陷阱、委托、事件、事件模型] - aehyok - 博客园

mikel阅读(1180)

[转载]编写高质量代码改善C#程序的157个建议[C#闭包的陷阱、委托、事件、事件模型] – aehyok – 博客园.

前言

本文已更新至http://www.cnblogs.com/aehyok/p/3624579.html 。本文主要学习记录以下内容:

建议38、小心闭包中的陷阱

建议39、了解委托的实质

建议40、使用event关键字对委托施加保护

建议41、实现标准的事件模型

建议38、小心闭包中的陷阱

  首先我们先来看一段代码:

class Program
{
static void Main(string[] args)
{
List list = new List();
for (int i = 0; i < 5; i++) { Action t = () =>Console.WriteLine(i.ToString());
list.Add(t);
}
foreach (Action t in list)
{
t();
}
Console.ReadLine();
}
}

你设想的结果或许是0,1,2,3,4

但没想到执行后结果如下

通过IL可以查看代码,组合后大致代码如下:

public class TempClass
{
public int i;
public void TempFunc()
{
Console.WriteLine(i.ToString());
}

}
class Program
{
static void Main(string[] args)
{
List list = new List();
TempClass tempClass = new TempClass();
for (tempClass.i = 0; tempClass.i < 5; tempClass.i++)
{
Action t = tempClass.TempFunc;
list.Add(t);
}
foreach (Action t in list)
{
t();
}
Console.ReadLine();
}
}

当然运行后结果还是5,5,5,5,5

其实这段代码所演示的就是一个闭包对象。所谓的闭包对象,指的是上面这种情形中的TempClass对象,如果匿名方法(Lambda表达式)引用了某个局部变量,编译器就会自动将该引用提升到该闭包对象中,即将for循环中的变量i修改成了引用闭包对象的公共变量i。这样一来,即使代码执行后离开了原局部变量i的作用域(如for循环),包含该闭包对象的作用域也还存在。

下面简单修改一下之前的代码

class Program
{

static void Main(string[] args)
{
List list = new List();
for (int i = 0; i < 5; i++) { int temp = i; Action t = () => Console.WriteLine(temp.ToString());
list.Add(t);
}
foreach (Action t in list)
{
t();
}
Console.ReadLine();
}
}

执行结果如下:

建议39、了解委托的实质

 http://www.cnblogs.com/aehyok/archive/2013/03/22/2976356.html这里有我之前对委托的简单的学习过程,虽然在工作中很少用,几乎就没用。不过还是拿来学习学习。

理解委托需要把握两个点:

1、委托是方法指针。

2、委托就是一个类。当对其进行实例化的时候,要将引用方法作为它构造函数的参数。

建议40、使用event关键字对委托施加保护

 http://www.cnblogs.com/aehyok/archive/2013/02/22/2922586.html 这也是对于事件的简单理解学习。

建议41、实现标准的事件模型

我们应该知道微软为事件模型设定的几个规范:

1、委托类型的名称以EventHandler结束。

2、委托原型返回值为void。

3、委托原型具有两个参数:sender表示事件触发者,e表示事件参数。

4、事件参数的名称以EventArgs结束。

public class FileUploadedEventArgs : EventArgs
    {
        public int FileProgress { get; set; }
    }

    public class FileUploader
    {
        public event EventHandler<FileUploadedEventArgs> FileUploaded;

        public void Upload()
        {
            FileUploadedEventArgs e = new FileUploadedEventArgs() { FileProgress=100 };
            while (e.FileProgress > 0)
            {
                ///传输代码,省略
                e.FileProgress--;
                if (FileUploaded != null)
                {
                    FileUploaded(this, e);
                }
            }
        }
    }

最终进行调用的代码如下:

class Program
    {
        static void Main(string[] args)
        {
            FileUploader fileUploader = new FileUploader();
            fileUploader.FileUploaded += Progress;
            fileUploader.Upload();
            Console.ReadLine();
        }

        static void Progress(object sender,FileUploadedEventArgs e)
        {
            Console.WriteLine(e.FileProgress);
        }
    }

[转载]Restful.Data v1.0 - 轻量级数据持久层组件, 正式开源发布了 - linli8 - 博客园

mikel阅读(1083)

[转载]Restful.Data v1.0 – 轻量级数据持久层组件, 正式开源发布了 – linli8 – 博客园.

经过几个星期的优化调整,今天 Restful.Data 正式开源发布。

源码地址:https://github.com/linli8/Restful

今天不写那么多废话了,还是重新介绍一下 Restful.Data 吧。


 

1、什么是Restful.Data?

Restful.Data是一套通用的轻量级数据持久层组件,除封装了ADO.NET基本的数据库操作以外,也提供了一些orm相关的API,用户可以方便的定义实体类,并使用这些API对数据进行增删改查等操作。

Restful.Data借鉴了业界如nhibernate、entity framework等知名的数据持久层组件,但从一开始设计的初衷就是为了让用户能快速的学习和使用,并写出更加简洁优雅的代码,所以摒弃了一些复杂的设 计和功能,用户可以使用变通的方式或方法使用Restful.Data组件实现其目的。

Restful.Data充分考虑了实体框架的执行效率问题,进行了反复的推敲和论证,尽可能的采用高效的设计方案来提高性能。


 

2、谁需要Restful.Data?

敢于冒险、追求完美、勇于挑战并极具责任感的程序设计人员。


 

3、Restful.Data提供哪些功能?

基本的ADO.NET操作:BeginTransaction、ExecuteScalar、ExecuteDataReader、 ExecuteDataTable、ExecuteDataSet、ExecutePageQuery、ExecuteStoredProcedure

ORM相关操作:Insert、Updete、Delete、Find


4、如何使用Restful.Data?

使用前请先下载Restful.dll、Restful.Data、Restful.Data.MySQL、Remotion.Linq.dll、MySQL.Data.dll,或者直接下载源代码进行编译并获取这5个dll,并在项目中引用这些dll。

在 Web.config 或 App.config 中配置连接字符串,如下:






注册提供程序工厂:

SessionFactories.Register();

提供程序工厂在一个Application中仅需注册一次。

如何进行基本的数据库操作:

using( ISession session = SessionFactory.CreateDefaultSession() )
{
string sql = "select * from Person";

DataTable dt = session.ExecuteDataTable( sql );
}

CreateDefaultSession默认情况下根据配置文件中连接字符串节点的第一项创建数据库连接,你可以调用CreateSession进行指定,或者你也可以使用 SessionFactory.Default = “MySql2″指定默认连接。

为防止 SQL 注入,你也使用带参数方法:

using( ISession session = SessionFactory.CreateDefaultSession() )
{
string sql = "select * from Person where Id = @Id;";

IDictionary&lt;string, object&gt; parameters = new Dictionary&lt;string, object&gt;();

parameters.Add( "@Id", 5 );

DataTable dt = session.ExecuteDataTable( sql, parameters );
}

与此类似的还有ExecuteScalar、ExecuteDataReader、ExecuteDataTable、ExecuteDataSet等方法。

如何进行分页查询:

using( ISession session = SessionFactory.CreateDefaultSession() )
{
string sql = "select * from User where CreateTime &lt; @CreateTime";

IDictionary&lt;string, object&gt; parameters = new Dictionary&lt;string, object&gt;();

parameters.Add( "@CreateTime", DateTime.Now );

// 查询第2页,每页10条,并根据 CreateTime 字段降序排列
PageQueryResult result = session.ExecutePageQuery( sql01, 2, 10, "CreateTime DESC", parameters );
}

如何进行数据新增:

using( ISession session = SessionFactory.CreateDefaultSession() )
{
var person = new Person();

// person.Id = 1; 若Id字段为自增类型,无需指定。
person.Name = "test01";
person.CreateTime = DateTime.Now;
person.IsActive = true;

int i = session.Insert( person );
}

如何进行数据更新:

using( ISession session = SessionFactory.CreateDefaultSession() )
{
var person = new Person();

person.Id = 1;
person.Name = "test01";
person.CreateTime = DateTime.Now;
person.IsActive = true;

// 在调用此方法时,务必指定实例的主键值。
int i = session.Update( person );
}

或者你也可以批量更新:

using( ISession session = SessionFactory.CreateDefaultSession() )
{
var person = new Person();

// person.Id = 1;
person.Name = "test01";
person.CreateTime = DateTime.Now;
person.IsActive = true;

// 在调用此方法时,不需要指定主键值,且不会更新主键字段
session.Update().Set( person ).Where( s =&gt; s.IsActive == false ).Execute();
}

如何进行数据删除:

using( ISession session = SessionFactory.CreateDefaultSession() )
{
var person = new Person() { Id = 1 };

// 在调用此方法时,需要指定主键值
session.Delete( person );
}

或者你也可以批量删除:

using( ISession session = SessionFactory.CreateDefaultSession() )
{
// 在调用此方法时,不需要指定主键值
session.Delete().Where( s =&gt; s.IsActive == false ).Execute();
}

如何进行单表查询:

using( ISession session = SessionFactory.CreateDefaultSession() )
{
var queryable = session.Find()
.Where( s =&gt; s.Name.Contains("a") )
.Where( s =&gt; s.CreateTime &lt; DateTime.Now ) .OrderBy( s =&gt; s.CreateTime )
.Skip(5)
.Take(10);

var list = queryable.ToList();
var count = queryable.Count();
var first = queryable.FirstOrDefault();

var queryable1 = from s in session.Find()
where s =&gt; s.Name.Contains("a")
orderby s.CreateTime descending
select new { Id = s.Id, Name = s.Name };

// ...
}

目前只支持对单表的LINQ查询,且为了降低复杂度,后期也不打算支持多表查询,对函数的支持也有限,仅支持string类型的StartsWith、EndsWith、Contains、Equals、IsNullOrEmpty等方法,对于其他方法后期将会继续完善。

如果你需要实现一个复杂的查询并将其转换成对象,你也可以这样:

using( ISession session = SessionFactory.CreateDefaultSession() )
{
string sql = "...";

T @object = session.Find( sql );
}

如何支持事务处理:

using( ISession session = SessionFactory.CreateDefaultSession() )
{
using( DbTransaction transaction = session.BeginTransaction() )
{
// ...
// ...

transaction.Commit();
}
}

SessionHelper的使用:

SessionHelper对session对象的方法进行了静态封装,如果你只是需要执行单条语句,并马上关闭连接,你可以使用 SessionHelper 类中提供的一些辅助方法。

5、如何定义实体类

[Serializable]
public class Person : EntityObject // 需继承与 EntityObject 类
{
private int m_Id;
private string m_Name;
private int? m_Age;
private decimal? m_Money;
private DateTime m_CreateTime;
private bool m_IsActive;

[PrimaryKey, AutoIncrease] // 如果是自增字段,标记为 AutoIncrease;如果是主键标记为 PrimaryKey
public int Id
{
get { return this.m_Id; }
set { this.m_Id = value; this.OnPropertyChanged( "Id", value ); }
}

public string Name
{
get { return this.m_Name; }
set { this.m_Name = value; this.OnPropertyChanged( "Name", value ); }
}

public int? Age
{
get { return this.m_Age; }
set { this.m_Age = value; this.OnPropertyChanged( "Age", value ); }
}

public decimal? Money
{
get { return this.m_Money; }
set { this.m_Money = value; this.OnPropertyChanged( "Money", value ); }
}

public DateTime CreateTime
{
get { return this.m_CreateTime; }
set { this.m_CreateTime = value; this.OnPropertyChanged( "CreateTime", value ); }
}

public bool IsActive
{
get { return this.m_IsActive; }
set { this.m_IsActive = value; this.OnPropertyChanged( "IsActive", value ); }
}
}

6、总结

因作者时间关系,组件目前并非十分完善,测试工作也只简单的进行了一部分,但您可以完全放心的应用于商业项目中,如遇到问题,作者将尽可能的解决。后期还将持续优化,感兴趣且愿意参与开源项目的小伙伴们,请加QQ群:338570336。

另如使用中发现bug,真心希望能分享出来,我们一并修正并改进。

[转载]C#开发微信门户及应用(11)--微信菜单的多种表现方式介绍 - 伍华聪 - 博客园

mikel阅读(1225)

[转载]C#开发微信门户及应用(11)–微信菜单的多种表现方式介绍 – 伍华聪 – 博客园.

在前面一系列文章中,我们可以看到微信自定义菜单的重要性,可以说微信公众号账号中,菜单是用户的第一印象,我们要规划好这些菜单的内容,布局等信 息。根据微信菜单的定义,我们可以看到,一般菜单主要分为两种,一种是普通的Url菜单(类型为View的菜单),一种是事件菜单(类型为Click的菜 单),一般情况下,微信的Url菜单,是无法获得用户的任何信息的,但微信用户信息非常重要,因此也提供了另外一种方式(类似重定向的方式)来给我们使 用,本篇主要介绍这种重新定向的方式菜单的使用,以使我们能够尽可能和用户进行交互。

1、微信自定义菜单的分类

微信对自定义菜单的要求:目前自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单。一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以“…”代替。

根据菜单的分类,我们可以把它通过图形进行分类展示:

我对各种微信公众号进行了解,发现多数账号采用的都是普通的View类型的菜单链接方式,通过它们链接到自己的微网站上,但也有一些做的好的,如省 立中山图书馆,就能通过重定向的方式,提供一个绑定图书馆用户和微信OpenID的入口,绑定后,用户就可以查看借阅的书籍,然后可以通过一键续借功能实 现图书的快速续借功能。

对于这种重定向类型的Url菜单事件,微信的说明如下:

如果用户在微信中(Web微信除外)访问公众号的第三方网页,公众号开发者可以通过此接口获取当前用户基本信息(包括昵称、性别、城市、国家)。利用用户信息,可以实现体验优化、用户来源统计、帐号绑定、用户身份鉴权等功能。请 注意,“获取用户基本信息接口是在用户和公众号产生消息交互时,才能根据用户OpenID获取用户基本信息,而网页授权的方式获取用户基本信息,则无需消 息交互,只是用户进入到公众号的网页,就可弹出请求用户授权的界面,用户授权后,就可获得其基本信息(此过程甚至不需要用户已经关注公众号。)”

2、重定向类型菜单的URL

上面说了,重定向类型的菜单分为了两种,其实他们也仅仅是参数Scope类型的不同,其他部分也还是一样的。

为了展示,我们在假设用户单击菜单的时候,切换到http://www.iqidi.com/testwx.ashx这个页面,并带过来当前用户的OpenID等参数信息

对于scope=snsapi_base方式的链接如下:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx3d81fc2886d86526&redirect_uri=http%3A%2F%2Fwww.iqidi.com%2Ftestwx.ashx&response_type=code&scope=snsapi_base&state=123#wechat_redirect

而对于scope=snsapi_userinfo方式的链接如下:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx3d81fc2886d86526&redirect_uri=http%3A%2F%2Fwww.iqidi.com%2Ftestwx.ashx&response_type=code&scope=snsapi_userinfo&state=123#wechat_redirect

不过他们给手机客户端的体验是不同的,第一种可以平滑切换,但是第二种会弹出一个对话框供用户确认才能继续。

为了演示上面两种获取数据的不同,我把他们传过来的code的值,用户换取OpenID后进行用户信息的解析,他们两者的结果都是一样了。具体测试界面如下所示。

其中TestWX.ashx的页面后台代码如下所示:

///
/// TestWX 的摘要说明
///

public class TestWX : IHttpHandler
{
string appId = ""; //换成你的信息
string appSecret = ""; //换成你的信息

public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
string content = "";

if (context.Request != null &amp;&amp; context.Request.Url != null)
{
NameValueCollection list = HttpUtility.ParseQueryString(context.Request.Url.Query);
foreach (string key in list.AllKeys)
{
content += string.Format("{0}:{1} \r\n", key, list[key]);
}
}

string code = context.Request.QueryString["code"] ?? "";
if (!string.IsNullOrEmpty(code))
{
IBasicApi api = new BasicApi();
try
{
AppConfig config = new AppConfig();
appId = config.AppConfigGet("AppId");//从配置中获取微信程序ID
appSecret = config.AppConfigGet("AppSecret");//从配置中获取微信程序秘钥

AccessTokenResult result = api.GetAccessToken(appId, appSecret, code);
if (result != null)
{
content += string.Format("openid:{0}\r\n", result.openid);

string token = api.GetAccessToken(appId, appSecret);
IUserApi userApi = new UserApi();
UserJson userDetail = userApi.GetUserDetail(token, result.openid);
if (userDetail != null)
{
content += string.Format("nickname:{0} sex:{1}\r\n", userDetail.nickname, userDetail.sex);
content += string.Format("Location:{0} {1} {2} {3}\r\n", userDetail.country, userDetail.province, userDetail.city, userDetail.language);
content += string.Format("HeadUrl:{0} \r\n", userDetail.headimgurl);
content += string.Format("subscribe:{0},{1}\r\n", (userDetail.subscribe == 1) ? "已订阅" : "未订阅", userDetail.subscribe_time.GetDateTime());
}
}
}
catch { }
}

context.Response.Write(content);
}

在上面的代码中,我主要分为几步,一个是打印当前用户重定向过来的链接的参数信息,代码如下。

NameValueCollection list = HttpUtility.ParseQueryString(context.Request.Url.Query);
foreach (string key in list.AllKeys)
{
content += string.Format("{0}:{1} \r\n", key, list[key]);
}

然后获取到Code参数后,通过API接口,获取AccessTokenResult的数据,这里面有用户的OpenID

AccessTokenResult result = api.GetAccessToken(appId, appSecret, code);

当正常调用后,我们把用户标识的OpenID进一步进行解析,调用API获取用户的详细信息,具体代码如下所示。

UserJson userDetail = userApi.GetUserDetail(token, result.openid);

当我们把用户的相关信息获取到了,就可以做各种用户信息的展示了,如下代码所示。

if (userDetail != null)
{
content += string.Format("nickname:{0} sex:{1}\r\n", userDetail.nickname, userDetail.sex);
content += string.Format("Location:{0} {1} {2} {3}\r\n", userDetail.country, userDetail.province, userDetail.city, userDetail.language);
content += string.Format("HeadUrl:{0} \r\n", userDetail.headimgurl);
content += string.Format("subscribe:{0},{1}\r\n", (userDetail.subscribe == 1) ? "已订阅" : "未订阅", userDetail.subscribe_time.GetDateTime());
}

3、重定向链接菜单的用途

这种菜单就是需要指定域名,在微信后台中进行设置,重定向的链接必须属于这个域名之中,否则不会转到你希望的链接。

这个方式,让我们的微信应用程序后台可以获得用户的标识、用户详细信息等,我们就可以用来绑定和用户相关的业务信息了,如上面提到的图书馆借阅信 息,送水客户的信息,客户的积分信息,或者可以和后台账号进行关联实现更加复杂的应用等。用户的身份信息如此重要,如果结合到我们的CRM系统、业务管理 系统,就可以发挥用户信息应用的作用了。

以上就是我对这个类型菜单链接的应用了解,具体还需要进一步深化其应用,希望和大家共同探讨这方面的应用场景。

 

如果对这个《C#开发微信门户及应用》系列感兴趣,可以关注我的其他文章,系列随笔如下所示:

C#开发微信门户及应用(10)–在管理系统中同步微信用户分组信息

C#开发微信门户及应用(9)-微信门户菜单管理及提交到微信服务器

C#开发微信门户及应用(8)-微信门户应用管理系统功能介绍

C#开发微信门户及应用(7)-微信多客服功能及开发集成

C#开发微信门户及应用(6)–微信门户菜单的管理操作

C#开发微信门户及应用(5)–用户分组信息管理

C#开发微信门户及应用(4)–关注用户列表及详细信息管理

C#开发微信门户及应用(3)–文本消息和图文消息的应答

C#开发微信门户及应用(2)–微信消息的处理和应答

C#开发微信门户及应用(1)–开始使用微信接口

主要研究技术:代码生成工具、Visio二次开发、客户关系管理软件、送水管理软件等共享软件开发
专注于Winform开发框架Web开发框架、WCF开发框架的研究及应用。
转载请注明出处:
撰写人:伍华聪  http://www.iqidi.com

[转载]页面UI注意事项,你在乎吗? - 我和小菜 - 博客园

mikel阅读(808)

[转载]页面UI注意事项,你在乎吗? – 我和小菜 – 博客园.

早上打开微信,看到一篇文章,下面就和大家分享一下,该文章属于前端文章系列,希望做后台开发系统的程序员也可以学习一下,只会写代码把功能实现是第一,接下来也要把界面做做好。

现在的界面风格对于手机而言,一直跟随苹果的设计风格,而安卓的很多app在今年也跟随苹果的扁平化风格开始改变UI设计思路

对于后台界面,我想淘宝的后台界面也不可能那么绚丽,也可能很平常普通的界面,但是我想凡事要不断的往前推进,让自己的产品要更好,更能够吸引客户 的眼光,首先UI还是第一个,一个十年前的界面放到现在,可能使用者会已经习惯了,不用再改动了吧,如果当你对UI进行了调整,客户也会赞美很多,下面就 看些注意事项

Good UI是一家研究用户体验的设计机构。我们知道成功的页面设计不仅有很高的转化率更便于用户使用,既能满足商业目标更能为用户带来良好的体验。今天为大家分享一些Good UI 在一些项目中获取的设计以及运营策略等方面的经验。

1. 用通栏布局代替多栏布局

2. 给用户些好处,别急着做生意

3. 整合相似的功能,去掉零碎的UI元素

4.利用社会认同效应,别总是自吹自擂

5.主要功能需要多次强化显示

6.区分选中和可点击的状态,不要使用户困惑

7.布局有层次有重点,而非简单罗列

8. 允许用户撤销操作而不是使用弹窗需要用户确认

9. 明确的告知用户适用人群而不是简单的面向所用用户

10.简洁明了,直接了当

11.页面上多使用对比的方法

12.直接标出产地,别总单纯的讲历史

13.使用简洁的表单

14.把选项列出来而不是藏起来

 

15.使用连续性的提示符,别让用户误以为页面到了终点

16.功能专一而不是使用太多的链接

17.提示体统状态

18. 在动作按钮上增加些吸引人的诱惑

19.用直接操作来代替无数个菜单

20.直接显示输入框可以省略一个页面

21. 用一些动效过度而不用立即显示变化

22. 循序渐进的引导用户而非生硬的要求用户注册

23.试着减少线框,减少不必要的注意

24.向用户展示功能上的便捷之处而不是泛泛的展示特性

25. 用户没有使用记录的时候要善于引导

26. 给出默认的选项而不需要用户选择

27.保持一致性降低用户的学习成本

28. 自动补全一些数据,降低用户的操作负担

29. 尊重用户的使用习惯而不是创造新的规则

30. 提示用户如何规避风险,而不是总想着如何获利

31. 善于引导用户的视觉浏览线,而非单一布局

32. 将相关的条目分组,不要杂乱无章的排列

33.采用及时校验而不是到最后才提示错误

34.需要用户输入的格式宽松严格限定格式

35.让用户有一些紧急的意识,别让用户拖得太久

36. 适当尝试饥饿营销

37. 帮助用户识别

38. 使用更大的点击区域

39. 增加加载的速度,别让用户等太久

40. 可以给用户提供一些快捷操作

41. 使用一些对比

42. 初始化的时候给用户一些激励

43.循序渐进地引导用户,不要简单粗暴地直接呈现给用户

这些注意点,设计师和工程师们,喜欢吗?

[转载]PHP生成二维码【谷歌API+qrcode+圆角Logo】 - 小编络络 - 博客园

mikel阅读(1332)

[转载]PHP生成二维码【谷歌API+qrcode+圆角Logo】 – 小编络络 – 博客园.

这几天在开发公司的企业版块,想在每个企业的展示页面上添加一个公司的二维码,通 过扫描二维码便可以将公司的信息导入手机通讯录中,想法产生了,于是开始搜索PHP生成二维码的方法,比较流行的方法主要有两种:1谷歌二维码API;2 PHP QR CODE;本文将重点介绍这两种方法。

 方法一:谷歌二维码API

接口地址:https://chart.googleapis.com/chart

官方文档:https://developers.google.com/chart/infographics/docs/qr_codes

参数说明:

cht=qr:必要参数,固定值<qr>,表明要生成二维码

chs=<width>x<height>必要参数,生成二维码尺寸,单位是像素,目前生成的二维码都是正方形的,所以两个宽高值都设置为一样的值

chl=<data>必要参数,生成二维码包含的信息,可以是数字、字符、二进制信息、汉字。不能混合数据类型,数据必须经过UTF-8 URL-encoded.如果需要传递的信息超过2K个字节,需使用POST方式

choe=<output_encoding>可选参数,编码格式。包括UTF-8/Shift_JIS/ISO-8859-1三个选项,默认为UTF-8。

chld=<error_correction_level>|<margin>可选参数,

  error_correction_level:容错级别(共分四个等级,L-默认:可以识别已损失的7%的数据;M-可以识别已损失15%的数据;Q-可以识别已损失25%的数据;H-可以识别已损失30%的数据)

  margin:生成的二维码离图片边框的距离

 

例一:扫描二维码打开网址(API)

<!--?php <br ?--> //二维码信息,用urlencode编码
$data = urlencode('http://www.baidu.com');
//生成二维码尺寸
$size = '300x300';
//完整的API地址
$qrurl = "http://chart.googleapis.com/chart?chs=$size&amp;cht=qr&amp;chl=$data&amp;chld=L|1&amp;choe=UTF-8";
//获取二维码
$qrcode = file_get_contents($qrurl);
//输出图片
header('Content-type: image/png');
echo $qrcode;

在打开一个网站之后,我们要来实现归初的目的,扫描二维码,将企业信息导入通讯录,即在二维码中包含一个名片信息,其实二维码说白了就是将一堆信息转换为图片的形式表达,而这堆信息到底是什么样子的它并不关心,真正关心这些信息的是扫描二维码的工具,以上面的例子来说,当你用微信扫描二维码后,微信读取到二维码中储存的数据,然后尝试开始辨别它,当它发现内容是百度的网址时便使用浏览器打开它,同样的当它发现内容是一堆简单的文本数据时便以文本的形式来显示,同样的微信还可以辨别出二维码的内容是不是一个 vcard 格式的电子名片,我们的手机通讯录导入导出的时候大多是这种格式,所以我们可以直接在二维码中包含一个标准的 vcard 电子名片,这样就可以让扫描工具将它识别为通讯录。

vcard 格式参考如下:

BEGIN:VCARD
VERSION:3.0
FN:用户名
TEL;CELL;VOICE:18858140621
TEL;WORK;VOICE:0358-2157466
TEL;WORK;FAX:0358-2157466
EMAIL;PREF;INTERNET:lzw#lzw.me
URL:http://lzw.me
orG:志文工作室
ROLE:产品部
TITLE:CTO
ADR;WORK;POSTAL:北京市朝阳区北四环中路35号;100101
REV:2012-12-27T08:30:02Z
END:VCARD

如果你想更详细的定制所需要的格式,请百度 vcard 的格式标准。

例二:生成一个名片二维码(API)

<!--?php <br ?--> //构建一个 vcard 格式数据
$vcard =
"BEGIN:VCARD".
"\nVERSION:3.0".
"\nFN:小编络络".
"\nTEL;CELL;VOICE:18858140621".
"\nTEL;WORK;VOICE:0358-2157466".
"\nEMAIL:luoluo@qq.com".
"\nURL:http://www.baidu.com".
"\nADR:浙江省杭州市滨江区".
"\nEND:VCARD";

//二维码信息,用urlencode编码
$data = urlencode($vcard);
//生成二维码尺寸
$size = '300x300';
//完整的API地址
$qrurl = "http://chart.googleapis.com/chart?chs=$size&amp;cht=qr&amp;chl=$data&amp;chld=L|1&amp;choe=UTF-8";
//获取二维码
$qrcode = file_get_contents($qrurl);
//输出图片
header('Content-type: image/png');
echo $qrcode;

 到此为止我们归初的目的已经基本实现,但实际使用中,由于直接将上述拼装好的 url 加到了 img 标签的 src 属性,结果出了点小问题,由于我们的名片信息比较多,导致了二维码生成错误,在本文开头已经用红色字体标出,get 方式最多只能传递 2K 大的数据,大于 2K 数据时我们需要使用 POST 请求,所以在实际使用中,可以先在程序中通过 POST 方式获取二维码并保存为本地图片,之后直接调用本地图片即可。

 

方法二:使用 PHP QR CODE 生成二维码

官方主页:http://phpqrcode.sourceforge.net

下载地址:http://sourceforge.net/projects/phpqrcode/

使用方法:QRcode::png($data, $filename , $errorCorrectionLevel, $matrixPointSize, $margin );

    * $data 数据  
    * $filename 生成二维码保存路径,如果为 false 直接输出到浏览器 
    *$errorCorrectionLevel 错误处理级别  L、M、Q、H;同谷歌 API 中纠错级别
    * $matrixPointSize 每个黑点的像素  
    * $margin 图片外围的白色边框像素

 

例三:扫描二维码打开网址(phpqrcode)

<!--?php </p-->

// 包含 qrlib.php 或 phpqrcode.php
// 包含 qrlib.php 需要同其它文件放到一起; phpqrcode.php 是合并后版本,只需要包含这个文件,但生成的图片速度慢而且不太准确
include('./phpqrcode/qrlib.php');

// 二维码数据
$data = 'http://www.111cn.net';

// 纠错级别:L、M、Q、H
$errorCorrectionLevel = 'L';

// 点的大小:1到10
$matrixPointSize = 5;

QRcode::png($data, false, $errorCorrectionLevel, $matrixPointSize, 2);

例二:生成一个名片二维码(phpqrcode)

<!--?php <br ?--> // 包含 qrlib.php 或 phpqrcode.php
include('./phpqrcode/qrlib.php');
// 构建 vcard 数据
$vcard =
"BEGIN:VCARD".
"\nVERSION:3.0".
"\nFN:王歌".
"\nTEL;CELL;VOICE:18858140621".
"\nTEL;WORK;VOICE:0358-2157466".
"\nEMAIL:wang@qq.com".
"\nURL:http://www.mailuow.com".
"\nADR:浙江省杭州市滨江区江虹路1750号".
"\nEND:VCARD";

// 纠错级别:L、M、Q、H
$errorCorrectionLevel = 'L';

// 点的大小:1到10
$matrixPointSize = 4;

QRcode::png($vcard, false, $errorCorrectionLevel, $matrixPointSize, 2);

到此为止我们已经可以用两种方法来实现最初的想法了,但二维码是挂上去了,功能也 实现了,不过总觉得不够华丽,如果再能把企业的 logo 嵌到二维码当中就好了,嘿嘿,当然这部分工作已经不在二维码生成的范筹了,接下来就要靠我们 PHP 中的 GD 库来完成了,但是有一点需要了解,我们在前面提到过二维码的容错级别,即二维码在损毁一部分之后仍有可能解析出完整信息,而给二维码中间添加 logo 后仍能解读出完整信息靠的正是它的高容错性。

网上有找到一些 PHP 生成带 Logo 二维码的方法,但不够细致,生成的二维码很难看,笔者试过好几种方法,现将效果最好的一种拿出来与大家分享。

整体思路如下图:

例五:生成带 Logo 二维码

<!--?php <br ?--> // 包含 qrlib.php 或 phpqrcode.php
include('./phpqrcode/qrlib.php');
// 构建 vcard 数据
$vcard =
"BEGIN:VCARD".
"\nVERSION:3.0".
"\nFN:王歌".
"\nTEL;CELL;VOICE:18858140621".
"\nTEL;WORK;VOICE:0358-2157466".
"\nEMAIL:wang@qq.com".
"\nURL:http://www.mailuow.com".
"\nADR:浙江省杭州市滨江区江虹路1750号".
"\nEND:VCARD";

// 纠错级别:L、M、Q、H
$errorCorrectionLevel = 'M';

// 点的大小:1到10
$matrixPointSize = 4;

// 保存文件名
$filename = 'test.png';

//生成二维码
QRcode::png($vcard, $filename, $errorCorrectionLevel, $matrixPointSize, 2);

//获取二维码
$qrcode = file_get_contents($filename);
$qrcode = imagecreatefromstring($qrcode);
$qrcode_width = imagesx($qrcode);
$qrcode_height = imagesy($qrcode);

//圆角图片
$corner = file_get_contents('./images/corner.png');
$corner = imagecreatefromstring($corner);
$corner_width = imagesx($corner);
$corner_height = imagesy($corner);

//计算圆角图片的宽高及相对于二维码的摆放位置,将圆角图片拷贝到二维码中央
$corner_qr_height = $corner_qr_width = $qrcode_width/5;
$from_width = ($qrcode_width-$corner_qr_width)/2;
imagecopyresampled($qrcode, $corner, $from_width, $from_width, 0, 0, $corner_qr_width, $corner_qr_height, $corner_width, $corner_height);

//logo图片
$logo = file_get_contents('./images/logo.jpg');
$logo = imagecreatefromstring($logo);
$logo_width = imagesx($logo);
$logo_height = imagesy($logo);

//计算logo图片的宽高及相对于二维码的摆放位置,将logo拷贝到二维码中央
$logo_qr_height = $logo_qr_width = $qrcode_width/5 - 6;
$from_width = ($qrcode_width-$logo_qr_width)/2;
imagecopyresampled($qrcode, $logo, $from_width, $from_width, 0, 0, $logo_qr_width, $logo_qr_height, $logo_width, $logo_height);

header('Content-type: image/png');
imagepng($qrcode);
imagedestroy($qrcode);
imagedestroy($corner);
imagedestroy($logo);

 本例中使用到的 corner 图片: 右击另存为

 本例中所有代码示例下载:http://yun.baidu.com/s/1c0ovV6w

 

[转载]C#开发微信门户及应用(7)-微信多客服功能及开发集成 - 伍华聪 - 博客园

mikel阅读(989)

[转载]C#开发微信门户及应用(7)-微信多客服功能及开发集成 – 伍华聪 – 博客园.

最近一直在弄微信的集成功能开发,发现微信给认证账户开通了一个多客服的功能,对于客户的咨询,可以切换至客服处理的方式,而且可以添加多个客服进 行处理,这个在客户咨询比较多的时候,是一个不错的营销功能。微信多客服的功能,能够在很大程度上利用客服员工资源,及时迅速对客户咨询信息进行处理,为 企业带来更多的机会和市场。

默认这个多客服的功能,需要在微信公众平台中的服务中心进行主动开通,默认是不开通的,为了体验这个功能,我这里把多客服功能进行开通。

1、多客服准备工作

微信的多客服功能,对于客服的响应操作,既可以在电脑的客户端上进行操作,也可以在微信多客服助手进行信息处理,两者都能对客户的信息进行回应、结束会话等操作。

开通微信多客服功能后,就需要添加一些处理客户信息的客服工号了。

多客服账号采用“工号@微信号”的形式进行登录,请您在登录窗口依照下图形式输入帐号信息。

2、使用多客服客户端或助手操作

在电脑客户端上使用

在手机客户端上进行多客服的使用,就是关注一个账号,信息通过转发到这里进行处理。关注公众号”多客服助手“就搞定了

通过上面两种途径,能够很好处理客户的相关信息,其实也就是类似电话坐席的方式,让不同的客服员工,对来访的客户进行处理。

3、微信多客服的开发使用

在微信的多客服开发介绍中,内容介绍的比较少,如下所示。

在新的微信协议中,开发模式也可以接入客服系统。 开发者如果需要使用客服系统,需要在接收到用户发送的消息时,返回一个MsgType为transfer_customer_service的消息,微信 服务器在收到这条消息时,会把用户这次发送的和以后一段时间内发送的消息转发客服系统。返回的消息举例如下。

<![CDATA[touser]]>
<![CDATA[fromuser]]>
1399197672
<![CDATA[transfer_customer_service]]>

而在开发的时候,我们一般把它封装为一个实体类信息,如下所示。主要就是指定消息类型,和翻转传入传出对象就可以了。

///
/// 客服消息
///

[System.Xml.Serialization.XmlRoot(ElementName = "xml")]
public class ResponseCustomer : BaseMessage
{
public ResponseCustomer()
{
this.MsgType = ResponseMsgType.transfer_customer_service.ToString().ToLower();
}

public ResponseCustomer(BaseMessage info) : this()
{
this.FromUserName = info.ToUserName;
this.ToUserName = info.FromUserName;
}
}

然后调用处理的时候,代码如下所示。

ResponseCustomer customInfo = new ResponseCustomer(info);
xml = customInfo.ToXml();

如我在客户应答处理里面,客户回应0,我就切换进入客服模式,这样客户后续所有的输入内容,均不会触发微信门户里面的解析,而转发到客服模式,让客服的工号可以和客户进行交谈了。

//处理 0 指令, 人工客服
if (string.IsNullOrEmpty(xml) &amp;&amp; eventKey.Trim() == "0")
{
xml = base.DealEvent(eventInfo, "event_customservice");
}

而在DealEvent里面,根据这个条件进行处理就可以了。

//人工客服
if (eventKey == "event_customservice")
{
ResponseCustomer customInfo = new ResponseCustomer(info);
xml = customInfo.ToXml();
}

通过使用多客服的客户端,这样处理消息交互起来非常方便,能获得客户的对话信息了,在电脑客户端上,看到的界面如下所示。

 

 

手机上的谈话截图如下所示。

 

                 

 

这样就能够通过多途径,及时响应客户的信息了。

 

如果感兴趣或者体验相关的客服应答功能,可以关注我的微信了解下。具体效果可以关注我的微信门户:广州爱奇迪,也可以扫描下面二维码进行关注了解。

 

 

 

 

如果对这个系列感兴趣,可以关注我的其他文章,系列随笔如下所示:

 

C#开发微信门户及应用(6)–微信门户菜单的管理操作

 

C#开发微信门户及应用(5)–用户分组信息管理

 

C#开发微信门户及应用(4)–关注用户列表及详细信息管理

 

C#开发微信门户及应用(3)–文本消息和图文消息的应答

 

C#开发微信门户及应用(2)–微信消息的处理和应答

 

C#开发微信门户及应用(1)–开始使用微信接口

 

 

主要研究技术:代码生成工具、Visio二次开发、客户关系管理软件、送水管理软件等共享软件开发
专注于Winform开发框架Web开发框架、WCF开发框架的研究及应用。
转载请注明出处:
撰写人:伍华聪  http://www.iqidi.com

[转载]Andorid开发学习---ubuntu 12.04下搭建超好用的安卓模拟器genymotion - Hi_Amos - 博客园

mikel阅读(972)

[转载]Andorid开发学习—ubuntu 12.04下搭建超好用的安卓模拟器genymotion – Hi_Amos – 博客园.

什么是Genymotion?

Genymotion是一套完整的工具,它提供了Android虚拟环境。它简直就是开发者、测试人员、推销者甚至是游戏玩家的福音。

Genymotion支持Windows、Linux和Mac OS等操作系统,容易安装和使用:按简单的安装过程,选择一款Android虚拟设备,开启后就体验Genymotion带来的快感吧。—–引自百度百科

 

一.下载并安装genymotion

1.下载genymotion

http://www.genymotion.cn/#theme=download_list 下载列表,必须要先注册才能使用genymotion.

下载Windows快速安装包

这个版本包含Oracle VirtualBox 4.2.12支持,因此您不用再手动下载安装VirtualBox。

其他平台版本

以下版本需要已安装Oracle VirtualBox(下载页面),才能启动虚拟设备。

注意:对于Debian系统的用户,为了获得最佳渲染,我们建议您安装libpngX(X取决于您的Debian版本)
下载IntelliJ IDEA插件
注意:如果要使用此插件,您的系统必须已经安装Genymotion
下载Eclipse插件
此插件也可以通过Eclipse直接安装:Help->Install New Software,然后添加下面的地址:http://plugins.genymotion.com/eclipse
注意:如果要使用此插件,您的系统必须已经安装Genymotion
目前最新版的是2.2.0版本的,建议同时下载其IDE插件,这里我下载了Eclipse插件,这里将jar包拷到eclipse/plugins目录下重启eclipse即可.

2.安装genymotion

下载完后.执行下面三个命令,

amosli@amosli-pc:~/workspace/genymotion$ ./genymotion-2.2.0_x64.bin 
amosli@amosli-pc:~/workspace/genymotion$ cd genymotion/
amosli@amosli-pc:~/workspace/genymotion/genymotion$ ./genymotion

如果没有安装vitualbox,那么会提示要安装vitualbox,可以接着安装vitualbox;已安装的可以跳过下面的内容.

二.下载.安装vitualbox

 1.下载vitualbox

https://www.virtualbox.org/wiki/Linux_Downloads

VirtualBox 4.3.10 for Linux

Note: The package architecture has to match the Linux kernel architecture, that is, if you are running a 64-bit kernel, install the appropriate AMD64 package (it does not matter if you have an Intel or an AMD CPU). Mixed installations (e.g. Debian/Lenny ships an AMD64 kernel with 32-bit packages) are not supported. To install VirtualBox anyway you need to setup a 64-bit chroot environment.

Please choose the appropriate package for your Linux distribution:

这里我选择的是ubuntu 12.04 amd64 位的.下载速度挺慢的,可以从sourceforge上面下载(http://sourceforge.jp/projects/sfnet_virtualbox.mirror/releases/),速度稍微快一点点,其实也差不多.

 

2.安装vitualbox

如果是deb格式的数据可以直接双击安装.

同时要加入一下其密钥:http://download.virtualbox.org/virtualbox/debian/oracle_vbox.asc

amosli@amosli-pc:~/Desktop$ sudo apt-key add oracle_vbox.asc
[sudo] password for amosli: 
OK

Ubuntu的/ Debian的用户可能要安装DKMS软件包,以确保VirtualBox主机的内核模块( vboxdrv , vboxnetflt和vboxnetadp )得到正确更新,可以执行下面的命令进行安装:

amosli@amosli-pc:~$ sudo apt-get install dkms

 

三.启动genymotion

安装完vitualbox后,再次重新启动genymotion

 

 

 

 

[转载]为 Node.js 开发者准备的8本免费在线电子书_IT新闻_博客园

mikel阅读(1034)

[转载]为 Node.js 开发者准备的8本免费在线电子书_IT新闻_博客园.  Node.js 是一套用来编写高性能网络服务器的 JavaScript 工具包,一系列的变化由此开始。比较独特的是,Node.js 会假设你是在 POSIX 环境下运行它 Linux 或 Mac OS X。如果你是在 Windows 下,那就需要安装 MinGW 以获得一个仿 POSIX 的环境。在 Node 中,Http 是首要的。Node 为创建 http 服务器作了优化,所以你在网上看到的大部分示例和库都是集中在 web 上(http 框架、模板库等)。

本文向你推荐 8 本免费的在线 Node.js 电子书。

1) Best Node.js eBook –  Node Beginner

http://static.oschina.net/uploads/img/201405/16071221_qumk.png

  2) Free Node.js eBook – Smashing Node

best free ebooks for node.js - smashingnodejs

  3) Best Free Node.js eBook – MasteringNode

best free ebooks for node.js - masteringnode

  4) Best Node.js eBook – Mixu’s Node

best free ebooks for node.js - mixunode

  5) Free Node.js eBook – Node: Up and Running

best free ebooks for node.js - nodejs

  6) Node.js Book – Node Guide

best free ebooks for node.js - nodeguide

  7) Pro Node.js for Developers

best free ebooks for node.js - pro-node

  8) Best Book –  Node.js the Right Way

node

[转载]Winform调用QQ发信息并且开机启动 (开源) - 我和小菜 - 博客园

mikel阅读(1058)

[转载]Winform调用QQ发信息并且开机启动 (开源) – 我和小菜 – 博客园.

前言

公司CS系统需要加入启动qq从winform调用qq聊天窗口的功能,前提是需要将聊天者的QQ号码作为参数传递到函数中,一直没有搞过,正好很感兴趣,就折腾,Winform调用qq,我想肯定是需要一些编码思路,下面列出编码前思路图

  1. 检查QQ安装后在注册表中的具体路径
  2. 根据注册表找到调用QQ程序的exe完整路径(Timwp.exe)
  3. 启动,达到winform调用QQ的要求

先看简单测试界面

步骤1

找到QQ的注册表路径,经过百度之后分析得到思路,正确的路径

32位QQ安装后注册表路径SOFTWARE\Tencent\QQ2009

64位QQ安装后注册表路径SOFTWARE\Wow6432Node\Tencent\QQ2009

64位系统注册表路径截图演示

步骤2

当我们找到注册表的路径后就已经很开心,就可以通过这个路径通过方法得到QQ实际安装路径在系统中的安装路径,图中就是需要我们启动的QQ安装的实际程序路径,得到这个路径就一次接近80%了。

 

步骤3

这一步再完成10%的代码,请求这个exe文件的时候,我们肯定需要提供给它,聊天的qq号码是什么,需要构建启动该进程时传递的命令行实参,也就是这一行代码,相信大家都看得懂,你只需要着一行字符串,作为启动进程的参数就可以了。

步骤4

将找到的文件路径和请求参数字符串作为参数调用启动进程资源就ok,100%了

成功效果图

截止到上面,我们完成了winform调用QQ快捷聊天的功能,下面说一下网页调动的方法

分析:启动浏览器进程,打开特定请求QQ链接的URL

效果截图:

下面来看个难一点的就是开机启动,对于很多的CS程序,开机启动都是一个比较好的,让客户认识记住软件的小方法,但是现在360太强大,经常动不动就说这个程序影响开机速度,不得很多程序被他给阻挡,但是这里因为兴趣爱好,还是研究一下。

分析思路

  1. 跟注册表有关,开机启动也是注册表中的某个路径
  2. 将指定启动的程序字符串写入注册中
  3. 开机自动会启动

下面系统代码截图

运行调试截图:

管理员身份运行截图:

在运行调试的过程中,由于测试电脑系统是win8,安全等级比较高,一直没有权限写入注册表,如果是以管理员身份启动就可以写入注册表中

开源代码:http://download.csdn.net/detail/mryanghenglian/7353877

希望对大家有用,可以加入我的群:IT(霸气测漏),请尊重我的劳动成果,转载请说明来源,谢谢

如果你觉得文章对你有帮助,可以收藏下次项目中遇到了可以翻出来研究一下,还希望大家可以推荐一下