转自:CWinThread类用法详解+实例_C的技术博客_51CTO博客
CWinThread有两种用法,一种是辅助线程,又叫工作线程(Worker_Thread),另外一种是交互线程(User_Interface_Thread)。其中第一种用法简单,而第二种就相对复杂了。我们来具体看一下。(笔者用的是VC2010)
例一:
我们建立一个Win32控制台程序空项目,右键点击项目,选择【属性】,
对项目做如上修改。
输入下面的代码:
#define _AFXDLL
#include"afxwin.h"
class CMyThread :public CWinThread
{
public:
DECLARE_DYNCREATE(CMyThread)
protected:
virtual BOOL InitInstance();
};
IMPLEMENT_DYNCREATE(CMyThread, CWinThread)
BOOL CMyThread::InitInstance()
{
//这里可以添加线程处理代码,你想在这里做什么都可以!
_tprintf(L"Hello CWinThread as Worker Thread\n");
//注意,这里必须返回FALSE,这是区别于User_Interface_Thread的地方!如果这里返回
//TRUE,那么InitInstance函数执行完毕后,MFC框架将会调用CMyThread类的虚拟函数Run()
//Run函数执行的是消息循环,在工作线程中,没有窗口,何来消息循环呢,所以这里一定要返回FALSE,
//记住了!!!
return FALSE;
}
int _tmain()
{
//创建一个新线程
CWinThread* p = AfxBeginThread(RUNTIME_CLASS(CMyThread));
_gettchar();
return 0;
}
这里面应该注意的问题,已经在程序的注释中给出了。在真正的MFC中使用这个类,用法没有任何区别,我们重点看User_Interface_Thread的用法。
--------------------------------------------
例子二:
首先创建一个MFC程序,选择对话框程序直接点完成。
这样,系统会给我们生成一个对话框,直接将对话框资源修改成下面的样子:
双击【确定】,得到
点击【项目】菜单,选择【添加类】
选择MFC类。
【类名】:CMyThread 【基类名】:CWinThread 直接【完成】。
系统自动生成CMyThread类,一共两个文件MyThread.h和MyThread.cpp
在MyThread.cpp中,添加如下代码:
// MyThread.cpp : 实现文件
//
#include "stdafx.h"
#include "tt、.h"
#include "MyThread.h"
// CMyThread
LRESULT CALLBACK MainWndProc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam) // second message parameter
{
switch (uMsg)
{
case WM_CREATE:
// Initialize the window.
return 0;
case WM_PAINT:
// Paint the window's client area.
return 0;
case WM_SIZE:
// Set the size and position of the window.
return 0;
case WM_DESTROY:
// Clean up window-specific data objects.
PostQuitMessage(0);
return 0;
//
// Process other messages.
//
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
// CMyThread
IMPLEMENT_DYNCREATE(CMyThread, CWinThread)
CMyThread::CMyThread()
{
}
CMyThread::~CMyThread()
{
}
BOOL CMyThread::InitInstance()
{
// TODO: 在此执行任意逐线程初始化
WNDCLASS wc, wc1;
// Register the main window class.
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = ::GetModuleHandle(NULL);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = L"ydm";
if (!GetClassInfo(GetModuleHandle(NULL), L"ydm", &wc1))
{
if (!RegisterClass(&wc))
return FALSE;
}
HWND hwnd = CreateWindow(L"ydm", NULL, WS_OVERLAPPEDWINDOW, 0, 0, 500, 300, NULL, NULL,
::GetModuleHandle(NULL), NULL);
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
return TRUE;
}
int CMyThread::ExitInstance()
{
// TODO: 在此执行任意逐线程清理
return CWinThread::ExitInstance();
}
BEGIN_MESSAGE_MAP(CMyThread, CWinThread)
END_MESSAGE_MAP()
// CMyThread 消息处理程序
在Dlg的cpp类中,添加如下代码:
// MyThread.cpp : 实现文件
//
#include "stdafx.h"
#include "tt、.h"
#include "MyThread.h"
// CMyThread
LRESULT CALLBACK MainWndProc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam) // second message parameter
{
switch (uMsg)
{
case WM_CREATE:
// Initialize the window.
return 0;
case WM_PAINT:
// Paint the window's client area.
return 0;
case WM_SIZE:
// Set the size and position of the window.
return 0;
case WM_DESTROY:
// Clean up window-specific data objects.
PostQuitMessage(0);
return 0;
//
// Process other messages.
//
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
// CMyThread
IMPLEMENT_DYNCREATE(CMyThread, CWinThread)
CMyThread::CMyThread()
{
}
CMyThread::~CMyThread()
{
}
BOOL CMyThread::InitInstance()
{
// TODO: 在此执行任意逐线程初始化
WNDCLASS wc, wc1;
// Register the main window class.
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = ::GetModuleHandle(NULL);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = L"ydm";
if (!GetClassInfo(GetModuleHandle(NULL), L"ydm", &wc1))
{
if (!RegisterClass(&wc))
return FALSE;
}
HWND hwnd = CreateWindow(L"ydm", NULL, WS_OVERLAPPEDWINDOW, 0, 0, 500, 300, NULL, NULL,
::GetModuleHandle(NULL), NULL);
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
return TRUE;
}
int CMyThread::ExitInstance()
{
// TODO: 在此执行任意逐线程清理
return CWinThread::ExitInstance();
}
BEGIN_MESSAGE_MAP(CMyThread, CWinThread)
END_MESSAGE_MAP()
// CMyThread 消息处理程序
在Dlg的cpp类中,添加如下代码:
// tt、.cpp : 定义应用程序的类行为。
//
#include "stdafx.h"
#include "tt、.h"
#include "tt、Dlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// Ctt、App
BEGIN_MESSAGE_MAP(Ctt、App, CWinApp)
ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()
// Ctt、App 构造
Ctt、App::Ctt、App()
{
// 支持重新启动管理器
m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;
// TODO: 在此处添加构造代码,
// 将所有重要的初始化放置在 InitInstance 中
}
// 唯一的一个 Ctt、App 对象
Ctt、App theApp;
// Ctt、App 初始化
BOOL Ctt、App::InitInstance()
{
// 如果一个运行在 Windows XP 上的应用程序清单指定要
// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
//则需要 InitCommonControlsEx()。否则,将无法创建窗口。
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// 将它设置为包括所有要在应用程序中使用的
// 公共控件类。
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinApp::InitInstance();
AfxEnableControlContainer();
// 创建 shell 管理器,以防对话框包含
// 任何 shell 树视图控件或 shell 列表视图控件。
CShellManager *pShellManager = new CShellManager;
// 标准初始化
// 如果未使用这些功能并希望减小
// 最终可执行文件的大小,则应移除下列
// 不需要的特定初始化例程
// 更改用于存储设置的注册表项
// TODO: 应适当修改该字符串,
// 例如修改为公司或组织名
SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
Ctt、Dlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: 在此放置处理何时用
// “确定”来关闭对话框的代码
}
else if (nResponse == IDCANCEL)
{
// TODO: 在此放置处理何时用
// “取消”来关闭对话框的代码
}
// 删除上面创建的 shell 管理器。
if (pShellManager != NULL)
{
delete pShellManager;
}
// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
// 而不是启动应用程序的消息泵。
return FALSE;
}
编译并执行,在对话框上点击【确定】,会出来一个新的对话框。这是User_Interface_Thread的使用方法。我们可以将以上两端代码中的粗体代码,换成我们想要的任何代码。