VC|窗口对象句柄、指针、ID的获取及它们之间的转换
bigegpt 2024-09-24 07:18 4 浏览
SDK的WIN32 API用句柄HANDLE操作Windows窗口,而VC将HANDLE封装为CWnd类的一个成员变量m_hWnd,可以取此对象的m_hWnd属性来得到句柄。同时,VC中每一个窗口类都可以声明为一个窗口指针来调用窗口类的成员属性和成员变量。
1 窗口
窗口是Windows应用程序中一个非常重要的元素,一个Windows应用程序至少要有一个窗口,称为主窗口,窗口是指现在是屏幕上面的一快矩形区域,是Windows应用程序与用户进行交互的接口。利用窗口,可以接收用户的输入及显示输出。
一个应用程序窗口通常包含标题栏、菜单栏、系统菜单、最小化框、最大化框、可调边框、滚动条等
窗口可以分为客户区和非客户区,客户区是窗口的一部分,应用程序通常在客户区中显示文字或绘制图形。而标题栏、菜单栏、系统菜单、最小化和最大化,可调系统边框为窗口的非客户区,他们由windows来管理,而应用程序则主要管理客户区的外观及操作。
窗口可以有一个父窗口,有父窗口的窗口称为子窗口,另外,对话框和消息框也是一种窗口,在对话框上面还包含许多子窗口,这些子窗口的形式有按钮、单选按钮、复选框、组框、文本编辑框等。
此外,在我们启动Windows系统后,我们的桌面也是一个窗口,称为桌面窗口,是位于最上层的窗口,由Windows系统创建和管理。
2 窗口句柄
当用你CreateWindow创建了一个窗口,这个窗口其实并不是你创建的,而是系统替你的创建的,系统为创建这个窗口,它必须要保留很多的和这个窗口相关的数据,这些数据并不是给你用的,而是系统用来维护窗口用的,而句柄就是系统用来找到这个窗口相关数据的一人索引。你向一个API提供一个句柄,比如ShowWindow(HWND);要显示这个窗口,这个工作还是系统替你做的,它根据你提供的索引,也就是句柄,找到窗口,然后进行相关的处理。所以说,句柄是相关对象的唯一索引。从这一点上看,有点像指针,但是指针的内容是对象的地址,而句柄并不是地址,句柄只是一个索引,一个整数。
句柄的实质就是一个结构体的实例。
Windows系统中有许多内核对象(这里的对象不完全等价于"面向对象程序设计"一词中的"对象",虽然实质上还真差不多),比如打开的文件,创建的线程,程序的窗口,等等。这些重要的对象肯定不是4个字节或者8个字节足以完全描述的,他们拥有大量的属性。为了保存这样一个"对象"的状态,往往需要上百甚至上千字节的内存空间,那么怎么在程序间或程序内部的子过程(函数)之间传递这些数据呢?拖着这成百上千的字节拷贝来拷贝去吗?显然会浪费效率。那么怎么办?当然传递这些对象的首地址是一个办法,但这至少有两个缺点:
I 暴露了内核对象本身,使得程序(而不是操作系统内核)也可以任意地修改对象地内部状态(首地址都知道了,还有什么不能改的?),这显然是操作系统内核所不允许的;
II 操作系统有定期整理内存的责任,如果一些内存整理过一次后,对象被搬走了怎么办?
所以,Windows操作系统就采用进一步的间接:在进程的地址空间中设一张表,表里头专门保存一些编号和由这个编号对应一个地址,而由那个地址去引用实际的对象,这个编号跟那个地址在数值上没有任何规律性的联系,纯粹是个映射而已。
在Windows系统中,这个编号就叫做"句柄"。
在Windows应用程序中,窗口是通过句柄HWND来标识的,我们要对某个窗口进行操作,首先就要获取到这个窗口的句柄。
每个窗口在被创建出来之后就会被赋予一个句柄,该句柄指向一个数据结构体,结构体里明确表示着该窗口的各种信息,窗口大小,窗口名等,当我们得到这个句柄时就可以请求操作系统对它做一系列操作,列如:移动窗口,关闭窗口,最小化最大化等,这些都是通过窗口句柄来告诉操作系统的,我们要对哪个窗口进行操作,而消息则是告诉操作系统要做什么样的操作,消息的附加参数就是操作值,列如移动窗口,会有附加的xy坐标参数!
句柄有Windows句柄,文件句柄,分配内存句柄,图形句柄等,系统在创建这次资源的时候回为其分配内存,并返回标识这些资源的标识号,这个标识号就是句柄,实际上,我们可以将句柄看做是指针。
在使用句柄之前,必须先创建他们,当不在使用时,应当及时销毁,如果不销毁他们,最终将到时资源泄露,资源泄露有可能导致系统崩溃,所以,务必确保在适当的时候销毁不在使用的句柄。
另外,程序运行时也是以进程存在,进程也是用ID或句柄去标识。
进程创建时,windows系统为进程构造了一个句柄表。当该进程希望获得一个内核对象句柄或者创建一个内核对象从而获得该对象句柄时。系统会将在句柄表中增加一个表项,表项的内容中存储了指向目标内核对象的指针。同时,系统返回这个表项在句柄表中的索引作为句柄。这样,进程就通过句柄查询句柄表得到对象指针,从而可以访问该对象。同时又由于有了句柄表的保护,可以防止对内核对象的非法操作。
3 Windows对象和MFC对象的区别
windows对象并不是我们平时所说的“面向对象”程序设计中的“类的对象”,而是一种windows资源实体,如画笔、字体等。
如果想要去使用这些windows对象我们需要用句柄来标识它们。
而MFC对象则是真正的“面向对象”思想中的“类的对象”(必须用构造函数去创建)。
在windows编程中,除了普通的“类的对象”外,用得最多的“C++类的对象”应该是MFC对象了(如果你是用MFC编程的话),
MFC对象是指“封装了windows对象的C++对象”(也就是MFC对象中有一个控制window对象的控制器,那么控制器想工作就得和一个window对象链接起来,这样就能控制器就能控制这个对象了)。
所谓Windows对象是Win32下用句柄表示的Windows操作系统对象;
所谓MFC对象就是C++对象,是一个C++类的实例.
一个MFC窗口对象是一个C++ CWnd类(或派生类)的实例,是程序直接创建的。
在程序执行中它随着窗口类构造函数的调用而生成,随着析构函数的调用而消失。
而Windows窗口则是Windows系统的一个内部数据结构的实例,由一个“窗口句柄”标识,Windows系统创建它并给它分配系统资源。
Windows窗口在MFC窗口对象创建之后,由CWnd类的Create成员函数创建,“窗口句柄”保存在MFC窗口对象的m_hWnd成员变量中。
Windows窗口可以被一个程序销毁,也可以被用户的动作销毁。
MFC中的窗口类,就是C++类与Windows窗口的句柄的结合。在基于CWnd继承而来的所有类中,都有一个公有的成员变量m_hWnd,这个成员变量就是窗口对象关联的windows窗口句柄。我们在类中可以直接使用这个窗口句柄成员变量。这个窗口对象就是标准的C++对象。其实MFC窗口类并不神奇,就是包装了一下API而已。m_hWnd的类型就是HWND。MFC给CWnd提供了两个成员函数Attach(HWND hWndNew )和Detach()。前者传入一个窗口句柄,将该窗口关联到C++对象,后者则是将当前关联的窗口解关联。而关联就是给m_hWnd赋值,解关联就是将m_hWnd设置为NULL。解关联后,窗口对象就不关联任何窗口了,此时就不能执行窗口相关的任何操作,都会失败。如果要关联新的窗口,只要执行Attach函数即可。
4 对话框控件消息响应函数中可以直接调用的函数
4.1 MFC全局函数,如:
AfxMessageBox 显示一个消息框
AfxGetApp 返回应用程序对象CWinApp的一个指针
AfxGetAppName 返回应用程序的名称
AfxInitRichEdit 为应用程序初始化RichEdit控件
4.2 API函数,如:
SendMessage(),调用一个窗口的窗口函数,将一条消息发给那个窗口;
OpenFile() 这个函数能执行大量不同的文件操作;
RegCreateKey() 在指定的项下创建或打开一个项;
GetCaretPos() 判断插入符的当前位置;
ShellExecute() 用指定程序打开指定路径下的文件;
4.3 其父类定义的成员函数,如CWnd类:
PreSubclassWindow()
在调用SubclassWindow之前,允许其它必要的子类化工作
FromHandle()
当给定一个窗口的句柄时,返回CWnd对象的指针。如果没有CWnd对象与这个句柄相连接,则创建一个临时的CWnd对象并与之相连接
GetSafeHwnd
返回m_hWnd,如果该指针为NULL,则返回NULL
etFocus()
要求输入焦点
SetWindowPos()
改变子窗口、弹出窗口和顶层窗口的大小、位置以及顺序
GetClientRect
获得CWnd客户区域的大小
GetDlgItem(),
获得指定的对话框中具有指定ID的控件
UpdateData()
初始化对话框或获得对话框中的数据
SetWindowText()
将窗口的文本或标题文字(如果有)设为指定的文本
SetWindowText
将窗口的文本或标题文字(如果有)设为指定的文本
SetTimer()
安装一个系统定时器,当它被激活时,发送一个WM_TIMER消息
MessageBox()
创建并显示一个窗口,其中包含了应用程序提供的消息和标题
SendMessage()
向CWnd对象发送一个消息,直到这条消息被处理之后才返回
OnPaint()
调用这个函数以重画窗口的一部分
OnLButtonDown()
当用户按下鼠标左键时调用这个函数
OnTimer()
当达到SetTimer指定的时间间隔时调用这个函数
4.4 继承关系不同的GetDlgItem()
1) CWindow::GetDlgItem HWND GetDlgItem(int nID)const; 2) CWnd::GetDlgItem CWnd* GetDlgItem(int nID) const; void CWnd::GetDlgItem( int nID, HWND *phWnd) const; 3)Windows SDK HWND GetDlgItem(HWND hDlg,int nIDDlgItem);
5 窗口句柄和指针使用的场合
先看下面的两行代码,简单了解一下窗口句柄和指针的一个使用场合:
5.1 API函数以句柄为参数
CString str = "在编辑框上显示给定文本。"; SendMessage(GetActiveWindow()->GetDlgItem(IDC_textbox)->m_hWnd, WM_SETTEXT , 0 , (LPARAM)str.GetBuffer(0));
此代码可以在当前活动窗口的IDC_textbox文本框控件中显示一个字符串str。
① API函数SendMessage()功能:将指定的消息发送到一个或多个窗口。
LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam)
hWnd:其窗口程序将接收消息的窗口的句柄。如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口,但消息不被发送到子窗口。
Msg:指定被发送的消息。
wParam:指定附加的消息特定信息。
IParam:指定附加的消息特定信息。
返回值:指定消息处理的结果,依赖于所发送的消息。
② CWnd类方法GetDlgItem(IDC_textbox),能够返回一个MFC指针*CWnd;
③ CWnd类方法GetActiveWindow(),可以返回当前窗口的一个HWND句柄;
④ “->m_hWnd”是将一个指针转换为句柄。一般窗口对象都会有一个其对应的句柄变量,所以我们可以取此对象的m_hWnd属性来得到句柄。
5.2 MFC对象指针调用成员函数
下面的的代码也是在编辑框上显示给定文件:
CString str = "在编辑框上显示给定文本。"; CEdit *edit1=(CEdit*)GetDlgItem(IDC_EDIT2); edit1->SetWindowText(str);
GetDlgItem()可以返回一个MFC指针*CWnd,并用(CEdit*)做了下类型转换,然后就可以使用CEdit类的成员函数,例如SetWindowText()。
5.3 API函数使用句柄作为参数
CString str = "F:\\help\\list.html"; API函数ShellExecute(this->m_hWnd, "open", str,"", NULL, SW_SHOW);
this->m_hWnd; //返回的就是窗口类自己的句柄呢,也可以用MFC全局函数:
AfxGetMainWnd()->m_hWnd;
6 窗口ID和指针
对MFC编程来说,对话框和控件都可以理解为一个子窗口,都有对应的一个ID和类。可以返回对应的对象指针。
7 获得窗口句柄的方法
HWND FindWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName)
HWND FindWindowEx(HWND hwndParent, HWND hwndChildAfter,LPCTSTR lpClassName, LPCTSTR lpWindowName)
HWND WindowFromPoint(POINT& Point)//获得当前鼠标光标位置的窗口HWND
在任何类中获得应用程序类
HWND AfxGetInstanceHandle()
获取当前活动窗口句柄
HWND GetActiveWindow(VOID)
获取前台窗口句柄
HWND GetForegroundWindow(void);
获得对话框中某控件的句柄
HWND GetDlgItem(m_hDLG,m_nID_DlgItem);
获得GDI对象的句柄
HWND m_hGDIObj = m_pGDIObj->GetSafeHanle();
8 获取窗口指针的办法
① 获取当前应用进程的指针
AfxGetApp();
② 获得主框架窗口指针(任何时候都可以用,只要是MFC程序中)
CWnd* pWnd = AfxGetMainWnd();
③ 获得对话框中控件指针
CWnd* pWnd = GetDlgItem(IDC_xxx);
可以强制转换为具体类型,如CEdit *edit1 = (*CEdit)GetDlgItem(IDC_xxx);
④ 获得工具栏指针
CToolBar * pToolBar=(CtoolBar*)AfxGetMainWnd()->GetDescendantWindow(AFX_IDW_TOOLBAR);
9 窗口、控件的指针和句柄的相互转化
① 指针转化为句柄
在MFC应用程序中首先要获得窗口的指针,然后将其转化为句柄
CWnd *pwnd = FindWindow(“ExploreWClass”,NULL); //希望找到资源管理器 HWND hwnd = pwnd->m_hwnd; //得到它的HWND
这样的代码当开始得到的pwnd为空的时候就会出现一个“General protection error”,并关闭应用程序,因为一般不能对一个NULL指针访问其成员,如果用下面的代码:
CWnd *pwnd = FindWindow(“ExploreWClass”,NULL); //希望找到资源管理器 HWND hwnd = pwnd->GetSafeHwnd(); //得到它的HWND
就不会出现问题,因为尽管当pwnd是NULL时,GetSafeHwnd仍然可以用,只是返回NULL
② 句柄转化为指针
在MFC应用程序中首先用GetDlgItem()获得对话框控件的句柄,然后获得其指针:
HANDLE hWnd; GetDlgItem(IDC_xxx,&hWnd); CWnd *pWnd=CWnd::FromHandle(hWnd); pWnd->Attach(hWnd); //Attaches a Windows to a CWnd object
// 用FindWindow()得到一个窗口句柄,然后转换为容器指针
HWND hWnd=::FindWindow(NULL,_T("IDD_Assistants")); //得到对话框的句柄 CAssistantsDialog* pWnd= (CAssistantsDialog*)CAssistantsDialog::FromHandle(hWnd); //由句柄得到对话框的对象指针 pWnd- >xxx( ); //调用C***Dialog中的函数xxx();
10 窗口、控件的指针和句柄与其ID的相互转化
ID->句柄,hWnd = ::GetDlgItem(hParentWnd,id);
ID->指针,CWnd::GetDlgItem();
句柄->ID,id = GetWindowLong(hWnd,GWL_ID);
指针->ID,id = GetWindowLong(pWnd->GetSafeHwnd,GWL_ID);
HICON->ID,HICON hIcon = AfxGetApp()->LoadIcon(nIconID);
ID->HICON,HICON hIcon = LoadIcon(AfxGetApp()->m_hInstance, MAKEINTRESOURCE(nIconID));
-End-
相关推荐
- 5分钟调色大片的方法(5分钟调色大片的方法有哪些)
-
哈喽大家好。在大家印象中一定觉得ps非常难学非常难。大家不要着急,小编的教学都是针对ps零基础的同学的,而且非常实用哦。只要大家跟着图文练习一两遍,保证大家立马学会~!好了,废话少说,下面开始我们今天...
- 闪白特效原来是这么用的(闪白特效怎么使用)
-
作者|高艳侠订阅|010-86092062闪白特效是影视作品中应用比较多的效果之一,那么具体该在哪些场景使用闪白特效?具体该如何操作?下面就以AdobePremiere(以下简称PR)为例,...
- ppt常用小图标去哪里找?3个矢量素材网站推荐!
-
ppt是一个注重可视化表达的演示载体,除了高清图片,ppt中另一类常用的素材是各种小图标,也叫矢量图标,巧妙运用小图标能提升整体美观度和表现力,那么ppt常用小图标去哪里找呢?为方便各位快速找到合适的...
- 有什么好用的截图录屏工具?试试这9款
-
经常有朋友反馈苦于缺乏截屏和录屏的趁手工具,本期我们分享几个相当好用的截屏和录屏工具,希望能帮到大家。ScreenToGifScreenToGif是一款免费且开源的录屏工具。此款工具最大的特点是可以...
- 配色苦手福音!专业快速色环配色PS插件
-
今天橘子老师给的大家介绍的是一款快速配色的插件,非常强大配色苦手福音来啦!(获取方式见文末)【插件介绍】配色在后期设计中占有主导地位,好的配色能让作品更加抢眼Coolorus这款专业的配色插件,能够...
- 如何用PS抠主体?(ps怎么抠主体)
-
1.主体法抠图-抠花苞和花梗导入一张荷花苞的照片,点击上图中顶部“选择”菜单栏,下拉单击“主体”。可以看到,只有花苞被选中,但是花梗并没有被选中。接下来单击上图中左侧工具栏的“快速选择工具”,上图中顶...
- 2799元的4K电视,有保障吗?(买4k电视机哪个品牌好)
-
在上一期《电脑报》的3·15专题报道中,我们揭露了一款不靠谱的42英寸4K智能电视——TCLD42A561U。这款售价2699元的4K智能电视不仅4K画质方面存在严重问题,而且各种功能和应用体验也不理...
- 苹果电脑的Touch Bar推出一段时间了 这款工具可以帮你开发适用于它的APP
-
距离苹果推出带有TouchBar的MacBookPro已经有一段时间了,除了那些像Adobe、Google和Microsoft大公司在开发适用于TouchBar的应用之外,其实还有很多独立的开...
- 如魔法般吸取颜色的桌灯(如魔法般吸取颜色的桌灯叫什么)
-
色彩为生活带来的感官刺激,逐渐被视为理所当然。一盏桌灯运用它的神奇力量,将隐藏于物件中的颜色逐一释放,成为装点环境的空间魔法师。ColorUp是一款可以改变颜色的吸色台灯,沿用传统灯泡的造型,融入了拾...
- 一篇文章带你用jquery mobile设计颜色拾取器
-
【一、项目背景】现实生活中,我们经常会遇到配色的问题,这个时候去百度一下RGB表。而RGB表只提供相对于的颜色的RGB值而没有可以验证的模块。我们可以通过jquerymobile去设计颜色的拾取器...
- ps拾色器快捷键是什么?(ps2019拾色器快捷键)
-
ps拾色器快捷键是什么?文章末尾有获取方式,按照以下步骤就能自动获得!学会制作PS特效需要一定程度的耐心和毅力。初学者可以从基本的工具和技术开始学习,逐渐提高他们的技能水平。同时,观看更多优秀的特效作...
- 免费开源的 Windows 截图录屏工具,支持 OCR 识别和滚动截图等
-
功能很强大、安装很小巧的免费截图、录屏工具,提供很多使用的工具来帮我么能解决问题,推荐给大家。关于ShareXShareX是一款免费的windows工具,起初是一个小巧的截图工具,经过多年的迭...
- 入门到精通系列PS教程:第13篇 · 拾色器、颜色问题说明及补充
-
入门到精通系列PS教程:第13篇·拾色器、颜色问题说明及补充作者|侯潇问题说明我的第12篇教程里,有个小问题没有说清楚。要说是错误,又不算是错误,只是没有说准确。写完那篇教程后,因为已经到了深...
- PS冷知识:用吸管工具吸取屏幕上的任意颜色
-
今天,我们给大家介绍PS中的一个冷知识:用吸管工具可以吸取屏幕上的任意颜色。其实,操作起来是非常简单的。大多数情况下,我们认为,PS的吸管工具只能吸取PS软件作图区域范围内的颜色,最多加上画布四周的...
- Windows 11 将提供内置颜色选择器工具
-
Windows11内置了颜色选择器,可以扫描并识别屏幕上的颜色并生成颜色代码。此外,微软还利用人工智能技术,让屏幕上的文本扫描和选择变得更加便捷。这两项功能均已在SnippingToolv1...
- 一周热门
- 最近发表
- 标签列表
-
- mybatiscollection (79)
- mqtt服务器 (88)
- keyerror (78)
- c#map (65)
- xftp6 (83)
- bt搜索 (75)
- c#var (76)
- xcode-select (66)
- mysql授权 (74)
- 下载测试 (70)
- linuxlink (65)
- pythonwget (67)
- androidinclude (65)
- libcrypto.so (74)
- linux安装minio (74)
- ubuntuunzip (67)
- vscode使用技巧 (83)
- secure-file-priv (67)
- vue阻止冒泡 (67)
- jquery跨域 (68)
- php写入文件 (73)
- kafkatools (66)
- mysql导出数据库 (66)
- jquery鼠标移入移出 (71)
- 取小数点后两位的函数 (73)