delphi 使用GDI吧jpg图片绘制在groupbox中的问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了delphi 使用GDI吧jpg图片绘制在groupbox中的问题相关的知识,希望对你有一定的参考价值。

procedure TForm1.Button1Click(Sender: TObject);
var
g : IGpGraphics;
RedPen : IGpPen;
Img : IGpImage;
r : TGpRectF;
mybox:tpanel;
dc:hdc;
begin
mybox:=tpanel.Create(self);
mybox.Parent:=self;
mybox.SetBounds(10,10,480,480);
dc:=getdc(mybox.Handle);
g := NewGpGraphics(dc);
RedPen := NewGpPen(kcRed, 3.0);
g.SmoothingMode := smHighQuality;
Img := NewGpBitmap(ExtractFilePath(ParamStr(0)) + test.jpg');
r := GpRect(0.0, 0.0, 80, 80);
g.ScaleTransform(0.1, 0.1);
g.DrawImage(Img,150,150);
g.ResetTransform();
end;
以上是代码,编译没有报错,但是在运行过程中JPG图片只是闪了一下就没有了,不知道是为什么,望达人解惑
我的最终目的是动态排列N张JPG照片,但是照片都很大,至少都有3兆,大的有10兆,直接将照片放到image控件中是不可能的,只要放十来张就不能放了,占用资源太大了,所以现在想试试绘画上去的方法,但是绘画上去没有控件支持的话貌似是没有事件响应的,所以考虑用groupbox作为载体,将图片放在里面,如果有更好更方便的方法可以实现此功能也请说说

参考技术A 你这N张图片总不会一下子全部都显示在窗体上吧,一是电脑的资源有限,二是用户也看不过来啊!你还不如把图片存放在数据库中,一张一张的加载(显示),这又有什么不好呢?就电脑显示屏来说,如果不是特别需要(比如图片分析,公安才用的上的),几百K和几十M的图片显示效果是差别不大的.追问

之前是考虑过把裁剪过的图放在数据库中,中间要多两道工序,而且效率好像不高,而且少则几十张多则两百张,所以这个是最后不得已的方法了

追答

如果说图片不是由用户来决定的话,放在数据库中是一种最好的办法了

参考技术B 学Delphi的果然没几个靠谱的。
1、GroupBox是Windows标准控件,如果不重写它的消息循环,每次重画Windows都会用默认的灰色画刷覆盖GroupBox表面。另外如果你只是要承载图片,用CreateWindow创建一个普通窗口不行么,非得用GroupBox?
2、至于怎么做,一点不难,我都懒的写。真有兴趣的话,可以进一步追问,我可以告诉你。
参考技术C 可以考虑画到TPaintBox里面,这是个专门用来绘画的控件,把绘画代码写到OnPaint事件里,当有区域失效或调用Invalidate就可以重绘追问

目前正在尝试使用paintbox控件来实现这个功能,但是在如何让图片能够完美填充paintbox还有有问题,图片的宽高是用的图片像素,和控件的宽高完全不是一个计算方法的。。。

本回答被提问者采纳
参考技术D 写绘图的画,应该在OnPaint 事件中去写,这样才能避免窗体在重绘时,图象不会刷新掉。追问

groupbox没有这个事件的,否则我就不会找它的句柄了
不过我找了一下image好像有print事件,我会试一试

追答

此事件是在Form中的

向使用 GDI+ 绘制的图像添加文本

【中文标题】向使用 GDI+ 绘制的图像添加文本【英文标题】:Adding Text to Image Drawn with GDI+ 【发布时间】:2022-01-17 06:59:28 【问题描述】:

我正在使用计时器和图片框显示图像。这些图像似乎是相互叠加而不是显示一个,然后删除那个,然后加载另一个。

在显示图像时,我想在图像上叠加文字。

这是我用来创建图像和文本的代码

 Dim fname As String = (Actually an array in images(jpg) that display with timer)
    Dim bm As New Bitmap(fname)
    PicBox.Image = bm
    findex -= 1  (index of image array)
    Dim g As Graphics = PicBox.CreateGraphics
    g.DrawImage(bm, 300, 10)
    g.DrawString("Kishman Tukus", New Font("Arial", 24, FontStyle.Bold), Brushes.Green, 400, 100)
    g.ResetTransform() '   
    g.Dispose()

我需要使用计时器一次在图片框中显示一个图像,并且我需要叠加 图片上也有文字。

有人可以帮助我阻止图像添加到图片框中,而不是一次显示一个吗? 或者更好的是,根本不使用 PictureBox,只显示带有文本覆盖的图像? 无论如何,我需要停止记忆流血。 谢谢你

【问题讨论】:

从代码中不清楚您真正想要实现的目标。设置 PictureBox 的 Image 属性将导致它根据 PictureBox 上的其他属性(SizeMode 等)在 PictureBox 内绘制该图像。您首先要说,“嘿 PictureBox,请在每次重绘时使用我在表单设计器或其他代码中分配的设置为自己绘制此图像。”然后你说,“哦,但就这一次,我想在你的特定位置画同样的图像,并在上面画一些文字。”请注意,如果需要重新绘制,这将变得更加丑陋 在您的示例代码中,它是同一张图像,但您似乎在描述相互绘制的不同图像,在我看来,这表明您没有向我们展示真正的代码。 【参考方案1】:

我认为如何加载图像很重要。您真的每次显示时都按文件名加载每个图像吗?这是误导性的,正如你提到的,有一个数组。区别在于您保留对这些图像的引用并且您正在修改每一个。请记住,这是一个引用类型,因此原始项目会被修改。因此,您最终会反复将文本覆盖在自身之上。具有讽刺意味的是,如果您确实在每个刻度上都加载了图像,那么您实际上就不会遇到这个问题 :)

我按照您所拥有的(我认为)制作了一些东西,我们使用 Object.Clone 在内存中制作每个位图的副本,您可以在不修改原始图像的情况下进行修改。

Private images As New List(Of Bitmap)()
Dim findex As Integer = 0

Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    Dim bmCopy = DirectCast(images(findex).Clone(), Bitmap)

    Using g As Graphics = Graphics.FromImage(bmCopy)
        g.DrawString(Guid.NewGuid().ToString(), New Font("Arial", 24, FontStyle.Bold), Brushes.Green, 400, 100)
    End Using

    PicBox.Image = bmCopy

    findex = (findex + 1) Mod images.Count()
End Sub

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    images.Add(My.Resources.Image1)
    images.Add(My.Resources.Image2)
    Timer1.Interval = 1000
    Timer1.Enabled = True
End Sub

没有内存泄漏。您可以检查内存增加,但 GC 最终会将其清除。

【讨论】:

【参考方案2】:

我希望看到更多类似的东西:

Dim bm As New Bitmap(fname)
Using g As Graphics = Graphics.FromImage(bm)
    g.DrawString("Kishman Tukus", New Font("Arial", 24, FontStyle.Bold), Brushes.Green, 400, 100)
End Using
PicBox.Image = bm

【讨论】:

以上是关于delphi 使用GDI吧jpg图片绘制在groupbox中的问题的主要内容,如果未能解决你的问题,请参考以下文章

Delphi GDI对象之绘制位图

向使用 GDI+ 绘制的图像添加文本

Delphi中的GDI行距?

delphi GDI 图片压缩代码 据说是位图缩放保持原图视觉效果最好的算法

C# 控制台应用程序 - 如何使用 GDI+ 在 BMP/JPG 文件中绘图?

Delphi: 圆形进度(环形进度)