2009-07-04 128 views
5

我該如何讓我的代碼工作? :)我試圖制定這個問題,但經過幾次失敗的嘗試後,我認爲你們會發現問題的速度比閱讀我的'解釋'更快。謝謝。使用他的類類型轉換TObject?

setCtrlState([ memo1, edit1, button1], False); 

_

procedure setCtrlState(objs: array of TObject; bState: boolean = True); 
var 
    obj: TObject; 
    ct: TClass; 
begin 
    for obj in objs do 
    begin 
    ct := obj.ClassType; 


    if (ct = TMemo) or (ct = TEdit) then 
     ct(obj).ReadOnly := not bState;  // error here :(

    if ct = TButton then 
     ct(obj).Enabled:= bState;  // and here :(

    end; 
end; 

回答

5

這將是更容易使用RTTI,而不是明確的鑄造,即:

uses 
    TypInfo; 

setCtrlState([ memo1, edit1, button1], False); 

procedure setCtrlState(objs: array of TObject; bState: boolean = True); 
var 
    obj: TObject; 
    PropInfo: PPropInfo; 
begin 
    for obj in objs do 
    begin 
    PropInfo := GetPropInfo(obj, 'ReadOnly'); 
    if PropInfo <> nil then SetOrdProp(obj, PropInfo, not bState); 

    PropInfo := GetPropInfo(obj, 'Enabled'); 
    if PropInfo <> nil then SetOrdProp(obj, PropInfo, bState); 
    end; 
end; 
4

您需要CT目標轉換爲TMemo/TEDIT/TButton的前可以設置對象的屬性。

你得到錯誤的行是錯誤的,因爲ct仍然是TClass,而不是TButton/etc。如果你投擲到TButton,那麼你可以將啓用設置爲true。

我推薦閱讀casting in Delphi。就個人而言,我建議使用as/is操作符,而不是使用ClassType。在這種情況下,代碼會更簡單,而且更容易理解。


就個人而言,我會寫這更像是:

procedure setCtrlState(objs: array of TObject; bState: boolean = True); 
var 
    obj: TObject; 
begin 
    for obj in objs do 
    begin 
    // I believe these could be merged by using an ancestor of TMemo+TEdit (TControl?) 
    // but I don't have a good delphi reference handy 
    if (obj is TMemo) then 
     TMemo(obj).ReadOnly := not bState; 

    if (obj is TEdit) then 
     TEdit(obj).ReadOnly := not bState; 

    if (obj is TButton) then 
     TButton(obj).Enabled := bState; 
    end; 
end; 
7

你必須明確地轉換對象的一些類。 這應該工作:

procedure setCtrlState(objs: array of TObject; bState: boolean = True); 
var 
    obj: TObject; 
    ct: TClass; 
begin 
    for obj in objs do 
    begin 
    ct := obj.ClassType; 

    if ct = TMemo then 
     TMemo(obj).ReadOnly := not bState 
    else if ct = TEdit then 
     TEdit(obj).ReadOnly := not bState 
    else if ct = TButton then 
     TButton(obj).Enabled := bState; 
    end; 
end; 

這可以通過使用「is」運營商縮短 - 無需CT變量:

procedure setCtrlState(objs: array of TObject; bState: boolean = True); 
var 
    obj: TObject; 
begin 
    for obj in objs do 
    begin 
    if obj is TMemo then 
     TMemo(obj).ReadOnly := not bState 
    else if obj is TEdit then 
     TEdit(obj).ReadOnly := not bState 
    else if obj is TButton then 
     TButton(obj).Enabled := bState; 
    end; 
end; 
+0

不應該在每一種情況下第二類型轉換爲「TEDIT」,而不是「TMemo」? – Argalatyr 2009-07-04 23:21:04

+0

+0.5表示你必須對每種類型進行演員表演。 +0.5使用「是」 – 2009-07-04 23:23:19

3

沒有必要投給TMemo和TEDIT分開,因爲它們是從常見的父類兩個後代,具有隻讀屬性:

procedure TForm1.FormCreate(Sender: TObject); 

    procedure P(const Obj: TComponent); 
    begin 
    if Obj is TCustomEdit then 
     TCustomEdit(Obj).ReadOnly := True; 
    end; 

begin 
    P(Memo1); 
    P(Edit1); 
end; 
2

你能避免引用各單位,如果你明確的鑄造不要介意小的性能影響並限制對已發佈屬性的更改。查看Delphi附帶的TypInfo單元。