我是一初学者,正在被windows编程所吸引,但同时也遇到很多让人苦恼的问题,句柄跟指针的区别我想网上的谈论算够多了,但是什么意见都有,有时候看了这个高人的说法觉得有道理,并认为是那样,但是不久以后看了另一个人的提法,觉得他说的也是,所以我现在真的是搞不清了,希望哪位出来帮帮忙!
------------------------------------
以下转载vc知识库
[问题提出]
如果想对对话框的控件进行控制,那么首先要获得此控件的句柄(指针),然后对其操作.
[解决方法]
MFC提供了获取子窗口,指定控件和指定窗口句柄的函数:CWnd::GetDlgItem.
[实现程序]
假设你已有了名为My的对话框工程,并且有了一个ID=IDC_EDIT1的Edit控件:
BOOL CMyDlg::OnInitDialog()
{
CDialog::OnInitDialog();
CEdit *m_Edit=(CEdit *)GetDlgItem(IDC_EDIT1);
m_Edit->SetWindowText("练习");
return TRUE;
}
-----------------------------------
第二:以下是另一种说法: 许多开始学习VC的朋友,最多听说的两个词莫过于指针于句柄了。
但是,确经常搞不清他们之间的区别。
首先,句柄是一个窗口的标志,也就是所有从CWND类继承下来的,多有句柄这个成员。
他能做的,也就是唯一代表一个桌面上的窗口罢了。而指针是一个地址,如果它指向了一个内存中的对象,那么就可以对它进行任意操作了,当然,并不局限于自己的应用程序,你如果能够获得别的应用程序的某个对象的指针,也可以进行操作。然而,如果要获得指针,首先,必须找到那个窗口的句柄,然后用函数FromHandle就可以得到他的指针了。好了,现在,你可以对窗口任意操作了
-------------------------------
第三:
以下另一种说法:
看看C++ 教材中是如何给句柄下定义的:“在Win32里,句柄是指向一个无值型对象(void *)的指针,是一个4字节长的数据”。虽然我对它的本质是什么还是很迷惑,但我知道句柄并不是一个真正意义上的指针。从结构上看,句柄的确是一个指针,尽管它没有指向用于存储某个对象的内存位置(很多书都这么说,这正是我的迷惑所在),而实际上句柄指向的是一个包含了对该对象进行的引用的位置。在编程时,只要抓住了对象的句柄就可以对该对象进行操作了---------------------------------
我想问一下,通过对象的指针和通过对象的句柄来 操作对象到底有什么区别?
为什么有的说法是要先获取句柄以后在获取指针?
------------------------------------
以下转载vc知识库
[问题提出]
如果想对对话框的控件进行控制,那么首先要获得此控件的句柄(指针),然后对其操作.
[解决方法]
MFC提供了获取子窗口,指定控件和指定窗口句柄的函数:CWnd::GetDlgItem.
[实现程序]
假设你已有了名为My的对话框工程,并且有了一个ID=IDC_EDIT1的Edit控件:
BOOL CMyDlg::OnInitDialog()
{
CDialog::OnInitDialog();
CEdit *m_Edit=(CEdit *)GetDlgItem(IDC_EDIT1);
m_Edit->SetWindowText("练习");
return TRUE;
}
-----------------------------------
第二:以下是另一种说法: 许多开始学习VC的朋友,最多听说的两个词莫过于指针于句柄了。
但是,确经常搞不清他们之间的区别。
首先,句柄是一个窗口的标志,也就是所有从CWND类继承下来的,多有句柄这个成员。
他能做的,也就是唯一代表一个桌面上的窗口罢了。而指针是一个地址,如果它指向了一个内存中的对象,那么就可以对它进行任意操作了,当然,并不局限于自己的应用程序,你如果能够获得别的应用程序的某个对象的指针,也可以进行操作。然而,如果要获得指针,首先,必须找到那个窗口的句柄,然后用函数FromHandle就可以得到他的指针了。好了,现在,你可以对窗口任意操作了
-------------------------------
第三:
以下另一种说法:
看看C++ 教材中是如何给句柄下定义的:“在Win32里,句柄是指向一个无值型对象(void *)的指针,是一个4字节长的数据”。虽然我对它的本质是什么还是很迷惑,但我知道句柄并不是一个真正意义上的指针。从结构上看,句柄的确是一个指针,尽管它没有指向用于存储某个对象的内存位置(很多书都这么说,这正是我的迷惑所在),而实际上句柄指向的是一个包含了对该对象进行的引用的位置。在编程时,只要抓住了对象的句柄就可以对该对象进行操作了---------------------------------
我想问一下,通过对象的指针和通过对象的句柄来 操作对象到底有什么区别?
为什么有的说法是要先获取句柄以后在获取指针?
他能做的,也就是唯一代表一个桌面上的窗口罢了。而指针是一个地址,如果它指向了一个内存中的对象,那么就可以对它进行任意操作了,当然,并不局限于自己的应用程序,你如果能够获得别的应用程序的某个对象的指针,也可以进行操作。然而,如果要获得指针,首先,必须找到那个窗口的句柄,然后用函数FromHandle就可以得到他的指针了。好了,现在,你可以对窗口任意操作了这里需要明确的是:这里的指针和句柄完全是两个东西,这里的指针指的是MFC封装的窗口类对象的指针,如果这个对象没有跟具体的窗口关联起来,那么这个指针屁用都没有。
而句柄的确是标识系统资源的一个变量,指向的是一个包含了对该对象进行的引用的位置。标识了具体的窗口或其他如画刷等对象。句柄,HWND,是一个无类型的指针,实际指向的是一个结构,因此他并不指向一个实际的窗口或系统其他资源的对象。如何能通过他找到具体的对象是操作系统的事,对用户透明。所以你可以尽管放心大胆使用他对窗口等对象进行操作。MFC封装的时候把窗口类对象指针同具体窗口关联起来,这样可以用FromHandle通过句柄得到窗口类对象指针,然后利用这个指针对窗口操作,实际在这个类内部还是通过了一个m_hWnd的成员数据(句柄)对窗口在操作。
指针是什么相信大家都明白。
而句柄,个人认为:
句柄就是一个对象区分于其他对象的一种标识。这种标识可以使用指向内部结构的
~~~
指针来实现,也可以使用任何其他技术实现,比如一个递增的整数,一个Hash值,一个数组的下标,都可以的。其实,我觉得,严格来讲,句柄和指针之间并没有什么必然的联系。
typedef void *HANDLE
但我想它的意义可能比指针更丰富一些,因为在nt中一些类型还可以有安全权限,但指针好象没有。
知道你家,在找你,指针存放句柄的地址,*P= NEW CLASS 是系统自动开辟一块内存,P指向
类
正因为现在中国的教育制度使很多人失去了对事物的好奇,在这种制度下教出来的学生不想去了解事物的来龙去脉,不去了解系统底层的东西就无法创新。
此外,小学生想了解相对论绝对是件好事,如果向楼上(codewarrior(会思考的草))那样对待一个想学习相对论的小学生,中国很可能因此失去了一个爱因斯坦。不好意思,跑题了,我觉得hugwind(风之眼)说的已经比较清楚了,句柄虽然定义为一个
void *,但是你不能直接使用它而是需要让操作系统来帮你间接的使用这个对象。
话说windows是一个操作系统,操作系统有资源管理功能。
如何管理呢,当然要有一个结构来存放当前使用的资源,
这个结构可以看成用某种数据结构构成的一张表。
那么,每个资源在这张表中应该有一个ID来标识。
句柄就是这个ID。
我比较喜欢用英语阅读的方法来对待计算机学习,因为当初刚开始看的时候,真的非常痛苦,一个名词接一个名词,一个术语接着一个术语,如果每个都要追根究底的话,根本没法看下去。我的建议就是,不妨碍理解的,跳过去;妨碍的,就找个类似的比喻,譬如就把句柄当做指针好了,它能唯一标识一个Windows对象,至于系统内部是如何实现的,可以是指针,也可以是一个序号而已。等功夫深了,自然就有能力刨根问底了。
按现在的水平,停留在细枝末节的地方,很容易只见树木不见森林,初学者还是先见森林,从大局上有个感性认识,有能力了再进行穿越丛林的挑战,那样得到的东西和从别人那里问来的是不一样的,毕竟是自己一步一步trace出来的,别人跟你解释句柄,很可能说了半天你还是一头雾水。
一点体会,仅供参考。欢迎进行攻击,但不要进行人身攻击:)
struct tagWND
{
int index;
int processid;
char szCaption[1024];
......
};
windows的许多窗口的内存分配正是由这么一段段的结构组成的表,所以就明白了当你调用一个函数,假如:
BOOL SetWindowText(
HWND hWnd, // handle to window or control
LPCTSTR lpString // address of string
);这个函数的执行过程:
根据hWnd的值从系统的窗口内存分配表中得到相应的窗口数据结构,然后把szCaption改掉,再刷新这个窗口的标题,OK~~
所以要描述句柄同指针的关系:
句柄是系统的一个概念,它需要用指针来实现。指针只是个工具而已。不对之处,还望指出。顺便做宣传:
http://expert.csdn.net/Expert/topic/2284/2284123.xml?temp=.3411981
不久后会开源码,不过要注册用户:)
#define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name伤脑筋,如果有时间你自己看吧。
你可能还没有搞清楚,CWnd是如何封装WNDCLASS的,CWnd并不是直接把整个WNDCLASS都包装在内,而仅仅是包装了一个指向窗口的句柄,就是说,使用CWnd的指针,最后还是要转化成句柄对窗口进行操作。
CWnd
CWnd* pWnd-----> ----------
| m_hWnd |------>WNDCLASS
| …… |
|其他成员|
----------
理解了上面你就能理解,为什么创建一个窗口(典型如工具条,状态栏)要经过两次操作,一次是建立C++对象CToolBar,此时CToolBar内的窗口句柄还是空,即不代表任何Window对象,第二次使用Create/CreateEx函数才是真正创建Windows对象,创建完了之后,CToolBar内的窗口句柄就有效了。
支持 codewarrior(会思考的草) 你要仔细研究一点小东西,你这一辈子可能都没见过其他DD。呵呵
==================================
谢谢,不过,你说的DD,啥意思呢?好奇地问。
CWnd
按这种说法:
CWnd* pWnd-----> ----------
| m_hWnd |------>WNDCLASS
| …… |
|其他成员|
----------
理解了上面你就能理解,为什么创建一个窗口(典型如工具条,状态栏)要经过两次操作,一次是建立C++对象CToolBar,此时CToolBar内的窗口句柄还是空,即不代表任何Window对象,第二次使用Create/CreateEx函数才是真正创建Windows对象,创建完了之后,CToolBar内的窗口句柄就有效了。我想可以理解!但是我们同样可以通过窗口的句柄获得这个对象的指针,通过对象指针不是同样可以进行任意操作,那安全性还体现在哪里?
是阿,DD是什么意思?会不会是很时髦的话?那你一定得贴出来让大家知道!!呵呵!
安全性?体现在OS内部。对象的指针最终还是要通过句柄起作用,Windows本身是没有CWnd这个东西的,只有HWND。换句话说,windows只认HWND,不认CWnd*。
C++对象和WNDCLASS没有什么瓜葛!!!
WNDCLASS != CWnd
上面这个句子大家是否是认为得到了指针呢?其实也不是,它是得到句柄,所以,->以后的必是windows的某个函数,所以,你到底还是用到了如SetWindowText这样的函数,而不是直接对它的指针进行操作。
但有些函数(如GlobalAlloc()),这些函数虽然得到句柄,但却可以向指针强制转化,这当另当别论,它是为了兼容16位版本,不在大家考虑的通常情况之列。