MFC 视图窗口

news2024/11/20 19:43:02

目录

视图窗口概述

视图窗口的使用

视图窗口创建流程

命令消息 WM_COMMAND 处理顺序

对象关系


视图窗口概述

作用:提供了一个用于显示数据的窗口

关于视图窗口

  • 视图类是用来展示用户,文档类是用来存储和管理数据
  • 视图窗口是覆盖掉框架窗口的客户区
  • 视图窗口是框架窗口的子窗口,它的创建应该是在框架窗口的WM_CREATE消息处理中
  • 每个窗口都有自己消息映射机制,处理属于自己的消息
  • 所有消息中,只有命令消息 WM_COMMAND 是可以被多个类处理的,系统消息,自定义消息只能由对应的窗口处理

框架窗口的消息映射机制:CMyFrameWnd---CFrameWnd---CWnd

视图窗口的消息映射机制:CMyView---CView---CWnd

视图窗口的使用

如何使用?

  • 定义一个自己的视图类(CMyView) ,派生自Cview,并重写父类成员纯虚函数OnDraw(可以用于绘图)
  • 其余框架类和应用程序类代码不变。
  • 在处理框架窗口的WM_CREATE消息时,定义CMyView类对象,并调用Create函数创建视图窗口。

在框架窗口的 WM_CREATE 消息处理函数中创建

int CMyFrameWnd::OnCreate(LPCREATESTRUCT pcs) {
	CMyView* pView = new CMyView;
	pView->Create(NULL, "MFCView", WS_CHILD | WS_VISIBLE | WS_BORDER, CRect(0, 0, 200, 200), this,
		AFX_IDW_PANE_FIRST);
	this->m_pViewActive = pView;
	return CFrameWnd::OnCreate(pcs);
}

WS_CHILD, WS_VISIBLEWS_BORDER 是窗口风格(Window Style)的标志,用于指定窗口的样式和行为。

  • WS_CHILD 表示该窗口是一个子窗口,它位于父窗口内部,并随父窗口的移动和调整大小而相应变化。
  • WS_VISIBLE 表示该窗口是可见的,即在创建后立即显示在屏幕上。
  • WS_BORDER 表示该窗口有一个边框,用于提供视觉上的分隔和装饰

 AFX_IDW_PANE_FIRST:添加之后,视图窗口就会完全覆盖掉框架窗口的客户区。如果客户由多个视图窗口的话,其他视图窗口的创建函数AFX_IDW_PANE_FIRST+1……即可。

但是多个视图窗口中只能由一个是激活窗口。

想要创建成功需要重写纯虚函数,这个纯虚函数是在父类 CVIEW 中的,父类有纯虚函数,所以是抽象类,子类继承父类也是抽象类。所以需要重写纯虚函数才能成功创建

void CMyView::OnDraw(CDC* pDC) {
	pDC->TextOut(100, 100, "CMyView::OnDraw");
}

在未处理WM_PAINT消息时,这个函数是由父类来调用的处理的

这个是调用父类的消息处理函数 

void CView::OnPaint()
{
	// standard paint routine
	CPaintDC dc(this);
	OnPrepareDC(&dc);
	OnDraw(&dc);
}

这个函数的功能和处理函数WM_PAINT功能是一样的

void CMyView::OnPaint() {
	PAINTSTRUCT ps = { 0 };
	HDC hdc = ::BeginPaint(this->m_hWnd, &ps);
	::TextOut(hdc, 200, 200, "CMyView::OnPaint", strlen("CMyView::OnPaint"));
	::EndPaint(this->m_hWnd, &ps);
}

如果重写了WM_PAINT消息,就不会再调用重写的虚函数了,优先交给WM_PAINT消息处理函数处理。

视图窗口创建流程

下断点分析

进入这个函数

熟悉的窗口结构体

创建之前的窗口处理函数,(1)注册窗口(2)更改cs未空的成员

埋个钩子,对WM_CREATE消息感兴趣,保存对象到全局变量程序线程信息,并且在钩子回调函数绑定句柄与对象

视图窗口的创建与框架窗口的创建是一样的

命令消息 WM_COMMAND 处理顺序

给 CMyApp,CMyFrameWnd,CMyView三个添加 WM_COMMAND 消息处理函数

#include <afxwin.h>
#include "resource.h"


class CMyView : public CView {
	DECLARE_MESSAGE_MAP()
public:
	void OnDraw(CDC* pDC);
	afx_msg void OnPaint();
	afx_msg void OnNew();
};
BEGIN_MESSAGE_MAP(CMyView, CView)
	ON_COMMAND( ID_NEW, OnNew )
	ON_WM_PAINT()
END_MESSAGE_MAP()
void CMyView::OnNew() {
	AfxMessageBox("视图类处理了WM_COMMAND消息");
}
void CMyView::OnPaint() {
	PAINTSTRUCT ps = { 0 };
	HDC hdc = ::BeginPaint(this->m_hWnd, &ps);
	::TextOut(hdc, 200, 200, "CMyView::OnPaint", strlen("CMyView::OnPaint"));
	::EndPaint(this->m_hWnd, &ps);
}
void CMyView::OnDraw(CDC* pDC) {
	pDC->TextOut(100, 100, "CMyView::OnDraw");
}


class CMyFrameWnd : public CFrameWnd {
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnPaint();
	afx_msg int OnCreate(LPCREATESTRUCT pcs);
	afx_msg void OnNew();
};
BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
	ON_WM_PAINT()
	ON_COMMAND( ID_NEW, OnNew )
	ON_WM_CREATE()
END_MESSAGE_MAP()
void CMyFrameWnd::OnNew() {
	AfxMessageBox("框架类处理了WM_COMMAND消息");
}
int CMyFrameWnd::OnCreate(LPCREATESTRUCT pcs) {
	CMyView* pView = new CMyView;
	pView->Create(NULL, "MFCView", WS_CHILD | WS_VISIBLE | WS_BORDER, CRect(0, 0, 200, 200), this,
		AFX_IDW_PANE_FIRST);
	this->m_pViewActive = pView;
	return CFrameWnd::OnCreate(pcs);
}
void CMyFrameWnd::OnPaint() {
	PAINTSTRUCT ps = { 0 };
	HDC hdc = ::BeginPaint(this->m_hWnd, &ps);
	::TextOut(hdc, 100, 100, "我是框架窗口客户区", strlen("我是框架窗口客户区"));
	::EndPaint(this->m_hWnd, &ps);
}



class CMyWinApp : public CWinApp {
	DECLARE_MESSAGE_MAP()
public:
	virtual BOOL InitInstance();
	afx_msg void OnNew();
};
BEGIN_MESSAGE_MAP(CMyWinApp, CWinApp)
	ON_COMMAND(ID_NEW, OnNew)
END_MESSAGE_MAP()
void CMyWinApp::OnNew() {
	AfxMessageBox("应用程序类处理了WM_COMMAND消息");
}
BOOL CMyWinApp::InitInstance() {
	CMyFrameWnd* pFrame = new CMyFrameWnd;
	pFrame->Create(NULL, "MFCView", WS_OVERLAPPEDWINDOW, CFrameWnd::rectDefault,
		NULL, (CHAR*)IDR_MENU1);
	this->m_pMainWnd = pFrame;
	pFrame->ShowWindow(SW_SHOW);
	pFrame->UpdateWindow();
	return TRUE;
}
CMyWinApp theApp;

可以知道 WM_COMMADN 消息处理的顺序:视图类---框架类---应用程序类

值得一提的是,this->m_pViewActive = pView;  激活当前视图窗口,否则需要先点击以下视图窗口,才能点击 文件--新建。

对象关系

CMyApp 应用程序类是全局的,有一个成员变量,保存了CMyFrameWnd对象地址

CMyFrameWnd对象有一个成员变量保存了 CMyView 对象的地址

也就说说拿到了CMyApp就可以拿到所有对象。

注意:this->m_pViewActive = pView; 还可以激活当前窗口

把这句代码注释掉对比以下:

没有点击视图窗口,点击  文件--新建,是框架类处理的命令消息

点击视图窗口,点击  文件--新建,是视图类处理的命令消息

添加上后,点击  文件--新建,是视图类处理的命令消息

这句代码可以直接把这个窗口设置为激活状态。

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

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

相关文章

【错误记录/js】保存octet-stream为文件后数据错乱

目录 说在前面场景解决方式其他 说在前面 后端&#xff1a;go、gin浏览器&#xff1a;Microsoft Edge 120.0.2210.77 (正式版本) (64 位) 场景 前端通过点击按钮来下载一些文件&#xff0c;但是文件内容是一些非文件形式存储的二进制数据。 后端代码 r : gin.Default()r.Stat…

算法学习——动态规划

动态规划 什么是动态规划动态规划的解题步骤动态规划应该如何debug 斐波那契数思路确定dp数组以及下标的含义确定递推公式dp数组如何初始化确定遍历顺序举例推导dp数组 代码 爬楼梯思路代码 使用最小花费爬楼梯思路代码 不同路径思路代码 不同路径 II思路代码 整数拆分思路代码…

【机器学习】决策树

参考课程视频&#xff1a;https://www.icourse163.org/course/NEU-1462101162?tid1471214452 1 概述 样子&#xff1a; 2 分裂 2.1 分裂原则 信息增益 信息增益比 基尼指数 3 终止 & 剪枝 3.1 终止条件 无需分裂 当前节点内样本同属一类 无法分裂 当前节点内…

vue3+element plus组件库中el-carousel组件走马灯特效,当图片变动时下面数字也随着图片动态变化

1.效果图 2.html <section style"height:30%"><div class"left-img1-title"><img src"../assets/img/title.png"alt""srcset""><div class"text">回收垃圾数量</div></div>…

Linux操作系统基础(二)系统的基础设置

结合上一节内容&#xff0c;这一节就对一些常见的linux操作设置进行讲解&#xff0c;内容有限&#xff0c;只做引导和抛砖引玉。 一、输入法的安装和设置 Linux 中安装中文输入法的方法有很多&#xff0c;常用的有以下几种&#xff1a; 使用软件包管理器安装 大多数 Linux …

NFC读卡------ci522

1、NFC及卡片 NFC是近距离无线通讯技术&#xff0c;是一种非接触式识别和互联技术&#xff0c;可以在移动设备、消费类电子产品、PC和智能控件工具间进行近距离无线通信。NFC提供了一种简单、触控式的解决方案&#xff0c;可以让消费者简单直观地交换信息、访问内容与服务。 …

Multi-Drone based Single Object Tracking with Agent Sharing Network阅读笔记

Multi-Drone based Single Object Tracking with Agent Sharing Network阅读笔记 Abstract 搭载摄像头的无人机可以从更广阔的视角在空中动态跟踪目标&#xff0c;与静态摄像头或地面移动传感器相比具有优势。然而&#xff0c;由于外观变化和严重遮挡等多种因素&#xff0c;使…

基于电商场景的高并发RocketMQ实战-Broker高并发消息写入、读写队列原理分析

&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308; 【11来了】文章导读地址&#xff1a;点击查看文章导读&#xff01; &#x1f341;&#x1f341;&#x1f341;&#x1f341;&#x1f341;&#x1f341;&#x1f3…

Java研学-Servlet 基础

一 概述 1 介绍 Servlet&#xff08;Server Applet&#xff09;是Java Servlet的简称&#xff0c;称为小服务程序或服务连接器&#xff0c;用Java编写的服务器端程序&#xff0c;具有独立于平台和协议的特性&#xff0c;主要功能在于交互式地浏览和生成数据&#xff0c;生成动…

SpringMVC:SSM(Spring+SpringMVC+MyBatis)代码整理

文章目录 SpringMVC - 07SSM 框架代码整理一、准备工作1. 分析需求、准备数据库2. 新建一个项目&#xff0c;导入依赖&#xff1a;pom.xml3. 用 IDEA 连接数据库 二、MyBatis 层1. 外部配置文件&#xff1a;db.properties2. MyBatis 核心配置文件&#xff1a;mybatis-config.xm…

超级量化第10期私募大咖——线上分享总结

《掘金之心公众号&#xff1a;gnu_isnot_unix》前Citadel现自营交易与量化管理&#xff0c;分享热点&#xff0c;主观&#xff0c;量化交易内容。活在当下&#xff0c;终身学习 - 给在职却对未来始终迷茫的人的公众号。借此想告诉不断努力&#xff0c;对生活充满热情的读者们&a…

ARM 汇编语言知识积累

博文参考&#xff1a; arm中SP&#xff0c;LR&#xff0c;PC寄存器以及其它所有寄存器以及处理器运行模式介绍 arm平台根据栈进行backtrace的方法-腾讯云开发者社区-腾讯云 (tencent.com) 特殊功能寄存器&#xff1a; SP&#xff1a; 即 R13&#xff0c;栈指针&#xff0c;…

并发踩坑:list共享变量的addAll

背景&#xff1a; 某业务报错了&#xff0c;提示&#xff1a;Caused by: org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. Cause: java.util.ConcurrentModificationException 分析&#xff1a; 这是执行查询时报的 并发修改异常。大概逻辑…

【postgres】8、Range 类型

文章目录 8.17 Range 类型8.17.1 内置类型8.17.2 示例8.17.3 开闭区间8.17.4 无穷区间 https://www.postgresql.org/docs/current/rangetypes.html 8.17 Range 类型 Range 类型&#xff0c;可以描述一个数据区间&#xff0c;有明确的子类型&#xff0c;而且子类型应该能被排序…

【设计模式】RBAC 模型详解

其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、什么是 RBAC 呢&#xff1f; 二、RBAC 的组成 三、RBAC 的优缺点 3.1 优点&#xff1a; 3.2 缺点&#xff1a; 四、RBAC 的…

putty免密登录和跳转到winscp相同目录的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

51单片机的羽毛球计分器系统【含proteus仿真+程序+报告+原理图】

1、主要功能 该系统由AT89C51单片机LCD1602显示模块按键等模块构成。适用于羽毛球计分、乒乓球计分、篮球计分等相似项目。 可实现基本功能: 1、LCD1602液晶屏实时显示比赛信息 2、按键控制比赛的开始、暂停和结束&#xff0c;以及两位选手分数的加减。 本项目同时包含器件清…

OpenSSH升级指南:实战检验的步骤,有效加固服务器安全

在做服务器漏扫时我们经常会遇到有关于OpenSSH相关的安全漏洞&#xff0c;本文主要给大家介绍一下有关于OpenSSH的升级方法&#xff0c;小伙伴们可以参考一下流程&#xff0c;按步骤操作&#xff0c;但是过程中一定会遇到各种各样的问题&#xff0c;需要自行解决&#xff0c;这…

LangChain 33: LangChain表达语言LangChain Expression Language (LCEL)

LangChain系列文章 LangChain 实现给动物取名字&#xff0c;LangChain 2模块化prompt template并用streamlit生成网站 实现给动物取名字LangChain 3使用Agent访问Wikipedia和llm-math计算狗的平均年龄LangChain 4用向量数据库Faiss存储&#xff0c;读取YouTube的视频文本搜索I…

Verilog RAM/ROM的数据初始化

文章目录 一、初始化方式二、测试 FPGA设计中RAM和ROM作为存储器用来存储可变或不可变类型的数据。 ROM初始化一般是加载固定数据&#xff0c;RAM声明时默认为不定态数据&#xff0c;初始化时可以让数据为全1或者全0。 一、初始化方式 复位时按地址写入初值always (posedge cl…