现状如下:(1).    A.exe  是主程序,上面有一个button1,点击后,运行子系统B.exe,并融合到A.exe的pageControl(或panel)上来。
    通过 windows.SetParent来实现B.exe融合到A.exe中来的。(2).   B.exe中有一个按钮,点击代码如下:
        form1:=Tform1.create(self);
        form1.showmodal;
        form1.release;运行后,B能正常融合,点击B中的按钮,表单form1也能正常工作,包括TAB等都能正常工作。但是:无意中切换到已打开的EXCEL或其他任务栏中的程序,再回来时,发现刚打开的form1不见了,
      于是用ALT+TAB 进行切换,找到了刚找开的form1,原来跑到A.exe(最大化)后面去了。于是:修改B.exe中按钮的代码:
      form1:=Tform1.create(self);
      form1.ParentWindow:=application.MainForm.Handle; //加了这句
        form1.showmodal;
        form1.release;再运行,并点击任务栏下的其他内容,再回到A.exe中来,form1还在(这次没有“消失”),但是form1窗体标题始终不能成激活状态,即使用鼠标点击窗体标题,也不能成激活状态。后发现,点击B.exe按钮,form1出现时,窗体就不能成激活状态。后来又用了 setActiveWindow、SetForcegroundWindow、PostMessage等想将form1设置成激活状态,一直不行。后来又用SPY想强行激活,也不行。所以,请教各位高手,我哪一个环节出现问题了。网上也找了DLL融合的方法进行参考,没有能解决。

解决方案 »

  1.   

    你这个是应用程序句柄的问题,你两个exe运行,相当于在两个进程空间中,
    你这种做法不好控制的,有个解决方案不知道是否适合你,你可以尝试把B改成带窗体的动态库,然后,把A的application句柄传入B.dll,控制起来就很自如了。
      

  2.   

    同意楼上的,将application传进去。公用一个。
    还有form1:=Tform1.create(self); 这个也改为application创建
      

  3.   

    谢谢楼上几位。因为B是一个独立的系统,也有不少表单,都改成DLL可能性很小。
      

  4.   

    你在B.exe中那个按钮单击的时候别创建form1,而是直接发消息给A.exe,
    然后在A.exe中写一个消息处理函数,如果收到消息,立即给B.exe发消息,把LParam设置成A的Application.handle,然后在B.exe中添加一个消息处理函数,
    收到A的消息之后,把LParam转换成Application,取个名字App_A之后
      form1:=Tform1.create(App_A);
      form1.ParentWindow:=App_A.MainForm.Handle; //加了这句
      form1.showmodal;
      form1.release
    这个方法试试可不可以,我这里没你的代码,没法试验。我估计应该差不多。
      

  5.   

    目前暂时在B.exe中用findwindow返回A.exe的MainForm的句柄,来作为Form1的父一级句柄Var 
      H:HWND;
    begin
      H:=FindWindow('A的标题',nil);
      if H>0 then
      begin
        form1:=Tform1.create(App_A);
        windows.SetParent(form1.Handle,H); //后来看了ParentWindow还是调用SetParent,就直接用
        form1.showmodal;
        form1.release 
      end;
    end;
    但是这样有一个缺点还没解决:尽管目前B.exe的 form1能够正常工作了,而且窗体也有焦点,且不会“消失"
    可是,此时A中所有的按钮及其他控件都还能够使用,而不是象常规EXE调用窗体showmodal后,必须关闭后,才可以使用主窗体中的内容。因此,还有一些细节还有待进行学习、探讨。
      

  6.   

    上面form1:=Tform1.create(App_A);
      就改为form1:=Tform1.create(application);
      

  7.   

    showmodal是在同一线程里搞的吧。
      

  8.   

    showmodel本身是接管了主程序的消息队列来实现showmodel的效果的,你的b程序本身和a程序根本就是两个进程,b的showmodel没办法接管其他进程的消息队列的
    我身边没环境,你试下这样看看
    在a程序点击运行时先createprocess运行b.exe,然后waiteforsingleobject等待b运行结束,然后b再showmodel,此时a是阻塞状态,不会响应鼠标事件的
      

  9.   

    这样,岂不是 一运行B,A里就不能操作了,直到b结束。我估计不是lz想要的吧~ 估计楼主是想 showmodel 时 A不能操作;不showmodel时,A可以操作
      

  10.   

    那问题有点麻烦,需要重载a的wndproc a.exe运行b.exe后一旦bshowmodel就发送一个消息给a,此时a丢弃掉所有键盘消息和鼠标消息,当b的模式窗体关闭后再给a发送消息,此时a再响应所有消息
      

  11.   

    目前先暂时disable掉B程序中的相关功能按钮,先把效果做出来。到于此时的A程序,还是要允许点击。因为A程序主界面中共有六个子系统按钮,以运行不同的子系统并融合到A程序的pagecontrol上来。A程序中的按钮点击后,如果没有运行,则运行,否则,切换到所对应的TabSheet.
      

  12.   

    目前先暂时disable掉B程序中的相关功能按钮,先把效果做出来。到于此时的A程序,还是要允许点击。因为A程序主界面中共有六个子系统按钮,以运行不同的子系统并融合到A程序的pagecontrol上来。A程序中的按钮点击后,如果没有运行,则运行,否则,切换到所对应的TabSheet
    *********************************************************
      

  13.   

    SendMessage form1.hWnd, WM_NCACTIVATE, true/false, 0
      

  14.   

    A.exe 与B.exe 该用COM控制行不?
      

  15.   

    SendMessage form1.hWnd, WM_NCACTIVATE, true/false, 0
    这种方法只能改变激活或者非激活的状态吧,但是还是不能阻止a form上的按钮点击还是用发送消息好些,想了想 不用禁用键盘和鼠标消息,直接修改form.enable属性就行了
    a.exe运行b.exe b showmodel时给a发一个消息m1,重载a 的wndproc,接到消息后a form.enable=false
    b 关闭模式窗体同样发送消息m2 ,a收到m2 form.enable=true,
      

  16.   

    做过几种融合,有兴趣、有时间的话,可以一起探讨:(以主窗体pageControl为融合对象)1、一般EXE程序中表单融合
    2、DLL中表单的融合
    3、BPL表单的融合4、目前正在偿试EXE之间的融合。
    仅个人兴趣。
      

  17.   


    谢谢,我就是这样操作的,只不过我只是把B程序有些功能按钮disable,但A程序是允许,因为还会运行其他程序。
      

  18.   

    在codeproject上可以找到NDde的项目,一个开源的进程间通信的类库,挺好用的。