線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:2272
推到 Plurk!
推到 Facebook!

(Delphi -> BCB) Constructor Loaded CreateParams 執行順序不一樣

答題得分者是:aftcast
mike_wws
一般會員


發表:3
回覆:10
積分:2
註冊:2011-06-02

發送簡訊給我
#1 引用回覆 回覆 發表時間:2013-07-20 17:15:01 IP:124.205.xxx.xxx 訂閱
這個問題困擾我很久,不知道是不是BCB的Bug.

今天想把以下Delphi code 轉成BCB

unit ChildFrm;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls, ExtCtrls, Menus;
type
TChildForm = class(TForm)
private
FAsChild: Boolean;
FTempParent: TWinControl;
protected
procedure CreateParams(var Params: TCreateParams); override;
procedure Loaded; override;
public
constructor Create(AOwner: TComponent); overload; override;
constructor Create(AOwner: TComponent; AParent: TWinControl); reintroduce; overload;
// The method below must be overriden to return either the main menu
// of the form, or nil.
function GetFormMenu: TMainMenu; virtual; abstract;
function CanChange: Boolean; virtual;
end;
var
ChildForm: TChildForm;
implementation
{$R *.DFM}
constructor TChildForm.Create(AOwner: TComponent);
begin
FAsChild := False;
inherited Create(AOwner);
end;
constructor TChildForm.Create(AOwner: TComponent; AParent: TWinControl);
begin
FAsChild := True;
FTempParent := aParent;
inherited Create(AOwner);
end;
procedure TChildForm.Loaded;
begin
inherited;
if FAsChild then
begin
align := alClient;
BorderStyle := bsNone;
BorderIcons := [];
Parent := FTempParent;
Position := poDefault;
end;
end;
procedure TChildForm.CreateParams(var Params: TCreateParams);
Begin
Inherited CreateParams(Params);
if FAsChild then
Params.Style := Params.Style or WS_CHILD;
end;
function TChildForm.CanChange: Boolean;
begin
Result := True;
end;
end.

轉成BCB如下:
//---------------------------------------------------------------------------
#include
#pragma hdrstop
#include "ChildFrm.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TChildForm *ChildForm;
//---------------------------------------------------------------------------
__fastcall TChildForm::TChildForm(TComponent* Owner)
: TForm(Owner)
{
FAsChild = false;
}
__fastcall TChildForm::TChildForm(TComponent* Owner,TWinControl* AParent)
: TForm(Owner)
{
FAsChild = true;
FTempParent = Parent;
}
void __fastcall TChildForm::Loaded(void)
{
TBorderIcons tempBI;
inherited::Loaded();
if (FAsChild)
{
Align = alNone;
BorderStyle = bsSizeable;
// BorderIcons = BorderIcons - [biMaximize] -[biMinimize];
tempBI >> biMaximize;
tempBI >> biMinimize;
BorderIcons = tempBI;
Parent = FTempParent;
Position = poDefault;
}
}
void __fastcall TChildForm::CreateParams(TCreateParams &Params)
{
inherited::CreateParams(Params);
if (FAsChild)
Params.Style|=WS_CHILD;
//Params.Style := Params.Style or WS_CHILD;
}
bool TChildForm::CanChange(void)
{
return true;
}

進行test 在BCB 去new 一個ChildForm 如下
/---------------------------------------------------------------------------
void __fastcall TMainForm::btnChildClick(TObject *Sender)
{
TChildForm *FChildForm;
//if (FNewChildForm == NULL)
{
FChildForm = new TChildForm(Application,pnlParent);
//UpdateWindow(FNewChildForm->Handle);
FChildForm->Show();
pnlParent->Height = pnlParent->Height-1;
}
}

BCB 執行順序是
1.CreateParams -> 2.Loaded -> 3.Constructor 這樣結果會和Delphi 不同.
Delphi 執行順序是
1.Constructor ->2.CreateParams -> 3.Loaded

捷克這是太神奇了,我想針對BCB TForm Default Constructor 的 Overloaded 一定有BUG

請高手解答一下,針對這個問題,我一度想放棄BCB,因為這個如果是BUG ,就太誇張了.

希望是我自己Something wrong.

編輯記錄
mike_wws 重新編輯於 2013-07-21 09:11:35, 註解 無‧
aftcast
站務副站長


發表:81
回覆:1482
積分:1762
註冊:2002-11-21

發送簡訊給我
#2 引用回覆 回覆 發表時間:2013-07-20 23:04:41 IP:114.44.xxx.xxx 訂閱

你好,

我剛以bcb6試的結果,是1.Constructor ->2.CreateParams -> 3.Loaded ,並非你說的那種情形。
難道你的版本不同?

===================引 用 mike_wws 文 章===================

BCB 執行順序是
1.CreateParams -> 2.Loaded -> 3.Constructor 這樣結果會和Delphi 不同.
Delphi 執行順序是
1.Constructor ->2.CreateParams -> 3.Loaded

捷克這是太神奇了,我想針對BCB TForm Default Constructor 的 Overloaded 一定有BUG

請高手解答一下,針對這個問題,我一度想放棄BCB,因為這個如果是BUG ,就太誇張了.

希望是我自己Something wrong.

------



蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
aftcast
站務副站長


發表:81
回覆:1482
積分:1762
註冊:2002-11-21

發送簡訊給我
#3 引用回覆 回覆 發表時間:2013-07-20 23:14:06 IP:114.44.xxx.xxx 訂閱
剛用 xe3,一樣也是
1.Constructor ->2.CreateParams -> 3.Loaded

並非你說的情形。是否有可能是別的程式碼造成?

我把child裡的每個函式都下中斷,然後在 main button click中的 FChildForm->Show(); 下中斷。然後安下button,就會發現是 1 2 3 的順序。

或是你上傳程式碼上來看一下呢?

===================引 用 aftcast 文 章===================

你好,

我剛以bcb6試的結果,是1.Constructor ->2.CreateParams -> 3.Loaded ,並非你說的那種情形。
難道你的版本不同?

------



蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
mike_wws
一般會員


發表:3
回覆:10
積分:2
註冊:2011-06-02

發送簡訊給我
#4 引用回覆 回覆 發表時間:2013-07-21 10:29:06 IP:124.205.xxx.xxx 訂閱
 非常感謝,我是用BCB6,以下是BCB的檔案.
https://docs.google.com/file/d/0B7_1w8hA0XHuNjVMTktQOEJRY00/edit?usp=sharing
編輯記錄
mike_wws 重新編輯於 2013-07-21 11:27:08, 註解 無‧
aftcast
站務副站長


發表:81
回覆:1482
積分:1762
註冊:2002-11-21

發送簡訊給我
#5 引用回覆 回覆 發表時間:2013-07-21 18:15:00 IP:114.44.xxx.xxx 訂閱
你好,下載後發現還是一樣,我附上圖給你看。

或者我有誤會到你的意思?…



===================引 用 mike_wws 文 章===================
非常感謝,我是用BCB6,以下是BCB的檔案.
https://docs.google.com/file/d/0B7_1w8hA0XHuNjVMTktQOEJRY00/edit?usp=sharing
------



蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
mike_wws
一般會員


發表:3
回覆:10
積分:2
註冊:2011-06-02

發送簡訊給我
#6 引用回覆 回覆 發表時間:2013-07-21 19:17:06 IP:198.148.xxx.xxx 訂閱
P1
https://docs.google.com/file/d/0B7_1w8hA0XHueTlKT1JWNVRnWVE/edit?usp=sharing

請看上圖,我只是單純的程式斷點,如果先到Constructor --> FAsChild = true; 那麼到了Loaded 和

CreateParams memeber function 之後就會執行if(FAsChild) 之後的程序.

在Delphi 7 會先到Constructor 所以FAsChild = true ,但BCB6 不會先到Constructor (這很不合理)

所以FAsChild = false





編輯記錄
mike_wws 重新編輯於 2013-07-21 19:57:19, 註解 無‧
aftcast
站務副站長


發表:81
回覆:1482
積分:1762
註冊:2002-11-21

發送簡訊給我
#7 引用回覆 回覆 發表時間:2013-07-21 22:40:24 IP:114.44.xxx.xxx 訂閱
嗯,我終於了解你說的事什麼。

1/ 這不是bug

2/ 其實問題的根源不是你說的"這種"順序不同。而是「另一種」順序不同! 哪一種呢? 就是 delphi 這個語言的物件導向實作與 c 有一個很大的不同 : 「c 在建構時是由父再子 ; delphi 是由子再父」。這個問題是少數人關注的事。我曾在唸bcb 英文help檔( c language support for vcl 裡面的 Object construction for C Builder VCL/CLX classes)時見到這個議題,你可以查一下! 注意那頁右邊的圖。

3/ 因此,
__fastcall TChildForm::TChildForm(TComponent* Owner,TWinControl* AParent)
: TForm(Owner) {

FAsChild = true; // 這行要等TForm建構完才會被叫

}

時,TForm這個建構先被叫,於是就進入了你的override 的 CreateParams與loadded,至此,你順序一如我一開始講的,是對的! 只是FAsChild = true; 還來不及被叫啦!

相反的,delphi的做法是 : 1 先叫 FAsChild = true; (因這是子的東西),然後才叫TForm來建構(父),接著因你override,所以一樣也是CreateParams->loadded。


結論: 你所謂的順序無論是bcb或是delphi都是一樣的。 造成你覺得不一樣的原由根源其實是 建構父類別的順序不同!!

額外一提,若就你的程式來看… 我覺得你這樣的物件設計算比較不佳,理當一個類別就是一種行為,不要用FAsChild 來變種,我的意思是,是child類別就應該一直是child,比如說FAsChild == 假的時候,你希望長像不一樣? 那就再創一個叫 NonChildForm的類別,然後在創物件時,用if 來決定是要 new childform 或是 nonChildForm。 以上是個人以物件導向設計較佳的觀點來看。當然,你的這個程式也因為用了override的東西,加上vcl 本來根子就是delphi,所以會更加加深你這樣的寫法極困擾!


以上,希望能有幫助到!


蕭沖


===================引 用 mike_wws 文 章===================
P1
https://docs.google.com/file/d/0B7_1w8hA0XHueTlKT1JWNVRnWVE/edit?usp=sharing

請看上圖,我只是單純的程式斷點,如果先到Constructor --> FAsChild = true; 那麼到了Loaded 和

CreateParams memeber function 之後就會執行if(FAsChild) 之後的程序.

在Delphi 7 會先到Constructor 所以FAsChild = true ,但BCB6 不會先到Constructor (這很不合理)

所以FAsChild = false





------



蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
mike_wws
一般會員


發表:3
回覆:10
積分:2
註冊:2011-06-02

發送簡訊給我
#8 引用回覆 回覆 發表時間:2013-07-22 10:28:55 IP:124.205.xxx.xxx 訂閱
 非常感謝你的解釋和建議,真是一語道破
系統時間:2017-10-22 18:05:06
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!