The Problem With Subclassing
If you develop ActiveX controls and intend to subclass or hook a window, you'll very quickly discover that doing it is not at all straightforward. A typical problem is that a control which works fine when there is a single instance on a form suddenly stops working or starts GPFing when you place two instances on the form. Why is this happening?The AddressOf operator requires you to place the callback routine in a module (and most annoying this is too!). This module is shared between all instances of your control and therefore the variables and subroutines contained by that module are also shared.To visualise the situation, consider a control which wants to know if its parent has changed size. To do this, you create a callback routine in a module to handle the WndProc callback. Then, you want to add this callback routine to the parent's window handle so you will be routed all the parent's messages. To add the callback, you change the parent's GWL_WNDPROC Window Long to the address of your WndProc function. This function returns a pointer to the previously installed WndProc function, which you must be sure to forward all messages to that you aren't fully handling yourself (otherwise you quickly find your control will do nothing or, more likely, prevent its container from doing anything!). When you remove an instance of your control, you need to put the old WndProc back again.

解决方案 »

  1.   

    Let me try.
    子类化的问题
    当你准备开发一个ACTIVEX控件,并试图子类化或挂钩一个窗体时,你很快就会发现这并不那么简单。一个典型的问题是当你在窗体里放置了两个类实例时,原来运行正常的单实例控件会突然停止工作或发生GPF(General Protection Fatal)事件,为什么会这样呢?
    AddressOf操作符需要你把回调例程放到类模块里(这也是最恼人的!)。这个模块将被你的所有控件实例所共享,也就是说其间的变量和子例程都会被共享。
    为了形象地说明这一情景,请考虑这样的一个控件,它会感知到父窗体的大小是否有所改变。为此,需要在模块里创建一个回调例程用来满足WNDPROC的回调需求。然后,你要把这个回调例程加入到父窗体里面去以便处理全部父窗体的消息。为了添加这个回调过程,你需要把窗体的消息处理入口地址改为你自己的处理函数的地址(I注:就是通过SetWindowLong这个API),该函数(就是我注释的那个API)会返回原来的消息处理函数的地址,你必须确保把那些你自己没有处理彻底的消息交给原处理函数。(否则,你会看到你的控件什么也没做,而且非常可能会阻止它的容器做任何事情)。当你去掉你的控件实例时,你需要恢复窗体的消息处理函数入口地址。
    好累!你的原文应该还没完吧,我想下面要说的就是正因为每创建一个新实例都需要替换并保留窗体消息例程,而你用于保存原来入口地址的变量是共享的,结果在出现两个例程时,真正的入口地址就被覆盖了,覆盖物就是你自己的处理函数入口地址,结果就出现循环了,没响应了,死机了,这就是问题所在,解决办法我设想是用动态数组来保存,具体细节你自己想吧。
      

  2.   

    请教各位大哥
    小弟使用file system objects 读取文件,要从一个文本文件中读取数据,程序如下:
    Private Sub Command1_Click()
        Dim fso As New filesystemobject, txtfile, fil As File, ts As textstream
        Set txtfile = fso.createtextfile("c:\testfile.txt", True)
        MsgBox "正在写入文件"
        Set fil = fso.getfile("c:\testfile.txt")
        Set ts = fil.openastextstream(forwriting)
        ts.write "hello world"
        ts.Close
        Set ts = fil.openastextstream(forreading)
        s = ts.readline
        MsgBox s
        ts.Close
    End Sub
    程序运行后出现如下提示:

    编译错误:
    用户定义类型未定义请问是什么原因?