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

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

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

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于51单片机的倒计时系统

基于51单片机的倒计时设计 &#xff08;仿真&#xff0b;程序&#xff0b;设计报告&#xff09; 功能介绍 具体功能&#xff1a; 1.六位LED显示&#xff0c;从59分59秒99开始倒计时&#xff1b; 2.倒计时精度为0.01秒&#xff0c;能正确地进行倒计时&#xff1b; 3.复位后…

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

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

OpenAI 震撼发布:GPT-4o免费,实时语音视频交互开启新纪元

OpenAI 震撼发布&#xff1a;GPT-4o免费&#xff0c;实时语音视频交互开启新纪元 在仅仅问世17个月后&#xff0c;OpenAI 研制出了仿佛科幻片中登场的超级人工智能——GPT-4o&#xff0c;而且所有人都可以完全免费使用&#xff0c;让这个科技界的巨浪让人震撼无比&#xff01;…

【CSP CCF记录】202009-1 称检测点查询

题目 过程 难点&#xff1a;编号和位置的一一对应&#xff0c;不同位置的距离可能相等。 所以使用一个结构体记录不同检测点的编号和到居民地的距离。 sort函数进行排序。Sort函数使用方法 参考&#xff1a;http://t.csdnimg.cn/Y0Hpi 代码 #include <bits/stdc.h>…

大华智能物联综合管理平台 fastjson反序列化漏洞

文章目录 免责声明漏洞描述漏洞原理影响版本漏洞复现修复建议 免责声明 本文章仅供学习与交流&#xff0c;请勿用于非法用途&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任 漏洞描述 大华智慧园区综合管理平台是一个集智能化、信息化、网络化、安全…

JavaEE初阶-多线程进阶2

文章目录 前言一、CAS1.1 CAS的概念1.2 原子类1.3 CAS的ABA问题 二、JUC中常用类2.1 Callable接口2.2 ReentrantLock&#xff08;可重入&#xff09;2.3 Semaphore信号量2.4 CountDownLatch类2.5 CopyOnWriteArrayList类2.6 ConcurrentHashMap 前言 对于多线程进阶的部分&…

大型语言模型自我进化综述

24年4月来自北大的论文“A Survey on Self-Evolution of Large Language Models”。 大语言模型&#xff08;LLM&#xff09;在各个领域和智体应用中取得了显着的进步。 然而&#xff0c;目前从人类或外部模型监督中学习的LLM成本高昂&#xff0c;并且随着任务复杂性和多样性的…

嵌入式学习第三十三天!(二叉树)

1. 树的概念&#xff1a; 1. 树&#xff1a;由n个结点组成的有限集&#xff0c;有且只有一个根结点&#xff08;由根结点可以访问后继结点&#xff09;&#xff0c;其他结点只有一个前驱结点&#xff0c;但可以有多个后继结点&#xff08;一对多&#xff09;。当n 0时&#xf…

unordered_map 和 unordered_set

unordered —— 无序的&#xff0c;从表面上来看&#xff0c;与 map 和 set 不同之处就在于&#xff0c;unordered_map 和 unordered_set 无法保证插入数据是有序的&#xff1b; 尽管如此&#xff0c;由于这两种容器内部封装了“哈希桶”&#xff0c;可以实现快速查找数据 ——…

EE trade:投资贵金属的技巧

投资贵金属&#xff0c;特别是流行的黄金和白银&#xff0c;需要一个明智的策略和一些重要的技巧。以下是一些有用的投资技巧&#xff1a; 进行市场研究&#xff1a;在投资前了解市场运行机制、价格波动因素以及可能影响市场的宏观经济指标。 理解供需关系&#xff1a;贵金属…

历史影像的下载办法总结

最近想要下黄河口的历史影像&#xff0c;试验了几个办法&#xff1a; 1&#xff09;参考文献1中的办法&#xff0c;用Global Mapper下载World Imagery Wayback网站的历史数据&#xff0c;能下载从2014年至现在的&#xff1b; 2&#xff09;参考文献1中的办法&#xff0c;用SA…

2024淘宝天猫618凑单跨店满300减多少及618红包领取口令是什么?

2024年天猫618购物狂欢节全攻略 随着夏日的脚步临近&#xff0c;一年一度的天猫618年中大促也即将拉开帷幕。作为年中最大的购物狂欢节&#xff0c;天猫618不仅汇聚了众多优质商品&#xff0c;还准备了丰富的优惠活动和红包福利&#xff0c;让消费者在享受购物乐趣的同时&…

LeetCode1657确定两个字符串是否接近

题目描述 如果可以使用以下操作从一个字符串得到另一个字符串&#xff0c;则认为两个字符串 接近 &#xff1a; 操作 1&#xff1a;交换任意两个 现有 字符。例如&#xff0c;abcde -> aecdb操作 2&#xff1a;将一个 现有 字符的每次出现转换为另一个 现有 字符&#xff0…

如何做好图纸加密

在工业设计领域&#xff0c;图纸无疑是企业最宝贵的资产之一&#xff0c;其中包含了大量的创新思想、独特设计和商业秘密。然而&#xff0c;随着信息技术的发展和应用的普及&#xff0c;图纸防泄密工作面临着前所未有的挑战。因此&#xff0c;如何有效地防止图纸泄密&#xff0…

QCC---Aptx Lossless验证

因为aptx Lossless属于高通骁龙声音的一部分&#xff0c;一般支持高通骁龙声音的设备会支持到&#xff0c;比如说手机&#xff0c;而且还要支持最新的aptx adaptive协议R2.2版本。但是如果手上没有这样的手机的话&#xff0c;有source芯片也可以去做测试验证。在最新的784.1版本…

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

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

品牌出海新趋势:掌握“微创新”策略,快速适应海外市场

在全球化的今天&#xff0c;品牌出海已成为众多企业拓展业务、实现国际化发展的重要途径。然而&#xff0c;海外市场与本土市场在文化、消费习惯、法律法规等方面均存在显著差异&#xff0c;这要求品牌在海外市场中必须灵活应变&#xff0c;通过微小的、有针对性的创新来快速适…

idea配置MySQL提示

点击sql语句&#xff0c;然后再选择show context actions 然后再选择Inject language or reference 然后再选择MySQL 然后我们会发现sql语句变颜色了 如果表是红色 那么需要我们连接mysql的对于的数据库

478.8-480W 宽电压输入 AC/DC 导轨式开关电源——TPR/SDR-480-XS 系列

TPR/SDR-480-XS 系列导轨式开关电源&#xff0c;额定输出功率为478.8-480W&#xff0c;产品输入范围&#xff1a;85-264VAC。提供24V、36V、48V输出&#xff0c;具有短路保护&#xff0c;过载保护等功能&#xff0c;并具备高效率&#xff0c;高可靠性、高寿命、更安全、更稳定等…

BGP—边界网关协议

BGP 动态路由协议可以按照工作范围分为IGP以及EGP。IGP工作在同一个AS内&#xff0c;主要用来发现和计算路由&#xff0c;为AS内提供路由信息的交换&#xff1b;而EGP工作在AS与AS之间&#xff0c;在AS间提供无环路的路由信息交换&#xff0c;BGP则是EGP的一种。 BGP是一…