2005年03月23日

中图分类号 for 计算机专业,及文献标识码
T 工业技术
 TP 自动化技术、计算机技术
  TP3 计算技术、计算机技术
   TP3-0 计算机理论与方法
    TP3-05 计算机与其他学科的关系
   TP30 一般性问题
    TP301 理论、方法
     TP301.1 自动机理论
     TP301.2 形式语言理论
     TP301.4 可计算性理论
     TP301.5 计算复杂性理论
     TP301.6 算法理论
    TP302 设计与性能分析
     TP302.1 总体设计、系统设计
     TP302.2 逻辑设计
     TP302.4 制图
     TP302.7 性能分析、功能分析
     TP302.8 容错技术
    TP303 总体结构、系统结构
     TP303+.1 元件
     TP303+.2 插件、机架
     TP303+.3 电源系统
    TP304 材料
    TP305 制造、装配、改装
     TP305+.1 微小型化工艺
     TP305+.2 防潮、防霉、防腐工艺
    TP306 调整、测试、校验
     TP306+.2 调整、测试方法
     TP306+.3 故障诊断与排除
    TP307 检修、维护
    TP308 机房
    TP309 安全保密
     TP309.1 计算机设备安全
     TP309.2 数据安全
     TP309.3 数据备份与恢复
     TP309.5 计算机病毒与防治
     TP309.7 加密与解密
   TP31 计算机软件
    TP311 程序设计、软件工程
     TP311.1 程序设计
     TP311.5 软件工程
    TP312 程序语言、算法语言
    TP313 汇编程序
    TP314 编译程序、解释程序
    TP315 管理程序、管理系统
    TP316 操作系统
        TP316.1/.5 操作系统:按类型分
     TP316.1 分时操作系统
     TP316.2 实时操作系统
     TP316.3 批处理
     TP316.4 分布式操作系统、并行式操作系统
     TP316.5 多媒体操作系统
        TP316.6/.8 操作系统:按名称分
     TP316.6 DOS操作系统
     TP316.7 Windows操作系统
     TP316.8 网络操作系统
     TP316.9 中文操作系统
    TP317 程序包(应用软件)
     TP317.1 办公自动化系统
     TP317.2 文字处理软件
     TP317.3 表处理软件
     TP317.4 图像处理软件
    TP319 专用应用软件
   TP32 一般计算器和计算机
    TP321 非电子计算机
     TP321+.1 求积仪、曲线仪
     TP321+.2 积分器
     TP321+.3 手动计算机
     TP321+.5 电动计算机
    TP322 分析计算机(穿孔卡片计算机)
     TP322+.1 穿孔机
     TP322+.2 验孔机
     TP322+.3 分类机
     TP322+.5 制表机
    TP323 电子计算器
     TP323+.1 台式计算器
     TP323+.2 袖珍计算器
      TP33/38 各种电子计算机
   TP33 电子数字计算机(不连续作用电子计算机)
    TP331 基本电路
     TP331.1 逻辑电路
     TP331.2 数字电路
    TP332 运算器和控制器(CPU)
     TP332.1 逻辑部件
     TP332.2 运算器
     TP332.3 控制器、控制台
    TP333 存贮器
     TP333.1 内存贮器(主存贮器)总论
     TP333.2 外存贮器(辅助存贮器)总论
     TP333.3 磁存贮器及其驱动器
     TP333.4 光存贮器及其驱动器
     TP333.5 半导体集成电路存贮器
     TP333.6 超导体存贮器
     TP333.7 只读(ROM)存贮器
     TP333.8 随机存取存贮器
     TP333.93 交换器
     TP333.95 延迟线存贮器
     TP333.96 虚拟存贮器
    TP334 外部设备
        TP334.1/.4 各种外部设备
     TP334.1 终端设备
     TP334.2 输入设备
     TP334.3 输出设备
     TP334.4 输入输出控制器
     [TP334.5] 外存储器
     TP334.7 接口装置、插件
     TP334.8 打印装置
     TP334.9 其他
    TP335 信息转换及其设备
     TP335+.1 模拟-数字转换设备
     TP335+.2 文字-代码转换设备
     TP335+.3 图形-代码转换设备
     TP335+.4 数字-模拟转换设备
    TP336 总线、通道
    TP337 仿真器
    TP338 各种电子数字计算机
     [TP338.1] 微型计算机
     TP338.2 小型计算机
     TP338.3 中型计算机
     TP338.4 大型、巨型计算机
     TP338.6 并行计算机
     TP338.7 阵列式计算机
     TP338.8 分布式计算机
   TP34 电子模拟计算机(连续作用电子计算机)
    TP342 运算放大器和控制器
     TP342+.1 运算放大器
     TP342+.2 运算器
     TP342+.3 控制器
    TP343 存贮器
    TP344 输入器、输出器
    TP346 函数发生器
    TP347 延时器
    TP348 各种电子模拟计算机
     TP348+.1 微分分析器与增量计算机
     TP348+.2 直流电子模拟计算机
     TP348+.3 交流电子模拟计算机
   TP35 混合电子计算机
    TP352 数字-模拟计算机
     TP352+.1 数字微分分析器
    TP353 模拟-数字计算机
   TP36 微型计算机
    TP368 各种微型计算机
     TP368.1 微处理机
     TP368.2 单板微型计算机
     TP368.3 个人计算机
     TP368.5 服务器、工作站
     TP368.6 网络计算机(NC)
   TP37 多媒体技术与多媒体计算机
   TP38 其他计算机
    TP381 激光计算机
    TP382 射流计算机
    TP383 超导计算机
    TP384 分子计算机
    TP387 第五代计算机
    TP389.1 人工神经网络计算机
   TP39 计算机的应用
    TP391 信息处理(信息加工)
     TP391.1 文字信息处理
     TP391.2 翻译机
     TP391.3 检索机
     TP391.4 模式识别与装置
     TP391.5 诊断机
     TP391.6 教学机、学习机
     TP391.7 机器辅助技术
     TP391.8 控制机
     TP391.9 计算机仿真
    TP392 各种专用数据库
    TP393 计算机网络
     TP393.0 一般性问题
     TP393.1 局域网(LAN)、城域网(MAN)
     TP393.2 广域网(WAN)
     {TP393.3} 洲际网络
     TP393.4 国际互联网
    TP399 在其他方面的应用

   TP18 人工智能理论
    TP181 自动推理、机器学习
    TP182 专家系统、知识工程
    TP183 人工神经网络与计算

文献标识码

A——理论与应用研究学术论文(包括综述报告);

B——实用性成果报告(科学技术)、理论学习与社会实践总结(科技);

C——业务指导与技术管理的文章(包括特约评论);

D——一般性通讯、报导、专访等;

E——文件、资料、人物、书刊、知识介绍等。

2005年01月29日

flash ActionScript 中的语法点有些很容易和C中的弄混,有必要点出来区别一下;

1、变量名大小写不敏感;
2、全局变量的使用无需先进行声明;
3、局部变量的声明用关键字“var”;
4、函数声明用function,例如:
funtion test(){
trace(“this is an example for declare a function!”);
}
5、ActionScript中的判断、循环、、注释和C是一样的;
6、多层式对象层次结构,根对象:_root表示舞台stage,_parent表示上一层对象;this表示当前对象;

2004年10月28日

Win32 API是微软的操作系统Windows提供给开发人员的编程接口,它决定了我们开发的Windows应用程序的能力。
          MFC是微软为开发人员提供的类库,在某种意义上是对Win32 API的封装。本文试图从全局角度对Win32 API和MFC进行理解──给出二者的概念模型。
          本文使用UML描述概念模型。Win32 API本不是面向对象的,我用面向对象的观点去理解它,无非是想表达其全局。

一、Win32 API的概念模型

Win32 API的object有3种:user obj,gdi obj,kernel obj。但是,如果一点不考虑OS本身的支持,就会在有些问题上疑惑,因此,我这里把“operation system负责将中断封装成message”加上。

1、user obj、gdi obj、kernel obj、system 4者的关系

由于是kernel obj部分负责将另外3者联系起来,因此我们在下图中直接深入到kernel obj部分内部。

从图中看到,在内存中运行的,除了“负责将中断封装成message”的system支持部分,还有另外3类object:kernel obj、user obj和gdi obj,每个obj都有一个句柄handle与之对应。其中,gdi obj建立了待开发的Windows 应用和外部输出设备的联系,kernel obj中的file建立了内存和永久存储设备的联系。具体说,内存中的file从可以从硬盘上来,如果这个file是可执行文件,它将生成module,module运行起来就是process,process可以包含多条thread,而thread的运行映象最终还是来自于file。thread是kernel obj中最重要的一个,因为消息队列就是thread拥有的,只有thread才能够接受message。对gdi obj、urser obj和file的操作,也是发生在thread中的。所以书都讲,process至少拥有一个thread。

2、展开“system负责将中断封装成message”部分

下面展开“system负责将中断封装成message”部分,尽早解除对“message到底是怎么形成的”的困惑。

3、展开“gdi obj”部分

开发人员可以通过gdi obj将app的信息反馈给User。

从图中看到,gdi obj有8种,其中7种为:bmp,brush,pen,region,font,palette,path。另一种比较特殊的是DC,它可以被理解为一种容器,程序员通过调用SelectPallette()将pallte放入容器,通过调用BeginPath()和EndPath()将path放入容器,其它5种gdi obj,是通过调用SelectObject()放入容器的。DC又具体分为4种,其中DisplayDC就是最常用的用来支持我们“画Window”的DC。 另外,如果觉得不好理解,请参考composite设计模式。

4、展开user obj部分

4.1 第1次迭代

window在Windows应用开发中占有重要地位。

从图中看到,window可分为3种:desktop,top-level window,child window。所有window被OS组织成tree,有专门的数据结构来管理。desktop就是树根,desktop的子节点是top-level window,top-level window的子节点是child window,child window仍然可以有子节点,同样归属于child window。tree数据结构中还记录了4种重要信息,是4种指针:parent指针、child指针、brother指针、owner指针。这样,从任何一个window就能很容易地找到其它window了。

好了,暂且得到 window = desktop + topLevel + child 的结论,看看全局先。毕竟,一步到位有时候并不好。
从图中看到,window确实占有重要地位。从逻辑是讲,thread是window的拥有者;但是,所有window一起决定了屏幕看起来是上面样子,何况点击任何一个window都会使window得相互覆盖关系发生变化,对所用window进行统一管理是必须的,所以OS又不得不统一用window tree来管理window,反映复杂的window关系。每个window都必须有一个且只能有一个客户区,还可能有一个title bar。

再来看看CreateWindow()函数的interface spec透露了哪些信息。


从图中看到,CreateWindow()负责为window建立与窗口类的联系。每个window都有一个窗口类与之对应,而一个窗口类可以对应多个window。窗口类中记录了窗口函数和菜单等资源信息,而由file生成的module正是窗口函数和资源的老家。

4.2 第2次迭代

考察消息种类。

从图中看到,每个message都是发送给某个window的。注意,msg可由SYS代码产生,也可以由API函数产生。

进一步考察window,深入topLevel和child。


从图中看到,OVERLAPPED风格的window是top-level window的一种,而另一种POPUP风格的window从本质上(行为上)是特殊的一种OVERLAPPED风格的window,虽然我们从coding的角度常常不这么认为。

还是不好,因为当我们调用CreateWindow() API函数时,明明感觉CHILD、OVERLAPPED、POPUP是“window style”。我再画一张图。

从图中看到,control必须是CHILD风格的,dialog必须是POPUP风格的,而一般性的window却可以是任意风格的。

4.3 第3次迭代

总结user obj:

CreateDialog()函数示意:

从图中看到,CreateDialog()和CreateWindow()最大的区别就是,它有对话框模板支持方便地定制dialog界面。注意,Dialog是特殊的window,窗口类它一定也是有的.

二、MFC的概念模型

前面我们研究了WIN32 API的“领域模型”,对它有较全面的认识。下面,对MFC概念模型的研究,我们把重点放在对app framework的研究上。
app framework中的message响应/传递机制是最重要的。而Hook机制和Message响应/传递机制是密切相关的,后者以前者为基础。

1. Hook机制

也许有些程序员只知道hook机制可以编写很“牛”的应用,孰不知MFC本身也是依靠hook机制的。

从图中看到,每个hook拥有一个指针队列,每个指针指向一个称为的HookProc函数,HookProc将在合适的时机被OS调用执行。hook是分不同种类的,其实正是hook的种类决定了它什么时机被OS调用执行。提示,可以看一下“订阅-发布”设计模式以助理解。

2 MFC中Message响应函数的安装

2.1 回忆API中Message响应函数的安装

API中Message响应函数的安装,是由CreateWindow()实现的,它将window与一个windowClass联系起来,而后者中记录了Message响应函数的指针。
至于细节,看一下如何用Win32 SDK或Win16 SDK写程序就清楚了,其中 DefWindowProc()是API函数,负责提供缺省的消息处理,所以,程序员只需要handle需要特殊处理的消息。

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow) 
{ WNDCLASS wndclass; ... wndclass.lpfnWndProc =WndProc; wndclass.lpszClassName = szWindowClass; 
... RegisterClass(&wndclass); hWnd = CreateWindow( szWindowClass, ...); ... } LRESULT CALLBACK 
WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam) { switch(message) { ... return; } 
return DefWindowProc(hwnd,message,wParam,lParam); } 

2.2 MFC中Message响应函数的安装

MFC中Message响应函数的安装显然更复杂,是在CWnd::CreateEx()被调用时完成的,其中还用到了Hook机制。

我们可以先猜一下MFC是怎么做的。MFC支持massage map,使得对消息的响应份散到多个message handler函数中,而不是API开发是那种集中式的消息处理函数;所以,想必会有专门的代码来负责“检索message map table然后调用message handle”。message map是为了支持程序员处理他关心的特殊message的,那么缺省的message处理逻辑在哪里呢?答案是MFC创建window obj时是用的“预定义的窗口类”,自然已经有了缺省的message处理函数。

从图中看到,CWnd有成员变量m_pfnSuper、成员变量m_hWnd、成员函数OnWndMsg()和成员函数DefWindowProc()。Wnd::OnWndMsg()负责“在message map中定义的message handle”能否处理到来的message,如果处理了要返回true;CWnd::DefWindowProc()负责对message缺省处理。
执行过程是,首先CWnd::CreateEx()被调用,window obj和window class被相应建立,此时window class的WindowProc字段存储了预定义的缺省处理函数的地址;由于有hook在监听窗口创建消息,所以注册的hookProc()会被调用执行,它将classWindow数据结构的WindowProc字段备份到CWnd::m_pfnSuper,再用SetWindowLong()改写classWindow数据结构的WindowProc字段为::AfxWndProc()的地址。当任何一个message到达时,::AfxWndProc()被调用,至于它的逻辑,聪明的你一定猜到了,先调用Wnd::OnWndMsg(),如果返回值为false,还要调用CWnd::DefWindowProc(),CWnd::m_pfnSuper指向的缺省处理逻辑,也会在CWnd::DefWindowProc()中被调用。
提示,上面其实有多态情况发生。比如你可以在搜一下pWnd->WindowProc(nMsg, wParam, lParam); 另外,OnWndMsg和DefWindowProc都是CWnd类的虚拟函数。

要是觉得不太好理解,最好在VC++里创建一个project实际跟踪一下,下面是我跟踪时调用栈映象的截图。

3. SubClass机制


从图中看到,SubClass机制以CWnd自身的m_pfnSuper为基础,和“MFC中Message响应函数的安装”很象。

4.frame work中的主要相关类

frame work中的主要相关类 就是 message route的候选人,正是它们的OnCmdMsg()共同完成了message route,形成了chain of responsability模式。

5. frame work中的chain of responsability模式

下图是一个对象树,注意消息会在纵向和横向两个方向传播。


消息在纵向方向上的传递,是在“上溯父类的massge map表”,MFC的message map完全是为了代替虚函数而采取的手段,而和message route无关。

消息在横向方向上的传递,才是message route,才是chain of responsability模式,由多个相关类的OnCmdMsg()共同完成。

三、 总结
从上面的讨论不难发现,MFC中用到了不少设计模式,如上面提到的chain of responsability模式、composite模式和“订阅-发布”模式。上面的讨论不仅有助于程序员全面掌握Win32 API和MFC,对architect设计architecture也有很大帮助。

2004年10月17日

20041016,同门师兄弟/妹一行20来号人往黄陂木兰天池一游。时入深秋,虽说秋云不雨,但雨是要下的,观乎近日天气,选日子不如撞日子,自筹划起第一个周末我们就出游了。

木兰天池风景区位于黄陂区北部的石门山,距武汉市中心仅55公里,属大别山南麓一脉,我们驱车两个半小时就到了。整个景区不大,我们两个小时不到就到达山上木兰湖边。因为距武汉市近的缘故,这里为一个新开发旅游区,因为有需求,所以就有商机,有投资,于是乎有了这个木兰山天池景区。游完之后给人最大的印象就是人造气息太浓,整条山路都是水泥石板,走在上面会让人咒骂这里的旅游开发团。

这次旅游最大的收获就是吃了一顿农家饭。虽然不相信会吃到所谓的野猪野兔,但在这样的地方还是点了一个野山羊火锅,一个野兔肉,一个马齿苋。做饭的时候我在厨房帮忙烧火洗菜,跟这里的农舍主人聊聊天。这个感觉真的很好,甚至幻想着来这里常住。临走时想买点山里的板栗带走,农舍主人不忍以劣货相欺,告诉我板栗一个月前就打玩了,这个时候的都不甜了,只好做罢。是啊,风景可以认为规划,但山里的淳朴是天然的,一如这里的水,没有污染。

回到武汉市内是18:00,夜幕降临,华灯初上。

为什么要使用Unicode?

(1) 可以很容易地在不同语言之间进行数据交换。

(2) 使你能够分配支持所有语言的单个二进制.exe文件或DLL文件。

(3) 提高应用程序的运行效率。

Windows 2000是使用Unicode从头进行开发的,如果调用任何一个Windows函数并给

 它传递一个ANSI字符串,那么系统首先要将字符串转换成Unicode,然后将Unicode

字符串传递给操作系统。如果希望函数返回ANSI字符串, 系统就会首先将Unicode

字符串转换成ANSI字符串,然后将结 果返回给你的应用程序。进行这些字符串的转

换需要占用系统的时间和内存。通过从头开始用Unicode来开发应用程序,就能够使你

的应用程序 更加有效地运行。

Windows CE 本身就是使用Unicode的一种操作系统,完全不支持ANSI Windows函数

Windows 98 只支持ANSI,只能为ANSI开发应用程序。

Microsoft公司将COM从16位Windows转换成Win32时,公司决定需要字符串的所有

COM接口 方法都只能接受Unicode字符串。

如何编写Unicode源代码?

Microsoft公司为Unicode设计了WindowsAPI,这样,可以尽量减少代码的影响。实

 际上 ,可以编写单个源代码文件,以便使用或者不使用Unicode来对它进行编译。

只需要定义两个宏(UNICODE和_UNICODE),就可以修改然后重新编译该源文件。

_UNICODE宏用于C运行期头文件,而UNICODE宏则用于Windows头文件。当编译源代

 码模块时,通常必须同时定义这两个宏。

Windows定义的Unicode数据类型有哪些?

数据类型 说明

WCHAR Unicode字符

PWSTR 指向Unicode字符串的指针

PCWSTR 指向一个恒定的Unicode字符串的指针

对应的ANSI数据类型为CHAR,LPSTR和LPCSTR。

ANSI/Unicode通用数据类型为TCHAR,PTSTR,LPCTSTR。

如何对Unicode进行操作?

字符集 特性 实例

ANSI 操作函数以str开头 strcpy

Unicode 操作函数以wcs开头 wcscpy

MBCS 操作函数以_mbs开头 _mbscpy

ANSI/Unicode 操作函数以_tcs开头 _tcscpy(C运行期库)

ANSI/Unicode 操作函数以lstr开头 lstrcpy(Windows函数)

所有新的和未过时的函数在Windows2000中都同时拥有ANSI和Unicode两个版本。

ANSI版本函数结尾以A表示;Unicode版本函数结尾以W表示。

Windows会如下定义:

#ifdef UNICODE

#define CreateWindowEx CreateWindowExW

#else

#define CreateWindowEx CreateWindowExA

#endif // !UNICODE

如何表示Unicode字符串常量?

字符集 实例

ANSI “string”

Unicode L“string”

ANSI/Unicode T(“string”)或_TEXT(“string”)

一、其它数据类型转换为字符串

整型(int) 

itoa(i,temp,10);///将i转换为字符串放入temp中,最后一个数字表示十进制 

itoa(i,temp,2); ///按二进制方式转换 

长整型(long) 

ltoa(l,temp,10); 

浮点数(float,double) 

用fcvt可以完成转换,这是MSDN中的例子: 

int decimal, sign; 

char *buffer; 

double source = 3.1415926535; 

buffer = _fcvt( source, 7, &decimal, &sign ); 

运行结果:source: 3.1415926535 buffer: ‘31415927′ decimal: 1 sign: 0 

decimal表示小数点的位置,sign表示符号:0为正数,1为负数  

CString变量

str = “2008北京奥运”;

buf = (LPSTR)(LPCTSTR)str;

BSTR变量

BSTR bstrValue = ::SysAllocString(L”程序员”);

char * buf = _com_util::ConvertBSTRToString(bstrValue);

SysFreeString(bstrValue);

AfxMessageBox(buf);

delete(buf);

CComBSTR变量

CComBSTR bstrVar(“test”);

char *buf = _com_util::ConvertBSTRToString(bstrVar.m_str);

AfxMessageBox(buf);

delete(buf);

_bstr_t变量

_bstr_t类型是对BSTR的封装,因为已经重载了=操作符,所以很容易使用

_bstr_t bstrVar(“test”);

const char *buf = bstrVar;///不要修改buf中的内容

AfxMessageBox(buf);

通用方法(针对非COM数据类型)

用sprintf完成转换

char  buffer[200];

char  c = ‘1′;

int   i = 35;

long  j = 1000;

float f = 1.7320534f;

sprintf( buffer, “%c”,c);

sprintf( buffer, “%d”,i);

sprintf( buffer, “%d”,j);

sprintf( buffer, “%f”,f);

二、字符串转换为其它数据类型

strcpy(temp,”123″);

短整型(int)

i = atoi(temp);

长整型(long)

l = atol(temp);

浮点(double)

d = atof(temp);

CString变量

CString name = temp;

BSTR变量

BSTR bstrValue = ::SysAllocString(L”程序员”);

…///完成对bstrValue的使用

SysFreeString(bstrValue);

CComBSTR变量

CComBSTR类型变量可以直接赋值

CComBSTR bstrVar1(“test”);

CComBSTR bstrVar2(temp);

_bstr_t变量

_bstr_t类型的变量可以直接赋值

_bstr_t bstrVar1(“test”);

_bstr_t bstrVar2(temp);

三、其它数据类型转换到CString 

使用CString的成员函数Format来转换,例如: 

整数(int) 

str.Format(“%d”,i); 

浮点数(float) 

str.Format(“%f”,i); 

字符串指针(char *)等已经被CString构造函数支持的数据类型可以直接赋值 

str = username; 

对于Format所不支持的数据类型,可以通过上面所说的关于其它数据类型转化到 

char * 

的方法先转到char *,然后赋值给CString变量。

四、BSTR、_bstr_t与CComBSTR 

CComBSTR 是ATL对BSTR的封装,_bstr_t是C++对BSTR的封装,BSTR是32位指针,但并 

不直 接指向字串的缓冲区。 

char *转换到BSTR可以这样: 

BSTR b=_com_util::ConvertStringToBSTR(“数据”);///使用前需要加上comutil. h和comsupp.lib 

SysFreeString(bstrValue); 

反之可以使用 

char *p=_com_util::ConvertBSTRToString(b); 

delete p; 

具体可以参考一,二段落里的具体说明。 

CComBSTR与_bstr_t对大量的操作符进行了重载,可以直接进行=,!=,==等操作,所 

以使用非常方便。 特别是_bstr_t,建议大家使用它。 

五、VARIANT 、_variant_t 与 COleVariant 

VARIANT的结构可以参考头文件VC98\Include\OAIDL.H中关于结构体tagVARIANT的 

 定义。 对于VARIANT变量的赋值:首先给vt成员赋值,指明数据类型,再对联合结构中相 

同数据类型的变量赋值,举个例子: 

VARIANT va; 

int a=2001; 

va.vt=VT_I4;///指明整型数据 

va.lVal=a; ///赋值 

对于不马上赋值的VARIANT,最好先用Void VariantInit(VARIANTARG FAR* 

pvarg);进行 

初始化,其本质是将vt设置为VT_EMPTY,下表我们列举vt与常用数据的对应关系: 

Byte bVal;  // VT_UI1. 

Short iVal;  // VT_I2. 

long lVal;  // VT_I4. 

float fltVal;  // VT_R4. 

double dblVal;  // VT_R8. 

VARIANT_BOOL boolVal;  // VT_BOOL. 

SCODE scode;  // VT_ERROR. 

CY cyVal;  // VT_CY. 

DATE date;  // VT_DATE. 

BSTR bstrVal;  // VT_BSTR. 

DECIMAL FAR* pdecVal  // VT_BYREF|VT_DECIMAL. 

IUnknown FAR* punkVal;  // VT_UNKNOWN. 

IDispatch FAR* pdispVal;  // VT_DISPATCH. 

SAFEARRAY FAR* parray;  // VT_ARRAY|*. 

Byte FAR* pbVal;  // VT_BYREF|VT_UI1. 

short FAR* piVal;  // VT_BYREF|VT_I2. 

long FAR* plVal;  // VT_BYREF|VT_I4. 

float FAR* pfltVal;  // VT_BYREF|VT_R4. 

double FAR* pdblVal;  // VT_BYREF|VT_R8. 

VARIANT_BOOL FAR* pboolVal;  // VT_BYREF|VT_BOOL. 

SCODE FAR* pscode;  // VT_BYREF|VT_ERROR. 

CY FAR* pcyVal;  // VT_BYREF|VT_CY. 

DATE FAR* pdate;  // VT_BYREF|VT_DATE. 

BSTR FAR* pbstrVal;  // VT_BYREF|VT_BSTR. 

IUnknown FAR* FAR* ppunkVal;  // VT_BYREF|VT_UNKNOWN. 

IDispatch FAR* FAR* ppdispVal;  // VT_BYREF|VT_DISPATCH. 

SAFEARRAY FAR* FAR* pparray;  // VT_ARRAY|*. 

VARIANT FAR* pvarVal;  // VT_BYREF|VT_VARIANT. 

void FAR* byref;  // Generic ByRef. 

char cVal;  // VT_I1. 

unsigned short uiVal;  // VT_UI2. 

unsigned long ulVal;  // VT_UI4. 

int intVal;  // VT_INT. 

unsigned int uintVal;  // VT_UINT. 

char FAR * pcVal;  // VT_BYREF|VT_I1. 

unsigned short FAR * puiVal;  // VT_BYREF|VT_UI2. 

unsigned long FAR * pulVal;  // VT_BYREF|VT_UI4. 

int FAR * pintVal;  // VT_BYREF|VT_INT. 

unsigned int FAR * puintVal; 

_variant_t是VARIANT的封装类,其赋值可以使用强制类型转换,其构造函数会自 

 动处理这些数据类型。 

使用时需加上#include <comdef.h> 

例如: 

long l=222; 

int i=100; 

_variant_t lVal(l); 

lVal = (long)i; 

COleVariant的使用与_variant_t的方法基本一样,请参考如下例子: 

COleVariant v3 = “字符串”, v4 = (long)1999; 

CString str =(BSTR)v3.pbstrVal; 

long i = v4.lVal;

六、其它 

对消息的处理中我们经常需要将WPARAM或LPARAM等32位数据(DWORD)分解成两个 

16位数 据(WORD),例如: 

LPARAM lParam; 

WORD loValue = LOWORD(lParam);///取低16位 

WORD hiValue = HIWORD(lParam);///取高16位 

对于16位的数据(WORD)我们可以用同样的方法分解成高低两个8位数据(BYTE),例如 

WORD wValue; 

BYTE loValue = LOBYTE(wValue);///取低8位 

BYTE hiValue = HIBYTE(wValue);///取高8位 

两个16位数据(WORD)合成32位数据(DWORD,LRESULT,LPARAM,或WPARAM) 

LONG MAKELONG( WORD wLow, WORD wHigh ); 

WPARAM MAKEWPARAM( WORD wLow, WORD wHigh ); 

LPARAM MAKELPARAM( WORD wLow, WORD wHigh ); 

LRESULT MAKELRESULT( WORD wLow, WORD wHigh ); 

两个8位的数据(BYTE)合成16位的数据(WORD) 

WORD MAKEWORD( BYTE bLow, BYTE bHigh ); 

从R(red),G(green),B(blue)三色得到COLORREF类型的颜色值 

COLORREF RGB( BYTE byRed,BYTE byGreen,BYTE byBlue ); 

例如COLORREF bkcolor = RGB(0×22,0×98,0×34); 

从COLORREF类型的颜色值得到RGB三个颜色值 

BYTE Red = GetRValue(bkcolor); ///得到红颜色 

BYTE Green = GetGValue(bkcolor); ///得到绿颜色 

BYTE Blue = GetBValue(bkcolor); ///得到兰颜色  

 

 

 

2004年10月13日

 有一个人在森林中漫游的时候,突然遇见了一只饥饿的老虎,
老虎大吼一声就扑了上来。
他立刻用生平最大的力气和最快的速度逃开,但是老虎穷追不舍,
他一直跑一直跑一直跑,最後被老虎逼入了断崖边上。
站在悬崖边上,他想:「与其被老虎捉到,活活被咬、肢解,
不如跳入悬崖,说不定还有一线生机。]
他纵身跳入悬崖,非常幸运的卡在一棵树上,
那是长在悬崖旁的梅树,树上结满了梅子。
正在庆幸的时候,他听到悬崖深处传来巨大的吼声,
往崖底望去,原来有一 只凶猛的狮子正抬头看著他,
狮子的声音使他心颤,但转念一想:
「狮子与老虎是相同的猛兽,被什么吃掉,都是一样的。」
他一放下心,又听见了一种声音,仔细一看,
 一黑一白的两只老鼠,正用力地咬著梅树的树干。
他先是一阵惊慌,立刻又放心了,
他想:「被老鼠咬断树干跌死,总比被狮子咬好。」
情绪平复下来后,他感到肚子有点饿,看到梅子长得正好,
 就采了一些吃起来。他觉得一辈子从来没吃过那么好吃的梅子,
找到一个三角形的枝丫休息,他想著:
「既然迟早都要死,不如在死前好好睡上一觉吧!」> >
他在樹上沉沉的睡去了。
睡醒之后,他发现黑白老鼠不见了,老虎、狮子也不见了。
他顺著树枝,小心翼翼的攀上悬崖,终于脱离险境。
原来就在他睡著的时候,饥饿的老虎按捺不住,
终于大吼一声,跳下悬崖。
黑白老鼠,听到老虎的吼声,惊慌逃走了。
跳下悬崖的老虎崖下的狮子展开激烈的打斗,双双负伤逃走了。
 
由我们诞生那一刻开始,
苦难.就像饥饿的老虎一直追赶著我们,
死亡,就像一只凶猛的狮子,一直在悬崖的尽头等待,
白天和黑夜的交替,就像黑白老鼠,不停地正用力咬著我們暫時棲
们暂时栖身的生活之树,
总有一天我们会落入狮子的口中。
既然知道了生命中最坏的情景是死亡,
唯一的路,
就是安然地享受树上甜美的果子,
 然後安心地睡觉,
只有存著这样单纯的心……少欲望、多一点赤子之心。
    幸福是一颗梦想的种子
    需要用生命的热情去灌溉
    幸福不是靠别人给的
    而是要认真抓住~用心选择!選擇       
 

本科毕业两年有半了,不知道今天大伙各自的心境和处境如何?真的很想大家。而且今天是我们的寝室生日,不知道另外五个××还记得否?今晚没有月亮,已然不能千里共婵娟了,能做的只是思念。

读研有两年有半了,我的专业可能不容于现在的潮流,但是幸运的是我遇到了一个好老板。从读研开始就进试验室,按时上下班,辛是辛苦点,但老板对我很好,免了我的学费,还给我发点粮饷。我能做的就是感恩,努力的工作,甚至给老板当秘书,做网站,做课件,做售后,当然最重要的是做自己的那部分项目。

谈朋友也谈了四年了,高中的前排,可惜到现在隔在我们之间的是空间,连接我们的只有电话线和电磁波,最奢侈的也只能是一年五六次的见面,最心疼的就是每个月不下200的话费了。真的很累……

活了24个年头了,在学校呆得太久太久,真的该出去混混了,下半年结了项目,发了文章,可能会出去走走。这个月如果条件允许,可能会去一趟甬沪苏杭,在东边的兄弟们可能会去找你们的哦,应该还记得我的模样吧,我还是那么瘦,嘻嘻。

假设:
    要调试hook.dll hook.h hook.lib

1。建立一个新工程Test,将hook整个工程目录拷贝到Test目录下

2。在Test工程中需要用到hook.dll的源文件中(或stdafx.h中)加入
     #include “.\hook\hook.h”
   这样在该源文件中使用”::”就可以索引到hook.h中所有的导出函数、
   变量以及类
  
3。在Test的工程设置->Link->Object/library modules中加入
     ./hook/debug/hook.lib

4。编译连接好Test之后,发现未找到hook.dll. 这需要设置path.
   可以在工程设置->Debug->Working directory中加入
     e:\Test\hook\debug\
   也可以在autoexe.bat中设置路径

5。通过工程->Insert Project into Workspace将hook.dsp工程加入 
   Test项目中。

6。设置hook工程为活动工程,在工程>Debug>Executable for
   Debug session中加入:
     e:\test\debug\test.exe

7。现在设置断点,按F5可以正常调试了

注意:当调试的DLL被映射到其他的应用程序(非TEST)进程空间并运行时,
在该DLL中设置的断点无效,当然可以通过MessageBox来查看变量,若该DLL
是MFC扩展DLL,则还可以用TRACE或afxDump来查看变量。

 Intel hex 文件格式解密

    Intel hex 文件常用来保存单片机或其他处理器的目标程序代码。它保存物理程序存储区中的目标

代码映象。一般的编程器都支持这种格式。
    Intel hex 文件全部由可打印的ASCII字符组成(可以用记事本打开),如下例所示:

  :2000000012014c75a800e4f508f509780a7a78e4f608dafcd283fcfded240af9a7050dbd81    
  :2000200000010ced2488ec34ff50edc283e4fcfded240af9e76d7013ed33e43c700d0dbd2a      
  :2000400000010ced2488ec34ff50e50509e50970020508e50924a8e50834fd50aee4f50874

    Intel hex 由一条或多条记录组成,每条记录都由一个冒号“:”打头,其格式如下:

         :CCAAAARR…ZZ  

    其中:

CC 

    本条记录中的数据字节数

AAAA 

    本条记录中的数据在存储区中的起始地址

RR 

    记录类型: 

00 数据记录 (data record) 
01 结束记录 (end record) 
02 段记录 (paragraph record) 
03 转移地址记录 (transfer address record)

… 

    数据域

ZZ 

    数据域校验和

    Intel hex文件记录中的数字都是16进制格式,两个16进制数字代表一个字节。CC域是数据域中的实际字节数,地址、记录类型和校验和域没有计算在内。校验和是取记录中从数据字节计数域(CC)到数据域(…)最后一个字节的所有字节总和的2的补码。
cypress文件夹中有一个hex2c的程序,可以将hex文件形式的固件变换成×.c文件;