分类目录归档:程序语言

各种TimeStamp

关于各种Timestamps的区别和比较:

UNIX timestamp: seconds since midnight, January 1, 1970 UTC. It is a 32-bit number.
Win32 FILETIME values count 100-nanosecond intervals since January 1, 1600 UTC. It is a 64-bit number.
CLR System.DateTime values count 100-nanosecond intervals since January 1, 1 UTC. It is a 64-bit number. These aren’t used much yet.
The DOS date/time format is a bitmask (YYYYYYYM MMMDDDDD hhhhhmmm mmmsssss) The year is stored as an offset from 1980. Seconds are stored in two-second increments. These values are recorded in local time.
The OLE automation date (DATE) format is a floating point value, counting days since midnight 30 December 1899. Hours and minutes are represented as fractional days.
The C runtime time_t value is the same as a UNIX timestamp, __time64_t is same except using 64-bit number

* time_t: 19:14:07, January 18, 2038, UTC.
* __time64_t: 23:59:59, December 31, 3000, UTC.

struct tm {
int tm_sec; /* seconds after the minute – [0,59] */
int tm_min; /* minutes after the hour – [0,59] */
int tm_hour; /* hours since midnight – [0,23] */
int tm_mday; /* day of the month – [1,31] */
int tm_mon; /* months since January – [0,11] */
int tm_year; /* years since 1900 */
int tm_wday; /* days since Sunday – [0,6] */
int tm_yday; /* days since January 1 – [0,365] */
int tm_isdst; /* daylight savings time flag */
};

typedef struct _SYSTEMTIME {
WORD wYear; /* no offset */
WORD wMonth; /* January is 1 */
WORD wDayOfWeek; /* Sunday is 0, Monday is 1, and so on.*/
WORD wDay; /* 1-31 */
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds;
} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME;

CTime 构造函数可以接受:

__time64_t(time_t),
{DosDate, DosTime},
SYSTEMTIME,
FILETIME,
{nYear: 1970-3000, nMonth: 1-12, nDay: 1-31, nHour, nMin, nSec}.
struct tm* GetGmtTm(struct tm* ptm = NULL) const;
struct tm* GetLocalTm(struct tm* ptm = NULL) const;
BOOL GetAsSystemTime(SYSTEMTIME& timeDest) const;
time_t GetTime() const;
int GetYear() const;
int GetMonth() const; // month of year (1 = Jan)
int GetDay() const; // day of month
int GetHour() const;
int GetMinute() const;
int GetSecond() const;
int GetDayOfWeek() const; // 1=Sun, 2=Mon, …, 7=Sat

COleDateTime 构造函数可以接收:

VARIANT,
DATE,
time_t,
SYSTEMTIME,
FILETIME,
{nYear: 100-9999, month: 0-12(from 1), day: 0-31 (from 1), hour: 0-23, minute: 0-59, second 0-59}
BOOL GetAsSystemTime(SYSTEMTIME& sysTime) const;
int GetYear() const;
int GetMonth() const; // month of year (1 = Jan)
int GetDay() const; // day of month (0-31)
int GetHour() const; // hour in day (0-23)
int GetMinute() const; // minute in hour (0-59)
int GetSecond() const; // second in minute (0-59)
int GetDayOfWeek() const; // 1=Sun, 2=Mon, …, 7=Sat
int GetDayOfYear() const; // days since start of year, Jan 1 = 1

http://www.codeproject.com/datetime/datetimedisc.asp

http://blogs.msdn.com/oldnewthing/archive/2003/09/05/54806.aspx

Window系统下文件图标和TrayIcon的使用情况

windows 2000
大图标、缩略图 用32X32 256色,没有256色,用16色
小图标, 用16X16 256色,没有256色,用16色。

windows 2000 下的Tray是尽量用32X32 256色, 缩小显示,
但碰到不是系统标准调色板的会出现错误。
如果有16X16的图标,无论16色或者256色,并不使用。

Windows XP
缩略图, 48X48
图标: 32X32
列表,详细资料: 16X16

Tray也是用32X32? 但不是系统标准调色板显示是正确的。

C++编程规范阅读手记(二)

第二部分:设计风格

5. 给一个实体一个内聚的职责
倾向于从小一些的低层抽象构造高层抽象;避免将许多低层抽象集合成一个更大的低层抽象。从一些简单个体完成复杂行为要比相反的更容易。
两个声名狼藉的例子:realloc 和 basic_string

6. 正确性,简单性,和清晰性先行
这是第二部分最重要的一条,其实重要性不言自明

7. 知道何时和如何为可伸缩性编写代码
在一切可能情况下使用线性(或更好的)算法;在一切合理情况下避免使用比线性差的多项式复杂度的算法;在任何时候避免使用指数复杂度的算法。

8. 避免过早优化
9. 避免过早恶化(pessimize)
这两条应该一起说,因为常常有人搞混。这里作者将“过早优化”定义为以优化的名义将设计和编码搞得更加复杂,也因此更加不可读,实际上并没有被证明的性能需求,因而也明显地没有为你的程序增加被证明的价值。

让一个正确的程序快起来要比让一个快的程序正确要容易得多得多。

不要进行过早优化的两个理由:1. 我们程序员并不能能准确地评估代码中的瓶颈,因为现在的计算机计算模型十分复杂。因此,要优化必须通过准确地实际度量。2. 现在越来越多的瓶颈不在于CPU的限制,而是内存、网络、磁盘、Web Service。数据库等等的等待上,因此实际上要优化的是如何减少这种等待时间而不是程序运行的时间。

但是,这并不意味着不注意一些效率上的考虑,这就是第9项想说明的:避免过早地恶化。
这些考虑包括:传递引用而不是传递值;使用前置++和–运算符而不是后置运算符;使用构造函数中的赋值语句而不是初始化语句列表。减少对象不必须的临时拷贝,尤其在内循环中;使用现成的抽象、库和算法,例如STL。

因为这些手段的采用并未影响代码的可读性,因而也不会影响代码的复杂性,相反,有时候还降低了代码的复杂性。

C++编程规范阅读手记(一)

《C++编程规范(英文版)》(英文名:《C++ Coding Standards – 101 Rules, Cuidelines, and Best Practices》)
Herb Sutter, Andrei Alexandrescu 著

第一部分:组织和政策问题

0. 不要为小问题焦虑(要知道哪些无需规范化)
统一最重要,而具体统一成什么细节并不是那么重要,比如缩进是多少,每行长度多少,命名方式如何,注释方式如何,括号方式如何,TAB还是空格等等。另外提到两条传统的规范认为无需遵守,一是匈牙利命名法,二是函数的单入单出。
个人意见:对于一个团队来说,最好还是需要需要就一些细节的东西进行统一,当然统一成什么格式关系不大,没有哪种格式一定比别的格式好。单入单出我是早就反对的,但匈牙利命名法得很习惯了。现在看到的许多软件开发的书籍里都提到说匈牙利命名法对面向对象的语言是不适合的,最近也是有些体会,但主要集中在类型的重复上(对类似乎还可以,但对于Generic Programming显然毫无意义),自己觉得作用域的说明似乎还是有些好处的。一个程序里阅读的时候直接能知道哪些是类的成员变量,哪些是局部变量或者函数的参数。不过也许按照写小函数的原则,一个小函数中这一点也能够看得很清楚,也许也会慢慢觉得没有必要。

1.使用最高的警告级别进行编译
2.使用一个自动构造系统
3.使用一个版本控制系统
这几点都在遵循,但自动构造系统并没有对公司所有产品都这么用。另外,以前很多习惯仍然没有到达“建立工具,让机器替代人来工作”的自觉程度,有时候还是为图省事就手工做了,然后一遍遍重复做。

4.在软件复查上投资
做得不好,所以重复一下书中的理由:
* 通过有益的同伴压力来增加代码质量
* 找到bug,不可移植的代码(如果适用),以及潜在的伸缩性问题。
* 通过想法的杂交促进更好的设计以及实现
* 带领新的团队成员和新手加快速度
* 在团队内部培养共同的价值观和一种社区感觉
* 增强精英意识,自信,积极性以及职业自豪感。

VBScript中的函数括号的使用

做的一个ActiveX后台组件,有个函数的定义为:

[id(1), helpstring(“method GetData”)] HRESULT GetData([out] VARIANT * pb);

GetData函数示例如下:
STDMETHODIMP CArrayBox::GetData(VARIANT *pb)
{
// TODO: Add your implementation code here
::VariantClear(pb);
pb->vt = VT_UI1 | VT_ARRAY;

SAFEARRAYBOUND bound;
bound.cElements = 200;
bound.lLbound = 0;
pb->parray = ::SafeArrayCreate(VT_UI1, 1, &bound);
if (pb->parray == NULL)
return E_FAIL;

memcpy(pb->parray->pvData, “abcdefg”, 7);
return S_OK;
}

在VBScipt中这样调用 o1.GetData(d) 是有问题的,d的类型和内容并不改变。
需要 o1.GetData d 不加括号才是对的

另一个函数定义是:
[id(15), helpstring(“method CreateNewFile”)] HRESULT CreateNewFile([in] BSTR bstrOutFileName, [in] long nFormat, [out, retval] VARIANT *pbResult);

o1.CreateNewFile(“res.pmd”, 6) 错误是: 调用子程序时不能使用括号
o1.CreateNewFile “res.pmd”, 6 正确
res = o1.CreateNewFile(“res.pmd”, 6) 正确
res = o1.CreateNewFile “res.pmd”, 6 错误是: 语句未结束

在网上看到这样的描述:

所有的方法, Function, Subroutine的呼叫都要加上小括号,但若呼叫Function但不需要Function 的回传值,或者Function不需要传入参数,可以使用不加小括号的方式呼叫, Subroutine不使用小括号也是可以的,但VB.NET中不再允许。

上面说“可以”不加小括号,但似乎是“必须”不加小括号。

又试了试上面的调用换成 k = o1.GetData(d),此时d的值就是对的了,但实际上原来的函数是没有返回值的。

有点想不明白VBScipt的机理。

[旧作]无关技术的官司

无关技术的官司(1997.11.7)

Microsoft公司最近官司连连。和Sun的关于Java的官司还没有眉目,美国司法部又于近日指控Microsoft公司要求各电脑生产厂商在安装微软的Windows 95软件时同时安装它的Web浏览器产品Internet Explorer。这违反了1995年司法部和Microsoft公司达成的反托拉斯协议法令。在这个法令中,Microsoft公司不得将产品许可证相互联系,即不能够在操作系统的许可证的基础上销售如Microsoft Word之类的应用软件。

但在同一个法令中也同样指出了,Microsoft可以在向PC制造商出售许可证的操作系统中增加新的功能。这就造成了一定程度的混淆,也成了Microsoft反击司法部的有力武器。

由此看来问题的核心在于技术上对操作系统的定义和浏览器的定位。浏览器究竟是操作系统不可分割的一部分,是操作系统之内的不可缺少的特征,还是它是一个完全独立的产品,只能够作为一个应用软件来对待。又或者它可以作为操作系统的一个功能性扩展,因此Microsoft可以象Windows 95 OSR2那样销售,在这个版本的引导画面上,显示的是蓝天白云和飞扬的窗口,以及”Windows with Internet Explorer”。

这正是卷入官司的双方争论的焦点,双方都在搜集一切有利于自己的证据,当然要证明的结论是大相径庭的。司法部的一位助理检察官Joel Klein在一个采访中谈道,确定 Internet Explorer 是否是一个独立于Windows 95的产品是司法部的调查过程中最耗费时间的工作,其过程几乎持续了一年之久,目前已经掌握了将近15页的文件材料。

而Microsoft的官员则表示:IE是操作系统的一部分,就象其它系统工具软件一样,因此不属于协议的限制范围。Microsoft一直在为操作系统进行升级,只是这次的升级在网络方面,是为了增强操作系统进入Internet的功能。

我不知道司法部完整的15页材料都有些什么,只听到Joel Klein说包括Microsoft的文档在内的多个例子都说明了IE是一个独立的产品。这似乎和Microsoft的论调并不一致。可是这并不奇怪,在两年前,恐怕谁都不会否认浏览器只是一个应用程序,恐怕谁也不会想到浏览器会和操作系统集成,包括Microsoft自己也不会想到。只是技术的发展日新月异,为什么昨日的应用程序不能够变成今日操作系统的一个特征呢?

其实,造成模糊的原因之一就是,在95年的反托拉斯法令上,根本没有提及Internet和Web,上面对于操作系统软件的定义是“一组用于控制个人计算机系统的操作和管理计算机的内存和诸如键盘,显示屏幕,磁盘驱动器和打印机等附属设备之间的交互的指令,代码和辅助信息。”那时候Internet远未流行,Web浏览器还在襁褓之中,谁能预见到这两年里的天翻地覆呢?这说明了过去技术是在迅猛发展的。

老实说,这个定义有点无力,司法部完全可以避免使用95年的这个旧的协议法令,而提出一个新的指控。可是为什么不呢?因为司法部要避免重开一个独立的反垄断案,那样意味着又一个重头开始旷日持久的调查,而等到结果出来的时候,也许Internet Explorer又已成明日黄花,没有意义了。这不又暗示着将来技术也将会是不断发展吗?

而且如果纯从技术的角度来看,我觉得将浏览器的功能集成进操作系统好处是很明显的。浏览器的几个特点都可以作为下一代操作系统的要素:使用URL访问方式,使得在线的资源和本地资源以同样的形式为用户所用;浏览器界面,允许用户更方便地在资源之间切换和转移;动态HTML能力,提供以平台为中心的方式来获取用户输入并表示结果。因此我认为,将IE集成进操作系统不仅仅是让操作系统运行得更好,这样的方式本身就是一个现代的操作系统的核心,是一个先进的操作系统不可分割的关键部分。正如Microsoft所说的,这样的操作系统
能更好地适应Internet时代的需要。

从纯技术的角度来说,我心中是向着Microsoft的,Microsoft的集成性工作的确可以带来许多我们在技术上盼望的东西。可是问题的关键真的在技术领域,在于操作系统的定义和浏览器的定位吗?难道真的有必要将浏览器是否是操作系统一部分的问题搞得那样清楚?试想一下,如果Apple公司在Macintosh的最新的操作系统—-狂想曲(Rhapsody)里加入了浏览器的功能,甚至是象Windows 98一样将浏览器集成在内了,也有Active Desktop, 也使用浏览器界面和同样的操作来对远程和本地的资源进行访问,司法部是否也会如此地大动干戈?我想不太可能,没有谁在乎。可是Microsoft不行,因为它控制了几乎90%的操作系统市场和大约50%的商业应用程序市场,它去年的利润要比排在它之后的多家软件公司的总和都要多。

再从另一个角度来想一想,为什么在Win95中加了那么多系统工具软件没有什么问题,一旦Microsoft在95的桌面上增加MSN(Microsoft Network)的图标就不行?使得它后来将这个图标做为安装的可选项。一旦要在操作系统里增加浏览器功能就又不行了?使得它又卷进了目前的这场官司。因为谁都知道,Internet和Web技术是最有希望打破Microsoft工业界中的垄断和市场上领导性地位的。因此Netscape的Navigator, Sun的Java, Oracle的NC, 都纷纷攘壤,要出来和Microsoft对抗。而Microsoft的这些手段,特别是目前在操作系统的许可证基础上捆绑销售IE的方式就明显有了利用操作系统的垄断性优势来扩展在Internet市场份额和地位,借以打击其它竞争厂商的意图。

所以仔细考虑一下就可以知道,问题的关键根本无关技术,而在于Microsoft的垄断以及Internet技术和Web技术的特殊地位。有些事情并不是单纯的技术上的事情,到一定时候就会通过其它手段来干预。作为软件业界的支配者,Microsoft就得面对这样一个特殊的法则。这些结论恐怕大家也都心中有数,可是让我想起来总觉得可笑是,对于这场无关技术的官司,双方却又都在技术领域寻找证据,讨论什么“浏览器究竟是否是一个独立于操作系统的产品”。

如果司法部获胜了,将是最大的受益者,谁将笑得最甜呢? 很显然的,是Netscape和Microsoft的其它竞争对手(有人戏称为NOISE阵营,Netscape, Oracle, IBM, Sun and Else)。其它虽然苦Microsoft久矣却又依赖于
Microsoft的PC厂商呢?也许能够在以后和Microsoft的谈判中获得讨价还价的筹码,胆子能够因此壮一些。因此包括Compaq、Gateway 2000和Micron在内的许多PC厂商都在纷纷指控Microsoft拒绝这些厂商关于清除Win95中IE的要求。但是司法部的胜利是否真的对这些厂商有益呢?堤内损失堤外补,Microsoft会不会通过其它途径来报复呢?谁也说不准。

而对于最终用户呢?他们能否从司法部的胜利中获得好处?作为一个最终用户,我更关心他们的命运,其实也是关心自己的命运。可是我也说不准。也许可以这样说:虽然他们失去了在Windows 系统中集成浏览器功能的机会,但打破了Microsoft的垄断,有利于公平竞争,也许会在未来获得更大的利益。但反过来也可以说,虽然他们得到的是暂时阻止了Microsoft的垄断势头,但毕竟失去了在Windows系统中集成浏览器功能,得到一个更先进,更强大的操作系统的机会。

[旧作]谈谈Java

谈谈Java (1997.10.30)

Java的历史就不在这里重复了,总之Web和Web浏览器的出现和流行使Java从一个没有用武之地的丑小鸭突然间就变成了信息时代的宠儿。一夜之间,Java仿佛成了网络世界的救世主。

在那些宣传得沸沸扬扬的特性里,可移植性无疑是最有诱惑力的一点,也是我最感兴趣的一点。write once, run anywhere,这是一个多么激动人心的目标。至于它和C++语法相近,但更加简洁,易于学习等等,我并不以为然。因为我想最易于学习的东西也是需要一个学习周期的,不熟悉C++语法的人从中得不到好处,而对于熟悉C++的人来说,假使这种语言没有什么新的特点的话,又何必去学习呢?再说,语言只是一种工具,好的工具只是使产生好的程序更加容易,而不是使产生好的程序成为必然,更重要的因素是程序的设计者和编写者。是人,而不是语言造就一个优秀的程序。我见过有些人用BASIC写的程序比另一些人用C写的程序结构化更好,可读性更佳。

记得在大学里刚刚开始学习C语言的时候,书上说C的一个最大的优点就是移植性好。 Ken Tompson和Dennis M. Richie这两个UNIX和C的鼻祖用C重写了UNIX,这才造就了UNIX的一世英名。可是这种移植性并没有发展到一种激动人心的地步。因为只有标准的ANSI C才能够实现这样的可移植性,可是随着软硬件技术的发展,越来越流行的GUI界面,人机交互,以及各种外设,完全超出了ANSI C所表达的范围。越来越多的功能成为操作系统的标准部分,例如显卡驱动和打印机驱动。你用不用?用,不同的操作系统并不是都实现了这些功能,即使实现了也不是以相同的方式。不用,你的程序还能够干些什么?

当Windows平台逐渐占据主导地位的时候,又一种可移植性被提了出来,叫做API级兼容。想法也很好,不管在什么硬件平台上,系统的功能通过相同的API调用来提供,底层实现的差异通过相同的API调用来掩盖。只要程序使用这些API,那么不管使用S3, Trident显卡,或是HP, EPSON, Brother打印机,应用程序可以以相同的方式自由使用操作系统丰富的底层功能了,发展到NT,CPU的差异也逐渐被掩盖,不管在Intel, Alpha, PowerPC, MIPS上API都是一样的。因此你不再需要编写不同的代码来区分不同的CPU,适应不同的显示模式,来使用不同的打印机。92年底,厌倦了为不同打印机编写打印代码的我刚刚接触Windows,为了这种兼容性欣喜万分。但过了几年,我开始考虑将公司的一个Windows软件移植到Unix上时,这才关心这样一个问题:这时候该怎么办?

Java建立在虚拟机的基础上,从源代码兼容和API兼容上又向前走了一步,实际上已经是一种可执行代码的兼容,尽管这种代码是解释执行的。可是现在的我已经不那么容易欣喜了。Java的这种的可移植性只是一种承诺,可是承诺和现实可是差得很大的两回事。多运行一些Java Applet, 你就会发现相同的Applet在不同的
浏览器上有时候运行效果并不一样,而且我也曾经被Java的汉字支持和处理的问题搞得焦头烂额,狼狈不堪。这很容易理解,各个厂商都有自己不同的Java虚拟机的设计,谁能保证这些设计在不同厂商不同平台之上有相同的表现?谁又能保证自己的虚拟机中没有几个BUG?特别是在现在Java还不算十分成熟,在这上面还没有积累足够的经验的时候?

而且虚拟机的概念也使性能很成问题。对于小的Java applet虽然就已经有人抱怨了,但我觉得问题还不算严重,至少还能忍受。对于那些application来说呢?我只用过两个用Java编写的应用程序,浏览器HotJava和编Java用的集成环境Java Workshop,速度慢得我这样自以为还是很有耐心的人也忍受不了。Corel最近也放弃了将它所有应用程序,包括著名的CorelDraw和WordPerfect移植到Java的计划。Java这杯香喷喷的热咖啡,太急着喝也会烫了嘴的。

虽然JIT(Just-In-Time, 即时编译器)得到了发展,可以大大加快速度,但说到底,Java虚拟机的规范使得很多独特的硬件功能无法使用,对于这点一般的厂商可没办法,只得通过改变规范来实现。说起规范,Sun最近要控告Microsoft,是说Microsoft在它的IE中实现的Java不是100% Pure Java. Microsoft回击说它的PURE是指Perfectly compatible, Ubiquitous, Rich set of class library, Extensible(完美的兼容性,广泛的可用性,丰富的类库,可扩展性)。不谈PURE的定义问题和Microsoft的野心和企图,至少Microsoft这个目标是很不错的,而且它也是朝着这样的目标发展的。事实上Microsoft的Java虚拟机是兼容性最好的,它的Java类库AFC(Application Foundation Classes)也做得很漂亮,它提供了Java和ActiveX相互作用的方法。虽说我也很不满Microsoft在计算机界一手遮天,可是Java的标准是被SUN一家所控制,这样的做法,和Microsoft把持着Windows操作系统有什么区别呢?标准是必须的,但不应有一家所把握,因为这样极大地限制着创造力。王小波在他的杂文里总说世界的美好在于参差多态,我心里也向往着这种美好。这样的美好源于竞争,源于市场驱动,源于竞争中创造力能被极大地激发出来,技术能得到更大的发展,而我们普通用户,能得到更大的利益。

有人说Java是网络世界的救世主,仿佛Java一出,天下太平,我是不信的。还记得Ada语言刚出台的时候被政府规定为标准语言,可现在用Ada的有多少?C语言良好的可移植性使其迅速成为了各种平台上的通用语言,但并没有最终解决跨平台编程的问题。C++语言以它面向对象的概念和类的方式试图解决软件重用的问题,但这个问题仍旧深深困扰着软件工业界,因此现在又有了用软组件(Software Component)来解决重用问题的概念。所以不要把Java看成是解决一切问题的灵丹妙药,还是好好发展,不要过于自信地预言未来吧。

说了这么多Java的“坏话”,但我心里仍旧认为它是个优秀的编程语言,Java毕竟是这个信息时代的伟大的产物,能解决许多问题。虽然同样还存在许多问题,但有了问题才有解决的目标。有了移植性的问题才有了C语言,才有了API兼容的概念,才有了Java虚拟机。有了性能问题,才有了JIT。有了软件重用的问题,才有了面向对象,才有了软组件。我只是想说:将来必定还有更伟大的产物被创造出来。人的创造力是无穷的,因此技术的发展也是没有终结的。总有人会有神奇的灵感,让这世界更加美丽的。

如何增加数字签名

首先要有工具包,包括以下几个软件:
makecert.exe 制作cer格式的证书,即X.509证书,同时可以创建私钥
cert2spc.exe 将cer格式证书转换成spc格式证书,即PKCS #7证书
signcode.exe 将证书签署到ocx上去
chktrust.exe 检查签署证书后的ocx是否正确
还有一个certmgr.exe,是管理证书用的。可以从这里面导出root.cer来,
网上很多文章写到这个证书,但是在VC的安装盘中却找不到。其实,没
有也没关系的。这几个软件可以从VC的安装盘中找到。

下面是具体的步骤:
1、创建一个自己的证书文件:
makecert /sv “Record.PVK” /n “CN=公司名称,E=email,O=作者” dream.cer
这里,Record.PVK表示新创建的私人密钥保存文件名
DreamCaptial是你想显示的公司名
dream.cer是你创建最后的证书文件名
这些根据你自己的要求填写,最后得到Record.PVK和dream.cer两个文件。
其中,运行过程中需要输入私人密钥的保护密码,一定要输入一致,不要
出错。

2、转换cer格式为spc格式(可以省略)
cert2spc dream.cer dream.spc
得到dream.spc文件。

3、给ocx进行签名
运行signcode,命令行的我没有试验通过,我是通过界面实现的。
signcode运行后会出现数字签名向导,首先选择你要签名的ocx,
下一步后会出现签名选项,一种是典型,一种是自定义。选择自定义,
这样才能从文件选择证书,选择前面制作的dream.spc,再下一步是
选择私钥文件,选择Record.PVK,输入私人密钥的保护密码,选择散
列算法,一般用md5就可以了,下一步是选择其他证书,直接下一步,
填写一下这个控件的声明,用户用ie浏览的时候,会弹出证书说明,
再下一步是加盖时间戳,我不会,直接下一步就完成了。

4、用chktrust检查是否正确
chktrust -v RecordProj.ocx

就这样,得到了一个测试证书,恩,虽然只是一个测试证书,但至
少保证这个ocx在ie浏览的时候能够弹出来一个窗口,问你是否安装,
而不是直接禁止了。

以上来自 http://www.edown8.com/info/20051732258.html

——————————————————————-
如果用于cab的数字签名,步骤是一样的,但是cab制作时必需为其保留空间。例如:

cabarc -s 6144 N jkaraok.cab jkaraok.ocx jkaraok.inf

Update(2005-10-14):

1. 以上工具在VC 6.0中没有, Visual Studio .NET 2003中的“\Common7\Tools\Bin”目录下的工具可以按照上文直接使用。

2. 有些文档里的描述的命令行工具名称一样,但用法和上文不一样,但好像是老的SDK中的工具,是针对IE 3.2的,而新的工具是针对IE 4.0的。

3. 使用测试证书的时候还必需用“SetReg 1 true”将测试证书的信任打开,否则测试证书仍然做为不可信任的证书。此工具同样在上述目录中。

OCX控件在网页使用时Presistence Property的使用

在网页中使用OCX时,可以使用PARAM,这时候在初始化时这些OCX的属性就会被设置, 如

<OBJECT ID=”abcd” WIDTH=500 HEIGHT=500
CLASSID=”CLSID:7B222D80-14C1-44CD-ABBB-45CDEE0E5E8E”
CODEBASE=”http://chenming/jkaraok.cab#Version=1,0,0,001″>
<PARAM NAME=”LyricFontName” VALUE=”隶书”>
<PARAM NAME=”LyricFontSize” VALUE=”18″>
<PARAM NAME=”LyricTextColor” VALUE=”255″>
<PARAM NAME=”LyricCurTextColor” VALUE=”16776960″>
<PARAM NAME=”WavForeColor” VALUE=”65280″>
</OBJECT>

如果这些属性的使用还要通过别的一些处理才能起到作用,那么就需要在PX_* 函数交换过数据后进行实际的一些处理工作:

void CJKaraOKCtrl::DoPropExchange(CPropExchange* pPX)
{
ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
COleControl::DoPropExchange(pPX);

// TODO: Call PX_ functions for each persistent custom property.
PX_Color(pPX, “LyricBackColor”, m_lyricBackColor, (DWORD)RGB(178, 198, 218));
PX_Short(pPX, “LyricLineHeight”, m_lyricLineHeight, 20);
PX_String(pPX, “LyricFontName”, m_lyricFontName, “宋体”);
……

if (pPX->IsLoading())
{
// 具体的一些处理工作
……
}

}