翻译《The Old New Thing》- Taxes: Remote Desktop Connection and painting

2024-05-14 13:12

本文主要是介绍翻译《The Old New Thing》- Taxes: Remote Desktop Connection and painting,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Taxes: Remote Desktop Connection and painting - The Old New Thingicon-default.png?t=N7T8https://devblogs.microsoft.com/oldnewthing/20060103-12/?p=32793

Raymond Chen 2006年01月03日


开发成本:远程桌面连接和绘制

        当用户通过远程桌面连接进行连接时,视频操作会通过网络传输到客户端进行显示。由于网络的延迟较高,且带宽远远低于本地PCI或AGP总线,您需要适应屏幕绘制成本的变化。

        如果您在屏幕上绘制一条线,那么“绘制线条”的命令会通过网络发送到客户端。如果您绘制文本,会发送一个“绘制文本”的命令(以及要绘制的文本)。到目前为止,一切都很好。

        但是,如果您将一个位图复制到屏幕上,那么整个位图都需要通过网络传输。

        让我们编写一个示例程序来说明这一点。从我们的新草稿程序开始,并进行以下更改:

void Window::Register()
{WNDCLASS wc;wc.style = CS_VREDRAW | CS_HREDRAW;wc.lpfnWndProc = Window::s_WndProc;...
}class RootWindow : public Window
{
public:virtual LPCTSTR ClassName() { return TEXT("Scratch"); }static RootWindow *Create();
protected:LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);LRESULT OnCreate();void PaintContent(PAINTSTRUCT *pps);void Draw(HDC hdc, PAINTSTRUCT *pps);
private:HWND m_hwndChild;
};void RootWindow::Draw(HDC hdc, PAINTSTRUCT *pps)
{FillRect(hdc, &pps->rcPaint, (HBRUSH)(COLOR_WINDOW + 1));RECT rc;GetClientRect(m_hwnd, &rc);for (int i = -10; i < 10; i++){TextOut(hdc, 0, i * 15 + rc.bottom / 2, TEXT("Blah blah"), 9);}
}void RootWindow::PaintContent(PAINTSTRUCT *pps)
{Draw(pps->hdc, pps);
}LRESULT RootWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{switch (uMsg){...case WM_ERASEBKGND: return 1;...}
}

        这里有一个奇怪的分工;PaintContent方法实际上并不执行任何绘制操作,而是将绘制任务委托给Draw方法来完成。(您很快就会明白原因。)

        确保启用了“拖动时显示窗口内容”的选项,然后运行这个程序并垂直调整其大小。

        哎呀,多么难看的闪烁。

        我们通过传统的双缓冲技术来修复这个问题。

void RootWindow::PaintContent(PAINTSTRUCT *pps)
{if (!IsRectEmpty(&pps->rcPaint)){HDC hdc = CreateCompatibleDC(pps->hdc);if (hdc){int x = pps->rcPaint.left;int y = pps->rcPaint.top;int cx = pps->rcPaint.right - pps->rcPaint.left;int cy = pps->rcPaint.bottom - pps->rcPaint.top;HBITMAP hbm = CreateCompatibleBitmap(pps->hdc, cx, cy);if (hbm){HBITMAP hbmPrev = SelectBitmap(hdc, hbm);SetWindowOrgEx(hdc, x, y, NULL);Draw(hdc, pps);BitBlt(pps->hdc, x, y, cx, cy, hdc, x, y, SRCCOPY);SelectObject(hdc, hbmPrev);DeleteObject(hbm);}DeleteDC(hdc);}}
}

        我们的新PaintContent方法创建了一个离屏位图,并请求Draw方法将其绘制到其中。一旦完成,结果就会一次性地复制到屏幕上,从而避免了闪烁。

        如果您运行这个程序,您会发现它在调整大小时非常平滑。

        现在,通过远程桌面连接连接到计算机,然后再次运行它。

        由于远程桌面连接禁用了“拖动时显示窗口内容”的选项,您不能通过调整大小来触发重绘,而是应该将程序最大化和恢复几次。

        请注意,在您最大化窗口时,窗口调整大小之前会有一段较长的延迟。

        这是因为我们在BitBlt调用中,通过远程桌面连接传输了一个巨大的位图。

        回到PaintContent方法的旧版本,即只调用Draw的那个版本,并通过远程桌面连接运行它。

        啊,这个快多了。

        这是因为简化的版本不会通过远程桌面连接传输一个巨大的位图;它只是发送了二十个TextOut调用,这些调用涉及一个相当短的文本字符串。

        这些调用所占用的带宽远少于一个1024×768的位图。

        我们有一种方法在远程桌面连接上更快,另一种方法在本地运行时更快。

        我们应该使用哪种方法?

        我们两者都用,根据程序是否通过远程桌面连接运行来选择我们的绘图方法。

void RootWindow::PaintContent(PAINTSTRUCT *pps)
{if (GetSystemMetrics(SM_REMOTESESSION)){Draw(pps->hdc, pps);}else if (!IsRectEmpty(&pps->rcPaint)){...如前所述...}
}

        现在我们得到了最佳效果。

        当在本地运行时,我们使用双缓冲绘图,这样可以无闪烁地绘制,但当通过远程桌面连接运行时,我们使用简单的Draw方法直接绘制到屏幕上,而不是绘制到离屏位图。

        这是一个适应远程桌面连接的非常简单的例子。

        在一个更复杂的世界里,您可能需要根据两种绘图风格的需要,处理更复杂的数据结构,或者您可能需要根据程序是否通过远程桌面连接运行来开启或关闭与绘图相关的后台活动。

        由于用户可以动态地连接和断开连接,您不能仅仅假设程序启动时远程桌面连接的状态将一直保持不变。

        下次我们将看到如何适应一个不断变化的环境。

这篇关于翻译《The Old New Thing》- Taxes: Remote Desktop Connection and painting的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/988830

相关文章

论文翻译:arxiv-2024 Benchmark Data Contamination of Large Language Models: A Survey

Benchmark Data Contamination of Large Language Models: A Survey https://arxiv.org/abs/2406.04244 大规模语言模型的基准数据污染:一项综述 文章目录 大规模语言模型的基准数据污染:一项综述摘要1 引言 摘要 大规模语言模型(LLMs),如GPT-4、Claude-3和Gemini的快

论文翻译:ICLR-2024 PROVING TEST SET CONTAMINATION IN BLACK BOX LANGUAGE MODELS

PROVING TEST SET CONTAMINATION IN BLACK BOX LANGUAGE MODELS https://openreview.net/forum?id=KS8mIvetg2 验证测试集污染在黑盒语言模型中 文章目录 验证测试集污染在黑盒语言模型中摘要1 引言 摘要 大型语言模型是在大量互联网数据上训练的,这引发了人们的担忧和猜测,即它们可能已

java线程深度解析(一)——java new 接口?匿名内部类给你答案

http://blog.csdn.net/daybreak1209/article/details/51305477 一、内部类 1、内部类初识 一般,一个类里主要包含类的方法和属性,但在Java中还提出在类中继续定义类(内部类)的概念。 内部类的定义:类的内部定义类 先来看一个实例 [html]  view plain copy pu

string字符会调用new分配堆内存吗

gcc的string默认大小是32个字节,字符串小于等于15直接保存在栈上,超过之后才会使用new分配。

excel翻译软件有哪些?如何高效提翻译?

你是否曾在面对满屏的英文Excel表格时感到头疼?项目报告、数据分析、财务报表... 当这些重要的信息被语言壁垒阻挡时,效率和理解度都会大打折扣。别担心,只需3分钟,我将带你轻松解锁excel翻译成中文的秘籍。 无论是职场新人还是老手,这一技巧都将是你的得力助手,让你在信息的海洋中畅游无阻。 方法一:使用同声传译王软件 同声传译王是一款专业的翻译软件,它支持多种语言翻译,可以excel

MonoHuman: Animatable Human Neural Field from Monocular Video 翻译

MonoHuman:来自单目视频的可动画人类神经场 摘要。利用自由视图控制来动画化虚拟化身对于诸如虚拟现实和数字娱乐之类的各种应用来说是至关重要的。已有的研究试图利用神经辐射场(NeRF)的表征能力从单目视频中重建人体。最近的工作提出将变形网络移植到NeRF中,以进一步模拟人类神经场的动力学,从而动画化逼真的人类运动。然而,这种流水线要么依赖于姿态相关的表示,要么由于帧无关的优化而缺乏运动一致性

Docker远程连接和Docker Remote Api

在Docker生态系统中一共有3种API:Registry API、Docker Hub API、Docker Remote API 这三种API都是RESTful风格的。这里Remote API是通过程序与Docker进行集成和交互的核心内容。 Docker Remote API是由Docker守护进程提供的。默认情况下,Docker守护进程会绑定到一个所在宿主机的套接字:unix:///v

linux dlopen手册翻译

名称 dlclose, dlopen, dlmopen 打开和关闭一个共享对象 简介 #include <dlfcn.h>void *dlopen(const char*filename, int flags);int dlclose(void *handle);#define _GNU_SOURCE#include <dlfcn.h>void *dlmoopen(Lmid_t lm

从计组中从重温C中浮点数表示及C程序翻译过程

目录 移码​编辑  传统浮点表示格式 浮点数的存储(ieee 754)->修炼内功 例子:   ​编辑 浮点数取的过程   C程序翻译过程 移码  传统浮点表示格式 浮点数的存储(ieee 754)->修炼内功 根据国际标准IEEE(电⽓和电⼦⼯程协会)  32位 例子:    64位    IEEE754对有效数字M和

List list = new ArrayList();和ArrayList list=new ArrayList();的区别?

List是一个接口,而ArrayList 是一个类。 ArrayList 继承并实现了List。 List list = new ArrayList();这句创建了一个ArrayList的对象后把上溯到了List。此时它是一个List对象了,有些ArrayList有但是List没有的属性和方法,它就不能再用了。而ArrayList list=new ArrayList();创建一对象则保留了A