Thursday, November 27

有开发winform经验的人都知道,要想使程序在windows XP下真正拥有XP风格,需要按照下面这篇文章所说的去做。The Code Project - Windows XP Visual Styles for Windows Forms - C# Programming
首先如果你的画面上有Button,CheckBox,RadionBox,GroupBox的话,需要改变他们属性FlatStyle为System,然后追加一个manifest文件到exe文件的同一个路径下。就像App.config文件那样。

当然,在.Net Framework 1.1下,你可以不必这么麻烦,只需要加一句Application.EnableVisualStyles();就可以了。

遗憾的是,我再做的项目要用1.0,在1.0里可没有这么方便了。

我有10几个小winform程序都需要这样做,所以我首先想到建立一个模板。就像往项目里追加一个app.config一样。我仿照app.config模板作法,复制一个模板,修改里面的app.config成app.manifest文件。改好的模板放在这里了。

AppXPStyle.zip

我在修改C:\Program Files\Microsoft Visual Studio .NET\Vb7\VBProjectItems\Local Project Items\Utility\LocalUtilityProjectItems.vsdir以后可以追加manifest进入项目了,但是文件名变成了App1.manifest,而且编译以后,它不会同App.config一样被改名,拷贝到exe所在的文件夹下。
App.config真是一个magic file啊,VS是怎么做的?

我改变想法,考虑用macro来自动生成manifest,可是不知道如何得到当前所在的project,以及它生成的exe文件的路径。:s


Tuesday, November 25

惯性太可怕
今天看了一眼一个很久以前用C++编的程序,突然发现在这个程序我这么写到
#define DECIMAL_DIGIT 3
... ...
int a = 10^DECIMAL_DIGIT; //求10的n次方
... ...
MyGod,我居然用这样的语句来计算10的3次方。
这是可是C++啊,不是Basic。
正确的写法应该是
#include < cmath >
using namespace std;
......
#define DECIMAL_DIGIT 3
... ...
double a = pow(10,DECIMAL_DIGIT)
... ...

我原来的写法至少犯了2个错误,
1,在Basic里^是求幂的符号,而在C++(包括C#)里则是求2进制"异或"的符号,作用是完全不同的。
2,无论是basic也好还是C++也好,求幂以后的返回值都是double型,即使你的输入都是int型。

沉重检讨,我为什么会犯这种错误!!!!
都是VB惹的祸????
很多时候BASIC确实很好用,我都不自觉地用到C++里了。惯性实在可怕。
2週間ぶりのBLOGだ。この2週間で新しいPCを組み合わせって、BenQ FP791 LCDを購入しました。悔しいことはLCDのドット抜けだ。一つの明るい点で、不良対象外だって悔しいだ。コーディングなら、このLCDは明るすぎだ、DVD鑑賞ならいいかも。
3連休を利用してNo!FlashをUPDATEしていた。うるさいActiveXをBLOCKしたい。来週かな?PUBLISH IT。
日本では、BLOGの利用は少ないと思いますが、実は「日記」という形式で流しています。東京大学のサイトに置いている
便所コオロギ観察日記はC++,Windows関連のBLOGを記録している。いい参考できます。

Monday, November 10

致命的BUG:KB326219

下午我在做一个WinForm in VB.Net的程序时遇到了奇怪的问题,在设置好LABEL的字体后,运行出错,是奇怪的System.ArithmeticException,可是出错的位置是VS自动生成的code。google之后发现,这是一个臭名昭著的问题:326219 - PRB: System.Arithmetic Exception Error When You Change the Floating-Point Control Register in a Managed Application
看了这篇KB,我非常奇怪,是什么改变了浮点控制寄存器呢?
我一个一个地关掉我桌面上的程序, 发现罪魁就是早上安装的WORKTIME,在这个程序里一定是使用了这个寄存器,而dotNet在使用它时没有正确地初始化。
按照KB的指示,我们必须在每new一个form之前样做浮点精度指定。就像这样:
Imports System.Runtime.InteropServices
Module StartUp

_
Overloads Function _controlfp(ByVal n As Integer, ByVal mask As Integer) As Integer
End Function

_
Public Sub Main()
FixArithBug()

' Starts the application.
Application.Run(New Form1())
End Sub

Public Sub FixArithBug()
'PRB: System.Arithmetic Exception Error When You Change the Floating-Point Control Register in a Managed Application
'http://support.microsoft.com/default.aspx?scid=kb%3Ben-us%3B326219 Const _MCW_EM As Integer = &H8001F
Const _RC_NEAR As Integer = &H0
Const _PC_53 As Integer = &H10000
Const _EM_INVALID As Integer = &H10
Const _EM_ZERODIVIDE As Integer = &H8
Const _EM_OVERFLOW As Integer = &H4
Const _EM_UNDERFLOW As Integer = &H2
Const _EM_INEXACT As Integer = &H1
Const _EM_DENORMAL As Integer = &H80000
Const _CW_DEFAULT As Integer = (_RC_NEAR + _PC_53 + _EM_INVALID + _EM_ZERODIVIDE + _EM_OVERFLOW + _EM_UNDERFLOW + _EM_INEXACT + _EM_DENORMAL)
_controlfp(_CW_DEFAULT, &HFFFFF)
End Sub
End Module

这个问题同时出现在framework1.0和1.1里面。
我实在不希望还出现在1.2里,因为这种程序之间互相干扰的问题有时候是很难发现。
类似的VS2003也对别的程序有影响。
这种类型的问题往往是因为WINDOWS的消息机制引起的,错误地发送消息给一个Window程序是常见的原因。但是因为寄存器的原因,我还是头一次遇到。

Friday, November 7

MS有一个方法允许在一个操作系统里同时运行不同的IE版本,但是并没有公开这种方法。这个秘密已经被发现了:Multiple IE's in Windows
这对需要测试多个IE版本的网页设计者带来了好处,不再需要额外的机器,虚拟机了。:)

Tuesday, November 4

可删除任意已知节点的左倾树
优先队列是一个非常有用的数据结构,一般用于多任务的优先权分配。比如一台打印机只能一个文档一个文档地打印,如果有多个打印任务,如何调度他们呢?一个简单的策略就是先来先打印(FIFO),可是如果一个等待处理的先来的任务有上千页,而后来的等待中的任务只有1,2页,那么仍然按照先来先打的策略将会很没有效率(恕我不解释"效率"这个词)。另外一个策略就是等待任务中页数最小的先打印。这个策略看上去更好一些。
我们现在的问题是如何调度类似的这些任务如何调度,合理的数据结构如何。这就要用到优先队列的这个数据结构了。一个有效的优先队列实现方案就是左倾树(Leftist Trees)。这在一些经典的数据结构和算法的书中都有介绍。
对这个数据结构稍加研究以后,就会发现它不能很好地解决一个特例,就是如果用户想取消一个还没有进行的任务(我想cancel一个打印文档是大家经常会遇到的)。解决这个特例直观的想法是重新构造左倾树,可是怎样做呢?上周五,布朗香写出了一个算法:可删除任意已知节点的左倾树。我有幸看到了这篇文章,记录于此。:)