Reputation:
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
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