deerchao的blog

Be and aware of who you are.

置顶随笔

[置顶]正则表达式30分钟入门教程

     摘要: 别被下面那些复杂的表达式吓倒,只要跟着我一步一步来,你会发现正则表达式其实并不像你想像中的那么困难。当然,如果你看完了这篇教程之后发现自己明白了很多,却又几乎什么都记不得,那也是很正常的--其实我认为没接触过正则表达式的人在看完这篇教程后能把提到过的语法记住80%以上的可能性为零。这里只是让你明白基本道理,以后你还需要多练习,多查资料,才能熟练掌握正则表达式。  阅读全文

posted @ 2006-08-24 22:04 deerchao 阅读(25574) | 评论 (609)编辑

2009年4月5日

A fast object clone class - using Expression.Compile()

写过一个负责对象克隆功能的类,最近改进了一下,提升了30%的效率:

Code

posted @ 2009-04-05 13:50 deerchao 阅读(126) | 评论 (0)编辑

2009年3月16日

jQuery.combobox, 给文本框添加下拉选项的轻量级插件

Description

jQuery.combobox is a lightweight jQuery plugin which transforms a textbox into a combobox, so users can enter text or select from supplied options.

It could be called more than once on the same textbox, however only the first time calling counts -- which means you can't change the suggestions once the combobox is created.

It would work with jQuery.bgiframe plugin to fix the IE select/zIndex bug if you include it in the same page.

Tested in IE 7, Firefox 3.

Updates

2009-3-18
Suggestion matching is now case-insensitive
The second time setting up combobox on the same textbox is working now
Fixed the IE relative z-index bug by avoiding relative positioning

Demostartion

Combobox 1

Combobox 2

This is a select box to see if there is a problem in IE.

Usage

Html

<input class="combo" />

Script

<link href="jquery.combobox.css" rel="stylesheet" />
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jquery.combobox.min.js"></script>

jQuery('.combo').combobox(['option1', 'option2', 'option3', ...], {imageUrl : '/images/dropdown.gif'});

 

Copyright

It's released under the MIT licence, so use it however you want.

By deerchao@gmail.com on 2009-3-16

Download

http://files.cnblogs.com/deerchao/jquery.combobox.zip

posted @ 2009-03-16 15:43 deerchao 阅读(1154) | 评论 (3)编辑

2009年3月7日

CDTray, 打开,关闭光驱的系统托盘程序

今天买了一台内置刻录机,安装完成后发现机箱提供的面板设计不太合理:光驱门打开后,按钮就根本没有用了,因为它附着在门上,与光驱本身提供的开仓按钮根本连不上了,于是我只能用手推动光盘托才能把光驱门给关上. 

郁闷之余,写了一个小工具来解决这个问题:

最核心的东西--开关光驱门,其实很简单:

Code
        public static void Open(string driveLetter)
        {
            
string returnString = "";
            mciSendStringA(
"set cdaudio!" + driveLetter + " door open", returnString, 00);
        }

        
public static void Close(string driveLetter)
        {
            
string returnString = "";
            mciSendStringA(
"set cdaudio!" + driveLetter + " door closed", returnString, 00);
        }

        [DllImport(
"winmm.dll", EntryPoint = "mciSendStringA")]
        
public static extern void mciSendStringA(string lpstrCommand, string lpstrReturnString, long uReturnLength, long hwndCallback);

 

上面的代码是从网上搜索得到的.我本来想判断一下光驱本身的状态--是开还是关,但是搜索了十来分钟,没找到相关资料,觉得这个也不是特别有必要,于是放弃了.

好了,下面就要获取系统里所有光驱了,其实很简单,一行代码就搞定:

 

Code
        public static string[] GetCDRoms()
        {
            
return DriveInfo.GetDrives().Where(x => x.DriveType == DriveType.CDRom).Select(x => x.Name).ToArray();
        }

 

为了让程序用起来更方便,我希望它能设置为随Windows自动启动.这个也没什么困难的,就是操作注册表而已,于是我从原来写的代码里扒出了一段,重新加工了一下:

 

Code
    class AutoLaunch
    {
        
string registryKey;

        
public AutoLaunch(string registryKey)
        {
            
this.registryKey = registryKey;
        }

        
string GetRunningExePath()
        {
            
return Application.ExecutablePath;
        }

        
public bool Enabled
        {
            
get
            {
                
try
                {
                    RegistryKey key 
= Registry.CurrentUser.OpenSubKey("Software");
                    key 
= key.OpenSubKey("Microsoft");
                    key 
= key.OpenSubKey("Windows");
                    key 
= key.OpenSubKey("CurrentVersion");
                    key 
= key.OpenSubKey("Run"true);

                    
string cmdline = key.GetValue(registryKey) as string;
                    
if (cmdline == null)
                    {
                        
return false;
                    }
                    
else
                    {
                        
if (!string.Equals(cmdline, GetRunningExePath(), StringComparison.OrdinalIgnoreCase))
                            key.SetValue(registryKey, GetRunningExePath());
                        
return true;
                    }
                }
                
catch (NullReferenceException)
                {
                    
return false;
                }
            }
            
set
            {
                RegistryKey key 
= Registry.CurrentUser.OpenSubKey("Software");
                key 
= key.OpenSubKey("Microsoft");
                key 
= key.OpenSubKey("Windows");
                key 
= key.OpenSubKey("CurrentVersion");
                key 
= key.OpenSubKey("Run"true);

                
if (value)
                {
                    key.SetValue(registryKey, GetRunningExePath());
                }
                
else
                {
                    key.DeleteValue(registryKey, 
false);
                }
            }
        }

    }

 

 

好了,现在可以做界面了.由于程序非常的简单,我选择了使用Windows Forms,而且决定一个窗口都不要,用户能看到的全部界面就是通知区域的一个图标.

那好的,在一个空白的Form上扔一个NotifyIcon,和一个ContextMenuStrip,并把NotifyIcon的ContextMenuStrip属性设置好.

然后就是我们的代码了,用于在Form的构造时,动态生成菜单内容:

 

Code
        AutoLaunch autoLaunch;
        
public Form1()
        {
            InitializeComponent();
            Init();
        }

        
private void Init()
        {

            ShowInTaskbar 
= false;
            WindowState 
= FormWindowState.Minimized;
            autoLaunch 
= new AutoLaunch("CDTool_deerchao");

            LoadMenu();
        }

 

 

Code
        private void LoadMenu()
        {
            var menuItems 
= new List<ToolStripItem>();

            menuItems.Add(
new ToolStripMenuItem
            {
                Text 
= "By deerchao",
            });
            menuItems.Add(
new ToolStripSeparator());

            
foreach (var cd in CDDrive.GetCDRoms())
            {
                menuItems.AddRange(LoadMenu(cd).Cast
<ToolStripItem>());

                menuItems.Add(
new ToolStripSeparator());
            }

            var autoStart 
= new ToolStripMenuItem("&Start with Windows"null, (s, e) => autoLaunch.Enabled = ((ToolStripMenuItem)s).Checked)
            {
                CheckOnClick 
= true,
                Checked 
= autoLaunch.Enabled,
            };

            var exit 
= new ToolStripMenuItem("E&xit"null, (s, e) => Application.Exit());
            menuItems.Add(autoStart);
            menuItems.Add(exit);

            contextMenu.Items.AddRange(menuItems.ToArray());
        }

        
private IEnumerable<ToolStripMenuItem> LoadMenu(string cd)
        {
            var open 
= new ToolStripMenuItem("&Open " + cd.Substring(02), null, (s, e) => CDDrive.Open(cd));
            var close 
= new ToolStripMenuItem("&Close " + cd.Substring(02), null, (s, e) => CDDrive.Close(cd));

            
yield return open;
            
yield return close;
        }

 

 

很好,现在运行起来就一切OK了.

但是,追求完美的我们怎么会如此轻易罢休呢..我们可以看到,代码里多处用到了Linq扩展方法,比如Where, Cast, Select, ToArray等. 而Linq则是.Net 3.5里才有的新东西..那意味着这个程序的用户,要去下载200多M的.Net 3.5安装程序,然后花两个小时来安装它,最后才能使用这个不到200K的小工具...

怎么办?打造山塞版的Linq吧,还好,我们使用到的Linq特性并不多,只要几十行代码就能完成:

 

Code
using System.Collections;
using System.Collections.Generic;

namespace System.Linq
{
    
delegate TResult Func<TSource, TResult>(TSource source);

    
static class Enumerable
    {
        
public static IEnumerable<T> Where<T>(this IEnumerable<T> source, Predicate<T> predict)
        {
            
foreach (var v in source)
                
if (predict(v))
                    
yield return v;
        }

        
public static IEnumerable<TDest> Cast<TDest>(this IEnumerable source)
        {
            
foreach (var v in source)
                
yield return (TDest)v;
        }

        
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> mapping)
        {
            
foreach (var v in source)
                
yield return mapping(v);
        }

        
public static List<T> ToList<T>(this IEnumerable<T> source)
        {
            
return new List<T>(source);
        }

        
public static T[] ToArray<T>(this IEnumerable<T> source)
        {
            
return ToList(source).ToArray();
        }
    }

}

namespace System.Runtime.CompilerServices
{
    
class ExtensionAttribute : Attribute
    {
    }
}

 

OK,把针对的.Net Framework版本改成2.0,砍掉不必要的引用项,重新编译,搞定!

现在唯一让我不爽的就是没有一个好图标了...好吧,我们从微软那里借一个来吧.操起刚Google来的图标编辑工具IcoFx,在File\Extract里选择C:\Windows\System32\imagers.dll,从里边挑选一个光盘图标,保存.

在项目里设置好图标以后,重新编译,That's All!

你可以从这里下载全部源代码.

posted @ 2009-03-07 16:15 deerchao 阅读(396) | 评论 (1)编辑

2009年2月23日

jQuery.Excel, 使用Ctrl+方向键/Home/End在input表格中移动

Code
// Enable user to move focus in a grid of inputs with Ctrl + Up, Down, Left, Right, Home, End
//
 Could be called again after more rows are created.
//
 deerchao@gmail.com   2009-2-23

// usage:
//
--------------Html----------------
//
  <tr class="dataRow">
//
      <td><input /></td>
//
      <td><input /></td>
//
      <td><input /></td>
//
  </tr>
//
  <tr class="dataRow">
//
      <td><input /></td>
//
      <td><input /></td>
//
      <td><input /></td>
//
  </tr>
//
--------------Script-------------
//
 jQuery.excel('dataRow');

jQuery.extend({
    excel: 
function(rowClass) {
        
var keys = { left: 37, up: 38, right: 39, down: 40, home: 36, end: 35 };
        rowClass 
= rowClass ? rowClass : '.excel';
        
if (rowClass[0!= '.')
            rowClass 
= '.' + rowClass;

        $(rowClass).unbind('keyup',onkeyup).bind(
'keyup',onkeyup);

        
function onkeyup(evt) {
            
var ctrlOnly = evt.ctrlKey && !evt.altKey && !evt.shiftKey;
            
switch (evt.keyCode) {
                
case keys.down:
                    go(
"down");
                    
break;
                
case keys.up:
                    go(
"up");
                    
break;
                
case keys.left:
                    
if (ctrlOnly)
                        go(
"left");
                    
break;
                
case keys.right:
                    
if (ctrlOnly)
                        go(
"right");
                    
break;
                
case keys.home:
                    
if (ctrlOnly)
                        go(
"home");
                    
break;
                
case keys.end:
                    
if (ctrlOnly)
                        go(
"end");
                    
break;
            }

            
function go(to) {
                
var td = $(evt.target).closest('td');
                
var tr = $(evt.currentTarget);
                
var toFocus = null;
                
switch (to) {
                    
case 'home':
                        toFocus 
= lastInput(td.prevAll('td'));
                        
break;
                    
case 'end':
                        toFocus 
= lastInput(td.nextAll('td'));
                        
break;
                    
case 'left':
                        toFocus 
= firstInput(td.prevAll('td'));
                        
if (!toFocus)
                            toFocus 
= lastInput(tr.prev('tr' + rowClass).children('td'));
                        
break;
                    
case 'right':
                        toFocus 
= firstInput(td.nextAll('td'));
                        
if (!toFocus)
                            toFocus 
= firstInput(tr.next('tr' + rowClass).children('td'));
                        
break;
                    
case 'up':
                        toFocus 
= firstInput(tr.prev('tr' + rowClass).children('td'), td.prevAll('td').size());
                        
break;
                    
case 'down':
                        toFocus 
= firstInput(tr.next('tr' + rowClass).children('td'), td.prevAll('td').size());
                        
break;
                }
                
if (toFocus) {
                    toFocus.focus();
                }
            }

            
function firstInput(tds, start) {
                
if (!start)
                    start 
= 0;
                
for (var i = start; i < tds.size(); i++) {
                    
var inputs = $(tds[i]).children('input, select, textarea');
                    
if (inputs.size())
                        
return inputs[0];
                }
                
return null;
            }

            
function lastInput(tds) {
                
for (var i = tds.size() - 1; i >= 0; i--) {
                    
var inputs = $(tds[i]).children('input, select, textarea');
                    
if (inputs.size())
                        
return inputs[0];
                }
                
return null;
            }
        }
    }
});

 

 

posted @ 2009-02-23 18:17 deerchao 阅读(545) | 评论 (0)编辑

2009年1月22日

原来Queryable是这样实现的..

一直没去细想为什么Enumerable和Queryable提供了两套签名一致的方法.今天在扩展IQToolkit,使之支持Insert/Update/Delete的过程中,遇到了问题,用Reflector看了一下Queryable类的源码,顿时醍醐灌顶.

在给代表数据库表格的类EntityTable(实现了IQueryable<TEntity>接口)添加一个扩展方法Delete(Expression<Predicate<TEntity>>)来做生成Delete语句的标识时,发现这个方法被直接调用了,觉得很郁闷.明明微软自己的Where, Select等方法都没被调用,而是作为Expression给传到了QueryProvider里, 凭什么我自己写的方法你就不给翻译一下传过去,而是当场执行呢?

不对啊,First, Single之类的方法也是当场执行的啊,难道编译器会根据方法的返回类型(是不是相同的IQueryable<T>)来决定如何对待它们?或者,可能有某个应用于方法上的Attribute,可以控制编译器这方面的行为?

还是看看Queryable里的代码是怎么写的吧.打开Reflector一看Queryable.First方法,马上明白了:

public static TSource First<TSource>(this IQueryable<TSource> source)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    return source.Provider.Execute<TSource>(Expression.Call(null, ((MethodInfo) MethodBase.GetCurrentMethod()).MakeGenericMethod(new Type[] { typeof(TSource) }), new Expression[] { source.Expression }));
}

晕了,原来根本不是编译器在捣鬼!这方法纯粹是一混蛋,屁事不干的主.不单屁事不干,还指使别人说,你再来调用我吧..

再看Queryable.Where:

public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    if (predicate == null)
    {
        throw Error.ArgumentNull("predicate");
    }
    return source.Provider.CreateQuery<TSource>(Expression.Call(null, ((MethodInfo) MethodBase.GetCurrentMethod()).MakeGenericMethod(new Type[] { typeof(TSource) }), new Expression[] { source.Expression, Expression.Quote(predicate) }));
}

First和Where的区别在于两者调用了不同的方法,一个要求直接执行对应的动作,一个要求返回一个新的IQueryable<T>对象以推迟实际行为的发生.

哎,这世界上怎么那么多比我聪明的人呢?

posted @ 2009-01-22 00:05 deerchao 阅读(168) | 评论 (2)编辑

<2009年7月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

导航

统计

公告

给网络添加价值,就是让自己增加价值.

本博客所有内容,均为原创或对互联网已有资源的再加工,希望对你有用.在声明原作者的前提下,你可以任意使用,但本人对其正确性,使用的后果等不做任何担保,也不负任何责任.

正则表达式30分钟入门教程 v2.21 2007-8-3

I Want Spec#!

捐献 != 攀比 != 作秀 != 摊派 !=勒索

与我联系

搜索

 

常用链接

留言簿

我管理的小组

我参加的小组

我的标签

随笔档案(136)

文章分类(9)

文章档案(9)

新闻档案(9)

Links

积分与排名

最新评论

评论排行榜