DBGrid i automatyczny Edit podświetlonej komórki

0

Witam!
Proszę o wskazówkę jak uzyskać efekt edycji podświetlonej komórki w dbgrid, po jej wybraniu bez względu czy user ustawił na niej kursor myszki czy komórka jest zaznaczona poprzez przyciski kursora. Po prostu musi wykonać się jakby w tle wcisnięcie F2. Próbuje to uzyskać poprzez: dbgrid1.EditorMode:=true; - niestety nie jest to rozwiązanie.

Dziękuje za podpowiedz i pozdrawiam serdecznie
Piotr

ps. próbowałem również:

 if (dataCol=3) and ( State = [gdSelected,gdFocused] )
   then
       PostMessage (Handle, WM_KEYUP, VK_F2, 0);

 
procedure TFAPQP.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
 var
   grid : TDBGrid;
   row : integer;
 begin
   grid := sender as TDBGrid;

   if (dataCol=2) and ( State = [gdSelected] )
   then
    dbgrid1.EditorMode:=true;


   row := grid.DataSource.DataSet.RecNo;
   grid.ReadOnly:=false;

   if grid.dataSource.DataSet.FieldByName('Resp_dep').AsString='HEAD'
     then grid.Canvas.Brush.Color := clSilver;
     //grid.Canvas.Brush.Color := clDkGray;

   //nie zamkniesz finish gdy OPEN Check_List

  if (Column.FieldName='Finish_Actual')
  and (grid.dataSource.DataSet.FieldByName('Finish_actual').AsString='')
  and (grid.dataSource.DataSet.FieldByName('Check_List').AsString='OPEN')
     then
      begin
        grid.Canvas.Brush.Color := clSilver;
        grid.ReadOnly:=true;
      end;
   //
   if grid.dataSource.DataSet.FieldByName('Stat').AsString='OVERDUE'
     then grid.Canvas.Brush.Color :=  TColor($9370DB);
   //
   if grid.dataSource.DataSet.FieldByName('Stat').AsString='SOONOVER'
     then grid.Canvas.Brush.Color :=  clyellow;
   //
 grid.DefaultDrawColumnCell(Rect, DataCol, Column, State) ;
end;

 
0

To nie tak się robi. Odwołujesz się do całego grida zamiast odwoływać się do aktualnie malowanej kolumny. Czyli:

if Column.Field.FieldName = 'Resp_dep' and Column.Field.AsString = 'HEAD' then 

zamiast:

if grid.dataSource.DataSet.FieldByName('Resp_dep').AsString='HEAD' 
0

dziękuje - to prawda.
Mnie jednak zależy na tym żeby w momencie gdy cela została podświetlona stała się w trybie edycji tj. żeby w niej mrugał kursor - tak jak po wciśnieciu F2

if (dataCol=2) and ( State = [gdSelected] )

ten stan wykrywa jednak symulacja wciśniecia f2 nic nie daje.

 if (dataCol=3) and ( State = [gdSelected,gdFocused] )
   then
       PostMessage (Handle, WM_KEYUP, VK_F2, 0);
 
0

To też inaczej. Po pierwsze napisz sobie procedurę o treści:

  keybd_event(VK_F2, 0, 0, 0);
  keybd_event(VK_F2, 0, 2, 0); 

i zawołaj ją w zdarzeniach OnEnter i OnColEnter swojego grida oraz w zdarzeniu AfterScroll swojego źródła danych.

0

grid.dataSource.DataSet.Edit nie rozwiąże problemu?

0

Może to i dobry pomysł, ale gdzie DBGrid1DrawColumnCell to wstawić?
w DBGrid1DrawColumnCell? - wykonuje się dla całej kolumny a nie jednej celi,
a może DBGrid1DrawDataCell - ustawiłem pułapkę nawet nie wchodzi...

0

w DBGrid1.DataSource.OnDataChange ale takie coś to bardzo zły pomysł wg mnie

0

Przeskakuję kursorem z komórki na komórkę, jeśli jest to odpowiedni typ komórki musi się załączyć tryb edycji bez konieczności klikania w cele lub wciskania F2.
Jak to zrobić?
DBGrid1.DataSource.OnDataChange - to zdarzenie które proponujesz generuje mi general error.
Pozdrawia
Piotr

0

OnDrawColumnCell jest wykonywane dokładnie dla jednej celi. Tylko że najpierw jest ustalane, co ma być namalowane. Mówiąc w dużym przybliżeniu ustalany jest prostokąt z celami, który trzeba namalować i każda z nich (z każdego wiersza i każdej kolumny) jest malowana. A w czasie malowania tego prostokąta nie zmienia się przecież ta "bieżąca" cela. Może nawet nie być w tym prostokącie i nie być malowana.
Zamiast procedury, która symuluje wciśnięcie F2, możesz spróbować jeszcze tego Edit, które podał abrakadaber. Ja tego nie próbowałem. Ogólnie to szukasz zdarzenia wołanego wtedy, gdy zmieni się "bieżąca" cela. Ale takiego nie ma. Musiałbyś napisać sobie własnego grida. Od podstaw.

0

Tak myślałem sprawa nie będzie łatwa.
Mój pomysł to własny komponent TGridList = class(TStringGrid) - zajmie mi to sporo czasu czy warto?
i obsługa zdarzenia
TGridList.DrawCell(ACol, ARow: Integer; Rect: TRect; State: TGridDrawState);
widzę że TStringGrid też nie ma zdarzenia które by się bardzo przydało onSelectCell - jak to zrobić?

Algorytm musi rozpoznać komórkę, sprawdzić jej status i wejść w tryb edycji.

Co o tym myślicie? wasze wskazówki są bardzo cenne.

1

Cały czas mam wrażenie, że błądzisz. Zdarzenie OnDrawCell służy do malowania, a nie do wymuszania edycji. Możesz wymuszać edycję w zdarzeniach, o których pisałem poprzednio. Myślę, że tak na początek to wystarczy. Choć pewnie trzeba by sprawdzać, czy Twój grid jest aktywną kontrolką formy.
Co do pisania własnej kontrolki, to (jeśli chciałbyś łatwo wykorzystać źródła z Delphi) przyjrzyj się zmiennej FCurrent w TCustomGrid. Tam trzeba by zacząć. Przerabianie TStringGrida ma jedną, ale bardzo dużą wadę. TFields źródła danych reprezentuje wartości z bieżącego wiersza. I TDBGrid jest do tego przystosowany. Przerabiając TStringGrid musiałbyś i to uwzględnić. I pewnie zrobić własne buforowanie rekordów. No i straciłbyś pewnie wydajność przewijania grida w górę i w dół (np używając PgDn i PgUp). Ale jeśli masz kasę ro zainteresuj się Gridem z firmy https://www.devexpress.com/Products/VCL/demos.xml . Jest to bardzo rozbudowany grid zachowujący się bardzo podobnie do string grida. Ale nie pamiętam, czy ma zdarzenie typu OnChangeCell. Możesz sprawdzić. Jest trial do ściągnięcia.
Ale małe pytanko. Czy w Twoim Delphi grid nie ma w opcjach dgAlwaysShowEditor?

0

Sadam2 - dziękuje ci i wszystkim którzy poświęcili swój czas na wskazówki w tej sprawie!
dgAlwaysShowEditor - to może wystarczyć moim userom, jeśli nie to powrócę do kompozycji własnego komponentu.
Have a nice day!
Piotr

1

coś takiego chcesz osiągnąć

TForm1 = class(TForm)
//...
  private
    procedure StartEdit;

    property DBGridColumn: Integer read FDBGridColumn write SetDBGridColumn;
    property DBGridRow: Integer read FDBGridRow write SetDBGridRow;
  end;

//...

procedure TForm1.dbgrd1ColEnter(Sender: TObject);
begin
  DBGridColumn := dbgrd1.SelectedIndex;
end;

procedure TForm1.SetDBGridColumn(const Value: Integer);
begin
  if FDBGridColumn <> Value then
  begin
    FDBGridColumn := Value;
    StartEdit;
  end;
end;

procedure TForm1.SetDBGridRow(const Value: Integer);
begin
  if FDBGridRow <> Value then
  begin
    FDBGridRow := Value;
    StartEdit;
  end;
end;

procedure TForm1.ds1DataChange(Sender: TObject; Field: TField);
begin
  DBGridRow := tbl1.RecNo;
end;

procedure TForm1.StartEdit;
begin
  if FDBGridColumn = 1 then
  begin
    keybd_event(VK_F2, 0, 0, 0);
    keybd_event(VK_F2, 0, 2, 0);
  end;
end;

przy kliknięciu/przejściu do kolumny nr. 1 automatycznie przechodzi w tryb edycji

0

Nie za ma co. To jeszcze dopowiem, że w Delphi JEDI, czyli w JEDI Visual Component Library jest TJvDBGrid, który ma zdarzenie OnCanEditCell. Myślę, że da się w tym zdarzeniu zablokować edycję wybranych cel. To jest Open Source. Czyli niech moc będzie z Tobą :-).

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