Delphi - 绘制到字符串网格中选定单元格的画布 - 可能吗?

发布于 2024-10-20 11:15:51 字数 1588 浏览 0 评论 0原文

我想在字符串网格中的单元格的画布上绘制。这将位于预加载到字符串网格中的图像之上。

我所得到的

目前,我不是在图像顶部绘制,而是加载第二个透明图像,然后在单元格顶部绘制。这是我使用的代码并且它有效。

procedure TfrmCavern.StringGridDrawCell(Sender: TObject; ACol, ARow: Integer;
                                    Rect: TRect; State: TGridDrawState);
var
  index : integer;
  I : integer;
begin
  // Calculate the corresponding linear index
  index := LinearIndexOf(ARow, ACol);
  //Draw image referenced to cell
  StringGrid.Canvas.StretchDraw(Rect, CellDetails[index].Images.Picture.Graphic);  

  //if player present draw corresponding player image
  for I := 0 to frmWelcome.NoofPlayers - 1 do
   begin
     if index = Players[I].pIndex then StringGrid.Canvas.StretchDraw(Rect,Players[I].UserImage.Picture.Graphic);
   end;
  end;
end;

该过程首先绘制引用单元格的图像。如果有“玩家”在场,它将把玩家的棋子画在上面。由于“玩家棋子”图像是透明的 .PNG 图像,因此下面的原始图像仍然可见。

我想要的

这种方法的缺点是,由于图像是恒定的,“玩家棋子”位于单元格内的设定位置。我希望能够根据选择的单元格在单元格内的不同位置绘制“玩家棋子”。我有大约 200 个单元格,所以我真的不想手动创建那么多具有不同位置的图像。

我尝试过

在drawcell过程中直接绘制到stringgrid的画布上,但这似乎引用了整个stringgrid而不是正在绘制的当前单元格。

StringGrid.Canvas.ellipse(10,10,50,50);

我已经看过了,但我似乎无法引用当前单元格的画布 - 我认为它不存在?

我尝试的下一件事是绘制临时图像,然后将图像绘制到单元格中。

TempImage.Canvas.Ellipse(10,10,50,50);
StringGrid.Canvas.StretchDraw(Rect, TempImage.Picture.Graphic);

这在一定程度上有效,它确实将图像绘制到单元格上,但是图像具有不透明的背景/画布,因此单元格是白色的,上面有圆圈,下面的图像不可见。我做了一些研究,但找不到使图像画布透明的方法。

我能想到的最后一件事是编写一个算法来定位当前单元格的左上角,然后从那里直接绘制到画布,但这可能会很麻烦,并且在重新绘制字符串网格时会产生问题。

有人能找到解决我的问题的方法吗?

提前致谢, 乔什

I want to draw on the canvas of a cell in a string grid. This is going to be on top of an image preloaded into the string grid.

What I've got

Currently instead of drawing on top of the image, I am loading a second transparent image and then painting on top of the cell. This is the code I use and it works.

procedure TfrmCavern.StringGridDrawCell(Sender: TObject; ACol, ARow: Integer;
                                    Rect: TRect; State: TGridDrawState);
var
  index : integer;
  I : integer;
begin
  // Calculate the corresponding linear index
  index := LinearIndexOf(ARow, ACol);
  //Draw image referenced to cell
  StringGrid.Canvas.StretchDraw(Rect, CellDetails[index].Images.Picture.Graphic);  

  //if player present draw corresponding player image
  for I := 0 to frmWelcome.NoofPlayers - 1 do
   begin
     if index = Players[I].pIndex then StringGrid.Canvas.StretchDraw(Rect,Players[I].UserImage.Picture.Graphic);
   end;
  end;
end;

The procedure first draws the image referenced to the cell. If there is a "player" present it will then draw the player piece on top. Because the "player piece" image is a transparent .PNG image the original image underneath is still visible.

What I want

The draw back of this method is that the "player piece" is in a set position within the cell due to the image being constant. I want to be able to draw the "player piece" in a different position within the cell depending on which cell is selected. I have around 200 cells so I dont really want to manually create that many images with different positions.

What I've tried

I've tried drawing directly to the canvas of the stringgrid within the drawcell procedure but that appeared to reference the entire stringgrid rather than the current cell that was being drawn.

StringGrid.Canvas.ellipse(10,10,50,50);

I've looked but I cant seem to be able to reference the canvas of the current cell - I presume it doesn't exist?

The next thing I tried was drawing to a temporary image and then drawing the image to the cell.

TempImage.Canvas.Ellipse(10,10,50,50);
StringGrid.Canvas.StretchDraw(Rect, TempImage.Picture.Graphic);

This worked to an extent, it did draw the image to the cell, however the image had an opaque background/canvas so the cell was white with the circle on it, the image beneath was not visible. I did a bit of research but couldn't find a way to make the canvas of the image transparent.

The last thing I can think of trying is to write an algorithm to locate the top left point of the current cell and then draw direct to the canvas from there, but that could be sloggy and create issues when redrawing the stringgrid.

Can anyone see a way around my issue?

Thanks in advance,
Josh

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

装纯掩盖桑 2024-10-27 11:15:51

OnDrawCell 的 Rect 参数指定特定单元格相对于网格客户端坐标系的边界。因此,您需要绘制位于该矩形内的坐标。在你的事件处理程序中尝试这样的事情:

StringGrid.Canvas.Pen.Color := clBlack;
StringGrid.Canvas.Brush.Style := bsClear;
StringGrid.Canvas.Ellipse(
  Rect.Left+5,
  Rect.Top+5,
  Rect.Left+15,
  Rect.Top+15
);

The Rect parameter to OnDrawCell specifies the bounds of the particular cell, relative to the grid's client coordinate system. So you need to draw to coordinates that lie within this rectangle. Try something like this in your event handler:

StringGrid.Canvas.Pen.Color := clBlack;
StringGrid.Canvas.Brush.Style := bsClear;
StringGrid.Canvas.Ellipse(
  Rect.Left+5,
  Rect.Top+5,
  Rect.Left+15,
  Rect.Top+15
);
要走就滚别墨迹 2024-10-27 11:15:51

只有一张画布,即控件的画布。每个单元格只是画布内的一个矩形。找到当前单元格在画布中的位置很简单。事实上,这就是 Rect 参数的用途。 Rect.Left 是单元格的 x 坐标,Rect.Top 是单元格的 y 坐标。

或者我误解了你的问题?

There is only one canvas, the control's canvas. Each cell is merely a rectangle inside this canvas. It is trivial to find the position of the current cell in the canvas. Indeed, this is what the Rect parameter is for. Rect.Left is the x coordinate of the cell, and Rect.Top is the y coordinate of the cell.

Or did I misinterpret your question?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文