标题：GetMessage
函数声明：
BOOL GetMessage（LPMSG lpMsg，HWND hWnd，UINT wMsgFilterMin，UINT wMsgFilterMax)
参数：
lpMsg：指向MSG结构的指针，该结构从线程的消息队列里接收消息信息。
hWnd：取得其消息的窗口的句柄。当其值取NULL时，GetMessage为任何属于调用线程的窗口检索消息，线程消息通过PostThreadMessage寄送给调用线程。
wMsgFilterMin：指定被检索的最小消息值的整数。
wMsgFilterMax：指定被检索的最大消息值的整数。
返回值：如果函数取得WM_QUIT之外的其他消息，返回非零值。如果函数取得WM_QUIT消息，返回值是零。如果出现了错误，返回值是-1。例如，当hWnd是无效的窗口句柄或lpMsg是无效的指针时。若想获得更多的错误信息，请调用GetLastError函数。
备注：
应用程序通常用返回值来确定是否终止主消息循环并退出程序。
GetMesssge只接收与参数hWnd标识的窗口或子窗口相联系的消息，子窗口由函数IsChild决定，消息值的范围由参数wMsgFilterMin和wMsgFilterMax给出。如果hWnd为NULL，则GetMessage接收属于调用线程的窗口的消息，线程消息由函数PostThreadMessage寄送给调用线程。GetMessage不接收属于其他线程或其他线程的窗口的消息，即使hWnd为NULL。由PostThreadMessage寄送的线程消息，其消息hWnd值为NULL。如果wMsgFilterMin和wMsgFilterMax都为零，GetMessage返回所有可得的消息（即，无范围过滤）。
常数 WM_KEYFIRST和WM_KEYLAST可作为过滤值取得与键盘输入相关的所有消息：常数WM_MOUSEFIRST和WM_MOUSELST可用来接收所有的鼠标消息。如果wMsgFilterMin和wMsgFilterMax都为零，GetMessage返回所有可得的消息（即，无范围过滤）。
GetMessage不从队列里清除WM.PAINT消息。该消息将保留在队列里直到处理完毕。
注意，此函数的返回值可非零、零或-1，应避免如下代码出现：
while（GetMessage（IpMsg，hwnd，0，0））…
－1返回值的可能性表示这样的代码会导致致命的应用程序错误。
速查：Windows NT： 3.1及以上版本；Windows：95及以上版本；Windows CE：1.0及以上版本：头文件：winuser.h；输入库：user32.Iib；Unicode：在Windows NT环境下以Unicode和ANSI方式实现。
实例:
unit Unit4;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,DBTables, Db, ADODB, Grids, DBGrids, StdCtrls, Buttons;
const
WM_OPENDATASET = WM_USER + 1;
WM_EXECUTESQL = WM_USER + 2;
type
TThreadDataSet = class(TThread)
private
procedure WMOpenDataSet(Msg: TMsg);
procedure WMExecSQL(Msg: TMsg);
protected
procedure Execute; override;
public
procedure Open(DataSet: TDataSet);
procedure ExecSQL(DataSet: TDataSet);
end;
TForm4 = class(TForm)
ADOTable1: TADOTable;
ADOQuery1: TADOQuery;
DataSource1: TDataSource;
DBGrid1: TDBGrid;
DBGrid2: TDBGrid;
DataSource2: TDataSource;
BitBtn1: TBitBtn;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure BitBtn1Click(Sender: TObject);
private
{ Private declarations }
FThread : TThreadDataSet;
public
{ Public declarations }
end;
var
Form4: TForm4;
implementation
{$R *.dfm}
uses ActiveX;
procedure TThreadDataSet.ExecSQL(DataSet: TDataSet);
begin
PostThreadMessage(ThreadID, WM_EXECUTESQL, Integer(DataSet), 0);
end;
procedure TThreadDataSet.Execute;
var
Msg : TMsg;
begin
CoInitialize(nil);
try
FreeOnTerminate := True;
PeekMessage(Msg, 0, WM_USER, WM_USER, PM_NOREMOVE);
while not Terminated do
begin
if GetMessage(msg,0,0,0) then
begin
case Msg.Message of
WM_OPENDATASET: WMOpenDataSet(Msg);
WM_EXECUTESQL: WMExecSQL(Msg);
end;
end;
end;
finally
CoUninitialize;
end;
end;
procedure TThreadDataSet.Open(DataSet: TDataSet);
begin
PostThreadMessage(ThreadID, WM_OPENDATASET, Integer(DataSet), 0);
end;
procedure TThreadDataSet.WMExecSQL(Msg: TMsg);
var
Qry : TQuery;
begin
try
Qry := TQuery(Msg.wParam);
try
Qry.Open;
except
Qry.ExecSQL;
end;
except
On E: Exception do
ShowMessage(E.Message);
end;
end;
procedure TThreadDataSet.WMOpenDataSet(Msg: TMsg);
var
Ds : TDataSet;
begin
try
Ds := TDataSet(Msg.wParam);
Ds.Open;
except
On E: Exception do ShowMessage(E.Message);
end;
end;
procedure TForm4.FormCreate(Sender: TObject);
begin
FThread := TThreadDataSet.Create(False);
end;
procedure TForm4.FormDestroy(Sender: TObject);
begin
FThread.Terminate;
end;
procedure TForm4.BitBtn1Click(Sender: TObject);
begin
FThread.Open(ADOTable1); // Opening a dataset (table or query)
FThread.ExecSQL(ADOQuery1); // Executing a SQL
end;
end.