Odznaczenie ComboBoxa

0

Witam ponownie, długo mnie tu nie było i znowu wiele rzeczy sobie muszę przypomnieć. Mój problem jest chyba banalny, wiedziałem jak to rozwiązać, tak mi się przynajmniej wydaje, ale nie mogę teraz sobie przypomnieć jak to zrobić. A więc na ekranie mam jeden ComboBox. Na razie nie chcę, zmieniać jego wyglądu. Tak jak mi ktoś kiedyś radził wolę napisać funkcjonalną aplikacje bez wymyślnego interfejsu, a dopiero później wszystko usprawniać i ulepszać gdy już będzie działało tak jak chce. Jednak strasznie mnie razi jedna rzecz. Otóż po zmienieniu wartości ComboBoxa text w nim wyświetlony zaznacza się na niebiesko, jakby był zaznaczony przez myszkę. W jaki sposób mogę to zmienić. Tak żeby zmieniła się wartość i żeby wygląd był taki jak na początku tyle, że ze zmienioną wartością. Mam nadzieję, ze dobrze wytłumaczyłem.

2

Ustaw właściwość Style na np. csOwnerDrawFixed i oprogramuj zdarzenie OnDrawItem, a zaznaczenie będzie mogło wyglądać tak jak chcesz; Tyle tylko, że tekst także będziesz musiał malować ręcznie - nic trudnego, zwykłe wywołanie TextOut dla określonej pozycji;

Jeżeli nie chcesz, aby rysowana była standardowa (kropkowana) ramka focusa, to na koniec metody rysującej wstaw poniższy kod:

procedure TForm1.ComboBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState);
begin
  with (Control as TComboBox).Canvas do
  begin
    // Twoje malowanie

    if odFocused in State then
    begin
      Pen.Color := Pen.Color xor $FFFFFF;
      DrawFocusRect(Rect);
    end;
  end;
end;

A systemowe kolory możesz bez problemu wykorzystać; Do obsługi specjalnych kolorów przyda się funkcja ColorToRGB.

2
ComboBox1.Style:=csDropDownList; 
0
Paweł Dmitruk napisał(a):
ComboBox1.Style:=csDropDownList; 

Niemal to czego potrzebowałem. Tyle tylko, że w tej sytuacji nie wyświetla się to co ustawiłem jako ComboBox1.Text := Jezyk(10); a jedynie puste pole.

0

Styl csDropDownList służy właśnie do tego, żeby nie dało się nic wpisać, a jedynie umożliwić wybór itemka z listy;

Jeżeli chcesz ustawiać jakiś tekst w edytorze komponentu, ale blokować wpisywanie tekstu z klawiatury czy wklejania ze schowka, to skorzystaj ze stylu csDropDown, zablokuj klawiaturę (np. w zdarzeniu OnKeyDown) oraz przypisz pusty PopupMenu do komponentu;

Można też zrobić inne "myki", żeby osiągnąć żądany efekt.

0
furious programming napisał(a):

Styl csDropDownList służy właśnie do tego, żeby nie dało się nic wpisać, a jedynie umożliwić wybór itemka z listy; Jeżeli chcesz ustawiać jakiś tekst w edytorze komponentu, ale blokować wpisywanie tekstu z klawiatury czy wklejania ze schowka, to skorzystaj ze stylu csDropDown, zablokuj klawiaturę (np. w zdarzeniu OnKeyDown) oraz przypisz pusty PopupMenu do komponentu;

Można też zrobić inne "myki", żeby osiągnąć żądany efekt.

PopupMenu nic mi niestety nie mówi. csDropDownList mi się bardzo podoba i niemal pasuje temu co bym chciał zrobić. Nawet jego wygląd jest znacznie ciekawszy. Jedyna zmiana jaką bym chciał to nie tyle aby móc coś wpisywać, bo właśnie na tym mi nie zależy, ale to aby domyślnie wyswietlała się wartość jednego z tych itemów które są dostępne do wyboru.

2
 ComboBox1.ItemIndex:=0;
//możesz przypisać wartość Text, tyle że tekst musi być jednym z itemów
0
dani17 napisał(a)

Jedyna zmiana jaką bym chciał to nie tyle aby móc coś wpisywać, bo właśnie na tym mi nie zależy, ale to aby domyślnie wyswietlała się wartość jednego z tych itemów które są dostępne do wyboru.

No to jeśli domyślnie ma wyświetlać się treść któregoś z itemów, to musisz ustalić ItemIndex, o czym napisał Paweł;

Standardowo, po położeniu komponentu na formularz, ItemIndex posiada wartość -1, czyli żadna pozycja nie jest wybrana (dlatego miałeś puste pole edytora); Itemy indeksowane są od 0, więc pierwszy i ten Twój domyślny będzie właśnie na tej pozycji; Dlatego też albo ustaw wartość właściwości ItemIndex w okienku Inspektora Obiektów, albo ustaw go np. w konstruktorze formularza, tak jak podał poprzednik; Jeżeli będziesz chciał zmienić tekst domyślnej wartości, to wpisz ją do Items[0];

Szkoda że od razu nie napisałeś tak - satysfakcjonującą odpowiedź dostałbyś wiele godzin temu.

0

Przy czym jeszcze jest jedna trudność. To nie może być losowy Item. Tylko konkretny z pliku tekstowego. Żeby lepiej nakreślić sytuację opiszę o co dokładnie chodzi. ComboBox znajduje się w Panelu "Ustawienia" i jest on wyborem języka programu. Mam do wyboru polski i english. Uszeregowane alfabetycznie. Aktualny język programu zapisany jest w pliku tekstowym usersettings. Mam napisaną funkcję której wynikiem jest string w danym języku. Funkcja pobiera z usersettings dane i otwiera odpowiedni plik językowy, a następnie sczytuję odpowiednią linijkę przekazaną do funkcji jako parametr. W ten sposób ComboBox1.Text := Jezyk(10); ustalałem zawsze odpowiedni string niezależnie od języka. Teraz nie wiem który index ustawić.

Zapewne muszę to zrobić mniej więcej tak: ?

 
for i := 0 to (ilosc itemow - 1) do
  if item[i] = Jezyk(10) then
    ComboBox1.ItemIndex := i;

Tylko kwestia, jak wyciągnąć ilość itemow, a po drugie wartość konkretnych itemów w zależności od i. Przepraszam, jeśli to banalne pytanie, ale już przysypiam i trochę nie bardzo jestem w stanie myśleć logicznie.

1

Napisałeś tak, że przynajmniej ja nadal nie bardzo wiem, co chcesz osiągnąć. Items to własnośc bazująca na klasie TStrings. A z nieabstrakcyjnych jest to na przykład klasa TStringList. Ilośc itemów jest we własności Count. Klasa ta ma także metody do ładowania i zapisywania do pliku. Można też przypisać jej zawartość obiektu typu TStringList poprzez metodę Assign. Wszystko jest pokazane w przykładach na mnóstwie stron, które można wyszukać. Tak że nic, tylko pogooglować, pokombinować trochę samodzielnie i używać. A program będzie "zrobi" to, co chciałbyś żeby zrobił :)

0

@dani17 - nie zmieniasz wartości właściwości Text, tylko wartość pierwszej pozycji we właściwości Items - oczywiście jeśli ItemIndex jest równy 0 (to oznacza, że aktywnym itemem jest wartość domyślna); Potem tylko ustawiasz ItemIndex na 0 i gitara;

Źródła przykładowego programu (kompilowane pod Delphi7) masz w załączniku (dla Lazarusa kod będzie wyglądał tak samo).

0

Można ten program odpalić by działał w Lazarusie? Niestety nie bardzo wiem jak :/

Załóżmy że mam takie Itemy: Warszawa, Kraków, Wrocław, Poznań, Gdańsk, Zakopane. Nie znam kolejności tych Itemów. W pliku usersettigns jest zapisane np. Gdańsk. I właśnie Gdańsk chciałbym wyświetlić jako CB1.Text Jak to zrobić? Zapewne w taki sposób jak podałem kod, tylko jak się odnieść do itema w zależności od indeksu?

3

Po prostu:

ComboBox1.ItemIndex:= ComboBox1.Items.IndexOf('Gdańsk');

chyba że chcesz ustawiać domyślny w razie gdyby nie znaleziono to:

var
  index: Integer;
begin
  index:= ComboBox1.Items.IndexOf('Gdańsk');
  if index > 0 then
    ComboBox1.ItemIndex:= index
  else
    ComboBox1.ItemIndex:= 0; //wartosc domyslna jezeli nie znaleziono
end;

Odnieść się? Znaczy odczytać tekst wybranego?

var
  text: string;
begin
  text:= ComboBox1.Items[ComboBox1.ItemIndex];
end;
1

Można ten program odpalić by działał w Lazarusie? Niestety nie bardzo wiem jak :/

@dani17 - myśl trochę; Otwierasz Lazarusa i wybierasz z menu głównego: Tools\Convert Delphi Project to Lazarus Project :]

@kAzek napisał Ci co zrobić, więc nie ma co papugować; Od siebie dodam tylko tyle, że wartość domyślna powinna być pierwsza na liście (czyli pod indeksem 0); Ty nie wiesz który będzie Gdańsk na liście, więc możesz odnaleźć go metodą IndexOf (tak jak pokazał poprzednik), a następnie przesunąć go na początek listy, za pomocą metody Move;

PS: Jeżeli wątek dotyczy Lazarusa, to nie dorzucaj do tagów Delphi;
PPS: Jeśli używasz znaków diakrytycznych w itemkach komponentu, to możesz mieć problem z kodowaniem znaków.

0
furious programming napisał(a):

Można ten program odpalić by działał w Lazarusie? Niestety nie bardzo wiem jak :/

@dani17 - myśl trochę; Otwierasz Lazarusa i wybierasz z menu głównego: Tools\Convert Delphi Project to Lazarus Project :]

Nigdy nie używałem Delphi, a projektów Delphi nie otwierałem w Lazarusie, dlatego nawet nie znałem takiej opcji, a przynzaję że wcześniej nie zwróciłem na nią uwagi.

furious programming napisał(a):

PS: Jeżeli wątek dotyczy Lazarusa, to nie dorzucaj do tagów Delphi;

Ok, będę pamiętał na przyszłość. Po prostu rozwiązania są takie same, więc nawet jak ktoś by szukał podobnego rozwiązania dla Delphi to mógłby znaleźć w ten sposób.

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