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


Автор: GogaM 8.9.2008, 15:21
Не могу изменить курсор у Virtual TreeView.
Когда выполняю операции которые занимают много времени выставляю у дерева свойство Cursor := crHourGlass, 
но визуально курсор на дереве не меняется, хотя свойство Cursor = crHourGlass. 
Курсор меняется только в том случае если я перед началом  цикла не выполняю BeginUpdate, 
но в этом случае дерево работе очень медленно.
Можно ли после BeginUpdate поменять курсор?

Автор: morpheyushka 8.9.2008, 15:25
Я в подобных случаях пользуюсь RxLib'ом.
Делаю это так:
Код

StartWait;
try
//код
finally
  StopWait;
end;


пока выполняется код в try...finally - пользователь наблюдает часикиsmile
и вставлять можно когда хочешь...

Автор: GogaM 8.9.2008, 15:56
Я так понимаю, что StartWait показывает часики на всем приложении а не на конкретном дереве.
Если это так, то этот вариан не подходит так же как и вариант Screen.Cursor := crHourGlass.
Поскольку оперции с деревом выполняются в потоке, остальные модули (формы) проекта должны нормально работать,
а при наведении мыши на контрол дерева курсор должен измениться.

Автор: Poseidon 8.9.2008, 16:04
Я не пойму в чем проблема? Меняй курсор, делай BeginUpdate и начинай цикл...

Автор: GogaM 9.9.2008, 08:08
Ещё раз.
Перед началом цикла делаю 
Virtual TreeView.Cursor := crHourGlass
Virtual TreeView.BeginUpdate
Цикл
Virtual TreeView.EndUpdate
Virtual TreeView.Cursor := crDefault
Во время цикла водим мышом над деревом курсор crDefault.
Как поменять на crHourGlass.

Автор: Poseidon 9.9.2008, 09:05
В общем, как показали эксперементы с BeginUpdate, этот метод запрещает вообще все сообщения контролу. Поэтому и получается, что курсор как бы не знает что он находится над деревом и не меняется. На скорую руку я бы это все обошел так:

Код
type
  TTestThread = class(TThread)
  private
    VT: TVirtualStringTree;
  protected
    procedure Execute; override;
    procedure UpdVT;
  end;

procedure TForm1.Button1Click(Sender: TObject);
var TestThread: TTestThread;
begin
  VirtualStringTree1.Cursor := crHourGlass;

  TestThread:= TTestThread.Create(True);
  TestThread.FreeOnTerminate:= True;
  TestThread.Resume;
end;


{ TTestThread }
procedure TTestThread.Execute;
var i: integer;
begin
  VT:= TVirtualStringTree.Create(nil);

  for i:= 0 to 50000 do VT.AddChild(nil); // < -- цикл заполнения

  Synchronize(UpdVT);
  VT.Free;
end;

procedure TTestThread.UpdVT;
begin
  with Form1 do
  begin
    VirtualStringTree1.Assign(VT);
    VirtualStringTree1.Cursor := crDefault;
  end
end;

Автор: GogaM 9.9.2008, 09:42
Про "скорую руку" согласен.
Только Assign придётся делать 2 раза, чтоб деревья не отличались.
В добавок  Assign происходит в основной нити и 2 Assign-а тож не мнгновенно отрабатывают.
Количество нод у мну в проекте примерно такое как в примере, да не по одному разу.

Автор: Poseidon 9.9.2008, 09:59
Цитата(GogaM @  9.9.2008,  09:42 Найти цитируемый пост)
В добавок  Assign происходит в основной нити и 2 Assign-а тож не мнгновенно отрабатывают.
Кто сказал? Assign в потоке. А то, что не мгновенно, так это спорно smile Assign - это присвоение данных которые в памяти. Такое присвоение обычно очень быстрое. Оно конечно медленнее чем если бы мы сразу заполняли дерево, но не ощутимо. Тем более пользователь видет в это время "часики". 

Автор: GogaM 9.9.2008, 10:04
В примере Assign вызывается через Synchronize.
Это означает что весь код выполняется в основной нити.

Автор: Poseidon 9.9.2008, 10:19
Ну верно и что? У нас есть пустое дерево в памяти и заполненное дерево в памяти. Мы берем данные из заполненного и копируем в пустое. Все это в основной нити и..? Ведь само заполнение данными, сама "тяжелая операция" проходит в потоке. А копирование память-память потом "общей кучей" пройдет за миллисекунды.

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