在渲染期间绘制装载盖图像

加入
2020年1月22日
消息
10
编程经验
10+
你好,
由于表单小程序,我有简单的单个无边界全屏形式(现在具有启用的双缓冲)应用程序。问题很简单,一个提到的applet reqiure全懒红,所以它导致屏幕闪烁。我制作全屏封面图像以隐藏该小程序的加载状态。有趣的是,我的封面图像闪烁!  :) 问题是组合形成NAD硬图像尺寸。快速绘制封面图像是否可以容易地避免背景闪烁? (某些屏幕绘图可能与某些Windows Lib或Nuget包。)我想要没有外部要求,只需小lib即可。还请记住,我想要过渡进入/淘汰这个封面图像,以便真正顺利地加载......
 

跳伞运动员

工作人员
加入
2019年4月6日
消息
2,892
地点
切萨皮克,va.
编程经验
10+
一个简单的飞溅屏幕不应该闪烁。向我们展示您的代码。
 

sh

众所周知的成员
加入
2018年9月5日
消息
1,982
编程经验
10+
提到的applet reqiure全懒红
什么applet?你从哪里得到它?
问题是组合形成NAD硬图像尺寸
你似乎知道这个问题,所以为什么你不能提议这个问题"hard image size"?
如果您正在绘制另一个图像,(它似乎在您所描述的那样),您是否认为闪烁的正常情况?
如果您在被绘制的人后面绘制了一个前景项目,双重缓冲不会帮助您有很多。

鉴于Windows迫使Windows 7用户升级到Windows 10,听起来像一个无意义的问题,但您使用应用程序的操作系统?
我问,因为如果你定位了一个旧的操作系统,你可以使用 ws_ex_composited; 我可以添加需要禁用Aero,这会急剧帮助减少闪烁。使用此API确实需要禁用DWM,但是,最合乎逻辑的事情是在WPF中设计您的应用程序,以避免所有这些必需品,特别是如果您的应用程序处于依赖的图形处理。
 
加入
2020年1月22日
消息
10
编程经验
10+
也是如此。我有全屏(无边缘最大化)表格(现在有启用的双重缓冲)和停靠(填充)控制。我想要封面形式把柄渲染在背景中。这是全部了。 FOMRS Rendeing的问题是众所周知的 - 形式控制无法呈现,如果不可见 - 在背景中。我尝试使用两个解决方案 - 绘制控制手柄并在屏幕手柄上绘制。在控制句柄上绘制的解决方案是坏的解决方案,因为小程序渲染在快速FPS中,它会导致闪烁。但在屏幕上绘制(Zero PTR)真正工作和涵盖控制渲染。屏幕渲染的唯一问题是绘制速度慢。所以我只想要在较低的代码中绘制覆盖图像过度形式/控制,即我知道,我使用了很多渲染框架等 - 只有我正在寻找一些简单的解决方案。我所需要的只是让我的表格顺利渲染在背景中,并在前面绘制全屏封面......(并在前面带上表格而不刷新加载的控制,只是渲染的涂料。)我在没有特殊libs等的情况下定位Windows 10因为它是可能的。必须有简单的解决方案,因为真的我知道,这是可能的。我可以为它做好准备,我可以运行一些有一些背景应用程序,具有DirectX Access等 - 真的只是我希望油漆覆盖图像过于形式,并在前面平稳地带来形式......

例如,我尝试了什么,它有效:
我可以在Zeroptr手柄和抓取控制快照上绘制封面,即我也绘制桌面句柄,但渲染是如此极低速度 - 我知道,绘制桌面句柄是坏主意。但它很苍蝇。
我在控制手柄上绘制定时器盖,这使得快速渲染和真正的促使控制渲染,但结束时会产生一个快速闪烁。所以我真的在寻找一些顺利过渡......
 
Last edited:

跳伞运动员

工作人员
加入
2019年4月6日
消息
2,892
地点
切萨皮克,va.
编程经验
10+
请向我们展示您的代码。我怀疑你正在做的事情正在导致你的屏幕闪烁。

考虑我介绍的代码 其他线程。它确实完整的屏幕矩阵屏幕保护程序效果而没有任何闪烁。 (授予,我只在2560x1080,1920x1080,1920x1080和更小的机器上测试了常规80-96个DPI监视器。我不拥有任何4K显示器。)我所做的一切都只使用内置的双重缓冲和在油漆活动中做正常绘画。我甚至甚至没有拔出所有其他技巧,使绘制更快地像跳过背景绘画,只跳过屏幕刷新率的速度更快,只是更新实际改变的屏幕的部分,或者通过绘制到屏幕上的图形表面。
 
加入
2020年1月22日
消息
10
编程经验
10+
我没有该小程序的代码。我有applet的lib,它有自定义渲染系统外部表单,它以表单应用程序托管。我确切地知道为什么闪烁。我在第一篇文章中描述它。只有问题是,这个小程序需要处理上一个屏幕,因此它绘制了空白屏幕并成为渲染。这我的意思是闪烁。 applet之前的空页成为渲染。而且我也必须在渲染期间观看物品位置。所以我只想要在我拥有的图像下覆盖这种渲染。真的没什么特别的。我要求绘制其他Sceen,所以我显示封面图像并将新屏幕发送到applet。 applet redraw屏幕与空白页并成为渲染。在Redered之后,我将applet控制带到前面。这就是我想要的。只是我想要一些低代码全屏渲染,可以轻松促使表格渲染。这是我的问题。真的我只是表格{maimated,无边缘},在这个表单停靠的控制中,我想覆盖它。而已。我只有这两个简单的物品。

问题也是如此,此小程序具有自定义渲染,因此不会导致绘制绘制事件。我没有控制小程序渲染。我不需要它。我只想让这个小程序渲染并覆盖我的图像下。我想要在完成工作时隐藏图像。在之前或之后没有空白屏幕。所以在较低的代码中,而不是愚蠢的形式......(模拟淡入/输出。)

只是我看到关于applet的信息,它会使用skia neatine进行渲染。
 
Last edited:

跳伞运动员

工作人员
加入
2019年4月6日
消息
2,892
地点
切萨皮克,va.
编程经验
10+
是applet,或者是您在全屏无边框表单中托管的Winforms控件或ActiveX控件?

能 you move your Form off screen (e.g. Form.Location = Screen.PrimaryScreen.Bounds.Location - Screen.PrimaryScreen.Bounds.Size;, and then when it is done drawing move it back on screen Form.Location = new Point(0,0);) ?
 
加入
2020年1月22日
消息
10
编程经验
10+
但是当前屏幕将是什么?正如我所提到的,它应该是Skia applet - 所以它是webgl的东西。它不是在表单句柄之外呈现,而且它也不会引起正常的形式事件......我写道时,当我在零把手上绘制图像时,它会覆盖它下面的形式,它为我工作。只有这种渲染非常慢,所以我只希望通过一些DirectX库渲染,或者在屏幕缓冲区上的东西。当我移动或调整主表单的大小时,它仍然使闪烁 - 我的意思是,在行动之前绘制的一些颜色矩形...所以我正在寻找真正的封面渲染,不需要表单句柄......
 

sh

众所周知的成员
加入
2018年9月5日
消息
1,982
编程经验
10+
也是如此。我有全屏(无边界最大化)表格(现在有启用的双人安全)
这个线程有一个可怕的回声。
你似乎知道这个问题,所以为什么你不能提议这个问题"hard image size"?
如果您正在绘制另一个图像,(它似乎在您所描述的那样),您是否认为闪烁的正常情况?
如果您在被绘制的人后面绘制了一个前景项目,双重缓冲不会帮助您有很多。
我会想到你的10年的经验,这对你来说,了解我所说的而不是试图将我的帖子视为一些无用的运球。也许如果你花了一些时间阅读你正在接收的回复,你会发现你的方法无法实现。在第4篇文章中,你遇到了粗鲁,就像谁回答你的代码猴子不明白你的问题,它似乎已经走过了我们的头,它没有。

你在谈论手柄上的绘画。大声笑你没有绘制句柄,你真的似乎没有明白把手是什么或者如何使用。这确实可以部分解释为熄灭主题链接到您原始问题。 什么是a"handle"?

此外,如果您有10年的经验。你应该知道你正在使用什么。它是applet,Active x控件,一个用户配置,自定义插件吗?

只是阅读你的回复,我可以告诉你没有十年的经验,你当然没有很好地了解你正在做的事情或者甚至可能。我会让你心痛,告诉你这不起作用,特别是在Winforms中。此外,如果您正在使用某种小程序,它将在重绘时对其中的一切效果在于,无论您应用的缓冲如何。 WinForms不是用于此类处理的。祝你好运。
 
加入
2020年1月22日
消息
10
编程经验
10+
我真的没有拥有10年的Windows形式的体验。我是BSD的Linux程序员,开始。最近5年的MVC ASP / PHP。我在用"INTPTR GETDC(INTPTR HWND);"用于控制控制。 (通过句柄。)我在7年之前使用了直接缓冲区。所以我知道,这真的很容易重绘屏幕缓冲区,只是我忘了解决方案。我不是桌面表格开发商。但我很确定我需要什么以及如何做到这一点。因为我是单声道/ XAMARIN开发人员4年,我花了一些部分形式渲染。我渴望通过一些较低的渲染来隐藏形式渲染......我在一小时前得到了想法,所以在大约40分钟后我会尝试。正如我写的,我不是很好的桌面开发人员,但这真的必须有简单的解决方案 - 隐藏控制绘画......
 

跳伞运动员

工作人员
加入
2019年4月6日
消息
2,892
地点
切萨皮克,va.
编程经验
10+
I am using "INTPTR GETDC(INTPTR HWND);"用于控制控制。 (通过手柄。)
并且有一些性能问题。当您使用P / Invoke呼叫时,需要将参数从世界的管理方面编组成未托管的方面,执行实际呼叫,然后将任何从非管理方面的回复返回到管理方面。因此,使用非托管代码需要几毫秒的GDI代码将进入数百毫秒。确保最小化这些托管/非托管过渡。

为什么你不仅仅是用自己的控制来绘画,你正在使用它来覆盖其他形式"applet" hosted in it?
 
加入
2020年1月22日
消息
10
编程经验
10+
我在哪里可以画?这是我的全部问题。我有封面形象。但是在哪里绘制......当我试图绘制控制时,它的渲染赢得......(并闪烁。)所以我需要一些新的图层,我可以在前面带来......这是我想要的。只需让控制完全呈现并覆盖它。它不会导致正常的绘画事件,因此我不能使用正常的Paiting ...我提到的,我可以为一些背景应用程序准备。它是Skia,WebGL,如我之前写的。我可以在背景中准备第二种形式,但我真的不知道,如何在没有闪烁的情况下在前面带来......而且,我的P / Invoke调用根本不慢。因为我在触发控制刷新之前正在做它。这就是我试图告诉你的开始。是我,谁导致控制渲染,所以我可以为它做好准备。我之前拍摄了快照,我之前绘制了快照,我会让控制刷新后。并在控制后隐藏封面。我可以管理这个的每一步。只是我无法访问较低的渲染,这可以快速重绘图像形式......你仍然试着告诉我,那是我的渲染闪烁,但不是,这真的不是问题,因为我不呼叫控制redraw直到我准备就绪..我可以为它做好准备,我可以在背景中运行其他应用程序,我可以做一切。只是我不知道如何顺利​​覆盖形式,让形式在前面带来没有重新加载控制......在这种情况下,只有一个小东西会导致闪烁。只有applet渲染的愚蠢,在渲染之前明确的sceen。因此,在筛选之前,它在屏幕上呈现几秒钟的背景颜色。它导致闪烁......我只想在我让控制刷新之前封存它......是的,这一次,我想在这个小程序论坛中寻找如何为此applet启用双缓冲区,但我没有答案。所以,我只是想隐藏它,因为我相信,这很简单而快速解决......
 

跳伞运动员

工作人员
加入
2019年4月6日
消息
2,892
地点
切萨皮克,va.
编程经验
10+
再次,没有看到你的代码很难谈论你正在做什么以及如何更好地制作事情。

如果你的"applet"使用WebGL并使用任何类型的GPU加速,直接绘制,或者如果它实际上在窗口上覆盖它是使用的(ALA一些NVIDIA和ATI / AMD视频播放加速),那么Winforms双缓冲就不会进入要做什么好,因为在GDI水平上发生双缓冲,而你的"applet"实际上是绘制到屏幕并绕过GDI。
 
加入
2020年1月22日
消息
10
编程经验
10+
我没有applet代码。我真的只有形式和控制。其他一切都是用于小程序内容的。我真的知道,那个Windows API的双缓冲不能解决,这就是为什么我每次都在圆括号中写下它。是的,它有GPU加速。我在4个帖子之前写了它,你忽略它......

"只是我看到关于applet的信息,它会使用skia neatine进行渲染。"

我也可以转移加速,但我不确定只为此解决方案做到这一点。 (它必须在App运行之前关闭,并且不能随时使用。)我必须写多少次,即我不希望用表单渲染解析它,我不希望用表单双缓冲来解决它!我知道,它不能解决。全职,从第一篇文章,我想在较低的代码中使用一些DirectX lib,但你仍然忽略它,仍然是关于表格的事情。但表单层真的无法解决。我知道,这就是我在这里的原因。我希望进入屏幕缓冲区......我真的不知道如何更好地写作。我有表单,运行表单,与停靠控件。从控制中拍摄快照,在控制DC中绘制图像,呼叫刷新(applet屏幕重新加载),并让您的图像上的控制闪烁的最后涂料。从这一次,我真的在想关掉GPU加速,我仍然不确定,如果我可以使用它。但你真的不能责怪我,我从第一篇文章写下你,我正在寻找低层渲染......我知道情况,我知道,表单的渲染是菜鸟......真的我正在谈论2个形式控制和刷新其中一个。而已。我真的没想到这个问题。只是我想在完成之前覆盖applet刷新......
 

跳伞运动员

工作人员
加入
2019年4月6日
消息
2,892
地点
切萨皮克,va.
编程经验
10+
您能创建一个展示问题的最小WinForms应用程序吗?它有:
- 托管您的表单的一些最小版本"applet"
- 您的表单的一些最小版本托管您的表单"docked Control"
- 您控制的一些最小版本
- 拍摄快照的代码的一些最小版本绘制了控制DC,呼叫刷新或Applet中的图像,并绘制您的控件。
 

跳伞运动员

工作人员
加入
2019年4月6日
消息
2,892
地点
切萨皮克,va.
编程经验
10+
在控制直流中绘制图像
为什么?您应该在您的控件中只需在您的控件中进行油漆活动进行拍摄的屏幕截图。
 

跳伞运动员

工作人员
加入
2019年4月6日
消息
2,892
地点
切萨皮克,va.
编程经验
10+
我知道,这就是我在这里的原因。我希望进入屏幕缓冲区......
"here"碰巧是Winforms论坛。 WinForms没有那种较低的级别访问。注意单词"forms" in "WinForms".

在你的第一个帖子中你说:
(某些屏幕绘图可能与某些Windows Lib或Nuget包。)我想要没有外部要求,只需小lib即可。
If you don't want external requirements, then using DirectX or DirectDraw is going to be eliminated because those are external dependencies. Even though it maybe installed on Windows, you'll still have to jump outside of WinForms to get to them. As it is, your current P/Invoke call to GetDC() is also technically an external dependency/requirement since again, you are jumping outside of WinForms. Granted that WinForms is built on WinUser and WinGDI, consider what happens when you run your code on .NET Core 3.0 on Linux where you may not have a real Windows DC to play with.
 

跳伞运动员

工作人员
加入
2019年4月6日
消息
2,892
地点
切萨皮克,va.
编程经验
10+
由于您如此终于提供一些尝试展示问题的代码,这里有一些试图重现它的代码。

模拟您的Skia的表格"applet", I have a fullscreen MainForm which has a SKGLControl. Inside the control, a bouncing ball and the current time is rendered at a target frame rate.

Unfortunately, I can't reproduce the flickering while drawing on SKIA control that is hardware accelerated. The closest I could get was for some horizontal tearing to happen on my old desktop computer with an 8 year ATI/AMD graphics card. (I couldn't get the same tearing to happen on my laptop that has a relatively modern dedicated ATI/AMD graphics chip.) I got the tearing to show by using higher values for PixelsPerSecond in the Ball class (line 142).

Anyway with the tearing appearing, I then show the covering DesktopForm on top of the MainForm by pressing the Escape key (see lines 91-101). All this form does is render an upside down screenshot of the desktop. I deliberately render the screen upside down because I was confusing myself as to when I had my real desktop vs. a static screenshot of it. If you don't want it upside down, comment out the transform lines. Any which way, I'm just using normal painting. I really don't understand why you would need to P/Invoke GetDC().

无论如何,我没有看到这种覆盖托管形式的新形式的任何闪烁或撕裂。我无法重现你的问题,在你说覆盖形式的封面形式闪烁的地方。

如果您不相信托管表实际上是继续渲染,请尝试将封面形式的不透明度设置为50%的解读线26。您将能够看到球继续在覆盖形式下移动。

通过单击它或按下键来解除覆盖形式,托管表格显示无任何问题。当原始形式在盖子消失时,我没有看到任何眨眼或闪烁。

SkiaWinForms:
using SkiaSharp;
using SkiaSharp.Views.Desktop;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SkiaWinForms
{
    [DesignerCategory("Code")]
    class DesktopForm : Form
    {
        readonly Bitmap _bitmap;

        public DesktopForm(Bitmap bitmap)
        {
            _bitmap = bitmap;

            Bounds = Screen.PrimaryScreen.Bounds;
            FormBorderStyle = FormBorderStyle.None;
            DoubleBuffered = true;
            // Opacity = 0.50;

            Click += (o, e) => Close();
            KeyPress += (o, e) => Close();
            Paint += (o, e) =>
            {
                e.Graphics.TranslateTransform(_bitmap.Width, bitmap.Height);
                e.Graphics.ScaleTransform(-1, -1);
                e.Graphics.DrawImage(_bitmap, Point.Empty);
            };
        }
    }

    [DesignerCategory("Code")]
    class MainForm : Form
    {
        readonly Bitmap _screenshot;
        readonly Ball _ball;

        MainForm(Bitmap screenshot, Ball ball, int framesPerSecond)
        {
            _screenshot = screenshot;
            _ball = ball;

            Bounds = Screen.PrimaryScreen.Bounds;
            FormBorderStyle = FormBorderStyle.None;
            DoubleBuffered = true;

            var skcontrol = new SKGLControl() { Dock = DockStyle.Fill };
            skcontrol.PaintSurface += Skcontrol_PaintSurface;
            skcontrol.Click += (o, e) => Close();
            skcontrol.KeyPress += (o, e) => Close();

            var timer = new Timer() { Interval = (int)Math.Round(1000.0 / framesPerSecond) };
            timer.Tick += (o, e) => { _ball.Update(); skcontrol.Invalidate(); };
            timer.Start();

            Controls.Add(skcontrol);
        }

        private void Skcontrol_PaintSurface(object sender, SKPaintGLSurfaceEventArgs e)
        {
            var surface = e.Surface;
            var canvas = surface.Canvas;

            canvas.Clear(SKColors.White);

            canvas.DrawCircle(_ball.Position, _ball.Radius, new SKPaint()
            {
                IsAntialias = true,
                Color = SKColors.Green,
                Style = SKPaintStyle.Fill
            });

            canvas.DrawText($"{DateTime.Now}", 100, 100, new SKPaint()
            {
                TextSize = 64.0f,
                IsAntialias = true,
                Color = SKColors.Red,
                Style = SKPaintStyle.Fill
            });

            canvas.Flush();
        }

        protected override bool ProcessDialogKey(Keys keyData)
        {
            if (keyData.HasFlag(Keys.Escape))
            {
                using (var desktop = new DesktopForm(_screenshot))
                    desktop.ShowDialog();
                return true;
            }

            return base.ProcessDialogKey(keyData);
        }

        static Bitmap CreateScreenshot()
        {
            var rect = Screen.PrimaryScreen.Bounds;
            var bitmap = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb);
            using (var g = Graphics.FromImage(bitmap))
            {
                g.CopyFromScreen(rect.Location, Point.Empty, rect.Size);
            }
            return bitmap;
        }

        [STAThread]
        static void Main()
        {
            const int FramesPerSecond = 24;

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm(CreateScreenshot(),
                            new Ball(Screen.PrimaryScreen.Bounds, FramesPerSecond),
                            FramesPerSecond));
        }
    }

    class Ball
    {
        readonly Rectangle _bounds;
        SKPoint _vector;
        SKPoint _position;

        public SKPoint Position => _position;
        public float Radius => 200.0f;

        public Ball(Rectangle bounds, int framesPerSecond)
        {
            _bounds = bounds;
            _position.X = _bounds.Width / 2;
            _position.Y = _bounds.Height / 2;

            const int PixelsPerSecond = 150;
            var pixelsPerFrame = (float) PixelsPerSecond / framesPerSecond;
            _vector = new SKPoint(pixelsPerFrame, pixelsPerFrame);
        }

        public void Update()
        {
            (_position.X, _vector.X) = CheckBounds(_position.X, _vector.X, _bounds.Left, _bounds.Right);
            (_position.Y, _vector.Y) = CheckBounds(_position.Y, _vector.Y, _bounds.Top, _bounds.Bottom);

            (float newValue, float newVector) CheckBounds(float value, float vector, float min, float max)
            {
                value += vector;
                if (value + Radius > max)
                {
                    value = max - Radius;
                    vector *= -1;
                }
                else if (value - Radius < min)
                {
                    value = min + Radius;
                    vector *= -1;
                }
                return (value, vector);
            }
        }
    }
}

代码也可提供: AzureskyDiver / Skiawinforms.
 
加入
2020年1月22日
消息
10
编程经验
10+
这很愚蠢地容易。我想避免用户舒适的双重形式,但只是问题。我只是留下一个表格活动的想法,它解决了它。只是我打开第二个表格,它让前一个表单渲染,并且在我可以在呈现主表单时隐藏我的封面形式。两种形式加双灾,它根本使载荷顺利。这是我的问题从开始 - 如何绘制图像以让表单在背景中呈现。并回答是,我需要第二个应用程序只是为了管理封面。现在我刚刚尝试将两种表格绑定在一起,用户某种方式更改窗口大小,所以我的封面形式必须具有与覆盖形式相同的位置和尺寸......(我在展示封面前进行一些测试,使其良好。)我也有兴趣,我如何隐藏我的应用程序的双重形式图标 - 不要在任务栏中制作混乱...但是真的感谢您尝试帮助...
 

跳伞运动员

工作人员
加入
2019年4月6日
消息
2,892
地点
切萨皮克,va.
编程经验
10+
我也有兴趣,我如何隐藏我的应用程序的双重形式图标 - 不要在任务栏等中制作混乱...
如果您不希望在任务栏中显示表格,请刚刚设置 showintaskbar. 假。但是如果您的主表单在帖子#1中所说的时候是全屏幕,那么无论如何都会隐藏任务栏,所以我没有看到这一点。 (更多关于以下全屏。)

并回答是,我需要第二个应用程序只是为了管理封面。
You don't need a second app. See how I managed with just a single application in post #18. The trick is to keep the message pump running. In post #18, I did that by using ShowDialog() to create a dialog. A modeless dialog will also work. (For details on modeless dialogs, see WinForms中的VILOWSESS对话框 .)

当您的主表单准备运行时,您基本上需要的是有效的飞溅屏幕。为此,您只需将封面表单显示为当前形式顶部的Voldeasess对话框,然后在准备好时,关闭封面表单。

现在我只是尝试将两种表格绑定在一起,用户某种方式更改窗口大小,因此我的封面必须具有与覆盖形式相同的位置和大小......
假设您使用单个应用程序,只要您的主表单获得调整大小的事件,请告诉您的封面表单也会调整大小。如果您必须使用2个应用程序,那么您将创建一个自定义wm_user + n消息并发布

但是,我没有看到你的主要形式如何调整正常情况。在你的帖子里#1你说:
我有简单的单一无边界全屏形式
这意味着如果它是无边界的,则不会有任何调整大小句柄。

如果您在平板电脑上运行并且用户更改方向,或者如果您在PC或笔记本电脑上以及用户替换监视器上的唯一时间,则是唯一的。考虑到您说速度仅在首先显示主表单时才会发生这种情况,发生这种情况的概率非常低。闪烁的时期多久了?不到1秒钟?不到3秒?
 
最佳 底部