一說到修改
delphi 原始碼或者訪問物件的私有成員函式,很多人馬上可以說出種種危害來否定我。這種做法我也提倡,但是有時候如果可以靈活運用,可以解決由於 delphi 因為封裝不正確而帶來的問題。我在這裡分享一些技巧: 1.
訪問私有成員變數
如果是 protected 的變數,可以用如下方法訪問:
type
tsomeclassaccess =class(tsomeclass);
begin
tsomeclassaccess(object1).protected_bool := false;
tsomeclassaccess(object1).protected_int := 0;
...end;
如果是private 的變數,那麼就要當心了。因為涉及到偏移量。還要考慮不同 delphi 版本的控制項的內部成員可能也有變化。最簡單的例子是:訪問 tmenuitem 的第二個內部成員變數 fhandle
type
thackmenuitem =class(tcomponent)
protected
//<-- change to protected
f***xcaption: ansistring;
fhandle: hmenu;
//<-- the property you want to access
end;
begin
thackmenuitem(amenuitem).fhandle := 0;
...end;
2.訪問私有成員函式
這個目前普遍的做法是偷梁換柱。就是把自己的函式位址替換成待修改函式的記憶體位址。不過其中涉及到了記憶體修改、位址偏移量……,具體做法可以參考 tntcontrols 中 tntsystem.pas 安裝系統補丁,或者是 fastcode 控制項包。當然這個替換是會出現***的:例如 aqtime 就無法測試安裝過 tntsystem 補丁的程式。
3.直接修改**的實現
如果是執行庫中的具體實現要修改,可以直接動原始碼,因為改動是implementation 的部分,不會影響到其它的呼叫該單元的部分。(注意:inte***ce 和 implementation 的內容不能直接修改,否則無法編譯通過。)修改之後,勾選編譯選項裡面的 „use debug dcus「,並編譯程式,再將編譯得到的 dcu 檔案儲存到編譯目錄下面。我一般建立2個目錄:patchedvcls 和 precompiled 放修改過的原始碼,和編譯之後的版本。然後把這個2個目錄定義到環境變數裡面,這樣只要在每個專案的路徑設定中新增這些變數,就可以使用改動過的**了。
4.間接修改**的實現
如果要在修改定義部分怎麼辦?方法3是肯定行不通了。因為所有引用到這個單元的單元也需要重新編譯,但不是所有 delphi 原始碼你都可以重新編譯的。這種情況就傷腦筋了。我目前只可以修改很小一部分的。基本思路是在自己的程式裡面定義需訪問物件的擴充套件類和具體實現。然後釋放原先物件例項,並以新擴充套件類重新建立例項。請參考
打入訊息迴圈的另類方法
。
總結:
以上四種方法是我在修改 delphi 庫或者第三方控制項時候所用到的。在修改原始碼的時候,盡量要考慮到**的移植性。要做到最少量的修改,得到最好的效果。並且需要考慮修改的**是否可以在不 同的 delphi 版本中使用。我在實際專案中,修改了6、7個原始碼。(有時間的話,我會一一列出,有需要的可以問我索取。)同時也歡迎交流更多的修改方法,以及 delphi 不正確封裝的補丁。
題外話:
剛剛來自 codegear 的訊息,delphi 下個版本會引入了新的技術,直接修改宣告部分的**將變的可能
。
如何訪問私有成員
如何訪問私有成員 class plane 公有屬性 captain 馬軍強 私有屬性 air sister 20個 公有繫結方法 def fly self print 飛機會飛 公有普通方法 def fly2 print 飛機會飛2 私有的繫結方法 def oil info self print 飛...
成員函式訪問物件私有成員
在類的定義過程中,成員函式可以訪問傳遞過來的 同類物件 的所有成員 可以訪問私有成員 可以這樣理解 類是在編譯階段就存在的概念,物件是在執行階段才存在的。c 的私有判斷是在編譯時間決定的,因此c 的私有只能是基於類的,不是基於物件的。封裝是編譯期的概念,是針對型別而非物件的,在類的成員函式中可以訪問...
C 怎樣訪問私有成員函式
我知道的大概是三種方法 通過位址進行訪問 通過友元函式 通過友元類 第二種和第三種是比較常見的做法,第一種可能不太常見 這種方法能夠使用只要是因為類的儲存機制,類內只有成員變數和虛函式,所以可以利用位址來進行訪問。即通過a a int a 來實現 includeusing namespace std...