http://www1.ustc.edu.cn/personal/csli/vc_note/frame.htm 

句      柄

出处: 方塘2003.9.22 整理,之所以前面引用了 贾旭滨 先生的这段描述,因为他写的是在精彩!
=== 重庆大学光电工程学院 贾旭滨 对句柄有下面的描述:

句柄概念在WINDOWS编程中是一个很重要的概念,在许多地方都扮演着重要的角色。但由此而产生的句柄概念也大同小异,比如:<<Microsoft Windows 3 Developer's Workshop>>(Microsoft Press,by Richard Wilton)一书中句柄的概念是:在Windows环境中,句柄是用来标识项目的,这些项目包括:
*.模块(module)
*.任务(task)
*.实例(instance)
*.文件(file)
*.内存块(block of memory)
*.菜单(menu)
*.控制(control)
*.字体(font)
*.资源(resource),包括图标(icon),光标(cursor),字符串(string)等
*.GDI对象(GDI object),包括位图(bitmap),画刷(brush),元文件(metafile),调色板(palette),画笔(pen),区域(region),以及设备描述表(device context)。

WINDOWS程序中并不是用物理地址来标识一个内存块,文件,任务或动态装入模块的,相反的,WINDOWS API给这些项目分配确定的句柄,并将句柄返回给应用程序,然后通过句柄来进行操作。

在<<WINDOWS编程短平快>>(南京大学出版社)一书中是这么说的:句柄是WONDOWS用来标识被应用程序所建立或使用的对象的唯一整数,WINDOWS使用各种各样的句柄标识诸如应用程序实例,窗口,控制,位图,GDI对象等等。WINDOWS句柄有点象C语言中的文件句柄。

从上面的2个定义中的我们可以看到,句柄是一个标识符,是拿来标识对象或者项目的,它就象我们的姓名一样,每个人都会有一个,不同的人的姓名不一样,但是,也可能有一个名字和你一样的人。从数据类型上来看它只是一个16位的无符号整数。应用程序几乎总是通过调用一个WINDOWS函数来获得一个句柄,之后其他的WINDOWS函数就可以使用该句柄,以引用相应的对象。在WINDOWS编程中会用到大量的句柄,比如:HINSTANCE(实例句柄),HBITMAP(位图句柄),HDC(设备描述表句柄),HICON(图标句柄)等等,这当中还有一个通用的句柄,就是HANDLE,比如下面的语句:

HINSTANCE hInstance;

可以改成:

HANDLE hInstance;

上面的2句语句都是对的。

一个WINDOWS应用程序可以用不同的方法获得一个特定项的句柄。许多API函数,诸如CreateWindow,GlobalAlloc,OpenFile的返回值都是一个句柄值。另外,WINDOWS也能通过应用程序的引出函数将一个句柄作为参数传送给应用程序,应用程序一旦获得了一个确定项的句柄,便可在WINDOWS环境下的任何地方对这个句柄进行操作。其实句柄的大量使用已经影响到了每一个WINDOWS的程序设计。

句柄只有当唯一的确定了一个项目的时候,它才开始有意义。句柄对应着项目表中的一项,而只有WINDOWS本身才能直接存取这个表,应用程序只能通过API函数来处理不同的句柄,举个例子来说吧!比如:我们可以为我们的应用程序申请一块内存块,通过调用API函数GlobalAlloc,来返回一个句柄值:

hMem=GlobalAlloc(......);

其实现在hMem的值只是一个索引值,不是物理地址,应用程序还不能直接存取这块内存。这儿还有一个话外题,就是,一般情况下我们在编程的时候,给应用程序分配的内存都是可以移动的或者是可以丢弃的,这样能使有限的内存资源充分利用,所以,在某一个时候我们分配的那块内存的地址是不确定的,因为他是可以移动的,所以得先锁定那块内存块,这儿应用程序需要调用API函数GlobalLock函数来锁定句柄。如下:

lpMem=GlobalLock(hMem);

这样应用程序才能存取这块内存。

我想现在大家已经能对句柄概念有所了解了,我希望我的文章能对大家有所帮助。其实如果你学过SDK编程,那对句柄的概念理解会更好,更深。如果你是直接学VC6的MFC编程的,建议你看一下SDK编程,这会对你大有好处。

=== 有关 句柄或指针的 常用函数

1. 如何获取应用程序的 实例句柄? AfxGetInstanceHandle()
    应用程序的 实例句柄保存在CWinAppIm_hInstance 中,可以这么调用 AfxGetInstancdHandle获得句柄.
      Example: HANDLE hInstance=AfxGetInstanceHandle();

2. 如何通过代码获得应用程序主窗口的 指针? AfxGetMainWnd  GetSafeHwnd() AfxGetAppName()  AfxGetThread
   主窗口的 指针保存在CWinThread::m_pMainWnd中,调用 AfxGetMainWnd实现。

【例】   AfxGetMainWnd() ->ShowWindow(SW_SHOWMAXMIZED); //使程序最大化.

【例】此例的主窗口是对话框,下面的代码是在另外一个CFileTreeCtrl 类(子窗)中相关函数实现在主对话框(主窗)中的几个 静态文本框(子窗)中显示路径:
            CWnd* m_pCWnd= AfxGetMainWnd(); //得到主窗口指针,通过主窗指针访问其他子窗资源
            //方法一
            m_pCWnd->SetDlgItemText(IDC_STATIC_path,"CWnd* "+m_sCurPath); //在主窗中的子窗(ID:IDC_STATIC_path)中显示字符串
            m_pCWnd->SetDlgItemText(IDC_STATIC_who,"路径显示由FileTreeCtrl类完成:");
            //方法二
            m_pCWnd->SendMessage(STN_CLICKED); //向主窗口发送一个消息,显示任务由主窗完成。
                                               //在主窗的.cpp中有:ON_MESSAGE(STN_CLICKED, OnSTATICpath3)相关描述

//有的函数必须通过窗口的 句柄 来访问,我们可以使用下面的方法三
           //CWnd::GetSafeHwnd
           //Returns the window handle for a window
           //HWND GetSafeHwnd( ) const;
           HWND m_hWnd_tree =GetSafeHwnd();//【注】此处得到的只是当前窗口(FileTree类)的句柄
           HWND m_hWnd = m_pCWnd->GetSafeHwnd();// 这里才是主窗口的句柄(由主窗指针得到主窗的句柄)

//BOOL SetWindowText( HWND hWnd, LPCTSTR lpString )
           ::SetWindowText(m_hWnd,"ok2222");//修改主窗口标题
           ::SetDlgItemText(m_hWnd,IDC_STATIC_path2,"HWND: "+m_sCurPath);

【另】AfxGetThread
      CWinThread* AfxGetThread( );
      Return Value:Pointer to the currently executing thread.

3. 如何在程序中获得其他程序的 图标? AfxGetInstanceHandle()

  HINSTANCE AfxGetInstanceHandle( );
   Return Value
    
An HINSTANCE to the current instance of the application. If called from within a DLL linked with the USRDLL version of MFC, an HINSTANCE to the DLL is returned.
   Remarks
    
This function allows you to retrieve the instance handle of the current application. AfxGetInstanceHandle always returns the HINSTANCE of your executable file (.EXE) unless it is called from within a DLL linked with the USRDLL version of MFC. In this case, it returns an HINSTANCE to the DLL.

两种方法:
        (1) SDK函数 SHGetFileInfo 或使用 ExtractIcon获得图标资源的 handle(句柄),
        (2) SDK函数 SHGetFileInfo获得有关文件的 很多信息,如大小图标,属性,类型等.

Example(1): 在程序窗口左上角显示 NotePad图标.
           void CSampleView: OnDraw(CDC * pDC)
             {
                if( :: SHGetFileInfo(_T("c:\\pwin95\\notepad.exe"),0,
                     &stFileInfo,sizeof(stFileInfo),SHGFI_ICON))
                   {
                     pDC ->DrawIcon(10,10,stFileInfo.hIcon);
                   }
              }

Example(2):同样功能,Use ExtractIcon Function
          void CSampleView:: OnDraw(CDC *pDC)
              {
                HICON hIcon=:: ExtractIcon(AfxGetInstanceHandle(),_T
                 ("NotePad.exe"),0);

if (hIcon &&hIcon!=(HICON)-1)
                   pDC->DrawIcon(10,10,hIcon);
              }
   【说明】关于如何得到系统文件的正确路径,象win.ini system32.ini等的路径,各种系统中具体的路径是不一样的。如:
           获得notepad.exe的路径正规上来说用GetWindowsDirectory 函数得到;
           如果是调用 win95下的画笔,应该用访问注册表的方法获得其路径;
           要作成一个比较考究的程序,考虑应该全面点.

【另】
                HINSTANCE AfxGetResourceHandle( );
                Return Value:
An HINSTANCE handle where the default resources of the application are loaded.

4.   有关取得桌面句柄 GetDesktopWindow()

MSDN中的例子:

// 静态函数CWnd:: GetDesktopWindow 返回桌面窗口的指针。下例说明了MFC
void CFrameWnd::BeginModalState ()
{
  //first count all windows that need to be disabled
  UINT nCount=0;
  HWND hWnd=:: GetWindow (:: GetDesktopWindow (), GW_CHILD);
  while (hWnd!=NULL)
  {
    if (:: IsWindowEnabled (hwnd) &&
        CWnd::FromHandlePermanent (hWnd)!=NULL &&
        AfxIsDescendant (pParent->m_hWnd, hWnd) &&
        :: SendMessage (hWnd, WM_DISABLEMODAL, 0, 0) == 0)
    {
       ++nCount;
    }
    hWnd=:: GetWindow (hWnd, GW_HWNDNEXT);
  }
}

//用户的问题:下面程序取的不是同一程序的句柄,但是GetModuleFileName返回的结果一样请问为什莫

HWND ChWnd;//子窗口句柄
HWND hwDesktop=::GetDesktopWindow();//取得桌面句柄
ChWnd=::GetWindow(hwDesktop,GW_CHILD);//取得桌面子句柄
CString csTitle,csClass,csTm,mLookstring;
char szBuffer[255];
while(ChWnd!=NULL)//循环取子句柄的同级句柄
{
    if(::IsWindowVisible(ChWnd))//判断是否为可显示窗口
    {
         ::GetWindowText(ChWnd,csTitle.GetBuffer(255),254);
         ::GetClassName(ChWnd,csClass.GetBuffer(255),254);
         csTitle.ReleaseBuffer();//标题
         csClass.ReleaseBuffer();//类名
         csTm.Format("%08X:",ChWnd);
         if(csTitle=="")
         {
               mLookstring=csTm+csClass;
         }else
         {
               mLookstring=csTm+csTitle;
         }
         //这里的窗口句柄不是同一个程序吧?(问题所在!)可是为什莫结果一样
         HINSTANCE hInstance = (HINSTANCE)::GetWindowLong(ChWnd,DWL_USER);
         ::GetModuleFileName(hInstance, szBuffer, sizeof(szBuffer));
         MessageBox(szBuffer,mLookstring);
    }
    ChWnd=::GetWindow(ChWnd,GW_HWNDNEXT);
}

回答:

问题在于Win32下GetWindowLong(ChWnd,DWL_USER)总是返回当前程序运行的hInstance,所以你得到的文件名总是一个。所以你要用枚举所有"进程的程序名"来获得程序名。
 

=== 再谈句柄于指针的区别

许多开始学习VC的朋友,最多听说的两个词莫过于指针和句柄了。
 但是,确经常搞不清他们之间的区别。
 首先,句柄是一个窗口的标志,也就是所有从CWND类继承下来的,多有句柄这个成员。
 他能做的,也就是唯一代表一个桌面上的窗口罢了。而指针是一个地址,如果它指向了一个内存中的对象,那么就可以对它进行任意操作了,当然,并不局限于自己的应用程序,你如果能够获得别的应用程序的某个对象的指针,也可以进行操作。然而,如果要获得指针,首先,必须找到那个窗口的句柄,然后用函数FromHandle就可以得到他的指针了。

===  问题1:

如何在自定义的消息中发送一个字符串?例如:
SendMessage(MyWnd,WM_USERDEFINED, 0,0)
如何将字符串Buffer写入wParam或lParam?

你可以把字符串的地址传递过去,因为地址正好是32位。如:
char s[256];
SendMessage(MyWnd,WM_USERDEFINED, (WPARAM) s,0)
接收方只需要将wParam赋给一个char*就可以了。但此方法只能使用于在一个进程内部传递数据。
 

===  问题2:
1.在VC应用程序框架中,如何加入自己做的类,如何定义这个类的对象,我想在鼠标点击某个菜单项的时候才生成这个对象,做得到吗?(这个类的构造函数是带参数的)。
2.消息发送函数:
  PostMessage(HWND handle,WM_MYMESSAGE,
              WPARAM wParam,LPARAM lParam)
  中:
第一个参数如何获得?
如果我的消息是在自己的应用程序中生成的,想发给应用程序的窗口让它显示某些数据(用TextOut函数),能做到吗?
(也可以说是这样的问题:用Appwizard生成应用程序框架,在生成的类(如CView)中如何得到窗口的句柄,并放在PostMessage函数中。)
3.wParam,lParam,在消息响应函数中如何用?vc是怎样保证这两个数传到函数中的?问题比较多,谢谢!
水平: 刚入门

回答:

1、这个问题是肯定的。你可以使用ClassWizard定义类,也可以手工输入。如果类定义已经在某个文件中,只要使用Project|Add files将文件加入工程就可以了。要想定义类的对象,只要在你的菜单项的相应事件中就可以了。如:
{
...
MyClass myObject("Hello");
myObject.MyMethod();
...
}
2、在你自己的程序中传递消息当然没有任何问题,只要你知道要调用的窗口类是从CWnd继承来的,你就可以使用GetSafeHwnd函数获得窗口句柄。不过一般在自己的同一个程序中有时不愿意使用自定义消息,因为太麻烦。你完全可以给要调用的类添加一个成员函数,只要想显示数据,直接调用这个成员函数不就可以了?何必使用PostMessage呢?一般只有在程序间调用,才愿意使用自定义消息。这时,你通常可以使用FindWindow获得窗口句柄(QA000251 "如何利用FindWindow()函数查找程序")。
3、对于MFC已经定义了消息处理函数的消息,MFC会自动把wParam和lParam映射为更容易使用的方式。如OnMouseMove( UINT nFlags, CPoint point )。对于MFC不能自动处理的函数,如你使用ON_MESSAGE定义消息函数,则MFC会把wParam和lParam原原本本的传递给你的函数,不做任何处理。

===  一个未公开的Win32 API函数:GetTaskmanWindow  ()

    下例中还用到: GetProcAddress    GetParent(hWnd)
                    HMODULE hUser32 = GetModuleHandle("user32");

download

// getaskmanwnd.cpp (Windows NT/2000)
//
// 利用一个未公开的Win32 API函数:GetTaskmanWindow,
// 对Windows的任务栏进行操作(显示/隐藏)。这个函数返回拥有任务栏按钮的窗口句柄。
//
// This example will show you how you can obtain a handle to the
// Windows Taskbar window.
//
// (c)1999 Ashot Oganesyan K, SmartLine, Inc
// mailto:ashot@aha.ru, http://www.protect-me.com, http://www.codepile.com
#include <windows.h>
#include <stdio.h>
// User32!GetTaskmanWindow (NT specific!)
//
// This function returns a handle to the window that ownes the taskbar buttons
//
// HWND GetTaskmanWindow()
//
typedef HWND (WINAPI *PROCGETTASKMANWND)(void);
PROCGETTASKMANWND GetTaskmanWindow;
void main(int argc, char* argv[])
{
if (argc<2)
{
printf("Usage:\n\ngetaskmanwnd.exe S|H\n");
return;
}
HMODULE hUser32 = GetModuleHandle("user32");
if (!hUser32)
return;
GetTaskmanWindow = (PROCGETTASKMANWND)GetProcAddress(hUser32,"GetTaskmanWindow");
if (!GetTaskmanWindow)
return;
HWND hWnd = GetTaskmanWindow();
if (!hWnd)
return;
if (*argv[1]=='H' || *argv[1]=='h')
ShowWindow(GetParent(hWnd),SW_HIDE);
else
ShowWindow(GetParent(hWnd),SW_SHOW);
}

重庆大学光电工程学院 贾旭滨 对 “句柄” “指针” 有下面的描述(AfxGetMainWnd GetSafeHwnd() AfxGetAppName() AfxGetThread)...相关推荐

  1. 23西安电子科技大学光电工程学院851考研录取情况

    01.光电工程学院各个方向 02.23光电工程学院一志愿考研录取情况总览.平均分 PS:在23年,西电物理与光电工程学院拆分为两个院,分别是:物理学院和光电工程学院.其中物理学院改考602高等数学+8 ...

  2. 吉林大学 十佳歌手 计算机科学与工程学院,贾海洋 - 吉林大学 - 计算机科学与技术学院...

    个人简介 讲授课程: 数据结构(课程链接) 算法分析(课程链接) 数据挖掘(课程链接) 教育经历: 2012-2014,美国加州大学圣迭戈分校,访问学者 2008-2009,香港大学,博士后 2003 ...

  3. 长江大学物理学院李c语言,李继军 - 长江大学 - 物理与光电工程学院

    个人简介 1.讲授的主要课程 (1)<大学物理>,公共基础课,4学时/周 (2)<医用物理学>,公共基础课,5学时/周 (3)<Matlab程序设计>,选修课,5学 ...

  4. 华侨大学计算机学院蔡绍滨,曾焕强-华侨大学-信息科学与工程学院

    曾焕强 姓名:曾焕强 学历/学位:博士 职称/职务:教授 所属部门:通信工程系 简介 新加坡南洋理工大学博士(2012),香港中文大学研究员(2012-2013),2014年起担任华侨大学信息科学与工 ...

  5. 南理工计算机学院贾修一,南京理工大学考研研究生导师简介-贾修一

    南京理工大学考研研究生导师简介-贾修一本站小编 Free考研网/2019-05-27 导师姓名:贾修一 性别:男 人气指数:623 所属院校:南京理工大学 所属院系:计算机科学与工程学院 职称:副教授 ...

  6. 计算机科学与工程学院彭骜宇,公派留学联合培养博士生项目校内评审答辩安排...

    公派留学联合培养博士生项目校内评审答辩安排 (7页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 9.90 积分 2017 年公派留学年公派留学联联合培养博 ...

  7. 产学交流 | 重庆理工大学计算机科学与工程学院一行到访芝诺数据

    产 学 交 流 6/23 2022 TODAY 6月23日,重庆理工大学计算机科学与工程学院副院长朱凌云,党委副书记厉华杰等一行人到访芝诺数据慰问计算机科学与工程学院的实习学生们,校企合作负责人刘辰靓 ...

  8. 产学交流 | 重庆理工大学计算机科学与工程学院信息管理系一行到访芝诺数据...

    产 学 交 流 3月9日,重庆理工大学计算机科学与工程学院信息管理系一行莅临我司调研交流,总经理甄少明热情接待学校一行,并向到访人员展示公司产品体系和教学科研平台,及芝诺数据在产学研领域与各高校及科研 ...

  9. 无锡计算机科学与工程学院,瞩目!公办本科,无锡学院首次招生,这些优势很突出!...

    这几天, 众多考生家长都在寻找志愿填报的最优解. 选大学要考虑哪些因素? 结合众多招考专家的意见 排在前三的分别是:考生的高考分数.学校的层次和优势专业.所在城市. 2018年迁址无锡办学的 南京信息 ...

最新文章

  1. 从决策树学习谈到贝叶斯分类算法
  2. 图解:为什么非公平锁的性能更高?
  3. 分号可以用来分段么_更高效的GMX分段模拟方法:修改tpr文件
  4. 通信模块开发 c语言,I2C通信模块c语言库文件
  5. uploadify 302 php,jQuery Uploadify 上传插件出现Http Error 302 错误的解决办法
  6. CISSP认证科普,涨姿势
  7. UE5 IK重定向并修改人物姿势
  8. 关于Bundle Adjustment的直观理解
  9. 第六章 姜小白当机立断逃莒国 姜诸儿瓜期不代终遇鬼
  10. jquery validate插件onfocosout/onkeyup出错的解决方法
  11. 图像频率域分析之频域谱(FDE)
  12. 项目管理之项目整体管理
  13. linux 串口转网口工具,linux下串口调试工具/串口终端推荐: picocom(转)
  14. Oracle创建数据链路
  15. 别人花了几万元学的英语,我帮你们免费弄来了
  16. 获取电信光猫TEWA-600超级管理密码,修改电信光猫为桥接模式
  17. 文章导引—Jeremy
  18. 性能篇 | 17 | jmeter | BeanShell内置变量prev的使用技巧
  19. i3 10110u 怎么样 相当于什么水平
  20. python-js逆向之AST语法树初学(一)

热门文章

  1. php实现商品购物车添加功能,PHP实现添加购物车功能
  2. html文字字号不改变,如何在不改变div大小的情况下更改HTML / css中的字体大小?...
  3. 数据结构与算法(C++)– 动态规划(Dynamic Programming)
  4. Scikit-Learn 机器学习笔记 -- MNIST
  5. 工业用微型计算机笔记(4)~编码,寄存器,引脚
  6. 【深度学习】3D深度学习简介
  7. 【职场】遇到了个失业开滴滴的程序员
  8. 【机器学习】在大数据上使用PySpark进行K-Means
  9. 【论文解读】DeepFM论文总结
  10. 推荐搜索炼丹笔记:向量召回 MIND多兴趣双塔模型