Win32开发MFC程序

开发MFC程序一般是利用MFC程序向导,建立工程开发项目。如果你细心会发现,根本找不到程序入口 ANSI版本的WinMain() 或者 _tWinMain();
(注实际MFC程序此时为wWinMain(),

#ifdef _UNICODE
#define _tWinMain wWinMain
#else
#define _tWinMain WinMain
#endif




不久后,通过查找资料和在目录中查找还是见到了WinMain身在何处appmodul.cpp

// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.

#include "stdafx.h"
#include "sal.h"

/////////////////////////////////////////////////////////////////////////////
// export WinMain to force linkage to this module
extern int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	_In_ LPTSTR lpCmdLine, int nCmdShow);

extern "C" int WINAPI
_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	_In_ LPTSTR lpCmdLine, int nCmdShow)
#pragma warning(suppress: 4985)
{
	// call shared/exported WinMain
	return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}

/////////////////////////////////////////////////////////////////////////////
// initialize app state such that it points to this module's core state

BOOL AFXAPI AfxInitialize(BOOL bDLL, DWORD dwVersion)
{
	AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
	pModuleState->m_bDLL = (BYTE)bDLL;
	ASSERT(dwVersion <= _MFC_VER);
	UNUSED(dwVersion);  // not used in release build
#ifdef _AFXDLL
	pModuleState->m_dwVersion = dwVersion;
#endif
#ifdef _MBCS
	// set correct multi-byte code-page for Win32 apps
	if (!bDLL)
		_setmbcp(_MB_CP_ANSI);
#endif //_MBCS
	return TRUE;
}

// force initialization early
#pragma warning(disable: 4074)
#pragma init_seg(lib)

#ifndef _AFXDLL
void AFX_CDECL _AfxTermAppState()
{
	// terminate local data and critical sections
	AfxTermLocalData(NULL, TRUE);
	AfxCriticalTerm();

	// release the reference to thread local storage data
	AfxTlsRelease();
}
#endif

#ifndef _AFXDLL
char _afxInitAppState = (char)(AfxInitialize(FALSE, _MFC_VER), atexit(&_AfxTermAppState));
#else
char _afxInitAppState = (char)(AfxInitialize(FALSE, _MFC_VER));
#endif

/////////////////////////////////////////////////////////////////////////////
MFC程序WinMain()还要调用AfxWinMain(),这个函数负责创建一个CWinApp类的对象,并初始化对象运行,CWinApp中创建CDialog/CDialogEx或CFrame的对象并初始化运行。AfxWinMain()的定义在winmain.cpp这个文件里面。

[winmain.cpp]

// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.

#include "stdafx.h"
#include "sal.h"


/////////////////////////////////////////////////////////////////////////////
// Standard WinMain implementation
//  Can be replaced as long as 'AfxWinInit' is called first

int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	_In_ LPTSTR lpCmdLine, int nCmdShow)
{
	ASSERT(hPrevInstance == NULL);

	int nReturnCode = -1;
	CWinThread* pThread = AfxGetThread();
	CWinApp* pApp = AfxGetApp();

	// AFX internal initialization
	if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
		goto InitFailure;

	// App global initializations (rare)
	if (pApp != NULL && !pApp->InitApplication())
		goto InitFailure;

	// Perform specific initializations
	if (!pThread->InitInstance())
	{
		if (pThread->m_pMainWnd != NULL)
		{
			TRACE(traceAppMsg, 0, "Warning: Destroying non-NULL m_pMainWnd\n");
			pThread->m_pMainWnd->DestroyWindow();
		}
		nReturnCode = pThread->ExitInstance();
		goto InitFailure;
	}
	nReturnCode = pThread->Run();

InitFailure:
#ifdef _DEBUG
	// Check for missing AfxLockTempMap calls
	if (AfxGetModuleThreadState()->m_nTempMapLock != 0)
	{
		TRACE(traceAppMsg, 0, "Warning: Temp map lock count non-zero (%ld).\n",
			AfxGetModuleThreadState()->m_nTempMapLock);
	}
	AfxLockTempMaps();
	AfxUnlockTempMaps(-1);
#endif

	AfxWinTerm();
	return nReturnCode;
}

/////////////////////////////////////////////////////////////////////////////
[winmain.cpp]

既然知道了MFC程序的运行原理,代码原则,我们就能够使用Win32建立MFC程序,当然也可以用控制台建立MFC程序,这个复杂一点。有时间可以尝试。控制台程序入口为main(),参数有要注意一下 一个是HINSTANCE,窗口句柄,要用 HINSTANCE hThisInstance =::GetModuleHandle(NULL);还有int nCmdShow,这个可以自己定义SW_SHOW,HINSTANCE hPreInstance,LPTSTR lpCmdLine并不是那么好搞了,hPreInstance是图形窗口共享内存的,新的Win32系统中直接NULL,完全OK,而lpCmdLine和main(int argc,char* argv[])两个参数对应,需要复杂的转换,自己去实践吧。
继续讲主题,我们利用Visual Studio建立Win32程序,一般而言除了Visual Studio,还没有什么可以开发MFC程序吧。那就用Visual Studio吧,注意建立的Win32为空项目!非空就会自动建立一个Frame程序,基于Win32API的程序,这个就和我们的原则背离了。
建立一个stdafx.h,Visual Studio 中有模板。

// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.

// STDAFX.H is the header that includes the standard includes that are used
//  for most of the project.  These are compiled into a pre-compiled header

#pragma once

#include <winsdkver.h>

#undef _WIN32_WINNT
#define _WIN32_WINNT _WIN32_WINNT_MAXVER

#include <sdkddkver.h>

#ifndef VC_EXTRALEAN
#define VC_EXTRALEAN		// Exclude rarely-used stuff from Windows headers
#endif

#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS	// some CString constructors will be explicit

#include <afxwin.h>         // MFC core and standard components
#include <afxext.h>         // MFC extensions
#include <afxdisp.h>        // MFC Automation classes

#if defined(_M_CEE)
#include <afxwinforms.h>
#endif
一个stdafx.cpp
#include "stdafx.h"
建立程序入口源文件mian.cpp
#include "stdafx.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPTSTR lpCmdLine, int nCmdShow)//Win32-MFC初始化函数!
{
		ASSERT(hPrevInstance == NULL);
// Win32应用程序只有一个实例,所以hPrevInstance肯定是NULL,
// 如果不是,则肯定是出了问题。

	int nReturnCode = -1;
// 预设返回值为-1。这个返回值是用来与父进程通信的。不过并没有这个值的标准
// 使用方法。

	CWinThread* pThread = AfxGetThread();
	CWinApp* pApp = AfxGetApp();
// CWinApp是CWinThread的派生类,上两行代码分别初始化了一个指向CWinThread对象的
// 指针和一个CWinApp对象。它们的初始化是通过调用AfxGetThread()和AfxGetApp()得到
// 的,也就是说,它们分别被初始化为指向当前应用程序的唯一全局线程/应用程序对象的
// 指针。

	// AFX internal initialization
	if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
		goto InitFailure;
// AfxWinInit()函数初始化MFC程序,处理很多难以预料的问题。该函数和后面的
// AfxWinTerm()对应。

	// App global initializations (rare)
	if (pApp != NULL && !pApp->InitApplication())
		goto InitFailure;
// 调用pApp->InitApplication(),初始化应用程序。不过这还不够。

	// Perform specific initializations
	if (!pThread->InitInstance())
// 调用pThread->InitInstance()函数,进行线程初始化。注意,InitInstance()通常
// 是你的MFC代码中唯一必须重载的函数。
// 下面的语句块是当初始化不成功时的处理。
	{
		if (pThread->m_pMainWnd != NULL)
		{
			TRACE0("Warning: Destroying non-NULL m_pMainWnd\n");
			pThread->m_pMainWnd->DestroyWindow();
		}
		nReturnCode = pThread->ExitInstance();
// ExitInstance()也是一个值得注意的函数
		goto InitFailure;
	}
	nReturnCode = pThread->Run();
// pThread->Run()是重要函数,它使得MFC进入消息循环。其细节待另文介绍。


// 以下代码处理各种初始化失败情形
InitFailure:
#ifdef _DEBUG 
	// Check for missing AfxLockTempMap calls
	if (AfxGetModuleThreadState()->m_nTempMapLock != 0)
	{
		TRACE1("Warning: Temp map lock count non-zero (%ld).\n",
			AfxGetModuleThreadState()->m_nTempMapLock);
	}
	AfxLockTempMaps();
	AfxUnlockTempMaps(-1);
#endif

	AfxWinTerm();
	return nReturnCode;
}

这里省略了AfxWinMain(),theApp实例的初始化直接放在了WinMain()中,不过,正式开发一定要注意不能这样,这不是很安全的选择。然后就是建立一个CWinApp的类,如果要CWinAppEx类,pApp->InitApplication() 初始化要换一下。上述编译通不过

如我的CWinApp类为:BuilderEx.h

#pragma once
#include "stdafx.h"
#include <afxwinappex.h>

#ifndef __AFXWIN_H__
	#error "在包含此文件之前包含“stdafx.h”以生成 PCH 文件"
#endif

#include "resource.h"		// 主符号


class BuilderEx : public CWinApp
{
public:
	BuilderEx();

// 重写
public:
	virtual BOOL InitInstance();

// 实现

	DECLARE_MESSAGE_MAP()
};

extern BuilderEx theApp;
BuilderEx.cpp:

// BuilderEx.cpp : 定义应用程序的类行为。
//


#include "stdafx.h"
#include "BuilderEx.h"
#include "Builderdlg.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#endif




// BuilderEx


BEGIN_MESSAGE_MAP(BuilderEx, CWinAppEx)
	//ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()




// BuilderEx 构造


BuilderEx::BuilderEx()
{
	// 支持重新启动管理器
	m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;


	// TODO: 在此处添加构造代码,
	// 将所有重要的初始化放置在 InitInstance 中
}




// 唯一的一个 BuilderEx 对象


BuilderEx theApp;




// BuilderEx 初始化


BOOL BuilderEx::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("应用程序向导生成的本地应用程序"));


	BuilderDlg 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;
}
这就是CWinApp的实现,这是一个对话框,你也可以设置其他的,这里我们还要建立一个对话框,直接在资源中建立即可,建立后使用类向导建立一个类,在CWinApp中会实现的
我直接贴代码
.h
#include "resource.h"
//#include <Windows.h>
//#include <afx.h>
#pragma once


// BuilderDlg 对话框

class BuilderDlg : public CDialogEx
{
	DECLARE_DYNAMIC(BuilderDlg)

public:
	BuilderDlg(CWnd* pParent = NULL);   // 标准构造函数
	virtual ~BuilderDlg();

// 对话框数据
	enum { IDD = IDD_DIALOG_WINM };

protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	virtual BOOL InitInstance();
	void OnPaint();
	HICON m_hIcon;
	void BuilderDlg::OnSize(UINT nType,int cx,int cy);
};
.cpp

//#include "BuilderDlg.h"
// BuilderDlg.cpp : 实现文件
//

#include "stdafx.h"
//#include "Builder.h"
#include "BuilderDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// BuilderDlg 对话框

IMPLEMENT_DYNAMIC(BuilderDlg, CDialogEx)

BuilderDlg::BuilderDlg(CWnd* pParent /*=NULL*/)
	: CDialogEx(BuilderDlg::IDD, pParent)
{
	EnableActiveAccessibility();
	m_hIcon = AfxGetApp()->LoadIcon(IDI_ICON_MAIN);
	//m_pAutoProxy = NULL;
}

BuilderDlg::~BuilderDlg()
{
}

void BuilderDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(BuilderDlg, CDialogEx)
	ON_WM_SIZE()
END_MESSAGE_MAP()


// BuilderDlg 消息处理程序
BOOL BuilderDlg::InitInstance()
{
	CDialogEx::OnInitDialog();

	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		
	return TRUE; 
}
void BuilderDlg::OnPaint()
{
		if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}
HCURSOR BuilderDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}
void BuilderDlg::OnSize(UINT nType,int cx,int cy)
{
  CDialogEx::OnSize(nType,   cx,   cy);    

  //MessageBox(_T("Hello"));
  CRect   rect;    
  CRichEditCtrl   *   wnd;    
  GetClientRect(rect);                                     //获取客户区大小    
  wnd=(CRichEditCtrl  *)GetDlgItem(IDC_EDIT1);     //获取其上控件的指针,是个编辑框    
  if(wnd)wnd->MoveWindow(rect);    
}
资源自己准备把,这里就不多说了,项目设置一定要使用MFC库,无论是静态还是共享!

这个程序还有一个Edit控件,现在和MFC程序的做法是一样的了,你自己想怎么搞就怎么搞!




















                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值