Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi-绘制文本,使其在重新绘制图像后不会消失_Delphi_Canvas_Delphi 7_Paint - Fatal编程技术网

Delphi-绘制文本,使其在重新绘制图像后不会消失

Delphi-绘制文本,使其在重新绘制图像后不会消失,delphi,canvas,delphi-7,paint,Delphi,Canvas,Delphi 7,Paint,我应该如何在画布上绘制文本,以使文本在重新绘制/更新/刷新后不会消失,而不需要一次又一次地重新绘制?就像它是作为图像绘制的,而不是临时绘制的。你不能。绘画只在屏幕上显示一次图像;如果希望它持久化,则每次操作系统请求时都必须重新绘制它。如果您谈论的是TPaintBox控件或类似控件,则没有可绘制的持久画布。系统根本不是这样设计的,VCL控件反映了底层的Windows框架 通常的做法如下: 首先绘制屏幕外位图 当系统要求重新绘制时,将屏幕外位图绘制到屏幕画布上 有多种原因可能导致您采用这种方法。通常

我应该如何在画布上绘制文本,以使文本在重新绘制/更新/刷新后不会消失,而不需要一次又一次地重新绘制?就像它是作为图像绘制的,而不是临时绘制的。

你不能。绘画只在屏幕上显示一次图像;如果希望它持久化,则每次操作系统请求时都必须重新绘制它。

如果您谈论的是
TPaintBox
控件或类似控件,则没有可绘制的持久画布。系统根本不是这样设计的,VCL控件反映了底层的Windows框架

通常的做法如下:

  • 首先绘制屏幕外位图
  • 当系统要求重新绘制时,将屏幕外位图绘制到屏幕画布上

  • 有多种原因可能导致您采用这种方法。通常,性能是一个因素。绘制和缓存图像可能会很昂贵,这会有所帮助。有时,绘制所需的信息可能是暂时的,缓存输出也可能是一种解决方案。

    使用TLabel(或某些衍生工具)并将其放置在画布上。TLabel将在必要时重新绘制自身。

    您只需要在系统要求时绘制。关于这个主题有两件事需要知道

    缓存

    您还可以实现自己的缓存系统。当使用多个层时,这可能会变得有点棘手。您可能有一个预计将以高速率变化的特定区域。然后背景大概不会被改变,除非它被调整了大小,或者颜色改变了,等等,比如一根针在某张照片上移动。只需在背景中保留两个不同的图像对象,并将它们组合在一起,确保顶部至少有一个是透明的

    您还可以使用
    Invalidate
    命令告诉Windows控件的缓存何时失效(下一主题…)。这将告诉Windows,您的控件中的某些内容已更改到需要重新绘制所有内容的程度。然后,Windows将通过调用
    Paint
    过程来决定何时准备好通知控件重新绘制

    系统油漆

    正如David在回答中提到的,如果您使用的是控件,那么当系统要求您重新绘制背景时,您应该重新绘制背景。这是通过从
    tgraphic control
    TCustomControl
    (以及其他一些)继承
    Paint
    过程来实现的。每次系统说需要刷新控件的内容时,都会调用此过程。这是系统告诉您缓存何时失效的方式

    procedure Paint; override;
    ...
    procedure TMyCustomControl.Paint;
    begin
      DoSomeDrawingOnCanvas;
    end;
    
    另一方面,您可以随时告诉Windows您希望它调用此
    Paint
    过程

    procedure TMyCustomControl.SetWidth(const Value: Integer);
    begin
      if Value <> FWidth then begin //Just a common check for performance reasons
        FWidth:= Value;
        Invalidate; //This tells Windows that you want to repaint your control
      end;
    end;
    
    过程TMyCustomControl.SetWidth(常量值:整数);
    开始
    如果值为FWidth,则开始//只是出于性能原因的一个常见检查
    FWidth:=值;
    使无效//这会告诉Windows您要重新绘制控件
    结束;
    结束;
    
    这取决于要绘制的画布。如果您使用的是自定义控件,那么只有一种方法。但是,如果您使用的是表单画布之类的东西,那么情况就不同了。Asker指的是将文本绘制到TCanvas。他们使用画布而不是标签来绘制文本肯定有一个可行的原因。