控制代碼的本質

2021-09-01 16:33:18 字數 3888 閱讀 1214

一、書上定義:

<>(microsoft press,by richard wilton)

在windows環境中,控制代碼是用來標識專案的,這些專案包括:模組(module)、任務(task)、例項 (instance)、檔案(file)、記憶體塊(block of memory)、選單(menu)、控制(control)、字型(font)、資源(resource),包括圖示(icon),游標 (cursor),字串(string)等、gdi物件(gdi object),包括位圖(bitmap),畫刷(brush),元檔案(metafile),調色盤(palette),畫筆(pen),區域 (region),以及裝置描述表(device context)。 

<

控制代碼是wondows用來標識被應用程式所建立或使用的物件的唯一整數,windows使用各種各樣的控制代碼標識諸如應用程式例項,視窗,控制,位圖,gdi物件等等。windows控制代碼有點象c語言中的檔案控制代碼。 

二、mfc源**:

#ifdef strict

typedef void *handle;

#define declare_handle(name) struct name##__ ; typedef struct name##__ *name

#else

typedef pvoid handle;

#define declare_handle(name) typedef handle name

#endif

declare_handle(hmodule); 

declare_handle(hinstance); 

declare_handle(hlocal); 

declare_handle(hglobal); 

declare_handle(hdc); 

declare_handle(hrgn); 

declare_handle(hwnd); 

declare_handle(hmenu); 

declare_handle(haccel); 

declare_handle(htask); 

三、理解:

handle就是pvoid,也就是無型別指標,

上面這些資源的控制代碼handles都不過是指向struct的指標,至於這個struct的用處,連m$都說unused了,現在解釋下m$這麼做的意義,這就是所謂資料封裝,你可以在你的程式中把m$的內部結構指標傳來傳去,可是你卻不知道它到底指向的內容是什麼。

控制代碼與指標確實是完全不同的兩個概念。控制代碼僅僅是乙個32位整數,win32中用於標記某個系統或程序的物件,可以理解為物件索引(由於m$未完全公開相關技術,在一定程度上只能如此理解),這個索引更像是一種對映關係(從控制代碼到物件指標的對映),而不是純粹意義上的「陣列下標」。 

控制代碼可以理解為用於指向或標識記憶體的一塊「資源」,這些資源如:檔案(file)、記憶體塊(block of memory)、選單(menu)等等。作業系統通過控制代碼來定位核心物件和系統資源。

指標即為指向記憶體的「資料或指令」某一單元。

說的確切一點,控制代碼實際上是一種指向某種資源的指標,但與指標又有所不同:指標對應著乙個資料在記憶體中的位址,得到了指標就可以自由地修改該資料。windows並不希望一般程式修改其內部資料結構,因為這樣太不安全。所以windows給每個使用globalalloc等函式宣告的記憶體區域指定乙個控制代碼(本質上仍是乙個指標,但不要直接操作它),平時你只是在呼叫api函式時利用這個控制代碼來說明要操作哪段記憶體。

四、引喻:

牧童遙指杏花村

牧童的手為指標,杏花村的牌子為控制代碼,杏花村酒店為物件的例項. 

附註:獲得視窗控制代碼三種方法

1.hwnd findwindow(lpctstr lpclassname, lpctstr lpwindowname) 

hwnd findwindowex(hwnd hwndparent, hwnd hwndchildafter,lpctstr lpclassname, lpctstr lpwindowname) 

2.hwnd windowfrompoint(point& point)//獲得當前滑鼠游標位置的視窗hwnd

3.bool callback enumchildproc(hwnd hwnd,lparam lparam)

bool callback enumchildwindows(hwnd hwndparent, wndenumproc lpenumfunc,lparam lparam)

bool callback enumwindows(wndenumproc lpenumfunc, lparam lparam)

bool callback enumwindowsproc(hwnd hwnd, lparam lparam)

從廣義上,能夠從乙個數值拎起一大堆資料的東西都可以叫做控制代碼。控制代碼的英文是"handle",本義就是"柄",只是在電腦科學中,被特別地翻譯成"控制代碼",其實還是個"柄"。從乙個小東西拎起一大堆東西,這難道不像是個"柄"嗎?

然後,指標其實也是一種"控制代碼",只是由於指標同時擁有更特殊的含義——實實在在地對應記憶體裡地乙個位址——所以,通常不把指標說成是"控制代碼"。但指標也有著能從乙個32位的值引用到一大堆資料的作用,這不是控制代碼又是什麼?

windows系統中有許多核心物件(這裡的物件不完全等價於"物件導向程式設計"一詞中的"物件",雖然實質上還真差不多),比如開啟的檔案,建立的執行緒,程式的視窗,等等。這些重要的物件肯定不是4個位元組或者8個位元組足以完全描述的,他們擁有大量的屬性。為了儲存這樣乙個"物件"的狀態,往往需要上百甚至上千位元組的記憶體空間,那麼怎麼在程式間或程式內部的子過程(函式)之間傳遞這些資料呢?拖著這成百上千的位元組拷貝來拷貝去嗎?顯然會浪費效率。那麼怎麼辦?當然傳遞這些物件的首位址是乙個辦法,但這至少有兩個缺點:

暴露了核心物件本身,使得程式(而不是作業系統核心)也可以任意地修改物件地內部狀態(首位址都知道了,還有什麼不能改的?),這顯然是作業系統核心所不允許的;

作業系統有定期整理記憶體的責任,如果一些記憶體整理過一次後,物件被搬走了怎麼辦?

所以,windows作業系統就採用進一步的間接:在程序的位址空間中設一張表,表裡頭專門儲存一些編號和由這個編號對應乙個位址,而由那個位址去引用實際的物件,這個編號跟那個位址在數值上沒有任何規律性的聯絡,純粹是個對映而已。

在windows系統中,這個編號就叫做"控制代碼"。

handle在windows中的含義很廣泛,以下關於談到的handle除非特別說明,將僅限於程序、執行緒的上下文中。

1、先來談談handle

handle本身是乙個32位的無符號整數,它用來代表乙個核心物件。它並不指向實際的核心物件,使用者模式下的程式永遠不可能獲得乙個核心物件的實際位址(一般情況下)。那麼handle的意義何在?它實際上是作為乙個索引在乙個表中查詢對應的核心物件的實際位址。那麼這個表在**呢?每個程序都有這樣的乙個表,叫控制代碼表。該錶的第一項就是程序自己的控制代碼,這也是為什麼你呼叫getcurrentprocess()總是返回0x7fffffff原因。

簡單地說,handle就是一種用來"間接"代表乙個核心物件的整數值。你可以在程式中使用handle來代表你想要操作的核心物件。這裡的核心物件包括:事件(event)、執行緒、程序、mutex等等。我們最常見的就是檔案控制代碼(file handle)。

另外要注意的是,handle僅在其所屬的程序中才有意義。將乙個程序擁有的handle傳給另乙個程序沒有任何意義,如果非要這麼做,則需要使用duplicatehandle(),在多個程序間傳遞handle是另外乙個話題了,與這裡要討論的無關。

2、程序id

首先,程序id是乙個32位無符號整數,每個程序都有這樣的乙個id,並且該id在系統範圍內是唯一的。系統使用該id來唯一確定乙個程序。

深入些說,系統可能使用程序id來計算代表該程序的核心物件的基位址(及eprocess結構的基位址),具體的計算公式你可以去問微軟的os開發人員。

3、hinstance

hinstance也是乙個32無符號整數,它表示程式載入到記憶體中的基位址。

控制代碼的本質

handle就是pvoid,也就是無型別指標,上面這些資源的控制代碼handles都不過是指向struct的指標,至於這個struct的用處,連m 都說unused了,現在解釋下m 這麼做的意義,這就是所謂資料封裝,你可以在你的程式中把m 的內部結構指標傳來傳去,可是你卻不知道它到底指向的內容是什麼...

控制代碼的本質

控制代碼 是wondows用來標識被應用程式所建立或使用的物件的唯一整數,windows使用各種各樣的 控制代碼標識諸如應用程式例項,視窗,控制,位圖,gdi物件等等。windows 控制代碼有點象c語言中的檔案控制代碼。從上面的定義中的我們可以看到,控制代碼是乙個識別符號,是拿來標識物件或者專案的...

模組控制代碼(例項控制代碼)和控制代碼的區別

解釋一 1 模組的概念 乙個模組代表的是乙個執行中的exe檔案或dll檔案,用來代表這個檔案中所有的 和資源,磁碟上的檔案不是模組,裝入記憶體後執行時就叫做模組。乙個應用程式呼叫其他dll中的api時,這些dll檔案被裝入記憶體,就產生了不同的模組,為了區分位址空間中的不同模組,每個模組都有乙個惟一...