Перейти к содержанию
Fire Monkey от А до Я
  • 0

[Delphi Berlin FMX Win32] Как реализовать двойной клик на ячейке в StringGrid?


brunnengi

Вопрос

Здравствуйте.

Использую StringGrid. В списке событий нет событий Click и DbClick. Есть только OnTap
Как реализовать отлов двойного клика, клика правой кнопкой мыши на строке в StrnigGrid?

Ссылка на комментарий

Рекомендуемые сообщения

  • 0
15 часов назад, Akad сказал:

Через StringGrid1.OnClick := например. Хз почему не выведены эти события в дизайнер.
 

Потому, что Х3 как определить то, что находится в гриде под курсором (обычная ячейка, недоступная ячейка, редактор ячейки, заголовок, пустое место), особенно в момент скроллирования на телефоне где и мыши-то нет. И ХЗ когда менять выделенную ячейку до срабатывания события, после срабатывания события, после первого клика, или после второго. И ХЗ как реагировать самому гриду на клик, если пользователь сам уже что-то сделал...

Поэтому в дизайнер введены другие события например OnSelectCellOnCellDblClick, которые срабатывают в таком порядке
OnSelectCell
OnSelChanged
OnCellClick
OnCellDblClick

Изменено пользователем RoschinSpb
Ссылка на комментарий
  • 0
  • Модераторы

оставлю это здесь

Скрытый текст

unit uMain;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, System.Rtti, FMX.Grid.Style, FMX.Controls.Presentation,
  FMX.ScrollBox, FMX.Grid;

type
  TStringGrid = class(FMX.Grid.TStringGrid)
  public
    property OnDblClick;
  end;

  TForm6 = class(TForm)
    StringGrid1: TStringGrid;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure MyDblClick(Sender: TObject);
  end;

var
  Form6: TForm6;

implementation

{$R *.fmx}

procedure TForm6.FormCreate(Sender: TObject);
begin
  StringGrid1.OnDblClick := MyDblClick;
end;

procedure TForm6.MyDblClick(Sender: TObject);
begin
  ShowMessage('DblClick');
end;

end.

 

Ссылка на комментарий
  • 0
В 11 ноября 2017 г. в 14:26, RoschinSpb сказал:

Потому, что Х3 как определить то, что находится в гриде под курсором (обычная ячейка, недоступная ячейка, редактор ячейки, заголовок, пустое место), особенно в момент скроллирования на телефоне где и мыши-то нет.

Извиняюсь, а какое отношение скроллирование имеет к клику? Клик это нажатие, удерживание и отпускание клавиши мыши в одном (примерно) месте. Скроллирование - это перемещение во время нажатия. 2 абсолютно разных действия. Двойной клик по аналогии.

В 11 ноября 2017 г. в 14:26, RoschinSpb сказал:

И ХЗ когда менять выделенную ячейку до срабатывания события, после срабатывания события, после первого клика, или после второго. И ХЗ как реагировать самому гриду на клик, если пользователь сам уже что-то сделал..

Ну тоже самое. Клик произошёл. Так что выделена ячейка должна быть под точкой клика.

P.S. а как без этих событий вообще работать с гридом в режиме [RowLines]? OnDblClick глючноват, но какие варианты? OnCellDblClick ведь сериализировать нельзя на единый обработчик кликов. Писать очередной велосипед, выполняя то, что обязан выполнять сам компонент?
 

Ссылка на комментарий
  • 0
18 часов назад, Akad сказал:

Извиняюсь, а какое отношение скроллирование имеет к клику? Клик это нажатие, удерживание и отпускание клавиши мыши в одном (примерно) месте. Скроллирование - это перемещение во время нажатия. 2 абсолютно разных действия. Двойной клик по аналогии.

Ну тоже самое. Клик произошёл. Так что выделена ячейка должна быть под точкой клика.

P.S. а как без этих событий вообще работать с гридом в режиме [RowLines]? OnDblClick глючноват, но какие варианты? OnCellDblClick ведь сериализировать нельзя на единый обработчик кликов. Писать очередной велосипед, выполняя то, что обязан выполнять сам компонент?
 

Обрабатывать OnDblClick - это и есть изобретение своего велосипеда и выполнение того, что должен выполнять сам компонент. Все просто в простейших контролах типа кнопки, когда не предусмотрено ни какой другой логики кроме выполнения события. А вот для TSwitch не всё так однозначно, там поведение уже более сложное (можно его переключить сдвинув пальцем и это не будет кликом). В Grid совсем все сложно. Логика поведения навороченная и любая отсябятина её поломает с непредсказуемыми последствиями.

Клик произошёл. Так что выделена ячейка должна быть под точкой клика. А кто-то (и таких людей наберется не мало) может сказать, "по клику я хочу сам выделить ячейку ту, которую считаю нужной, а не ту на которую ткнул пользователь". Допустим в одном столбце картинка во втором значение и по клику на картинку я хочу выделить соседнюю ячейку с изменяемым параметром. Кроме того не факт, что под курсором оказалась "не задизабленая" ячейка, об этом должен не забыть подумать прикладной программист.
Скроллирование тут при том, нажатие и отпускание мыши (пальца) происходит примерно в рандомном месте (два раза). На нажатие-отпускание пальца реакция может быть разной, скроллирование может остановиться/замедлится/пойти в другую сторону, при долгом нажатии остановиться и выделиться ячейка.

OnCellDblClick ведь сериализировать нельзя на единый обработчик кликов. Так и да, сделать два обработчика вместо одного — воистину адская по сложности работа :o) Да и странно, что таблица реагирует на нажатие также как кнопка, хотя всякое бывает.

scenic.gif.ac82105b5c6f6dd100d54c102eccae8a.gifЕсли продолжить философские рассуждения,
то на контролах не должно было быть событий относящихся к аппаратным средствам. Потому, что на разных платформах может быть мышь, а может сенсорный экран что на первый взгляд похоже но не совсем одно и то же, а может быть и то и другое, кстати и в этом разобраться очень трудно. Должны быть события относящиеся именно к контролам, к примеру вместо OnClick на кнопкообразных контролах должно быть что-то типа OnExecute. Может кликнули мышью, может ткнули пальцем, может нажали пробел на клавиатуре, может сдвинули пальцем переключатель, может еще что угодно о чем нам знать не обязательно и за это отвечает контрол — но в итоге произошло нечто в результате чего мы должны выполнить некоторое действие.
Также и в Grid можно десятью способами реагировать на разные клики/жесты в разных местах на разных платформах (включая будущие). На сколько правильно остаётся на совести компонента. Прикладной программист обрабатывает события не вдаваясь в подробности о том, в результате каких манипуляций они произошли, но реализует логику работы о которой можно догадаться из названия или краткой справки. Например OnSelectCell - неважно что произошло в подлунном мире, но грид хочет знать можно ли выделить определенную ячейку. OnSelChanged - опять, ни кого не интересует каким образом это произошло, но выделенная ячейка поменялась. OnExecute - надо выполнить какое-то действие. OnAltExecute - надо выполнить какое-то альтернативное действие и т.п.

К сожалению изначально на эту тему не задумывались. Сохранили совместимость с виндовой VCL там, где этого не следовало делать. Зато поломали совместимость там где в этом не было серьезной необходимости
Caption -> Text;
Left, Top: Integer -> Position.X, Position.Y: Single;
Font.Color -> FontColor

А ведь если бы можно было VCL-ный dfm запустить на андроиде... не, это было бы конечно не так круто, как натянуть грид на грани вращающегося куба, но гораздо более востребовано на практике.

Ссылка на комментарий
  • 0
2 часа назад, RoschinSpb сказал:

Обрабатывать OnDblClick - это и есть изобретение своего велосипеда и выполнение того, что должен выполнять сам компонент.

Мне нужен факт двойного клика (двойного тапа и т.д. в общем экшена для выбранной строки). Если это мне не даёт OnDblClick, то это как минимум... эмммм... странно.

2 часа назад, RoschinSpb сказал:

А вот для TSwitch не всё так однозначно, там поведение уже более сложное (можно его переключить сдвинув пальцем и это не будет кликом). В Grid совсем все сложно. Логика поведения навороченная и любая отсябятина её поломает с непредсказуемыми последствиями.

Не представляю там отсебятины. Если клик (нажатие и отпускание в пределах определённой маленькой дельты координат), то это клик. С двойным кликом всё ровно тоже самое, только там ещё дельта времени. Если сдвиг пальцем, то это сдвиг пальцем (хоть мышью, хоть пером). Тоже самое, что если я вод виндой мышью нажал на кнопку, а потом передумал, то я её (мышь) сдвигаю, и потом кнопку отпускаю. И это не клик.

2 часа назад, RoschinSpb сказал:

А кто-то (и таких людей наберется не мало) может сказать, "по клику я хочу сам выделить ячейку ту, которую считаю нужной, а не ту на которую ткнул пользователь".

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

Grid1SelectCell(Sender: TObject; const ACol,  ARow: Integer; var CanSelect: Boolean),

что по определению не даёт и половины возможностей, а хотя бы

Grid1SelectCell(Sender: TObject; var ACol,  ARow: Integer)

а ещё лучше

 Grid1SelectCell(Sender: TObject; const LastCol,LastRow:integer; var NewCol,  NewRow: Integer);

это вообще идеально. Тогда ни каких велосипедов не надо будет вообще по описанному Вами случаю.

2 часа назад, RoschinSpb сказал:

OnCellDblClick ведь сериализировать нельзя на единый обработчик кликов. Так и да, сделать два обработчика вместо одного — воистину адская по сложности работа :o) Да и странно, что таблица реагирует на нажатие также как кнопка, хотя всякое бывает.
 

В текущем проекте у меня абсолютно все элементы создаются динамически. И если я для листов, таблиц и прочих списков буду создавать разные обработчики двойного нажатия - то это лишь раздует код, и при любом исправлении логики придётся править её в 10 местах. Что идеологически не верно.

2 часа назад, RoschinSpb сказал:

А ведь если бы можно было VCL-ный dfm запустить на андроиде... не, это было бы конечно не так круто, как натянуть грид на грани вращающегося куба, но гораздо более востребовано на практике.

StringReplace и всё. :)

А если серьёзно - абсолютно поменялся принцип программирования. Например нельзя сделать как раньше MyStringTable.ColCount := 10, надо каждый  столбец теперь создать через create, как будто это не задача самого компонента. Плюс сделали подобие com с сильными и слабыми ссылками. И теперь не возможно правильно уничтожить объект. Вот тут принципиальная разница, которая наводит некий ужас, и постоянное ЗАЧЕМ ТАК ДЕЛАТЬ???? Как например с zero based strings по умолчанию на мобильных платформах. Я программирую на Delphi начиная с 2-й версии, до этого программировал Turbo vision. И могу с уверенностью сказать, что по сравнению с тем, что я тут написал caption->text это вообще ерунда не заслуживающая упоминания. :D


 

Ссылка на комментарий
  • 0

делать так затем, что компиляторы писать денег не хватит под каждую платформу отдельно, поэтому используются чужие

а там сделано так, как сделано. и это идет от соответствующих ОС

 

Ссылка на комментарий
  • 0
43 минуты назад, Akad сказал:

при любом исправлении логики придётся править её в 10 местах. Что идеологически не верно.

А вынести код в свой отдельный метод и его уже вызывать из обработчика события тоже религия не позволяет?

Цитата

Grid1SelectCell(Sender: TObject; var ACol,  ARow: Integer)

Столбец ACol может быть Disabled, или просто по некоторым причинам мы не хотим попадать в ячейку, если Вам этой функциональности не нужно это не значит, что её не нужно ни кому. Если Вы для ACol указали недоступный столбец, то либо будет совершенно незаметно для вас выделен не тот столбец который вы хотели выделить, либо будет исключение в недрах реализации Grid`а.

Поэтому есть два события OnSelectCell и OnSelChanged по первому определяем (если надо) хотим ли мы выделить ячейку (любым способом), а второе срабатывает когда действительно перешли в другую ячейку. Да это отдельные события которые не OnClick и не OnDblClick.

Цитата

Мне нужен факт двойного клика (двойного тапа и т.д. в общем экшена для выбранной строки).

OnCellDblClick - факт двойного клика/экшена по заданной ячейке (строке).

OnDblClick - факт двойного клика по области, которую занимает грид, почувствуйте разницу. Это вовсе не факт того, что это приведет к смене выделенной ячейки, и даже не факт того, что под курсором находится ячейка. Это унаследованное событие, которое которое работает так же как на любом контроле (button/label/switch) менять логику работы - значит поломать существующий ранее написанный код который исходил из этой логики работы. Само по себе знание того, что куда-то в область Grid дважды кликнули имеет мало смысла, требуется точно знать куда кликнули и что с этим делать, с учетом кучи свойств Grid'a и столбцов. Т.е. требует реализацию некоторой нетривиальной логики работы повторяющей логику работы TGrid - это я и называю изобретением велосипеда. Если для вас это не проблема, то уж тем более не будет проблемой в Run-Time присвоить событие.

Цитата

Не представляю там отсебятины.

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

Ссылка на комментарий
  • 0

с сильными и слабыми ссылками
По этому поводу можно по-читать эпосы Allen'а Bauer'а. По мне так это "былинный отказ", но не будем о грустном.

Ссылка на комментарий
  • 0



 

22 часа назад, RoschinSpb сказал:

А вынести код в свой отдельный метод и его уже вызывать из обработчика события тоже религия не позволяет?

Можно. В простонародье называется костыль поставить.

22 часа назад, RoschinSpb сказал:

Между двумя пальцетыками грид может уехать на несколько строк.

Не может. Так как клик должен останавливать скролл. В общем я понимаю, что вы всё стараетесь максимально усложнить. Особенно там, где сложности ни какой нет. Отсюда у вас и бесконечные глюки. Так как отладить это просто не реально. :(

22 часа назад, RoschinSpb сказал:

Столбец ACol может быть Disabled, или просто по некоторым причинам мы не хотим попадать в ячейку

Вот для этого и var ACol. А с нынешнем var CanSelect каши не сваришь. Придётся для кастомизации всё равно ловить не это событие, а последующие, узнавать где сейчас курсор, запомнив где-то у себя где он был ранее и так далее. В общем идиотизм. Такой-же идиотизм, кстати как и TGridOption.Editing/TGridOption.CancelEditingByDefault назначать всей таблице, а не конкретным колонкам. Или TColumn.CanEdit в котором изменить значение нельзя. И прочее и прочее... Но это я о своём уже, о грустном.

В 13 ноября 2017 г. в 17:28, krapotkin сказал:

делать так затем, что компиляторы писать денег не хватит под каждую платформу отдельно, поэтому используются чужие

Вот только умничать не надо. Если бы это было так, то не было бы секретной директивы компилятору, которая всё фиксит.




 

Изменено пользователем Akad
Ссылка на комментарий
  • 0
Цитата

А с нынешнем var CanSelect каши не сваришь.

А я вот сварил:

procedure TForm1.Grid1SelectCell(Sender: TObject; const ACol, ARow: Integer; var CanSelect: Boolean);
begin
  if (ACol = 1) and (ARow = 2) then
  begin
    CanSelect := False;
    if Sender is TStringGrid then
    begin
      TStringGrid(Sender).Cells[2, 5] := IntToStr(TStringGrid(Sender).Col) + ' ' + IntTostr(ACol);
      TStringGrid(Sender).SelectCell(2, 5);
    end;
  end;
end;

Можно получить информацию и по старому столбцу и по новому и выделить ту ячейку, которую хочу. 

И чем же CanSelect это идиотизм по сравнению с Вашим идеальным var NewCol, NewRow: Integer, а вот OnClick не идиотизм в сравнении с OnCellClick? В общем это риторический вопрос.

Цитата

А вынести код в свой отдельный метод и его уже вызывать из обработчика события тоже религия не позволяет?

Можно. В простонародье называется костыль поставить.

Магическая кнопка

TColumn.CanEdit - виртуальный метод в дополнение к TColumn.Enabled и TColumn.ReadOnly, которые можно менять. Используется в основном для определения того, поддерживает ли колонка определенного класса редактирование значений в принципе, например TProgressColumn не поддерживает. Но если Вы реализовали двойной клик на ячейке через OnClick на гриде, то очевидно для Вас не составит труда и добавить свойство в колонку с использованием CanEdit.

TGridOption.Editing - добавлен то ли для совместимости, то ли как аналог TGrid.ReadOnly когда его еще не было, есть не просит, удалять не просили.

CancelEditingByDefault - была личная инициатива раньше этой опции не было и ни кто на это не жаловался, но я думаю что если Вы напишите в QC предложение распространить это свойство еще и на колонки начав своё письмо со слов Dear idiots, то безусловно в сжатые сроки предложение будет рассмотрено.

Цитата

то не было бы секретной директивы компилятору, которая всё фиксит.

Да есть, прямиком из ЦРУ..., но есть и еще более секретная директива от самого... сами знаете кого, которая всё ломает.

Изменено пользователем RoschinSpb
Ссылка на комментарий
  • 0
11 час назад, RoschinSpb сказал:

А я вот сварил:

Если это действительно работает, то это просто жесть по архитектуре или глюк очередной. Вызов из Grid1SelectCell SelectCell обязан как минимум к переполнению стека приводить в реальной жизни. То есть делать этого нельзя. Ну или нельзя будет когда глюк будет исправлен.

12 часа назад, RoschinSpb сказал:

TColumn.CanEdit - виртуальный метод в дополнение к TColumn.Enabled и TColumn.ReadOnly, которые можно менять

Тут вообще закачаться архитектура. Вот ситуация. Таблица из 5-ти колонок. 3-ю и 5-ю можно править, остальные нет. Соответственно в свойствах таблицы надо выставить [TGridOption.Editing]. Ну пытаемся запретить править остальные колонки для редактирования. Смотрим как это сделать. Начинаем перебирать методы: ReadOnly - мимо.  CanEdit - мимо. Locked - мимо. CanFocus - мимо. Enabled - мимо. InEditMode - мимо. Эээээ... всё. Нет очевидного способа сделать колонку не изменяемой. Так же нет события начала редактирования (создания редактора), что бы было можно его отменить.

P.S. Именно запретить редактирование, а не сделать колонку не изменяемой, что делает ReadOnly.
 

Ссылка на комментарий
  • 0
6 часов назад, Akad сказал:

Вызов из Grid1SelectCell SelectCell обязан как минимум к переполнению стека приводить в реальной жизни.

Может но не обязан, так же как и Ваше идеальное событие. Так же как аналогичное VCL-ное событие работает с прошлого века, странно, что Вы этого не знаете программируя начиная с Delphi2.

7 часов назад, Akad сказал:

P.S. Именно запретить редактирование, а не сделать колонку не изменяемой, что делает ReadOnly.

Т.е. свойство которое запрещает редактирование доступного столбца (любопытно, должно ли оно разрешать редактирование недоступного столбца?). Да, как-то за пять лет заявок не эту тему не припомню. У TEdit, кстати тоже есть только ReadOnly и Enabled, а что-то среднее называется TLabel и ни кто не жаловался. Конечно реальная жизнь сложна и многогранна наверняка найдется пользователи которым это понадобилось бы, кому-то и розовый котенок в пятом углу нужен, но данный функционал не особо востребован. Так или иначе есть возможность создать своего наследника колонки и в Runtime, и зарегистрировать его в IDE для работы в DesignTime.

Ссылка на комментарий
  • 0
44 минуты назад, RoschinSpb сказал:

Может но не обязан, так же как и Ваше идеальное событие. Так же как аналогичное VCL-ное событие работает с прошлого века, странно, что Вы этого не знаете программируя начиная с Delphi2.

Я и не утверждал, что в VCL всё работает корректно. Так же как и переопределение этого события там подобным образом. В своё время даже статьи писались об этом. И в книгах отдельные жирные шрифты к чему могут приводить подобные переопределения в событии. Ну и которые, к сожалению, были проигнорированы при разработке fmx. :(

46 минут назад, RoschinSpb сказал:

Т.е. свойство которое запрещает редактирование доступного столбца (любопытно, должно ли оно разрешать редактирование недоступного столбца?).

Правильно. По логике. Оно должно запрещать редактирование. НО редактирование разрешено. Не разрешёно лишь изменение редактируемого. Напомните... где здесь ээээ... слово забыл... А! логика?

48 минут назад, RoschinSpb сказал:

У TEdit, кстати тоже есть только ReadOnly и Enabled, а что-то среднее называется TLabel и ни кто не жаловался.

Правильно. У грида так же есть TCurrencyColumn, TImageColumn, TCheckColumn и так далее. Но как только мы говорим про [TGridOption.Editing], тут здравый смысл кончается. TCheckColumn работает одинаково, а вот TStringColumn без него не работает вообще (я про реадонли), а с ним работает в режиме всегда редактируем. Понимаю, что опять нужно искать логику. Лично я её в упор не вижу.

P.S. В целом - Ваших словах есть логика. Но она НЕ ОЧЕВИДНА людям, которые перешли с VCL. А так как документация на fmx по факту отсутствует, примеры показывают только сферических коней в вакууме - пока поймёшь, где это там настроена нужная тебе фишка - можно не один час убить - всё пишется методом проб и ошибок. И как я изначально написал - с постоянным возгласом - "ну зачем ТАК делать???"

Смысла в дальнейшем разговоре не вижу. Всё равно глюки ни куда не денутся  - придётся мне их править (реадонли и постоянная потеря OnKeyDown как минимум если мы говорим о гриде). Хотя меня сейчас абсолютная не работоспособность браузера под всеми платформами напрягает больше всего. Короче посмотрим. Логику разработчика я услышал. Благодарю. 
 

Ссылка на комментарий
  • 0

Ячейка/эдит/мемо с данными, которые не могут меняться, нужны для того, чтобы хотя бы скопировать весь, или часть текста в буфер обмена, для этого и существует свойство ReadOnly. Только текст который не содержит меняющихся данных (метка/заголовк) практически ни когда не требуется копировать в буфер обмена, но такие элементы пользовательского интерфейса не требуют и получения фокуса ввода. Запрет на выделение ячейки легко делается OnSelectCell. Ввод новых свойств с мутным смыслом всегда дело неблагодарное. 
Например:

  1. Enabled := False;
  2. Editing := True;
  • Серая колонка, нельзя войти в режим редактирования ячейки -> Баг! Я поставил Editing в True, очевидно что должна быть возможность войти в режим редактирования. Вы там с логикой дружите?
  • Серая колонка, можно войти в режим редактирования -> Баг! Колонка выглядит как недоступная, тем не меняя можно войти в режим редактирования. Что за дизайн?
  • Обычная колонка, нельзя войти в режим редактирования -> Баг! Enabled у меня стоит False, а колонка выглядит как доступная, очевидно что если Enabled = False, должна быть серая как и все элементы управления. Вы лучше баги правьте, а не ломайте то, что работает!
  • Обычная колонка, нельзя войти в режим редактирования, Enabled становится False -> Баг! В очередной версии почему-то свойство Enabled самопроизвольно меняет своё значение. Почему в каждой версии что-нибудь да отваливается?

TGridOption.Editing = not Grid.ReadOnly - полезно для ситуаций, когда надо явно переходить в режим изменения данных с использованием блокировок. Нажимаем кнопку "изменить" - можно вводить данные, нажимаем кнопку "применить" - нельзя вводить данные, но по прежнему можно смотреть.

14 часа назад, Akad сказал:

придётся мне их править

Было бы не плохо, если бы Вы тут выложили пример своей идеальной колонки, это бы ввело обсуждение в конструктивное русло. А то после всего написанного Капитан Очевидность шепчет о том, что к программированию Вы имеете весьма опосредованное отношение, но я конечно не верю. В конце концов хороший программист не обязан писать повести как Лев Толстой и тут простого примера было бы достаточно, чтобы расставить все точки над Ė, да и след в истории будет хороший.
За сим прощаюсь, т.к. действительно общение вышло за рамки заявленной темы и превратилось в оффтоп переходящий в троллинг.

Изменено пользователем RoschinSpb
Ссылка на комментарий

Присоединяйтесь к обсуждению

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

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...