很简单的一个测试程序:
  一个工程里有两个form,都是自动创建,
  在主form上放一button,click事件中是这样写的 (主form中引用idglobal单元)  form2.show;
  debugoutput(format('%u',[form2.handle]));
  form2.Parent := self;
  debugoutput(format('%u',[form2.handle]));
  form2.Parent := nil;
  debugoutput(format('%u',[form2.handle]));
  form2.Parent := self;
  debugoutput(format('%u',[form2.handle]));在event窗口可以看到执行结果,debug输出的4个值均不相同。
为什么form2的句柄会改变??怎么才能不让它变?
我印象中form创建后,handle不应该变的呀,请高手解释
测试环境: delphi6 + upd1 + upd2   windows xp sp1 / windows 2000 pro sp4

解决方案 »

  1.   

    你更改了Parent属性了哦。。应该是窗口销毁后重新创建了一个
      

  2.   

    var
      from:tfrom;
    begin
      from:=tfrom.create(self);
      from.parent:=self;
      from.caption:='自动创建';
      from.width:=300;
      from.hight:=200;
      from.show;
    end;
      

  3.   

    动态创建的form的句柄是OS动态的分配给form的,你每次重新运行你的程序,你的主窗口的句柄是不一样的,不过在这里应该是更改了其parent后,才发生变化的,
      

  4.   

    procedure TCustomForm.SetParent(AParent: TWinControl);
    begin
      if (Parent <> AParent) and (AParent <> Self) then
      begin
        if Parent = nil then DestroyHandle;//DestroyHandle;
        inherited SetParent(AParent);
        if Parent = nil then UpdateControlState;
      end;
    end;更改了其parent后,会重新创建窗体
    procedure TWinControl.DestroyHandle;
    var
      I: Integer;
    begin
      if FHandle <> 0 then
      begin
        if FWinControls <> nil then
          for I := 0 to FWinControls.Count - 1 do
            TWinControl(FWinControls[I]).DestroyHandle;
        DestroyWnd;//这里
      end;
    end;很明显
      

  5.   

    使用调试dcu再debug进去就明白了
      

  6.   

    请DeadWolf讲得明白些,我跟到了Controls里面,也没有搞清楚是在哪一点改的Handle
      

  7.   

    procedure TCustomForm.SetParent(AParent: TWinControl);
    begin
      if (Parent <> AParent) and (AParent <> Self) then
      begin
        if Parent = nil then DestroyHandle;//这里最终会进到TWinControl.DestroyWindowHandle;
        inherited SetParent(AParent);
        if Parent = nil then UpdateControlState;
      end;
    end;procedure TWinControl.DestroyWindowHandle;
    begin
      Include(FControlState, csDestroyingHandle);
      try
        if not Windows.DestroyWindow(FHandle) then
          RaiseLastOSError;
      finally
        Exclude(FControlState, csDestroyingHandle);
      end;
      FHandle := 0;//更改句柄
    end;
      

  8.   

    哦 是喔  内部 搞鬼。。你Ctrl + left mouse 到 DestroyHandle 一路追踪。procedure TWinControl.DestroyWindowHandle;
    begin
      Include(FControlState, csDestroyingHandle);
      try
        if not Windows.DestroyWindow(FHandle) then
          RaiseLastOSError;
      finally
        Exclude(FControlState, csDestroyingHandle);
      end;
      FHandle := 0;
    end;
      

  9.   

    怎么办,就这么办
    重新创建form2,
    你的那种改变form的父亲的思路是要不得的
      

  10.   

    d7 + win2kserver sp4
    是变的。我测试了如下代码procedure TForm1.Button1Click(Sender: TObject);
    begin
      Memo1.Clear ;
      form2.Show ;1:  Memo1.Lines.Add(format('%u  %u', [form2.Handle, FindWindow('TForm2', 'Form2')]));  form2.Parent := Self ;
      //Sleep(5000) ;
    2:  Memo1.Lines.Add(format('%u  %u', [form2.Handle, FindWindow('TForm2', 'Form2')]));  form2.Parent := nil ;
      //Sleep(5000) ;
    3:  Memo1.Lines.Add(format('%u  %u', [form2.Handle, FindWindow('TForm2', 'Form2')]));  form2.Parent := Self ;
      //Sleep(5000) ;
    4:  Memo1.Lines.Add(format('%u  %u', [form2.Handle, FindWindow('TForm2', 'Form2')]));
    f9 运行程序,结果如下:       form2.handle        findwindow     parent
    1:      2688084              2688084       Application
    2:      2753620              2950424       form1
    3:      2819156              2819156       nil
    4:      2884692              2950424       form1    
      
    从上面的数据可以看到:
    1,3 中,form2.handle = findwindow ;
    1,2,3,4中 ,form2.handle 各不相同;
    2,4中,findwindow 相同;
    关闭 form2,再次执行上面的代码,结果是:
        form2.handle    findwindow      parent          d
    1:  1770722           2950424      Application
    2: 1770722           2950424      form1
    3: 1836258           1836258       nil
    4: 1901794           2950424       form1从结果看:
    3中  form2.handle = findwindow
    1,2中,form2.handle 和 findwindow 分别对应相等;
    2,4中, findwindow 对应相等;
    再次运行的结果和第二此的结果类似,只是具体数值不同而已。
      

  11.   

    to trainbox:    什么叫作改变form的parent的思路是要不得的?既然它有parent这个属性,又是可写的,为什么不能改?有什么道理请仔细讲来听听,多谢!如果不是偶尔在改变了parent之后用到了Handle属性,我也不会发现有这个问题,以前也没有听谁问起过这事。我倒是认为这是delphi自身的问题。窗口创建了,handle应该成为唯一标识的东东,为什么要改变呢?我问了用VC的朋友,都说不可能会变的,不知道borland怎么想的。
      

  12.   

    不仅如此,如果form1.parent = form2
    当改变form2的BoardStyle时,form1的Handle也会变
    真的很不爽,delphi为什么会这样做
    哪位高人给个理由先
      

  13.   

    还没想过为什么,呵呵,一直傻乎乎的跟着delphi走