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

news2025/1/21 12:20:46

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方法直接绘制到屏幕上,而不是绘制到离屏位图。

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

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1673871.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

四川易点慧电商抖音小店:优势尽显,引领电商新潮流

在当下这个信息爆炸、消费模式日新月异的时代&#xff0c;电商行业正在经历一场前所未有的变革。四川易点慧电商抖音小店凭借其独特的优势&#xff0c;成功吸引了大量消费者的目光&#xff0c;成为电商领域的一股新势力。 四川易点慧电商抖音小店的最大优势在于其强大的品牌影…

安装adobe系列,提示错误代码146解决办法

安装Adobe系列产品如PS、PR、Lrc等产品时&#xff0c;会因为各种各样的错误导致安装失败&#xff01;今天小编为大家带来的是安装adobe系列&#xff0c;提示错误代码146解决办法&#xff0c;收藏起来吧&#xff01; 方法一&#xff1a;就是传说中的万能大法&#xff0c;关机重启…

eBay自养买家号测评攻略:如何稳定提升账号权重?

eBay账号的重要程度对应测评来说是不言而喻的&#xff0c;有的账号第一天注册&#xff0c;第二天就被封&#xff0c;或者一下单就封&#xff0c;如何养成稳定的买家号是大家都在思考的问题&#xff0c;那下面就来讲解eBay测评都是怎么来养稳定买家号的。 一、账号注册后的注意…

娱乐营销的新玩法:Kompas.ai如何让内容更加趣味化

在数字化时代&#xff0c;内容营销已成为品牌与消费者沟通的重要桥梁。然而&#xff0c;随着信息的爆炸式增长&#xff0c;用户的注意力越来越分散&#xff0c;传统的营销方式已经难以吸引用户的兴趣。在这种背景下&#xff0c;娱乐营销应运而生&#xff0c;它通过将娱乐元素融…

抖音API数据接口在电商中的应用与影响

抖音是一款短视频应用&#xff0c;在电商领域具有广泛的应用和影响。以下是抖音API在电商中的应用与影响&#xff1a; 广告推广&#xff1a;抖音API可以让电商平台将自己的广告内容嵌入到抖音用户的视频流中&#xff0c;从而提高品牌知名度和推广效果。商品展示&#xff1a;通过…

华为OD机试 - 测试用例执行计划(Java 2024 C卷 100分)

华为OD机试 2024C卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测试…

《控制系统实验与综合设计》自控第一次(含程序和题目)

实验一 零极点对系统性能的影响 一、实验完成任务 1、理解并分析传递函数零、极点的动态性质 2、进行理论值计算 3、利用MATLAB编写程序&#xff0c;得出实验结果 4、将计算所得的理论值与实验结果对比并分析 二、实验内容 &#xff08;1&#xff09;分析有零点系统的阶…

Linux 多进程开发

0、程序和进程 程序 是包含一系列信息的文件&#xff0c;这些信息描述了如何在运行时创建一个进程。 进程 是正在运行的程序的实例。是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。 1、区别 程序是静态的&#xff0c;进程是动态的&#xff0c;程序是存储在某…

httpsok-v1.11.0支持CDN证书自动部署

&#x1f525;httpsok-v1.11.0支持CDN证书自动部署 介绍 httpsok 是一个便捷的 HTTPS 证书自动续签工具&#xff0c;专为 Nginx 、OpenResty 服务器设计。已服务众多中小企业&#xff0c;稳定、安全、可靠。 一行命令&#xff0c;一分钟轻松搞定SSL证书自动续期 v1.11.0 版…

《控制系统实验与综合设计》自控第二次(含程序和题目)

实验五 二阶系统的瞬态响应 一、实验完成任务 1、测试在不同阻尼比的条件下单位阶跃响应曲线&#xff0c;并进行其他动态性能指标测量。 2、通过调节开环增益得到相应K值&#xff0c;并进行其他动态性能指标测量。 3、在阻尼比一定时&#xff0c;测试角频率不同时的单位阶跃…

石墨烯材料商汉烯科技授权世强硬创,代理产品具备高导热/导电特点

近日&#xff0c;武汉汉烯科技有限公司&#xff08;下称“汉烯科技”&#xff0c;英文&#xff1a;HANXI TECH&#xff09;与世强先进&#xff08;深圳&#xff09;科技股份有限公司&#xff08;下称“世强先进”&#xff09;达成授权代理合作&#xff0c;面向锂电新能源、电子…

【数据结构】解密链表之旅(单链表篇)

前言 哈喽大家好&#xff0c;我是野生的编程萌新&#xff0c;首先感谢大家的观看。数据结构的学习者大多有这样的想法&#xff1a;数据结构很重要&#xff0c;一定要学好&#xff0c;但数据结构比较抽象&#xff0c;有些算法理解起来很困难&#xff0c;学的很累。我想让大家知道…

GPT-4o--真AI助手来临,可免费使用!

​ 今天凌晨&#xff0c;OpenAI又双缀缀发大招了&#xff0c;直接放出新的模型–GPT-4o&#xff0c;并号称可以实时对音频、视觉和文本进行推理。现场直播效果非常炸裂&#xff0c;能听、说、看&#xff0c;而且几乎没有延迟。 在GPT-4o出来以前&#xff0c;GPT也有语音对话功…

win10共享文件夹到ubuntu22

win10共享文件夹 新建用户 新建用户、设置密码。避免共享给EveryOne&#xff0c;导致隐私问题。 点击左下角的开始菜单&#xff0c;选择“设置”&#xff08;WinI&#xff09;打开设置窗口。在设置窗口中&#xff0c;搜索或直接点击“账户”进入账户设置。在账户设置中&…

【全开源】多功能投票小程序支持微信公众号+微信小程序+H5(源码搭建/上线/运营/售后/维护更新)

介绍 多功能投票小程序是一款基于FastAdminThinkPHPuniapp开发的一款多功能投票小程序。 ​用户友好与便捷性&#xff1a; 投票小程序界面简洁直观&#xff0c;操作简便&#xff0c;用户无需下载和安装额外的应用&#xff0c;即可在微信或其他平台上直接使用&#xff0c;大大提…

直线道路线通过霍夫变换进行识别并画出

最近在研究高速直线识别&#xff0c;搜了一圈看了很多文章&#xff0c;确定了以下的主要流程。 霍夫变换 lines cv2.HoughLinesP(image,rho,theta,threshold,lines,minLineLength,maxLineGap)#概率霍夫变换 image:必须是二值图像&#xff0c;推荐使用canny边缘检测的结果图像…

C语言笔记14

指针1 在C语言中给内存单元的编号起了个名字叫做指针&#xff0c;通俗来说就是地址。&#xff08;内存单元编号地址指针&#xff09; 1.指针变量与地址 int a10&#xff1b; int* p&a&#xff1b; * 说明了这里p的是指针变量&#xff1b;int*说明p是一个整形指针&…

【class2】人工智能初步(自然语言处理)

要实现从评价中提取高频关键词&#xff0c;并判别其正负面性&#xff0c;其实是通过人工智能领域中的一个分支&#xff1a;自然语言处理。 在了解自然语言处理之前&#xff0c;我们先来说说&#xff0c;什么是自然语言&#xff08;Natural Language&#xff09;&#xff1f;自…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-15.1,2,3-GPIO中断控制实验

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

全自动发布小红薯思维导图笔记(附爆款AI提示词)

全自动电脑接管&#xff0c;帮你生成图片、文案&#xff0c;然后还帮你自动发布。 大家好&#xff0c;我是大胡子&#xff0c;专注于研究RPA实战与解决方案&#xff0c;今天来介绍一款全自动生产内容并发布小红薯的神器&#xff0c;最后附有AI提示词&#xff0c;记得收藏点赞…