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.
我希望这对其他人有所帮助。祝你有美好的一天!
是否有 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.
我希望这对其他人有所帮助。祝你有美好的一天!