//窗體可以為其擁有的組件來處理鍵盤消息。
if (Message.Msg >= WM_KEYFIRST) and (Message.Msg <= WM_KEYLAST) then
begin
Form := GetParentForm(Self);
if (Form <> nil) and Form.WantChildKey(Self, Message) then Exit;
end
//關於鼠標的消息
else if (Message.Msg >= WM_MOUSEFIRST) and (Message.Msg <= WM_MOUSELAST) then
begin
//如果組件不可以接受和處理雙擊消息,就將雙擊消息映射為單擊消息。
if not (csDoubleClicks in ControlStyle) then
case Message.Msg of
WM_LBUTTONDBLCLK, WM_RBUTTONDBLCLK, WM_MBUTTONDBLCLK:
Dec(Message.Msg, WM_LBUTTONDBLCLK - WM_LBUTTONDOWN);
end;
case Message.Msg of
WM_MOUSEMOVE: Application.HintMouseMessage(Self, Message);//如果是鼠標移動的消息,則出現hint窗口
WM_LBUTTONDOWN, WM_LBUTTONDBLCLK://如果是左鍵被按下,或者雙擊,如果是自動拖動模式,則開始拖動,並將左鍵按下的狀態加入組件的狀態。
begin
if FDragMode = dmAutomatic then
begin
BeginAutoDrag;
Exit;
end;
Include(FControlState, csLButtonDown);
end;
WM_LBUTTONUP:
Exclude(FControlState, csLButtonDown); //如果是左鍵放開,則將左鍵按下的狀態剔除。
else
with Mouse do
if WheelPresent and (RegWheelMessage <> 0) and //如果鼠標有滾輪,並且滾輪滑動時發出了消息
(Message.Msg = RegWheelMessage) then
begin
GetKeyboardState(KeyState); //將256虛擬鍵的狀態拷貝到緩存中去
with WheelMsg do //填充記錄
begin
Msg := Message.Msg;
ShiftState := KeyboardStateToShiftState(KeyState);
WheelDelta := Message.WParam;
Pos := TSmallPoint(Message.LParam);
end;
MouseWheelHandler(TMessage(WheelMsg)); //派發鼠標滾輪的消息
Exit;
end;
end;
end
else if Message.Msg = CM_VISIBLECHANGED then
with Message do
SendDockNotification(Msg, WParam, LParam); //處理自定義消息
Dispatch(Message); //派發未處理的消息
end;
但是只有TWinControl可以獲得焦點:
procedure TWinControl.WndProc(var Message: TMessage);
var
Form: TCustomForm;
begin
case Message.Msg of
WM_SETFOCUS: //設置控件的焦點
begin
Form := GetParentForm(Self);
if (Form <> nil) and not Form.SetFocusedControl(Self) then Exit;
end;
WM_KILLFOCUS:
if csFocusing in ControlState then Exit;
//當鼠標有活動的時候發出該消息,如果鼠標沒有被捕捉到,則消息發往鼠標下面的那個窗口,否則消息將發往捕捉到鼠標的那個窗口。
WM_NCHITTEST:
begin
inherited WndProc(Message); //調用父類的處理方法
//如果窗體被擋住並且在指定的點沒有控件,則返回結果為在clIEnt區。
if (Message.Result = HTTRANSPARENT) and (ControlAtPos(ScreenToClIEnt(
SmallPointToPoint(TWMNCHitTest(Message).Pos)), False) <> nil) then
Message.Result := HTCLIENT;
Exit;
end;
WM_MOUSEFIRST..WM_MOUSELAST:
if IsControlMouseMsg(TWMMouse(Message)) then //鼠標消息是否直接發往組件的窗體子組件
begin
{ Check HandleAllocated because IsControlMouseMsg might have freed the
window if user code executed something like Parent := nil. }
if (Message.Result = 0) and HandleAllocated then
DefWindowProc(Handle, Message.Msg, Message.wParam, Message.lParam);//調用默認的的消息處理方法對該消息進行默認處理。
Exit;
end;
WM_KEYFIRST..WM_KEYLAST:
if Dragging then Exit;
WM_CANCELMODE:
if (GetCapture = Handle) and (CaptureControl <> nil) and
(CaptureControl.Parent = Self) then
CaptureControl.Perform(WM_CANCELMODE, 0, 0);
end;
inherited WndProc(Message);
end;
TApplication在程序中發揮著重要的作用:
Application.Run;
procedure TApplication.Run;
begin
FRunning := True;
try
AddExitProc(DoneApplication);
if FMainForm <> nil then
begin
case CmdShow of
SW_SHOWMINNOACTIVE: FMainForm.FWindowstate := wsMinimized;
SW_SHOWMAXIMIZED: MainForm.Windowstate := wsMaximized;
end;
if FShowMainForm then
if FMainForm.FWindowstate = wsMinimized then
Minimize else
FMainForm.Visible := True;
//一個消息循環直到Terminated為True時才退出。
repeat
try
HandleMessage;
except
HandleException(Self);
end;
until Terminated;
end;
finally
FRunning := False;
end;
end;
procedure TApplication.HandleMessage;
var
Msg: TMsg;
begin
if not ProcessMessage(Msg) then Idle(Msg);
end;
function TApplication.ProcessMessage(var Msg: TMsg): Boolean;
var
Handled: Boolean;
begin
Result := False;
if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then //從現成的消息循環中取出消息並放入指定的消息結構中。
begin
Result := True;
if Msg.Message <> WM_QUIT then //如果不是退出消息則進行相應的處理
begin
Handled := False;
if Assigned(FOnMessage) then FOnMessage(Msg, Handled);
if not IsHintMsg(Msg) and not Handled and not IsMDIMsg(Msg) and
not IsKeyMsg(Msg) and not IsDlgMsg(Msg) then
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end
else
FTerminate := True;
end;
end;