VC/MFC开发中的句柄HWND

13 篇文章 0 订阅
8 篇文章 0 订阅

Windows开发中,经常会碰到一个常见的字眼HWND,如下

   HWND hWnd;
   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW | WS_VISIBLE,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
HWND就是句柄,那么句柄是什么?

【句柄定义】

先看Windows下面的定义,如下

DECLARE_HANDLE            (HWND);
DECLARE_HANDLE            (HHOOK);
再往下看接续查找DECLARE_HANDLE的定义,如下
#ifdef STRICT //编译级别的选项开关
typedef void *HANDLE;  // void* 
#if 0 && (_MSC_VER > 1000)
#define DECLARE_HANDLE(name) struct name##__; typedef struct name##__ *name
#else
#define DECLARE_HANDLE(name) struct name##__{int unused;}; typedef struct name##__ *name
#endif
#else
typedef PVOID HANDLE;
#define DECLARE_HANDLE(name) typedef HANDLE name
#endif
typedef HANDLE *PHANDLE;

这里我的编译器采用的是VS2012,_MSC_VER含义如下:

MSVC++ 11.0 _MSC_VER = 1700 (Visual Studio 2012)
MSVC++ 10.0 _MSC_VER = 1600 (Visual Studio 2010)
MSVC++ 9.0  _MSC_VER = 1500 (Visual Studio 2008)
MSVC++ 8.0  _MSC_VER = 1400 (Visual Studio 2005)
MSVC++ 7.1  _MSC_VER = 1310 (Visual Studio 2003)
MSVC++ 7.0  _MSC_VER = 1300
MSVC++ 6.0  _MSC_VER = 1200
MSVC++ 5.0  _MSC_VER = 1100
就进入了宏开关的else分支:
#define DECLARE_HANDLE(name) struct name##__{int unused;}; typedef struct name##__ *name
展开上面的宏,假设传入的name为obj,展开后的结果
	#define DECLARE_HANDLE(obj) 
	struct obj__
	{
		int unused;
	}; 
	typedef struct obj__ *obj
再将DECLARE_HANDLE            (HWND);展开
	#define DECLARE_HANDLE(HWND) 
	struct HWND__
	{
		int unused;
	}; 
	typedef struct HWND__ *HWND
那么HWND就是一个仅含有一个整型成员变量的结构体对象的地址,这样一来HWND hwnd; 其实就等价于 HWND__* hWnd;

注意:(1)句柄是跨进程可见的,而指针从来都是属于某个特定进程的,这里摘自网上还没验证,但是根据核心编程里面对内核对象的理解,那里指出内核对象是内核地址上的一块区域,应该差不多

           (2)HANDLE、HINSTANCE又是什么呢?

#ifdef STRICT
typedef void *HANDLE;
...
#endif
typedef HANDLE *PHANDLE;

而HINSTANCE的定义域HWND类似,就是HINSTACE__ *

DECLARE_HANDLE(HINSTANCE);

【句柄猜想】

注意:这里是参照Windows核心编程对内核对象的解释

句柄其实就是对象地址的再次封装,防止肆意破坏对象且提供了一种安全的机制权限的一个整型值,这里我们进封装,由于Windows对象很多,需要一个类似索引的表,如

     句柄         地址      ...           权限

     1  0x0000 1200    ????    0x0000 0000

     2  0x0000 3400    ????    0x0000 0001

以上是一种猜测的假设, 这样句柄1的内存地址为0x0000 1200 ,假设权限0x0000 0000 就是无任何权限或者继承当前窗口或者进程的权限

参照上面的定义查询,发现没有权限之类的?why?这个我暂时也没搞懂,总之内核里面会维护一张句柄表,而每次都从那张表中查找具体的对象地址

何为内核对象?何为用户对象?何为GDI对象?

内核对象提供了一种健全的机制,可保证不同用户、不同权限的访问,在创建内核对象必须使用安全标志,并且其分布在内核地址空间某一段内存中,具体地址请查看微软技术丛书,而这两种就是除了上面讲的之外的句柄对象,例如一个窗口的使用,就是一个用户对象的使用;

【GDI对象的使用】

。。。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
了解了您的问题,您是想通过获取窗口的句柄来实现截屏功能。在 Windows 平台上,可以使用以下方式来实现: ```c++ #include <Windows.h> bool CaptureScreen(HWND hWnd, const char* filename) { HDC hDc = GetDC(hWnd); HDC hMemDc = CreateCompatibleDC(hDc); RECT rcClient; GetClientRect(hWnd, &rcClient); int nWidth = rcClient.right - rcClient.left; int nHeight = rcClient.bottom - rcClient.top; HBITMAP hBitmap = CreateCompatibleBitmap(hDc, nWidth, nHeight); HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDc, hBitmap); BitBlt(hMemDc, 0, 0, nWidth, nHeight, hDc, 0, 0, SRCCOPY); SelectObject(hMemDc, hOldBitmap); DeleteDC(hMemDc); ReleaseDC(hWnd, hDc); PBITMAPINFO pbi; pbi = CreateBitmapInfoStruct(hWnd, hBitmap); LPBYTE lpBits; lpBits = (LPBYTE)GlobalAlloc(GMEM_FIXED, pbi->bmiHeader.biSizeImage); GetDIBits(hMemDc, hBitmap, 0, (UINT)pbi->bmiHeader.biHeight, lpBits, pbi, DIB_RGB_COLORS); HANDLE hf; BITMAPFILEHEADER hdr; PBITMAPINFOHEADER pbih; LPBYTE lpData; DWORD dwTotal; DWORD cb; BYTE* hp; DWORD dwTmp; pbih = (PBITMAPINFOHEADER)pbi; lpData = (LPBYTE)(lpBits + pbih->biSize + pbi->bmiHeader.biClrUsed * sizeof(RGBQUAD)); dwTotal = ((DWORD)(pbih->biSizeImage + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER))); hdr.bfType = 0x4d42; hdr.bfSize = dwTotal; hdr.bfReserved1 = 0; hdr.bfReserved2 = 0; hdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER) + pbi->bmiHeader.biClrUsed * sizeof(RGBQUAD); hf = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, (DWORD)0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, (HANDLE)NULL); if (hf == INVALID_HANDLE_VALUE) return false; WriteFile(hf, (LPVOID)&hdr, sizeof(BITMAPFILEHEADER), (LPDWORD)&dwTmp, NULL); WriteFile(hf, (LPVOID)pbih, sizeof(BITMAPINFOHEADER) + pbi->bmiHeader.biClrUsed * sizeof(RGBQUAD), (LPDWORD)&dwTmp, (NULL)); WriteFile(hf, (LPVOID)lpData, (DWORD)pbih->biSizeImage, (LPDWORD)&dwTmp, NULL); CloseHandle(hf); GlobalFree((HGLOBAL)lpBits); DeleteObject(hBitmap); return true; } ``` 上面的代码,`CaptureScreen` 函数接收两个参数:`hWnd` 表示窗口句柄,`filename` 表示截图保存的文件名。该函数实现了从指定窗口截图,并将截图保存到指定文件的功能。 注:上述代码使用了一些辅助函数,如 `CreateBitmapInfoStruct`,请根据实际情况进行实现。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值