书籍:《Visual C++ 2017从入门到精通》
环境:Visual Studio 2022
创建单文档工程
添加类CMyThread
添加类CmyWnd
编写CMyWnd类
说明:CMyWnd类是基于CFrameWnd基类的,必须要通过DECLARE_DYNCREATE(CMyWnd)声明和IMPLEMENT_DYNCREATE(CMyWnd, CFrameWnd)定义。
根据需要如下方式为WM_CREATE, WM_TIMER, WM_DESTROY消息添加对应的消息函数。
编写CMyWnd.h
#pragma once
#include <afxwin.h>
//继承关系:CMyWnd 继承自 CFrameWnd,表明这是一个框架窗口类。
//动态创建支持:DECLARE_DYNCREATE 宏允许通过 RUNTIME_CLASS 动态创建对象。
class CMyWnd :
public CFrameWnd
{
DECLARE_DYNCREATE(CMyWnd) // 支持动态创建
public:
CMyWnd();
CProgressCtrl m_pos; // 进度条控件:用于显示进度条。
protected:
virtual ~CMyWnd();
DECLARE_MESSAGE_MAP()
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); //WM_CREATE:初始化控件和定时器。
afx_msg void OnTimer(UINT_PTR nIDEvent); //WM_TIMER:更新进度条。
afx_msg void OnDestroy(); //WM_DESTROY:清理定时器。
};
编写CMyWnd.cpp
#include "pch.h"
#include "CMyWnd.h"
//动态创建支持
IMPLEMENT_DYNCREATE(CMyWnd, CFrameWnd)
CMyWnd::CMyWnd()
{
}
CMyWnd::~CMyWnd()
{
}
BEGIN_MESSAGE_MAP(CMyWnd, CFrameWnd)
ON_WM_CREATE()
ON_WM_TIMER()
ON_WM_DESTROY()
END_MESSAGE_MAP()
int CMyWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 在此添加您专用的创建代码
// 创建进度条控件:创建进度条控件,设置样式、位置、父窗口和控件ID。
m_pos.Create(WS_CHILD | WS_VISIBLE, CRect(10, 10, 300, 50), this, 10001);
//进度条配置:设置进度条范围(0~100)和步长(每次增加1)。
m_pos.SetRange(0, 100);
m_pos.SetStep(1);
// 设置定时器:设置定时器,ID为1,间隔50毫秒,无自定义数据。
SetTimer(1, 50, NULL);
return 0;
}
void CMyWnd::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
//进度条更新:使进度条前进一个步长(默认步长为1)。
m_pos.StepIt();
//调用基类 CFrameWnd 的 OnTimer 方法,执行框架默认的定时器处理逻辑。
CFrameWnd::OnTimer(nIDEvent);
}
void CMyWnd::OnDestroy()
{
CFrameWnd::OnDestroy();
// TODO: 在此处添加消息处理程序代码
//定时器清理:强制销毁定时器 ID 为 1 的定时器。
KillTimer(1);
}
编写CMyThread类
说明:CMyWnd类是基于CFrameWnd基类的,必须要通过DECLARE_DYNCREATE(CMyWnd)声明和IMPLEMENT_DYNCREATE(CMyWnd, CFrameWnd)定义.
根据以下方式重写InitInstance()和ExitInstance()
编写CMyThread.h
#pragma once //防止头文件被重复包含,替代传统的 #ifndef 方式。
#include <afxwin.h> //包含 MFC 核心头文件,提供 CWinThread 类的定义和其他 MFC 功能。
class CMyThread :
public CWinThread
{
DECLARE_DYNCREATE(CMyThread) // 支持动态创建
protected:
CMyThread(); // 构造函数(protected)
virtual ~CMyThread(); // 析构函数(protected)
public:
virtual BOOL InitInstance(); // 线程初始化
virtual int ExitInstance(); // 线程清理
};
编写CMyThread.cpp
#include "pch.h"
#include "CMyThread.h"
#include "CMyWnd.h"
//动态创建支持
//实现动态创建功能,允许通过 AfxBeginThread(RUNTIME_CLASS(CMyThread)) 创建线程实例。
IMPLEMENT_DYNCREATE(CMyThread, CWinThread)
CMyThread::CMyThread()
{
}
CMyThread::~CMyThread()
{
}
//线程入口函数 InitInstance
BOOL CMyThread::InitInstance()
{
// TODO: 在此添加专用代码和/或调用基类
//return CWinThread::InitInstance();
//创建一个自己定义的窗口,设置标题,并进行显示。
CMyWnd* pFrameWnd = new CMyWnd();
pFrameWnd->Create(NULL, _T("线程中创建的窗口"));
pFrameWnd->ShowWindow(SW_SHOW);
pFrameWnd->UpdateWindow();
return TRUE;
}
//线程退出函数 ExitInstance
int CMyThread::ExitInstance()
{
// TODO: 在此添加专用代码和/或调用基类
return CWinThread::ExitInstance();
}
添加“创建用户界面线程”子菜单
书中是在 视图菜单中添加的,本例中是在文件菜单中添加。
右击该子菜单->添加事件处理程序
编写On32771()
启动一个新线程,即用户点击“创建用户界面线程”子菜单时,会启用一个线程CMyThread,线程中会创建一个自定义窗口CMyWnd,在该窗口中有一个进度条控件,每隔50ms会更新进度条。
void CTest819View::On32771()
{
// TODO: 在此添加命令处理程序代码
//启动一个新线程,动态创建 CMyThread 类的实例。
AfxBeginThread(RUNTIME_CLASS(CMyThread));
}
编译执行查看效果
相关内容
详细介绍DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE-CSDN博客
DECLARE_DYNCREATE,IMPLEMENT_DYNCREATE和DECLARE_DYNAMIC,IMPLEMENT_DYNAMIC 的差异-CSDN博客
DECLARE_DYNCREATE,IMPLEMENT_DYNCREATE和DECLARE_DYNAMIC,IMPLEMENT_DYNAMIC 可以互换使用吗?-CSDN博客