MFC绘图

news2025/1/31 20:29:03

文章目录

  • 消息组成
  • 消息的作用
  • 获取消息
  • 翻译消息
  • 常见消息
    • WM_DESTROY
    • WM_SYSCOMMAND
  • 消息循环的阻塞
  • 发送消息
  • 字符串资源
  • 加速键资源
  • GDI绘图对象-画笔
  • 位图绘制
  • 文本绘制
  • 字体
  • 模式对话框
  • 动态库特点
  • 线程
    • 创建线程
  • 互斥
  • 事件
  • 信号量

消息组成

  • 窗口句柄
  • 消息ID
  • 消息的两个参数
  • 消息产生的时间
  • 消息产生时的鼠标位置

消息的作用

  • 当系统通知窗口工作时,就采用消息的方式派发给窗口
//显示窗口
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
//消息循环
MSG nMsg = {0}while(GetMessage(&nMsg,NULL,0,0)){
	TranslateMessage(&nMsg);
	DispatchMessage(&nMsg);
}
return 0;

获取消息

BOOL GetMessage(
	LPMSG lpMsg, //存取获取到的消息BUFF
	HWND hWnd, // 窗口句柄
	UINT wMsgFilterMin,//获取消息的最小ID
	UINT wMsgFilterMax,//获取消息的最大ID

)
  • lpMsg–当获取到的消息后,将消息的参数存放到MSG结构中
  • hWnd–获取到hWnd所指定窗口的消息
  • wMsgFilterMin和wMsgFilterMsx—只能获取到由他们指定的消息,如果都为0,则表示没有范围

翻译消息

TranslateMessage–翻译消息,按键消息,翻译成字符消息

BOOL TranslateMessage{
	CONST MSG * lpMsg;//要翻译的消息地址
}
  • 检查消息是否是按键的消息,如果不是按键消息,不做任何处理,继续执行。

常见消息

WM_DESTROY

  • 产生时间:窗口被销毁时的消息
  • 附带信息:wParam为0 lParam 为0
  • 一般用法:常用于在窗口被销毁之前,做相应的善后处理,例如资源、内存等

WM_SYSCOMMAND

  • 产生时间:当点击窗口的最大化,最小化,关闭等
  • 附带消息:wParam:具体点击的位置,例如关闭SC_CLOSE等 lParam:鼠标光标的位置,LOWORD(lParam);//水平位置 HIWORD(lParam);//垂直位置
  • 一般用法:常用在窗口关闭时,提示用户处理

消息循环的阻塞

在这里插入图片描述

while(1){
	if(PeekMessage(&nMsg,NULL,0,0,PM_NOREMOVE)){
		if(GetMessage(&nMsg,NULL,0,0)){
			TranslateMessage(&nMsg);
			DisPatchMessage(&nMsg);
		}
	}
}

发送消息

  • SendMessage–发送消息,会等候消息处理的结果
  • PostMessage–投递消息,消息发出后立刻返回并不会等候消息执行结果
BOOL SendMessage/PostMessage{
	HWND hWnd;//消息发送的目的窗口
	UINT msg;//消息ID
	WPARAM wParam;//消息参数
	LPARAM lParam;//消息参数
}

自定义消息:

  • 系统消息:0x000-0x03ff 由系统定义好的消息,可以在程序中直接使用
  • 用户自定义消息–ID范围(0x0400-0x7fff) 由用户自己定义,满足用户自己的需求,由用户自己发出消息,并相应处理
#define WM_USER 0X0400+1
SendMessage(hWnd,msg,1,2);

字符串资源

  • 添加字符串资源:添加字符串表,在表中增加字符串
  • 字符串资源的使用
int LoadString(
	HINSTANCE hInstance;
	UINT uID,
	LPTSTR lpBuffer,
	int nBufferMax
);成功返回字符串长度,失败0

加速键资源

GDI绘图对象-画笔

  • 画笔作用:线的颜色、线型、线粗;HPEN-画笔句柄
  • 画笔使用:创建画笔
HPEN CreatePen(
	int fnPenStyle, //画笔的样式
	int nWidth, //画笔的粗细
	COLORREF crColor //画笔的颜色
)创建成功返回句柄
  • 其他:可以使用GetStockObject函数获取系统维护的画刷、画笔等,如果不使用画刷填充,需要使用NULL_BRUSH参数,获取不填充的GetStockObject返回的画刷不需要DeleteObject
HANDLE g_hOutput = 0;
void DrawPit(HDC hdc) {
	for (int i = 0; i < 256; i++) {
		for (int j = 0; j < 256; j++) {
			SetPixel(hdc, i, j, RGB(i, j, 0));
		}
	}
}

void DrawLine(HDC hdc) {
	MoveToEx(hdc, 100, 100, NULL);
	LineTo(hdc, 300, 300);
}


void DrawRect(HDC hdc) {
	Rectangle(hdc, 100, 100, 300, 300);
}
void DrawEll(HDC hdc) {
	Ellipse(hdc, 100, 100, 300, 300);
}
void OnPaint(HWND hWnd) {
	PAINTSTRUCT ps = { 0 };
	HDC hdc = BeginPaint(hWnd, &ps);
	//DrawPit(hdc);
	//DrawLine(hdc);
	//DrawRect(hdc);
	HPEN hPen = CreatePen(PS_DASH, 1, RGB(255, 0, 0));
	HGDIOBJ nOldPen = SelectObject(hdc, hPen);
	//HBRUSH hBrush = CreateSolidBrush(RGB(0, 255, 0));
	HGDIOBJ hBrush = GetStockObject(NULL_BRUSH);//透明颜色

	HGDIOBJ nOldBrush = SelectObject(hdc, hBrush);
	DrawEll(hdc);
	
	//DeleteObject(hBrush);
	SelectObject(hdc, nOldBrush);
	//SelectObject(hdc, nOldPen);
	//DeleteObject(hPen);
	EndPaint(hWnd, &ps);
}

位图绘制

- 位图

在这里插入图片描述
在这里插入图片描述

void DrawBmp(HDC hdc) {
	//添加位图资源(不需要代码)
	HBITMAP hBmp = LoadBitmap(g_hInstance, (char *)IDB_BITMAP1);
	HDC hMemdc = CreateCompatibleDC(hdc);
	//创建一个内存DC,并构建一个虚拟区域,并且内存DC在虚拟区域中绘图
	HGDIOBJ nOldBmp = SelectObject(hMemdc, hBmp);
	//将位图数据送给内存DC,内存DC在虚拟区域中将位图绘制出来
	BitBlt(hdc, 100, 100, 48, 48, hMemdc, 0, 0, SRCCOPY);
	//将虚拟区域中绘制好的图像城成像到窗口中
	StretchBlt(hdc, 200, 200, 24, 24, hMemdc, 0, 0, 48, 48, SRCCOPY);
	//缩放成像
	SelectObject(hMemdc, nOldBmp);
	DeleteObject(hBmp);
	DeleteDC(hMemdc);
}

文本绘制

在这里插入图片描述
在这里插入图片描述

void OnPaint(HWND hWnd) {
	PAINTSTRUCT ps = { 0 };
	HDC hdc = BeginPaint(hWnd, &ps);
	char szText[] = "hello txt";
	SetTextColor(hdc, RGB(255, 0, 0));
	SetBkColor(hdc, RGB(0, 255, 0));
	SetBkMode(hdc, TRANSPARENT);
	TextOut(hdc, 100, 100, szText, strlen(szText));
	
	RECT rc;
	rc.left = 100;
	rc.top = 150;
	rc.right = 200;
	rc.bottom = 200;
	Rectangle(hdc, 100, 150, 200, 200);
	DrawText(hdc, szText, strlen(szText), &rc, DT_LEFT | DT_TOP | DT_WORDBREAK);

	EndPaint(hWnd, &ps);
}

字体

在这里插入图片描述
在这里插入图片描述

void OnPaint(HWND hWnd) {
	PAINTSTRUCT ps = { 0 };
	HDC hdc = BeginPaint(hWnd, &ps);
	SetTextColor(hdc, RGB(255, 0, 0));
	SetBkColor(hdc, RGB(0, 255, 0));
	SetBkMode(hdc, TRANSPARENT);
	HFONT hFont = CreateFont(30, 0, 45, 0, 900, 1, 1, 1, GB2312_CHARSET, 0, 0, 0, 0, "黑体");
	HGDIOBJ nOldFont = SelectObject(hdc, hFont);
	char szText[] = "hello txt";
	TextOut(hdc, 100, 100, szText, strlen(szText));
	
	RECT rc;
	rc.left = 100;
	rc.top = 150;
	rc.right = 200;
	rc.bottom = 200;
	Rectangle(hdc, 100, 150, 200, 200);
	DrawText(hdc, szText, strlen(szText), &rc, DT_LEFT | DT_TOP | DT_WORDBREAK);
	SelectObject(hdc, nOldFont);
	DeleteObject(hFont);
	EndPaint(hWnd, &ps);
}

模式对话框

在这里插入图片描述
在这里插入图片描述

HINSTANCE g_hInstance = 0;
void OnCommand(HWND hWnd,WPARAM wParam){
	switch(LOWORD(wParam)){
		case ID_MODEL:
		{
			DialogBox(g_hInstance,(char*)IDD_DIALOG1,hWnd,DlgProc);
		}
	}
}

INT CALLBACK DlgProc(HWND hwndlg,UINT msgID, WPARAM wParam,LPARAM lParam){
	if(wParam == SC_CLOSE){
		EndDialog(hwndlg,100);
	}
	break;
	return FALSE;
}

动态库特点

动态库特点

  • 运行时独立存在
  • 源码不会连接到执行程序
  • 使用时加载(使用动态库必须动态库执行)

与静态库比较:

  1. 由于静态库是将代码嵌入

线程

创建线程

HANDLE CreateThread(
	LPSECURITY_ATTRIBUTES lpThreadAttributes,//安全属性
	SIZE_T dwStackSize,  //线程栈的大小
	LPTHREAD_START_ROUTINE lpStartAddress, //线程处理函数的函数地址
	LPVOID lpParameter,   //传递给线程处理函数的参数
	DWORD dwCreationFlags, //线程的创建方式
	LPDWORD lpThread //创建成功,返回线程的ID
);创建成功,返回线程句柄

定义线程处理函数

DWORD WINAPI ThreadProc(
	LPVOID lpParameter //创建线程时,传递给线程的参数
)

互斥

相关的问题:
多线程下代码或资源的贡献使用
互斥的使用:
1、创建互斥

HANDLE CreateMutex(
	LPSECURITY_ATTRIBUTES lpMutexAttributes,//安全属性
	BOOL bInitialOwner, //初始的拥有者 true/false
	LPCTSTR lpName //命名
);创建成功或返回互斥句柄

2、等候互斥
WaitFor… 互斥的等候遵循谁先等候谁先获取
3、释放互斥

BOOL ReleaseMutex(
	HANDLE hMutex //handle to mutex
);

3、关闭互斥句柄

#include<Windows.h>
#include<stdio.h>

HANDLE g_hMutex;
DWORD CALLBACK TestProc(LPVOID pParam) {
	char* pszText = (char *)pParam;
	while (1) {
		WaitForSingleObject(g_hMutex, INFINITE);
		for (int i = 0; i < strlen(pszText); i++) {
			printf("%c", pszText[i]);
			Sleep(125);

		}
		printf("\n");
		ReleaseMutex(g_hMutex);
	}
	return 0;
}
DWORD CALLBACK TestProc2(LPVOID pParam) {
	char* pszText = (char *)pParam;
	while (1) {
		WaitForSingleObject(g_hMutex, INFINITE);
		for (int i = 0; i < strlen(pszText); i++) {
			printf("%c", pszText[i]);
			Sleep(125);

		}
		printf("\n");
		ReleaseMutex(g_hMutex);
	}
	return 0;
}
int main() {
	g_hMutex = CreateMutex(NULL, FALSE, NULL);
	DWORD nID = 0;
	char *pszText = "**********";
	HANDLE hThread = CreateThread(NULL, 0, TestProc, pszText, 0, &nID);
	char *pszText2 = "----------";
	HANDLE hThread2 = CreateThread(NULL, 0, TestProc2, pszText2, 0, &nID);
	getchar();

	getchar();
	return 0;

}

事件

相关问题:
程序之间的通知的问题
事件的使用
1、创建事件

HANDLE CreateEvent(
	LPSECURITY_ATTRIBUTES lpEventAttributes,//安全属性
	BOOL bManualReset,//事件重置方式,true手动,false自动
	BOOL bInitialState, //事件初始状态,true有信号
	LPCTSTR lpName //事件命名
);创建成功返回事件句柄

2、等候事件

WaitForSingleObject/WaitForMUltipleObjects

3、触发事件(将事件设置成有信号状态)

BOOL SetEvent(
	HANDLE hEvent //handle to event
);

4、复位事件(将事件设置成无信号状态)

BOOL ResetEvent(
	HANDLE hEvent //handle to evnet
);

5、关闭事件 CloseHandle

小心事件的死锁

#include<Windows.h>
#include<stdio.h>
HANDLE g_hEvent = 0;
DWORD CALLBACK PrintProc(LPVOID pParam) {
	while (1) {
		WaitForSingleObject(g_hEvent, INFINITE);
		ResetEvent(g_hEvent);
		printf("********\n");
	}
}
DWORD CALLBACK CtrlProc(LPVOID pParam) {
	while (1) {
		Sleep(1000);
		SetEvent(g_hEvent);
	}
}
int main() {
	g_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	DWORD nID = 0;
	HANDLE hThread[2] = { 0 };
	hThread[0] = CreateThread(NULL, 0, PrintProc, NULL, 0, &nID);
	hThread[1] = CreateThread(NULL, 0, CtrlProc, NULL, 0, &nID);
	WaitForMultipleObjects(2, hThread,TRUE, INFINITE);
	CloseHandle(g_hEvent);
	return 0;
}

信号量

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

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

相关文章

RPG Maker MZ中被你忽略的干货操作——独立开关和“开关”在事件页中的关系

文章目录 独立开关和“开关”在事件页中的关系图片参考结论确认信息双方同时满足是否执行事件页2如果有2个开关条件和一个“独立开关”条件是否是and关系&#xff1f;如果2个开关满足&#xff0c;但是“独立开关”不满足是否执行&#xff1f; 独立开关和“开关”在事件页中的关…

echarts地图添加外边框(散乱地图块添加区域边界线)

需求&#xff1a; 蓝色边是街道地图&#xff0c;也是实际有用的地图&#xff0c;可以点击拖动之类&#xff0c;由于太散乱&#xff0c;现在增加一个灰色边表示外面区县&#xff08;不可点击&#xff09;&#xff0c;让他看起来是一个整体 下面这个图是我最后做出来的案例 难…

JUC并发编程第十一章——Synchronized与锁升级

1 入门知识介绍 1.1 面试题 谈谈你对Synchronized的理解 请你聊聊Synchronized的锁升级 1.2 本章路线总纲 1.2.1 锁使用的强制要求 【强制】高并发时&#xff0c;同步调用应该去考量锁的性能损耗&#xff0c;能用无锁数据结构&#xff0c;就不要用锁&#xff1b;能锁区块&…

harmony相关开发参考文档

以下列举一些Harmony Os应用开发文档以及相关参考开源案例,可协助高效率开发: 1.鸿蒙NEXT开发官方资料:包含鸿蒙NEXT开发所有的特性,HarmonyOS SDK等,可以按需查阅,需要开通白名单:应用开发导读-入门 | 华为开发者联盟 (huawei.com) 2。OpenHarmony三方库中心仓(一些优…

架构设计 - MySQL 插入数据性能优化策略

mysql 数据库提高数据插入效率主要可以考虑以下方面&#xff1a; 使用批量插入数据的 SQL 语句&#xff0c;避免使用 for 循环逐条记录插入。 所有插入语句共用一个事务&#xff0c;避免1条SQL语句开1个事务&#xff0c;所有操作都完成后再提交事务。 尽量按照索引递增顺序插入…

T3-加密通信

T3-加密通信 题目描述 在一次军事演习中&#xff0c;小凯担任通信兵&#xff0c;负责解密传来的信息。他会收到一份 nn 的数字 表&#xff08;仅包含 0-9 共 10 种数码&#xff09;&#xff0c;和一份 mm 的字母表&#xff08;仅包含 A-Z、a-z 共 52 种字符&#xff09;。 数…

力扣每日一题-3040

题目 给你一个整数数组 nums &#xff0c;如果 nums 至少 包含 2 个元素&#xff0c;你可以执行以下操作中的 任意 一个&#xff1a; 选择 nums 中最前面两个元素并且删除它们。选择 nums 中最后两个元素并且删除它们。选择 nums 中第一个和最后一个元素并且删除它们。 一次…

SAS:PROC SQL和ANSI标准

文章来源于SAS HELP PROC SQL 和ANSI SQL 的区别——图表和视图名称的作用域规则不同 例1&#xff1a;匹配数据集相关名称 当PROC SQL匹配数据集相关名称时&#xff0c;会依次进行3个步骤&#xff1a;1、有别名&#xff0c;用别名匹配&#xff1b;2、1匹配失败&#xff0c;在无…

Spring Cloud Bus 消息总线基础入门与实践总结

【1】基础介绍 其主要是实现分布式自动刷新配置功能&#xff0c;Spring Cloud Bus 配合 Spring Cloud Config 使用可以实现配置的动态刷新。Spring Cloud Bus是用来将分布式系统的节点与轻量级消息系统链接起来的框架&#xff0c;它整合了Java的事件处理机制和消息中间件的功能…

测长仪的发展历程!

测长仪的发展历程可以大致分为以下几个阶段&#xff1a; 早期发展&#xff1a; 最早的测量工具主要是一些机械式测量工具&#xff0c;如角尺、卡钳等。 16世纪&#xff0c;在火炮制造中已开始使用光滑量规。 1772年和1805年&#xff0c;英国的J.瓦特和H.莫兹利等先后制造出利用…

【网络安全的神秘世界】Kali 自带 Burp Suite 使用指南:字体与CA证书设置详解等

&#x1f31d;博客主页&#xff1a;泥菩萨 &#x1f496;专栏&#xff1a;Linux探索之旅 | 网络安全的神秘世界 | 专接本 Kali 自带 Burp Suite 使用指南目录 Burp Suite的打开方式设置Burp Suite软件的字体大小查看Burp Suite 默认代理在火狐浏览器设置代理Burp Suite 抓不到本…

零售行业会员管理有哪些业务场景?解析不同业务场景的分析指标

在当今竞争激烈的零售市场中&#xff0c;会员管理不再仅仅是收集和存储数据&#xff0c;而是要求企业能够从数据中获取洞察&#xff0c;并据此制定策略。会员板块的业务场景涵盖了多个方面&#xff0c;每一个场景都为企业提供了一个独特的视角&#xff0c;帮助企业了解和服务于…

android 抓取 logcat 日志的方法

1.找到这个路径 2.然后执行命令&#xff08;adb logcat -v time >.\\logcat.log&#xff09;&#xff0c;开始抓取日志 3.这个时候就可以去操作APP了&#xff0c;复现BUG了。 Ctrlc 结束日志抓取 adb logcat -c 清空旧日志

USB端口管控软件|USB端口控制软件有哪些(小技巧)

​USB端口管控软件成为了保障企业数据安全的重要手段。 本文将为您介绍几款知名的USB端口控制软件&#xff0c;并分享一些实用的小技巧&#xff0c;帮助您更好地管理US端口&#xff0c;确保企业信息安全。#usb接口# 一、USB端口控制软件推荐 1&#xff0c;域智盾 域智盾是一…

tmux-以脚本中的tmux命令为例解释常用tmux命令

SESSIONenv_monitor_hr_parking ----- 将会话名称env_monitor_hr_parking赋值给变量SESSION tmux new-session -s $SESSION -n runner -d ----- new-session 用于创建新的会话。-s $SESSION 是一个选项&#xff0c;其中 $SESSION 是你想要给你的新会话命名的名称。-n runner 是…

如何高效接入闲鱼商品详情实时数据——goodfish.item_get API接口指南

闲鱼平台&#xff0c;作为中国领先的二手交易平台&#xff0c;拥有庞大的商品数据库和用户群体。为了提供一个透明、高效的交易环境&#xff0c;闲鱼平台通过其商品详情API接口&#xff08;goodfish.item_get&#xff09;为开发者和商家提供实时的商品信息获取服务。下面将深入…

使用 Python 和 Selenium 进行网络抓取

如果你今天的工作是从竞争对手的网站上抓取定价页面信息。你会怎么做&#xff1f;复制粘贴&#xff1f;手动输入数据&#xff1f;当然不行&#xff01;他们绝对会花费你超级多的时间&#xff0c;而且你可能会犯一些错误。 需要指出的是&#xff0c;Python已经成为最流行的数据…

超级马里奥-小游戏

学习目标&#xff1a; 练习Java面向对象的编程思想&#xff1b; 巩固Java语言基础&#xff0c;数据类型、集合、数组等&#xff1b; 深刻理解Java的三大特性&#xff0c;封装、继承、多态&#xff1b; 效果展示&#xff1a;

[发布]嵌入式系统远程测控软件-基于Qt

目录 一. 引言二. 软件功能2.1 原理2.2 软件功能2.3 运行环境 三. 软件操作使用3.1 软件界面3.2 软件功能使用详解3.2.1 连接3.2.2 数据监测&#xff08;串口示波器&#xff09;3.2.3 数据修改3.2.4 数据保存 3.3 软件的硬件连接 四. 通信协议——STM32移植篇4.1 通信协议4.2 S…

Java SE LTS版本商用收费,有那些开源的替代方案?

&#x1f680; Java SE LTS版本商用收费&#xff0c;有那些开源的替代方案&#xff1f; 摘要 Java 对于云服务、大数据、电子商务、支付、欺诈和身份、交易等许多应用程序来说都是至关重要的语言。然而&#xff0c;Oracle 对 Java SE LTS 版本的商用收费政策引发了广泛关注和…