今天遇到一个需求:在一个dll中让主程序中的某个窗口显示出来。该窗口上还有很多复杂的控件。
开始,我直接把TForm类型(VCL类型)封装到了dll中,然后用Form->Show()即可,结果在dll的去勾选build with runtime package时,编译通不过,因为使用了VCL类型时,必须使用一些vcl包进行编译。而如果勾选了build with runtime package,则不能在其他的机子上使用该dll了。
于是这种方法行不通。(如果哪位仁兄有打包含VCL的DLL的例子,并且dll体积不大的话,一定要告诉我)后来我又使用了API函数ShowWindow,结果不如人意,因为这个函数使用极为复杂,仅适合于单窗体的操作,对于含有很多复杂控件的窗体来说,仅仅使用ShowWindow(HWND)是不行的,而且传入dll的参数自然是越少越好。
最后,一个想法在我脑中诞生,在windows操作系统中,我觉得最强大的指令之一SendMessage几乎是万能的。在dll中只要知道了窗体的句柄,则可以向其发送任何消息。但是,如果单纯的发送SendMessage(HWND,WM_SHOWWINDOW,wp,lp)有用吗,答案是否定的,这和ShowWindow方法如出一辙。
但是我们可以通过发送一个特定的消息A,当目标窗体接受到该特定消息A时,就调用Form->Show()函数。这时,可能大部分人想到的是使用自定义消息。可我懒得去查如何注册和使用自定义消息了(自己写过,总结在札记里)。那不使用自定义消息,又如何做呢。
消息是死的,参数是活的,说到这,肯定大家知道怎么做了。对,我们就使用已知消息WM_SHOWWINDOW,然后把它的wp,lp参数设置的奇怪点,让目标窗体的WndProc消息循环函数判断一下就行了。我使用的消息是这样的:
Dll中:
SendMessage(pwindow,WM_SHOWWINDOW,-1,-1);//使用两个-1来做为奇怪的参数。
窗体的WndProc中:
if(Msg.Msg==WM_SHOWWINDOW)
{
if(Msg.WParam==-1&&Msg.LParam==-1)
{
Show();
return;
}
}
使用了如上方法后,就可以把dll中的#include<vcl.h>删除了,而且去掉勾选build with runtime package也可以成功build了。这样就不需要用到vcl60.bpl和其他库了。程序立马小了2-5M。通过这个例子,告诉自己和大家,API是死的,但是人是活的,很多功能并不需要多强大的技术,用好现有的API,也许就能取得效率和功能上的双赢,毫不逊色于其他技术。