1.句柄: 到处用的都是句柄,听说是能使对象持久存在.
能不能说一些为什么这样做?2.send和post
发送消息有两种方法,这两种方法分别在什么时候用合适?

解决方案 »

  1.   

    句柄概念在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编程,这会对你大有好处。
      

  2.   

    总结]关于句柄
    <<WINDOWS编程短平快>>(南京大学出版社): 
    句柄是WONDOWS用来标识被应用程序所建立或使用的对象的唯一整数,WINDOWS使用各种各样的句柄标识诸如应用程序实例,窗口,控制,位图,GDI对象等等。WINDOWS句柄有点象C语言中的文件句柄。 
    babyman(原文经过翻译): 
       尽管你会想要深入钻研源代码,但你其实并不会这样做。Windows编程起初都是非常困难的。让我们来快速的看一看Windows下的程序是这样运作的。你编程的关键将是处理和发送消息。那什么是消息呢?简单的说,消息是一个32位值,用来指明一个事件。比如:当你移动鼠标的时候,一个消息(定义为WM_MOUSEMOVE)就被发送给当前的窗口。当你按下键盘上的键,一个消息(定义为WM_KEYDOWN)就被发送给了当前的窗口。当你调整窗口的尺寸,一个消息(定义为WM_SIZE)被发送到当前的窗口。想象出这个过程了么?那么这些消息被发送到哪里去了呢?它们会排进一个队里,窗口最终会将它们拿出来并相应的执行。例如当窗口得到WM_MOVE消息,它将改变窗口坐标并在屏幕上重画窗口。 
       让我们来看看句柄。Windows在面向对象方面做的很好。你面对着一些window对象(比如桌面,你现在用来阅读的程序,等等...)。一个程序员用非面向对象的方式怎么区分这类东呢? 
       句柄用来引用不同的windows对象。你可以对窗口、文件使用句柄,也能对分配了的内存、图象使用句柄。可以把句柄理解为与指针类似。你必须通过某种方式来创建句柄;而且在使用完后销毁掉,不然将造成资源泄漏而使你的系统瘫痪。所以要保证它们在某个时候被销毁了。 
       好了,现在是时候让我们把这两件东西放在一起了。 
       比方说有一个窗口,你有一个指向它的句柄(称为HWND)。把你的句柄命名为your_HWND。当这个遮盖在这个窗口上面的其他窗口被移去的时候,系统会要求你重画窗口。windows会这样发送消息: 
    PostMessage(your_HWND, WM_PAINT, 0,0); 
       这个函数发送一个重画的消息给句柄为your_HWND的窗口。最后的两个参数作为该消息的额外信息,现在先不必考虑。这样,你的程序就应该有一个包括很多分支判断的函数来处理不同的消息。比如: 
    void  HandleTheMessage(long Message) 

     switch(Message) 
     { 
       case WM_PAINT 
         DrawWindow(); 
         break; 
       case WM_KEYDOWN 
         break; 
         etc... 
     } 

    sebsdin (孤灯下) from BBS 水木清华站: 
    句柄是一种指向指针的指针。我们知 道,所谓指针是一种内存地址。应用程序启动后,组成这个程序的各对象是住留在内存的。如果简单地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这个地址 访问对象。但是,如果您真的这样认为,那么您就大错特错了。我们知道,Windows是一 个以虚拟内存为基础的操作系统。在这种系统环境下,Windows内存管理器经常在内存中来回移动对象,依此来满足各种应用程序的内存需要。对象被移动意味着它的地址变化 了。如果地址总是如此变化,我们该到哪里去找该对象呢?为了解决这个问题,Windows操作系统为各应用程序腾出一些内存储地址,用来专门 登记各应用对象在内存中的地址变化,而这个地址(存储单元的位置)本身是不变的。Windows内存管理器在移动对象在内存中的位置后,把对象新的地址告知这个句柄地址来保存。这样我们只需记住这个句柄地址就可以间接地知道对象具体在内存中的哪个位置。这个地址是在对象装载(Load)时由系统分配给的,当系统卸载时(Unload)又释放给系统。句柄地址(稳定)→记载着对象在内存中的地址→对象在内存中的地址(不稳定)→实际对象。但是,必须注意的是程序每次从新启动,系统不能保证分配给这个程序的句柄还是原来的那个句柄,而且绝大多数情况的确不一样的。假如我们把进入电影院看电影看成 是一个应用程序的启动运行,那么系统给应用程序分配的句柄总是不一样,这和每次电 影院售给我们的门票总是不同的一个座位是一样的道理。   
    feeboby from csdn: 
    受M$的帮助文档以及很多Windows编程书籍的影响,大家对局柄比较普遍的认识是:句柄 
    是一个整数,用以标识Windows对象,句柄不是一个指针……而实际上,这些不过是M$进行数据封装的幌子而已,下面我们一起来分析一下HANDLE到底是什么。 
    请先到Windef.h找绝大多数句柄的定义: 
    DECLARE_HANDLE(HWND); 
    DECLARE_HANDLE(HHOOK); 
    …… 
    DECLARE_HANDLE(HGDIOBJ); 
    DECLARE_HANDLE(HBITMAP); 
    DECLARE_HANDLE(HBRUSH); 
    …… 
    typedef HANDLE              HGLOBAL; 
    typedef HANDLE              HLOCAL; 
    …… 
    OK, 现在大家跟我一起翻到Winnt.h,看看DECLARE_HANDLE和HANDLE到底是什么: 
    #ifdef STRICT 
    typedef void *HANDLE; 
    #define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct 
    name##__ *name 
    #else 
    typedef PVOID HANDLE; 
    #define DECLARE_HANDLE(name) typedef HANDLE name 
    #endif 
    typedef HANDLE *PHANDLE; 
    哈哈,现在知道了吧,HANDLE就是PVOID,也就是无类型指针, 
    而DECLARE_HANDLE(HWND);就是: 
    struct HWND__ { 
       int unused;}; 
    typedef struct HWND__ *HWND; 
    现在实际上都清楚啦,这些Handles都不过是指向struct的指针,至于这个struct的用处 
    ,连M$都说unused了,^o^ 
    现在解释下M$这么做的意义,这就是所谓数据封装,你可以在你的程序中把M$的内部结 
    构指针传来传去,可是你却不知道它到底指向的内容是什么,而且可以编个句柄的瞎话 
    防止大家的质疑:)。而M$的程序大可以这么写: 
    #include <windows.h>  //这个和大家用的一样 
    #include "windows_in.h"  //这个是M$自用的,外人别想看到^o^ 
    HSOMETHINGELSE DoSomething(HSOMETHING hSomething) { 
       struct RealSomething* p = (struct RealSomething*)hSomething; //先强制类型 
    转换成内部结构指针 
       ……do something…… 
       return (HSOMETHINGELSE)pRealSomethingElse;//强制类型逆转换 

    classfactory from vcroad: 
    单从概念上讲,句柄指一个对象的标识,而指针是一个对象的首地址。从实际处理的角度讲,即可以把句柄定义为指针,又可以把它定义为同类对象数组的索引,这两种处理方法都有优缺点,至于选用哪种方式,完全应该看实际需要,这可以说是一种程序设计上的技巧。那种单纯认为句柄是指针或索引的想法都是机械的、不确切的。 
    其实,在Windows中类似的处理是很多的、很灵活的。再具个相似的例子: 
    我们知道,在Windows中有个函数叫做CallWindowProc。故名思义,它的作用就是向指定的窗口过程传递一个消息。你也许会想,既然我已经有了窗口过程的指针,为什么我不可以直接通过这个指针调用该函数(这是C语言的内建功能)?事实上,在Win16中确实可以这么做,因为GetWindowLong返回的确实是该函数的指针。但在Win32下,GetWindowLong返回的并不是该函数的指针,而是一个包含函数指针的数据结构的指针(MSDN上说返回的是一个窗口函数地址或它的句柄,就是指的这种情况)。该数据结构是可变的,但只要你使用CallWindowProc来调用的话是不会出错的。这里我们又看到使用句柄处理带来的好处。(补充说明一点:微软在这里之所以这么处理,是为了解决16位/32位以及ANSI/UNICODE的转化问题) 
    另有一段文字,作者不详: 
    句柄是一个标识符,是拿来标识对象或者项目的,它就象我们的姓名一样,每个人都会有一个,不同的人的姓名不一样,但是,也可能有一个名字和你一样的人。从数据类型上来看它只是一个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); 
    这样应用程序才能存取这块内存。
      

  3.   

    The SendMessage function sends the specified message to a window or windows. The function calls the window procedure for the specified window and does not return until the window procedure has processed the message. The PostMessage function, in contrast, posts a message to a thread's message queue and returns immediately. 
    SendMessage 是将一条特殊的消息发到窗口,调用窗口的特殊处理过程来进行处理,在处理这个消息之前不会返回,实际上是是发送一个线程消息并且立即返回。
    The PostMessage function places (posts) a message in the message queue associated with the thread that created the specified window and then returns without 
    waiting for the thread to process the message.
    PostMessage 是放置一条消息到窗口的消息队列中,不管窗口会不会处理。
      

  4.   

    我们知道,Windows是一 个以虚拟内存为基础的操作系统。在这种系统环境下,Windows内存管理器经常在内存中来回移动对象,依此来满足各种应用程序的内存需要。对象被移动意味着它的地址变化 了。如果地址总是如此变化,我们该到哪里去找该对象呢?为了解决这个问题,Windows操作系统为各应用程序腾出一些内存储地址,用来专门 登记各应用对象在内存中的地址变化,而这个地址(存储单元的位置)本身是不变的。Windows内存管理器在移动对象在内存中的位置后,把对象新的地址告知这个句柄地址来保存。这样我们只需记住这个句柄地址就可以间接地知道对象具体在内存中的哪个位置。这个地址是在对象装载(Load)时由系统分配给的,当系统卸载时(Unload)又释放给系统。句柄地址(稳定)→记载着对象在内存中的地址→对象在内存中的地址(不稳定)→实际对象。但是,必须注意的是程序每次从新启动,系统不能保证分配给这个程序的句柄还是原来的那个句柄,而且绝大多数情况的确不一样的。假如我们把进入电影院看电影看成 是一个应用程序的启动运行,那么系统给应用程序分配的句柄总是不一样,这和每次电 影院售给我们的门票总是不同的一个座位是一样的道理。
      

  5.   

    请解释Windows是一 个以虚拟内存为基础的操作系统意思。
      

  6.   

    我喜欢把道理简单化,句柄与对象的关系就好像遥控器与电视,有了句柄就可以操控电视,是为了方便
    post 与send是2种模式,异步和同步,send是要阻赛的,post则不用,你如果希望你的消息马上得到反馈send,不需要就post,post的消息也可能不被相应
      

  7.   

    浅显地说:Post就是  :  我给网友发了一封信, 不管他有没有收到, 或者能不能收到,我都不管了,我该继续干什么干什么去.Send却是:   我给女友发了一封信, 还没收到她的回信,我就啥事都干不了,就等着回信.