Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > ShellTreeView и SetFocus


Автор: neweraser 2.4.2012, 14:27
Здравствуйте. Не могу понять... Мне нужно добавлять папку в директорию и давать пользователю редактировать ее, как все привыкли в обычном проводнике. С showmessage почему-то все замечательно работает, а без них фокус не ставится, либо ставится совсем не туда, либо вылетает ошибка.
Код

  CreateDir(ShellTreeView1.Path +'\123');
  showmessage(ShellTreeView1.Path);
  ShellTreeView1.Path:= ShellTreeView1.Path +'123';
  showmessage(ShellTreeView1.Path);
  ShellTreeView1.SetFocus;
  ShellTreeView1.Selected.EditText;

Ответ должен быть прост, но я уже сломал голову. Спасибо заранее.

Автор: Ne1tr1n0 2.4.2012, 14:59
Обновлять список не пробовал?
Так надо чтоб так было?
Код

  CreateDir(ShellTreeView1.Path +'\123');
  ShellTreeView1.Refresh(ShellTreeView1.Selected);
  ShellTreeView1.Path:= IncludeTrailingPathDelimiter(ShellTreeView1.Path) +'123';
  ShellTreeView1.SetFocus;
  ShellTreeView1.Selected.EditText;

Автор: Чучмек 2.4.2012, 15:04
А у меня работает.И без SetFocus работает.

Автор: neweraser 2.4.2012, 15:13
Вот эта строчка IncludeTrailingPathDelimiter гораздо лучше того, как я извращался, чтобы не было ошибки с разделителями  smile
Уже намного лучше, но почему-то все равно редактирование не включается, вот после этого
Код

  CreateDir(ShellTreeView1.Path +'\123');
  ShellTreeView1.Refresh(ShellTreeView1.Selected);
  ShellTreeView1.Path:= IncludeTrailingPathDelimiter(ShellTreeView1.Path) +'123';
  ShellTreeView1.SetFocus;
  Showmessage('Не понимаю');
  ShellTreeView1.Selected.EditText;

Все работает как надо) Пробовал вставлять Refresh - ситуация не меняется...

Автор: Ne1tr1n0 2.4.2012, 15:59
Непонятно, что именно не работает?
Я вот тут набросал по клику на кнопке всё работает, или я что-то неправильно понимаю? Как надо-то?

Автор: neweraser 2.4.2012, 21:21
Спасибо, тут совсем по-другому и работает как надо, я без функции делал, по идее все было верно, но загвоздка либо в делфях 7-ки портейбл, либо в моих руках или и в том и другом... если не затруднит, напишешь комментарии к функции? Там что-то много нового для меня. И вообще за день влиться в делфи после года-полтора как-то напряжно  smile Еще раз спасибо, буду дальше разбираться с утра.
И заваливать форум непонятными вопросами  smile 

Автор: Ne1tr1n0 3.4.2012, 10:26
Ну не сказал бы что совсем по другому, просто разные объекты пространства имен оболочки могут частично ссылаться на одни и те же объекты файловой системы. Так корневой объект Shell Namespace'a Desktop (рабочий стол) частично содержит дочерние элементы физической папки C:\Users\<User>\Desktop, для которой тоже есть объект оболочки. ShellTreeView он на то и Shell* что отображает иерархию объектов оболочки. При этом если создать папку на рабочем столе, то она появится дочерним элементом как у одного объекта, так и у другого. Собственно у меня обновляется тот узел дерева, который выделен, поэтому создается впечатление, что папка появляется именно там, где нужно. Функция FindNodeWithText взята из недр http://delphiworld.narod.ru/base/sl_to_dir_tree.html находит новую созданную папку (перебирает дочерние элементы узла TreeView и при совпадении имен возвращает ссылку на этот узел), и мы выделяем её для редактирования имени. 
При этом первый If на случай если выделенный узел в TreeView является виртуальной папкой (Сетевое окружение, Мой компьютер, Панель управления и т.д.), то в этих папках CreateDir по понятным причинам не отработает. Соответственно и выделять нечего. 
SetFocus на TreeView нужен, потому что редактирование имени папки в TreeView как правило завершается нажатием Enter, но без SetFocus'a его принимает Button и из-за этого возникает ошибка (вызывается ещё раз процедура создания папки, но она уже переименована, отсюда и ссылка на несуществующий каталог).
Собственно всё.

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

Автор: neweraser 5.4.2012, 11:08
Спасибо, с предыдущей проблемой разобрался, тут еще...
Суть вопроса изменилась, но новая тема имела бы то же самое название, поэтому не стал создавать.
В OnCreate добавляю к ShellTreeView чекбоксы, есть возможность при выделении каких-либо чекбоксов выделять соответствующие строки в treeview и не снимать фокус (или заново восстанавливать) после рефреша?
Вот код:
Код

procedure TForm1.FormCreate(Sender: TObject);
var
  dwStyle: DWord;
begin
  dwStyle:= GetWindowLong(ShellTreeView1.Handle ,GWL_STYLE);
  dwStyle:= dwStyle or TVS_CHECKBOXES;
  SetWindowLong(ShellTreeView1.Handle ,GWL_STYLE,dwStyle);
end;

Автор: Ne1tr1n0 5.4.2012, 12:35
Именно строки выделять? В смысле синим подсвечивать?
Тогда наверное придется писать наследника от ShellTreeView и реализовывать в нем мультиселект, как сделано например в этом компоненте: http://www.delphikingdom.com/asp/viewitem.asp?catalogid=314
Ну а состояния чекбоксов наверное придется самому хранить где-то и после рефреша восстанавливать их. Вот кстати ещё один потомок от TCustomTreeView, в нем реализована работа с чекбоксами у дерева. Тоже можно взять на вооружение. http://www.delphimaster.net/view/1-1135233149

Автор: neweraser 5.4.2012, 14:32
А можно как-то таким способом? 
Код

function TForm1.IsNodeChecked(aNode :TTreeNode): Boolean;
var
  aTVItem: TTVItem;
begin
  with aTVItem do begin
    Mask := TVIF_STATE;
    hItem:= aNode.ItemId;
  end;
  TreeView_GetItem(aNode.TreeView.Handle, aTVItem);
  result:= (aTVItem.State and $2000) = $2000;
end;

...

  TTreeView(ShellTreeView1).MultiSelect:= True;
  for i:=0 to ShellTreeView1.Items.Count-1 do
  if IsNodeChecked(ShellTreeView1.Items[i]) then
  ShellTreeView1.Select(ShellTreeView1.Items[i]); // Вот с этой строчкой путаюсь

...


Наверное, циклом перебирать дерево - не лучший вариант, но мне надо попроще и побыстрее, сроки горят smile

Автор: Ne1tr1n0 5.4.2012, 15:12
Ну разве что только не всё дерево обходить, а лишь текущую ноду? Мы ведь только её обновляем, и только у нее чекбоксы сбрасываются...

Автор: neweraser 5.4.2012, 15:17
Согласен, но код все равно не работает. Не подсвечивает синим строки в цикле.. Удерживая control и жмакая лкм в дереве все прекрасно выделяется  smile 

Автор: Ne1tr1n0 5.4.2012, 15:42
А так?
Код

procedure TForm1.Button2Click(Sender: TObject);
var i: integer;
begin
for i:=0 to ShellTreeView1.Items.Count-1 do
  if IsNodeChecked(ShellTreeView1.Items[i]) then
    ShellTreeView1.Select(ShellTreeView1.Items[i], [ssCtrl]); // Вот с этой строчкой путаюсь
ShellTreeView1.SetFocus;
end;

Автор: neweraser 5.4.2012, 15:58
Так работает, только почему-то иногда выделяет не все строчки (верхняя не подсвечивается), но это не важно, буду разбираться дальше. Спасибо!

Автор: Ne1tr1n0 5.4.2012, 16:00
Возможно по тому, что верхняя строчка уже выделена на тот момент (Это равносильно тому, как если при нажатом Ctrl кликнуть по выделенной ноде - выделение снимется).

Автор: neweraser 5.4.2012, 16:25
Да, надо как-то убирать фокус перед обновлением по клику на ShellTreeView. Может к вечеру начнет голова соображать..
зы. во тему раздул...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)