[delphi] windows消息

windows消息的結構

  TMsg = packed record

    hwnd: HWND;//窗口句柄

    message: UINT;//消息標識

    wParam: WPARAM;//

    lParam: LPARAM;//

    time: DWORD;//消息創建的時間

    pt: TPoint;//消息創建時鼠標所在位置

  end;


WM_KEYDOWN,WM_KEYUP, WM_KEYPRESS: KEYPress消息不同之處在於只有對應有ascii碼的按鍵纔會產生這個消息


windows消息流程

1.系統中產生事件

2.windows把這個事件翻譯成消息,並放入消息隊列

3.應用程序從消息隊列中接收到這個消息,把它放到TMsg記錄中

4.應用程序把消息傳遞給一個適當的窗口的窗口過程

5.窗口過程響應這個消息並處理

步驟3,4就構成了應用程序的消息循環。


delphi把windows的TMsg記錄中的信息映射爲TMessage記錄:

TMessage = record
  Msg: Cardinal;
  case Integer of
   0:( WParam: LongInt;
       LParam: LongInt;
       Result: LongInt);
   1:( WParamLo: Word;
       WParamHi: Word;
       LParamLo: Word;
       LParamHi: Word;
       ResultLo: Word;
       ReslutHi: Word);
end;


除此之外,delphi爲每個windows消息定義了一個特殊的消息記錄,方便使用,例如一個鼠標消息:

TWMMoust = record
  Msg: Cardinal;
  Keys: LongInt;
  case: Integer of
  0:(XPos, YPos: SamllInt);
  1:(Pos: TSmallPoint; Result: LongInt);
end;


MessageBeep(): 窮人的調試器


對消息中的Result賦值:

典型的例子是WM_CTLCOLOR,處理這個消息時,windows期望返回一個畫刷的句柄,

所以需要在消息處理之後對result賦值

procedure TFrom1.WMCtlColor(var Msg: TWMCtlColor);
var
  BrushHand: hBrush;
begin
  inherited;
  // todo: 創建一個畫刷,放入BrushHand
  Msg.Result := BrushHand;
end;

Application.OnMessage

OnMessage相應的是從消息隊列中檢索到的消息,所以SendMessage發送的消息會繞過消息隊列,就不會觸發OnMessage事件

子類化

用自己的窗口過程代替Application的窗口過程,當在自己的窗口過程處理完成呢過後,把消息再傳遞給原窗口。這個過程就叫 子類化

1.使用SetWindowLong()來指定與i個新的窗口過程:

  聲明:

function NewWndProc(Handle: hWnd; Msg, WParam, LParam: LongInt): Longint; stdcall;
使用
OldWndProc := Pointer(SetWindowLong(Application.Handle, gwl_WndProc, Integer(@NewWndProc)));
來設置。

2.也可以使用Delphi方法來代替上面的NewWndProc

需要使用MakeObjectInstance()來處理一下這個delphi的方法

  NewProc := MakeObjectInstance(self.NewWndProc);
  OldWProc := Pointer(SetWindowLong(Application.Handle, GWL_WNDPROC, Integer(NewProc)));

3.HookMainWindow()

這個函數能把一個自定義的消息處理過程插入到TApplication的WndProc方法之前








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章