WIN32下執行緒和視窗的資料繫結
WIN32下執行緒和視窗的資料繫結
一. 寫給自己
我很懶。這是我寫的第一篇涉及到程式設計的文章,也許就是因為太懶的緣故吧。在此之前也有寫的衝動可不知為什麼沒有寫成,懶得回憶了。說道記憶,啊,去年我在陳家莊。。。暈,又來了。有些事情我確實懶得記啦,以至於過去苦心鑽研的“經--典”程式碼,現在又得重新研究。後悔當初沒有給自己留下點什麼痕跡,蛛絲馬跡也好啊。本來很懶的我現在又得做重複勞動啊,那麼我到底懶不懶啊?唉,總得給自己留下點什麼吧,哪怕回憶也好啊。
由於本人記性不好,所以留此文章,已被後查。
二. 問題的提出
最近想在WIN32下對視窗封裝一下。於是查閱了很多資料並分析了MFC的視窗實現,這才知道MFC的博大(有夠大)。同時也使我積累了很多知識和技術,其實經常分析MFC實現對程式的編寫和設計是大有益處,高手就在於你看了多少程式碼。這裡不對MFC做過多評價,我們需要的僅是精華部分。
三. 執行緒資料的繫結
有的時候我們需要將一些資料或控制程式碼繫結到當前執行緒,以供不時只需。
在WIN32程式設計中,有些系統回撥函式並沒有準備足夠的引數為我們傳遞資料。而在這些回撥函式中就包括WindowProc,TimerProc等。下面介紹一種方法將我們的資料繫結到系統的當前執行緒中,線上程中的任何一個角落都會取到我們之前繫結的資料,執行緒到哪我們的資料也就到哪。接下來我們所使用的技術稱作執行緒本地儲存(TLS)。
執行緒本地儲存
要將資料(指標、控制程式碼)繫結到執行緒,我們需要一個全域性索引,而這個索引正是通過TlsAlloc分配的。
TlsAlloc
函式功能:分配一個執行緒區域性儲存(TLS)索引。該程式的任何執行緒都可以使用該索引來儲存和檢取執行緒中的值。
函式原型:DWORD TlsAlloc(void)
引數:無。
返回值:若函式成功,則返回值為一個TLS索引。失敗則返回0XFFFFFFFF。
需要說明的是,程式可以同時分配多個索引,用於存放不同的資料。下面提供程式、執行緒、索引、儲存槽的關係圖以便更好地理解。
當越過程式邊界時,TLS索引變為無效。一個DLL不能假定在一個程式中分配的索引在另一個程式中依然有效。
當一個DLL附加到一個程式時,它使用TlsAlloc分配一個TLS索引。然後,DLL分配一些動態儲存單元,並呼叫TlsSetValue向TLS槽中儲存地址。TLS索引儲存在DLL的全域性或靜態變數中。
有了這個索引,我們就可以通過它來取得、設定資料,然而這些資料只對當前執行緒可見。針對索引系統為每個執行緒分配一個儲存槽,當然我們可以隨意的來使用這個槽。下面的函式用於取和設槽置。
TlsGetValue
函式功能:檢取呼叫執行緒的執行緒區域性儲存(TLS)槽的值。對於每個TLS索引,程式的每個執行緒都有它自己的槽。
函式原型:LPVOID TlsGetValue(DWORD dwTlsIndex)
引數:
dwTlsIndex:由TlsAlloc分配的索引。
返回值:若函式成功,則返回撥用執行緒的TLS槽中的值;失敗則返回0。注意,存放在TLS槽中值可以為0,在這種情況下GetLastError返回NO_ERROR。
每個執行緒的TLS槽被初始化為NULL。
TlsSetValue
函式功能:儲存呼叫執行緒的執行緒區域性儲存(TLS)槽的值。
函式原型:BOOL TlsSetValue(DWORD dwTlsIndex, LPVOID lpTlsValue)
引數:
dwTlsIndex:由TlsAlloc分配的索引。
lpTlsValue:呼叫執行緒的執行緒區域性儲存(TLS)槽的值。
返回值:若函式成功,則返回值不為0;失敗則返回0。
TlsSetValue和TlsGetValue實現以提高速度為目標。這些函式執行最小的引數驗證和錯誤檢查。
當資料不再有用,我們需要將索引釋放,有始有終嗎。TlsFree函式不釋放任何與TLS相關的動態儲存單元。
TlsFree
函式功能:釋放呼叫執行緒區域性儲存(TLS)索引。
函式原型:BOOL TlsFree(DWORD dwTlsIndex)
引數:
dwTlsIndex:由TlsAlloc分配的索引。
返回值:若函式成功,則返回值不為0;失敗則返回0。
四. 視窗資料的繫結
下面介紹視窗資料的繫結,如果在WIN32下經常建立視窗,那麼你一定對WindowProc函式不會陌生了,所有的視窗訊息都是通過它來分配到視窗的。WindowProc無非就是windows的一個回撥函式,下面對該函式做下說明:
WindowProc
函式功能:該函式是一個應用程式定義的函式。它處理髮送給視窗的訊息。WNDPROC型別定義了一個指向該函式的指標。
函式原型:LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
引數:
hWnd:指向視窗的控制程式碼。
uMsg:指定訊息。
wParam, lParam:指定uMsg訊息的特定資訊。
返回值:訊息的處理結果,它與傳送的訊息有關。
所有的回撥函式都是全域性或靜態的,然而根據上面的函式描述並沒有給我們留下什麼儲存空間的指標,那麼我們的資料如何繫結到視窗上呢?
SetWindowLong
函式功能:改變指定視窗的屬性,也將指定的一個32位值設定在視窗的額外儲存空間中。
函式原型:LONG SetWindowLong(HWND hWnd, int nIndex, LONG dwNewLong)
引數:
hWnd:視窗控制程式碼。
nIndex:指定大於0的偏移值。可以指定下面的值之一:
GWL_EXISTYLE:設定一個新的擴充套件風格。GWL_STYLE:設定一個新的視窗風格。
GWL_WNDPROC:為視窗過程設定一個新的地址。GWL_ID:設定一個新的視窗識別符號。
GWL_HINSTANCE:設定一個新的應用程式例項控制程式碼。
GWL_USERDATA:設定與視窗有關的32位值。每個視窗均有一個由建立該視窗的應用程式使用的32位值。
當hWnd引數標識了一個對話方塊時,也可以使用下列值:
DWL_DLGPROC:設定對話方塊過程的新地址。
DWL_MSGRESULT:設定對話方塊過程中處理的訊息的返回值。
DWL_USER:設定應用程式私有的額外資訊,例如一個控制程式碼或指標。
dwNewLong:指定的替換值。
返回值:若成功返回原來的32位值,失敗則返回0。
GetWindowLong
函式功能:獲取指定視窗的屬性,也將獲取視窗的額外儲存空間中的一個32位值。
函式原型:LONG GetWindowLong(HWND hWnd, int nIndex)
引數:
hWnd:視窗控制程式碼。
nIndex:指定大於0的偏移值。可以指定下面的值之一:
GWL_EXISTYLE:獲取擴充套件風格。GWL_STYLE:獲取視窗風格。
GWL_WNDPROC:獲取視窗過程地址。GWL_ID:獲取視窗識別符號。
GWL_HINSTANCE:獲取應用程式例項控制程式碼。
GWL_USERDATA:獲取與視窗有關的32位值。每個視窗均有一個由建立該視窗的應用程式使用的32位值。
當hWnd引數標識了一個對話方塊時,也可以使用下列值:
DWL_DLGPROC:獲取對話方塊過程地址。
DWL_MSGRESULT:獲取對話方塊過程中一個處理的訊息的返回值。
DWL_USER:獲取應用程式私有的額外資訊,例如一個控制程式碼或指標。
返回值:若成功返回原來的32位值,失敗則返回0。
五.
相關文章
- 執行緒的【生命週期】和【執行緒的同步】(多視窗售票例子)執行緒
- Windows下繫結執行緒到指定的CPU核心Windows執行緒
- Win32執行緒——等待另一個執行緒結束Win32執行緒
- win32多執行緒和C++11多執行緒對比Win32執行緒C++
- 執行緒繫結cpu核心的程式碼研究執行緒
- 在非主執行緒中建立視窗執行緒
- win32 單例項程式執行-無視窗程式也可Win32單例
- Linux 中執行緒與 CPU 核的繫結Linux執行緒
- c#多執行緒更新視窗介面之 Invoke和BeginInvoke方法的使用C#執行緒
- Win32 多執行緒的效能(2) (轉)Win32執行緒
- Win32 多執行緒的效能(1) (轉)Win32執行緒
- 簡單資料繫結和複雜資料繫結
- 多執行緒:執行緒池理解和使用總結執行緒
- 多執行緒下的程式同步(執行緒同步問題總結篇)執行緒
- 執行緒轉儲:命名你的執行緒和檢視系統(轉)執行緒
- 深入淺出Win32多執行緒程式設計--之MFC的多執行緒Win32執行緒程式設計
- RxJava 觀察繫結和事件傳送流程及其中的執行緒切換分析RxJava事件執行緒
- Android : 執行緒的結束,掛起和恢復(下)Android執行緒
- win32的建立視窗程式碼Win32
- windows下檢視oracle 執行緒 (session)WindowsOracle執行緒Session
- 執行緒和執行緒池執行緒
- netty系列之:在netty中實現執行緒和CPU繫結Netty執行緒
- 執行緒、開啟執行緒的兩種方式、執行緒下的Join方法、守護執行緒執行緒
- Android的執行緒和執行緒池Android執行緒
- 多執行緒-程式和執行緒的概述執行緒
- 執行計劃繫結
- 漫畫:多執行緒經典例子之一視窗售票執行緒
- 同一個語句在plsql的sql視窗可以執行命令視窗不能執行SQL
- sqm執行計劃的繫結
- 【阿不】深入ASP.NET資料繫結(下)—多樣的繫結方式ASP.NET
- 設定滑鼠捕獲屬於當前執行緒的指定視窗執行緒
- C#資料結構-執行緒安全佇列C#資料結構執行緒佇列
- 微信小程式-檢視資料繫結微信小程式
- 【多執行緒總結(二)-執行緒安全與執行緒同步】執行緒
- web worker和主執行緒的資料交換效率初探Web執行緒
- 多執行緒-執行緒組的概述和使用執行緒
- 多執行緒-執行緒池的概述和使用執行緒
- java資料——執行緒(轉)Java執行緒