0

How can I change the color of text in a TStringGrid cell depending on certain conditions?

I am using TStringGrid to display a monthly calendar view on a form and I'm populating the TStringGrid with days of the month in certain rows and columns, with days of the week as column headings. I'm also populating the TStringGrid with job work orders for certain dates that are based on entries in a database. So I'm using the DrawCell event to display the content in the TStringGrid. Certain jobs are recurring jobs and other jobs are one offs. I'd like the recurring jobs to appear in one color and the one offs in another.

Is this possible, and/or should I be using a different component to accomplish this task? I assume it's not possible to have two different text colors in the same cell.

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;
Hackbrew
  • 349
  • 1
  • 10
  • 23

1 Answers1

0

Yes, it is possible to use multiple colors in a single cell. Since you are already using the TStringGrid.OnDrawCell event to draw the cells yourself, simply extend your drawing logic to include per-job text colors. All you have to do is assign the TStringGrid.Canvas.Font.Color property before drawing a job's text onto the TStringGrid.Canvas. You just need to expose a way for your OnDrawCell handler to know when a given job is recurring or not, so it can assign the appropriate color before drawing that job's text.

Update: Try something more like this instead:

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;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • I guess I'm not understanding exactly when the OnDrawCell is executing, because I added the code to handle the job type and to change the text color, but it's not working. – Hackbrew Nov 19 '15 at 19:51
  • It is executed every time the grid needs to be repainted, such as in response to a `WM_PAINT` message. If the coloring is not working, you are doing something wrong. Please edit your question to show your actual code. – Remy Lebeau Nov 19 '15 at 20:45
  • I edited my original question by pasting in the code and it states that "This edit will be visible only to you until it is peer reviewed.". – Hackbrew Nov 19 '15 at 21:18
  • You accidentally pasted into the answer instead of the question, I've moved it into the question. – sheilak Nov 19 '15 at 21:25
  • @Hackbrew: you are setting the Grid's `Canvas.Font.Color` property inside your `FillWithWorkOrders()` function while looping through the DB records. It does not belong there. It needs to be inside your `OnDrawCell` handler instead. Since you are including each record's `SerType` value in your cell text, you can have your `OnDrawCell` handler split the current cell's text into its individual records, and for each one extract its `SerType` value, assign the `Canvas.Font.Color` accordingly, and then draw the record onto the `Canvas` where needed. – Remy Lebeau Nov 19 '15 at 23:20
  • @Hackbrew: you are relying on the Grid's default drawing of each cell's text, and that is not going to work if you want to customize the colors of each DB record within a cell. You have to draw each record manually so you can customize each record's drawing as needed. – Remy Lebeau Nov 19 '15 at 23:22
  • @Hackbrew: and BTW, you need to get rid of the `ShowMessage()` in your `OnDrawCell` handler, it does not belong there. Also, when you add the new logic to your `OnDrawCell` handler to draw the individual DB records with colors, make sure you draw your SkyBlue background first for the cell of the current date, otherwise it will wipe out all of your text drawing. – Remy Lebeau Nov 19 '15 at 23:27
  • So should I step through my DB records in the FillWithWorkOrders() function, or should that also be moved into my OnDrawCell handler? I'm a little confused now as to what I should have in my FillWithWorkOrders() function and what should be in my OnDrawCell handler. Also, should I set the StringGrid's DefaultDrawing property to False? – Hackbrew Nov 20 '15 at 13:28
  • Sorry @Remy Lebeau, I didn't see the updated code you embedded. I loaded the code, but when I try to execute it I get a [dcc32 Error] PolarCalendarTest.dpr(13): E2003 Undeclared identifier: 'CalViewForm'. For some reason it's not recognizing my form. Any ideas why? – Hackbrew Nov 20 '15 at 16:58
  • @Remy Lebeau: Ok, created a new form and got it running, but all the jobs are posted under 1 day, which is today (11/20/2015). – Hackbrew Nov 20 '15 at 17:19
  • @Remy Lebeau: I changed wDay := DayOfTheMonth(FDateTime) to wDay := DayOfTheMonth(dtTime) and now they post on their proper days, but they are all in a black font. What do I need to change to get them to appear in the different colors? – Hackbrew Nov 20 '15 at 18:27
  • @Remy Lebeau: Update: I changed CalViewStringGrid.Canvas. Font.Color := clRed to CalViewStringGrid.Font.Color := clRed, and I changed the other SerType tests to the proper colors and now they appear in different colors, but they blink like they are being refreshed many times. Also, If a day doesn't have a job, its day number does not appear in the calendar and there some weird black grid lines that appear starting in half way in column 5 and starting half way in row 4. – Hackbrew Nov 20 '15 at 18:40
  • @Hackbrew: DO NOT perform your DB operations in your `OnDrawCell` handler! Drawing events are only for painting, not for data management. Prepare the data in `FillWithWorkOrders()`, draw the data in `OnDrawCell`. There is no reference to a `CalViewForm` object in the code I showed (or in yours, for that matter). As for the font color, in the `OnDrawCell` handler, you must set the `TStringGrid.Canvas.Font.Color` instead of the `TStringGrid.Font.Color`. Changing the `TStringGrid.Font` invalidates the `TStringGrid` window, triggering a repaint. Endless repaints cause your flickering issue... – Remy Lebeau Nov 20 '15 at 19:04
  • @Hackbrew: the missing number for days without work orders was a typo, I have fixed it. – Remy Lebeau Nov 20 '15 at 19:08
  • @Remy Lebeau: Most everything is working except for the font color. When I change them back to the {TStringGrid.Canvas.Font.Color} it doesn't flicker, but all the text is black. – Hackbrew Nov 20 '15 at 19:17
  • @Remy Lebeau: Also, what is causing the grid lines in the later rows and columns? – Hackbrew Nov 20 '15 at 19:21
  • @Hackbrew: Did you try stepping through the `OnDrawCell` code in the debugger to make sure it is parsing the `SerType` value correctly for each job? As for the grid lines, please edit your question to show a screenshot of what you are seeing. – Remy Lebeau Nov 20 '15 at 19:38
  • @Remy Lebeau: The font is still all black. When I step through the debugger it assigns the color properly, but the CalViewStringGrid.Font.Color is initially set to -16777208. which is passed to CalViewStringGrid.Canvas.Font.Color. Also, the missing number of days issue is back missing, even though I have made the change to wDay := DayOfTheMonth(dtTime). – Hackbrew Nov 20 '15 at 19:56
  • @Hackbrew: regarding the missing day numbers, the fix I did was to change `ds := s;` to `sDay := s;` when no jobs are present on the day. As for the color, I can't say what is happening. Only the `TStringGrid.Canvas.Font` is used during painting. `TStringGrid.Font` is assigned to `TStringGrid.Canvas.Font` before `OnDrawCell` is called. `-16777208` is `clWindowText`, which is indeed black by default. The only way the code I gave you would use that color is if each job's `SerType` is not being parsed correctly. Again, double-check your `SerType` handling. And yes, set `DefaultDrawing` to false. – Remy Lebeau Nov 20 '15 at 23:43
  • @Hackbrew: With all this custom drawing, you might consider switching to a `TDrawGrid` instead, and store your job data in a separate array. – Remy Lebeau Nov 20 '15 at 23:44
  • @Remy Lebeau: The SerType appears to be deciphered correctly because the colors are correct when I use TStringGrid.Canvas.Font.Color, even though I get the flickering. I'll play around with it a bit more before attempting TDrawGrid. I really appreciate all your help on this, as I've learned a lot already. – Hackbrew Nov 21 '15 at 00:21
  • @Hackbrew: You can't get flickering when your `OnDrawCell` handler assigns colors to `TStringGrid.Canvas.Font.Color`, only when assiging to `TStringGrid.Font.Color`. – Remy Lebeau Nov 21 '15 at 00:46
  • @Remy Lebeau: I think I have it. When I remove the line "CalViewStringGrid.Canvas.Font.Color := CalViewStringGrid.Font.Color" it appears to work without flickering. – Hackbrew Nov 23 '15 at 13:38
  • Thanks @Remy Lebeau for all your help! – Hackbrew Nov 23 '15 at 13:40