ShowMessage 出现在表单后面-Delphi

ShowMessage is appearing behind form-Delphi

我的程序在代码中有一个 MessageBox。我第一次 运行 它似乎没有出现,程序冻结了。我花了几个小时阅读论坛,并且尝试了所有方法。我在 MessageBox 之前最小化了我的表单,对话框似乎出现在表单后面。我尝试了这段代码,但没有任何效果。

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

P.S.: 我在程序中有另一个表格,它在那个表格上工作正常,我确保它们都有相同的设置

编辑:

我刚刚意识到是我的 StringGrid 的 OnCellDraw 功能导致消息被隐藏。我设法通过使 StringGrid 不可见然后再次可见来使其工作。 OnDrawCell 有一个愚蠢的代码,它使用彩色单元格显示一年中的预订天数。我想知道是否有更好的方法可以在不使 stringgrid 不可见的情况下显示消息。没有 运行 OnDrawCell,MessageBox 也可以工作

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;```


问题是您使用 OnDrawCell 处理程序中的数据填充字符串网格。

你只应该在这个方法中绘制 canvas;你不应该触摸数据。

当网格需要重新绘制时,调用其 OnDrawCell 处理程序。您在网格中绘制(没关系),但您也更改了数据。正因为如此,网格意识到它需要再次重绘自己(因为它的数据已经改变!),所以它的 OnDrawCell 处理程序被调用。您在网格中绘制(没关系),但您也更改了数据。正因为如此,网格意识到它需要再次重绘自己(因为它的数据已经改变!),所以它的 OnDrawCell 处理程序被调用,...

好吧,我就到此为止吧。

显然,这会导致无限次的重绘,这将使您的应用程序忙于重绘网格。

您可以很容易地看到这种现象。只需创建一个新的 VCL 应用程序,在主窗体上放置一个 TStringGrid 并添加

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

您会在 (3, 3) 单元格中看到一个不断更新的随机数。

忙于绘制网格会产生很多后果。例如,除了您发现的消息框异常之外,您可能会看到您的进程用完了 CPU 的单个“线程”(如果您有四核 HT CPU,比如说,您将完全使用一个线程,或 1/8 = 12.5% CPU).