imho.ws |
![]() |
![]() |
![]() |
# 1 |
Newbie
Регистрация: 03.10.2007
Пол: Male
Сообщения: 8
![]() |
Помогите пожалуйста с EnumWindows
Имеется приложение, при старте создается сокет (на winsock), ставится на прослушку и стартует поток-диспетчер, который следит, подключился ли к нам кто-то, если да, то стартует еще один поток, который обрабатывает клента.
Из этого потока вызывается EnumWindows - она перечисляет все окна верхнего уровня и передает их хэндлы callback функции, дак вот, при вызове не из основного потока в callback идут нули, а должны идти хэндлы. Вопрос: как из неосновного потока правильно вызвать EnumWindows? Или тут вообще нужен другой подход. P.S.: Задача отыскать чужое окно, по команде с удаленного компьютера (за этим и используются сокеты) |
![]() |
![]() |
# 3 |
Newbie
Регистрация: 03.10.2007
Пол: Male
Сообщения: 8
![]() |
Вот код
Код:
//объявления классов потоков //поток-диспетчер type TDispThread = class(TThread) Sock:TSocket; private protected procedure execute; override; end; //поток выполнения обслуживания клиента type TMyServThread = class(TThread) qwestion:Integer; ASock:TSocket; private protected procedure Execute; override; function EnumProc(Wd:hWnd; param:LongInt):Boolean; stdcall; end; //в процедуре создания формы открываем сокет и стартуем поток - диспетчер procedure TForm1.FormCreate(Sender: TObject); var D:WSAData; S,ASock:TSocket; A:TSockAddr; ASockAddr:PSockAddr; begin //вызываем старт winsock, но ошибок не обрабатываем, т.к. юзеру не надо знать что у него стоит эта вещь try WSAStartUp(MakeWord(2,0),D); //начиняем структуру адреса инфой A.sin_family:=AF_INET; A.sin_port:=htons(3333); A.sin_addr.S_addr:=htonl(INADDR_ANY); //создаем сокет S:=Socket(AF_INET,SOCK_STREAM,IPPROTO_IP); //биндим сокет Bind(S,A,sizeof(A)); //ставим сокет на прослушку Listen(S,3); //создаем поток-диспетчер Disp:=TDispThread.Create(true); Disp.Priority:=tpNormal; Disp.FreeOnTerminate:=true; //передаем диспетчеру открытый на прослушивание серверный сокет Disp.Sock:=S; //стартуем поток-диспетчер Disp.Resume; except WSACleanUp(); end; {try} end; //код потока-диспетчера procedure TDispThread.execute; var So:TSocket; Opt:PChar; begin Opt:='1'; //запуск цикла ожидания подключения while true do begin So:=Accept(Sock,nil,nil); if So <> INVALID_SOCKET then begin //установим опции ассептнутого сокета (чтобы он у нас сразу высвобождался, как только будет закрыт) SetSockOpt(So,SOL_SOCKET,SO_LINGER,Opt,SizeOf(Opt)); //даем информацию потоку обслуживания клиента MyThread:=TMyServThread.Create(true); MyThread.Priority:=tpNormal; MyThread.FreeOnTerminate:=true; //передаем потоку ассептнутый сокет MyThread.ASock:=So; //запускаем поток на выполнение MyThread.Resume; end;{if} //проверяем, не отработал ли клиентский поток if MyThread.Terminated = true then //чистим сокет CloseSocket(So); end; {while} end; //а вот сам поток обслуживания клиента procedure TMyServThread.Execute; var buf:array[0..100] of char; begin recv(ASock,buf,sizeof(buf),0); ShowMessage(buf); if buf = 'close1c0' then begin qwestion:=0; ShutDown(ASock,0); CloseSocket(ASock); EnumWindows(@TMyServThread.EnumProc,0); end;{if close1c0} if buf = 'close1c1' then begin qwestion:=1; ShutDown(ASock,0); CloseSocket(ASock); EnumWindows(@TMyServThread.EnumProc,0); end;{if} MyThread.Terminate; end; //и процедура EnumProc //callback функция которая будет обрабатывать результаты enumwindow function TMyServThread.EnumProc(Wd:hWnd; param:LongInt):Boolean; stdcall; var hSnap:THandle; pe:TProcessEntry32; pt:TThreadEntry32; PID,wndPID:DWord; BHY,BHN:THandle; //хэндл кнопки begin PID:=0; //получаем pid нашего процесса pe.dwSize:=SizeOf(pe); hSnap:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); If Process32First(hSnap,pe) then begin if pe.szExeFile='1cv7s.exe' then PID:=pe.th32ProcessID; While Process32Next(hSnap,pe) do begin If pe.szExeFile='1cv7s.exe' then begin PID:=pe.th32ProcessID; break; end;{if} end; {while} end; {if} //конец получения pid if IsWindow(Wd) = true then begin GetWindowThreadProcessID(Wd,wndPID); if wndPID = PID then begin //мы нашли наше окно (1с), теперь пошлем ему сигнал о закрытии PostMessage(Wd,WM_CLOSE,0,0); if qwestion = 1 then begin //у нас появится дочернее окно о подтверждении закрытия, его то мы и будем искать if FindWindow(nil,'1С:Предприятие') <> 0 then begin //мы нашли окно с кнопкой BHN:=FindWindowEX(FindWindow(nil,'1С:Предприятие'),0,'Button','&Нет'); if BHN <> 0 then begin SetWindowText(BHN,'Жми меня!'); //SendMessage(BHN,BM_CLICK,0,0); end; {if BHN} end;{if} end;{if} end;{if} end;{if} EnumProc:=true; end; |
![]() |