如题。
试用了CloseWindow函数,结果是最小化;SendMessage函数发送WM_Close,没反应,返回值等于0;DestroyWindow,倒是实现了窗体关闭(其实我知道是销毁窗体),但是再次加载是无效的。
可是我的目标是:API代码实现窗体卸载;之后还可以通过Load方法加载的。
怎么实现呢??
另外,工程1中可不可以捕获工程2中某窗体是否已卸载或者正在卸载的消息(工程1中已知工程2中窗体的句柄)?然后可以实现下一步的功能。

解决方案 »

  1.   

    补充一下:可能有朋友看了不免会想,直接Unload 某窗体不就完了!
    呵呵,是我没说清楚。
    是这样的:工程1中调用另外一个Active Dll工程。在工程1中点击某按钮1则显示Dll类中的窗体Form1。现在要求在工程1中点击另外一个按钮2则将Form1卸载;如果再点击按钮1则又显示Form1窗体。
      

  2.   

    搞什么API这么复杂。
    在DLL中加入公共方法,此公共方法执行SHOW和UNLOAD FORM的动作。
      

  3.   

    呵呵,呵呵呵呵,这个问题么,有点捣怪,我是指问题,楼主代码测试通过20分可不够啊。在工程1中卸载,用如下代码(某按钮2_click事件):
    DestroyWindow ActiveDllFrmHwnd   '用句柄卸载,尊重你的原文.
    在工程1中重新加载时,首先用的不是Load方法;在工程1中重新加载的代码(某按钮1_click事件):
    Unload ActiveDllFrm  '在原来的工程里,将其在VB运行环境中销毁(关键哦,关键哦,你就缺这么一行)
    ActiveDllFrm.Show    '重新加载之
    '上面两行用对象,这里你用的名称可能是Form1,别奇怪,确实不是我打错了,是Unload ,不是Load,测试代码吧.这里呢,给你一个建议,就是你最开始加载和现在加载用的代码一个是LOAD,一个是UNLOAD,会混的,可以用ActiveDllFrm.HWND=0来判断。
    也就是把上面改成:
    if ActiveDllFrm.hwnd=0 then Unload ActiveDllFrm  '在原来的工程里,将其在VB运行环境中销毁(关键哦,关键哦,你就缺这么一行)
    ActiveDllFrm.Show    '重新加载之先谢过楼主的分。嘿嘿。
      

  4.   

    重新考虑了一下我是在同一个工程里测试的按楼主所说,如果楼主不能修改那个ACTIVEDLL那就麻烦。。上面参考的代码里用到了UNLOAD方法,应该加到ACTIVEDLL的加载代码中,直接用在点击事件里似乎不行。。提供我测试时的代码,两个FRM名称默认,FORM1中两个CMDBOX,名称默认,Private Declare Function DestroyWindow Lib "user32" (ByVal hwnd As Long) As LongPrivate Sub Command1_Click()
    Destroy
    End SubPrivate Sub Destroy()
        DestroyWindow form2.hwnd
    End SubPrivate Sub UnDestroy()
    Me.Caption = form2.hwnd
        'load the window
        Unload form2
        'show the window
        form2.Show
    End SubPrivate Sub Command2_Click()
    UnDestroy
    End SubPrivate Sub Form_Load()
    form2.Show
    End Sub
      

  5.   

    总之呢,我的思路就是DestroyWindow函数卸载以后,VB仍然认为窗体存在,状态也没变,你得想办法让VB知道窗体已经没了。这样它才会给你重新加载的。
      

  6.   

    有个新想法,看了看楼主用SENDMESSAGE,为什么不能成功呢,如果用它投递消息成功了,那么VB可以知道窗体的变化,就可以正常加载了,给出用这个函数销毁窗体的代码
    Public Const WM_SYSCOMMAND = &H112
    Public Const SC_CLOSE = &HF060& '注释:关闭窗体,这里用的不是WM_CLOSE可能楼主是这里搞错了.
    SendMessage form2.hwnd, WM_SYSCOMMAND, SC_CLOSE, ByVal 0& '注释:关闭窗体
    这就可以关闭了,byval 0& 可以换成vbnullstring。
    然后楼主用什么方法加载的窗体可以再用什么方法加载就行了,加载部分代码不用变:
    “在工程1中点击某按钮1则显示Dll类中的窗体Form1”
      

  7.   

    yechat(点尘不惊) :
    你换了个思路,这是我当初想到的。不过还是谢谢你!
    zcsor():
    你的方法很好!!佩服佩服!解决了我的疑惑。
    现在还有一问题请教:
    在工程1中点击某按钮1则将ActiveDLL中Form1显示于工程1中窗体的Picture1中;即设置ActiveDLL中Form1的Parent为工程1中窗体的Picture1。此时我还想通过工程1中点击某按钮3,实现Picture1中的ActiveDLL-〉Form1铺满整个Picture1。其中是已知ActiveDLL-〉Form1的窗口句柄的,假设为frmHwnd。我是这样做的:Declare Function MoveWindow Lib "user32" (ByVal hwnd As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal bRepaint As Long) As LongPrivate Sub Command3_Click()
        MoveWindow frmHwnd, 0, 0, Picture1.ScaleWidth, Picture1.ScaleHeight, ByVal 1&
    End Sub结果ActiveDLL-〉Form1是移到Picture1内的左上角了,但大小却变得和Picture1所在的主窗体一般大小。莫名其妙的,这是为何?
    zcsor():来吧!
    高手,来吧!
    我会再加分的!!!!
    不会食言的!
      

  8.   

    在工程1中点击某按钮1则将ActiveDLL中Form1显示于工程1中窗体的Picture1中;即设置ActiveDLL中Form1的Parent为工程1中窗体的Picture1这里是说,你把FRM1捕获到了PIC1中,还是FRM本身就是PIC1呢按你后来的说法,应该是把PIC1作为FRM1的父窗体了。。从你的叙述可以看出,以下代码中,前3个参数是正确的,句柄,起位X,起位Y,错误出现在第4、5两个参数,这两个是用来改变大小的,你要知道,在VB中使用的量度和系统有所不同,API中一般都使用的是象素,而VB中这是需要定义的,一般来说,可以通过ScaleMode来设置。你可以参照MSDN中“ScaleHeight、ScaleWidth 属性”一节,以及“ScaleMode 属性一节。
    MoveWindow frmHwnd, 0, 0, Picture1.ScaleWidth, Picture1.ScaleHeight, ByVal 1&
    是否在调用上述语句时将ScaleMode设置为VbPixels呢。当然,如果是我用你的方法,我会比较笨,将ScaleMode设置为VbPixels或者/14转换为象素,而使用Picture1的Height和Width两种属性。
      

  9.   

    多谢zcsor()兄!
    以后还请多多指教!
    。共同提高!!
      

  10.   

    看来你的问题是解决了。。睡了一会,忘记了一个细节,突然想起来了。你的FRM1显示到PIC1里了吗。。怎么觉得你的叙述好象没有。用指定新父的办法就可以了。
    如果我写你的代码可能这么写
    FRM1.HEIGHT=PIC1.HEIGHT/14 +1 
    FRM1.WIGHT-PIC1.WIGHT/14 +1
    FRM1.LEFT=-1 
    FRM1.TOP=-1
    SetParent FRM1.HWND PIC1.HWND
    这样把FRM1放到PIC1里的时候,就基本正好了
    不知道你能看见不了。。
    看家回下
      

  11.   

    zcsor()兄继续和我探讨,我真是很感动!
    我以上陈述中所涉及到的几个对象之间的关系如下:
    工程1下:主窗口Form1。该窗口中有3个按钮,即Command1,Command2,Command3。还有一PictureBox:Picture1。
    ActiveDLL下:窗口Form1,以及类中的公共方法ShowForm1(lngParentHwnd As Long)。ShowForm1()方法加载窗口Form1并且为其指定已知句柄的新父。在工程1的主窗口Form1中点击Command1,调用ActiveDLL的ShowForm1()方法,并在Picture1中显示ActiveDLL的Form1;点击Command2,则使用SendMessage使Picture1中的Form1关闭;点击Command3,则使用MoveWindow 使Picture1中的Form1充满整个Picture1。呵呵,见笑!zcsor()兄,多谢你的关心、支持!
      

  12.   

    倒,说的太客气了呵呵,不知道你的代码是不是真的写COMMAND1,COMMAND2,FORM1,这样容易混,我经常混得重新lvlv,哈哈。。还是用有代表性的名称吧,我E文没学回,没办法,学的鹅文,所以经常用拼音。。去定义名称,偶尔也用E文,毕竟学了N多年编程了,也会一些建议你还是用有代表性的名称例如COMMAND1改成CmdShowFrm,只是举个例子