Updates from 五月, 2009

  • 北京对角巷科技招聘技术团队成员

    shishirui 11:37 on 2009/05/31 | 0 Permalink | Reply

    http://jobsdigg.com/story/568

    很有意思的招聘

     
  • MYSQL索引

    shishirui 15:29 on 2009/05/27 | 0 Permalink | Reply

    http://blog.csdn.net/feng_sundy/archive/2006/04/19/669324.aspx

    http://space.itpub.net/9842/viewspace-312607

    http://blog.chinaunix.net/u/14468/showart_441875.html

     
  • 关于FLOAT DOUBLE DECIMAL类型

    shishirui 18:20 on 2009/05/26 | 0 Permalink | Reply

    http://blog.sina.com.cn/s/blog_494b7b9201000988.html

    http://www.phpchina.com/html/28/1628-20455.html

     
  • DES加密(PHP)

    shishirui 16:22 on 2009/05/26 | 0 Permalink | Reply

    $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_DES, MCRYPT_MODE_ECB), MCRYPT_RAND);
    $card = base64_encode(mcrypt_encrypt(MCRYPT_DES, $key, $card, MCRYPT_MODE_ECB, $iv));

    $key 是密钥,如果在DES模式,则key是不超过8位的字符串,如果是CBC模式,则是不超过24位的字符串。

    $card 是被加密的字符串。

    注意,一般情况下base64_encode或bin2hex后进行传输,当然也有别的情况,用时应该根据情况转码后传输,否则会让对方无法解密。

     
  • C#多线程操作界面控件的解决方案

    shishirui 21:57 on 2009/05/23 | 0 Permalink | Reply

    在.Net2.0环境上开发WinForm程序,当在多线程中修改界面控件的状态,会抛出一个异常:Cross-thread operation not valid:Control 'textBox1' accessed from a thread other than the thread it was created on .后查询知道这是因为.net 2.0以后加强了安全机制,不允许在winform中直接跨线程访问控件的属性。到网上Google下,找到的解决方案有三种,现将这三种解决方案整理如下:

    首先写下原先的代码:

    public partial class Form1 : Form
    {
    public Form1()
    {
    InitializeComponent();
    }
    private void Form1_Load(object sender, EventArgs e)
    {
    Thread thread = new Thread(ThreadFuntion);
    thread.IsBackground = true;
    thread.Start();
    }
    private void ThreadFuntion()
    {
    while (true)
    {
    this.textBox1.Text = DateTime.Now.ToString();
    Thread.Sleep(1000);
    }
    }
    }

    第一种解决方案:

    我们在Form1_Load()方法中加一句代码:

    private void Form1_Load(object sender, EventArgs e)
    {
    Control.CheckForIllegalCrossThreadCalls = false;
    Thread thread = new Thread(ThreadFuntion);
    thread.IsBackground = true;
    thread.Start();
    }
    加入这句代码以后发现程序可以正常运行了。这句代码就是说在这个类中我们不检查跨线程的调用是否合法(如果没有加这句话运行也没有异常,那么说明系统以及默认的采用了不检查的方式)。然而,这种方法不可取。我们查看CheckForIllegalCrossThreadCalls 这个属性的定义,就会发现它是一个static的,也就是说无论我们在项目的什么地方修改了这个值,他就会在全局起作用。而且像这种跨线程访问是否存在异常,我们通常都会去检查。如果项目中其他人修改了这个属性,那么我们的方案就失败了,我们要采取另外的方案。

    第二种解决方案:

    就是使用delegate和invoke来从其他线程中控制控件信息。网上有很多人写了这种控制方式,然而我看了很多这种帖子,表明上看来是没有什么问题的,但是实际上并没有解决这个问题,首先来看网络上的那种不完善的方式:

    public partial class Form1 : Form
    {
    private delegate void FlushClient();//代理
    public Form1()
    {
    InitializeComponent();
    }
    private void Form1_Load(object sender, EventArgs e)
    {
    Thread thread = new Thread(CrossThreadFlush);

    thread.IsBackground=true;
    thread.Start();
    }

    private void CrossThreadFlush()
    {
    //将代理绑定到方法
    FlushClient fc = new FlushClient(ThreadFuntion);
    this.BeginInvoke(fc);//调用代理
    }
    private void ThreadFuntion()
    {
    while (true)
    {
    this.textBox1.Text = DateTime.Now.ToString();
    Thread.Sleep(1000);
    }
    }
    }

    使用这种方式我们可以看到跨线程访问的异常没有了。但是新问题出现了,界面没有响应了。为什么会出现这个问题,我们只是让新开的线程无限循环刷新,理论上应该不会对主线程产生影响的。其实不然,这种方式其实相当于把这个新开的线程“注入”到了主控制线程中,它取得了主线程的控制。只要这个线程不返回,那么主线程将永远都无法响应。就算新开的线程中不使用无限循环,使可以返回了。这种方式的使用多线程也失去了它本来的意义。

    第三中解决方案,也是我推荐的解决方案:

    public partial class Form1 : Form
    {
    private delegate void FlushClient();//代理
    public Form1()
    {
    InitializeComponent();
    }
    private void Form1_Load(object sender, EventArgs e)
    {
    Thread thread = new Thread(CrossThreadFlush);
    thread.IsBackground = true;
    thread.Start();
    }

    private void CrossThreadFlush()
    {
    while (true)
    {
    //将sleep和无限循环放在等待异步的外面
    Thread.Sleep(1000);
    ThreadFunction();
    }
    }
    private void ThreadFunction()
    {
    if (this.textBox1.InvokeRequired)//等待异步
    {
    FlushClient fc = new FlushClient(ThreadFunction);
    this.Invoke(fc);//通过代理调用刷新方法
    }
    else
    {
    this.textBox1.Text = DateTime.Now.ToString();
    }
    }
    }

    运行上述代码,我们可以看到问题已经被解决了,通过等待异步,我们就不会总是持有主线程的控制,这样就可以在不发生跨线程调用异常的情况下完成多线程对winform多线程控件的控制了

     
  • 使用委托(C# 编程指南)

    shishirui 22:45 on 2009/05/20 | 0 Permalink | Reply

    委托是一种安全地封装方法的类型,它与 C 和 C++ 中的函数指针类似。与 C 中的函数指针不同,委托是面向对象的、类型安全的和保险的。委托的类型由委托的名称定义。下面的示例声明了一个名为 Del 的委托,该委托可以封装一个采用字符串作为参数并返回 void 的方法。

    public delegate void Del(string message);

    构造委托对象时,通常提供委托将包装的方法的名称或使用匿名方法。实例化委托后,委托将把对它进行的方法调用传递给方法。调用方传递给委托的参数被传递给方法,来自方法的返回值(如果有)由委托返回给调用方。这被称为调用委托。可以将一个实例化的委托视为被包装的方法本身来调用该委托。例如:

    // Create a method for a delegate.
    public static void DelegateMethod(string message)
    {
    System.Console.WriteLine(message);
    }

    // Instantiate the delegate.
    Del handler = DelegateMethod;

    // Call the delegate.
    handler("Hello World");

    委托类型派生自 .NET Framework 中的 Delegate 类。委托类型是密封的,不能从 Delegate 中派生委托类型,也不可能从中派生自定义类。由于实例化委托是一个对象,所以可以将其作为参数进行传递,也可以将其赋值给属性。这样,方法便可以将一个委托作为参数来接受,并且以后可以调用该委托。这称为异步回调,是在较长的进程完成后用来通知调用方的常用方法。以这种方式使用委托时,使用委托的代码无需了解有关所用方法的实现方面的任何信息。此功能类似于接口所提供的封装。有关更多信息,请参见何时使用委托而不使用接口。

    回调的另一个常见用法是定义自定义的比较方法并将该委托传递给排序方法。它允许调用方的代码成为排序算法的一部分。下面的示例方法使用 Del 类型作为参数:

    public void MethodWithCallback(int param1, int param2, Del callback)
    {
    callback("The number is: " + (param1 + param2).ToString());
    }

    然后可以将上面创建的委托传递给该方法:

    MethodWithCallback(1, 2, handler);

    在控制台中将收到下面的输出:

    The number is: 3

    在将委托用作抽象概念时,MethodWithCallback 不需要直接调用控制台 -- 设计它时无需考虑控制台。MethodWithCallback 的作用只是准备字符串并将该字符串传递给其他方法。此功能特别强大,因为委托的方法可以使用任意数量的参数。

    将委托构造为包装实例方法时,该委托将同时引用实例和方法。除了它所包装的方法外,委托不了解实例类型,所以只要任意类型的对象中具有与委托签名相匹配的方法,委托就可以引用该对象。将委托构造为包装静态方法时,它只引用方法。考虑下列声明:

    public class MethodClass
    {
    public void Method1(string message) { }
    public void Method2(string message) { }
    }

    加上前面显示的静态 DelegateMethod,现在我们有三个方法可由 Del 实例进行包装。

    调用委托时,它可以调用多个方法。这称为多路广播。若要向委托的方法列表(调用列表)中添加额外的方法,只需使用加法运算符或加法赋值运算符(“+”或“+=”)添加两个委托。例如:

    MethodClass obj = new MethodClass();
    Del d1 = obj.Method1;
    Del d2 = obj.Method2;
    Del d3 = DelegateMethod;

    //Both types of assignment are valid.
    Del allMethodsDelegate = d1 + d2;
    allMethodsDelegate += d3;

    此时,allMethodsDelegate 在其调用列表中包含三个方法 -- Method1、Method2 和 DelegateMethod。原来的三个委托 d1、d2 和 d3 保持不变。调用 allMethodsDelegate 时,将按顺序调用所有这三个方法。如果委托使用引用参数,则引用将依次传递给三个方法中的每个方法,由一个方法引起的更改对下一个方法是可见的。如果任一方法引发了异常,而在该方法内未捕获该异常,则该异常将传递给委托的调用方,并且不再对调用列表中后面的方法进行调用。如果委托具有返回值和/或输出参数,它将返回最后调用的方法的返回值和参数。若要从调用列表中移除方法,请使用减法运算符或减法赋值运算符(“-”或“-=”)。例如:

    //remove Method1
    allMethodsDelegate -= d1;

    // copy AllMethodsDelegate while removing d2
    Del oneMethodDelegate = allMethodsDelegate - d2;

    由于委托类型派生自 System.Delegate,所以可在委托上调用该类定义的方法和属性。例如,为了找出委托的调用列表中的方法数,您可以编写下面的代码:

    int invocationCount = d1.GetInvocationList().GetLength(0);

    在调用列表中具有多个方法的委托派生自 MulticastDelegate,这是 System.Delegate 的子类。由于两个类都支持 GetInvocationList,所以上面的代码在两种情况下都适用。

    多路广播委托广泛用于事件处理中。事件源对象向已注册接收该事件的接收方对象发送事件通知。为了为事件注册,接收方创建了旨在处理事件的方法,然后为该方法创建委托并将该委托传递给事件源。事件发生时,源将调用委托。然后,委托调用接收方的事件处理方法并传送事件数据。给定事件的委托类型由事件源定义。有关更多信息,请参见事件(C# 编程指南)。

    在编译时,对分配了两种不同类型的委托进行比较将产生编译错误。如果委托实例静态地属于类型 System.Delegate,则允许进行比较,但在运行时将返回 false。例如:

    delegate void Delegate1();
    delegate void Delegate2();

    static void method(Delegate1 d, Delegate2 e, System.Delegate f)
    {
    // Compile-time error.
    //Console.WriteLine(d == e);

    // OK at compile-time. False if the run-time type of f
    //is not the same as that of d.
    System.Console.WriteLine(d == f);
    }

     
  • Calibri字体

    shishirui 09:25 on 2009/05/14 | 0 Permalink | Reply

    12px的Calibri还是蛮好看的

    calibri

     
  • PHP判断字符串编码并且获取字符串中的中文

    shishirui 12:49 on 2009/05/12 | 0 Permalink | Reply

    参考URL:http://www.w3.org/International/questions/qa-forms-utf-8.en.php

    $result = preg_match(’%^(?:
    [\x09\x0A\x0D\x20-\x7E] # ASCII
    | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
    | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
    | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
    | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
    | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
    | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
    | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
    )*$%xs’, $string);

    如果$result为真,则是UTF-8编码的字符串,否为ANSI

    以上面为条件,匹配出字符串中的中文

    if ($result) {
    preg_match_all("/[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}/", $str, $arr);
    print_r($arr[0]);
    } else {
    preg_match_all("/[\x80-\xFF]./", $str, $arr);
    print_r($arr[0]);
    }

     
  • 关于C#中ListBox控件重绘Item项

    shishirui 00:37 on 2009/05/10 | 0 Permalink | Reply

    “如何让ListBox的Item项显示多行?”,貌似没有人给出直接的答案。
    现在将一点个人经验总结如下:
    1、首先选中拖至面板的ListBox控件,点属性,选中DrawMode,改成OwnerDrawFixed或OwnerDrawVariable
    2、还是在属性工具中,切换到事件(就是那个闪电图标),鼠标双击‘行为’菜单下的DrawItem,添加一个事件。
    3、在‘窗体设计器生成的代码’中就添加了一个新的事件
    this.listBox1.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.listBox1_DrawItem);
    4、学过的朋友应该知道,这时代码里会有一个 listBox1_DrawItem()的方法,在里面写代码吧。

    private void listBox1_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)
    {
    e.DrawBackground();
    Brush myBrush = Brushes.Black;  //初始化字体颜色=黑色
    this.listBox1.ItemHeight=90; //设置项高,根据具体需要设置值
    //为每个项设置字体颜色
    //如果不需要可以不写此switch
    switch (e.Index)
    {
    case 0:
    myBrush = Brushes.Red;
    break;
    case 1:
    myBrush = Brushes.Orange;
    break;
    case 2:
    myBrush = Brushes.Purple;
    break;
    case 4:
    myBrush = Brushes.White;
    break;
    }
    e.Graphics.DrawString(listBox1.Items[e.Index].ToString(), e.Font, myBrush,e.Bounds,null);
    //这句好象可以不要,自己试下
    e.DrawFocusRectangle();
    }

    其实,看过MSDN的朋友应该知道了,MSDN里有类似的代码,我不过修改了几个地方,
    加入了项高this.listBox1.ItemHeight=90,可以输入多行字符,这里要注意的是,
    整个ListBox的高应该是你设置的Item项高的倍数大一点点,不然ListBox在显示时会有所变形!
    (例如:我的Item项高是60,而ListBox要一次显示三项,所以设置为184)

     
  • 漂亮的小图标

    shishirui 12:53 on 2009/05/09 | 0 Permalink | Reply

    http://icondock.com/resources/master-list-of-free-icons

     
c
撰写新文章
j
下一篇
k
上一篇
r
回复
e
编辑
o
显示/隐藏评论
t
返回顶部
esc
关闭