forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   Delphi (http://forum.boolean.name/forumdisplay.php?f=66)
-   -   Прошу помощи (http://forum.boolean.name/showthread.php?t=11975)

Tronix 20.02.2010 21:48

Прошу помощи
 
Вложений: 2
Привет, ситуация: есть CheckListBox. Изначально пустой, по ходу работы программы туда добавляются имена файлов. Программа производит сканирование всех *.exe и *.dll, ищет в них некоторую сигнатуру. Если находит - добавляет имя файла в CheckListBox.
Хочется сделать чтоб если юзер нажал на имени файла в CheckListBox - показалось информация - размер файла, и некоторая другая информация об этом файле (см скриншот внизу). Очень не хотелось заморачиваться с динамическим списком, поэтому делаю через костыль примерно так: Есть тип:
PHP код:

Type
  FInfo 
record
    Id   
Integer//сюда будем заносить itemindex из checklistbox'а
    
Size Cardinal// размер файла
    
Info String// дополнительная информация о файле.
  
end

Потом есть такой массив и его индекс:
PHP код:

Var
  
FI : Array [1..1000of FInfo// предположим, что файлов будет не больше 1k
  
Index Word 1// индекс этого массива 

Естественно Index сначала равен 1. Далее рекурсивно сканируем файлы.
Это уже если нашли DLL или EXE:
PHP код:

res := SearchSign(path+'\'+sr.name,False,S,SZ); // ищет в файле сигнатуру
// возвращает 255, если находит, а также возвращает в S - строку информацию
// а в SZ - размер файла
                  if res = 255 then //если нашли сигнатуру, добавляем имя файла в CheckListBox.
                  begin
                  form1.checklistbox1.Items.Append(path+'
\'+sr.name); //добавляем
// а вот здесь заносим в массив информацию о файле
                  FI[Index].Id := form1.CheckListBox1.Items.IndexOf(path+'
\'+sr.name);
                  FI[Index].Size := SZ; //размер
                  FI[Index].Info := S; //некая строка
                  Inc(Index); // и увеличиваем индекс массива
                  end; 

Ну и обработчик, если юзер нажал в CheckListBox'е на имени файла, выводим инфу о файле из нашего массива:
PHP код:

procedure TForm1.CheckListBox1Click(SenderTObject);
Var 
Word;
begin
      
For := 1 to Index do
          if 
FI[i].Id checklistbox1.itemindex then  // если ид совпадают
            
Begin
              label4
.Caption := CheckListBox1.Items[checklistbox1.itemindex]; //вывели имя файла
              
label5.Caption := IntToStr(FI[i].Size); //вывели размер
              
label3.Caption := FI[i].Info// и дополнительную инфу
            
End;
end

Косяк в том, что на первом файле не показывает информацию. На первом файле - имею ввиду Id = 0. На всех остальных - показывает. Ничего не понимаю, весь моск сломал. Что не так? Скриншоты ниже:

firstvirus 20.02.2010 23:15

Ответ: Прошу помощи
 
Цитата:

Сообщение от Tronix (Сообщение 138444)
if FI[i].Id = checklistbox1.itemindex then // если ид совпадают

А теперь глянь данные что у тебя выводятся для второго файла и сравни с данными для первого :). Индексы во всех списках начинаются не с 1 а с 0, т.е. правильно будет if FI[i].Id = checklistbox1.itemindex+1 then. И вообще для удобства массив лучше было начинать не с 1 а с 0. Еще есть вариант обойтись без массива и решить через связанный список. Правда там писать больше придется, но во первых быстрее работать будет и памяти жрать меньше(вроде). Хотя связанные списки я до сих пор разбираю, но понял что это оч удобно если грамотно использовать :). надеюсь помог, а не написал бред :).

Tronix 20.02.2010 23:28

Ответ: Прошу помощи
 
Цитата:

Сообщение от firstvirus (Сообщение 138461)
А теперь глянь данные что у тебя выводятся для второго файла и сравни с данными для первого :). Индексы во всех списках начинаются не с 1 а с 0, т.е. правильно будет if FI[i].Id = checklistbox1.itemindex+1 then. И вообще для удобства массив лучше было начинать не с 1 а с 0. Еще есть вариант обойтись без массива и решить через связанный список. Правда там писать больше придется, но во первых быстрее работать будет и памяти жрать меньше(вроде). Хотя связанные списки я до сих пор разбираю, но понял что это оч удобно если грамотно использовать :). надеюсь помог, а не написал бред :).

Дык в Id то находится реальный Id, который я туда запихиваю сразу при добавлении в checklistbox:
PHP код:

// добавляем имя файла на форму
form1.checklistbox1.Items.Append(path+'\'+sr.name);
// и сразу заносим в Id только что добавленный id
FI[Index].Id := form1.CheckListBox1.Items.IndexOf(path+'
\'+sr.name); 

Хм, может забить на Items.IndexOf и считать действительно просто от нуля? Ведь файлы последовательно добавляются... Но все равно интересно, почему такая конструкция не работает.. Странно это.
А насчет связных списков - оно конечно правильно, но вот только сильно влом ))) Вообщем-то тулзу можно сказать для себя пишу, и не хочется заморачиваться с ними просто. Я конечно понимаю, что это быдлокод :)
А насчет памяти там вообще волноватся не стоит. Я ж каждый файл гружу в память, не смотря на его размер. Когда прогонял тесты, попался EXE файл размером в 900 мб (архив самораспаковывающийся), так я его тоже в память подгрузил прямо весь )) Надо будет потом ограничение сделать и не грузить такие файлы ))

Tronix 20.02.2010 23:47

Ответ: Прошу помощи
 
Хм, а проблема то не здесь похоже. Почему-то функция не возвращает на первом файле никаких параметров... Хм..

firstvirus 21.02.2010 18:43

Ответ: Прошу помощи
 
если дашь исходник мне проще будет помочь. со списками я тррррр(ну ты понял :))лся очень долго и много. :)

Tronix 21.02.2010 18:55

Ответ: Прошу помощи
 
Да не, проблема как выяснилось не в этом. Проблема в том, что функция
res := SearchSign(path+'\'+sr.name,False,S,SZ)
при нахождении первого файла не возвращает в S и SZ ничего.
Сама функция находится в отдельном модуле и описана так:
Function SearchSign(FName: string; DoIt: Boolean; var Sinf:String; var SiZ:Cardinal): Integer;
тоесть Sinf и SiZ - возвращаемые параметры..

Вообще мне все это не нравится, какой-то говнокод получается, прям самому тошно на это смотреть :) Но баг интересный, подозреваю что какие-то косяки с проклятыми потоками. Как же я их не люблю, кто бы знал.

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

firstvirus 21.02.2010 22:00

Ответ: Прошу помощи
 
ну можно не через глобальные переменные а разделить эти функции на 2 по каждому результату.

Tronix 22.02.2010 21:43

Ответ: Прошу помощи
 
Уфф, разобрался с багом. Лог-файл полезная вещь )
Оказывается когда я обходил элементы списка, выводил сначала всю инфу, если ID совпадали, а потом шел дальше по списку и упирался в конец с пустыми элементами, где ID тоже было равно 0. И вся инфа перезатиралась пустой ). Все, что нужно было сделать - написать Index-1, вместо Index :)


Часовой пояс GMT +4, время: 14:03.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot