当前位置:C++技术网 > 资讯 > 获取窗口实例句柄的五种方法,获取窗口实例句柄方法大全

获取窗口实例句柄的五种方法,获取窗口实例句柄方法大全

更新时间:2016-01-15 20:59:12浏览次数:1+次

    实例句柄在程序中很多地方都要用到,全面了解下三种获取程序实例的方法,对于编程有很大的好处。当然这些方法,可以用于其他地方,比如MFC等,原理是一样的。毕竟,在Windows平台上运行的类库框架都基于Win32,所以,一样一样的。
    在win32中,实现程序的功能的地方就是窗口过程,通过处理不同的消息可以实现不同的功能点。然而,在窗口过程中,获取程序的实例句柄,并没有那么直接。因为窗口过程的参数中并没有实例句柄的参数。
    那么我们要用其他方式来的获取实例句柄。在获取实例句柄之前,我们大概了解一下实例句柄的用处。
    我们要创建窗口,必然要用到实例句柄,来指定窗口所属的进程的线程。自然,我们不需要关注进程线程这东西,我们知道,一个实例句柄代表了一个执行的程序。那么指定这个实例句柄,系统就知道,创建的窗口是与我们的程序关联。那么当鼠标键盘的消息产生时,系统就会将消息投递到我们的程序中。
    另一方面,如果要使用程序中的自定义的图标等资源,我们需要用实例句柄来指定资源所在的位置。如果你不用实例句柄而是用NULL,则表示使用系统的默认的图标等资源。
    那么用途就不多说了。相必你在编程时自然会用到。在Win32中,没有其他框架,没有其他类库的包装,所有的一切都在我们的控制之中,这也让我们得到了最大的自由。我们提供的方法,看似在win32中最方便,实际上这是三种途径罢了,使用MFC自然也是可用的,只是可能是不能像Win32这么直接而已。
    获取实例句柄的第一种方法:全局变量。这是共享数据的最方便的方法。在WinMain函数的参数中,就有实例的句柄,我们只要将这个句柄存储在全局变量即可。而对于MFC,就被包装到应用程序类的成员变量里存储了。实质上,就是一样的。
    获取实例句柄的第二种方法:在WM_CREATE消息的创建窗口的结构体变量中获取。当窗口被创建的时候,也就是WM_CREATE消息产生的时候,消息的参数中含带了我们需要的实例句柄。为什么会携带实例句柄呢?你说呢?窗口创建的时候,你是不是可能还要创建子窗口控件呢?创建子窗口控件也就是创建窗口,不就需要实例句柄嘛。所以,参数中传递过来的创建结构体就已经含带了这个句柄哦。
    创建结构体为CREATESTRUCT,声明如下:
typedef struct tagCREATESTRUCT {
    LPVOID    lpCreateParams;
    HINSTANCE hInstance;//实例句柄
    HMENU     hMenu;
    HWND      hwndParent;
    int       cy;
    int       cx;
    int       y;
    int       x;
    LONG      style;
    LPCTSTR   lpszName;
    LPCTSTR   lpszClass;
    DWORD     dwExStyle;
} CREATESTRUCT, *LPCREATESTRUCT;
    这个结构体包含了创建窗口需要的所有信息。这个结构体的数据的地址在WM_CREATE消息的lParam参数中。要使用这个结构体,只要将lParam参数转换为结构体的指针,然后就可以使用里面的参数了。
    下面是使用创建结构体的代码示例,获取实例句柄的代码:
LPCREATESTRUCT lpCS = (LPCREATESTRUCT)lParam;//强制类型转换
HINSTANCE hIns = plCS->hInstance;//从创建结构体数据中获取实例句柄
    你可以在窗口创建的时候,将此值存储起来,就不用在WinMain中存储了。
    获取实例句柄的第三种方法:通过GetWindowLong函数来获取实例句柄。那么这种方法又是什么原理呢?系统通过窗口类创建了一个窗口后,窗口类结构体只是维护了公共的类型信息。然而很多的窗口都有各自的特别的数据。所以系统会给每一个窗口维护一个单独的数据,这就是GetWindowLong所能获得数据的原理。千万不要和GetClassLong混为一谈。一个是针对窗口类的,一个是针对单个窗口的,完全不是一回事。不过窗口类和窗口肯定也是有联系的,我在后面的文章在专题讲述。比如,要修改窗口的背景画刷,GetWindowLong和GetWindowLongPtr函数都没得办法,以为这个是窗口类独有的,所以此时才需要使用GetClassLong。所以,窗口特有的,自然使用GetWindowLong。
    那么我们查阅MSDN知道,要获取窗口的实例句柄使用GWL_HINSTANCE标识来调用GetWindowLong即可。其实GetWindowLongPtr使用GWLP_HINSTANCE标识也是可以获取的。
    我们使用GetWindowLong和GetWindowLongPtr来获取实例句柄的代码如下:
HINSTANCE hIns = (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE);
HINSTANCE hIns = (HINSTANCE)GetWindowLongPtr(hwnd,GWLP_HINSTANCE);
    然而你不要企图使用GetClassLong来获取实例句柄。这个不完全正确。为什么这么说呢?因为窗口类可能并不一定是你的实例里注册的,可能是dll注册的,并且在程序运行的时候加载到了进程的空间,让进程全局可用。那么此时你通过GCL_HMODULE标准调用GetClassLong得到的是dll的句柄,而不是你的窗口所在的实例句柄哦。当然,如果窗口类本身就是你自己注册的局部窗口类,其实也是可以的。只是我没有单独作为第四种方法,是因为他不完全通用,所以免得让大家误解了。如果硬要作为方法列举的话,GetWindowLongPtr为第四种,GetClassLong为第五种。
    所以使用GetClassLong要做一个额外的判断,就是明确的知道这个窗口类时在本实例注册的。如果确保是在本实例下注册的,那么用法如下:
HINSTANCE hIns = (HINSTANCE)GetClassLong(hwnd,GCL_HMODULE);
    那么以上就是所有可能获取窗口实例句柄的方法了,算是比较全面的方法了。注意使用GetClassLong需要注意的事项哦。为了达到最灵活的使用,推荐使用GetWindowLong和GetWindowLongPtr函数,要是最推荐的,自然是GetWindowLong,因为可以少打几个字咯。哈哈哈。