翻译《The Old New Thing》 - The new scratch program

news2025/1/16 13:44:45

7a192c04fb484e14ba672bbba3d9d7b8.png

The new scratch program - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20050422-08/?p=35813

Raymond Chen 2005年4月22日


译注:此篇是 翻译《The Old New Thing》 - The scratch program 姊妹篇,对 scratch 程序作作了升级,采用了现代 C++ 编程风格,避免了全局状态,并通过虚函数和基类指针提供了扩展性。

 

         我认为是时候更新我们过去一年来一直在使用的 scratch 程序了。我听说有一种叫做 C++ 的新语言,它很快就会变得非常流行,所以让我们也来跟风吧!

#define STRICT
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <windowsx.h>
#include <ole2.h>
#include <commctrl.h>
#include <shlwapi.h>
#include <shlobj.h>
#include <shellapi.h>
HINSTANCE g_hinst;
class Window
{
public:
 HWND GetHWND() { return m_hwnd; }
protected:
 virtual LRESULT HandleMessage(
                         UINT uMsg, WPARAM wParam, LPARAM lParam);
 virtual void PaintContent(PAINTSTRUCT *pps) { }
 virtual LPCTSTR ClassName() = 0;
 virtual BOOL WinRegisterClass(WNDCLASS *pwc)
     { return RegisterClass(pwc); }
 virtual ~Window() { }
 HWND WinCreateWindow(DWORD dwExStyle, LPCTSTR pszName,
       DWORD dwStyle, int x, int y, int cx, int cy,
       HWND hwndParent, HMENU hmenu)
 {
  Register();
  return CreateWindowEx(dwExStyle, ClassName(), pszName, dwStyle,
                  x, y, cx, cy, hwndParent, hmenu, g_hinst, this);
 }
private:
 void Register();
 void OnPaint();
 void OnPrintClient(HDC hdc);
 static LRESULT CALLBACK s_WndProc(HWND hwnd,
     UINT uMsg, WPARAM wParam, LPARAM lParam);
protected:
 HWND m_hwnd;
};
void Window::Register()
{
    WNDCLASS wc;
    wc.style         = 0;
    wc.lpfnWndProc   = Window::s_WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = g_hinst;
    wc.hIcon         = NULL;
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = ClassName();
    WinRegisterClass(&wc);
}
LRESULT CALLBACK Window::s_WndProc(
               HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
 Window *self;
 if (uMsg == WM_NCCREATE) {
  LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
  self = reinterpret_cast<Window *>(lpcs->lpCreateParams);
  self->m_hwnd = hwnd;
  SetWindowLongPtr(hwnd, GWLP_USERDATA,
            reinterpret_cast<LPARAM>(self));
 } else {
  self = reinterpret_cast<Window *>
            (GetWindowLongPtr(hwnd, GWLP_USERDATA));
 }
 if (self) {
  return self->HandleMessage(uMsg, wParam, lParam);
 } else {
  return DefWindowProc(hwnd, uMsg, wParam, lParam);
 }
}
LRESULT Window::HandleMessage(
                          UINT uMsg, WPARAM wParam, LPARAM lParam)
{
 LRESULT lres;
 switch (uMsg) {
 case WM_NCDESTROY:
  lres = DefWindowProc(m_hwnd, uMsg, wParam, lParam);
  SetWindowLongPtr(m_hwnd, GWLP_USERDATA, 0);
  delete this;
  return lres;
 case WM_PAINT:
  OnPaint();
  return 0;
 case WM_PRINTCLIENT:
  OnPrintClient(reinterpret_cast<HDC>(wParam));
  return 0;
 }
 return DefWindowProc(m_hwnd, uMsg, wParam, lParam);
}
void Window::OnPaint()
{
 PAINTSTRUCT ps;
 BeginPaint(m_hwnd, &ps);
 PaintContent(&ps);
 EndPaint(m_hwnd, &ps);
}
void Window::OnPrintClient(HDC hdc)
{
 PAINTSTRUCT ps;
 ps.hdc = hdc;
 GetClientRect(m_hwnd, &ps.rcPaint);
 PaintContent(&ps);
}
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();
private:
 HWND m_hwndChild;
};
LRESULT RootWindow::OnCreate()
{
 return 0;
}
LRESULT RootWindow::HandleMessage(
                          UINT uMsg, WPARAM wParam, LPARAM lParam)
{
 switch (uMsg) {
  case WM_CREATE:
   return OnCreate();
  case WM_NCDESTROY:
   // Death of the root window ends the thread
   PostQuitMessage(0);
   break;
  case WM_SIZE:
   if (m_hwndChild) {
    SetWindowPos(m_hwndChild, NULL, 0, 0,
                 GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
                 SWP_NOZORDER | SWP_NOACTIVATE);
   }
   return 0;
  case WM_SETFOCUS:
   if (m_hwndChild) {
    SetFocus(m_hwndChild);
   }
   return 0;
 }
 return __super::HandleMessage(uMsg, wParam, lParam);
}
RootWindow *RootWindow::Create()
{
 RootWindow *self = new RootWindow();
 if (self && self->WinCreateWindow(0,
       TEXT("Scratch"), WS_OVERLAPPEDWINDOW,
       CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
       NULL, NULL)) {
      return self;
  }
 delete self;
 return NULL;
}
int PASCAL
WinMain(HINSTANCE hinst, HINSTANCE, LPSTR, int nShowCmd)
{
 g_hinst = hinst;
 if (SUCCEEDED(CoInitialize(NULL))) {
  InitCommonControls();
  RootWindow *prw = RootWindow::Create();
  if (prw) {
   ShowWindow(prw->GetHWND(), nShowCmd);
   MSG msg;
   while (GetMessage(&msg, NULL, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
   }
  }
  CoUninitialize();
 }
 return 0;
}

        这个程序的基本思想与我们旧的临时程序相同,但现在它有了新鲜的柠檬味 C++ 气息。我们不是在全局变量中保存状态,而是声明了一个 C++ 类并将其与窗口关联起来。

        为了简单起见,对象的生命周期与窗口本身绑定在一起。

        首先,有一个基本的 Window 类,我们将把它作为我们未来任何“与窗口关联的类”工作的基类。

        目前唯一的派生类是 RootWindow,这是顶级框架窗口,目前是程序使用的唯一窗口。

        你可能已经猜到,随着需求的出现,我们以后可能会有其他派生类。

   WinRegisterClass 方法之所以是虚拟的(并且没有做任何有趣的事情),是为了让派生类可以修改注册类时使用的 WNDCLASS

        我目前没有立即需要它,但如果我需要,拿来就能用。

        我们使用 GWLP_USERDATA 窗口长指针来存储关联类的指针,从而允许我们从窗口句柄中恢复对象。

        请注意,在 RootWindow::HandleMessage 方法中,我使用了 Visual C++ 的 __super 扩展。如果你不想依赖非标准扩展,你可以改为编写:

class RootWindow : public Window {
public:
 typedef Window super;
 ...(其余代码)
}

并使用 super 代替 __super

这个程序本身没有做什么有趣的事情;它只是未来示例的一个框架。

 

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

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

相关文章

【通信】电子科协通信专题

数字通信 最直观的通信方式-基带通信 问题&#xff1a;①无限大的带宽②天线体积

[QTcreator]QT中一个cpp文件如何使用另一个界面的控件

在工作过程中将函数封装成一个类放入一个cpp文件中&#xff0c;但是里面的函数需要运用到其他界面的控件&#xff0c;以此记录昨天的学习。 首先明确一下我需要在vtkfuntion.cpp使用mainwindow.ui中的qvtkwidget控件 step1:更改mainwindow.h 添加需要应用的文件的头文件&…

python:画饼图

我现在因工作需要在写一篇中文文章&#xff0c;领导要我用python处理数据和画图&#xff0c;那我也刚好学习一下python画图。 import matplotlib.pyplot as plt # 饼图数据 labels [A, B, C, D] sizes [15, 30, 45, 10] # 每个部分的大小 # 绘制饼图 plt.figure(figsize(6,…

Spring Web MVC 快速入门

&#x1f3a5; 个人主页&#xff1a;Dikz12&#x1f525;个人专栏&#xff1a;Spring学习之路&#x1f4d5;格言&#xff1a;吾愚多不敏&#xff0c;而愿加学欢迎大家&#x1f44d;点赞✍评论⭐收藏 目录 什么是Spring MVC&#xff1f; MVC模式介绍 ​编辑学习Spring MVC…

开源数据可视化大屏对接表单数据实践!

如果你需要一个表单系统&#xff0c;进行数据收集&#xff1b;可以使用tduck填鸭进行私有化部署&#xff0c;进行表单制作&#xff0c;完成数据收集。 在实际业务中&#xff0c;往往需要将收集的数据进行展示或分析&#xff1b;此时就可以使用表单数据推送到TReport中&#xf…

详细解读性能测试指标(性能指标、CPU、内存、负载、磁盘)

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 性能测试指标是衡量系统性能的评价标准&#xff0c;常用的系统性…

remmina无法连接远程桌面,Remmina无法连接远程桌面的原因与解决办法

在解决Remmina无法连接远程桌面的问题时&#xff0c;我们需要考虑多种可能的原因&#xff0c;并采取相应的解决办法。以下是一些常见的原因及其对应的解决方案&#xff1a; 1、网络问题 原因&#xff1a;不稳定的网络连接或中断可能导致无法建立远程桌面连接。 解决办法&#x…

环保设备统一管理系统

在环保意识日益增强的今天&#xff0c;企业如何有效管理环保设备&#xff0c;确保其正常运行&#xff0c;减少环境污染&#xff0c;成为了一个重要议题。HiWoo Cloud平台以其独特的环保设备统一管理系统&#xff0c;为企业提供了一套完整的解决方案&#xff0c;帮助企业实现绿色…

量化地形处理

1: 量化地形切片&#xff1a;GDAL查询数据&#xff1b;CTB算法转mesh&#xff1b;高度图需要和周围高度图边界做高度融合&#xff0c;四顶点需要做平均值融合&#xff1b;法线想要在前端显示正确必须将mesh坐标转为4326或者3857&#xff1b; 这个使用开源即可&#xff1a;cesi…

肖特基二极管 SOD-123HE封装 散热性好

肖特基二极管发热问题&#xff0c;一直是众多电子工程师常讨论的话题之一。在实际应用中&#xff0c;肖特基二极管发热量真地不容忽视&#xff0c;其发热量大小和实际工作电流和压降大小有关。针对肖特基二极管发热问题&#xff0c;二三极管厂家东沃电子DOWOSEMI有几点建议&…

怎么编辑百度百科个人词条

辑百度百科个人词条是一个相对复杂的过程&#xff0c;需要遵循一定的步骤和规则。以下是百科优化网整理的编辑百度百科个人词条的步骤和注意事项。 1. 确定编辑资格 百度百科个人词条的编辑权主要赋予那些具有一定影响力的公众人物&#xff0c;或者是有一定“身份”的人物&…

STM32 GPIO介绍

每个GPI/O端口有两个32位配置寄存器(GPIOx_CRL&#xff0c; GPIOx_CRH)&#xff0c;两个32位数据寄存器 (GPIOx_IDR和GPIOx_ODR)&#xff0c;一个32位置位/复位寄存器(GPIOx_BSRR)&#xff0c;一个16位复位寄存器(GPIOx_BRR)和一个32位锁定寄存器(GPIOx_LCKR)。 通过软件配置寄…

idea修改maven项目名称及子模块名称

一、修改目录名称 shift F6修改目录&#xff0c;选择“rename module and dictionary”。![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/43efd9c6af6e43ad9656455db94b37a2.png)二、修改子项目pom的 三、修改父项目pom的 四、刷新maven项目

SpringBoot:SpringBoot:实战项目TILAS智能学习辅助系统1.3

登录认证 需求:输入登录请求服务器判断用户的用户名和密码 //控制层 PostMapping("/login")public Result login(RequestBody Emp emp);Overridepublic Result login(Emp emp) {Emp emp1 empService.selectLogin(emp);if(emp1 null){System.out.println("用…

企业百度百科词条怎么修改

在进行企业百度百科词条的修改前&#xff0c;首先需要做好以下准备&#xff1a; 注册并登录百度账号&#xff1a;只有注册并登录了百度账号&#xff0c;你才能进行词条的编辑和修改。 熟悉百度百科编辑规则&#xff1a;了解百度百科的编辑规则&#xff0c;包括内容要求、格式规…

思通数科大模型在智能数据查询系统中的深度应用:销售数据分析的革新

在企业决策支持系统中&#xff0c;销售数据分析占据着举足轻重的地位。思通数科的大模型技术&#xff0c;结合自然语言处理&#xff08;NLP&#xff09;和机器学习&#xff0c;为智能数据查询系统提供了强大的分析能力。本文将详细描述思通数科大模型在销售数据分析中的应用&am…

2020 年国考【计算机专业】真题及答案

真题及答案 第一部分数学基础课程 一、&#xff08;共 5 分&#xff09;用逻辑符号表达下列语句&#xff08;论域为包含一切事物的合集&#xff09; &#xff08;2 分&#xff09;确诊者并不都有症状&#xff08;注&#xff1a;需给出两种形式表达, 一种用存在量词, 一种用全称…

ASP.NET小型证券术语解释及翻译系统的设计与开发

摘 要 在系统设计上&#xff0c;综合各种翻译类型网站优缺点&#xff0c;设计出具有任何使用者都可添加术语信息的且只有管理员能够实现术语修改及删除等独特方式的术语查看管理系统。此方式能够使术语量快速增大&#xff0c;并且便于使用者及管理员操作&#xff0c;满足相互…

J1019基于SpringBoot的护肤品推荐系统设计与实现(源码+包运行+技术指导)

项目描述 临近学期结束&#xff0c;开始毕业设计制作&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉的困难吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。今天给大家介绍一篇基于SpringBoot的护…

万用板是什么?和印刷电路板一样吗?

同学们大家好&#xff0c;今天我们继续学习杨欣的《电子设计从零开始》&#xff0c;这本书从基本原理出发&#xff0c;知识点遍及无线电通讯、仪器设计、三极管电路、集成电路、传感器、数字电路基础、单片机及应用实例&#xff0c;可以说是全面系统地介绍了电子设计所需的知识…