消息结构:
MyMessage = packed recordhwnd: HWND; //应用程序窗口识别值
MessageID: Longint;
wParam: Longint;
lParam: Longint;
time: Longint;
pt: TPoint;
end;
//窗口定义
MyWindowClassInfo = packed record
style : UINT; //窗口类型
iWidth: Intger; //窗口高度
iHeight: Integer; //宽度
lpfnwndProc: Pointer; //代表应用程序可以把任何的函数地址指定给此字段以代表可以处理此窗口消息 的函数
hIcon: HICON;
hCursor: HCURSOR; //窗口使用的光标种类
hbrBackground: HBRUSH;
lpszMenuName: PAnsichar;
lpszClassName: PAnsichar; //窗口的类名称
hIconSm : HICON;
这三个问题如果可以回答的完美,那么delphi(以及windows)的消息处理流程就基本到家了。
1、 应用程序可能拥有许多窗口,如何把触发的消息分发给正确的窗口去处理?
答:在消息结构中添加窗口ID。
2、把消息分派给应用程序或是窗口是如何办到的?
答:在执行环境将事件转换为消息记录后,应用程序会将此记录提供给窗口的回调函数(即上面窗口结构中的lpfnwndProc),我们可以看到lpfnwndProc为指针类型,此即为处理消息的函数的地址。
3、当分派了消息给窗口之后,窗口要如何处理次消息?答:第二个问题只是说明了应用程序会将此记录提供给窗口的回调函数,但回调函数由谁调用呢,对了,有执行环境调用。这样此消息就算顺利的被执行了。
getMessage translateMessage dispatchmessage此三个函数为消息处理函数。
撰写windows应用程序包含了四个简单的步骤:
1、定义窗口类的内容,以决定窗口的创建格式以及回调函数;
2、注册窗口类;
3、创建窗口;
4、进入窗口消息处理循环以便让回调函数处理窗口消息,直到应用程序结束为止;
例子:
program Project1;
uses
Forms,windows,Messages,sysUtils,
Unit1 in 'Unit1.pas' {Form1};
const
AppName = 'ddd';
{$R *.res}
function WindowProc(window: HWND;
AMessage: UINT;
WParam: WPARAM;
LParam: LPARAM):LRESULT; stdcall;export;
var
dc: HDC;
ps: TPaintStruct;
r : TRect;
begin
WindowProc := 0;
case AMessage of
WM_PAINT:
begin
dc := BeginPaint(window,ps);
GetClientRect(window,r) ;
DrawText(dc,'使用pascal撰写的Native Windows 程序',1,r,DT_SINGLELINE or DT_CENTER or DT_VCENTER);
EndPaint(window,ps);
Exit;
end;
WM_DESTROY:
begin
PostQuitMessage(0);
Exit;
end;
end;
WindowProc := DefWindowProc(window,AMessage,WParam,LParam);
end;
{ Register the window class}
function WinRegister: Boolean;
var
WindowClass: WNDCLASS;
begin
WindowClass.style := CS_VREDRAW or CS_HREDRAW;
WindowClass.lpfnWndProc := TFNWndProc(@WindowProc);
WindowClass.cbClsExtra := 0;
WindowClass.cbWndExtra := 0;
WindowClass.hInstance := SYSTEM.MainInstance;
WindowClass.hCursor := LoadCursor(0,IDC_ARROW) ;
WindowClass.hIcon := LoadIcon(0,IDI_APPLICATION) ;
WindowClass.hbrBackground := GetStockObject(WHITE_BRUSH);
WindowClass.lpszMenuName := nil;
WindowClass.lpszClassName := AppName;
Result := RegisterClass(WindowClass) <> 0 ;
end;
{ create the window class}
function WinCreate: HWND;
var
hWindow: HWND;
begin
hWindow := CreateWindow(AppName,'dddddddddd',WS_OVERLAPPEDWINDOW,cw_UseDefault,
cw_UseDefault,cw_UseDefaultcw_UseDefault,0,0,system.MainInstance,nil);
if hWindow <> 0 then
begin
ShowWindow(hWindow,CmdShow);
ShowWindow(hWindow,SW_SHOW);
UpdateWindow(hWindow);
end;
Result := hWindow;
end;
var
AMessage: TMsg;
hWindow: HWND;
begin // 主程序入口
if not WinRegister then
begin
MessageBox(hWindow,'',nil,MB_OK);
Exit;
end;
hWindow := WinCreate;
if LongInt(hWindow) = 0 then
begin
MessageBox(hWindow,'',nil,MB_OK);
Exit;
end;
while GetMessage(AMessage,0,0,0) do
begin
TranslateMessage(AMessage);
DispatchMessage(AMessage);
end;
Halt(AMessage.wParam);
end;
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.