TToolButton dynamicznie - problem z Image

0

Witam serdecznie, piszę, ponieważ napotkałem dość nietypowy problem, którego jak się okazało nie mogę na żaden sposób rozwiązać.

Sprawa dotyczny TToolButton i obrazów w TImageList.

Mam formularz, który w późniejszym czasie będzie służył jako okno dialogowe. Są na nim komponenty typowe jak na standardowych dialogach. Prócz tego, jest komponent TToolBar. Na tym komponencie tworzę dynamicznie listę dysków - sprawdzam ile jest partycji z flagą DRIVE_FIXED przez GetDriveType, po czym dynamicznie tworzę tyle button'ów z klasy TToolButton, ile jest uzyskanych wcześniej partycji.

Nie ma najmniejszego problemu w uzyskaniu liter partycji opisanych jako DRIVE_FIXED. Z tworzeniem przycisków też nie ma większego problemu. Wszystko w tym temacie gra jak tamta lala. Problem pojawia się, gdy potrzebuje przypisać obraz z ImageList do utworzonego wcześniej przycisku.

Sprawa wygląda tak, że mam pięć partycji, stąd po pojawieniu się formy widnieje 5 przycisków na pasku. Litery dysków to: C:, E:, F:, G:, H:. W komponencie ImageList mam dodane dwie pierwsze ikony jako Pulpit i Moje dokumenty. Kolejne 25 to Obrazy typu PNG z grafiką dysku oraz jego literą. Podczas tworzenia przycisków obliczam z prostego wzoru indeks obrazu w ImageList:

dla znaku C - jego kod ASCII to 67, indeks obrazu z dyskiem C: to 2, więc 67 - 2 = 65

stąd:

ImageIndex := Ord('C') - 65;

W ten sposób mogę pozyskać dla każdej partycji w zależności od znaku indeks obrazu w ImageList.

I niestety tutaj pojawia się nieoczekiwany problem. Mianowicie litery dysków pobiera bezbłędnie, Hint ustawia jako:

tbNew := 'Dysk lokalny (' + cDrive['C'] + ')';

z tym też nie ma żadnego problemu. Caption przycisku to ścieżka dysku (czyli w tym przypadku litera dysku i ':'). Też jest wszystko w porządku. Problem pojawia się podczas ładowania obrazów do przycisków (czyli ImageIndex). Tutaj jest kłopot, ponieważ indeksy są takie, jakie mają być, ale obrazy ładuje różnie. Pierwsze trzy przyciski są w porządku (czyli C:, E:, F:), ale dwa ostatnie zawsze są takie same. Niestety dla dysku G: zostaje przypisany obraz dysku H:. Dla dysku H: jest w porządku - obraz z dyskiem H:.

Mam więc pytanie - co jest źle w poniższym kodzie. Ja niestety nie mogę nic złego w tym znaleźć:

procedure TLoadPictureDialogForm.FormCreate(Sender: TObject);
var
  tbNew: TToolButton; //nowy przycisk
  cDrives: array of Char; //tablica z odnalezionymi literami partycji
  cDrive: Char; //licznik pętli wyszykującej
  iLeft: Integer; //nie dotyczy - służy do ustawiania kolejności przycisków
  I: Byte; //licznik pętli
begin
  {DRIVE MENU}
  iLeft := 78;
  SetLength(cDrives, 0);

  for cDrive := 'C' to 'Z' do //tworzenie listy partycji
    if GetDriveType(PChar(cDrive + ':\')) = DRIVE_FIXED then
      begin
        SetLength(cDrives, Length(cDrives) + 1);
        cDrives[High(cDrives)] := cDrive;
      end;

  if Length(cDrives) > 0 then //jeżeli znaleziono jakąś partycję
    for I := 0 to High(cDrives) do
      begin //tworzenie przycisków
        tbNew := TToolButton.Create(Self);

        with tbNew do
          begin
            Name := 'tbDrive' + cDrives[I];
            Parent := tbMenu;
            Caption := cDrives[I] + ':\';

            iLeft := iLeft + 39;
            Left := iLeft;

            Cursor := crArrow;
            ImageIndex := Ord(cDrives[I]) - 65; //ustawienie indeksu obrazu

            ShowHint := True;
            ParentShowHint := False;
            Hint := 'Dysk lokalny (' + cDrives[I] + ':)'; //ustawienie podpowiedzi
          end;
      end;
end;

Dodam jeszcze, że obrazy w komponencie ImageList są poukładane prawidłowo, sprawdzałem też czy grafiki się powtarzają, ale nic takiego nie ma miejsca.

Bardzo proszę o pomoc.
Dziękuję z góry. Pozdrawiam.

0
            ImageIndex := Ord(cDrives[I]) - 65;
            Caption := IntToStr(ImageIndex);
 
            iLeft := iLeft + 39;
            Left := iLeft;
 
            Cursor := crArrow;

i zobacz co Ci się na przyciskach pokaże. Obrazki w IL mogą być ułożone prawidłowo, ale czy mają indeksy po kolei?

0

Obrazki w IL mogą być ułożone prawidłowo, ale czy mają indeksy po kolei?

Tak, zanim posta napisałem dokładnie sprawdziłem, czy wszystko jest tak jak ma być. Sprawdzałem czy obrazki i ich litery są prawidłowo ustawione według indeksów. Dodawałem do IL po jednym obrazku by czegoś źle nie ustawić, więc każdy obraz jest na swoim miejscu.

Naprawdę nie wiem co może być w tym kodzie źle. Myślę, że nie w nim tkwi problem. Ale z kolei jeśli to nie kod jest błędny a IL jest dobrze zorganizowany to co w takim razie jest źle...?

Sam już nie wiem.

ImageIndex sprawdzałem podczas tworzenia formularza. Zasotosowałem taki kod:

ImageIndex := Ord(cDrives[I]) - 65;
Caption := cDrives[I] + ':\';

ShowMessage(IntToStr(ImageIndex));

Za każdym razem dla przycisku tbDriveG pokazuje w ShowMessage wartość 6. Sprawdziłem więc co się dzieje w IL, pod indeksem 6 jest obrazek z dyskiem G.

0

no to jak ImageIndex wynosi 6 i w IL pod 6 jest obrazek z G to jedynie czary...
Zrób printscreena IL i pokaż go tu. Dodaj na formę memo

procedure TLoadPictureDialogForm.FormCreate(Sender: TObject);
var
  cDrive: Char; //licznik pętli wyszykującej
  iLeft: Integer; //nie dotyczy - służy do ustawiania kolejności przycisków
begin
  {DRIVE MENU}
  iLeft := 78;

  for cDrive := 'C' to 'Z' do //tworzenie listy partycji
    if GetDriveType(PChar(cDrive + ':\')) = DRIVE_FIXED then
      with TToolButton.Create(Self) do
      begin
        Name := 'tbDrive' + cDrive;
        Parent := tbMenu;
        Caption := cDrive + ':\';
 
        iLeft := iLeft + 39;
        Left := iLeft;
 
        Cursor := crArrow;
        ImageIndex := Ord(cDrive) - 65; //ustawienie indeksu obrazu
 
        ShowHint := True;
        ParentShowHint := False;
        Hint := 'Dysk lokalny (' + cDrive + ':)'; //ustawienie podpowiedzi
        
        memo1.Lines.Add('Drive: ' + cDrive + '  Index: ' + IntToStr(ImageIndex));
      end;
end;

co dostajesz w memo?

0

misiekd, nie sprawdzałem Twojego kodu, lecz wiem, że jest poprawny - wynikiem tego będzie:

Drive: C Index: 2
Drive: E Index: 4
Drive: F Index: 5
Drive: G Index: 6
Drive: H Index: 7

Na dodatek powiem, że z mojego kodu nie winika nic złego. Ale muszę powiedzieć, że niestety jeżeli zmienię flagę z DRIVE_FIXED na DRIVE_CDROM (u mnie jest tylko jeden napęd - Dysk D: (mam laptopa)), to dzieją się jeszcze większe jaja. Mianowicie fakt faktem utworzony zostanie przycisk z obrazem dysku D:, ale drugi przycisk z kolei (czyli Moje dokumenty) także zostaje zmieniony, choć nigdzie w kodzie nie jest to uwzględnione (też zostaje mu zmieniony obraz na dysk D:). Co jest tego przyczyną? Nie mam zielonego pojęcia... Dlaczego przycisk na sztywno ustawiony zmienia się? Ja myślałem, że kompilator coś świruje.

Coś mnie napadło, żeby zmienić kolejność przypisywanych właściwości komponentom. Najpierw ustawiłem linię zmieniającą pozycję od lewej, a następnie pozostałe właściwości. Co mogę powiedzieć? Działa w 100% i dla flagi DRIVE_FIXED i dla DRIVE_CDROM. Nawet podłączyłem dodatkowo dysk przenośny na USB, żeby pokazało jeszcze jedną partycję i także dla niej zostaje poprawnie utworzony przycisk z dyskiem I:.

Co ma do rzeczy kolejność przypisywanych właściwości? Nie wiem i do tej pory nie rozumiem. Działający w pełni kod wygląda w ten sposób:

procedure TLoadPictureDialogForm.FormCreate(Sender: TObject);
var
  tbNew:   TToolButton;
  cDrives: array of Char;
  cDrive:  Char;
  iLeft:   Integer;
  I:       Byte;
begin
  {DRIVE MENU}
  iLeft := 78;
  SetLength(cDrives, 0);

  for cDrive := 'C' to 'Z' do
    if GetDriveType(PChar(cDrive + ':\')) = DRIVE_FIXED then
      begin
        SetLength(cDrives, Length(cDrives) + 1);
        cDrives[High(cDrives)] := cDrive;
      end;

  if Length(cDrives) > 0 then
    for I := 0 to High(cDrives) do
      begin
        tbNew := TToolButton.Create(Self);

        with tbNew do
          begin
            iLeft := iLeft + 39;
            Left := iLeft;

            Name := 'tbDrive' + cDrives[I];
            Parent := tbMenu;
            Caption := cDrives[I] + ':\';

            Cursor := crArrow;
            ImageIndex := Ord(cDrives[I]) - 65;

            ShowHint := True;
            ParentShowHint := False;
            Hint := 'Dysk lokalny (' + cDrives[I] + ':)';
          end;
      end;
end;

W każdym razie teraz wszystko działa. Jeżeli naprawdę nie ma znaczenia kolejność edytowanych właściwości, to tak jak piszesz misiekd - dzieją się cuda.

Podsumowując - dziękuję za zainteresowanie i pomoc.
Pozdrawiam.

1 użytkowników online, w tym zalogowanych: 0, gości: 1