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


Автор: neweraser 11.4.2012, 09:20
Доброго времени суток! Очень расчитываю на вашу помощь, т.к. в winapi я вообще не понимаю. На форме лежит ShellTreeView, в OnCreate формы к нему добавляются чекбоксы вот таким образом:
Код

procedure TMainForm.FormCreate(Sender: TObject);
var
  dwStyle: DWord;
begin
  dwStyle:= GetWindowLong(ShellTreeView1.Handle ,GWL_STYLE);
  dwStyle:= dwStyle or TVS_CHECKBOXES;
  SetWindowLong(ShellTreeView1.Handle ,GWL_STYLE,dwStyle);
  fList:= TStringList.Create(); // Список выделенных нодов я храню тут
end;

...

procedure TMainForm.ShellTreeView1Click(Sender: TObject);
var
  i: Integer;
begin
  fList.Clear;
  for i:= 0 to  ShellTreeView1.Items.Count - 1 do
  if IsNodeChecked(ShellTreeView1.Items[i]) then
  fList.Add(ShellTreeView1.Folders[i].PathName);
end;

function 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;


Мне нужно как-то сделать, чтобы при выделении корневого каталога выделялись и все дочерние каталоги, а в fList записывался только корневой, и наоборот, при выделении дочерних - с корня снималась галочка и в fList переписывались только дочерние. Это нужно будет для копирования групп файлов. Думаю, нормально объяснил, я старался   smile 
Спасибо за любую помощь!

Автор: Чучмек 12.4.2012, 20:29
Цитата(neweraser @  11.4.2012,  09:20 Найти цитируемый пост)
выделении корневого каталога выделялись и все дочерние каталоги, а в fList записывался только корневой

Выделение или установка галочки?

Автор: neweraser 13.4.2012, 08:34
Галочки smile Есть какие-нибудь идеи? 

Автор: Чучмек 13.4.2012, 10:41
А onCheck как обработать нашел?
Я, пока, ничего лучше, чем запомнить ноду и ее состояние на onMouseMove, а затем сравнить с нодой на  onClick, не придумал.

Автор: neweraser 13.4.2012, 13:48
Я думаю, тут по-другому надо, в событии onClick проверять стоит ли галочка в вышестоящей директории, если да - убирать ее и результат записывать в fList. Потом если кликаешь по директории и она раскрыта - ставятся чекбоксы на все дочерние дериктории и в список файлов fList записывается только верхняя директория, так как она пойдет потом на копирование/перемещение, дабы избежать ошибку или по 2-му кругу не копировать файлы. Как-то так...

Автор: Чучмек 14.4.2012, 00:37
Вот посмотри, выводит в memo выбранные папки.
Правда  тестить и писать комментарии уже было неохота да и времени нет.
Даю в сыром виде. Что не понятно или не так работает, пиши.  

Автор: neweraser 19.4.2012, 14:50
Все работает, но мне очень хотелось бы узнать и разобраться как... Устал уже искать в гугле, справках и msdn, может кто-нибудь даст ссылку или ткнет пальцем что ли... 
Код

  fillchar(tvi,sizeof(tvi),0); // Тут заполнение ноды 0 раз вычислением размера переменной? Ниче не понятно :)
...
  tvi.hItem:= N.ItemId; // Что значит hItem и N.ItemId?
...
TreeView_SetItem(n.TreeView.Handle, tvi); // Следующие строки вообще не разобрал
...
  mp:= GetMessagePos;
  tvhtinfo.pt.X:= $0000FFFF and mp;
  tvhtinfo.pt.y:= ($FFFF0000 and mp) shr 16;
  MapWindowPoints(HWND_DESKTOP,ShellTreeView1.Handle,tvhtinfo.pt,1);
  TreeView_HitTest(ShellTreeView1.Handle,tvhtinfo);

Спасибо.

Автор: Чучмек 19.4.2012, 19:48
Цитата(neweraser @  19.4.2012,  14:50 Найти цитируемый пост)
fillchar(tvi,sizeof(tvi),0); // Тут заполнение ноды 0 раз вычислением размера переменной? Ниче не понятно smile

Заполняешь память, выделенную под переменную tvi, нулями(все целочисленные 0, все указатели nil). В данном случае, скорее всего, можно эту строчку убрать.
 
Цитата(neweraser @  19.4.2012,  14:50 Найти цитируемый пост)
 tvi.hItem:= N.ItemId; // Что значит hItem и N.ItemId?

Дескриптор(идентификатор) ноды. А то, как TreeView "узнает", за какую ноду его спрашивают?

Цитата(neweraser @  19.4.2012,  14:50 Найти цитируемый пост)
TreeView_SetItem(n.TreeView.Handle, tvi)

Отправляет окну с дескриптором n.TreeView.Handle (в данном случае нашему ShellTreeView1) сообщение TVM_SETITEM в качестве lParam передается адрес стуктуры  tvi
TreeView по содержанию полей структуры tvi определяет ноду, и что с ней сделать.

Добавлено через 8 минут
Цитата(neweraser @  19.4.2012,  14:50 Найти цитируемый пост)
 mp:= GetMessagePos;
  tvhtinfo.pt.X:= $0000FFFF and mp;
  tvhtinfo.pt.y:= ($FFFF0000 and mp) shr 16;
  MapWindowPoints(HWND_DESKTOP,ShellTreeView1.Handle,tvhtinfo.pt,1);

http://vsokovikov.narod.ru/New_MSDN_API/Message_queue/fn_getmessagepos.htm
http://vsokovikov.narod.ru/New_MSDN_API/Coordinate_spaces/fn_mapwindowpoints.htm

Автор: Чучмек 19.4.2012, 20:04
Цитата(neweraser @  19.4.2012,  14:50 Найти цитируемый пост)
TreeView_HitTest(ShellTreeView1.Handle,tvhtinfo);

Цитата

Determines the location of the specified point relative to the client area of a tree-view control. You can use this macro or send the TVM_HITTEST message explicitly.

Определяешь к какой ноде и к какому участку ноды принадлежит точка tvhtinfo.pt
  

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