句柄(Handle)是一个32位(4个字节,64位程序中为8字节)的无符号整数,实际上是Windows在内存中维护的一个对象(窗口等)内存物理地址(32或64位)列表的整数索引因为Windows的内存管理经常会将当前空闲对象的内存释放掉,当需要访问时再重新提交到物理内存,所以对象的物理地址是变化的,不允许程序直接通过物理地址来访问对象程序将想访问的对象的句柄传递给系统,系统根据句柄检索自己维护的对象列表就能知道程序想访问的对象及共物理地址了,现在小编就来说说关于mfc全局变量是什么意思?下面内容希望能帮助到你,我们来一起看看吧!
mfc全局变量是什么意思
1 通俗化理解句柄句柄(Handle)是一个32位(4个字节,64位程序中为8字节)的无符号整数,实际上是Windows在内存中维护的一个对象(窗口等)内存物理地址(32或64位)列表的整数索引。因为Windows的内存管理经常会将当前空闲对象的内存释放掉,当需要访问时再重新提交到物理内存,所以对象的物理地址是变化的,不允许程序直接通过物理地址来访问对象。程序将想访问的对象的句柄传递给系统,系统根据句柄检索自己维护的对象列表就能知道程序想访问的对象及共物理地址了。
我们知道,所谓指针是一种内存地址。应用程序启动后,组成这个程序的各对象是驻留在内存的。如果简单地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这个地址访问对象。但是,Windos是一个以虚拟内存为基础的操作系统。在这种系统环境下,Windows内存管理器经常在内存中来回移动对象,以此来满足各种应用程序的内存需要。对象被移动意味着它的地址变化了。如果内存总是如此变化,我们该到哪里去找该对象呢?为了解决这个问题,Windows系统为进程分配固定的地址(句柄)来存储进程下的数据对象变化后的地址。Windows操作系统为各应用程序腾出一些内存地址,用来专门登记各应用对象在内存中的地址变化,而这个地址本身是不会变的。Windows内存管理器移动对象在内存中的位置后,把对象新的地址告知这个句柄地址来保存。这样我们只需要记住这个句柄地址就可以间接地知道对象具体在内存中的哪个位置。这个地址是在对象装载时由系统分配的,当系统卸载时又释放给系统。但是,必须注意的是,程序每次重新启动,系统不能保证分配给这个程序的句柄还是原来的那个句柄。而且绝大多数情况下的确不一样。假如我们把进入电影院看电影看成是一个应用程序的启动运行,那么系统给应用程序分配的句柄总是不一样,这和每次电影院售给我们的门票总是不同的座位是一样的道理。
所谓Windows Object(Windows对象)是Win32下用句柄表示的Windows操作系统对象;所谓MFC Object (MFC对象)是C 对象,是一个C 类的实例,这里MFC Object是有特定含义的,指封装Windows Object的C Object,并非指任意的C Object。
MFC Object 和Windows Object是不一样的,但两者紧密联系。以窗口对象为例:
一个MFC窗口对象是一个C CWnd类(或派生类)的实例,是程序直接创建的。在程序执行中它随着窗口类构造函数的调用而生成,随着析构函数的调用而消失。而Windows窗口则是Windows系统的一个内部数据结构的实例,由一个“窗口句柄”标识,Windows系统创建它并给它分配系统资源。Windows窗口在MFC窗口对象创建之后,由CWnd类的Create成员函数创建,“窗口句柄”保存在窗口对象的m_hWnd成员变量中。Windows窗口可以被一个程序销毁,也可以被用户的动作销毁。MFC窗口对象和Windows窗口对象的关系如图2-1所示。其他的Windows Object和对应的MFC Object也有类似的关系。
MFC给这些类定义了一个成员变量来保存MFC Object对应的Windows Object的句柄。对于设备描述表CDC类,将保存两个HDC句柄。
MFC Object通过构造函数由程序直接创建;Windows Object由相应的SDK函数创建。
MFC中,使用这些MFC Object,一般分两步:
首先,创建一个MFC Object,或者在STACK中创建,或者在HEAP中创建,这时,MFC Object的句柄实例变量为空,或者说不是一个有效的句柄。
然后,调用MFC Object的成员函数创建相应的Windows Object,MFC的句柄变量存储一个有效句柄。
(句柄经常做为函数返回值或函数参数而存在。)
MFC Object和Windows Object的对应关系:
描述 Windows句柄 MFC Object 窗口 HWND CWnd and CWnd-derived classes 设备上下文 HDC CDC and CDC-derived classes 菜单 HMENU CMenu 笔 HPEN CGdiObject类,CPen和CPen-derived classes 刷子 HBRUSH CGdiObject类,CBrush和CBrush-derived classes 字体 HFONT CGdiObject类,CFont和CFont-derived classes 位图 HBITMAP CGdiObject类,CBitmap和CBitmap-derived classes 调色板 HPALETTE CGdiObject类,CPalette和CPalette-derived classes 区域 HRGN CGdiObject类,CRgn和CRgn-derived classes 图像列表 HimageLIST CimageList和CimageList-derived classes 套接字 SOCKET CSocket,CAsynSocket及其派生类 可以从一个MFC Object得到对应的Windows Object的句柄;一般使用MFC Object的成员函数GetSafeHandle得到对应的句柄。
可以从一个已存在的Windows Object创建一个对应的MFC Object; 一般使用MFC Object的成员函数Attach或者FromHandle来创建,前者得到一个永久性对象,后者得到的可能是一个临时对象。
从指针到句柄 :
CWnd *pWnd = GetDlgItem(ID_***); // 取得控件的指针,CWnd是窗口类
HWND hwnd = pWnd->GetSafeHwnd(); // 取得控件的句柄
hdc=GetDC(hwnd);
有了DC绰号hdc,就可以画图了:
MoveToEx( hdc,0, y_shift-(draw_yu-y_min)*ry, NULL );
LineTo(hdc,900,y_shift-(draw_yu-y_min)*ry);
CPaintDC dc(this); // device context for painting
//CPaintDC是CDC的一个派生类,只是在OnPaint()函数中使用;
CPen pen1(PS_SOLID, 1, RGB(198, 198, 198));
//把画笔选到设置描述表当中.覆盖默认画笔.
CDC* pDC = pWnd->GetWindowDC(); //取得CDC的指针
//或CDC *pDC = GetDC();
dc.SelectObject(&pen1);
dc.MoveTo(0,455);//移动到该坐标
dcneTo(917,455); //画线画到这个点
pDC->TextOut(92,50,"(如:ifeng)");
从句柄到指针 :
CComBox* com; //声明一个CComBox类的指针
HWND hwnd = GetDlgItem(hwnd,IDC_XX)->GetSafeHwnd();
com = (CComBox*)FromHandle(hwnd);
相当于
CWnd* pCtrl = this->FromHandle(::GetDlgItem(hwnd,IDC_XX));
注意这里FromHandle是CWnd的一个静态函数,也就是说只能用在CWnd或者CWnd的子类,如CDIalog,或者你自己的继承自CWnd的类中。
使用控件指针:
CWnd *pWnd = GetDlgItem(ID_***); // 取得控件的指针,CWnd是窗口类
HWND hwnd = pWnd->GetSafeHwnd(); // 取得控件的句柄
CRichEditCtrl* pRichEdit = (CRichEditCtrl*)(CWnd::FromHandle(hwnd));//hwnd是上面两句获得的句柄,转化为对应控件的指针
CString szRichMsg;
szRichMsg.Format("%s",msg.c_str());
CString szUname;
std::string uname=stanza->from().username();
szUname.Format("%s",uname.c_str());
pRichEdit->ReplaceSel((szUname "\t" m_Time) "\n" szRichMsg "\n");//使用控件指针
以下用控件指针也是可以操作控件的:
CEdit *edit1=(CEdit*)GetDlgItem(IDC_EDIT2);
edit1->GetWindowText(m_text);
ID--句柄--指针三者之间的互相转换
id->句柄-----------hWnd = ::GetDlgItem(hParentWnd,id);
id->指针-----------CWnd::GetDlgItem();
句柄->id-----------id = GetWindowLong(hWnd,GWL_ID);
句柄->指针--------CWnd *pWnd=CWnd::FromHandle(hWnd);
指针->ID----------id = GetWindowLong(pWnd->GetSafeHwnd,GWL_ID);
GetDlgCtrlID();
指针->句柄--------hWnd=cWnd.GetSafeHandle() or mywnd->m_hWnd;
HICON->ID--------HICON hIcon = AfxGetApp()->LoadIcon(nIconID);
HICON hIcon = LoadIcon(AfxGetApp()->m_hInstance, MAKEINTRESOURCE(nIconID));
3 再说Windows窗口句柄与MFC窗口类Windows窗口句柄是用来确定Windows窗口的一个值,在win32编程中,都是很常见的。但是MFC为了简化编程就提供了CWnd窗口类将其包装了,然后对API函数封装后,就在创建对象时将窗口句柄关联到对象,然后提供的成员函数就可以省掉窗口句柄参数了。所以,在基于CWnd继承而来的所有类中,都有一个公有的成员变量m_hWnd,这个成员变量就是窗口对象关联的windows窗口句柄。我们在类中可以直接使用这个窗口句柄成员变量。这个窗口对象就是标准的C 对象。
其实MFC窗口类并不神奇,就是包装了一下API而已。m_hWnd的类型就是HWND。因为窗口类都是一个C 对象,而C 对象就是我们平时使用C 时用的类实例化而来的。这么一说,其实窗口类和窗口对象其实就是将窗口句柄作为C 对象的一个成员,然后创建时关联的而已。在CreateWindow函数中,传入了窗口的ID,这样就让窗口类可以获得这个窗口ID的窗口句柄,进而保存到窗口对象成员m_hWnd中。这样就形成了关联。这样就创建了一个窗口对象。
MFC给这些类定义了一个成员变量来保存MFC Object对应的Windows Object的句柄。对于设备描述表CDC类,将保存两个HDC句柄。
CDC类有两个成员变量:m_hDC,m_hAttribDC,它们都是Windows设备描述表句柄。CDC的成员函数作输出操作时,使用m_Hdc;要获取设备描述表的属性时,使用m_hAttribDC。
void CMyView::OnDraw(CDC *pDC)
{
CPen penBlack; //构造MFC CPen对象
if (penBlack.CreatePen(PS_SOLID, RGB(0, 0, 0)))
{
CPen *pOldPen = pDC->SelectObject(&penBlack)); //选进设备表,保存原笔
…
pDC->SelectObject(pOldPen); //恢复原笔
}else
{
…
}
}
pDC->SelectObject(&penBlack)返回了一个CPen *指针,也就是说,它根据原来PEN的句柄创建了一个MFC CPen对象。
-End-
,