2008年4月15日星期二

DateTimePicker背景色設定方法

DateTimePickerの背景色設定はMSのBUGです。
下記のSRCで背景色を設定できます。
注意点は:
① Graphics作成:Graphics.FromHdc(m.WParam);
② SolidBrush作成:new SolidBrush(Color);
SolidBrushではFillのメッソドがあります。範囲内の色設定はできます。
③ 色設定
g.FillRectangle(backBrush, ClientRectangle);
④ 最後の片付け処理。
brush.Dispose()
g.Dispose();

----------------------SRC---------
///
/// 背景色の設定
///

///
protected override void WndProc(ref Message m)
{
// 背景色を描きなおし場合、
if (m.Msg == 0x14) // WM_ERASEBKGND
{
// get Graphics object
Graphics g = Graphics.FromHdc(m.WParam);
// get Brush object
SolidBrush backBrush = new SolidBrush(this.BackColor);
// 背景色設定
g.FillRectangle(backBrush, ClientRectangle);
// Brush objectを解放
backBrush.Dispose();
// Graphics objectを解放
g.Dispose();
         // システムの書き直しは止めさせる。
return;
}
base.WndProc(ref m);
}

2008年4月12日星期六

[Win32API]笔记-Window相关的函数

对Windows编程一直很感兴趣,却因为能力和精力有限,每次都是学了点皮毛,然后又忘掉。 这次要做笔记,
准备集腋成裘。

1 Hook功能,是我一直最感兴趣的,记得第一次看到关于Hook功能的说明,让我兴奋不已,
作者不记得了,这个前辈说,可以写一小段程序,这小段程序启动后,当你打开你机器上的QQ的时候,
发现你得QQ今天很怪,用户名和密码的输入框都不能输入了。

原因是什么呢,就是我写的这一小段程序在监视QQ程序的状态,当QQ启动后,我的这段程序就能知道,
然后给QQ登录窗口发送一个消息,让QQ窗口上的用户号码和密码输入框不可用。

虽然看起来很简单,但对于新手来说,确实是个很大的难题。
因为在一般的PG来说,很少见过两个exe程序相互影响的。
说说思想吧,Windows是事件驱动的,我们所作的一切鼠标键盘操作,都是发给系统的,系统给具体对应的窗口发送消息,做出响应,正常期情况下,不同程序的窗口之间是不能够相互影响的,不然就乱了。
但是windows肯定会为高手留一个方法,让窗口之间可以通信,那就是使用nativewindow.

nativewindow关注重点:
1 NativeWindow类有个AssignHandle方法,当知道某个窗口的句柄(hwnd)时,可以通过这个方法将系统发给hwnd窗口的消息拦截下来,是否将消息告诉hwnd就取决于NativeWindow是否高兴了。
当然这个类还有个ReleaseHandle()方法,就是放弃自己拦截传向hwnd消息的权利。
如何拦消息,就是重写他的WndProc。


为了能够得到具体窗口的句柄,有以下几个方法,
1 FindWindow(IntPtr hwndParent, IntPtr hwndChild, string lpszClassName, string lpszWindowName),这个方法中的四个参数,就像SQL中的条件一样,知道的话就写上具体的,不知道的话,就写上0或者null,很方便。

2 EnumWindows 将枚举所有顶级窗口,但不枚举子窗口。
EnumChildWindows 函数既不会枚举由特定窗口拥有的顶级窗口,也不会枚举任何其他拥有的窗口。EnumThreadWindows 函数将枚举与某个线程关联的所有非子窗口。尽管所有窗口都有一个类,但并不是所有窗口也都有一个标题。

2008年4月11日星期五

[设计模式] Observer 观察者



Observer 的目的是一处改动,通过调用Update(),通知所有关联的地方都作相应的变化。当然关联关系是可以增加或者消除的。

Observable 是发生源,当有什么改动,需要通知给相应的对象的时候,通过调用Notify方法,来告诉他所拥有的Observer,而具体的Observer就会通过自己的Update方法,更新自身。

这个原理,有点类似windows中的事件驱动。当发生了某个事件,就会去找对应的事件处理程序,有多少个,就执行多少个。例如C#中这样写
button1.Click += button1_Click;
还可以继续增加事件处理程序
button1.Click += btnAll_Click;
button1.Click += functionButton_Click;
如果某种情况下,不想通知btnAll_Click去执行,那就
button1.Click -= btnAll_Click;
就可以了。

java中的类,下面是这么写的,

java.util.Observable类:

void
addObserver(Observer o)
Adds an observer to the set of observers for this object, provided that it is not the same as some observer already in the set.

protected void
clearChanged()
Indicates that this object has no longer changed, or that it has already notified all of its observers of its most recent change, so that the hasChanged method will now return false.

int
countObservers()
Returns the number of observers of this Observable object.

void
deleteObserver(Observer o)
Deletes an observer from the set of observers of this object.

void
deleteObservers()
Clears the observer list so that this object no longer has any observers.

boolean
hasChanged()
Tests if this object has changed.

void
notifyObservers()
If this object has changed, as indicated by the hasChanged method, then notify all of its observers and then call the clearChanged method to indicate that this object has no longer changed.

void
notifyObservers(Object arg)
If this object has changed, as indicated by the hasChanged method, then notify all of its observers and then call the clearChanged method to indicate that this object has no longer changed.

protected void
setChanged()
Marks this Observable object as having been changed; the hasChanged method will now return true.




java.util.Observer接口:

void
update(Observable o, Object arg)
This method is called whenever the observed object is changed

2008年4月8日星期二

RegEx 中日韩字符判断

\p{IsHiragana}
\p{IsKatakana}
\p{IsCJKUnifiedIdeographs}

bool isHiragana = Regex.IsMatch(str, @"^\p{IsHiragana}*$");

2008年4月7日星期一

[转载]项目管理中的注意事项

A) 寻找最容易找到的技术人员组建团队。这样可以将人员流动对项目的影响减到最小,同时也可以快速的组建团队进入开发期。目前,IT人力资源市场上,Java方向和.NET方向是两个主要的企业级开发方向,多数IT人才也集中在这两块。
B) 使用成熟技术。显然,Java和.NET都是成熟的技术。在软件解决方案方面都有各自的长处和优点,但对企业级应用而言都可以胜任。通过这几年的发展,.NET和Java都形成了丰富的社会技术资源。.NET经过1.0到3.5的发展,在企业级应用方面已经在实践中变得更加的成熟了。
C) 使用团队熟悉的技术。避免过于陡峭的学习曲线,可以把对开发人员的的要求降至更低。但这并不等于使用最简单的技术来完成复杂庞大的企业级应用,应该是在易学易用的前提下构造稳定可维护的目标系统。冒着危险选择不成熟的技术或者不熟悉的技术都只能得到一个漏洞百出的系统。
D) 侧重于开发期的规划与管理,开发稳定可维护的产品。对团队的素质侧重点放在沟通和编写稳定可维护代码的视角,避免目标系统走向紊乱而不可控的地步,从而导致最终失败的结局。


结合具体实际情况,结论很容易得出了。考虑的方向是:目标系统 + 技术团队 =〉 解决方案

[转载]永远别向复杂低头

比尔·盖茨:永远别向复杂低头。

改变世界的阻碍,并非人类的冷漠,而是世界的太过复杂性。

为了将关心转变为行动,我们需要找到问题,发现解决方法,评估后果。但是复杂性阻碍了这些步骤。

就算我们真地发现了问题所在,也不过是迈出了第一步,接着还有第二步:那就是从复杂的事件中找到解决办法。

从复杂中找到解决办法可以分为四个步骤:确定目标,找到最高效的方法,发现适用于这个方法的新技术,同时最聪明地利用现有的技术——不管它是复杂的药物,还是最简单的蚊帐。

在发现问题、找到解决方法之后,就是最后一步——评估工作结果,将你的成功经验或者失败教训分享,这样其他人就可以从你的努力中有所收获。


但是如果你想激励其他人参加你的项目,你就必须拿出比统计数字更多的东西:你必须展示你工作的人性因素,这样人们才会感到拯救一个生命对那些处在困境中的家庭意味着什么

2008年4月3日星期四

Invoke 的一点笔记

一直对Invoke这个方法不是很熟悉,今天在调查了一下,大体搞明白了,
Invoke是跨线程用的一个方法。
例如
有ThreadA, ThreadB两个线程,ThreadA中作了画面处理,中途遇到了大的计算,将计算放到ThreadB中,但是在ThreadB中做了一半,需要更新ThreadA中的某个属性,然后继续ThreadB的操作。
这种情况下,由于是ThreadA,ThreadB分离开的,谁都不能直接操作另一个Thread中的具体属性,
只好求助Invoke了。
Invoke,可以翻译成触发或者激活,那么Invoker就是触发器啦,触发什么呢,就是让另一个方法执行起来,所以经常用到的就是MethodInvoker 。
上面的情况,用代码来说明就是:
// Form1.cs
private void button1_Click(object sender, EventArgs e)
{
this.SetEnabledOfControls(false);
Thread threadB= new Thread(
delegate()
{
// 5秒代表假设这个ThreadB处理第一步计算可能要花5秒钟
Thread.Sleep(5000);
// 修改ThreadA(就是主线程Form线程)中的某个属性
this.SetEnabledOfControls(true);
// 修改完ThreadA的属性后,还要进行下一步计算,可能是花了1秒
Thread.Sleep(1000);
});
// 启动ThreadB
threadB.Start();
}
///
/// ThreadA中的处理,设定Enabled属性
///

private void SetEnabledOfControls(bool value)
{
// 这步判断,目的是确定执行这个方法的时候,下面要用的Controls是有根的,
// 也就是说,这个方法归根结底是只应该在ThreadA主线程中被执行的,不管在哪里激活他,
// 执行的时候,应该是在主线程内部执行。如果是其他的线程的话,就不能再执行了。
if (!this.IsHandleCreated))
{ return; }

// 这句稍微复杂,
// 其实隐藏了一个delegate声明,同时将这个隐藏的delegate关联上了一个方法体
// 执行的时候,只需要通知(也就是激活)这个delegate去执行,就可以了。
MethodInvoker mtdDelegate = (MethodInvoker)delegate()
{
// 这里面就是方法体,没有方法名,方法直接通过delegate转换,
// 就成了一个Delegate实例了。

// 设定Controls的Enabled属性为value
foreach(Control ctr in Controls)
{
ctr.Enabled = value;
}
};

// 判断这个方法是ThreadA直接调用的,还是从ThreadB内部通过Delegate委托调用的。
// 委托调用的场合,InvokeRequired属性会返回true,判断调用元不是本线程
if (this.InvokeRequired)
{
// 这种场合需要使用Invoke激活,让这个delegate去执行它内部的逻辑。
this.Invoke(mtdDelegate);
}
else
{
// 既然激活元就是当前的主线程ThreadA,
// 就让这个delegate自发激活,直接执行就可以了。
mtdDelegate.Invoke();
}
}
下面是抄来的。

public static class ControlUtil
{
public static object SafelyOperated(Control context, Delegate process)
{
return ControlUtil.SafelyOperated(context, process, null);
}

public static object SafelyOperated(Control context, Delegate process, params object[] args)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
if (process == null)
{
throw new ArgumentNullException("process");
}

if (!(context.IsHandleCreated))
{
return null;
}
if (context.InvokeRequired)
{
return context.Invoke(process, args);
}
else
{
return process.DynamicInvoke(args);
}
}
}
private void SetEnabledOfControls(bool value)
{
MethodInvoker process =
(MethodInvoker)delegate()
{
// 具体处理
};
ControlUtil.SafelyOperated(this, process);
}