无意中在电脑中的角落,发现05年替成都的路正驾校做的学员管理系统,被遗忘在这里很久了。是刚毕业不久接下来的第一个“私活”,呵呵。这个系统从头到尾都是用VC做的,也费了不少时间,用业余的时间来做,做了差不多一个月。要是现在,我一定会用C#来开发了,开发时间至少节约一半以上 :) 第一次做的东西,还是比较值得留恋。其实界面和功能上都有待提高。不幸的是我的系统重装过了,以前的数据库表脚本也找不到了。只是恢复了登陆验证的数据。抓了几张图,留在这里做一个纪念。
许可生成器
登录界面
操作界面
君看一叶舟,出没风波里
无意中在电脑中的角落,发现05年替成都的路正驾校做的学员管理系统,被遗忘在这里很久了。是刚毕业不久接下来的第一个“私活”,呵呵。这个系统从头到尾都是用VC做的,也费了不少时间,用业余的时间来做,做了差不多一个月。要是现在,我一定会用C#来开发了,开发时间至少节约一半以上 :) 第一次做的东西,还是比较值得留恋。其实界面和功能上都有待提高。不幸的是我的系统重装过了,以前的数据库表脚本也找不到了。只是恢复了登陆验证的数据。抓了几张图,留在这里做一个纪念。
许可生成器
登录界面
操作界面
很久没来自己的blog写点什么了。接近年底,加班也开始多起来,到现在还堆积了N个需求要做。还有些同事下周就会请假回家,看来任务更重了。
最近我们WMS项目组来了个新同事,据说以后也会加入Shipping项目的开发。上周开发经理找我谈了话,让我来带这位新同事–Matt。从来还没有带过人,感觉还比较新鲜。不过责任也在那里,因为项目比较紧,WMS组也一直比较缺人手。感觉自己也有一定的责任。我的计划是做一个模拟项目,让Matt能很快上手,就像我当初来Newegg的时候,也是从实际项目开始上手,虽然刚开始比较觉得有压力,但是通过在实际的设计和编码重,最能锻炼人,也能让人很快进入角色。 今天还是比较有成就感了,基本完成了2、3个需求,感觉自己效率还是有点高[cool],到现在,机器上还在跑一个MSMQ测试的Windows Service。
终于决定去参加这次全球峰会了。星期一和Aaron Zhao一起去办了签证手续,这周星期四约好到美国领事馆的签证面试,今天也抓紧中午休息的时间,准备了一些资料。峰会住的酒店也选好了,看来看去,还是选了Westin Seattle Hotel,看照片上的风景还不错。 最后,希望Aaron Zhao和我这次签证面试能够顺利过关。[wink]
几天没来我的blog,今天刚刚打开,OMG… 多半的页面都快被垃圾广告引用占满了。心里很是气愤。到后台以看,垃圾引用3000多条。虽然这个版本的PJ-Blog,作者专门针对垃圾引用,加入了批量删除功能,可是这样10条删一次,我岂不是要点300多次?郁闷!后来查看了blog数据库的表结构,发现引用都被添加在数据库表blog_Trackback里面。自己动手,丰衣足食,索性写了个清理Trackback的asp脚本。只要上传到你的网站blog根目录下,在浏览器访问一下,就可以清除了,节约了不少时间 :)
如果你也和我用相同版本的PJ-Blog,下面的脚本,你也可以拿去用,只是在数据库连接那里,把数据库文件名称改成你的就可以了 :) 注意下PJBlog版本,看是否和你的一致,看我blog下面的版本信息吧。
最后,BS一下那些发垃圾引用的人,做损人利己的事!
在用VC做一些软件功能的时候,为了方便使用,通常会涉及到托盘编程。也就是在程序最小化的时候,会在右下角的托盘区域添加一个图标,这个图标通常会支持弹出菜单功能。问题就在这里出现了,你也许会发现我们使用TrackPopupMenu呼出的弹出菜单,如果用户在取消选择的时候,在桌面任意地方单击,这个菜单也不会消失,很是郁闷,通常让初学者感到万念俱灰~~。 托盘程序中调用弹出菜单示例代码如下:
if(message==WM_SHELL_NOTIFY && lParam==WM_RBUTTONDOWN)
{
CPoint pt;
GetCursorPos(&pt);
CMenu *pMenu,menu;
menu.LoadMenu(IDR_SYSMENU);
pMenu=menu.GetSubMenu(0);
pMenu->TrackPopupMenu(TPM_RIGHTBUTTON,pt.x,pt.y,this,0);
}
要解决这个问题,其实比较简单,在响应托盘消息以及鼠标右击消息的时候,需要我们先调用一个函数,在你弹出菜单之前,设置你的窗口为最前窗口,问题就会迎刃而解。 修改后的代码如下: if(message==WM_SHELL_NOTIFY && lParam==WM_RBUTTONDOWN) { this->SetForegroundWindow(); //这里将主窗口设置为最前端窗口 CPoint pt; GetCursorPos(&pt); CMenu *pMenu,menu; menu.LoadMenu(IDR_SYSMENU); pMenu=menu.GetSubMenu(0); pMenu->TrackPopupMenu(TPM_RIGHTBUTTON,pt.x,pt.y,this,0); }
编译后,再看看效果,问题就这样解决了。
远程唤醒,是现在很多网卡都支持的功能。而远程唤醒的实现,主要是向目标主机发送特殊格式的数据包,是AMD公司制作的Magic Packedt这套软件以生成网络唤醒所需要的特殊数据包,俗称魔术包(Magic Packet)。Magic Packet格式虽然只是AMD公司开发推广的技术,并非世界公认的标准,但是仍然受到很多网卡制造商的支持,因此 许多具有网络唤醒功能的网卡都能与之兼容。 要实现远程唤醒,还需要硬件的设置: 主板和网卡必须都支持远程唤醒功能。一般目前的主板都支持这个功能,支持的主板上通常都有一个专门的3芯插座,以便在关机时为网卡供电。但 并非所有的网卡都支持该功能(特别是一些价格较便宜的低档网卡),要判断网卡是否支持远程唤醒功能的方法很简单,支持远程唤醒的网卡上都有一个3针的WOL接口和一条3芯的远程唤醒电缆,通过判断网卡是否带有WOL接口即可(有些较新的网卡可能没有WOL接口也能支持远程唤醒。这是因为现在流行的主板支持PCI2.2标准,而PCI 2.2标准不需要通过专门的WOL接口为网卡供电,允许主板直接通过PCI插槽向网卡提供Standby电源)。
1.硬件连接 网卡安装完毕后将远程唤醒电缆的一端插入到网卡的WOL接口上,另外一端与主板的3针WOL远程唤醒接口相连(该接口旁通常标有WOL_CON的字样,当然如果主板和网卡都支持PCI2.2标准则无须做这一步)。
2.CMOS设置 打开CMOS远程唤醒功能很简单,只要将CMOS设置中的“Power Management Setup”的“Wake Up On LAN”项设置为“Enable”即可。
软件的实现方面,其实就是通过socket向目标的机器发送魔术包了,魔术包的格式,包含有连续6个字节的“FF”和连续重复16次的MAC地址。程序中我们可以采用UDP方式广播发送,不需要端口号,只要知道对方机器的MAC地址即可 :)
程序运行界面如下:
程序打包下载:
在平常的开发过程中,我们为了改善用户的体验,通常会在界面上花一些功夫。因为清爽的界面,通常给用户带来一些耳目一新的感觉,并且能增强用户满意度。前几周的一个项目中,就用到了ListBox,需要突出用户在ListBox中选中的项,而.NET自带的ListBox由于配色过于普通,无法满足我们的需要,这就需要我们重新对ListBox的配色进行一些修改。 在Windows的消息机制中,有一个消息叫做WM_DRAWITEM,当控件(比如:Button,ComboBox,ListBox,Menu)需要被重新绘制的时候,会向该控件的父窗口发送这个消息。父窗口通过响应这个消息,就可以实现对该控件外观的绘制,也就是说,通过响应WM_DRAWITEM消息,我们可以接管系统对控件的绘制,这样,我们就可以随心所欲,用我们喜欢的方式,来绘制这个控件了。听起来不错吧? .NET的WinForm程序,也是基于Windows的GUI界面的窗口,而.NET追溯到最底层,其实也是对Win32 API的更高一个层次的封装。所以,.NET的WinForm程序同样也逃脱不了消息机制。于是我们就可以在程序中,通过设置控件为Owner Draw属性,然后加入对WM_DRAWITEM的处理,就可以在OnDrawItem函数中,定制控件外观了。 理论上就是这样,我们开始动手吧,打造一个具有个性的ListBox控件!需要说明的是,当我们把控件属性中的DrawMode改为OwnerDrawFixed过后,.NET以及将绘制这个控件的责任交给了我们,因此我们必须要实现DrawItem函数,否则ListBox会是一片白,什么也看不到。 1.建立一个简单的工程,在工具箱拖放ListBox到Form上,然后将ListBox属性中的DrawMode改为OwnerDrawFixed,或者在Form_Load中,设置控件的属性: this.listBox1.DrawMode = DrawMode.OwnerDrawFixed; 2.在事件窗口中,为DrawItem添加处理函数。 3.配色方案:这里,我们设定被选中的项目有一个蓝色的外框,并且选中的项中,内容呈亮绿色显示,背景色呈灰色显示,这样就更醒目一些了。 4.最后一步,就是加入OnDrawItem的代码,如下:
private void listBox1_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)
{
//定义背景色,选中为灰色,未选中为白色
Brush brNoSelectedBack=Brushes.White;
Brush brSelectedBack=Brushes.Gray;
//定义前景色,选中为亮绿色,未选中为黑色
Brush brSelectedFore=Brushes.LightGreen;
Brush brNoSelectedFore=Brushes.Black;
//定义焦点,有焦点状态下绘制蓝色外框(蓝色)
Pen penFocus=new Pen(Brushes.Blue);
e.Graphics.FillRectangle(Brushes.White,e.Bounds);
//绘制Item被选中的情况
if((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{
e.Graphics.FillRectangle(brSelectedBack,e.Bounds);
//绘制焦点外框
e.Graphics.DrawRectangle(penFocus,e.Bounds.X,e.Bounds.Y,e.Bounds.Width,e.Bounds.Height-1);
e.Graphics.DrawString(this.listBox1.Items[e.Index].ToString(),
this.listBox1.Font,brSelectedFore,e.Bounds);
//e.DrawFocusRectangle();
return;
}
//绘制没有被选中的情况
e.Graphics.FillRectangle(brNoSelectedBack,e.Bounds);
e.Graphics.DrawString(this.listBox1.Items[e.Index].ToString(),
this.listBox1.Font,brNoSelectedFore,e.Bounds);
}
到这里,一个简单的自绘ListBox就实现了,不过这里的代码都是直接加载父窗体的里面,不是很美观。其实我们可以自己实现一个这样的类,并把这个ListBox编译为一个.NET控件,这样,在其他的项目中就可以很简单的重用这个控件了。:)
下面是这个自绘控件的效果,左边是我们的自绘ListBox,右边是普通的ListBox。等有时间,我会把这些封装成为一个dll控件 :)。这里提供源代码的下载,有兴趣的朋友可以再根据自己的需求进行一些自己的修改。
10月6日从深圳回来,迫不及待地打开我的hotmail,果然有一封邮件在那里,标题是“恭喜你……”。很荣幸的连任MVP,被授予2007 Microsoft® MVP 称号。
在此特别感谢Microsoft,感谢Sisley,感谢CCTV。我会更加努力的。 [cool] 今天去梁振的MSN Space,看到他也连任成功,再次祝贺你哦 :)
从今日起,恢复Blog的MVP标徽。
不知不觉,又快一年了。而在9.30号,我的MVP一年的任期也将结束了。回顾这一年,自己又有了不少的进步。从最开始的VC到现在接触到.net,对我的发展方向也有很大的影响。MVP不仅仅是一个称号,而是一种文化、一种勉励。让我能不断的去学习新的技术,和大家一起分享。
在这一年,我有幸参加了成都的MVP Open Day,见到了传说中的MVP Leader :Sisley。也见到了Eddie Liu。认识了Eric Liu,Eric Zhong,Richie,Simon,Jack,Kim,还有Aaron Zhao,和张美波,梁振.
估计10月连任的消息会在国庆左右公布,希望自己连任能成功。从今天起,我会取消在我的blog上面的MVP徽标。希望能有机会再次将他挂上 [cool]
上次写过一个调试windows服务的一点经验的日志。这段时间也在做一个和Windows Service有关的东西。又有了些经验,所以拿来和大家分享下。调试windows服务,采用的一般方法,就是设好断点,然后启动服务,在IDE里面直接通过进程列表,把Service的exe附加到IDE上面来调试,这个方法在上一个日志也提到过。其实在.NET建立的服务程序中,还有一个方法,也是之前没有想到的方法,更为简单 :)
// 进程的主入口点 static void Main() { System.ServiceProcess.ServiceBase[] ServicesToRun;
// 同一进程中可以运行多个用户服务。若要将
//另一个服务添加到此进程,请更改下行
// 以创建另一个服务对象。例如,
//
// ServicesToRun = New System.ServiceProcess.ServiceBase[] {new Service1(), new MySecondUserService()};
//
ServicesToRun = new System.ServiceProcess.ServiceBase[] { new Service1() };
System.ServiceProcess.ServiceBase.Run(ServicesToRun);
}
也就是在Main方法,服务程序开始的地方,如上,把默认的创建并运行服务的代码全部注释掉,然后直接生成本类的一个实例,然后调用OnStart方法就可以了,这里要注意的是OnStart方法是一个受保护的无返回值的方法,而Main函数是静态方法,所以需要把OnStart也改动一下,设置为静态函数。这样的话,服务和一般的.net应用程序就一样了,调试的时候更加方便,直接F5就可以了 :) 不过在完成调试过后,一定记得要把上面的改动还原 [cool]
改动后的代码如下:
// 进程的主入口点
static void Main()
{
Service1 obj=new Service1();
obj.OnStart();
}
这个方法虽然有点投机,不过确实能够节省很多步骤,让调试服务和调试一般的应用程序那样方便!值得推荐