刚刚看了inside vcl,觉得里面写的太散了,产生不少疑问!
比如点窗体form1上的button1,则发生wm_buttondown,我想应该从button1的wndproc的窗口处理函数中去寻找处理函数,找不到的话就往父类找,继而dispatch,而书上的流程是这样的:队列--initwndproc-stdwndproc--tform.wndproc--twincontrol.wndproc--tcontrol.wndproc--dispatch--form1.button1.click不明白的是这个消息是发生于button1的,应用程序找到的句柄也应该是button1,所以应该用button1.wndproc,为什么还要用tform.wndproc!谢谢解答!

解决方案 »

  1.   

    inside vcl里写得很清楚,点击Button消息是只在Button的Wndproc处理,但VCL内部发送了一个通知消息,发送到父窗口,所以form能够产生click事件
      

  2.   

    你学过Windows编程吗?
    一切的消息都传向窗口过程,然后再由窗口过程来处理,当按钮点下的时候,其实窗口是收到了
    WM_COMMAND消息,窗口过程再根据两个附加参数来判断是那个子窗口(即控件)触发了消息。而VCL对其做了封装,使子窗口自己能够处理消息。你可以自己做一个实验,载获主窗体的WM_COMMAND消息,那么当你点下按钮等事件之后,WM_COMMAND就触发。
      

  3.   

    linzhengqun(风。为菜鸟服务)批评得对,我上面的说法的确不正确。今天我认真看了Inside VCL第5章第3节,现在再谈谈我的理解,不到之处,请大家批评指正。
    点击Button后,Button会触发两个消息wm_lbuttondown、wm_lbuttonup,消息经Tbuttoncontrol.wndproc-〉Twincontrol.wndproc到Tcontrol.wndproc然后Dispatch进行派发。TButton、TButtoncontrol都没有通过动态方法拦截处理这两个消息,最后在Tcontrol中被处理,也就是    
    procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;
    procedure WMLButtonUp(var Message: TWMLButtonUp); message WM_LBUTTONUP;
    通过分别调用DoMouseDown和domouseup两个静态方法,两者又分别调用了mousedown和mouseup两个动态方法,在mousedown和mouseup里就和onmousedown和onmouseup事件处理函数结合起来。点击Button后,wm_lbuttonup消息发生后,系统还会自动发出一个wm_command消息给其的主窗体,如果button在form1里,消息就给form1,如果button在panel1里,消息就给panel1。消息由form1(panel1)的wndproc后,最终经Tcontrol.wndproc的Dispatch派发,最后都是在TWincontrol类中被wmcommand动态方法处理。
    procedure TWinControl.WMCommand(var Message: TWMCommand);
    begin
      if not DoControlMsg(Message.Ctl, Message) then inherited;
    end;
    DoControlMsg方法中能够确认这个句柄为Message.ctl(也就是Button)是VCL封装组件,便将WM_Command这个消息转换为VCL内部消息CN_Command,通过perform方式调用Button的Wndproc进行处理。Button通过CNCommand动态方法
    procedure TButton.CNCommand(var Message: TWMCommand);
    begin
      if Message.NotifyCode = BN_CLICKED then Click;
    end;
    调用了Click方法,Click方法最终又继承了Tcontrol.click方法,TControl.click方法中将OnClick事件处理函数结合起来。总结
    Button的Onmousedown和OnMouseup事件处理函数是由Button自行发出消息自行调用。
    而OnClick事件处理函数是由主窗口发出消息经由VCL内部查找后转换成内部消息通知Button调用的。