![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Отловить сообщение во втором потоке созданным CreateThread
Black_Tomcat © (2007-12-26 07:08:00)Здравствуйте.
Подскажите пожалуйста как отправить сообщение во второй поток и как его там поймать. А то, я что запутался окончательно вроде отправка осуществляется при помощи функции PostThreadMessage, а прием PeekMessage. Но вот только PostThreadMessage возвращает False, a GetLastError 1159. Что я не так делаю?
Black_Tomcat (2008-01-18 13:29:00) [1]Еще раз спасибо.
Запомню.
Slym (2008-01-18 13:28:00) [2]Black_Tomcat (18.01.08 9:51) [30]
не забываем про DefWindowProc!
function WindowThreadProc(WND:HWND; Msg : Integer; wParam:Wparam;
lParam:Lparam):Longint; stdcall; export;
begin
if Msg=WM_COPYDATA then
begin
//что-нибудь делаем
end
else
result:=DefWindowProc(WND,Msg,wParam,lParam);
end;
Сергей М. (2008-01-18 12:57:00) [3]
> TranslateMessage(Msg);
Эт лишнее.
Black_Tomcat (2008-01-18 09:51:00) [4]Спасибо за помощь я вроде разобрался маленько. Решил написать как сделал может кому-нибудь когда-нибудь пригодится.
Кусок кода чужой, но кое-что я изменил.
function WindowThreadProc(WND:HWND; Msg : Integer; wParam:Wparam;
lParam:Lparam):Longint; stdcall; export;
begin
if Msg=WM_COPYDATA then
begin
//что-нибудь делаем
end
end;
//второй поток
Function Query:DWORD;
var i:integer;
Msg:TagMSG;
WndClassEx: TWndClassEx;
PQRec:PQueryRecord;
begin
FormThread2 := CreateWindowEx (
ws_Ex_OverlappedWindow,
'Message',//Специальный класс окна для обмена сообщениями
'Plain API Demo',
ws_OverlappedWindow,
cw_UseDefault, 0,
cw_UseDefault, 0,
0,
0,
Thread2,
nil);
if FormThread2 = 0 then
MessageBox (0, 'Window not created',
'Plain API', MB_OK);
//заменяю процедуру обработки сообщений окна
SetWindowLong(FormThread2,GWL_WNDPROC,integer(@WindowThreadProc));
while GetMessage(Msg,FormThread2,0,0) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end;
MetalFan (2007-12-28 14:03:00) [5]а, ну да... тут же WM_COPYDATA
MetalFan (2007-12-28 14:03:00) [6]а зачем AllocateHWND???
Сергей М. (2007-12-28 11:58:00) [7]Вот тебе тоже самое, но без TThread:
type
TMyThread = class( TObject)
private
FhWnd: THandle;
procedure ThreadWndProc(var Message: TMessage);
procedure MsgWmCopydata(var Msg: TWMCopyData); message WM_COPYDATA;
procedure MsgWmSendata(var Msg: TWMSendData); message WM_SEND_DATA;
..
end;
..
procedure TMyThread.MsgWmCopydata(var Msg: TWMCopyData);
begin
.. обработка сообщения WM_COPYDATA ..
end;
procedure TMyThread.MsgWmSendata(var Msg: TWMSendData);
begin
.. обработка сообщения WM_SEND_DATA ..
end;
procedure TMyThread.ThreadWndProc(var Message: TMessage);
begin
Dispatch(Message);
end;
function MyThreadFunc(MyThreadObject: TMyThread): Integer;
var
Msg: TMsg;
begin
with MyThreadObject do
begin
FhWnd := AllocateHWnd(ThreadWndProc);
try
while GetMessage(Msg, 0, 0, 0) do
DispatchMessage(Msg);
finally
DeallocateHWnd(FhWnd);
end;
end;
end;
..
BeginThread(nil, 0, @MyThreadFunc, Pointer(TMyThreadObject.Create), MyThreadId);
Сергей М. (2007-12-28 11:36:00) [8]
> с удовольствием сделал через класс потока, но нельзя
Да на здоровье. Нельзя так нельзя. Пользуй BeginThread().
Сергей М. (2007-12-28 11:34:00) [9]
> wParam передает не указатель отправляемому окну равный тому
> который я передавал
wParam на момент вызова SensMessage должно содержать хэндл окна-"оптавителя", а ты в этом параметре передаешь черт те что, но только не хэндл окна.
> lParam предает модифицированный указатель
Никакой он не "модифицированный". Обычный указатель на COPYDATASTRUCT-структуру в адресном пространстве процесса-отправителя.
А в адресном пространстве процесса-получателя полученный lParam будет содержать совершенно другой указатель на принятую структуру, и это абсолютно нормально - адресные пространства процессов абсолютно изолированы друг от друга.
Black_Tomcat (2007-12-28 11:30:00) [10]Я бы с удовольствием сделал через класс потока, но нельзя.
Спасибо.
Теперь буду докуривать Джеффри Рихтера, и Windows SDK.
Еще раз спасибо.
Сергей М. (2007-12-28 11:22:00) [11]
type
TMyThread = class(TThread)
private
FhWnd: THandle;
procedure ThreadWndProc(var Message: TMessage);
procedure MsgWmCopydata(var Msg: TWMCopyData); message WM_COPYDATA;
procedure MsgWmSendata(var Msg: TWMSendData); message WM_SEND_DATA;
..
protected
procedure Execute; override;
..
end;
..
procedure TMyThread.MsgWmCopydata(var Msg: TWMCopyData);
begin
.. обработка сообщения WM_COPYDATA ..
end;
procedure TMyThread.MsgWmSendata(var Msg: TWMSendData);
begin
.. обработка сообщения WM_SEND_DATA ..
end;
procedure TMyThread.ThreadWndProc(var Message: TMessage);
begin
Dispatch(Message);
end;
procedure TMyThread.Execute;
var
Msg: TMsg;
begin
FhWnd := AllocateHWnd(ThreadWndProc);
try
while not Terminated and GetMessage(Msg, 0, 0, 0) do
DispatchMessage(Msg);
finally
DeallocateHWnd(FhWnd);
end;
end;
Black_Tomcat (2007-12-28 11:12:00) [12]Я проверял в режиме отладки эта функция почему-то выполняется основном потоке есть, еще одно подтверждение
var list:Array of integer;
Data:tagCOPYDATASTRUCT;
begin
Data.dwData:= 123;
Data.cbData:= Length(List)*4;
Data.lpData:=@list;
SendMessage(FormThread2,WM_COPYDATA,wParam(@list),lParam(@data));
wParam передает не указатель отправляемому окну равный тому который я передавал и он рабочий, a lParam предает модифицированный указатель предназначенный второму потоку, но при обращении к нему я не могу ничего получить.
А WinAPI это задание на курсач типа как для ознакомления с ним, и что они вообще есть.
А знания препода оставляют желать лучшего как вам задание передача данных меджу потоками через сообщения. И синхронизация с помощью семафора?
Сергей М. (2007-12-28 10:57:00) [13]Почему вообще WinAPI ?
Это блажь или учебная задача ?
Если блажь, то чья - твоя или препода ?
Если учебная задача, то не рановато ли при таких знаниях "валить препода" ?)
Сергей М. (2007-12-28 10:50:00) [14]
> функция обработки сообщений созданного окна выполняется
> в основном потоке
Ничего подобного.
Оконная функция выполняется в потоке, создавшем окно.
Black_Tomcat (2007-12-28 10:45:00) [15]У меня возник еще вопросик.
Я во втором потоке создал окно все вроде работает, но функция обработки сообщений созданного окна выполняется в основном потоке, как ее выполнить в потоке создавшем окно?
Вот код на всякий случай.
unit Unit1;
var Thread2:THandle;
FormThread2:HWND;
Procedure Query;
function SecondWinProc (hWnd: THandle; nMsg: UINT;wParam, lParam: Cardinal): Cardinal; export; stdcall;
begin
if nMsg=WM_COPYDATA then
//do something
else
if nMsg=WM_SEND_DATA then
//do something
end;
var xPos,yPos,nWidth,nHeight : Integer;
var wc : TWndClassEx;
Msg : TMsg;
begin
wc.cbSize:=sizeof(wc);
wc.style:=cs_hredraw or cs_vredraw;
wc.lpfnWndProc:=@SecondWinProc;
wc.cbClsExtra:=0;
wc.cbWndExtra:=0;
wc.hInstance:=Thread2;
wc.hIcon:=LoadIcon(0,idi_application);
wc.hCursor:=LoadCursor(0,idc_arrow);
wc.hbrBackground:=COLOR_BTNFACE+1;
wc.lpszMenuName:=nil;
wc.lpszClassName:='SecondForm';
RegisterClassEx(wc);
xPos:=0;
yPos:=0;
nWidth:=0;
nHeight:=0;
FormThread2:=CreateWindowEx(
0,
'SecondForm',
'SecondForm',
ws_overlappedwindow,
xPos,
yPos,
nWidth,
nHeight,
0,
0,
Thread2,
nil
);
While GetMessage(Msg,FormThread2,0,0) do
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Thread2:=CreateThread(nil,2048,@Query,nil,0,ThreadID2);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
SendMessage(FormThread2,WM_COPYDATA,0,lParam(123));
SendMessage(FormThread2,WM_COPYDATA,0,Integer(321));
end;
Все я не стал копировать, но я думаю смысл от этого не изменится.
Сергей М. (2007-12-26 11:23:00) [16]
> пойду валить препода
Как бы он тебя не завалил)
Black_Tomcat (2007-12-26 11:07:00) [17]Спасибо.
Теперь пойду валить препода. :-)
Сергей М. (2007-12-26 11:02:00) [18]
> Поток его забирает из очереди собщений
Его забирает тот поток, который создал окно, т.е. в твоем случае основной.
Далее этот поток смотрит на семафор - если он занят, то делает с полученным сообщением одно действие , иначе другое.
Black_Tomcat (2007-12-26 10:53:00) [19]Я отправляю сообщение окну.
Поток его забирает из очереди собщений, например занимает семафор, а процедура обработки сообщения целевого потока в зависимости от состояния семаформа решает обрабатывать его или нет.
Или я вообще неправильно думаю.
Сергей М. (2007-12-26 10:47:00) [20]
> как отправить это сообщение в созданный мною поток?
Никак. Только окну его можно отправить.
Меняй концепцию и логику.
> Может ли мною созданный поток, выгребать сообщения из очереди
> сообщений окна?
А собссно зачем ? Поясни ..