【问题标题】:Delphi creating a paint event canvas issuesDelphi 创建绘制事件画布问题
【发布时间】:2016-01-27 03:10:27
【问题描述】:

当我查看TWinControl 时,CanvasclBtnFace 屏蔽,然后调用WM_PAINT。这会导致我不需要的不可避免的闪烁。此外,给定的画布允许在滚动条上绘图,从而在 WM_PAINT 事件后重新绘制滚动条并产生更多闪烁。

GetMetrics 和内部滚动条信息给出了真正的画布大小。如果我错了,请纠正我,但我知道HDC 是表单上的一个句柄,它有一个矩形画布可以打印。所以我在想:

  1. 如何创建一个具有较小宽度和高度的新 HDC 并且不移动左上角。如果可能的话,我想通过不使用WM_ERASEBKGND 消息来消除闪烁,并且不通过分配新大小的HDC 来打印滚动条,然后使用正确的HDC 设置Delphi 画布句柄。

  2. 使用我不知道是否应该使用的 Windows 位图并将 BitBlt() 副本的位图画布大小设置为 TWinControl(下)。

    DC := GetDC(0);
    MemBitmap := CreateCompatibleBitmap(DC, ClientRect.Right, ClientRect.Bottom);
    ReleaseDC(0, DC);
    MemDC := CreateCompatibleDC(0);
    OldBitmap := SelectObject(MemDC, MemBitmap);
    try
      DC := BeginPaint(Handle, PS);
      Perform(WM_ERASEBKGND, MemDC, MemDC);
      Message.DC := MemDC;
      WMPaint(Message);
      Message.DC := 0;
      BitBlt(DC, 0, 0, ClientRect.Right, ClientRect.Bottom, MemDC, 0, 0, SRCCOPY);
      EndPaint(Handle, PS);
    finally
      SelectObject(MemDC, OldBitmap);
      DeleteDC(MemDC);
      DeleteObject(MemBitmap);
    end;
    

我不知道在无闪烁结果中哪个选项更好,以及如何在 Delphi 中实现它。

【问题讨论】:

  • 所以您正在编写自定义 TWinControl 并且您显示的代码块是绘制方法?不如你把这个问题说清楚一点,这是一团糟。或者你是在画箱里画画吗?
  • 你想多了。如果您说的是真的,那么所有标准控件都会像您所描述的那样闪烁不良。那明显是错的。导致闪烁问题的原因可能在于您自己的绘图代码,而不是TWinControl 如何管理其Canvas。请显示您遇到问题的实际代码。
  • 我们需要minimal reproducible example 为您提供帮助

标签: delphi delphi-7


【解决方案1】:

...CanvasclBtnFace 屏蔽掉...

背景颜色可通过设置Brush.Color调整。

然后调用WM_PAINT。这会导致不可避免的闪烁...

这可以通过绕过WM_ERASEBKGND 消息来避免。

如何新建一个宽度和高度较小的HDC

这是不可能的。设备上下文没有大小。它仅受托管它的窗口的限制。

给定的画布允许在滚动条上绘图,从而在 WM_PAINT 事件之后重新绘制滚动条。

系统在WM_NCPAINT 中绘制原生滚动条。如果你可以在它们上面绘制,那么你就得到了整个窗口的设备上下文,而不是它的客户空间。

但总的来说,解决方案非常简单:不要超出窗口的客户区域。

作为提示:我建议您从 TCustomControl 而不是 TWinControl 派生控件,因为该类已经有一个可以绘制的画布,可以消除所有 WinAPI 代码。

【讨论】:

  • 是的 TCustomControl 后代,Remy Lebeau 我不知道从哪里真正开始,也不知道 API 调用,当我阅读来源或范围时,我不知道这意味着什么。 WM_ERASEBKGND 消息是我需要摆脱的!!!! NGLN。我可以使用标准的 RecreateWin,而且我的手柄坚如磐石,但正如我解释的那样,它闪烁得很厉害。事实上,我在 mousedown 和 keydown 上也使用了画布句柄,但不推荐它。您不能从绘制事件中创建的线程运行句柄。
  • 我仍然有两种设计选择,使用空白画布和复制或在重建之前将小区域涂黑。
  • 还有 'DC := GetDC(0);'使用 0 对我没有意义。
  • ' DC := GetDC(0); MemBitmap := CreateCompatibleBitmap(DC, ClientPoint.X, ClientPoint.Y);释放DC(0, DC); MemDC := CreateCompatibleDC(0); OldBitmap := SelectObject(MemDC, MemBitmap);试试 DC := BeginPaint(Handle, PS);画布.锁;试试 Canvas.Handle := MemDC;尝试油漆;最后 Canvas.Handle := 0;结尾;最后是 Canvas.Unlock;结尾; BitBlt(DC, 0, 0, ClientRect.Right, ClientRect.Bottom, MemDC, 0, 0, SRCCOPY); EndPaint(手柄,PS);最后选择对象(MemDC,OldBitmap);删除DC(MemDC); ..等'
  • GetDC(0) 获取桌面的设备上下文,即整个屏幕的绘画表面。难怪你在滚动条上作画。请编辑您的问题并包含更多信息:您到底想做什么,具体时间以及使用哪种控件?您是在绘制自定义组件,还是在现有控件的事件中进行绘制?您的代码缺少方法名称和签名,因此我们无法估计它何时运行。我们不应该估计,你应该更好地解释你想要什么以及你到底在做什么。请具体。我们无法说服您。
猜你喜欢
  • 2011-02-08
  • 1970-01-01
  • 2019-09-01
  • 2013-01-13
  • 1970-01-01
  • 1970-01-01
  • 2011-05-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多