Tuesday, January 27, 2009

Windows 窗口创建时的几个关键消息调用顺序,及其使用注意点.

这个东西其实做个实验就可以知道.不过分析起来比较有意思.
CreateWindow Called
WM_CREATE
CreateWindow Return
Message Loop

在CreateWindow和Message Loop之间,可以调用相应的函数如ShowWindow, UpdateWindow.
其事件顺序是:

ShowWindow Called
WM_SIZE
ShowWindow Return
UpdateWindow Called
WM_PAINT
UpdateWindow Return

如果带有WS_VISIBLE的窗体,并不主动调用ShowWindow和UpdateWindow函数.则在Message Loop开始后,先调用 WM_SIZE,后调用WM_PAINT.

其实这些都很容易理解,不过使用的时候就有很多地方需要注意了.

比如我们经常将CreateWindow的返回值作为全局的变量.我们也会在WM_CREATE时调用一些初始化函数.
这些初始化函数需要的主窗口句柄就必须是WM_CREATE消息的,而不能是全局的那个.因为全局的那个还没有被正确地返回.

同样的道理.如果WM_SIZE和WM_PAINT都使用一些公共的变量,就要在WM_SIZE里面先准备好.也尽量不要主动调用WM_PAINT.否则难免出现变量混乱的局面.

Saturday, January 24, 2009

工具介绍 Control Spy 2.0

Control Spy是微软免费提供的一个小巧的工具.别的不说,先看截图.

如果你做过WIN32开发.可能你已经看出来了.这是一个用来测试Windows公共控件的工具.
微软的原话是Control Spy is a tool to help developers understand common controls.

公共控件(common controls)给人的感觉是虽然很普通,但是却很复杂.(这点用.NET编程的人我猜一般是不会体会到的,前几天一个学弟对我说"C#的按钮划过的事件怎么这么复杂啊...". –_-~~)

使用Control Spy可以几乎做到对控件的完全控制.包括Message, Notify.可以直接更改STYLE.
对应不熟悉控件消息的人来说这绝对是福音.
不过我使用的时候发现很多BUG,比如某些Style识别出错.有些STYLE不起效果.
我想这就是为什么他没有被加入到VS中的原因.
还有就是由于其自身设计的原因,有些东西是一辈子捕捉不到的.比如更改某些STYLE后重绘的XXX.还有窗体移动的消息....

一个简单的小例子,更改按钮文字.通过他至少知道参数是从LPARAM传进去的.

另外,通过它我终于明白了为什么Vista的控件有时候渐变得很干涩...
原来它是通过把原来一次解决的WM_PAINT事件一连调用16次来达到渐变...
以图为证.

PS:内部代号为BinPlayer的播放器进展缓慢.在家7天重构了3次.还是觉得不满意.核心功能没增加反而减少了...

Windows API 手动载入 动态连接库 (.dll, .ax等) 运行其函数

自己编程一般不会用到这个.
大多数可以编程的库都提供文档,头文件,lib等文件.
不过有些是不提供的.活生生只给你一个dll.
不过这时候如果知道里面函数的名字和参数啥的,就可以调用.

以ax为例,ax后缀的一般是解码器的Filter.编写过filter的都知道,其实他就是一个DLL,有些解码器就是以dll作为后缀的.
现在:我要载入RealMediaSplitter.ax这个连接库,并且运行DllRegisterServer这个无参函数.
这里仅给出一个样例.核心就是使用LoadLibrary和GetProcAddress函数,用了一个typedef来使其看起来像模像样.

if(HMODULE h = LoadLibrary(TEXT("RealMediaSplitter.ax"))) {
typedef HRESULT (__stdcall * PDllRegisterServer)();
if (PDllRegisterServer p = (PDllRegisterServer)GetProcAddress(h, "DllRegisterServer")) {
p();
}
FreeLibrary(h);
}

测试结果OK.其效果等价于在终端运行regsvr32 RealMediaSplitter.ax, 但是不是绿色载入, 以后会介绍一种绿色载入的方法, 那种方法在BinPlayer中被采用, 非常安全.