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。
 
五. 
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值