(Delphi -> BCB) Constructor Loaded CreateParams 執行順序不一樣 |
答題得分者是:aftcast
|
mike_wws
一般會員 發表:3 回覆:10 積分:2 註冊:2011-06-02 發送簡訊給我 |
這個問題困擾我很久,不知道是不是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 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
你好, 我剛以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 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
剛用 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 發送簡訊給我 |
|
aftcast
站務副站長 發表:81 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
你好,下載後發現還是一樣,我附上圖給你看。
或者我有誤會到你的意思?… ===================引 用 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 發送簡訊給我 |
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 回覆:1485 積分:1763 註冊:2002-11-21 發送簡訊給我 |
嗯,我終於了解你說的事什麼。
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 文 章=================== 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 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |