{ Custom WindowProc function }
function WindowProc(hWnd, uMsg, wParam, lParam: Integer): Integer; stdcall;
begin
  Result := DefWindowProc(hWnd, uMsg, wParam, lParam);
  { Checks for messages }
  if (lParam = Button1) and (uMsg = WM_COMMAND) then
    CheckPassword;
  if uMsg = WM_DESTROY then
    Halt;
end;begin
  { ** Register Custom WndClass ** }
  Inst := hInstance;
  with WinClass do
  begin
    style              := CS_CLASSDC or CS_PARENTDC;
    lpfnWndProc        := @WindowProc;
    hInstance          := Inst;
    hbrBackground      := color_btnface + 1;
    lpszClassname      := 'AG_TESTWINDOW';
    hCursor            := LoadCursor(0, IDC_ARROW);
  end; { with }
  RegisterClass(WinClass);  { ** Create Main Window ** }
  Handle := CreateWindowEx(WS_EX_WINDOWEDGE, 'AG_TESTWINDOW', 'Amigreen TestWindow 1.00',WS_VISIBLE or WS_SIZEBOX or WS_CAPTION or WS_SYSMENU,363, 278, 305, 65, 0, 0, Inst, nil);  { ** Create a button ** }
  Button1 := CreateWindow('Button', 'OK', WS_VISIBLE or WS_CHILD or BS_PUSHLIKE or BS_TEXT,216, 8, 75, 25, handle, 0, Inst, nil);  { ** Create a label (static) ** }
  Label1 := Createwindow('Static', '', WS_VISIBLE or WS_CHILD or SS_LEFT,
               8, 12, 76, 13, Handle, 0, Inst, nil);  { ** Create an edit field ** }
  Edit1 := CreateWindowEx(WS_EX_CLIENTEDGE, 'Edit', '', WS_CHILD or WS_VISIBLE or WS_BORDER or ES_PASSWORD, 88, 8, 121, 21, Handle, 0, Inst, nil);
......  { ** Message Loop ** }
  while(GetMessage(Msg,Handle, 0, 0)) do
  begin
    TranslateMessage(msg);
    DispatchMessage(msg);
  end; { with }
end.请问我下面的理解对否?
1、通过WinClass创建一个句柄为handle的主窗口,属于进程Inst。
2、button、label和edit也都是窗口,为什么不需要向系统注册?不注册,怎么找到它们的窗口处理函数,怎么去处理它们的消息?
3、假设有无数个应用程序(进程),触发了无数个消息,系统是用一个消息队列来管理,还是给每一个应用程序(进程)都管理一个消息队列。也就是getmessage读的消息队列里有没有其他应用程序(进程)的消息?
4、GetMessage(Msg,Handle, 0, 0)是读取与handle主窗口有关的消息,而GetMessage(Msg,0, 0, 0)是读取本进程中所有的消息?
5、DispatchMessage(msg)是将消息派发到窗口,也就是调用msg.handle句柄窗口的窗口函数来处理该消息。主窗口可以通过lpfnWndProc使系统找到WindowProc来处理主窗口消息。但button、label和edit的消息了。难道都通过windowproc来处理?
6、sendmessage函数也就相当DispatchMessage(msg)这一步了。

解决方案 »

  1.   

    2.不是不用注册,而是一些标准的Windows控件在系统里已经注册了。它们的窗口处理函数是在一个大的WindowProc,也即窗口的WindowProc。
    3.每一个应用程序都有消息队列。
    6.SendMessage也就是直接把消息发送到指定的窗口过程,等消息处理完毕才返回。这也只是我的理解,不一定准确。还是看看李维的《Inside VCL》吧,里面对VCL消息机制讲的很清楚。Windows消息处理过程请参考《Windows程序设计》。
      

  2.   

    sendmessage 或 postmessage 建议使用postmessage
    还有一个广播功能, 可以向当前所有窗口发消息
    只有注册过该消息号的窗口才能接受
    楼主可以看看所有消息的help
      

  3.   

    Windows消息的流程:
    Windows->Delphi Application->TWinControl
    MainWndProc->WndProc->Dispatch->Handler
    首先,Windows是一个基于消息的系统,应用程序运行时,程序中每个有窗口句柄的控件都会在Windows中注册一个窗口过程,这个过程就是上面的MainWndProc。消息到达MainWndProc后,由MainWndProc使用VCL的消息派遣机制来处理这个消息。
    那么,消息是如何到达MainWndProc中的呢?每个Delphi Application运行后(Application.Run)调用ProcessMessages方法,由这个方法实现一个消息循环。在这个方法内部调用了另一个TApplication的方法ProcessMessage,它从Windows中提取属于本Application的消息,如果提取的消息是WM_QUIT,则中止程序。每当提取一个消息,就会触发OnMessage事件并调用方法DispatchMessage。在OnMessage事件中如果用户已经编写了处理消息的代码,则运行这些代码,消息到此结束。如果在OnMessage中没有处理,则调用DispatchMessage。
    function DispatchMessage(const lpMsg: TMsg): Longint; stdcall
    在lpMsg中有消息正文和消息需要发往的窗口句柄,该方法将消息发送到控件的MainWndProc,从此,消息进入了VCL自己的消息处理机制,从而在TWinControl内部实现消息处理。在MainWndProc中实际上是调用了WindowProc方法。WindowProc又等价于WndProc,所以实际上是调用了WndProc。WndProc让控件能对一些特殊的消息进行必要响应,比如focus,mouse,keyboard等。WndProc将消息传入Dispatch,Dispatch实现消息派遣,它首先在本类中查找与消息对应的消息方法,如果没有,则在父类、祖父类中找,直到TObject,如果TObject中也没有,那么调用DefaultHandler,DefaultHandler保证所有消息都能被处理。到此,整个消息机制结束。
      

  4.   

    在VCL中每一个窗口控件创建时(button,Edit),都向系统注册了MainWndproc,通过dispatchmessage从而能找到相应窗口句柄的MainWndProc?在Application中的Onmessage能捕捉到所有隶属于Application窗口的消息,比如主窗口、主窗口上的button和Edit,而button的MainWndProc只能捕捉到和button有关的消息。TGraphicControl控件不会向系统注册MainWndproc,而是通过其父的TWinControl控件发送内部消息。但TWinControl是如何发送内部消息给其子TGraphicControl控件的?顶上面的那个纯Api程序,Button和edit没有向系统注册窗口函数,照juliens(星星球爱思纯^_^) 说说标准控件系统已注册,那么我要响应button和edit的消息,只能将其子类化了。
      

  5.   

    1、是的2、被注册的是类,而不是窗口的实例(也就是WindowProc)。至于其他的Edit什么的,如上面所说,已经被Windows自己注册了。4、没有试过……5、所谓窗口其实并不只是我们日常拖得动的那个东西。所有拥有Handle和WindowProc的对象实例都可以称之为窗口。6、SendMessage是一个同步执行的方法。相当于你直接调用目标窗口的WindowProc。所以在通常的消息处理函数中可以使用SendMessage而不会造成死锁。Application的ProcessMessages其实也是类似的执行机制。
      

  6.   

    关于SendMessage再补充一点。因为是阻塞式的执行,所以对于同一个消息来说SendMessage是不能嵌套的。比如说在WM_MYMESSAGE的处理方法中再次调用SendMessage(..., WM_MYMESSAGE, ...),否则就会出现堆栈溢出。但也正因为是阻塞式执行,所以它返回很快,不用等待在它之前发出的其他的消息处理完毕。所以也经常被用来获取或设置控件的一些属性,比如ComboBox的下拉框的宽度等等。但是异步执行的PostMessage就没有这个问题。你可以在WM_MYMESSAGE的处理方法中再次调用PostMessage(..., WM_MYMESSAGE, ...)而不用担心任何的溢出。
      

  7.   

    4.当窗口句柄为0是接受被线程内所有窗体的消息。比如你有一个窗体句柄是1000,而窗体中又有一个字窗体(比如按钮,memo等等)它的句柄是1001,当你设定窗体句柄是0的时候,你接受的不仅是1000窗体的消息,同时也将接受1001子窗体的消息。因为这两个窗体在同一个线程中。
    5.button、label和edit有自己的默认窗口过程处理函数。此例子中,使他们的父窗口先截取了传给他们的消息。
    6.sendmessage是向窗体发送消息,窗体通过getmessage接受消息,但是getmessage此时并没有把消息传递给窗体过程,传递任务是通过DispatchMessage进行的。