Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 03.07.2014, 18:18   #1
FleXik
Форумчанин
 
Регистрация: 01.11.2012
Сообщений: 770
Вопрос ListView лагает при прокрутке загруженного списка

ListView лагает при прокрутке загруженного списка, при загрузке 500 строк, при прокрутке, лагов нет, при загрузке 1000+ строк начинаются лаги, то ли обновлять не успевает то ли нужно сделать чтобы обновляло только видимые строки а не весь список... Пожалуйста, помогите решить проблему.. Строки загружаются в ListView спаршенные с сайта по 30-60шт за 1 раз, при использовании BeginUpdate и EndUpdate список начинает обновляться 100500 раз, поэтому их не использую.
FleXik вне форума Ответить с цитированием
Старый 03.07.2014, 18:26   #2
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

Цитата:
при использовании BeginUpdate и EndUpdate список начинает обновляться 100500 раз, поэтому их не использую.
они вообще-то останавливают отрисовку на время между begin и end. Показывай где и как их используешь.
Человек_Борща вне форума Ответить с цитированием
Старый 03.07.2014, 18:38   #3
FleXik
Форумчанин
 
Регистрация: 01.11.2012
Сообщений: 770
По умолчанию

Код:
procedure thread.ListViewAdd;
begin
  Item:=Form1.ListView1.Items.Add;
  Item.SubItems.Add('2 колонка');
  Item.SubItems.Add('3 колонка');
  Item.SubItems.Add('4 колонка');
  Item.SubItems.Add('5 колонка');
end;
потом в Execute синхронизирую эту процедуру... смотрел демку VirtualListView там в ListView отображаются файлы винды так там при прокрутке ничего не лагает и списки большие =(
FleXik вне форума Ответить с цитированием
Старый 03.07.2014, 19:53   #4
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

Не вижу вызова BeginUpdate, EndUpdate.
А причина скорее все та же. больше 2х потоков на 1 ListView и того, каждый дергает EndUpdate и вызывает перерисовку.
Человек_Борща вне форума Ответить с цитированием
Старый 03.07.2014, 19:54   #5
FleXik
Форумчанин
 
Регистрация: 01.11.2012
Сообщений: 770
По умолчанию

Человек_Борща, так как тогда переделать чтобы работало?
FleXik вне форума Ответить с цитированием
Старый 03.07.2014, 20:27   #6
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Цитата:
как тогда переделать чтобы работало
в делфи 7 есть демка с исходниками для подобной задачи. Её изучить и будет работать, наверно. И точно, если изучить тщательно
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 03.07.2014, 22:26   #7
FleXik
Форумчанин
 
Регистрация: 01.11.2012
Сообщений: 770
По умолчанию

кто-то конкретный пример может дать?
FleXik вне форума Ответить с цитированием
Старый 03.07.2014, 22:39   #8
eval
Подтвердите свой е-майл
 
Регистрация: 29.08.2012
Сообщений: 4,011
По умолчанию

а демо уже не конкретно?
eval вне форума Ответить с цитированием
Старый 03.07.2014, 22:59   #9
FleXik
Форумчанин
 
Регистрация: 01.11.2012
Сообщений: 770
По умолчанию

Цитата:
а демо уже не конкретно?
там много лишнего кода
единственное что я понял это то что OwnerData обязательно ставить в True

Код:
unit VListView;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ComCtrls, StdCtrls, ToolWin, ShlObj, ImgList, Menus;

type
  PShellItem = ^TShellItem;
  TShellItem = record
    FullID,
    ID: PItemIDList;
    Empty: Boolean;
    DisplayName,
    TypeName: string;
    ImageIndex,
    Size,
    Attributes: Integer;
    ModDate: string;
  end;

  TForm1 = class(TForm)
    ListView: TListView;
    CoolBar1: TCoolBar;
    ToolBar2: TToolBar;
    ToolbarImages: TImageList;
    btnBrowse: TToolButton;
    btnLargeIcons: TToolButton;
    btnSmallIcons: TToolButton;
    btnList: TToolButton;
    btnReport: TToolButton;
    cbPath: TComboBox;
    ToolButton3: TToolButton;
    PopupMenu1: TPopupMenu;
    btnBack: TToolButton;
    procedure FormCreate(Sender: TObject);
    procedure ListViewData(Sender: TObject; Item: TListItem);
    procedure btnBrowseClick(Sender: TObject);
    procedure cbPathKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure cbPathClick(Sender: TObject);
    procedure btnLargeIconsClick(Sender: TObject);
    procedure ListViewDblClick(Sender: TObject);
    procedure ListViewDataHint(Sender: TObject; StartIndex,
      EndIndex: Integer);
    procedure ListViewKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure ListViewDataFind(Sender: TObject; Find: TItemFind;
      const FindString: String; const FindPosition: TPoint;
      FindData: Pointer; StartIndex: Integer; Direction: TSearchDirection;
      Wrap: Boolean; var Index: Integer);
    procedure ListViewCustomDrawItem(Sender: TCustomListView;
      Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
    procedure ListViewCustomDrawSubItem(Sender: TCustomListView;
      Item: TListItem; SubItem: Integer; State: TCustomDrawState;
      var DefaultDraw: Boolean);
    procedure btnBackClick(Sender: TObject);
    procedure Form1Close(Sender: TObject; var Action: TCloseAction);
  private
    FPIDL: PItemIDList;
    FIDList: TList;
    FIShellFolder,
    FIDesktopFolder: IShellFolder;
    FPath: string;
    procedure SetPath(const Value: string); overload;
    procedure SetPath(ID: PItemIDList); overload;
    procedure PopulateIDList(ShellFolder: IShellFolder);
    procedure ClearIDList;
    procedure CheckShellItems(StartIndex, EndIndex: Integer);
    function  ShellItem(Index: Integer): PShellItem;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses ShellAPI, ActiveX, ComObj, CommCtrl, FileCtrl;

//PIDL MANIPULATION

procedure DisposePIDL(ID: PItemIDList);
var
  Malloc: IMalloc;
begin
  if ID = nil then Exit;
  OLECheck(SHGetMalloc(Malloc));
  Malloc.Free(ID);
end;

function CopyITEMID(Malloc: IMalloc; ID: PItemIDList): PItemIDList;
begin
  Result := Malloc.Alloc(ID^.mkid.cb + SizeOf(ID^.mkid.cb));
  CopyMemory(Result, ID, ID^.mkid.cb + SizeOf(ID^.mkid.cb));
end;

function NextPIDL(IDList: PItemIDList): PItemIDList;
begin
  Result := IDList;
  Inc(PChar(Result), IDList^.mkid.cb);
end;

function GetPIDLSize(IDList: PItemIDList): Integer;
begin
  Result := 0;
  if Assigned(IDList) then
  begin
    Result := SizeOf(IDList^.mkid.cb);
    while IDList^.mkid.cb <> 0 do
    begin
      Result := Result + IDList^.mkid.cb;
      IDList := NextPIDL(IDList);
    end;
  end;
end;


procedure StripLastID(IDList: PItemIDList);
var
  MarkerID: PItemIDList;
begin
  MarkerID := IDList;
  if Assigned(IDList) then
  begin
     while IDList.mkid.cb <> 0 do
    begin
      MarkerID := IDList;
      IDList := NextPIDL(IDList);
    end;
    MarkerID.mkid.cb := 0;
  end;
end;

function CreatePIDL(Size: Integer): PItemIDList;
var
  Malloc: IMalloc;
  HR: HResult;
begin
  Result := nil;

  HR := SHGetMalloc(Malloc);
  if Failed(HR) then
    Exit;

  try
    Result := Malloc.Alloc(Size);
    if Assigned(Result) then
      FillChar(Result^, Size, 0);
  finally
  end;
end;

function CopyPIDL(IDList: PItemIDList): PItemIDList;
var
  Size: Integer;
begin
  Size := GetPIDLSize(IDList);
  Result := CreatePIDL(Size);
  if Assigned(Result) then
    CopyMemory(Result, IDList, Size);
end;

function ConcatPIDLs(IDList1, IDList2: PItemIDList): PItemIDList;
var
  cb1, cb2: Integer;
begin
  if Assigned(IDList1) then
    cb1 := GetPIDLSize(IDList1) - SizeOf(IDList1^.mkid.cb)
  else
    cb1 := 0;

  cb2 := GetPIDLSize(IDList2);

  Result := CreatePIDL(cb1 + cb2);
  if Assigned(Result) then
  begin
    if Assigned(IDList1) then
      CopyMemory(Result, IDList1, cb1);
    CopyMemory(PChar(Result) + cb1, IDList2, cb2);
  end;
end;
FleXik вне форума Ответить с цитированием
Старый 03.07.2014, 23:00   #10
FleXik
Форумчанин
 
Регистрация: 01.11.2012
Сообщений: 770
По умолчанию

Код:
//SHELL FOLDER ITEM INFO

function GetDisplayName(ShellFolder: IShellFolder; PIDL: PItemIDList;
                        ForParsing: Boolean): string;
var
  StrRet: TStrRet;
  P: PChar;
  Flags: Integer;
begin
  Result := '';
  if ForParsing then
    Flags := SHGDN_FORPARSING
  else
    Flags := SHGDN_NORMAL;

  ShellFolder.GetDisplayNameOf(PIDL, Flags, StrRet);
  case StrRet.uType of
    STRRET_CSTR:
      SetString(Result, StrRet.cStr, lStrLen(StrRet.cStr));
    STRRET_OFFSET:
      begin
        P := @PIDL.mkid.abID[StrRet.uOffset - SizeOf(PIDL.mkid.cb)];
        SetString(Result, P, PIDL.mkid.cb - StrRet.uOffset);
      end;
    STRRET_WSTR:
      Result := StrRet.pOleStr;
  end;
end;

function GetShellImage(PIDL: PItemIDList; Large, Open: Boolean): Integer;
var
  FileInfo: TSHFileInfo;
  Flags: Integer;
begin
  FillChar(FileInfo, SizeOf(FileInfo), #0);
  Flags := SHGFI_PIDL or SHGFI_SYSICONINDEX or SHGFI_ICON;
  if Open then Flags := Flags or SHGFI_OPENICON;
  if Large then Flags := Flags or SHGFI_LARGEICON
  else Flags := Flags or SHGFI_SMALLICON;
  SHGetFileInfo(PChar(PIDL),
                0,
                FileInfo,
                SizeOf(FileInfo),
                Flags);
  Result := FileInfo.iIcon;
end;

function IsFolder(ShellFolder: IShellFolder; ID: PItemIDList): Boolean;
var
  Flags: UINT;
begin
  Flags := SFGAO_FOLDER;
  ShellFolder.GetAttributesOf(1, ID, Flags);
  Result := SFGAO_FOLDER and Flags <> 0;
end;


function ListSortFunc(Item1, Item2: Pointer): Integer;
begin
  Result := SmallInt(Form1.FIShellFolder.CompareIDs(
                  0,
                  PShellItem(Item1).ID,
                  PShellItem(Item2).ID
            ));
end;

{TForm1}

//GENERAL FORM METHODS

procedure TForm1.FormCreate(Sender: TObject);
var
  FileInfo: TSHFileInfo;
  ImageListHandle: THandle;
  NewPIDL: PItemIDList;
begin
  OLECheck(SHGetDesktopFolder(FIDesktopFolder));
  FIShellFolder := FIDesktopFolder;
  FIDList := TList.Create;
  ImageListHandle := SHGetFileInfo('C:\',
                           0,
                           FileInfo,
                           SizeOf(FileInfo),
                           SHGFI_SYSICONINDEX or SHGFI_SMALLICON);
  SendMessage(ListView.Handle, LVM_SETIMAGELIST, LVSIL_SMALL, ImageListHandle);

  ImageListHandle := SHGetFileInfo('C:\',
                           0,
                           FileInfo,
                           SizeOf(FileInfo),
                           SHGFI_SYSICONINDEX or SHGFI_LARGEICON);

  SendMessage(ListView.Handle, LVM_SETIMAGELIST, LVSIL_NORMAL, ImageListHandle);
  OLECheck(
    SHGetSpecialFolderLocation(
      Application.Handle,
      CSIDL_DRIVES,
      NewPIDL)
  );
  SetPath(NewPIDL);
  ActiveControl := cbPath;
  cbPath.SelStart := 0;
  cbPath.SelLength := Length(cbPath.Text);
end;

procedure TForm1.btnBrowseClick(Sender: TObject);
var
  S: string;
begin
  S := '';
  if SelectDirectory('Select Directory', '', S) then
    SetPath(S);
end;

procedure TForm1.cbPathKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if Key = VK_RETURN then
  begin
    if cbPath.Text[Length(cbPath.Text)] = ':' then
      cbPath.Text := cbPath.Text + '\'; 
    SetPath(cbPath.Text);
    Key := 0;
  end;
end;

procedure TForm1.cbPathClick(Sender: TObject);
var
  I: Integer;
begin
  I := cbPath.Items.IndexOf(cbPath.Text);
  if I >= 0 then
    SetPath(PItemIDList(cbPath.Items.Objects[I]))
  else
    SetPath(cbPath.Text);
end;

procedure TForm1.btnLargeIconsClick(Sender: TObject);
begin
  ListView.ViewStyle := TViewStyle((Sender as TComponent).Tag);
end;

procedure TForm1.ListViewDblClick(Sender: TObject);
var
  RootPIDL,
  ID: PItemIDList;
begin
  if ListView.Selected <> nil then
  begin
    ID := ShellItem(ListView.Selected.Index).ID;
    if not IsFolder(FIShellFolder, ID) then Exit;
    RootPIDL := ConcatPIDLs(FPIDL, ID);
    SetPath(RootPIDL);
  end;
end;

function TForm1.ShellItem(Index: Integer): PShellItem;
begin
  Result := PShellItem(FIDList[Index]);
end;

procedure TForm1.ListViewKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  case Key of
    VK_RETURN:
      ListViewDblClick(Sender);
    VK_BACK:
      btnBackClick(Sender);  
  end;
end;

//SHELL-RELATED ROUTINES.

procedure TForm1.ClearIDList;
var
  I: Integer;
begin
  for I := 0 to FIDList.Count-1 do
  begin
    DisposePIDL(ShellItem(I).ID);
    Dispose(ShellItem(I));
  end;
  FIDList.Clear;
end;
FleXik вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
ListView лагает когда прокручиваю список, прокручиваю вручную FleXik Общие вопросы Delphi 27 18.06.2014 17:09
Фиксация блока при вертикальной прокрутке ВалекFCRK HTML и CSS 2 27.03.2014 16:06
Фиксация картинки при прокрутке tarakanet HTML и CSS 0 20.07.2012 01:14
цикл останавливается при прокрутке страницы vasser200189 Microsoft Office Excel 1 16.05.2012 13:26