子类化初始工作代码FHookWndProc := MakeObjectInstance(HookWndProc);
OldWndProc := Pointer(GetWindowLong(ParentWindow, GWL_WNDPROC));
SetWindowLong(ParentWindow, GWL_WNDPROC, Longint(FHookWndProc));
OldWndProc的变量类型是Pointer我想把OldWndProc转换类型为String保存成文本文件,用下面的代码可以转换成文本,貌似是函数的地址。ShowMessage(Format('%p', [OldWndProc]));
我的问题是如何把它再转换成Pointer类型并且可以在窗口函数中使用with Msg do
begin
  Result := CallWindowProc(OldWndProc, ParentWindow, Msg, WParam, LParam);
end;CallWindowProc函数里面的OldWndProc是通过String类型转换成Pointer类型。谢谢大家,祝春节快乐。

解决方案 »

  1.   

    指针只是一个地址,你光保留个地址有嘛用?要想序列化和反序列化,需要将整个类保存起来,而且还要看这个类是否继承自TPersisten
      

  2.   

    如果该类不支持持久化,那你就自己做一个文件保留该类的关键属性,下次重新create一个,把属性填上就行了
      

  3.   

    谢谢楼上的高手,OldWndProc是IE的消息处理函数,我想把这个函数持久化怎么办?
      

  4.   

    我的程序是一个ActiveForm(OCX)在IE里用的,需要截获IE的消息进行处理。
    ParentWindow是IE窗口的句柄。
      

  5.   

    我想持久化这个窗体函数是因为多次调用ocx就会多次子类化ie窗口函数,导致复原IE的窗口函数出错,所以我在第一次运行ocx的时候就把IE的窗口函数保存在某个地方,留着以后复原用。
      

  6.   

    如果你指的是主程序不关闭,指针指向的地址没有释放的话,你可以参看钩子的实现
    http://wenku.baidu.com/view/8cd214717fd5360cba1adb71.html
    这句是替换原始函数指针gwl_wndproc为你自己的函数newwndproc
    oldwndproc=point(setwindowlong(application.handle,gwl_wndproc,intger(newwndproc)));
    这句就是还原函数指针gwl_wndproc
    setwindowlong(application.handle,gwl_wndproc,intger(oldwndproc));
      

  7.   

    OldWndProc := Pointer(cc); //cc是ie窗口函数的地址,我转换成功了但是程序报错了,这个问题真是头疼啊。
      

  8.   


    谢谢高手回复,ie窗口是可以关闭的,只是会报错。这个原因这是清楚的。
    具体流程我给你说一下:
    1)首先ocx第一次运行取得的ie消息函数地址是正确的,直接关闭ie是没有问题的。复原的地址也是ie的
    2)如果再打开一个新的ie标签,再载入相同的ocx这时候取的消息函数就不是ie的了,而是第一次ocx的消息处理函数,这样就会有一个问题,如果关闭第一个ocx网页,再关闭第二个的话,ie报错。这是因为关闭第一个网页的时候消息函数地址也被ie收回了,第二个网页复原的时候地址不存在。错非先关闭第二个ocx,再关闭第一个是正常的。
      

  9.   


    ie是多标签浏览器,每个标签类名是frame tab,所以的标签都是ie的子窗体。我是把这个地址值保存到一个文件中,如果需要多次加载ocx我就读取这个文件把ie的函数地址复原,以后关闭整个ie窗口的时候,可以复原所有正确的ie窗口地址。比如说我有10个标签页都载入这个ocx,直接关闭ie肯定出错。我不太清楚关闭整个ie标签页回收资源的顺序。但可以肯定的是,这10个页面我按照后进先出的顺序,一个个关闭程序是完成正常的。如果先把第一个ocx关了,那么关闭其它任意9个页面当中的一个都会直接报错。
      

  10.   

    通俗一点讲,假如一个网页已经加载了ocx
    现在我又加载一次ocx,下面的代码OldWndProc保存的地址其实是第一次加载ocx的消息处理函数地址
    FHookWndProc := MakeObjectInstance(HookWndProc);
    OldWndProc := Pointer(GetWindowLong(ParentWindow, GWL_WNDPROC));
    SetWindowLong(ParentWindow, GWL_WNDPROC, Longint(FHookWndProc));
    如果把第一次加载的ocx网页关闭了
    那么第二次加载的ocx在恢复窗口地址的时候就会出错,原因他要恢复的地址已经被ie回收了
    SetWindowLong(ParentWindow, GWL_WNDPROC, Longint(OldWndProc));
    这里的OleWndProc地址其实是第一个ocx的消息处理函数。
          
      

  11.   

    另外dll里是有进程和线程的访问处理的
              DLL_PROCESS_ATTACH:
            DLL_PROCESS_DETACH:
            DLL_THREAD_ATTACH:
            DLL_THREAD_DETACH: 
      

  12.   


    高手别啊,其实只要在第一次运行ocx的时候把OleWndProc保存住,以后再子类化的时候就用保存的函数地址就行。我现在卡在这里了,不知道如何把这个oldwndproc持久化。
      

  13.   


    我貌似搞定了,我用txt文件保存ie原始窗口函数,只有第一次创建文本文件,以后的加载直接读文本文件,把里面的地址转换就行了,就是有一点不好,还要维护这个文本文件。    fn := 'c:\' + IntToStr(ParentWindow) + '.txt';
        AssignFile(F, fn);
        
        if (FileExists(fn)) then
        begin
          Reset(F);
          Readln(F, cc);
          ShowMessage(cc);
          OldWndProc := Pointer(StrToInt('$'+ cc));
        end else
        begin
          OldWndProc := Pointer(GetWindowLong(ParentWindow, GWL_WNDPROC));
          Rewrite(F);
          Writeln(F, Format('%p', [OldWndProc]));
        end;
        CloseFile(F);
      

  14.   

    新问题来了,多是多次子类化ie窗口函数,但是只有一个ocx能捕获消息,其它的ocx没有消息响应了,郁闷。
      

  15.   

    没怎么研究过ocx,我印象里ocx和dll类似,如果加载机制相同的话,应该在进程里只加载一次,多个线程调用只会将一个地址映射到调用函数中