2017-05-09 60 views
3

有一個TFrame子類,如下所示:覆蓋的setEnabled與處理信息CM_ENABLEDCHANGED

TCustomHistoryFrame = class(TFrame) 
    tbMainFunction: TToolBar; 
    // there's more, of course, but that is irrelevant to the question 
end; 

我注意到,當我把這個框架的Enabled財產False,其組成tbMainFunction不會得到(視覺)已禁用。

我的第一個想法是重寫虛方法TControl.SetEnabled。看看它的實現,我發現當實際值不同時,它會執行控制消息CM_ENABLEDCHANGED

我不知道如何在框架的Enabled狀態應用於該工具欄的正確途徑。
會是什麼做的常見方式?由於這個問題主要是基於意見的,請讓我重新修改它:

對於覆蓋SetEnabled或處理CM_ENABLEDCHANGED有什麼優缺點?


的事情,我認爲自己的:

  • 覆蓋SetEnabled
    • 我將不得不重新檢查,新值是否與舊值不同。這將是一個冗餘。 (這對性能沒有顯著影響,但 - 叫我的頭髮分路器 - 氣味給我。)
  • 處理CM_ENABLEDCHANGED
    • 如何維持遺傳代碼此消息?有此消息(至少)在TControlTWinControl實現。如果我在我的課TCustomHistoryFrame中處理消息,他們仍會被執行嗎?
+2

是否幀具有一個窗口句柄?還是隻是將其控件注入其父項?在這種情況下,您可能會將整個區域包裝在面板中並禁用該區域。 –

+1

@DavidHeffernan我不太清楚,我是否理解正確。每個'TWinControl'後裔(如'TFrame')獲取'TWinControl.CreateWindowHandle'窗口句柄。另一方面,框架當然是一種可視化組件包裝。如果我把所有東西(特別是'tbMainFunction')放在'TPanel'上,那麼我是不是有同樣的問題來禁用它? –

+0

我不確定'TFrame'是否被窗口化了。 –

回答

5

處理CM_ENABLEDCHANGED是正確的解決方案。這種消息特別設計用於允許後代類對基類中聲明的屬性的更改作出反應。

例如:

TCustomHistoryFrame = class(TFrame) 
    tbMainFunction: TToolBar; 
private 
    procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED; 
end; 

procedure TCustomHistoryFrame.CMEnabledChanged(var Message: TMessage); 
begin 
    inherited; 
    tbMainFunction.Enabled := Enabled; 
end; 

或者:

TCustomHistoryFrame = class(TFrame) 
    tbMainFunction: TToolBar; 
protected 
    procedure WndProc(var Message: TMessage); override; 
end; 

procedure TCustomHistoryFrame.WndProc(var Message: TMessage); 
begin 
    inherited; 
    if Message.Msg = CM_ENABLEDCHANGED then 
    tbMainFunction.Enabled := Enabled; 
end; 
+0

在第一個例子中,繼承的'CMEnabledChanged'會被執行,儘管它在基類中是私有的嗎?明天我會試一試。特別是爲了暗示VMT污染。我們應儘可能避免污染。 –

+1

在第一個示例中,無論基礎處理程序的可見性如何,都會執行基礎處理程序。 –

+1

爲什麼污染DMT比污染VMT好? –