WIN32下线程和窗口的数据绑定(转)

xiaoxiao2021-03-01  15

原来出处:http://blog.csdn.net/zhoujianhei/archive/2007/11/19/1891891.aspx 作者:乞丐中的霸主 一. 写给自己 我很懒。这是我写的第 一篇涉及到编程的文章,也许就是因为太懒的缘故吧。在此之前也有写的冲动可不知为什么没有写成,懒得回忆了。说道记忆,啊,去年我在陈家庄。。。晕,又来 了。有些事情我确实懒得记啦,以至于过去苦心钻研的“经--典”代码,现在又得重新研究。后悔当初没有给自己留下点什么痕迹,蛛丝马迹也好啊。本来很懒的 我现在又得做重复劳动啊,那么我到底懒不懒啊?唉,总得给自己留下点什么吧,哪怕回忆也好啊。 由于本人记性不好,所以留此文章,已被后查。 二. 问题的提出 最近想在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。 相关资源:带音效新年烟花动画特效-HTML-代码
转载请注明原文地址: https://www.6miu.com/read-4050334.html

最新回复(0)