Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2008.11.23;
Скачать: [xml.tar.bz2];

Вниз

Отловить сообщение во втором потоке созданным CreateThread   Найти похожие ветки 

 
Black_Tomcat   (2007-12-26 07:08) [0]

Здравствуйте.
Подскажите пожалуйста как отправить сообщение во второй поток и как его там поймать. А то, я что запутался окончательно вроде отправка осуществляется при помощи функции PostThreadMessage, а прием PeekMessage. Но вот только PostThreadMessage возвращает False, a GetLastError 1159. Что я не так делаю?


 
Сергей М. ©   (2007-12-26 08:34) [1]

Что говорит SysErrorMessage(GetLastError) ?


 
Black_Tomcat   (2007-12-26 09:19) [2]


> Что говорит SysErrorMessage(GetLastError) ?


"Сообщение может быть использовано только с операциями синхронизации"
А что это значит?


 
Сергей М. ©   (2007-12-26 09:27) [3]

А какое конкретно сообщение ты посылаешь ?


 
Black_Tomcat   (2007-12-26 09:35) [4]

var
Data:tagCOPYDATASTRUCT;

PostThreadMessage(ThreadID,WM_COPYDATA,0,lParam(@Data));


 
Сергей М. ©   (2007-12-26 09:38) [5]

Тогда отлуп ты получаешь вполне резонно - сообщение с кодом WM_COPYDATA есть специальный зарезервированный вид сообщения, которое можно отправлять только синхронно, т.е. с использованием SendMessage, а не Post[Thread]Message


 
Black_Tomcat   (2007-12-26 09:43) [6]

Ясно спасибо.
А как его отловить во втором потоке?


 
Сергей М. ©   (2007-12-26 09:47) [7]

Прежде чем его "ловить" нужно осознать, что ф-ция SendMessage подразумевает адресатом окно (или окна) , а не нить. Целевая нить у тебя создает хоть одно окно ?


 
Black_Tomcat   (2007-12-26 09:53) [8]

Это я знаю :-)
Окно у меня есть. И оно умеет обрабатывать это сообщение. Мне нужно его как-то перехватить перед тем как окно его обработает. Это возможно?


 
Сергей М. ©   (2007-12-26 10:11) [9]


> Окно у меня есть


Оно откуда взялось ? Его какая нить создала - целевая ?


 
Black_Tomcat   (2007-12-26 10:17) [10]

Я пишу на VCL окно стандартное.
Целевая нить и основной поток это одно и тоже?


 
Сергей М. ©   (2007-12-26 10:20) [11]

Поток (кодовый) = нить = тред = thread.

Если ты отправляешь сообщение основному потоку, то разумеется он является целевым потоком.


 
Сергей М. ©   (2007-12-26 10:22) [12]

Определись, кому ты посылаешь сообщение - потоку или окну..


 
Black_Tomcat   (2007-12-26 10:30) [13]

Мне нужно отправить это сообщение в созданный поток.
И из созданного потока обратно окну.
Oкну можно его отправить  например так SendMessage(Form1.Handle,WM_COPYDATA,0,lParam(i)) .

Но вот как отправить это сообщение в созданный мною поток? И как его там обработать, я не могу понять.
Может ли мною созданный поток, выгребать сообщения из очереди сообщений окна?


 
Сергей М. ©   (2007-12-26 10:47) [14]


> как отправить это сообщение в созданный мною поток?


Никак. Только окну его можно отправить.
Меняй концепцию и логику.


> Может ли мною созданный поток, выгребать сообщения из очереди
> сообщений окна?


А собссно зачем ? Поясни ..


 
Black_Tomcat   (2007-12-26 10:53) [15]

Я отправляю сообщение окну.
Поток его забирает из очереди собщений, например занимает семафор, а процедура обработки сообщения целевого потока в зависимости от состояния семаформа решает обрабатывать его или нет.
Или я вообще неправильно думаю.


 
Сергей М. ©   (2007-12-26 11:02) [16]


> Поток его забирает из очереди собщений


Его забирает тот поток, который создал окно, т.е. в твоем случае основной.

Далее этот поток смотрит на семафор - если он занят, то делает с полученным сообщением одно действие , иначе другое.


 
Black_Tomcat   (2007-12-26 11:07) [17]

Спасибо.
Теперь пойду валить препода. :-)


 
Сергей М. ©   (2007-12-26 11:23) [18]


> пойду валить препода


Как бы он тебя не завалил)


 
Black_Tomcat   (2007-12-28 10:45) [19]

У меня возник еще вопросик.
Я во втором потоке создал окно все вроде работает, но  функция обработки сообщений созданного окна выполняется в основном потоке, как ее выполнить в потоке создавшем окно?
Вот код на всякий случай.

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-28 10:50) [20]


> функция обработки сообщений созданного окна выполняется
> в основном потоке


Ничего подобного.
Оконная функция выполняется в потоке, создавшем окно.


 
Сергей М. ©   (2007-12-28 10:57) [21]

Почему вообще WinAPI ?
Это блажь или учебная задача ?
Если блажь, то чья - твоя или препода ?
Если учебная задача, то не рановато ли при таких знаниях "валить препода" ?)


 
Black_Tomcat   (2007-12-28 11:12) [22]

Я проверял в режиме отладки эта функция почему-то выполняется основном потоке есть, еще одно подтверждение

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 11:22) [23]

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:30) [24]

Я бы с удовольствием сделал через класс потока, но нельзя.
Спасибо.
Теперь буду докуривать Джеффри Рихтера, и Windows SDK.
Еще раз спасибо.


 
Сергей М. ©   (2007-12-28 11:34) [25]


> wParam передает не указатель отправляемому окну равный тому
> который я передавал


wParam на момент вызова SensMessage должно содержать хэндл окна-"оптавителя", а ты в этом параметре передаешь черт те что, но только не хэндл окна.


> lParam предает модифицированный указатель


Никакой он не "модифицированный". Обычный указатель на COPYDATASTRUCT-структуру в адресном пространстве процесса-отправителя.
А в адресном пространстве процесса-получателя полученный lParam будет содержать совершенно другой указатель на принятую структуру, и это абсолютно нормально - адресные пространства процессов абсолютно изолированы друг от друга.


 
Сергей М. ©   (2007-12-28 11:36) [26]


> с удовольствием сделал через класс потока, но нельзя


Да на здоровье. Нельзя так нельзя. Пользуй BeginThread().


 
Сергей М. ©   (2007-12-28 11:58) [27]

Вот тебе тоже самое, но без 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);


 
MetalFan ©   (2007-12-28 14:03) [28]

а зачем AllocateHWND???


 
MetalFan ©   (2007-12-28 14:03) [29]

а, ну да... тут же WM_COPYDATA


 
Black_Tomcat   (2008-01-18 09:51) [30]

Спасибо за помощь я вроде разобрался маленько. Решил написать как сделал может кому-нибудь когда-нибудь пригодится.
Кусок кода чужой, но кое-что я изменил.


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;



 
Сергей М. ©   (2008-01-18 12:57) [31]


> TranslateMessage(Msg);


Эт лишнее.


 
Slym ©   (2008-01-18 13:28) [32]

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;


 
Black_Tomcat   (2008-01-18 13:29) [33]

Еще раз спасибо.
Запомню.



Страницы: 1 вся ветка

Форум: "WinAPI";
Текущий архив: 2008.11.23;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.006 c
2-1223557692
AlexDan
2008-10-09 17:08
2008.11.23
RichEdit и буфер обмена


2-1224146235
Vunda
2008-10-16 12:37
2008.11.23
панель в OLE


2-1223627971
Zlo
2008-10-10 12:39
2008.11.23
Транзакции


8-1187006365
Dio
2007-08-13 15:59
2008.11.23
Изменить уровень звука


2-1223829610
yasuo
2008-10-12 20:40
2008.11.23
Как правильно настроить Runtime packages (чтобы Exe был малым )





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский