Ponowne programowe zaznaczanie wiersza stringgrid.

0

Witam wszystkich.

Temat wydaje się znajomy i oklepany ale chodzi o ponowne zaznaczenie a to nie takie oczywiste jak mi się wydawało.
http://4programmers.net/Forum/Newbie/151976-zaznaczanie_wszystkich_komorek_wiersza_w_stringgridzie_po_wcisnieciu_przycisku
http://www.elektroda.pl/rtvforum/topic119963.html

Pojawiła się potrzeba programowo ponownego zaznaczenia już wcześniej zaznaczonego wiersza w Delphi Stringrid i okazało się że ponowne zaznaczenie metoda zwykłego zaznaczenia nie działa. Ponowne zaznaczenie danego wiersza jest potrzebne ponieważ zawartość stringgrida się zmienia i muszę odświeżyć wyświetlane pod tabelką dane.
Poniżej jakby gotowy kod, byłbym wdzięczny za wrzucenie odpowiednich poprawek a ja szukam dalej może coś znajdę.

Przed każdym zaznaczeniem generowane są nowe liczby wypełniające jedna z kolumn, dzięki temu można sprawdzić czy zaznaczenie i ponowne zaznaczenie rzeczywiście działa (dla początkujących).
W tej postaci zaznaczenie nowej pozycji działa a ponowne zaznaczenie z wykorzystaniem tego samego mechanizmu już nie. Pytanie brzmi (żeby być precyzyjnym) jak wyglądałby kod zaznaczania w procedure MStringGrid_SelectRow żeby to działało jak należy? co zmienić?

Procedury i obsługa odpowiednich zdarzeń:

type
  TForm1 = class(TForm)
    StringGrid1: TStringGrid;
    Edit1: TEdit;
    ButtonRowNext: TButton;
    ButtonRowSame: TButton;
    procedure StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer;
      var CanSelect: Boolean);
    procedure ButtonRowSameClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure ButtonRowNextClick(Sender: TObject);
  private
     procedure Generuj();

  public

  end;


var
  Form1: TForm1;

implementation
var
   fRowWyb: Integer;          // Pozycja na liście liczona od zera

{$R *.dfm}


procedure TForm1.FormCreate(Sender: TObject);
begin
   fRowWyb:= 0;
   Generuj();
end;

procedure MStringGrid_SelectRow(const aStGDs: TStringGrid; const aRowWybSr: Integer);
var
  _myRect: TGridRect;    // do zaznaczania
  _RowWyb: Integer;
begin
  if aRowWybSr>-1
  then _RowWyb := aRowWybSr+1
  else _RowWyb := aStGDs.RowCount-1;

    with aStGDs do
    begin
      Row     := _RowWyb;
      with _myRect do
      begin
        Top := _RowWyb;
        Bottom := _RowWyb;
        Left := FixedRows;
        Right := ColCount - 1;
      end;
      Selection := _myRect;
      SetFocus;
    end;

end;

procedure TForm1.Generuj();
var _row: Integer;
begin
   Randomize;
   for _row:= 1 to StringGrid1.RowCount - 1 do
      StringGrid1.Cells[1,_row]:= IntToStr(Random(100));
end;

procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol, ARow: Integer;
  var CanSelect: Boolean);
begin
   Edit1.Text:= StringGrid1.Cells[1,ARow];
end;

// Przyciski

procedure TForm1.ButtonRowNextClick(Sender: TObject);
begin
   Generuj();
   if fRowWyb+1 > StringGrid1.RowCount - 2
   then fRowWyb:= 0
   else fRowWyb:= fRowWyb +1;

   MStringGrid_SelectRow(StringGrid1, fRowWyb);
end;

procedure TForm1.ButtonRowSameClick(Sender: TObject);
begin
   Generuj();
   MStringGrid_SelectRow(StringGrid1, fRowWyb);
end;

end.

A potem wystarczy wkleić na formę:

object StringGrid1: TStringGrid
  Left = 16
  Top = 16
  Width = 345
  Height = 145
  TabOrder = 2
  OnSelectCell = StringGrid1SelectCell
end
object Edit1: TEdit
  Left = 16
  Top = 216
  Width = 121
  Height = 21
  TabOrder = 3
  Text = 'Edit1'
end
object ButtonRowNext: TButton
  Left = 16
  Top = 243
  Width = 129
  Height = 25
  Caption = 'Zaznacz nastepny'
  TabOrder = 0
  OnClick = ButtonRowNextClick
end
object ButtonRowSame: TButton
  Left = 151
  Top = 243
  Width = 129
  Height = 25
  Caption = 'Zaznacz ten sam'
  TabOrder = 1
  OnClick = ButtonRowSameClick
end

zamiana znacznika <quote> na <code class="delphi"> - @furious programming

1

zaznacz inny a potem ten który chcesz zaznaczyć

0

Nie do końca rozumiem, do czego dążysz, ale, tak jak ja to widzę, to:

procedure TForm1.ButtonRowSameClick(Sender: TObject);
begin
  Generuj();
  StringGrid1.Invalidate;
  StringGrid1.SetFocus;
end; 
0

@Sadam2 ten sposób nie działa, może dlatego że mam delphi 2007
@abrakadaber zrobiłem tak

    with aStGDs do
    begin
      Row     := RowCount - 1;   // bo ostatni wiersz mam pusty
      Row     := _RowWyb;
      // dalej jak w powyższym przykładzie

Jesli się nie da bardziej elegancko to musi tak zostać, jednak nie jestem pewny czy taka chwilowa zmiana wartości w ten sposób nie ma wpływu na inne zdarzenia. Jak na razie na tym etapie działa dobrze. Dziękuję za podpowiedź.

0

@Integers - ColCount zwraca ilość kolumn, czy indeks ostatniej kolumny? Bo jeśli ilość kolumn, to ostatnia ma indeks ColCount - 1, a przedostatnia ColCount - 2.

0

W moim delphi działają oba sposoby. Czyli I Twoja metoda i mój kod. Ale przedmówca mnie natchnął. Tobie chyba chodzi o to, żeby był zaznaczany cały wiersz. Jeśli tak i jeśli nie potrzebujesz edytować tego grida, to wystarczy dać mu Enabled na false i wywalić SetFocus.

0

Co do

goEditing:= False;

to masz rację, ale

procedure TForm1.ButtonRowSameClick(Sender: TObject);
begin
  Generuj();
  StringGrid1.Invalidate;
  StringGrid1.SetFocus;
end;

u mnie nie reaguje.. a na formie i w kodzie mam tylko to co na początku pokazałem. Ale mimo że zmiana wartości Row pomaga było by dobrze ustalić dlaczego Invalidate nie działa.

1

Czyli tak: u mnie działa, u Ciebie nie. Żeby nie było nieporozumień to załączam źródła i exe. Mam Delphi 2006. Ale zainstalowałem je ponad 8 lat temu i od tego czasu już zdążyłem nagrzebać. Nie stać mnie (czasowo i sprzętowo) na stawianie Delphi od nowa, aby sprawdzić, czy w takim "oryginalnym" też będzie mi działać. Na dodatek chyba nie rozumiem, co, według Ciebie, nie działa. Może w "moim" exe też nie działa, a ja, stary ślepol, nie widzę. Mam nadzieję, że odpowiesz.

0

No właśnie też mi zależy na wyjaśnieniu co za Zonk.. ale już się wyjaśniło (mniej więcej).. ściągnąłem paczkę, uruchamiam exe, klikam kolejno przyciski i Zaznacz ten sam inaczej nie działa jak trzeba.. więc albo się mylę albo mój WinXP ma defekt w tym miejscu. czasami tak bywa. Dzięki za cierpliwość i dociekliwość.

0
Integers napisał(a):

... uruchamiam exe, klikam kolejno przyciski i Zaznacz ten sam inaczej nie działa jak trzeba.. więc albo się mylę albo mój WinXP ma defekt w tym miejscu. czasami tak bywa. Dzięki za cierpliwość i dociekliwość.

Zrozumiałem z tego, że "moje" exe u Ciebie nie działa, jak trzeba. Ale co znaczy, że nie działa, jak trzeba? To jak to ma być to "trzeba"? Bom ciekaw.

Ja, jak na moim starutkim XP uruchamiam projekt, to mam:

10d877fb57.png

klikam na zaznacz następny i mam:

f8e9216008.png

klikam na zaznacz ten sam i mam:

8d1bd391ea.png

klikam na zaznacz ten sam inaczej i mam:

273a56bf07.png

I od razu w tym miejscu przepraszam moderatora. Próbowałem te obrazki wkleić przeznaczonym do tego przyciskiem "Wstaw obraz", ale nic mi nie wychodziło.

A co do tematu, to naprawdę jestem ciekaw, co się u Ciebie pokazuje.

0

A nie.. to u Ciebie też nie działa.. Po wciśnięciu zaznacz ten sam inaczej powinna się wyświetlić liczba 71 czyli aktualnie występująca w zaznaczonym (tym samym) wierszu. A masz w tej chwili 74 które się pojawiło w zaznacz następny.

1

A, to o to Ci idzie. No to zapomnij o trzecim przycisku. On był tylko tak, dla wyjaśnienia.

Pewnie Twoją potrzebę można by załatwić wieloma metodami. Mi wpadły dwie do głowy:

 type
  THackCustomGrid = class(TCustomGrid);


{$R *.dfm}
procedure MStringGrid_SelectRow(const aStGDs: TStringGrid; const aRowWybSr: Integer);
var
  _myRect: TGridRect;    // do zaznaczania
  _RowWyb: Integer;
begin
  if aRowWybSr > -1
  then _RowWyb := aRowWybSr + 1
  else _RowWyb := aStGDs.RowCount - 1;

  with aStGDs do
  begin
    Row := _RowWyb;
    THackCustomGrid(aStGDs).FocusCell(1, _RowWyb, True);
    with _myRect do
    begin
      Top := _RowWyb;
      Bottom := _RowWyb;
      Left := FixedRows;
      Right := ColCount - 1;
    end;
    Selection := _myRect;
  end;
end;

oraz:

procedure MStringGrid_SelectRow(const aStGDs: TStringGrid; const aRowWybSr: Integer);
var
  _myRect: TGridRect;    // do zaznaczania
  _RowWyb: Integer;
  MustSelect: Boolean;
begin
  if aRowWybSr > -1
  then _RowWyb := aRowWybSr + 1
  else _RowWyb := aStGDs.RowCount - 1;

  with aStGDs do
  begin
    Row := _RowWyb;
    aStGds.OnSelectCell(aStGds, 1, _RowWyb, MustSelect);
    with _myRect do
    begin
      Top := _RowWyb;
      Bottom := _RowWyb;
      Left := FixedRows;
      Right := ColCount - 1;
    end;
    Selection := _myRect;
  end;
end; 
0

Oba działają jak trzeba. W pierwszym przypadku widok tabelki się przesuwa na lewo a w drugim na prawo ale bezpieczniej to wygląda niż w przypadku chwilowej zmiany wartości Row. Takiego rozwiązania bym nie wymyślił. Dziękuję.

0
Integers napisał(a):

... W pierwszym przypadku widok tabelki się przesuwa na lewo a w drugim na prawo ...

Jejku, a jak to wygląda?. Ja znowu (tak, jak poprzednio tej zawartości Edita) nic nie widzę u siebie.

0

Nie, spoko teraz jest już w porządku, to o przesunięciu tabeli to już taki szczegół. To i przy zwykłym zaznaczaniu wiersza tak samo działa.. tylko chodziło mi o to że w jednym przypadku pokazuje lewy a w drugim prawy brzeg tabeli (gdy tabela ma znacznie więcej kolumn niż jest miejsca żeby pokazać).

0

A to ciekawe. Zmieniłem. Było 5 w ColumnCount, teraz mam 20. I nic mi nie lata. Możesz załączyć kod?

0

Kod to ten sam co podesłałeś jako załączniki powyżej, tylko odblokowałem Enabled Tabelki i podmieniam procedurę MStringGrid_SelectRow na Twoje przykłady. Jeśli masz 20 kolumn to ustaw widok na środkowe.. i będzie latało.
Dla jasności to co podpowiedziałeś jest super, miodzio itp. wystarczające ale jeśli Cię nurtuje i udało by się żeby nie latało na boki to też jestem ciekaw czy się da to poprawić.

1

Aha. Tutaj jest pewna niedogodność. Bieżąca cela nie musi być widoczna. Ale może idzie Ci o to, co teraz wyskrobałem.

0

Właśnie dokładnie taki efekt braku samo-przesuwania kolumn przez program. Pewnie nie tylko mi się to przyda. Podpatrzę jak się co się tam dzieje. Dzięki

0
Integers napisał(a):

Do kompilacji komponentu jeśli ktoś nie ma ColoredStringGrid z paczki SG.ZIP może się przydać moduł
http://read.pudn.com/downloads65/sourcecode/delphi_control/232641/MystringGrid.pas__.htm

Hmm... W SG.ZIP jest MyStringGrid.pas. Po prostu zrobiłem taki prosty komponent i załączyłem. A link przez Ciebie podany prowadzi do jakiejś dziwnej realizacji czegoś zamiast DBGrida. To coś ma wady. Widać wycieki pamięci. Czegóż to ludzie nie publikują, no, no. No ale idea ładowania do jednego grida wybranych danych z różnych źródeł byłaby może niekiedy przydatna. O ile tych danych nie jest zbyt dużo. No ale to wymaga znacznego dopracowania. Dużo pracy. Po mojemu bardzo dużo, aby otrzymać znośną funkcjonalność.

0

Ok, usunąłem link, nie rozpowszechniamy wadliwego kogu ^^

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