现有的图形为位图 [英] Existing Graphics into Bitmap

查看:164
本文介绍了现有的图形为位图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写的一个交易软件的一个插件(C#的WinForms,.NET 3.5),我想画一个十字光标在面板(比方说 ChartPanel ),其中包含的数据,可能是昂贵的画。我到目前为止,完成的是:

I'm writing a plugin for a trading software (C#, winforms, .NET 3.5) and I'd like to draw a crosshair cursor over a panel (let's say ChartPanel) which contains data that might be expensive to paint. What I've done so far is:

  1. 我添加了一个 CursorControl 到面板
    • 在此 CursorControl 定位在主拉丝面板,使其覆盖它的整个区域
    • 已启用=假,使所有输入事件传递到父 ChartPanel
    • 油漆方法被实现,使得它吸引行从上到下和从左至右在当前鼠标位置
  1. I added a CursorControl to the panel
    • this CursorControl is positioned over the main drawing panel so that it covers it's entire area
    • it's Enabled = false so that all input events are passed to the parent ChartPanel
    • it's Paint method is implemented so that it draws lines from top to bottom and from left to right at current mouse position
  • A)呼叫 ChartPanel.Invalidate(),但正如我所说,基础数据可能是昂贵的画,这将导致一切重绘每次我移动鼠标,这是错误的(但我可以做这项工作,现在唯一的办法)
  • B)呼叫 CursorControl.Invalidate()键,光标绘制之前,我会采取目前得出的数据的快照,并保持它作为背景的​​光标会将刚刚恢复每次光标需要重新绘制...这个问题是... 我不知道该怎么做
  • A) Call ChartPanel.Invalidate(), but as I said, the underlying data may be expensive to paint and this would cause everything to redraw everytime I move a mouse, which is wrong (but it is the only way I can make this work now)
  • B) Call CursorControl.Invalidate() and before the cursor is drawn I would take a snapshot of currently drawn data and keep it as a background for the cursor that would be just restored everytime the cursor needs to be repainted ... the problem with this is ... I don't know how to do that.

2.B。将意味着:

  • 打开现有的图形对象为位图(它(图形)通过画图给我方法,我一定要画它,所以我不能创建一个新的Graphics对象......也许我搞错了,但是这是我理解的方式)
  • 十字线画前,恢复从位图图形内容,并重新绘制十字
  • Turn existing Graphics object into Bitmap (it (the Graphics) is given to me through Paint method and I have to paint at it, so I just can't create a new Graphics object ... maybe I get it wrong, but that's the way I understand it)
  • before the crosshair is painted, restore the Graphics contents from the Bitmap and repaint the crosshair

我无法控制画昂贵的数据的过程。我可以访问我的 CursorControl 和它的那些通过API。

I can't control the process of painting the expensive data. I can just access my CursorControl and it's methods that are called through the API.

那么,有没有办法现有图形内容存储到的位图,并在以后恢复呢?或者有没有更好的办法来解决这个问题呢?

So is there any way to store existing Graphics contents into Bitmap and restore it later? Or is there any better way to solve this problem?

解决:这么多小时的反复试验后,我想出了一个可行的解决方案。有许多问题,我用的不能笼统地讨论的软件,但主要原则是明确的:

RESOLVED: So after many hours of trial and error I came up with a working solution. There are many issues with the software I use that can't be discussed generally, but the main principles are clear:

  • 在现有的与已涂的东西显卡不能转化为直接位图,而不是我不得不使用 panel.DrawToBitmap 方法首先在@古斯曼的答复中提到。我知道这件事,我想避免它,但最终我不得不接受,因为它似乎是唯一的出路
  • 我也想避免每帧的双绘图,所以第一个十字线涂料总是直接吸引到 ChartPanel 。后不改变图表图像鼠标移动我拿snapshow通过 DrawToBitmap 并继续在选定的答案描述。
  • 控制必须是不透明的(未启用透明背景),这样清爽不调用paint它的父控件(这将导致整个图表重绘)
  • existing Graphics with already painted stuff can't be converted to Bitmap directly, instead I had to use panel.DrawToBitmap method first mentioned in @Gusman's answer. I knew about it, I wanted to avoid it, but in the end I had to accept, because it seems to be the only way
  • also I wanted to avoid double drawing of every frame, so the first crosshair paint is always drawn directly to the ChartPanel. After the mouse moves without changing the chart image I take a snapshow through DrawToBitmap and proceed as described in chosen answer.
  • The control has to be Opaque (not enabled Transparent background) so that refreshing it doesn't call Paint on it's parent controls (which would cause the whole chart to repaint)

我仍然会遇到偶尔闪烁每隔几秒钟左右的时间,但我想我能明白这一点不知。虽然我选择了古斯曼的回答,我要感谢每个人都参与,为我所用在其他的答案中提到的许多其他的技巧,如Panel.BackgroundImage,使用绘图()方法,而不是paint()来锁定图像等

I still experience occasional flicker every few seconds or so, but I guess I can figure that out somehow. Although I picked Gusman's answer, I would like to thank everyone involved, as I used many other tricks mentioned in other answers, like the Panel.BackgroundImage, use of Plot() method instead of Paint() to lock the image, etc.

推荐答案

在你的CursorControl你为什么不克隆在ChartPanel所有的图形?

Why don't you clone all the graphics in the ChartPanel over your CursorControl?

所有code在这里一定要放在你的CursorControl内。

All the code here must be placed inside your CursorControl.

首先,创建将举行一个参考图表,钩到它的Paint事件,像这样的属性:

First, create a property which will hold a reference to the chart and hook to it's paint event, something like this:

ChartPanel panel;

public ChartPanel Panel
{ 
    get{ return panel; } 

    set{ 

         if(panel != null)
            panel.Paint -= CloneAspect;

         panel = value;

         panel.Paint += CloneAspect;
    }

}

现在定义CloneAspect功能,这将使得该控件的外观位图,每当一个Paint opperation已在图板上完成的:

Now define the CloneAspect function which will render the control's appearance to a bitmap whenever a Paint opperation has been done in the Chart panel:

Bitmap aspect;

void CloneAspect(object sender, PaintEventArgs e)
{

    if(aspect == null || aspect.Width != panel.Width || aspect.Height != panel.Height)
    {

         if(aspect != null)
            aspect.Dispose();

         aspect = new Bitmap(panel.Width, panel.Height, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);

    }

    panel.DrawToBitmap(aspect, new Rectangle(0,0, panel.Width, panel.Height);

}

然后在OnPaint中重写的方法做到这一点:

Then in the OnPaint overriden method do this:

public override void OnPaint(PaintEventArgs e)
{
    e.Graphics.DrawImage(aspect);

    //Now draw the cursor
    (...)
}

最后,无论你创建图表,你做的CustomCursor:

And finally wherever you create the chart and the customcursor you do:

CursorControl.Panel = ChartPanel;

和瞧,你可以重画,你需要尽可能多的时间,而重新计算图表的内容。

And voila, you can redraw as many times you need without recalculating the chart's content.

干杯。

这篇关于现有的图形为位图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆