Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Print Screen видео [D7, WinXP]


Страницы:   1 2

Eraser ©   (2005-04-11 21:26:00) 

Добрый вечер! Вопрос такой: как сделать Print Screen окна, в котором отображается видео?
Копирование с HDC окна даёт чёрный прямоугольник...

Спасибо.


Eraser   (2005-04-22 15:42:00) [1]

Grief ©

Так мне общий случай нужен... а не частный.
Кстати в Win медиапелеере некоторые типы файлов снимаются принт скрином, некотрые нет... наверное декодеры разные.


Grief   (2005-04-20 18:34:00) [2]

винамп снимается и принтскрином и через DC, юзай его!


Анонимщик1   (2005-04-18 11:07:00) [3]

Это все. С зябликами разбирайтесь сами. Если будут вопросы по коду, объяснить смогу только на протяжении сегодняшнего дня.


Анонимщик1   (2005-04-18 11:05:00) [4]

Конец окончания:

   RxMemoryData1.First;
   while not RxMemoryData1.Eof do
   begin
     currFileName := DirectoryEdit1.Text + '\' + RxMemoryData1StopCadr.AsString + '.bmp';
     rt := RxMemoryData1StopCadr.AsLargeInt * 10000;
     if rt


Анонимщик1   (2005-04-18 11:03:00) [5]

Середина окончания:

 try
   hr := CoCreateInstance(CLSID_FilterGraph, nil, CLSCTX_INPROC, IID_IGraphBuilder, pGraphBuilder);
   if FAILED(hr) then raise Exception.Create('Íå óäàåòñÿ ñîçäàòü GraphBuilder');

   hr := CoCreateInstance(CLSID_SampleGrabber, nil, CLSCTX_INPROC, IID_ISampleGrabber, pSampleGrabber);
   if FAILED(hr) then raise Exception.Create('Íå óäàåòñÿ ñîçäàòü SampleGrabber');

   pGrabCB := TGrabCB.Create(nil);
   if not Assigned(pGrabCB) then raise Exception.Create('Íå óäàåòñÿ ñîçäàòü SampleGrabberCB');

   hr := pSampleGrabber.SetCallback(pGrabCB, 1);
   if FAILED(hr) then raise Exception.Create('Íå óäàåòñÿ óñòàíîâèòü callback - ôóíêöèþ');

   pSampleGrabber.SetOneShot(TRUE);

   hr := CoCreateInstance(CLSID_NullRenderer, nil, CLSCTX_INPROC, IID_IBaseFilter, pNullRenderer);
   if FAILED(hr) then raise Exception.Create('Íå óäàåòñÿ ñîçäàòü NullRenderer');

   hr := pGraphBuilder.QueryInterface(IID_IMediaControl, pMediaControl);
   if FAILED(hr) then raise Exception.Create('Íå óäàåòñÿ ïîëó÷èòü èíòåðôåéñ MediaControl');

   hr := pGraphBuilder.QueryInterface(IID_IMediaEvent, pMediaEvent);
   if FAILED(hr) then raise Exception.Create('Íå óäàåòñÿ ïîëó÷èòü èíòåðôåéñ MediaEvent');

   hr := pGraphBuilder.AddSourceFilter(StringToOleStr(Label1.Caption), '', pSourceFile);
   if FAILED(hr) then raise Exception.Create('Íå óäàåòñÿ äîáàâèòü ôèëüòð èñòî÷íèêà');

   hr := pGraphBuilder.AddFilter(pSampleGrabber as IBaseFilter, 'Sample Grabber');
   if FAILED(hr) then raise Exception.Create('Íå óäàåòñÿ äîáàâèòü SampleGrabber');

   hr := pGraphBuilder.AddFilter(pNullRenderer, 'Null Renderer');
   if FAILED(hr) then raise Exception.Create('Íå óäàåòñÿ äîáàâèòü NullRenderer');

   pSourceOutPin := GetPin(pSourceFile, PINDIR_OUTPUT);
   if not Assigned(pSourceOutPin) then raise Exception.Create('Íå óäàåòñÿ ïîëó÷èòü èñõîäÿùèé êîíòàêò ôèëüòðà èñòî÷íèêà');

   pSampleGrabberInPin := GetPin(pSampleGrabber as IBaseFilter, PINDIR_INPUT);
   if not Assigned(pSampleGrabberInPin) then raise Exception.Create('Íå óäàåòñÿ ïîëó÷èòü âõîäÿùèé êîíòàêò çàãðàáàñòîðà');

   hr := pGraphBuilder.Connect(pSourceOutPin, pSampleGrabberInPin);
   if FAILED(hr) then raise Exception.Create('Íå óäàåòñÿ ñîåäèíèòü ôèëüòð èñòî÷íèêà è SampleGraber');

   pSampleGrabberOutPin := GetPin(pSampleGrabber as IBaseFilter, PINDIR_OUTPUT);
   if not Assigned(pSampleGrabberOutPin) then raise Exception.Create('Íå óäàåòñÿ ïîëó÷èòü èñõîäÿùèé êîíòàêò çàãðàáàñòîðà');

   pNullRenderInPin := GetPin(pNullRenderer, PINDIR_INPUT);
   if FAILED(hr) then raise Exception.Create('Íå óäàåòñÿ ïîëó÷èòü âõîäÿùèé êîíòàêò NullRenderer''à');

   hr := pGraphBuilder.Connect(pSampleGrabberOutPin, pNullRenderInPin);
   if FAILED(hr) then raise Exception.Create('Íå óäàåòñÿ ñîåäèíèòü SampleGraber è NullRenderer');

   hr := pGraphBuilder.QueryInterface(IID_IMediaSeeking, pMediaSeeking);
   if FAILED(hr) then raise Exception.Create('Íå óäàåòñÿ ïîëó÷èòü èíòåðôåéñ MediaSeeking');

   hr := pMediaSeeking.SetTimeFormat(TIME_FORMAT_MEDIA_TIME);
   if FAILED(hr) then raise Exception.Create('Íå óäàåòñÿ óñòàíîâèòü çàáèòûé ìíîþ ôîðìàò âðåìåíè');

   hr := pMediaSeeking.GetDuration(length);
   if FAILED(hr) then raise Exception.Create('Íå óäàåòñÿ ïîëó÷èòü äëèòåëüíîñòü');


Анонимщик1   (2005-04-18 10:59:00) [6]

Начало окончания:

procedure TForm1.FullProcessing;
var
 hr: HRESULT;
 rt: REFERENCE_TIME;
 evCode: Integer;

 pGraphBuilder        : IGraphBuilder;
 pSourceFile          : IBaseFilter;
 pMediaControl        : IMediaControl;
 pMediaEvent          : IMediaEvent;
 pMediaSeeking        : IMediaSeeking;
 pNullRenderer        : IBaseFilter;

 pSourceOutPin        : IPin;
 pSampleGrabberInPin  : IPin;
 pSampleGrabberOutPin : IPin;
 pNullRenderInPin     : IPin;

 pGrabCB              : TGrabCB;

 length               : LongLong;
begin
 Enabled := false;
 pGraphBuilder         := nil;
 pSourceFile           := nil;
 pMediaControl         := nil;
 pMediaEvent           := nil;
 pMediaSeeking         := nil;
 pNullRenderer         := nil;

 pSourceOutPin         := nil;
 pSampleGrabberInPin   := nil;
 pSampleGrabberOutPin  := nil;
 pNullRenderInPin      := nil;

 pGrabCB               := nil;


Анонимщик1   (2005-04-18 10:56:00) [7]

Продолжение:

function TGrabCB.BufferCB(SampleTime: Double; pBuffer: PByte; BufferLen: Longint): HRESULT; stdcall;

 function GetDIBLineSize(BitCount, Width: Integer): Integer;
 begin
   if BitCount = 15 then BitCount := 16;
   Result := ((BitCount * Width + 31) div 32) * 4;
 end;

var
 Bmp         : TBitmap;
 BitmapHandle: HBitmap;
 MediaType   : TAMMediaType;
 BiHeaderPtr : PBitmapInfoHeader;
 DIBPtr      : Pointer;
 DIBSize     : LongInt;
 errorCode: Integer;
 newMediaType: TAMMediaType;
 BMPInfo: TBitmapInfo;
begin
 Result := pSampleGrabber.GetConnectedMediaType(MediaType);
 if Result S_OK then exit;

 try
   Bmp := TBitmap.Create;
   if not IsEqualGUID(MediaType.majortype, MEDIATYPE_VIDEO) then exit;
   BiHeaderPtr := nil;
   if IsEqualGUID(MediaType.formattype, FORMAT_VideoInfo) then begin
     if MediaType.cbFormat = SizeOf(TVideoInfoHeader) then
       BIHeaderPtr := @(PVideoInfoHeader(MediaType.pbFormat)^.bmiHeader);
   end else if IsEqualGUID(MediaType.formattype, FORMAT_VideoInfo2) then begin
     if MediaType.cbFormat = SizeOf(TVideoInfoHeader2) then
       BIHeaderPtr := @(PVideoInfoHeader2(MediaType.pbFormat)^.bmiHeader);
   end;

   if not Assigned(BiHeaderPtr) then begin
     New(BiHeaderPtr);
     BiHeaderPtr.biSize := SizeOf(TVideoInfoHeader);
     BiHeaderPtr.biWidth := PVideoInfoHeader(MediaType.pbFormat).bmiHeader.biWidth;
     BiHeaderPtr.biHeight := PVideoInfoHeader(MediaType.pbFormat).bmiHeader.biHeight;
     BiHeaderPtr.biPlanes := PVideoInfoHeader(MediaType.pbFormat).bmiHeader.biPlanes;
     BiHeaderPtr.biBitCount := PVideoInfoHeader(MediaType.pbFormat).bmiHeader.biBitCount;
   end;

   BitmapHandle := CreateDIBSection(0, PBitmapInfo(BIHeaderPtr)^, DIB_RGB_COLORS, DIBPtr, 0, 0);

   if BitmapHandle 0 then begin
     try

       if DIBPtr = nil then exit;

       DIBSize := BIHeaderPtr.biSizeImage;
       if DIBSize = 0 then DIBSize := GetDIBLineSize(BIHeaderPtr.biBitCount, BIHeaderPtr.biWidth) *
                                       BIHeaderPtr.biHeight * BIHeaderPtr.biPlanes;

       if not Assigned(pBuffer) then begin
         BufferLen := 0;
         if (pSampleGrabber.GetCurrentBuffer(BufferLen, 0) S_OK) or (BufferLen DIBSize then BufferLen := DIBSize;
         if pSampleGrabber.GetCurrentBuffer(BufferLen, DIBPtr) S_OK then exit;
       end else begin
         if BufferLen > DIBSize then BufferLen := DIBSize;
         Move(pBuffer^, DIBPtr^, BufferLen);
       end;
       Bmp.Handle := BitmapHandle;

     finally
       if Bmp.Handle BitmapHandle
       then DeleteObject(BitmapHandle)
       else Bmp.SaveToFile(currFileName);
     end;
   end;

 finally

   if MediaType.cbFormat 0 then begin
     CoTaskMemFree(MediaType.pbFormat);
     MediaType.cbFormat := 0;
     MediaType.pbFormat := 0;
   end;
   if MediaType.pUnk nil then MediaType.pUnk := nil;

   Bmp.Free;

 end;

 Result := S_OK;
end;

function GetPin(pFilter: IBaseFilter; pinDir: PIN_DIRECTION): IPin;
var
 bFound: boolean;
 pEnum : IEnumPins;
 pPin  : IPin;

 PinDirThis: PIN_DIRECTION;

begin
 bFound := false;
 pFilter.EnumPins(pEnum);
 while (pEnum.Next(1, pPin, 0) = S_OK ) do
 begin
   pPin.QueryDirection(PinDirThis);
   if (pinDir = PinDirThis) then begin
     bFound := true;
     break;
   end;
 end;
 pEnum.Reset;

 if bFound
 then Result := pPin
 else result := nil;

end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 CoInitialize(nil);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 CoUninitialize;
end;

procedure TForm1.Load1Click(Sender: TObject);
begin
 if not OpenDialog1.Execute then exit;
 Label1.Caption := OpenDialog1.FileName;
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
var
 fName: String;
begin
 if Label1.Caption = '' then raise Exception.Create('Íå çàäàíî èìÿ âèäåîôàéëà');
 if not FileExists(Label1.Caption) then raise Exception.Create('Âèäåîôàéë íå íàéäåí');
 if DirectoryEdit1.Text = '' then raise Exception.Create('Íå çàäàíî èìÿ äèðåêòîðèè íàçíà÷åíèÿ');
 if not DirectoryExists(DirectoryEdit1.Text) then raise Exception.Create('Äèðåêòîðèÿ íàçíà÷åíèÿ íå íàéäåíà');
 if RxMemoryData1.IsEmpty then raise Exception.Create('Íå çàäàíî âðåìÿ ñòîï-êàäðîâ');
 RxMemoryData1.First;
 while not RxMemoryData1.Eof do
 begin
   fName := DirectoryEdit1.Text + '\' + RxMemoryData1StopCadr.AsString + '.bmp';
   if FileExists(fName) then raise Exception.Create('Ôàéë ' + fName + ' óæå ñóùåñòâóåò. Îòìåíà îïåðàöèè.');
   RxMemoryData1.Next;
 end;
 FullProcessing;
end;


Анонимщик1   (2005-04-18 10:55:00) [8]

main.pas:

unit main;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, Menus, StdCtrls, DB, Grids, DBGridEh, RxMemDS, Mask, ToolEdit,
 Buttons;

type
 TForm1 = class(TForm)
   Label1: TLabel;
   MainMenu1: TMainMenu;
   File1: TMenuItem;
   Load1: TMenuItem;
   OpenDialog1: TOpenDialog;
   RxMemoryData1: TRxMemoryData;
   DBGridEh1: TDBGridEh;
   DataSource1: TDataSource;
   DirectoryEdit1: TDirectoryEdit;
   Label2: TLabel;
   BitBtn1: TBitBtn;
   RxMemoryData1StopCadr: TLargeintField;
   procedure Load1Click(Sender: TObject);
   procedure BitBtn1Click(Sender: TObject);
   procedure FormCreate(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
 private
   { Private declarations }
   procedure FullProcessing;
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

uses ActiveX, DirectShow9;

var
 currFileName: String = '';
 pSampleGrabber: ISampleGrabber;

type
 TGrabCB = class(TComponent, ISampleGrabberCB)
 private
   function SampleCB(SampleTime: Double; pSample: IMediaSample): HRESULT; stdcall;
   function BufferCB(SampleTime: Double; pBuffer: PByte; BufferLen: Longint): HRESULT; stdcall;
   function QueryInterface(const IID: TGUID; out Obj): HRESULT; stdcall;
   function _AddRef: Integer; stdcall;
   function _Release: Integer; stdcall;
           end;

function TGrabCB.QueryInterface(const IID: TGUID; out Obj): HRESULT; stdcall;
begin
 Result := inherited QueryInterface(IID, Obj);
end;

function TGrabCB._AddRef: Integer; stdcall;
begin
 Result := 2;
end;

function TGrabCB._Release: Integer; stdcall;
begin
 Result := 1;
end;

function TGrabCB.SampleCB(SampleTime: Double; pSample: IMediaSample): HRESULT;
begin
 ShowMessage('Êó-êó!');
end;


Анонимщик1   (2005-04-18 10:51:00) [9]

Код я написал под ваш заказ и в боевых условиях не тестировал.
Поэтому вылавливайте глюки сами. Понимание кода - тоже ваша проблема, когда поймете, попробуйте переделать с использованием DSPack'а - выйдет проще.
Проект состоит из dpr-файла:

program SetMediaPos_Sample;

uses
 Forms,
 main in 'main.pas' {Form1};

{$R *.res}

begin
 Application.Initialize;
 Application.CreateForm(TForm1, Form1);
 Application.Run;
end.


И одного pas-модуля c dfm-ом. Я использовал библиотеку RX, так что, если у вас ее нет - не взыщите. Да, забыл сказать, что делает программа: она позволяет выбирать avi-файл (другие форматы тоже, в принципе, не исключаются, но, как я уже говорил на два поста выше, с ними могут быть проблемы), задавать, в миллисекундах время стоп-кадров, и задавать директорию, в которую эти самые стоп-кадры будут складироваться.
Итак, main.dfm:

object Form1: TForm1
 Left = 192
 Top = 107
 Width = 755
 Height = 480
 Caption = 'Set Media Position And Get Cadrs'
 Color = clBtnFace
 Font.Charset = DEFAULT_CHARSET
 Font.Color = clWindowText
 Font.Height = -11
 Font.Name = 'MS Sans Serif'
 Font.Style = []
 Menu = MainMenu1
 OldCreateOrder = False
 OnCreate = FormCreate
 OnDestroy = FormDestroy
 PixelsPerInch = 96
 TextHeight = 13
 object Label1: TLabel
   Left = 0
   Top = 0
   Width = 747
   Height = 13
   Align = alTop
 end
 object Label2: TLabel
   Left = 323
   Top = 22
   Width = 85
   Height = 13
   Caption = 'Destination Folfer:'
 end
 object DBGridEh1: TDBGridEh
   Left = 0
   Top = 13
   Width = 320
   Height = 421
   Align = alLeft
   DataSource = DataSource1
   Flat = True
   FooterColor = clWindow
   FooterFont.Charset = DEFAULT_CHARSET
   FooterFont.Color = clWindowText
   FooterFont.Height = -11
   FooterFont.Name = 'MS Sans Serif'
   FooterFont.Style = []
   TabOrder = 0
   TitleFont.Charset = DEFAULT_CHARSET
   TitleFont.Color = clWindowText
   TitleFont.Height = -11
   TitleFont.Name = 'MS Sans Serif'
   TitleFont.Style = []
   Columns = <
     item
       EditButtons =
       FieldName = 'StopCadr'
       Footers =
       Title.Alignment = taCenter
       Title.Caption = 'Ñòîï-êàäðû, ìèëëèñåêóíäû'
       Width = 264
     end>
 end
 object DirectoryEdit1: TDirectoryEdit
   Left = 412
   Top = 18
   Width = 327
   Height = 21
   NumGlyphs = 1
   TabOrder = 1
 end
 object BitBtn1: TBitBtn
   Left = 323
   Top = 64
   Width = 75
   Height = 25
   Caption = '&Run'
   TabOrder = 2
   OnClick = BitBtn1Click
   Glyph.Data = {
     76010000424D7601000000000000760000002800000020000000100000000100
     04000000000000010000120B0000120B00001000000000000000000000000000
     800000800000008080008000000080008000808000007F7F7F00BFBFBF000000
     FF0000FF000000FFFF00FF000000FF00FF00FFFF0000FFFFFF00333333000000
     033333FFFF77777773F330000077777770333777773FFFFFF733077777000000
     03337F3F3F777777733F0797A770003333007F737337773F3377077777778803
     30807F333333337FF73707888887880007707F3FFFF333777F37070000878807
     07807F777733337F7F3707888887880808807F333333337F7F37077777778800
     08807F333FFF337773F7088800088803308073FF777FFF733737300008000033
     33003777737777333377333080333333333333F7373333333333300803333333
     33333773733333333333088033333333333373F7F33333333333308033333333
     3333373733333333333333033333333333333373333333333333}
   NumGlyphs = 2
 end
 object MainMenu1: TMainMenu
   Left = 14
   Top = 32
   object File1: TMenuItem
     Caption = '&File'
     object Load1: TMenuItem
       Caption = '&Load ...'
       OnClick = Load1Click
     end
   end
 end
 object OpenDialog1: TOpenDialog
   Filter = 'AVI-files|*.avi|All files|*.*'
   Left = 46
   Top = 32
 end
 object RxMemoryData1: TRxMemoryData
   Active = True
   FieldDefs = <
     item
       Name = 'StopCadr'
       DataType = ftLargeint
     end>
   Left = 14
   Top = 66
   object RxMemoryData1StopCadr: TLargeintField
     FieldName = 'StopCadr'
   end
 end
 object DataSource1: TDataSource
   DataSet = RxMemoryData1
   Left = 46
   Top = 66
 end
end


Анонимщик1   (2005-04-17 22:39:00) [10]

Есть, кончено. У меня.


Eraser   (2005-04-17 00:26:00) [11]

LA

Поддерживаю!


LA   (2005-04-16 20:57:00) [12]

это все, конечно, хорошо... только вот слова оверлей, DirectShow, SampleGrabber ничего мне не говорят (разве лишь говорят то, что где-то я их уже слышал) :(... может быть имеется уже готовый код, который это все делает?


Анонимщик1   (2005-04-15 14:29:00) [13]

Зато в ней оверлея нет. Во всяком случае для простых avi сделать токое несложно все с помощью того же DirectShow. Хотя для более сложных случаев тоже можно, главное, чтобы декодеры были соответсвующие и давали возможность выстроить цепочку фильтров с SampleGrabber'ом. Сложность может быть в случае, когда декодер заточен под выдачу видео именно на оверлей (есть такие, сам сталкивался, хотя для них есть возможность отключать такую опцию). Еще одна проблема - непосредственная попытка соединения фильтра файла-источника и SampleGrabber'а. Дело в том, что IntelligentConnect не всегда правильно понимает, что о него требуется, и подсовывает соединение с граббером через аудиоконтакт, например. Ну, в таком случае можно либо вручную строить весь граф, либо, если есть желание помучиться, сделать файлу Render, потом убрать аудиоветвь, найти VideoRenderer, и вместо него подставить соединение с SampleGrabber'ом, а затем все сливать на NullRenderer. Сам же файл проигрывать не нужно, достаточно только позиционироваться с помощью интерфейса IMediaSeeking, а, чтобы при проигрывании не было лишних кадров, вызвать метод ISampleGrabber'а - SetOneShot(TRUE).


Eraser   (2005-04-15 14:14:00) [14]

LA

Ну это уже немного другая задача... тут внутрь avi файла лезть надо.


Анонимщик1   (2005-04-15 11:34:00) [15]

>> LA
Вот интересно, с чего эта тема стала такой популярной последнее время?


LA   (2005-04-14 23:53:00) [16]

а конкретный код у кого-нибудь имеется? поделитесь, плз...
причем, мне нужно сделать скриншоты с фильмов, например, на 10-ой, 30-ой и 60-ой минутах фильма... желательно, чтобы сам этот фильм не отображался... т.е. проге подсовывается файл и она в заданную папку генерит скрины...


Eraser   (2005-04-14 22:00:00) [17]

Sapersky
Но вроде как просил "именно для оверлея", вот я и изощряюсь... :)


Вообще я любому совету по этой теме рад! ))
Задача "проста"- перехватить картинку в Media плеере, например...


Sapersky   (2005-04-14 21:30:00) [18]

Есть способ проще - отключить оверлей, чтобы видео выводилось на обычную поверхность. Делается в настройках фильтра "Video Renderer", причём эти настройки глобальны для DirectShow, так что, наверное, их можно поменять в своей программе.
Но вроде как просил "именно для оверлея", вот я и изощряюсь... :)


Eraser   (2005-04-14 15:52:00) [19]

Sapersky

ИМХО есть способ проще... существует ряд программ, которые умеют делать принт скрин медиаплееров... может надо DC брать (getwindowDC) конкретно у окна отображения, а не всего десктопа...?


Sapersky   (2005-04-14 12:24:00) [20]

Попробовал ради интереса сделать по методу [4]. С оверлеем для DX7 работает, а с медиаплеером не хочет. Ну, правильно - даже если используется DirectDraw, зачем MS обращаться к нему через интерфейсы? Они же непосредственно объекты могут использовать.

Так что если делать перехватом функций - нужно влезать в DirectShow. Здесь я не специалист... Но если в DirectShow-программе в принципе можно получить кадр видео, независимо от метода вывода (что-то было недавно про SampleGrabber - или это только для видеозахвата?) - тогда можно заставить это сделать и посторонний медиаплеер.

Что касается драйвера... Ну, получим доступ к памяти - а как оверлей в ней искать?


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо