如何使用WPF控制像素获得WritableBitmap像素1:1? [英] Howto get WritableBitmap pixels 1:1 with WPF Control pixels?
问题描述
即使调整控件的大小,如何有效地获取WritableBitmap的像素以匹配屏幕上的像素1:1?
How can I efficiently get the pixels of a WritableBitmap to match on-screen pixels 1:1, even as a control is resized?
或者,如何像Windows.Forms一样快速地在WPF中使用文本快速进行2d矢量绘制?
Or alternatively, how can I do fast 2d vector drawing with text in WPF, as fast as Windows.Forms?
背景:
我有一个简单的Windows.Forms应用程序,我正在尝试将其转换为WPF.它具有用户绘制的控件,该控件会随音频电平图不断更新.在Windows.Forms中,控件会定期调用Invalidate,并具有一个绘制它的OnPaint处理程序.
I have a simple Windows.Forms app I'm trying to convert to WPF. It has a user-drawn control which is continuously updated with an Audio Level Graph. In Windows.Forms, the control periodically calls Invalidate, and has an OnPaint handler which draws it.
我在WPF中的第一次尝试是将UIElement用于用户绘制的控件.但是,我唯一想重绘的方法是InvalidateVisual(),它会导致完全重新布局并且运行缓慢.同样,使用DrawingContext绘制文本的速度也非常慢.
My first attempt in WPF was using a UIElement for the user-drawn control. However, the only way I could figure out to repaint it was InvalidateVisual() which causes a full relayout and was slow. Also drawing text with DrawingContext is incredibly slow.
我当前的代码是将Image用于用户绘制的控件,并使用System.Drawing.Graphics绘制到该图像的WriteableBitmap源上.这非常快并且效果很好.
My current code is using Image for my user-drawn control, with System.Drawing.Graphics to paint onto a WriteableBitmap source for the image. This is extremely fast and works well.
但是,我无法弄清楚如何有效地将Imageable控件的WriteableBitmap大小调整为1:1且带有屏幕像素.我试图使用LayoutUpdated来制作一个具有新大小的新WritableBitmap,并将其设置为Image.Source,但这实在令人难以置信 慢.
However, I can't figure out how to efficiently get the WriteableBitmap to be sized 1:1 with screen-pixels for the Image control. I tried to use LayoutUpdated to make a new WritableBitmap with the new size, and set it as the Image.Source, but this is incredibly slow.
您可以在此处查看我当前的代码:
You can see my current code here:
https://github.com/jeske/SoundLevelMonitor/blob/master/SoundLevelMonitorWPF/SoundLevelMonitor/AudioLevelsUIElement.cs#L46
https://github.com/jeske/SoundLevelMonitor/blob/master/SoundLevelMonitorWPF/SoundLevelMonitor/AudioLevelsUIElement.cs#L46
推荐答案
我解决了我的问题.
I solved my problem.
捕获调整大小事件的正确方法是侦听Image.SizeChanged事件,该事件仅在大小改变时才触发.在该事件处理程序中,我制作了一个新的WriteableBitmap,其大小为RenderSize,将其设置为Image.Source,并且一切都很好. 世界.我还必须将Image控件设置为Stretch ="Fill".以防止其保持底层位图的长宽比.
The correct way to catch the resize events is to listen to the Image.SizeChanged event, which only fires when the size changes. Inside that event handler I make a new WriteableBitmap of size RenderSize, set that to the Image.Source, and all is good in the world. I also had to set the Image control to Stretch="Fill" to prevent it from maintaining the underlying bitmap's aspect ratio.
Image.LayoutUpdated,这会导致性能下降.
Image.LayoutUpdated is actually fired every time the content changes, and this was causing the bad performance.
这篇关于如何使用WPF控制像素获得WritableBitmap像素1:1?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!