Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 1 369

/ вопрос открыт /

Доброго времени суток, уважаемые эксперты! Имеется следующий модуль.
Вопрос: как выводить какое-нибудь сообщение при переименовании папки, т.е.
SH.WatchEvents:=[neFolderRename];
а дальше где и что я должен написать, чтобы увидеть, что данное событие произошло?

Приложение:
  1. <-------------- Begin UNIT code ---------------------------->
  2.  
  3. {$IFNDEF VER80} {$IFNDEF VER90} {$IFNDEF VER93}
  4. {$DEFINE Delphi3orHigher}
  5. {$ENDIF} {$ENDIF} {$ENDIF}
  6.  
  7. unit ShellNotify;
  8. interface
  9.  
  10. uses Windows, Messages, SysUtils, Classes, Controls, Forms, Dialogs,
  11. {$IFNDEF Delphi3orHigher} OLE2, {$ELSE} ActiveX, ComObj, {$ENDIF}
  12. ShlObj;
  13.  
  14. type
  15. NOTIFYREGISTER = record
  16. pidlPath : PItemIDList;
  17. bWatchSubtree : boolean;
  18. end;
  19.  
  20. PNOTIFYREGISTER = ^NOTIFYREGISTER;
  21.  
  22. const
  23. SNM_SHELLNOTIFICATION = WM_USER +1;
  24. SHCNF_ACCEPT_INTERRUPTS = $0001;
  25. SHCNF_ACCEPT_NON_INTERRUPTS = $0002;
  26. SHCNF_NO_PROXY = $8000;
  27.  
  28. type
  29. TNotificationEvent = (neAssociationChange, neAttributesChange,
  30. neFileChange, neFileCreate, neFileDelete, neFileRename,
  31. neDriveAdd, neDriveRemove, neShellDriveAdd, neDriveSpaceChange,
  32. neMediaInsert, neMediaRemove, neFolderCreate, neFolderDelete,
  33. neFolderRename, neFolderUpdate, neNetShare, neNetUnShare,
  34. neServerDisconnect, neImageListChange);
  35. TNotificationEvents = set of TNotificationEvent;
  36.  
  37. TShellNotificationEvent1 = procedure(Sender: TObject;
  38. Path: String)of Object;
  39. TShellNotificationEvent2 = procedure(Sender: TObject;
  40. path1, path2: String) of Object;
  41. // TShellNotificationAttributesEvent = procedure(Sender: TObject;
  42. // OldAttribs, NewAttribs: Integer) of Object;
  43.  
  44. TShellNotification = class( TComponent )
  45. private
  46. fWatchEvents: TNotificationEvents;
  47. fPath: String;
  48. fActive, fWatch: Boolean;
  49.  
  50. prevPath1, prevPath2: String;
  51. PrevEvent: Integer;
  52.  
  53. Handle, NotifyHandle: HWND;
  54.  
  55. fOnAssociationChange: TNotifyEvent;
  56. fOnAttribChange: TShellNotificationEvent2;
  57. FOnCreate: TShellNotificationEvent1;
  58. FOnDelete: TShellNotificationEvent1;
  59. FOnDriveAdd: TShellNotificationEvent1;
  60. FOnDriveAddGui: TShellNotificationEvent1;
  61. FOnDriveRemove: TShellNotificationEvent1;
  62. FOnMediaInsert: TShellNotificationEvent1;
  63. FOnMediaRemove: TShellNotificationEvent1;
  64. FOnDirCreate: TShellNotificationEvent1;
  65. FOnNetShare: TShellNotificationEvent1;
  66. FOnNetUnShare: TShellNotificationEvent1;
  67. FOnRenameFolder: TShellNotificationEvent2;
  68. FOnItemRename: TShellNotificationEvent2;
  69. FOnFolderRemove: TShellNotificationEvent1;
  70. FOnServerDisconnect: TShellNotificationEvent1;
  71. FOnFolderUpdate: TShellNotificationEvent1;
  72.  
  73. function PathFromPidl(Pidl: PItemIDList): String;
  74. procedure SetWatchEvents(const Value: TNotificationEvents);
  75. function GetActive: Boolean;
  76. procedure SetActive(const Value: Boolean);
  77. procedure SetPath(const Value: String);
  78. procedure SetWatch(const Value: Boolean);
  79. protected
  80. procedure ShellNotifyRegister;
  81. procedure ShellNotifyUnregister;
  82. procedure WndProc(var Message: TMessage);
  83.  
  84. procedure DoAssociationChange; dynamic;
  85. procedure DoAttributesChange(Path1, Path2: String); dynamic;
  86. procedure DoCreateFile(Path: String); dynamic;
  87. procedure DoDeleteFile(Path: String); dynamic;
  88. procedure DoDriveAdd(Path:String); dynamic;
  89. procedure DoDriveAddGui(Path: String); dynamic;
  90. procedure DoDriveRemove(Path: String); dynamic;
  91. procedure DoMediaInsert(Path: String); dynamic;
  92. procedure DoMediaRemove(Path: String); dynamic;
  93. procedure DoDirCreate(Path: String); dynamic;
  94. procedure DoNetShare(Path: String); dynamic;
  95. procedure DoNetUnShare(Path: String); dynamic;
  96. procedure DoRenameFolder(Path1, Path2: String); dynamic;
  97. procedure DoRenameItem(Path1, Path2: String); dynamic;
  98. procedure DoFolderRemove(Path: String); dynamic;
  99. procedure DoServerDisconnect(Path: String); dynamic;
  100. procedure DoDirUpdate(Path: String); dynamic;
  101. public
  102. constructor Create(AOwner: TComponent); override;
  103. destructor Destroy; override;
  104. published
  105. property Path: String read fPath write SetPath;
  106. property Active: Boolean read GetActive write SetActive;
  107. property WatchSubTree: Boolean read fWatch write SetWatch;
  108.  
  109. property WatchEvents: TNotificationEvents
  110. read fWatchEvents write SetWatchEvents;
  111.  
  112. property OnAssociationChange: TNotifyEvent
  113. read fOnAssociationChange write FOnAssociationChange;
  114.  
  115. property OnAttributesChange: TShellNotificationEvent2
  116. read fOnAttribChange write fOnAttribChange;
  117.  
  118. property OnFileCreate: TShellNotificationEvent1
  119. read FOnCreate write FOnCreate;
  120.  
  121. property OnFolderRename: TShellNotificationEvent2
  122. read FOnRenameFolder write FOnRenameFolder;
  123.  
  124. property OnFolderUpdate: TShellNotificationEvent1
  125. read FOnFolderUpdate write FOnFolderUpdate;
  126.  
  127. property OnFileDelete: TShellNotificationEvent1
  128. read FOnDelete write FOnDelete;
  129.  
  130. property OnDriveAdd: TShellNotificationEvent1
  131. read FOnDriveAdd write FOnDriveAdd;
  132.  
  133. property OnFolderRemove: TShellNotificationEvent1
  134. read FOnFolderRemove write FOnFolderRemove;
  135.  
  136. property OnItemRename: TShellNotificationEvent2
  137. read FOnItemRename write FOnItemRename;
  138.  
  139. property OnDriveAddGui: TShellNotificationEvent1
  140. read FOnDriveAddGui write FOnDriveAddGui;
  141.  
  142. property OnDriveRemove: TShellNotificationEvent1
  143. read FOnDriveRemove write FOnDriveRemove;
  144.  
  145. property OnMediaInserted: TShellNotificationEvent1
  146. read FOnMediaInsert write FOnMediaInsert;
  147.  
  148. property OnMediaRemove: TShellNotificationEvent1
  149. read FOnMediaRemove write FOnMediaRemove;
  150.  
  151. property OnDirCreate: TShellNotificationEvent1
  152. read FOnDirCreate write FOnDirCreate;
  153.  
  154. property OnNetShare: TShellNotificationEvent1
  155. read FOnNetShare write FOnNetShare;
  156.  
  157. property OnNetUnShare: TShellNotificationEvent1
  158. read FOnNetUnShare write FOnNetUnShare;
  159.  
  160. property OnServerDisconnect: TShellNotificationEvent1
  161. read FOnServerDisconnect write FOnServerDisconnect;
  162. end;
  163.  
  164. function SHChangeNotifyRegister( hWnd: HWND; dwFlags: integer;
  165. wEventMask : cardinal; uMsg: UINT; cItems : integer;
  166. lpItems : PNOTIFYREGISTER) : HWND; stdcall;
  167. function SHChangeNotifyDeregister(hWnd: HWND) : boolean; stdcall;
  168. function SHILCreateFromPath(Path: Pointer; PIDL: PItemIDList;
  169. var Attributes: ULONG):HResult; stdcall;
  170. implementation
  171.  
  172. const Shell32DLL = 'shell32.dll';
  173.  
  174. function SHChangeNotifyRegister; external Shell32DLL index 2;
  175. function SHChangeNotifyDeregister; external Shell32DLL index 4;
  176. function SHILCreateFromPath; external Shell32DLL index 28;
  177.  
  178. { TShellNotification }
  179.  
  180. constructor TShellNotification.Create(AOwner: TComponent);
  181. begin
  182. inherited Create( AOwner );
  183. if not (csDesigning in ComponentState) then
  184. Handle := AllocateHWnd(WndProc);
  185. end;
  186.  
  187. destructor TShellNotification.Destroy;
  188. begin
  189. if not (csDesigning in ComponentState) then
  190. Active := False;
  191. if Handle <> 0 then DeallocateHWnd( Handle );
  192. inherited Destroy;
  193. end;
  194.  
  195. procedure TShellNotification.DoAssociationChange;
  196. begin
  197. if Assigned( fOnAssociationChange ) and (neAssociationChange in fWatchEvents) then
  198. fOnAssociationChange( Self );
  199. end;
  200.  
  201. procedure TShellNotification.DoAttributesChange;
  202. begin
  203. if Assigned( fOnAttribChange ) then
  204. fOnAttribChange( Self, Path1, Path2 );
  205. end;
  206.  
  207. procedure TShellNotification.DoCreateFile(Path: String);
  208. begin
  209. if Assigned( fOnCreate ) then
  210. FOnCreate(Self, Path)
  211. end;
  212.  
  213. procedure TShellNotification.DoDeleteFile(Path: String);
  214. begin
  215. if Assigned( FOnDelete ) then
  216. FOnDelete(Self, Path);
  217. end;
  218.  
  219. procedure TShellNotification.DoDirCreate(Path: String);
  220. begin
  221. if Assigned( FOnDirCreate ) then
  222. FOnDirCreate( Self, Path );
  223. end;
  224.  
  225. procedure TShellNotification.DoDirUpdate(Path: String);
  226. begin
  227. if Assigned( FOnFolderUpdate ) then
  228. FOnFolderUpdate(Self, Path);
  229. end;
  230.  
  231. procedure TShellNotification.DoDriveAdd(Path: String);
  232. begin
  233. if Assigned( FOnDriveAdd ) then
  234. FOnDriveAdd(Self, Path);
  235. end;
  236.  
  237. procedure TShellNotification.DoDriveAddGui(Path: String);
  238. begin
  239. if Assigned( FOnDriveAddGui ) then
  240. FOnDriveAdd(Self, Path);
  241. end;
  242.  
  243. procedure TShellNotification.DoDriveRemove(Path: String);
  244. begin
  245. if Assigned( FOnDriveRemove ) then
  246. FOnDriveRemove(Self, Path);
  247. end;
  248.  
  249. procedure TShellNotification.DoFolderRemove(Path: String);
  250. begin
  251. if Assigned(FOnFolderRemove) then
  252. FOnFolderRemove( Self, Path );
  253. end;
  254.  
  255. procedure TShellNotification.DoMediaInsert(Path: String);
  256. begin
  257. if Assigned( FOnMediaInsert ) then
  258. FOnMediaInsert(Self, Path);
  259. end;
  260.  
  261. procedure TShellNotification.DoMediaRemove(Path: String);
  262. begin
  263. if Assigned(FOnMediaRemove) then
  264. FOnMediaRemove(Self, Path);
  265. end;
  266.  
  267. procedure TShellNotification.DoNetShare(Path: String);
  268. begin
  269. if Assigned(FOnNetShare) then
  270. FOnNetShare(Self, Path);
  271. end;
  272.  
  273. procedure TShellNotification.DoNetUnShare(Path: String);
  274. begin
  275. if Assigned(FOnNetUnShare) then
  276. FOnNetUnShare(Self, Path);
  277. end;
  278.  
  279. procedure TShellNotification.DoRenameFolder(Path1, Path2: String);
  280. begin
  281. if Assigned( FOnRenameFolder ) then
  282. FOnRenameFolder(Self, Path1, Path2);
  283. end;
  284.  
  285. procedure TShellNotification.DoRenameItem(Path1, Path2: String);
  286. begin
  287. if Assigned( FOnItemRename ) then
  288. FonItemRename(Self, Path1, Path2);
  289. end;
  290.  
  291. procedure TShellNotification.DoServerDisconnect(Path: String);
  292. begin
  293. if Assigned( FOnServerDisconnect ) then
  294. FOnServerDisconnect(Self, Path);
  295. end;
  296.  
  297. function TShellNotification.GetActive: Boolean;
  298. begin
  299. Result := (NotifyHandle <> 0) and (fActive);
  300. end;
  301.  
  302. function TShellNotification.PathFromPidl(Pidl: PItemIDList): String;
  303. begin
  304. SetLength(Result, Max_Path);
  305. if not SHGetPathFromIDList(Pidl, PChar(Result)) then Result := '';
  306. if pos(#0, Result) > 0 then
  307. SetLength(Result, pos(#0, Result));
  308. end;
  309.  
  310. procedure TShellNotification.SetActive(const Value: Boolean);
  311. begin
  312. if (Value <> fActive) then
  313. begin
  314. fActive := Value;
  315. if fActive then ShellNotifyRegister else ShellNotifyUnregister;
  316. end;
  317. end;
  318.  
  319. procedure TShellNotification.SetPath(const Value: String);
  320. begin
  321. if fPath <> Value then
  322. begin
  323. fPath := Value;
  324. ShellNotifyRegister;
  325. end;
  326. end;
  327.  
  328. procedure TShellNotification.SetWatch(const Value: Boolean);
  329. begin
  330. if fWatch <> Value then
  331. begin
  332. fWatch := Value;
  333. ShellNotifyRegister;
  334. end;
  335. end;
  336.  
  337. procedure TShellNotification.SetWatchEvents(
  338. const Value: TNotificationEvents);
  339. begin
  340. if fWatchEvents <> Value then
  341. begin
  342. fWatchEvents := Value;
  343. ShellNotifyRegister;
  344. end;
  345. end;
  346.  
  347. procedure TShellNotification.ShellNotifyRegister;
  348. var
  349. NotifyRecord: PNOTIFYREGISTER;
  350. Flags: DWORD;
  351. Pidl: PItemIDList;
  352. Attributes: ULONG;
  353. begin
  354. if not (csDesigning in ComponentState) and
  355. not (csLoading in ComponentState) then
  356. begin
  357. SHILCreatefromPath( PChar(fPath), Addr(Pidl), Attributes);
  358. NotifyRecord^.pidlPath := Pidl;
  359. NotifyRecord^.bWatchSubtree := fWatch;
  360.  
  361. if NotifyHandle <> 0 then ShellNotifyUnregister;
  362. Flags := 0;
  363. if neAssociationChange in FWatchEvents then
  364. Flags := Flags or SHCNE_ASSOCCHANGED;
  365. if neAttributesChange in FWatchEvents then
  366. Flags := Flags or SHCNE_ATTRIBUTES;
  367. if neFileChange in FWatchEvents then
  368. Flags := Flags or SHCNE_UPDATEITEM;
  369. if neFileCreate in FWatchEvents then
  370. Flags := Flags or SHCNE_CREATE;
  371. if neFileDelete in FWatchEvents then
  372. Flags := Flags or SHCNE_DELETE;
  373. if neFileRename in FWatchEvents then
  374. Flags := Flags or SHCNE_RENAMEITEM;
  375. if neDriveAdd in FWatchEvents then
  376. Flags := Flags or SHCNE_DRIVEADD;
  377. if neDriveRemove in FWatchEvents then
  378. Flags := Flags or SHCNE_DRIVEREMOVED;
  379. if neShellDriveAdd in FWatchEvents then
  380. Flags := Flags or SHCNE_DRIVEADDGUI;
  381. if neDriveSpaceChange in FWatchEvents then
  382. Flags := Flags or SHCNE_FREESPACE;
  383. if neMediaInsert in FWatchEvents then
  384. Flags := Flags or SHCNE_MEDIAINSERTED;
  385. if neMediaRemove in FWatchEvents then
  386. Flags := Flags or SHCNE_MEDIAREMOVED;
  387. if neFolderCreate in FWatchEvents then
  388. Flags := Flags or SHCNE_MKDIR;
  389. if neFolderDelete in FWatchEvents then
  390. Flags := Flags or SHCNE_RMDIR;
  391. if neFolderRename in FWatchEvents then
  392. Flags := Flags or SHCNE_RENAMEFOLDER;
  393. if neFolderUpdate in FWatchEvents then
  394. Flags := Flags or SHCNE_UPDATEDIR;
  395. if neNetShare in FWatchEvents then
  396. Flags := Flags or SHCNE_NETSHARE;
  397. if neNetUnShare in FWatchEvents then
  398. Flags := Flags or SHCNE_NETUNSHARE;
  399. if neServerDisconnect in FWatchEvents then
  400. Flags := Flags or SHCNE_SERVERDISCONNECT;
  401. if neImageListChange in FWatchEvents then
  402. Flags := Flags or SHCNE_UPDATEIMAGE;
  403. NotifyHandle := SHChangeNotifyRegister(Handle,
  404. SHCNF_ACCEPT_INTERRUPTS or SHCNF_ACCEPT_NON_INTERRUPTS,
  405. Flags, SNM_SHELLNOTIFICATION, 1, NotifyRecord);
  406. end;
  407. end;
  408.  
  409. procedure TShellNotification.ShellNotifyUnregister;
  410. begin
  411. if NotifyHandle <> 0 then
  412. SHChangeNotifyDeregister(NotifyHandle);
  413. end;
  414.  
  415. procedure TShellNotification.WndProc(var Message: TMessage);
  416. type
  417. TPIDLLIST = record
  418. pidlist : array[1..2] of PITEMIDLIST;
  419. end;
  420. PIDARRAY = ^TPIDLLIST;
  421. var
  422. Path1 : string;
  423. Path2 : string;
  424. ptr : PIDARRAY;
  425. repeated : boolean;
  426. event : longint;
  427.  
  428. begin
  429. case Message.Msg of
  430. SNM_SHELLNOTIFICATION:
  431. begin
  432. event := Message.LParam and ($7FFFFFFF);
  433. Ptr := PIDARRAY(Message.WParam);
  434.  
  435. Path1 := PathFromPidl( Ptr^.pidlist[1] );
  436. Path2 := PathFromPidl( Ptr^.pidList[2] );
  437.  
  438. repeated := (PrevEvent = event)
  439. and (uppercase(prevpath1) = uppercase(Path1))
  440. and (uppercase(prevpath2) = uppercase(Path2));
  441.  
  442. if Repeated then exit;
  443.  
  444. PrevEvent := Message.Msg;
  445. prevPath1 := Path1;
  446. prevPath2 := Path2;
  447.  
  448. case event of
  449. SHCNE_ASSOCCHANGED : DoAssociationChange;
  450. SHCNE_ATTRIBUTES : DoAttributesChange( Path1, Path2);
  451. SHCNE_CREATE : DoCreateFile(Path1);
  452. SHCNE_DELETE : DoDeleteFile(Path1);
  453. SHCNE_DRIVEADD : DoDriveAdd(Path1);
  454. SHCNE_DRIVEADDGUI : DoDriveAddGui(path1);
  455. SHCNE_DRIVEREMOVED : DoDriveRemove(Path1);
  456. SHCNE_MEDIAINSERTED : DoMediaInsert(Path1);
  457. SHCNE_MEDIAREMOVED : DoMediaRemove(Path1);
  458. SHCNE_MKDIR : DoDirCreate(Path1);
  459. SHCNE_NETSHARE : DoNetShare(Path1);
  460. SHCNE_NETUNSHARE : DoNetUnShare(Path1);
  461. SHCNE_RENAMEFOLDER : DoRenameFolder(Path1, Path2);
  462. SHCNE_RENAMEITEM : DoRenameItem(Path1, Path2);
  463. SHCNE_RMDIR : DoFolderRemove(Path1);
  464. SHCNE_SERVERDISCONNECT : DoServerDisconnect(Path);
  465. SHCNE_UPDATEDIR : DoDirUpdate(Path);
  466. SHCNE_UPDATEIMAGE : ;
  467. SHCNE_UPDATEITEM : ;
  468. end;//Case event of
  469. end;//SNM_SHELLNOTIFICATION
  470. end; //case
  471. end;
  472.  
  473. end.
  474.  
  475.  
  476.  
  477. unit Unit1;
  478.  
  479. interface
  480.  
  481. uses
  482. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  483. Dialogs, StdCtrls, ShellNotify1;
  484.  
  485. type
  486. TForm1 = class(TForm)
  487. Button1: TButton;
  488. procedure FormClick(Sender: TObject);
  489. private
  490. { Private declarations }
  491. public
  492. { Public declarations }
  493. end;
  494.  
  495. var
  496. Form1: TForm1;
  497. sh:TShellNotification;
  498. implementation
  499.  
  500. {$R *.dfm}
  501.  
  502. procedure TForm1.FormClick(Sender: TObject);
  503. begin
  504. SH:=TShellNotification.Create(self);
  505. SH.Active:=True;
  506. SH.Path:='C:\Temp';
  507. SH.WatchSubTree:=True;
  508. SH.WatchEvents:=[neFolderRename];
  509. end;
  510.  
  511. end.


Иванов Вопрос ожидает решения (принимаются ответы, доступен мини-форум)

Вопрос задал: Иванов (статус: Посетитель)
Вопрос отправлен: 23 февраля 2008, 21:02
Состояние вопроса: открыт, ответов: 1.

Ответ #1. Отвечает эксперт: Вадим К

Здравствуйте, Иванов!
Скопировал я ваш код и запустил. И приложение ругнулось. Присмотревшись к коду, я заметил, что в процедуре ShellNotifyRegister используется структура NotifyRecord: PNOTIFYREGISTER, но память под неё не выделяется. Странно, у вас оно не ругалость при запуске? хотя может и нет, так как у вас создание объекта повешено на клик по форме, но я надеюсь, что вы его делали.
Я добавил выделение памяти - у меня получилось где то так

 begin
    SHILCreatefromPath(PChar(fPath), Addr(Pidl), Attributes);
    New(NotifyRecord); //<-- вставленная строка
    NotifyRecord^.pidlPath      := Pidl;
Теперь по поводу обработки события. вообще то данный код - это компонент, соответсвенно нужно подцепить обрабочик. Эта тема неоднократно обсуждалась в интернете и книгах, но к данному случаю напишу последовательность действий.
Вначале смотрим, что интересующий нас обработчкик обявлен как FOnRenameFolder: TShellNotificationEvent2;
смотрим объявление TShellNotificationEvent2 и видим сигнатуру процедуры для обработки.
Теперь переходим к форме, идем в раздел private и пишем такое
  private
     procedure MyRenameEvents(Sender: TObject; path1, path2: string);
Понятно, что имя я выбрал произвольно (но конечно в согласии с правилами делфи. Теперь, оставивь курсор на этой строке (если точнее - то внутри обявления формы) и жмем Ctrl+Shift+C. Делфи делает для нас обрабочик.
так как я приблизительно догадываюсь, что означают параметры, но не знаю точно, то я поступаю так - ставлю на форму компонент Memo1, а обработчик дополняю таким кодом.
procedure TForm2.MyRenameEvents(Sender: TObject; path1, path2: string);
begin
  Memo1.Lines.Add('Path1 = ' + path1);
  Memo1.Lines.Add('Path2 = ' + path2);
  Memo1.Lines.Add('-------------------------');
end;
Осталось мелочь - привязать этот обработчик к компоненту. для этого идём к месту его создания и дописываем в конец такую строку
sh.OnFolderRename := MyRenameEvents;
Запускаем проект и переименовываем в папке temp заранее подготовленную папку. Видим в, что в мемо начали появляться записи. path1 соответствует старому имени папки, а path2 - новому. Вот только почему обработчик вызывается дважды я не разбирался. беглый осмотр кода не показал причин.

Ответ отправил: Вадим К (статус: Академик)
Время отправки: 23 февраля 2008, 23:26
Оценка за ответ: 5


Мини-форум вопроса

Мини-форум пуст.

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 11:36
Выполнено за 0.03 сек.