c语言回调函数中的句柄 c回调函数应用场景

c中的句柄是什么意思,如何理解?所谓句柄实际上是一个数据c语言回调函数中的句柄,是一个Long (整长型)的数据 。
句柄是WONDOWS用来标识被应用程序所建立或使用的对象的唯一整数,WINDOWS使用各种各样的句柄标识诸如应用程序实例,窗口 , 控制,位图,GDI对象等等 。WINDOWS句柄有点象C语言中的文件句柄 。
从上面的定义中的我们可以看到,句柄是一个标识符,是拿来标识对象或者项目的,它就象我们的姓名一样,每个人都会有一个,不同的人的姓名不一样,但是,也可能有一个名字和c语言回调函数中的句柄你一样的人 。从数据类型上来看它只是一个16位的无符号整数 。应用程序几乎总是通过调用一个WINDOWS函数来获得一个句柄,之后其他的WINDOWS函数就可以使用该句柄,以引用相应的对象 。
如果想更透彻一点地认识句柄,我可以告诉大家,句柄是一种指向指针的指针 。我们知道,所谓指针是一种内存地址 。应用程序启动后 , 组成这个程序的各对象是住留在内存的 。如果简单地理解,似乎我们只要获知这个内存的首地址,那么就可以随时用这个地址访问对象 。但是,如果您真的这样认为,那么您就大错特错了 。我们知道,Windows是一个以虚拟内存为基础的操作系统 。在这种系统环境下,Windows内存管理器经常在内存中来回移动对象,依此来满足各种应用程序的内存需要 。对象被移动意味着它的地址变化了 。如果地址总是如此变化 , 我们该到哪里去找该对象呢?
为了解决这个问题,Windows操作系统为各应用程序腾出一些内存储地址 , 用来专门登记各应用对象在内存中的地址变化,而这个地址(存储单元的位置)本身是不变的 。Windows内存管理器在移动对象在内存中的位置后,把对象新的地址告知这个句柄地址来保存 。这样我们只需记住这个句柄地址就可以间接地知道对象具体在内存中的哪个位置 。这个地址是在对象装载(Load)时由系统分配给的,当系统卸载时(Unload)又释放给系统 。
句柄地址(稳定)→记载着对象在内存中的地址————→对象在内存中的地址(不稳定)→实际对象
本质:WINDOWS程序中并不是用物理地址来标识一个内存块,文件 , 任务或动态装入模块的,相反的,WINDOWS API给这些项目分配确定的句柄,并将句柄返回给应用程序,然后通过句柄来进行操作 。
但是必须注意的是程序每次从新启动,系统不能保证分配给这个程序的句柄还是原来的那个句柄,而且绝大多数情况的确不一样的 。假如我们把进入电影院看电影看成是一个应用程序的启动运行 , 那么系统给应用程序分配的句柄总是不一样,这和每次电影院售给我们的门票总是不同的一个座位是一样的道理 。
如何用回调函数SendMessageCallback获取窗体句柄?系统以messagesc语言回调函数中的句柄的形式将输入传递给窗口过程 。消息可以被系统和应用程序产生 。系统产生消息当每一次输入事件发生c语言回调函数中的句柄 , 如当用户敲键盘,移鼠标,或者单击滚动条 。系统也用消息来响应由于应用程序引起的系统变化 。如应用程序改变系统字体资源或者改变它的一个窗口 。应用程序产生消息来让他的窗口执行一些任务或者与其他应用程序的窗口通讯 。
系统发送消息给窗口过程并传递4个参数 , windows句柄, 消息标识符, 2个消息参数 。系统使用窗体句柄来决定那个窗口过程来接受消息 。
消息标识符以常量命名指出消息的含义 。当窗口过程接收到消息,使用消息标识符决定如何处理消息 。例如、WM_PAINT告诉窗口过程窗体客户区被改变c语言回调函数中的句柄了需要重绘 。
消息参数指定被窗口过程使用的数据和数据的位置 。其含义和值取决于消息类型 。消息参数可以包含一个整数,标志位,一个指针等 。当消息不使用消息参数时 , 他们被设置位NULL 。一个Window窗口过程必须根据消息标识符来决定如何解释消息参数 。
Message Types
This section describes the two types of messages:
· System-Defined Messages
· Application-Defined Messages
System-Defined Messages
当系统和应用程序通讯时,系统post和send系统定义消息 。他使用消息来控制应用程序的操作,提供输入和其他信息让应用程序处理 。应用程序也可以post或者send系统定义消息 。
每一个系统定义消息由一个唯一的标识符与一致的常量以声明消息的含义 。例如 WM_PAINT 要求窗口绘制它的内容 。
符号常量指定系统定义消息属于的类别,常量的前缀指定处理解释消息的窗体的类型 。以下使一些前缀和他们相关的消息类别 。
Prefix Message category
ABM Application desktop toolbar
BM Button control
CB Combo box control
CBEM Extended combo box control
CDM Common dialog box
DBT Device
DL Drag list box
DM Default push button control
DTM Date and time picker control
EM Edit control
HDM Header control
HKM Hot key control
IPM IP address control
LB List box control
LVM List view control
MCM Month calendar control
PBM Progress bar
PGM Pager control
PSM Property sheet
RB Rebar control
SB Status bar window
SBM Scroll bar control
STM Static control
TB Toolbar
TBM Trackbar
TCM Tab control
TTM Tooltip control
TVM Tree-view control
UDM Up-down control
WM General window
通用窗体消息覆盖c语言回调函数中的句柄了很大一个信息和请求的范围, 包括鼠标键盘消息, 菜单对话框的输入, 窗体产生与管理, 动态数据交换 (DDE).
Application-Defined Messages
应用程序可以产生自己用的消息或者与其他进程中窗体通讯 。如果应用程序产生自己的消息,窗口过程接受并且必须提供合适的处理 。
系统保留消息标识符的值在0x0000在0x03ff(WM_USER-1)范围 。这些值被系统定义消息使用 。应用程序不能使用这些值给自己的消息 。
private window classes用0x0400(WM_USER)到0x7fff消息标识符
· If your application is marked version 4.0, you can use message-identifier values in the range 0x8000 (WM_APP) through 0xBFFF for private messages.
系统使用RegisterWindowMessage来注册消息 , 返回一个消息标识符范围在0XC000到0XFFFF,使用这个函数来保证整个系统范围内是唯一的
Message Routing
系统有两个方法将消息传递到窗口过程 。Post一个消息到先进先出的消息队列 。系统定义的临时内存对象 。和直接 send消息到窗口过程 。
被发送到消息队列的消息称做入队消息,主要是由鼠标键盘输入,例如 WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_KEYDOWN, and WM_CHAR messages 。还包括定时器, 刷新, 退出: WM_TIMER, WM_PAINT, and WM_QUIT 。其他直接发送到窗口过程的消息被称为 非入队消息 。
Queued Messages
系统可以显示任何数量的窗体同一时间 。为了传递鼠标键盘消息到合适的窗口,系统使用消息队列 。
系统维护一个系统消息队列和每一个GUI线程的消息队列,为避免给non-GUI现成创建消息队列,所有线程产生时并没有消息队列 。仅当线程第一次调用GDI函数时,系统给线程创建一个消息队列 。只要用户移动鼠标,点击鼠标 , 敲键 , 驱动程序将其转换为消息将他们放在系统消息队列中 。系统将他们从系统消息队列中移走,检查他们的目标窗口 , 然后将他们发送到创建目标窗口的线程的消息队列 。线程消息队列接收由这个线程创建的所有窗口的鼠标键盘消息 。线程删除消息系统调用窗口过程进行处理 。
WM_PAINT是一个例外,系统总是将消息Post在消息队列的末尾 。这样保证窗口以先进先出的顺序接受消息 。然而, 仅当没有其他消息时WM_PAINT才被传递窗口过程 。同一个窗口的多个 WM_PAINT被合并成一个 WM_PAINT 消息, 合并所有的无效区域到一个无效区域 。合并WM_PAIN减少了刷新窗口的次数 。
系统通过填充MSG结构并将它复制到消息队列来发送消息到线程队列 。MSG结构包括:窗口句柄,消息标识符,两个消息参数 。消息被posted的时间, 和鼠标的位置 。线程可以使用PostMessage和PostThreadMessage来给发送消息到自己消息队列或者另一个线成的消息队列 。
应用程序可以使用GetMessage从消息队列删除消息 。可以使用 PeekMessage来检查一个消息而不删除它 。这个函数将消息队列的消息填充到MSG结构 。
在从消息队列删除了一个消息,应用程序可以使用DispatchMessage使系统将消息发送到窗口过程来处理 。DispatchMessage拥有一个指向由GetMessage或者PeekMessage填充的MSG结构的指针,传递窗口句柄,消息标识符 , 消息参数给窗口过程 。但它并不传递消息发送的时间和鼠标的位置,应用程序可以通过GetMessageTime和GetMessagePos来得到这些信息 。
线程可以使用WaitMessage将控制交给其他线程当消息队列中没有他的消息队烈时,这个函数挂起线程,并不返回,直到新的消息放置于消息队列中 。
你可以调用SetMessageExtraInfo函数来关联一个值到当前线程的消息队列 。调用GetMessageExtraInfo来得到这个与最后一次通过GetMessage或者PeekMessaage获得的消息关联得值 。
Nonqueued Messages
非入队消息即直接发送到窗口过程的消息,绕过系统队列和线程消息队列 。系统发送非入队消息通知一个窗口事件 , 例如,当用户激活一个新的应用程序窗口,系统发送WM_ACTIVATE, WM_SETFOCUS, and WM_SETCURSOR 。这些消息通知窗口它被激活了,键盘输入被直接传递到窗口,鼠标在当前窗口内移动 。非入队消息也可以由当应用程序调用系统函数产生 。例如,当程序调用SetWindowPos系统发送WM_WINDOWPOSCHANGED消息 。
一些函数也发送非入队消息如 BroadcastSystemMessage, BroadcastSystemMessageEx, SendMessage, SendMessageTimeout, and SendNotifyMessage.
Message Handling
应用程序必须移除和处理被post到消息队列的消息 。单线程应用程序通常在WinMain使用消息循环来移除和分发消息到何时窗口过程来处理 。多线程应用程序可以在每一个创建窗口的线程中中包含消息循环 。
Message Loop
A simple message loop consists of one function call to each of these three functions: GetMessage, TranslateMessage, and DispatchMessage. Note that if there is an error, GetMessage returns -1 -- thus the need for the special testing.
Show Example
MSG msg;
BOOL bRet;
while( (bRet = GetMessage( msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(msg);
DispatchMessage(msg);
}
}
GetMessage 函数从消息队列获得一个消息并将它复制到MSG结构 。他返回一个非0值,除非遇到WM_QUIT消息 。否则它返回0然后结束循环 。In a single-threaded application, ending the message loop is often the first step in closing the application. 应用程序可以使用PostQuitMessage来结束自己的消息循环 。通常在主窗口的WM_DESTROY消息中调用 。
如果你将一个窗口句柄作为第二个参数传入GetMessage,那么只有指定窗口的的消息可以从队列中获得 。GetMessage也可以从消息队列中过滤消息只接受消息队列中落在范围内的消息 。详细见消息过滤 。一个线程循环必须包括TranslateMessage如果线程接受键盘的字符输入 。每一次用户按键系统产生虚拟键消息,一个虚拟键消息包含虚拟键用来标志那个键被按下,并不是他的字符值,要获得这个值消息循环必须调用TranslateMessage,用于将虚拟键转换为字符消息WM_CHAR然后将它放回应用程序消息队列 。通过将它转发到窗口过程,字符消息被删除 。
DispatchMessage 函数分发消息到MSG结构中的窗口句柄关联的窗口过程 。如果窗口句柄是HWND_TOPMOST,DispatchMessage分发消息到系统中的所有的top-level窗口的窗口过程 。如果句柄是NULL,DispatchMessage不做任何事 。
应用程序得主线程在初始化,创建至少一个窗口后启动它的消息循环,一旦启动消息循环持续从线程队列中获得消息,然后分发他们到合适的窗口 。消息循环在通过GetMessage得到WM_QUIT并将他从队列中删除后结束 。
一个消息都列仅需要一个消息循环, 即使程序包含很多窗口 。DispatchMessage 总是分发消息到合适的窗口 , 这是因为MSG结构包含消息所属的窗口的句柄 。
你可以用各种方式修改消息循环 。例如,从消息队列获得消息消息但不把他们分发到窗口中去 。当应用程序发送一个消息但不指定窗口时是有用的 。你可以用GetMessage获得一个特定的消息,而保留其他消息在消息队列 。当你需要改变先进先出的顺序时是有用的 。
应用程序使用加速键必须将键盘消息转换为WM_COMMAND消息 。所以消息循环必须包括TranslateAccelerator函数 。详细信息参见加速键 。
如果线程使用非模态对话框,消息循环必须包括 IsDialogMessage 以使非模态对话框获得键盘输入 。
Window Procedure
窗口过程是一个用于处理所有发送到这个窗口的消息的函数 。任何一个窗口类都有一个窗口过程 。同一个类的窗口使用同样的窗口过程来响应消息 。
系统发送消息给窗口过程将消息数据作为参数传递给他,窗口过程使用参数产生合适行为 。
一个窗口过程通常不忽略消息,如果他不处理,它会将消息传回到执行默认的处理 。窗口过程通过调用DefWindowProc来做这个处理 。窗口过程必须return一个值作为它的消息处理结果 。大多数窗口只处理小部分消息和将其他的通过DefWindowProc传递给系统做默认的处理 。
因为窗口过程是同一个类的窗口共享的,它可以为不同的窗口处理消息 。通过检查消息中的窗口句柄来找到被消息影响的窗口 。详细信息请看Window Procedures 。
Message Filtering
应用程序可以从消息队列选择特定的消息 。使用GetMessage或者PeekMessage并指定一个消息过滤器 。这个过滤器是一个消息标识符的范围或者是一个窗体句柄,或者两者同时指定 。GetMessage和PeekMessage使用过滤器来选择从消息队列中获得那些消息 。当应用程序要查找一个后入消息队列的消息是很有用 。
一个应用程序过滤消息时必须保证符合过滤条件的消息能被发送 。例如应用程序在窗口中过滤WM_CHAR并不能得到键盘输入,GetMessage并不返回 。这将挂起应用程序 。
Posting and Sending Messages
应用程序可以post和send消息 , 通过将消息复制到消息队列即post消息 , send消息将消息数据作为参数直接传递到窗口过程 。
可以使用PostMessage来post消息 , SendMessage,BroadcastSystemMessage, SendMessageCallback, SendMessageTimeout, SendNotifyMessage, or SendDlgItemMessage来send消息 。
Posting Messages
应用程序post消息通知指定窗体执行任务 。PostMessage可以创建MSG结构并将它Copy到消息队列 。消息循环最终捕获消息并分发到合适的窗口过程 。
给PostMessage传递一个NULL句柄不指定哪一个窗口,这个消息就被发送到当前线程消息队列 , 应用程序必须在消息处理中处理这个消息 。这是为整个应用程序发送消息的一个方法 。
偶尔你可以使用HWND_TOPMOST 这个参数作为句柄参数向所有的top-level窗口发送消息 。
当消息队列满的时候PostMessage并不发送消息,应用程序需要检查PostMessage函数的返回值来确定消息是否被发送 , 或者没有需要重发 。
Sending Messages
通过Send消息来通知窗口过程立即执行任务 。SendMessage将消息发送给指定窗口的窗口过程 。函数将等待窗口过程处理完才返回一个消息结果 。父窗口和子窗口通常使用Send消息来互相通讯 。例如 , 一个父窗口拥有以一个文本框作为它的子窗口 , 它可以通过发送消息到子窗口来给文本框设置文字 。子窗口也可将文字被用户改变的消息发送给父窗口 。
SendMessageCallback也将消息发送给指定窗口的窗口过程 , 但是他立即返回 。在窗口过程处理完消息后,系统调用指定的回调函数,回调函数的详细资料参见SendAsyncProc
偶尔,你可以发送消息系统中到所有的top-level窗口,例如,应用程序改变了系统时间 。它必须以HWND_TOPMOST作为句柄参数发送一个WM_TIMECHANGE 消息通知所有的top-level窗口,你也可以将lpdwRecipients 指定为BSM_APPLICATIONS 用BroadcastSystemMessage函数向所有应用程序广播 。
可以使用InSendMessage或者InSendMessageEx函数,窗口过程可以判断它处理的消息是否是由其他线程调用SendMessage发送过来的 。This capability is useful when message processing depends on the origin of the message.
Message Deadlocks
一个线程可以调用SendMessage想其他线程发送消息,这个线程不能继续执行直到获得消息得窗口过程返回 。如果接受消息的线程处理消息时yields控制,发送线程的消息将永远得不到执行 , 因为他在等待SendMessage返回 。如果接受线程和发送线成语同一个消息队列联系起来,它可能导致消息死锁 。
Note that the receiving thread need not yield control explicitly; calling any of the following functions can cause a thread to yield control implicitly.
接受线程不需要明确yield控制,下面任何一个函数回导致一个线程明确yield控制 。
· DialogBox
· DialogBoxIndirect
· DialogBoxIndirectParam
· DialogBoxParam
· GetMessage
· MessageBox
· PeekMessage
· SendMessage
为了避免潜在的死锁,可以使用SendNotifyMessage 或者 SendMessageTimeout,否则窗口过程,将用InSendMessage或者InSendMessageEx判断消息是否由另一个线程发送过来 。当调用前面任何一个函数窗口过程将首先调用InSendMessage或者InSendMessagEx,如果函数返回true窗口过程必须在引起线程yeild控制前调用ReplyMessage。
Broadcasting Messages
每一个消息包括消息标识符和两个参数 , wParam和lParam,消息标识符是唯一的代表这个消息的含义 。参数提供与消息相关的额外的信息,但是wParam参数通常是一个类型值提供更多的消息信息 。
消息广播是简单的将消息发送到系统中的多个接收者 。使用BroadcastSystemMessage函数来广播消息,你必须指定一个或者多个接收者类型,这些类型可以是applications, installable drivers, network drivers, and system-level device drivers 。系统将消息发送给指定类型的所有成员 。
系统广播消息来响应系统设备驱动程序或者组件的变化 。驱动程序或相关组件广播消息给应用程序和其他组件以通知他们这些变化 。例如,负责磁盘响应的组件广播消息只要软盘驱动程序发现媒体的变化,如当用户将磁盘插入驱动器 。
系统按一下顺序广播消息给接收者c语言回调函数中的句柄:系统级的设备驱动程序,网络驱动程序,installable drivers,和应用程序 。意味着如果系统级设备驱动程序作为接收者总是第一个有机会来响应消息 。在接受者类型中,没有一个驱动程序能保证在其他驱动程序前接受一个消息 。即一个给特定驱动程序的消息必须有一个全局唯一的标志使其他不关心这个消息的驱动程序不处理它 。
你也可以广播消息给所有顶层窗口通过在SendMessage等函数中指定HWND_BROADCAST 。
应用程序通过顶层窗口的窗口过程来接收消息 。消息不发送到子窗口 。服务可以接收消息通过窗口过程或者他们的服务控制函数 。
Query Messages
你可以创建自定义的消息使用它们来调整你的应用程序和其他组件之间的行为 。这个非常有用如果你已创建你自己的installable drivers和系统机设备驱动程序 。你的驱动程序和使用这个驱动程序的应用程序可以通过自定义消息互相传递信息 。
To poll recipients for permission to carry out a given action, use a query message.你可以通过在dwFlags参数中设置BSF_QUERY调用BroadcastSystemMessage 。每一个query message的接收者必须返回TRUE来将消息发送到下一个接收者 。如果任何一个接收者返回BROADCAST_QUERY_DENY,广播立即停止函数返回0 。
Windows 95/98/Me: 你可以创建广播和处理消息的installable drivers 。一个installable drivers是一个导出DriverProc函数的dll 。驱动程序通过它的DriverProc来接收消息 。Installable drivers典型的用来支持多媒体设备,例如sound boards , 也可以用于其他设备和目的 。
Windows 95/98/Me: 网络驱动程序是给应用程序提供以下支持的dlls 。系统级设备驱动程序是系统特定的提供直接访问和管理计算机硬件的可执行组件 。这些组件如何处理系统消息超出了这篇文章的范围 。
对于一个只懂C语言得人来说,怎么理解句柄?句柄是一个序号,它不是一个内存地址 。
它用于管理Windows内核对象,比如用户打开一个文件,Windows即会建立一个文件内核对象 , 所谓内核对象就是一块内存结构,里面有文件路径,文件大小,当前文件指针等等信息 。Windows系统会打开很多的文件 , 因此就有很多的文件内核对象,同样Windows系统还会建立其它的类型的很多很多的内核对象 。如何管理这么多的内核对象 呢?Windows通过建立一个叫做句柄表的东西,用于记录内核对象的地址 。表中每一个元素,都是一个内核对象的起始地址,然后给每一个对象对应一个序号,此序号即为句柄 。
//句柄表类似于下面的结构,像0、1、2这样的序号即为句柄
----------------------------------------------------
0第一个内核对象的地址
1第二个内核对象的地址
2第三个内核对象的地址
----------------------------------------------------
句柄是什么意思句柄(handle) , 有两种解释
1,句柄是一种特殊的智能指针。当一个应用程序要引用其他系统(如数据库、操作系统)所管理的内存块或对象时 , 就要使用句柄 。
2,整个Windows编程的基础 。一个句柄是指使用的一个唯一的整数值,即一个4字节长的数值,来标识应用程序中的不同对象和同类中的不同的实例,诸如 , 一个窗口,按钮,图标,滚动条 , 输出设备,控件或者文件等 。
扩展资料:
注意事项:
1,内核对象句柄,是用来标识某个内核对象的一个ID 同一个对象的该id对于每个进程是不同的 , 具体如何实现是ms不公开的算法,以下是一个近似的 , 可能的算法 。
2,进程创建时 , windows系统为进程构造了一个句柄表 。
3,当该进程希望获得一个内核对象句柄或者创建一个内核对象从而获得该对象句柄时 。
4,系统会将在句柄表中增加一个表项 , 表项的内容中存储了指向目标内核对象的指针 。
同时,系统返回这个表项在句柄表中的索引作为句柄 。
参考资料:百度百科——句柄
句柄是什么?它中C语言编程中有何作用?差不多如此c语言回调函数中的句柄了 。在16位windows时期c语言回调函数中的句柄,句柄差不多也是对象在内存中分配c语言回调函数中的句柄的初始地址;但在win32,标识对象用一个32位c语言回调函数中的句柄的c语言回调函数中的句柄 , 唯一的整数.然后系统同这个对象打交道,主要就通过这个handle.
求助:C语言如何输出句柄句柄就是一种资源的序号,一般是个无符号整数而已,比如文件句柄,就是系统提供一组可以打开文件的数据结构(实际上是结构数组) , 句柄就是数组下标 。
所谓输出句柄,你可以将句柄当作函数调用的返回值 , 或者打印出来看也不是不可以 。
【c语言回调函数中的句柄 c回调函数应用场景】c语言回调函数中的句柄的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于c回调函数应用场景、c语言回调函数中的句柄的信息别忘了在本站进行查找喔 。

    推荐阅读