Delphi stringgrid Функция TAdvsTringgrid для отключения и повторного включения щелчков мыши - PullRequest
0 голосов
/ 16 мая 2018

Существует ли функция Delphi для включения или отключения щелчков мышью для сетки строк?

Я использую производную stringgrid, называемую Tadvstringgrid, которая позволяет окрашивать ячейки на основе contens

Мне нужно предотвращать щелчки мыши внутри сетки строк при заполнении элемента управления данными из различных потоков.

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

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Grids, StdCtrls;

type
  TForm1 = class(TForm)
    StringGrid1: TStringGrid;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}




type
  TThread_populate_stringgrid = class(TThread)

  strict private

f_stringgrid_to_populate:Tstringgrid;
f_name:string;




  protected

    procedure Execute; override;




  public

    constructor Create(a_name:string;a_stringgrid_to_populate:Tstringgrid);




  end;



constructor TThread_populate_stringgrid.Create(a_name:string;a_stringgrid_to_populate:Tstringgrid);
begin
  inherited Create(False);
  freeonterminate:=true;
  priority:=tpNormal ;

f_name:=a_name;
f_stringgrid_to_populate:=a_stringgrid_to_populate;
end;






procedure TThread_populate_stringgrid.Execute;
begin

Synchronize(
procedure
begin



f_stringgrid_to_populate.cells[0,0]:='DATE';
f_stringgrid_to_populate.cells[1,0]:='NAME';
f_stringgrid_to_populate.cells[2,0]:='ADRESS';
f_stringgrid_to_populate.cells[3,0]:='CITY';
f_stringgrid_to_populate.cells[4,0]:='COUNTRY';


f_stringgrid_to_populate.Cols[0].Add(FormatDatetime('dd-mm-yyyy hh:mm:ss', Now));
f_stringgrid_to_populate.Cols[1].Add(f_name);
f_stringgrid_to_populate.Cols[2].Add('58 RED ROAD');
f_stringgrid_to_populate.Cols[3].Add('ENGLAND');
f_stringgrid_to_populate.Cols[3].Add('UK');



end
)
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
TThread_populate_stringgrid.Create('Andrei',form1.StringGrid1);
TThread_populate_stringgrid.Create('Matei',form1.StringGrid1);
TThread_populate_stringgrid.Create('Iulia',form1.StringGrid1);
TThread_populate_stringgrid.Create('Petru',form1.StringGrid1);
TThread_populate_stringgrid.Create('Gheorghe',form1.StringGrid1);
TThread_populate_stringgrid.Create('Tudor',form1.StringGrid1);
TThread_populate_stringgrid.Create('Cineva',form1.StringGrid1);
TThread_populate_stringgrid.Create('Altcine',form1.StringGrid1);
end;

end.

Спасибо!

1 Ответ

0 голосов
/ 22 мая 2018

Вот решение, которое работает для меня:

-В главной форме поместите компонент «ApplicationEvents».

-Перейдите в раздел «События» ApplicationEvents

-дважды щелкните по свойству «Onmessage» и добавьте следующую процедуру

procedure TForm1.deactivate_mouse_in_advstringgrid(var Msg: tagMSG;
  var Handled: Boolean);

 var
  pnt: TPoint;
  ctrl: TWinControl;
 begin
  if (
  (Msg.message = SB_VERT) OR
  (Msg.message = SB_HORZ) OR
  (Msg.message = WS_HSCROLL) OR
  (Msg.message = WS_VSCROLL) OR
  (Msg.message = WM_VSCROLL) OR
  (Msg.message = WM_MOUSEWHEEL) OR
  (Msg.message = WM_LBUTTONDOWN)   OR
  (Msg.message = WM_LBUTTONUP)   OR
  (Msg.message = WM_LBUTTONDBLCLK)   OR
  (Msg.message = WM_MBUTTONDOWN)   OR
  (Msg.message = WM_MBUTTONUP) OR
  (Msg.message = WM_MBUTTONDBLCLK) OR
  (Msg.message = WM_RBUTTONDOWN) OR
  (Msg.message = WM_RBUTTONUP) OR
  (Msg.message = WM_RBUTTONDBLCLK) OR
  (Msg.message = WM_KEYUP) OR
  (Msg.message = WM_KEYDOWN)
  )

  then
  begin

    if not GetCursorPos(pnt) then Exit;
    ctrl := FindVCLWindow(pnt);
    if Assigned(CTRL) then
   begin
      if Ctrl is TAdvstringgrid then
         begin
        // Msg.hwnd:=ctrl.Handle;
      //Msg.hwnd := advsg1.Handle;
            if thread_activ>0 then
               begin
              Msg.hwnd := 0;
              Exit;
                end
            else
              begin
              Msg.hwnd:=ctrl.Handle;
             end;
  end;
  end;
  end;
end;

Если вы используете компонент Tadvstringgrid, измените этот код на «если Ctrl равен TAdvstringgrid».

Если вы используетеStringgrid замените это на «если Ctrl is TStringgrid».

Вышеприведенная процедура использует глобальную переменную «thread_activ», которая содержит количество активных потоков.Таким образом, если есть активные потоки, использующие компонент Advstringgrid, щелчки мыши, колесо мыши, полосы прокрутки и нажатия клавиш подавляются.

Поток сохраняется во втором модуле, имеющем следующий код:

unit thread_stringgrid;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Grids, StdCtrls;


type
  TThread_populate_stringgrid = class(TThread)

  strict private

f_stringgrid_to_populate:Tstringgrid;
f_name:string;


  protected

    procedure Execute; override;



  public
    CriticalSection: TRTLCriticalSection;
    constructor Create(a_name:string;a_stringgrid_to_populate:Tstringgrid);
  end;



implementation

{use the unit that holds the global vaiable "thread_activ"}
uses unit1;



constructor TThread_populate_stringgrid.Create(a_name:string;a_stringgrid_to_populate:Tstringgrid);
begin
  inherited Create(False);
  freeonterminate:=true;
  priority:=tpNormal ;

f_name:=a_name;
f_stringgrid_to_populate:=a_stringgrid_to_populate;
end;



procedure TThread_populate_stringgrid.Execute;
begin

//before the threads starts
InitializeCriticalSection(CriticalSection);

//in the thread
EnterCriticalSection(CriticalSection);
//From now on, you can safely make
//changes to the variables.

{increment variable from main unit1}
inc(unit1.thread_activ);

//End of safe block
LeaveCriticalSection(CriticalSection);

Synchronize(
procedure
begin

f_stringgrid_to_populate.cells[0,0]:='DATE';
f_stringgrid_to_populate.cells[1,0]:='NAME';
f_stringgrid_to_populate.cells[2,0]:='ADRESS';
f_stringgrid_to_populate.cells[3,0]:='CITY';
f_stringgrid_to_populate.cells[4,0]:='COUNTRY';


f_stringgrid_to_populate.Cols[0].Add(FormatDatetime('dd-mm-yyyy hh:mm:ss', Now));
f_stringgrid_to_populate.Cols[1].Add(f_name);
f_stringgrid_to_populate.Cols[2].Add('58 RED ROAD');
f_stringgrid_to_populate.Cols[3].Add('ENGLAND');
f_stringgrid_to_populate.Cols[3].Add('UK');



end
);

{eliminate thread counter from global variable "thread_activ"}
 EnterCriticalSection(CriticalSection);
  try
{decrement variable from main unit1}
dec(unit1.thread_activ);
finally
 LeaveCriticalSection(CriticalSection);
 end;

end;

(*
procedure TForm1.Button1Click(Sender: TObject);
begin
TThread_populate_stringgrid.Create('Andrei',form1.StringGrid1);
TThread_populate_stringgrid.Create('Matei',form1.StringGrid1);
TThread_populate_stringgrid.Create('Iulia',form1.StringGrid1);
TThread_populate_stringgrid.Create('Petru',form1.StringGrid1);
TThread_populate_stringgrid.Create('Gheorghe',form1.StringGrid1);
TThread_populate_stringgrid.Create('Tudor',form1.StringGrid1);
TThread_populate_stringgrid.Create('Cineva',form1.StringGrid1);
TThread_populate_stringgrid.Create('Altcine',form1.StringGrid1);
end;

*)

(*
procedure TForm1.GridDrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
var
  S: string;
  RectForText: TRect;
begin
  // Check for your cell here (in this case the cell in column 4 and row 2 will be colored)
  //if (ACol = 1) and (ARow = 1) then
  if ((ACol = 1) and (ARow>0))  then
  begin
    S := form1.StringGrid1.Cells[ACol, ARow];
    if (s='Andrei') then
      begin
    // Fill rectangle with colour
    //form1.StringGrid1.Canvas.Brush.Color := clBlack;
    form1.StringGrid1.Canvas.FillRect(Rect);
    // Next, draw the text in the rectangle
    form1.StringGrid1.Canvas.Font.Color := clGreen;
    RectForText := Rect;
    // Make the rectangle where the text will be displayed a bit smaller than the cell
    // so the text is not "glued" to the grid lines
    InflateRect(RectForText, -2, -2);
    // Edit: using TextRect instead of TextOut to prevent overflowing of text
    form1.StringGrid1.Canvas.TextRect(RectForText, S);
      end;
  end;

   // if (ACol = 2) and (ARow = 1) then
     if ((ACol = 2)and (ARow>0)) then
  begin

    S := form1.StringGrid1.Cells[ACol, ARow];
    if (s='58 RED ROAD') then
    begin

    // Fill rectangle with colour
    //form1.StringGrid1.Canvas.Brush.Color := clwhite;
    form1.StringGrid1.Canvas.FillRect(Rect);
    // Next, draw the text in the rectangle
    form1.StringGrid1.Canvas.Font.Color := clRed;
    RectForText := Rect;
    // Make the rectangle where the text will be displayed a bit smaller than the cell
    // so the text is not "glued" to the grid lines
    InflateRect(RectForText, -2, -2);
    // Edit: using TextRect instead of TextOut to prevent overflowing of text
    form1.StringGrid1.Canvas.TextRect(RectForText, S);
    end
    else
    begin
     // Fill rectangle with colour
    //form1.StringGrid1.Canvas.Brush.Color := clwhite;
    form1.StringGrid1.Canvas.FillRect(Rect);
    // Next, draw the text in the rectangle
    form1.StringGrid1.Canvas.Font.Color := clBlue;
    RectForText := Rect;
    // Make the rectangle where the text will be displayed a bit smaller than the cell
    // so the text is not "glued" to the grid lines
    InflateRect(RectForText, -2, -2);
    // Edit: using TextRect instead of TextOut to prevent overflowing of text
    form1.StringGrid1.Canvas.TextRect(RectForText, S);
    end;
  end;


     //if (ACol = 3) and (ARow = 1) then
     if ((ACol = 3)and (ARow>0)) then
  begin
    S := form1.StringGrid1.Cells[ACol, ARow];
    if s='Altcine' then
    begin
    // Fill rectangle with colour
    //form1.StringGrid1.Canvas.Brush.Color := clwhite;
    form1.StringGrid1.Canvas.FillRect(Rect);
    // Next, draw the text in the rectangle
    form1.StringGrid1.Canvas.Font.Color := clYellow;
    RectForText := Rect;
    // Make the rectangle where the text will be displayed a bit smaller than the cell
    // so the text is not "glued" to the grid lines
    InflateRect(RectForText, -2, -2);
    // Edit: using TextRect instead of TextOut to prevent overflowing of text
    form1.StringGrid1.Canvas.TextRect(RectForText, S);
    end;
  end;

 *)



end.

Я надеюсь, что это помогает другим.Хорошего дня!

...