如何根据特定条件更改TStringGrid单元格中文本的颜色?
我正在使用TStringGrid在表单上显示月度日历视图,并且我将TStringGrid填充为某些行和列中每月的几天,一周中的几天作为列标题。我还在TStringGrid中填充了基于数据库中条目的某些日期的作业工作单。所以我使用DrawCell事件来显示TStringGrid中的内容。某些工作是经常性的工作,其他工作是一次性的。我希望重复的工作以一种颜色显示,而另一种颜色则显示在另一种颜色中。
这是否可行,和/或我应该使用其他组件来完成此任务?我假设在同一个单元格中不可能有两种不同的文本颜色。
type
TCalendarView2 = class(TForm)
CalViewStringGrid: TStringGrid;
NextBtn: TButton;
PrevBtn: TButton;
MonthLabel1: TLabel;
CloseBtn: TButton;
procedure OnShow(Sender: TObject);
procedure CalViewStringGridDrawCell(Sender: TObject; ACol, ARow: Integer;
Rect: TRect; State: TGridDrawState);
procedure NextBtnClick(Sender: TObject);
procedure PrevBtnClick(Sender: TObject);
procedure CloseBtnClick(Sender: TObject);
private
{ Private declarations }
FDateTime: TDateTime;
FDay: Word;
EndDate, StartDay: TDateTime; // selected date so we know what month the calendar is for
iNumDays, iDay: Integer; // Holds the number of days for a given month
procedure FillWithWorkOrders;
procedure UpdateRowHeights;
public
{ Public declarations }
MyDate : TDateTime;
end;
var
CalendarView2: TCalendarView2;
implementation
{$R *.dfm}
uses POEData;
procedure TCalendarView2.OnShow(Sender: TObject);
var
wYear, wMonth: Word;
begin
FDateTime := Date;
// Extract the month, day and year for the current date
DecodeDate (FDateTime, wYear, wMonth, FDay);
MonthLabel1.Caption := FormatSettings.LongMonthNames[wMonth] + ' ' + IntToStr(wYear);
FillWithWorkOrders;
end;
procedure TCalendarView2.CloseBtnClick(Sender: TObject);
begin
CalendarView2.Close;
end;
procedure TCalendarView2.CalViewStringGridDrawCell(Sender: TObject; ACol,
ARow: Integer; Rect: TRect; State: TGridDrawState);
var
s, ds, sDay, WorkOrder, WorkOrders: string;
dd, idx: integer;
dtDate: TDateTime;
SerType, WoNum, ETips: string;
bIsToday: boolean;
begin
s := CalViewStringGrid.Cells[ACol, ARow];
Inc(Rect.Left, 2);
Inc(Rect.Top, 2);
if (gdFixed in State) then
begin
CalViewStringGrid.Canvas.Brush.Color := CalViewStringGrid.FixedColor;
CalViewStringGrid.Canvas.Font.Color := CalViewStringGrid.Font.Color;
CalViewStringGrid.Canvas.FillRect(Rect);
CalViewStringGrid.Canvas.TextRect(Rect, Rect.Left, Rect.Top, s);
Exit;
end;
idx := Pos(#10, s);
if idx <> 0 then
begin
sDay := Copy(s, 1, idx-1);
WorkOrders := Copy(s, idx+1, MaxInt);
end else
begin
ds := s;
WorkOrders := '';
end;
if sDay <> '' then
begin
dd := StrToIntDef(sDay, 0);
dtDate := Date;
bIsToday := (MonthOf(dtDate) = MonthOf(FDateTime)) and (DayOf(dtDate) = dd);
end else begin
bIsToday := False;
end;
if bIsToday then
begin
CalViewStringGrid.Canvas.Brush.Color := clSkyBlue;
CalViewStringGrid.Canvas.Font.Color := clBlue;
end;
begin
CalViewStringGrid.Canvas.Brush.Color := CalViewStringGrid.Color;
CalViewStringGrid.Canvas.Font.Color := CalViewStringGrid.Font.Color;
end;
CalViewStringGrid.Canvas.FillRect(Rect);
CalViewStringGrid.Canvas.TextRect(Rect, Rect.Left, Rect.Top, sDay);
if (WorkOrders = '') then Exit;
Inc(Rect.Top, CalViewStringGrid.Canvas.TextHeight(sDay) + 2);
repeat
idx := Pos(#10, WorkOrders);
if idx <> 0 then
begin
WorkOrder := Copy(WorkOrders, 1, idx-1);
WorkOrders := Copy(WorkOrders, idx+1, MaxInt);
end else
begin
WorkOrder := WorkOrders;
WorkOrders := '';
end;
s := WorkOrder;
idx := Pos('-', s);
ETips := Copy(s, 1, idx-1);
s := Copy(s, idx+1, MaxInt);
idx := Pos('-', s);
SerType := Copy(s, 1, idx-1);
s := Copy(s, idx+1, MaxInt);
WoNum := s;
if bIsToday then
begin
CalViewStringGrid.Canvas.Brush.Color := clSkyBlue;
//CalViewStringGrid.Font.Color := clBlue;
end
else if SerType = 'R' then
begin
CalViewStringGrid.Canvas.Font.Color := clRed;
end
else if SerType = 'P' then
begin
CalViewStringGrid.Canvas.Font.Color := clBlue;
end
else if SerType = 'S' then
begin
CalViewStringGrid.Canvas.Font.Color := clGreen;
end
else if SerType = 'N' then
begin
CalViewStringGrid.Canvas.Font.Color := clBlack;
end;
begin
CalViewStringGrid.Canvas.Font.Color := CalViewStringGrid.Font.Color;
end;
CalViewStringGrid.Canvas.TextRect(Rect, Rect.Left, Rect.Top, WorkOrder);
Inc(Rect.Top, CalViewStringGrid.Canvas.TextHeight(WorkOrder) + 2);
until WorkOrders = '';
// CalViewStringGrid.Canvas.Font.Color := clBlack;
end;
procedure TCalendarView2.FillWithWorkOrders;
const
days: array[0..6] of String = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
var
X, Y, i, DateSW, RotType, PurType, SheType, SW, iNumDays: Integer;
dtTime, StartDay, EndDate: TDateTime;
SerType, WoNum, CoName, SCity, ETips, s: string;
wDay: Word;
WorkOrders: array[1..31] of String;
begin
RotType := 0;
PurType := 0;
SheType := 0;
SW := 0;
// This section displays the abbreviated day of the week in each cell in the first row,
// and clears out cell info just in case any data was left over from before
for i := 0 to 6 do
begin
CalViewStringGrid.Cells[i, 0] := days[i];
CalViewStringGrid.Cells[i, 1] := '';
CalViewStringGrid.Cells[i, 2] := '';
CalViewStringGrid.Cells[i, 3] := '';
CalViewStringGrid.Cells[i, 4] := '';
CalViewStringGrid.Cells[i, 5] := '';
CalViewStringGrid.Cells[i, 6] := '';
end;
// Gets the number of days for the current month
iNumDays := DaysInMonth(FDateTime);
// The next two lines initialize the variables the first time through
if DateSW = 0 then
begin
StartDay := FDateTime - FDay;
EndDate := EndOfTheMonth(FDateTime);
end;
DateSW := 1;
//Generate and open the ToBeSchedGrid Query
POE_Data.ToBeSchedGrid.Close;
POE_Data.ToBeSchedGrid.Sql.Clear;
POE_Data.ToBeSchedGrid.Sql.Add('SELECT DISTINCT D.WorkOrder, D.CustID, D.OpID, D.EnteredDate, D.EnteredTime, D.EstServiceDate, D.Status, D.EstBoxes, D.Truck, D.EstTips, D.ServiceDesc, D.Zone, D1.CompanyName, D1.Contact, D1.SContact1, D1.SPhone1, D1.SCity');
POE_Data.ToBeSchedGrid.Sql.Add('FROM ":Shred:WorkOrdersIn.DB" D, ":Shred:Customer.DB" D1');
POE_Data.ToBeSchedGrid.Sql.Add('WHERE (D.EstServiceDate > "' + DateToStr(StartDay) + '")');
POE_Data.ToBeSchedGrid.Sql.Add('AND (D.EstServiceDate <= "' + DateToStr(EndDate) + '")');
POE_Data.ToBeSchedGrid.Sql.Add('AND (D1.CustID = D.CustID)');
POE_Data.ToBeSchedGrid.Sql.Add('AND (D.Status <> "Cancelled")');
POE_Data.ToBeSchedGrid.Sql.Add('ORDER BY D.EstServiceDate');
// Save this Query to a text file for debugging purposes
POE_Data.ToBeSchedGrid.Sql.SaveToFile('c:\PolarQBE\WorkOrdersIn.txt');
POE_Data.ToBeSchedGrid.Open;
// populate each day's Work Orders
While NOT POE_Data.ToBeSchedGrid.EOF do
begin
dtTime := POE_Data.ToBeSchedGridEstServiceDate.AsDateTime;
SerType := POE_Data.ToBeSchedGridServiceDesc.AsString;
WoNum := POE_Data.ToBeSchedGridWorkOrder.AsString;
SCity := POE_Data.ToBeSchedGridSCity.AsString;
ETips := POE_Data.ToBeSchedGridEstTips.AsString;
if ETips = '' then ETips := '0';
CoName := POE_Data.ToBeSchedGridCompanyName.AsString;
if SerType = 'Route' then
Inc(RotType);
if SerType = 'Purge' then
Inc(PurType);
if SerType = 'Shred Event' then
Inc(SheType);
//wDay := DayOfTheMonth(FDateTime);
wDay := DayOfTheMonth(dtTime);
//WorkOrders[wDay] := WorkOrders[wDay] + ETips + '-' + Copy(CoName,1,11) + '-' + Copy(SCity,1,8) + '-' + Copy(SerType,1,1) + '-' + WoNum + #10;
WorkOrders[wDay] := WorkOrders[wDay] + ETips + '-' + Copy(SerType,1,1) + '-' + WoNum + #10;
POE_Data.ToBeSchedGrid.Next;
end;
// Initialize the Row and Column counters
Y := 1;
X := DayOfWeek(StartOfTheMonth(FDateTime)- 1);
if X > 6 then X := (X div 6) - 1;
for i := 1 to iNumDays do
begin
s := IntToStr(i);
if WorkOrders[i] <> '' then begin
s := s + #10 + WorkOrders[i];
end;
CalViewStringGrid.Cells[X, Y] := s;
// increment the column counter
Inc(X);
// if the column counter is greater than 6 reset back to 0.
if X > 6 then
begin
X := 0;
Inc(Y);
end;
end;
UpdateRowHeights;
end;
procedure TCalendarView2.UpdateRowHeights;
var
X, Y, TxtHeight: Integer;
MaxHeight: Integer;
R: TRect;
begin
// This next line seems to really control the height of the rows
CalViewStringGrid.Canvas.Font.Size := 8;
for Y := CalViewStringGrid.FixedRows to CalViewStringGrid.RowCount - 1 do
begin
MaxHeight := CalViewStringGrid.DefaultRowHeight - 4;
for X := CalViewStringGrid.FixedCols to CalViewStringGrid.ColCount - 1 do
begin
R := Rect(0, 0, CalViewStringGrid.ColWidths[X] - 4, 0);
TxtHeight := DrawText(CalViewStringGrid.Canvas.Handle,
PChar(CalViewStringGrid.Cells[X, Y]), -1, R, DT_WORDBREAK or DT_CALCRECT);
if TxtHeight > MaxHeight then
MaxHeight := TxtHeight;
end;
// 11/18/2015 - was = AGrid.RowHeights[Y] := MaxHeight + 4;
CalViewStringGrid.RowHeights[Y] := MaxHeight + 1;
end;
end;
答案 0 :(得分:0)
是的,可以在单个单元格中使用多种颜色。由于您已经使用TStringGrid.OnDrawCell
事件自行绘制单元格,因此只需将绘图逻辑扩展为包含每个作业的文本颜色。您需要做的就是在将作业的文本绘制到TStringGrid.Canvas.Font.Color
之前指定TStringGrid.Canvas
属性。您只需要为OnDrawCell
处理程序提供一种方法,以便知道给定作业何时重复出现,因此可以在绘制该作业的文本之前指定适当的颜色。
更新:尝试更类似的内容:
type
TCalViewForm = class(TForm)
CalViewStringGrid: TStringGrid;
procedure OnShow(Sender: TObject);
procedure CalViewStringGridDrawCell(Sender: TObject; ACol,
private
FDateTime: TDateTime;
FDay: Word;
procedure FillWithWorkOrders;
procedure UpdateRowHeights;
end;
...
procedure TCalViewForm.OnShow(Sender: TObject);
var
wYear, wMonth: Word;
begin
FDateTime := Date;
// Extract the month, day and year for the current date
DecodeDate (FDateTime, wYear, wMonth, FDay);
MonthLabel.Caption := FormatSettings.LongMonthNames[wMonth] + ' ' + IntToStr(wYear);
FillWithWorkOrders;
end;
procedure TCalViewForm.FillWithWorkOrders;
const
days: array[0..6] = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
var
X, Y, i, DateSW: Integer;
dtTime: TDateTime;
SerType, WoNum, CoName, SCity, ETips, s: string;
wDay: Word;
WorkOrders: array[1..31] of String;
begin
RotType := 0;
PurType := 0;
SheType := 0;
SW := 0;
// This section displays the abbreviated day of the week in each cell in the first row,
// and clears out cell info just in case any data was left over from before
for i := 0 to 6 do
begin
CalViewStringGrid.Cells[i, 0] := days[i];
CalViewStringGrid.Cells[i, 1] := '';
CalViewStringGrid.Cells[i, 2] := '';
CalViewStringGrid.Cells[i, 3] := '';
CalViewStringGrid.Cells[i, 4] := '';
CalViewStringGrid.Cells[i, 5] := '';
CalViewStringGrid.Cells[i, 6] := '';
end;
// Gets the number of days for the current month
iNumDays := DaysInMonth(FDateTime);
// The next two lines initialize the variables the first time through
if DateSW = 0 then
begin
StartDay := FDateTime - FDay;
EndDate := EndOfTheMonth(FDateTime);
end;
DateSW := 1;
//Generate and open the ToBeSchedGrid Query
POE_Data.ToBeSchedGrid.Close;
POE_Data.ToBeSchedGrid.Sql.Clear;
POE_Data.ToBeSchedGrid.Sql.Add('SELECT DISTINCT D.WorkOrder, D.CustID, D.OpID, D.EnteredDate, D.EnteredTime, D.EstServiceDate, D.Status, D.EstBoxes, D.Truck, D.EstTips, D.ServiceDesc, D.Zone, D1.CompanyName, D1.Contact, D1.SContact1, D1.SPhone1, D1.SCity');
POE_Data.ToBeSchedGrid.Sql.Add('FROM ":Shred:WorkOrdersIn.DB" D, ":Shred:Customer.DB" D1');
POE_Data.ToBeSchedGrid.Sql.Add('WHERE (D.EstServiceDate > "' + DateToStr(StartDay) + '")');
POE_Data.ToBeSchedGrid.Sql.Add('AND (D.EstServiceDate <= "' + DateToStr(EndDate) + '")');
POE_Data.ToBeSchedGrid.Sql.Add('AND (D1.CustID = D.CustID)');
POE_Data.ToBeSchedGrid.Sql.Add('AND (D.Status <> "Cancelled")');
POE_Data.ToBeSchedGrid.Sql.Add('ORDER BY D.EstServiceDate');
// Save this Query to a text file for debugging purposes
POE_Data.ToBeSchedGrid.Sql.SaveToFile('c:\PolarQBE\WorkOrdersIn.txt');
POE_Data.ToBeSchedGrid.Open;
// populate each day's Work Orders
While NOT POE_Data.ToBeSchedGrid.EOF do
begin
dtTime := POE_Data.ToBeSchedGridEstServiceDate.AsDateTime;
SerType := POE_Data.ToBeSchedGridServiceDesc.AsString;
WoNum := POE_Data.ToBeSchedGridWorkOrder.AsString;
SCity := POE_Data.ToBeSchedGridSCity.AsString;
ETips := POE_Data.ToBeSchedGridEstTips.AsString;
if ETips = '' then ETips := '0';
CoName := POE_Data.ToBeSchedGridCompanyName.AsString;
if SerType = 'Route' then
Inc(RotType);
if SerType = 'Purge' then
Inc(PurType);
if SerType = 'Shred Event' then
Inc(SheType);
wDay := DayOfTheMonth(dtTime);
//WorkOrders[wDay] := WorkOrders[wDay] + ETips + '-' + Copy(CoName,1,11) + '-' + Copy(SCity,1,8) + '-' + Copy(SerType,1,1) + '-' + WoNum + #10;
WorkOrders[wDay] := WorkOrders[wDay] + ETips + '-' + Copy(SerType,1,1) + '-' + WoNum + #10;
POE_Data.ToBeSchedGrid.Next;
end;
// Initialize the Row and Column counters
Y := 1;
X := DayOfWeek(StartOfTheMonth(FDateTime)- 1);
if X > 6 then X := (X div 6) - 1;
for i := 1 to iNumDays do
begin
s := IntToStr(i);
if WorkOrders[i] <> '' then begin
s := s + #10 + WorkOrders[i];
end;
CalViewStringGrid.Cells[X, Y] := s;
// increment the column counter
Inc(X);
// if the column counter is greater than 6 reset back to 0.
if X > 6 then
begin
X := 0;
Inc(Y);
end;
end;
UpdateRowHeights;
end;
procedure TCalViewForm.CalViewStringGridDrawCell(Sender: TObject; ACol,
ARow: Integer; Rect: TRect; State: TGridDrawState);
var
s, sDay, WorkOrder, WorkOrders: string;
dd, idx: integer;
dtDate: TDateTime;
SerType, WoNum, ETips: string;
bIsToday: boolean;
begin
s := CalViewStringGrid.Cells[ACol, ARow];
Inc(Rect.Left, 2);
Inc(Rect.Top, 2);
if (gdFixed in State) then
begin
CalViewStringGrid.Canvas.Brush.Color := CalViewStringGrid.FixedColor;
CalViewStringGrid.Canvas.Font.Color := CalViewStringGrid.Font.Color;
CalViewStringGrid.Canvas.FillRect(Rect);
CalViewStringGrid.Canvas.TextRect(Rect, Rect.Left, Rect.Top, s);
Exit;
end;
idx := Pos(#10, s);
if idx <> 0 then
begin
sDay := Copy(s, 1, idx-1);
WorkOrders := Copy(s, idx+1, MaxInt);
end else
begin
sDay := s;
WorkOrders := '';
end;
if sDay <> '' then
begin
dd := StrToIntDef(sDay, 0);
dtDate := Date;
bIsToday := (MonthOf(dtDate) = MonthOf(FDateTime)) and (DayOf(dtDate) = dd);
end else begin
bIsToday := False;
end;
if bIsToday then
begin
CalViewStringGrid.Canvas.Brush.Color := clSkyBlue;
CalViewStringGrid.Canvas.Font.Color := clBlue;
end
begin
CalViewStringGrid.Canvas.Brush.Color := CalViewStringGrid.Color;
CalViewStringGrid.Canvas.Font.Color := CalViewStringGrid.Font.Color;
end;
CalViewStringGrid.Canvas.FillRect(Rect);
CalViewStringGrid.Canvas.TextRect(Rect, Rect.Left, Rect.Top, sDay);
if (WorkOrders = '') then Exit;
Inc(Rect.Top, CalViewStringGrid.Canvas.TextHeight(sDay) + 2);
repeat
idx := Pos(#10, WorkOrders);
if idx <> 0 then
begin
WorkOrder := Copy(WorkOrders, 1, idx-1);
WorkOrders := Copy(WorkOrders, idx+1, MaxInt);
end else
begin
WorkOrder := WorkOrders;
WorkOrders := '';
end;
s := WorkOrder;
idx := Pos('-', s);
ETips := Copy(s, 1, idx-1);
s := Copy(s, idx+1, MaxInt);
idx := Pos('-', s);
SerType := Copy(s, 1, idx-1);
s := Copy(s, idx+1, MaxInt);
WoNum := s;
if SerType = 'R' then
begin
CalViewStringGrid.Canvas.Font.Color := clRed;
end
else if SerType = 'P' then
begin
CalViewStringGrid.Canvas.Font.Color := clBlue;
end
else if SerType = 'S' then
begin
CalViewStringGrid.Canvas.Font.Color := clGreen;
end
else if bIsToday then
begin
CalViewStringGrid.Canvas.Font.Color := clBlue;
end
begin
CalViewStringGrid.Canvas.Font.Color := CalViewStringGrid.Font.Color;
end;
CalViewStringGrid.Canvas.TextRect(Rect, Rect.Left, Rect.Top, WorkOrder);
Inc(Rect.Top, CalViewStringGrid.Canvas.TextHeight(WorkOrder) + 2);
until WorkOrders = '';
end;
procedure TCalViewForm.UpdateRowHeights;
var
X, Y, TxtHeight: Integer;
MaxHeight: Integer;
R: TRect;
begin
// This next line seems to really control the height of the rows
CalViewStringGrid.Canvas.Font.Size := 9;
for Y := CalViewStringGrid.FixedRows to CalViewStringGrid.RowCount - 1 do
begin
MaxHeight := CalViewStringGrid.DefaultRowHeight - 4;
for X := CalViewStringGrid.FixedCols to CalViewStringGrid.ColCount - 1 do
begin
R := Rect(0, 0, CalViewStringGrid.ColWidths[X] - 4, 0);
TxtHeight := DrawText(CalViewStringGrid.Canvas.Handle,
PChar(CalViewStringGrid.Cells[X, Y]), -1, R, DT_WORDBREAK or DT_CALCRECT);
if TxtHeight > MaxHeight then
MaxHeight := TxtHeight;
end;
// 11/18/2015 - was = AGrid.RowHeights[Y] := MaxHeight + 4;
CalViewStringGrid.RowHeights[Y] := MaxHeight + 1;
end;
end;