user13898928
user13898928

Reputation:

ShowMessage is appearing behind form-Delphi

My program has got a MessageBox in the code. the first time I ran it it appeared it wasn't showing up and the program froze. I have spent hours reading through forums and I have tried everything. I minimized my form just before the MessageBox and it appears the dialogue appears behind the form. I tried this piece of code but nothing worked.

Application.NormalizeTopMosts; MessageBox(Handle,'Test','A message test',MB_SYSTEMMODAL or MB_SETFOREGROUND or MB_TOPMOST or MB_ICONHAND);

P.S.: I have another form in the program and it works fine on that form and I have ensured they both have the same settings

Edit:

I just realized that it was the OnCellDraw feature of my StringGrid that caused the message to be hidden. I managed to get it to work by making the StringGrid invisible and then visible again. The OnDrawCell has the foolowing code which displays booked days of the year using cells coloured in. I would like to know if there is a better way to make the message appear without making the stringgrid invisible. Without running the OnDrawCell, the MessageBox also works

procedure TfrmClient.stgYearPlanDrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
var
  k, iMonth, iDay, iStart, iEnd, iSubtract : Integer;
begin
    case iYear of
      2020 :  begin
                iStart := 1;
                iEnd:= 12;
                iSubtract := 0;
              end;
      2021  : begin
                iStart := 13;
                iEnd:= 24;
                iSubtract := 12;
              end;
      2022  : begin
                iStart := 25;
                iEnd := 36;
                iSubtract := 24;
              end;
    end;
    for k := 1 to 31 do
      stgYearPlan.Cells[k,0] := IntToStr(k);

    for k := 1 to 12 do
      stgYearPlan.Cells[0,k] := ShortMonthNames[k];

    for iMonth := iStart to iEnd do
    begin
    for iDay := 1 to 31 do
     begin
          if ar2Booking[iDay,iMonth] = 'Y' then
          begin
            if (ACol = iDay) and (ARow = (iMonth-iSubtract)) then
            begin
              stgYearPlan.Canvas.Brush.Color := clBlack;
              stgYearPlan.Canvas.FillRect(Rect);
              stgYearPlan.Canvas.TextOut(Rect.Left,Rect.Top,stgYearPlan.Cells[ACol, ARow]);
            end;
          end;

          if ar2Booking[iDay,iMonth] = 'D' then
          begin
            if (ACol = iDay) and (ARow = (iMonth-iSubtract)) then
            begin
              stgYearPlan.Canvas.Brush.Color := clSilver;
              stgYearPlan.Canvas.FillRect(Rect);
              stgYearPlan.Canvas.TextOut(Rect.Left+2,Rect.Top+2,stgYearPlan.Cells[ACol, ARow]);
            end;
          end;
     end;
     end;
end;```


Upvotes: 0

Views: 1017

Answers (1)

Andreas Rejbrand
Andreas Rejbrand

Reputation: 109158

The problem is that you populate the string grid with data in its OnDrawCell handler.

You are only supposed to draw on the canvas in this method; you shouldn't touch the data.

When the grid needs to repaint, its OnDrawCell handler is called. You draw in the grid (that's OK), but you also change the data. Because of this, the grid realises that it needs to redraw itself again (because its data has changed!), so its OnDrawCell handler is called. You draw in the grid (that's OK), but you also change the data. Because of this, the grid realises that it needs to redraw itself again (because its data has changed!), so its OnDrawCell handler is called, ...

Well, I'll stop there.

Clearly, this causes an infinite sequence of repaints which will make your application busy repainting the grid.

You can see this phenomenon in action rather easily. Just create a new VCL application, drop a TStringGrid on the main form and add

procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
begin
  StringGrid1.Cells[3, 3] := Random(100).ToString;
end;

You'll see a constantly updating random number in the (3, 3) cell.

Being busy with painting the grid will have many consequences. For instance, in addition to the message box anomaly you discovered, you'll likely see your process maxing out a single "thread" of the CPU (if you have a quad-core HT CPU, say, you will use one thread fully, or 1/8 = 12.5% CPU).

Upvotes: 3

Related Questions