Delphi stringgrid TAdvsTringgrid 函数禁用和重新启用鼠标点击

Delphi stringgrid TAdvsTringgrid function to disable and reenable mouse clicks

是否有 Delphi 函数来启用或禁用 stringgrid 的鼠标点击?

我正在使用名为 Tadvstringgrid 的 stringgrid 派生,它允许根据内容为单元格着色

我需要在使用来自不同线程的数据填充控件时防止在 stringgrid 中单击鼠标。

仅仅禁用控件是不够的。如果我点击随机单元格,信息就会被搞砸,这意味着一些字符串被放置在我点击的最后一个单元格中。

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.

谢谢!

这是适合我的解决方案:

-在主窗体中放置一个 "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 组件,请将此代码更改为 "if Ctrl is TAdvstringgrid"。

如果您使用 Stringgrid,请将其更改为 "if 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.

我希望这对其他人有所帮助。祝你有美好的一天!