现在的位置: 首页 > 综合 > 正文

句柄(Handle)是什么–对句柄的简单理解。

2013年10月01日 ⁄ 综合 ⁄ 共 2905字 ⁄ 字号 评论关闭

    开始学习C++,不了解句柄,无从下手,今天在网上找了找,并查阅MSDN,算是明白了不少。现汇总如下:

    简单说来,句柄(Handle)就是对象的一个标识,它就像是人的身份证号码一样具有唯一性。它是Windows用来标识被应用程序所建立或使用的对象的唯一整数(LONG类型的整数,4个字节)。
    句柄是整个Windows编程的基础。用于标识应用程序中不同的对象和同类对象中不同的实例,诸如一个窗口,按钮,图标,滚动条,输出设备,控件或者文件等,都有各自不同的句柄。
    句柄是一些表的索引,也就是指向指针的指针。间接的引用对象,Windows可以修改对象的"物理"地址和描述器的值,但是句柄的值是不变的。
    使用句柄有利于Windows在进程内存地址空间移动分配的内存块,以防止进程的内存空间被撕的四分五裂而存在过多的碎片。

 

    句柄是一个标识符,是拿来标识对象或者项目的,从数据类型上来看它只是一个16位的无符号整数。应用程序几乎总是通过调用一个Windows函数来获得一个句柄,之后其他的Windows函数就可以使用该句柄,以引用相应的对象。

    句柄是一种指向指针的指针。所谓指针是一种内存地址。应用程序启动后,组成这个程序的各对象是住留在内存的。如果简单地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这个地址访问对象了。不过,Windows是一个以虚拟内存为基础的操作系统。在这种系统环境下,Windows内存管理器经常在内存中来回移动对象,依此来满足各种应用程序的内存需要。对象被移动意味着它的地址变化了。如果地址总是如此变化,该到哪里去找该对象呢?

    为了解决这个问题,Windows操作系统为各应用程序腾出一些内存储地址,用来专门登记各应用对象在内存中的地址变化,而这个地址(存储单元的位置)本身是不变的。Windows内存管理器在移动对象(在内存中的位置)后,把对象新的地址告知这个句柄地址来保存。这样只需记住这个句柄地址,就可以间接地知道对象具体在内存中的哪个位置。这个地址是在对象装载(Load)时由系统分配给的,当系统卸载时(Unload)又释放给系统。 
    句柄地址(稳定)→记载着对象在内存中的地址;对象在内存中的地址(不稳定)→实际对象。

    本质:Windows程序中并不是用物理地址来标识一个内存块,文件,任务或动态装入模块的,相反的,Windows API给这些项目分配确定的句柄,并将句柄返回给应用程序,然后通过句柄来进行操作。

    但是必须注意的是程序每次从新启动,系统不能保证分配给这个程序的句柄还是原来的那个句柄,而且绝大多数情况的确不一样的。

 

[From MSDN]

 

TN003: Mapping of Windows Handles to Objects

This note describes the MFC routines that support mapping Windows object handles to C++ objects.

The Problem

Windows objects are normally represented by HANDLEs. The MFC classes wrap Windows object handles with C++ objects. The handle wrapping functions of the MFC class library provide a way to find the C++ object that is wrapping the Windows object with a particular handle. There are times when a Windows object does not have a C++ wrapper object, however, and at these times a temporary object is created to act as the C++ wrapper.

The Windows objects that use handle maps are:

  • HWND (CWnd and CWnd-derived classes)
  • HDC (CDC and CDC-derived classes)
  • HMENU (CMenu)
  • HPEN (CGdiObject)
  • HBRUSH (CGdiObject)
  • HFONT (CGdiObject)
  • HBITMAP (CGdiObject)
  • HPALETTE (CGdiObject)
  • HRGN (CGdiObject)
  • HIMAGELIST (CImageList)
  • SOCKET (CSocket)

Given a handle to any of these objects, you can find the MFC object that wraps the handle by calling the static member function FromHandle. For example, given an HWND called hWnd:

CWnd::FromHandle(hWnd)

will return a pointer to the CWnd that wraps the hWnd. If that hWnd does not have a specific wrapper object, then a temporary CWnd is created to wrap the hWnd. This makes it possible to get a valid C++ object from any handle.

Once you have a wrapper object, you can get to its handle through a public member variable. In the case of an CWnd, m_hWnd contains the HWND for that object.

Attaching Handles to MFC Objects

Given a newly created handle-wrapper object and a handle to a Windows object, you can associate the two by calling Attach. For example:

CWnd myWnd;
myWnd.Attach(hWnd);

This makes an entry in the permanent map associating myWnd and hWnd. Calling CWnd::FromHandle(hWnd) will now return a pointer to myWnd. When myWnd is deleted, the destructor will automatically destroy the hWnd by calling the Windows DestroyWindow function. If this is not desired, the hWnd must be detached from myWnd before the myWnd object is destroyed (normally when leaving the scope at which myWnd was defined). The Detach member function does this.

myWnd.Detach();

抱歉!评论已关闭.