MFC文档视图结构框架分析

MFC文档视图结构框架分析
MFC文档视图结构框架分析

MFC文档视图结构框架分析

1:程序的“导火索”---theApp

CmyApp theApp;

在声明对象的同时,调用其构造函数。按C++的语法,首先要调用其基类Cwinapp的构造函数. 这个文件主要用于应用程序的一些初始化操作。

class CWinApp : public CWinThread

{

DECLARE_DYNAMIC(CWinApp)

public:

// Constructor

CWinApp(LPCTSTR lpszAppName = NULL);

…………

}

CWinApp::CWinApp(LPCTSTR lpszAppName)

{

if (lpszAppName != NULL)

m_pszAppName = _tcsdup(lpszAppName);

else

m_pszAppName = NULL;

// initialize CWinThread state

AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();

AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread;

ASSERT(AfxGetThread() == NULL);

pThreadState->m_pCurrentWinThread = this;

ASSERT(AfxGetThread() == this);

m_hThread = ::GetCurrentThread();

m_nThreadID = ::GetCurrentThreadId();

// initialize CWinApp state

ASSERT(afxCurrentWinApp == NULL); // only one CWinApp object please pModuleState->m_pCurrentWinApp = this;

ASSERT(AfxGetApp() == this);

// in non-running state until WinMain

m_hInstance = NULL;

m_hLangResourceDLL = NULL;

m_pszHelpFilePath = NULL;

m_pszProfileName = NULL;

m_pszRegistryKey = NULL;

m_pszExeName = NULL;

m_pRecentFileList = NULL;

m_pDocManager = NULL;

m_atomApp = m_atomSystemTopic = NULL;

m_lpCmdLine = NULL;

m_pCmdInfo = NULL;

// initialize wait cursor state

m_nWaitCursorCount = 0;

m_hcurWaitCursorRestore = NULL;

// initialize current printer state

m_hDevMode = NULL;

m_hDevNames = NULL;

m_nNumPreviewPages = 0; // not specified (defaults to 1) // initialize DAO state

m_lpfnDaoTerm = NULL; // will be set if AfxDaoInit called // other initialization

m_bHelpMode = FALSE;

m_eHelpType = afxWinHelp;

m_nSafetyPoolSize = 512; // default size

}

2:theApp之后的隐藏代码,由他控制整个程序的流程。

_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

LPTSTR lpCmdLine, int nCmdShow)

{

// call shared/exported WinMain

return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);

}

其中有宏定义:#define _tWinMain wWinMain

int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

LPTSTR lpCmdLine, int nCmdShow)

{

ASSERT(hPrevInstance == NULL);

int nReturnCode = -1;

CWinThread* pThread = AfxGetThread();;// CWinApp是从CWinThread派生的, CWinApp* pApp = AfxGetApp(); //实质上就是pThread==pApp

// 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()) //注意多态性virtual BOOL InitInstanc e();

//又因为pThread==pApp,所以调用pApp-> 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;

}

由上面的程序可以看到几个很重要的函数

(1)AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))

goto InitFailure;

(2) pApp->InitApplication())

(3) pThread->InitInstance()

(4) pThread->Run()

其中1,2 也是完成程序的一些初始化工作,4 主要是为了处理消息,3呢,很关键,我们运行时看到的窗口就是从这里产生。下面一一介绍

3:程序自动产生的InitInstance()函数

以下是自动生成的InitInstance()源程序:

BOOL CmyApp::InitInstance()

{

// 如果一个运行在 Windows XP 上的应用程序清单指定要

// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,

//则需要 InitCommonControls()。否则,将无法创建窗口。

InitCommonControls();

CWinApp::InitInstance();

// 初始化 OLE 库

if (!AfxOleInit())

{

AfxMessageBox(IDP_OLE_INIT_FAILED);

return FALSE;

}

AfxEnableControlContainer();

// 标准初始化

// 如果未使用这些功能并希望减小

// 最终可执行文件的大小,则应移除下列

// 不需要的特定初始化例程

// 更改用于存储设置的注册表项

// TODO: 应适当修改该字符串,

// 例如修改为公司或组织名

SetRegistryKey(_T("应用程序向导生成的本地应用程序"));

LoadStdProfileSettings(4); // 加载标准 INI 文件选项(包括 MRU) // 注册应用程序的文档模板。文档模板

// 将用作文档、框架窗口和视图之间的连接

CMultiDocTemplate* pDocTemplate;

pDocTemplate = new CMultiDocTemplate(IDR_myTYPE,

RUNTIME_CLASS(CmyDoc),

RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架

RUNTIME_CLASS(CmyView));

if (!pDocTemplate)

return FALSE;

AddDocTemplate(pDocTemplate);

// 创建主 MDI 框架窗口

CMainFrame* pMainFrame = new CMainFrame;

if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME))

return FALSE;

m_pMainWnd = pMainFrame;

// 仅当具有后缀时才调用 DragAcceptFiles

// 在 MDI 应用程序中,这应在设置 m_pMainWnd 之后立即发生

// 分析标准外壳命令、DDE、打开文件操作的命令行

CCommandLineInfo cmdInfo;

ParseCommandLine(cmdInfo);

// 调度在命令行中指定的命令。如果

// 用 /RegServer、/Register、/Unregserver 或 /Unregister 启动应用程序,则返回 FALSE。

if (!ProcessShellCommand(cmdInfo)) //引发窗口注册

return FALSE;

// 主窗口已初始化,因此显示它并对其进行更新

pMainFrame->ShowWindow(m_nCmdShow);

pMainFrame->UpdateWindow();

return TRUE;

}

其中,注册窗口用到了一下函数,比较长,如下:

BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister)

{

// mask off all classes that are already registered

AFX_MODULE_STATE* pModuleState = AfxGetModuleState();

fToRegister &= ~pModuleState->m_fRegisteredClasses;

if (fToRegister == 0)

return TRUE;

LONG fRegisteredClasses = 0;

// common initialization

WNDCLASS wndcls;

memset(&wndcls, 0, sizeof(WNDCLASS)); // start with NULL defaults

wndcls.lpfnWndProc = DefWindowProc; //窗口处理函数

wndcls.hInstance = AfxGetInstanceHandle();

wndcls.hCursor = afxData.hcurArrow;

INITCOMMONCONTROLSEX init;

init.dwSize = sizeof(init);

// work to register classes as specified by fToRegister, populate fReg isteredClasses as we go

if (fToRegister & AFX_WND_REG)

{

// Child windows - no brush, no icon, safest default class styles wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;

wndcls.lpszClassName = _afxWnd;

if (AfxRegisterClass(&wndcls))

fRegisteredClasses |= AFX_WND_REG;

}

if (fToRegister & AFX_WNDOLECONTROL_REG)

{

// OLE Control windows - use parent DC for speed

wndcls.style |= CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;

wndcls.lpszClassName = _afxWndOleControl;

if (AfxRegisterClass(&wndcls))

fRegisteredClasses |= AFX_WNDOLECONTROL_REG;

}

if (fToRegister & AFX_WNDCONTROLBAR_REG)

{

// Control bar windows

wndcls.style = 0; // control bars don't handle double click

wndcls.lpszClassName = _afxWndControlBar;

wndcls.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);

if (AfxRegisterClass(&wndcls))

fRegisteredClasses |= AFX_WNDCONTROLBAR_REG;

}

if (fToRegister & AFX_WNDMDIFRAME_REG)

{

// MDI Frame window (also used for splitter window)

wndcls.style = CS_DBLCLKS;

wndcls.hbrBackground = NULL;

if (_AfxRegisterWithIcon(&wndcls, _afxWndMDIFrame, AFX_IDI_STD_MDIF RAME))

fRegisteredClasses |= AFX_WNDMDIFRAME_REG;

}

if (fToRegister & AFX_WNDFRAMEORVIEW_REG)

{

// SDI Frame or MDI Child windows or views - normal colors

wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;

wndcls.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);

if (_AfxRegisterWithIcon(&wndcls, _afxWndFrameOrView, AFX_IDI_STD_F RAME))

fRegisteredClasses |= AFX_WNDFRAMEORVIEW_REG;

}

if (fToRegister & AFX_WNDCOMMCTLS_REG)

{

// this flag is compatible with the old InitCommonControls() API init.dwICC = ICC_WIN95_CLASSES;

fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WIN95CTLS_M ASK);

fToRegister &= ~AFX_WIN95CTLS_MASK;

}

if (fToRegister & AFX_WNDCOMMCTL_UPDOWN_REG)

{

init.dwICC = ICC_UPDOWN_CLASS;

fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_ UPDOWN_REG);

}

if (fToRegister & AFX_WNDCOMMCTL_TREEVIEW_REG)

{

init.dwICC = ICC_TREEVIEW_CLASSES;

fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_ TREEVIEW_REG);

}

if (fToRegister & AFX_WNDCOMMCTL_TAB_REG)

{

init.dwICC = ICC_TAB_CLASSES;

fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_

TAB_REG);

}

if (fToRegister & AFX_WNDCOMMCTL_PROGRESS_REG)

{

init.dwICC = ICC_PROGRESS_CLASS;

fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_ PROGRESS_REG);

}

if (fToRegister & AFX_WNDCOMMCTL_LISTVIEW_REG)

{

init.dwICC = ICC_LISTVIEW_CLASSES;

fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_ LISTVIEW_REG);

}

if (fToRegister & AFX_WNDCOMMCTL_HOTKEY_REG)

{

init.dwICC = ICC_HOTKEY_CLASS;

fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_ HOTKEY_REG);

}

if (fToRegister & AFX_WNDCOMMCTL_BAR_REG)

{

init.dwICC = ICC_BAR_CLASSES;

fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_ BAR_REG);

}

if (fToRegister & AFX_WNDCOMMCTL_ANIMATE_REG)

{

init.dwICC = ICC_ANIMATE_CLASS;

fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_

ANIMATE_REG);

}

if (fToRegister & AFX_WNDCOMMCTL_INTERNET_REG)

{

init.dwICC = ICC_INTERNET_CLASSES;

fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_ INTERNET_REG);

}

if (fToRegister & AFX_WNDCOMMCTL_COOL_REG)

{

init.dwICC = ICC_COOL_CLASSES;

fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_ COOL_REG);

}

if (fToRegister & AFX_WNDCOMMCTL_USEREX_REG)

{

init.dwICC = ICC_USEREX_CLASSES;

fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_ USEREX_REG);

}

if (fToRegister & AFX_WNDCOMMCTL_DATE_REG)

{

init.dwICC = ICC_DATE_CLASSES;

fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_ DATE_REG);

}

if (fToRegister & AFX_WNDCOMMCTL_LINK_REG)

{

init.dwICC = ICC_LINK_CLASS;

fRegisteredClasses |= _AfxInitCommonControls(&init, AFX_WNDCOMMCTL_

LINK_REG);

}

// save new state of registered controls

pModuleState->m_fRegisteredClasses |= fRegisteredClasses;

// special case for all common controls registered, turn on AFX_WNDCOM MCTLS_REG

if ((pModuleState->m_fRegisteredClasses & AFX_WIN95CTLS_MASK) == AFX_W IN95CTLS_MASK)

{

pModuleState->m_fRegisteredClasses |= AFX_WNDCOMMCTLS_REG;

fRegisteredClasses |= AFX_WNDCOMMCTLS_REG;

}

// must have registered at least as mamy classes as requested

return (fToRegister & fRegisteredClasses) == fToRegister;

}

他是在PreCreateWindow中调用的注册,

BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)

{

if (cs.lpszClass == NULL)

{

VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));

cs.lpszClass = _afxWndFrameOrView; // COLOR_WINDOW background

}

if (cs.style & FWS_ADDTOTITLE)

cs.style |= FWS_PREFIXTITLE;

cs.dwExStyle |= WS_EX_CLIENTEDGE;

return TRUE;

}

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

{

if( !CFrameWnd::PreCreateWindow(cs) )

return FALSE;

// TODO: Modify the Window class or styles here by modifying

// the CREATESTRUCT cs

return TRUE;

}

BOOL CView::PreCreateWindow(CREATESTRUCT & cs)

{

ASSERT(cs.style & WS_CHILD);

if (cs.lpszClass == NULL)

{

VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));

cs.lpszClass = _afxWndFrameOrView; // COLOR_WINDOW background }

if (cs.style & WS_BORDER)

{

cs.dwExStyle |= WS_EX_CLIENTEDGE;

cs.style &= ~WS_BORDER;

}

return TRUE;

}

BOOL CTestView::PreCreateWindow(CREATESTRUCT& cs)

{

// TODO: Modify the Window class or styles here by modifying

// the CREATESTRUCT cs

return CView::PreCreateWindow(cs);

}

有几点要说明

(1)m_pMainWnd,头文件里并没有这个变量呀?噢,这个在基类里定义的public 类型的变量,所以,他是通过继承得到的。

(2) 你注意过吗,当我们一点运行,会默认出来一个视图窗口,这是谁调用的呢?哦,就是下面这几行,它调用了opendocument() 函数。

CCommandLineInfo cmdInfo;

ParseCommandLine(cmdInfo);

if (!ProcessShellCommand(cmdInfo))

return FALSE;

(3)这个函数有个关键的地方

CMultiDocTemplate* pDocTemplate;

pDocTemplate = new CMultiDocTemplate(IDR_myTYPE,

RUNTIME_CLASS(CmyDoc),

RUNTIME_CLASS(CChildFrame), // 自定义 MDI 子框架

RUNTIME_CLASS(CmyView));

if (!pDocTemplate)

return FALSE;

AddDocTemplate(pDocTemplate);

通过它,把视图,窗口和文档结合起来。

4:主窗口CMainFrame的创建

(1)通过CMainFrame* pMainFrame = new CMainFrame;

我们得到的是不断调用的基类

CMainFrame::CMainFrame()

{

// TODO: 在此添加成员初始化代码

}

CMDIFrameWnd::CMDIFrameWnd()

{

m_hWndMDIClient = NULL;

}

CFrameWnd::CFrameWnd()

{

ASSERT(m_hWnd == NULL);

m_nWindow = -1; // unknown window ID

m_bAutoMenuEnable = TRUE; // auto enable on by default m_lpfnCloseProc = NULL;

m_hMenuDefault = NULL;

m_hAccelTable = NULL;

m_nIDHelp = 0;

m_nIDTracking = 0;

m_nIDLastMessage = 0;

m_pViewActive = NULL;

m_cModalStack = 0; // initialize modality support m_phWndDisable = NULL;

m_pNotifyHook = NULL;

m_hMenuAlt = NULL;

m_nIdleFlags = 0; // no idle work at start

m_rectBorder.SetRectEmpty();

m_bHelpMode = HELP_INACTIVE; // not in Shift+F1 help mode m_dwPromptContext = 0;

m_pNextFrameWnd = NULL; // not in list yet

m_bInRecalcLayout = FALSE;

m_pFloatingFrameClass = NULL;

m_nShowDelay = -1; // no delay pending

AddFrameWnd();

}

(2)pMainFrame->LoadFrame(IDR_MAINFRAME)所引发的一系列

BOOL CMDIFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,

CWnd* pParentWnd, CCreateContext* pContext)

{

if (!CFrameWnd::LoadFrame(nIDResource, dwDefaultStyle,

pParentWnd, pContext))

return FALSE;

// save menu to use when no active MDI child window is present ASSERT(m_hWnd != NULL);

m_hMenuDefault = ::GetMenu(m_hWnd);

if (m_hMenuDefault == NULL)

TRACE(traceAppMsg, 0, "Warning: CMDIFrameWnd without a default menu. \n");

return TRUE;

}

BOOL CFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,

CWnd* pParentWnd, CCreateContext* pContext)

{

// only do this once

ASSERT_VALID_IDR(nIDResource);

ASSERT(m_nIDHelp == 0 || m_nIDHelp == nIDResource);

m_nIDHelp = nIDResource; // ID for help context (+HID_BASE_RESOURC E)

CString strFullString;

if (strFullString.LoadString(nIDResource))

AfxExtractSubString(m_strTitle, strFullString, 0); // first sub-string

VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));

// attempt to create the window

LPCTSTR lpszClass = GetIconWndClass(dwDefaultStyle, nIDResource);

CString strTitle = m_strTitle;

if(!Create(lpszClass, strTitle, dwDefaultStyle, rectDefault, pParentWnd, MAKEINTRESOURCE(nIDResource), 0L, pContext))

{

return FALSE; // will self destruct on failure normally }

// save the default menu handle

ASSERT(m_hWnd != NULL);

m_hMenuDefault = ::GetMenu(m_hWnd);

// load accelerator resource

LoadAccelTable(MAKEINTRESOURCE(nIDResource));

if (pContext == NULL) // send initial update

SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE);

return TRUE;

}

BOOL CFrameWnd::Create(LPCTSTR lpszClassName,

LPCTSTR lpszWindowName,

DWORD dwStyle,

const RECT& rect,

CWnd* pParentWnd,

LPCTSTR lpszMenuName,

DWORD dwExStyle,

CCreateContext* pContext)

{

HMENU hMenu = NULL;

if (lpszMenuName != NULL)

{

// load in a menu that will get destroyed when window gets destroye d

HINSTANCE hInst = AfxFindResourceHandle(lpszMenuName, RT_MENU);

if ((hMenu = ::LoadMenu(hInst, lpszMenuName)) == NULL) {

TRACE(traceAppMsg, 0, "Warning: failed to load menu for CFrameW nd.\n");

PostNcDestroy(); // perhaps delete the C++ object return FALSE;

}

}

m_strTitle = lpszWindowName; // save title for later

if (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.to p,

pParentWnd->GetSafeHwnd(), hMenu, (LPVOID)pContext))

{

TRACE(traceAppMsg, 0, "Warning: failed to create CFrameWnd.\n");

if (hMenu != NULL)

DestroyMenu(hMenu);

return FALSE;

}

return TRUE;

}

因为CFrameWnd没有重新写CreateEX,所以是调用的基类的CreateEx的函数:BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,

LPCTSTR lpszWindowName, DWORD dwStyle,

int x, int y, int nWidth, int nHeight,

HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam)

{

// allow modification of several common create parameters

CREATESTRUCT cs;

cs.dwExStyle = dwExStyle;

cs.lpszClass = lpszClassName;

cs.lpszName = lpszWindowName;

cs.style = dwStyle;

cs.x = x;

cs.y = y;

cs.cx = nWidth;

cs.cy = nHeight;

cs.hwndParent = hWndParent;

cs.hMenu = nIDorHMenu;

cs.hInstance = AfxGetInstanceHandle();

cs.lpCreateParams = lpParam;

if (!PreCreateWindow(cs))

{

PostNcDestroy();

return FALSE;

}

AfxHookWindowCreate(this);

HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass,

cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,

cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);

#ifdef _DEBUG

if (hWnd == NULL)

{

TRACE(traceAppMsg, 0, "Warning: Window creation failed: GetLastErro r returns 0x%8.8X\n",

GetLastError());

}

#endif

if (!AfxUnhookWindowCreate())

PostNcDestroy(); // cleanup if CreateWindowEx fails too soon

if (hWnd == NULL)

return FALSE;

ASSERT(hWnd == m_hWnd); // should have been set in send msg hook return TRUE;

}

可以看到,::CreateWindowEx是一个全局的函数,在其中触发WM_CREATE消息,进而调用我们自己定义的CMainFrame::OnCreate()

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)

return -1;

if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP

| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))

MFC经典绘图方法总结

MFC经典绘图方法总结 Windows 绘图的实质就是利用windows提供的图形设备接口GDI(Graphics Device Interface)将图形会制在显示器上。 为了支持GDI绘图,MFC提供了两种重要的类: 设备上下文DC(Device Context)类,用于设置绘图属性和绘制图形; 绘图对象类,封装了各种GDI绘图对象,包括画笔、刷子、字体、位图、调色板和区域。 CDC类介绍: 在MFC中,CDC是设备上下文类的基类,派生类包括:CClientDC, CPaintDC, CWindowDC, CMetaFileDC类 CClientDC 客户区设备上下文,绘制客户区时 CPaintDC 一般发生在窗口需要重绘时 CWindwDC 可以绘制整个窗口,通常在窗口WM_NCPAINT消息的响应函数CWnd::OnNCPaint()中使用 CMetaFileDC 专门用于图元文件的绘制,图元文件记录一组GDI命令,重建图形输出。 CDC包含m_hDC和m_hAttribDC二个设备上下文。CDC指导所有对m_hDC的输出GDI调用(SetTextColor)以及对m_hAttribDC的大部分属性GDI调用(GetTextColor)。 CDC对象的重要函数如下: 1、为指定设备创建上下文virtual BOOL CreateDC(...) 比如创建一个为屏幕的设备上下文 CDC dc; dc.CreateDC("DISPLAY", NULL, NULL,NULL); 2、创建内存设备上下文,与指定设备上下文兼容virtual BOOL CreateCompatibleDC( CDC * pDC) 3、删除CDC对象对应的Windows设备上下文, 通常不调用该函数而是使用析构程序virtual BOOL DeleteDC(); 4、将HDC句柄转化为设备上下文的句柄: CDC *pDC=CDC::FromHandle( hDC ) 5、选择GDI对象入选到设备上下文中,一共有五种形式: CPen * SelectObject( CPen * pPen) ; CBrush * SelectObject( CBrush * pBrush) ; virtual CFont * SelectObject( CFont * pFont) ; CBitmap * SelectObject( CBitmap * pBitmap) ; int SelectObject( CRgn * pRgn) ;

MFC程序结构分析

MFC程序结构分析2008-11-08 16:39 分类:VC\MFC 字号:大中小 1 Windows程序工作原理 WINDOWS 程序设计是一种完全不同于传统的DOS 方式的程序设计方法,它是一种事件驱动方式的程序设计模式。在程序提供给用户的界面中有许多可操作的可视对象。用户从所有可能的操作中任意选择,被选择的操作会产生某些特定的事件,这些事件发生后的结果是向程序中的某些对象发出消息,然后这些对象调用相应的消息处理函数来完成特定的操作。WINDOWS 应用程序最大的特点就是程序没有固定的流程,而只是针对某个事件的处理有特定的子流程,WINDOWS 应用程序就是由许多这样的子流程构成的。 从上面的讨论中可以看出,WINDOWS 应用程序在本质上是面向对象的。程序提供给用户界面的可视对象在程序的内部一般也是一个对象,用户对可视对象的操作通过事件驱动模式触发相应对象的可用方法。程序的运行过程就是用户的外部操作不断产生事件,这些事件又被相应的对象处理的过程。下面是WINDOWS 程序工作原理的示意图。 2 建立应用程序 在介绍AppWizard 的时候,我们已经建立了一个名字为TEST 的工程,事实上这个框

架程序已经可以编译运行了。在BUILD 菜单中选择REBUILD ALL 菜单项,系统开始编译由 APPWIZARD 自动生成的程序框架中所有文件中的源代码,并且链接生成可执行的应用程 序。在BUILD 菜单中选择EXECUTE 菜单项,应用程序就开始开始运行了,虽然我们没有编 写一行代码,但是可以看出由系统自动生成的应用程序的界面已经有了一个标准WINDOWS 应用程序所需的几个组成部分,我们要做的事情是往这个应用程序添加必要的代码以完成 我们所需要的功能。 接下来将要对WINDOWS 自动生成的这个应用程序框架作详细的介绍,让你对MFC 方式的 WINDOWS 应用程序的工作原理有全面的认识,只有这样你才会知道应该如何往程序框架当 中添加需要的代码。 3 程序结构剖析 为了让您对MFC 方式的程序的框架有一个总体的认识,这里设计了一个表示程序中的 主要类之间的关系的图表:

MFC程序结构分析

主题: MFC深入浅出 1.MFC深入浅出 MFC概述 2. 3. 1.MFC是一个编程框架 2. 3.MFC (Microsoft Foundation Class Library) 中的各种类结 合起来构成了一个应用程序框架,它的目的就是让程序员在此基础 上来建立Windows下的应用程序,这是一种相对SDK来说更为简单 的方法。因为总体上,MFC框架定义了应用程序的轮廓,并提供了 用户接口的标准实现方法,程序员所要做的就是通过预定义的接口 把具体应用程序特有的东西填入这个轮廓。Microsoft Visual C++ 提供了相应的工具来完成这个工作:AppWizard可以用来生成初步 的框架文件(代码和资源等);资源编辑器用于帮助直观地设计用 户接口;ClassWizard用来协助添加代码到框架文件;最后,编译, 则通过类库实现了应用程序特定的逻辑。 4. 5. 6. 7. 1.封装 2. 3.构成MFC框架的是MFC类库。MFC类库是C++类库。这 些类或者封装了Win32应用程序编程接口,或者封装了应用 程序的概念,或者封装了OLE特性,或者封装了ODBC和DAO 数据访问的功能,等等,分述如下。 4. 5.(1)对Win32应用程序编程接口的封装 6. 7.用一个C++ Object来包装一个Windows Object。例 如:class CWnd是一个C++ window object,它把Windows window(HWND)和Windows window有关的API函数封装在C++ window object的成员函数内,后者的成员变量m_hWnd就 是前者的窗口句柄。 8. 9.(2)对应用程序概念的封装

MFC原理结构说明

JEI
N.
MFC 原理結構說明
捷胤工業有限公司 總合研究所 (JISC)
CO .
LT D
捷胤工業有限公司 NEW JEIN Corp. Corp.

JEI
? 質流控制器(Mass?Flow?Controller)簡稱 MFC。簡 易的詮釋 MFC 是一種流量與控制閥組的精密組機 電組合,其測量方式與一般流量計最大的差別, 是在於它是利用熱感溫差 非接觸方式測量氣體 是在於它是利用熱感溫差、非接觸方式測量氣體 之質量流速。
N.
MFC 簡介
? MFC 應用於I C 工業、真空工業、食品工業、化 學工業以及醫療儀器等行業,需要求高精確度、 高穩定度及高品質等氣體流量控制,如:蝕刻、 物理 化學氣相沉積 高穩定度來達成 其應用 物理、化學氣相沉積、高穩定度來達成,其應用 之層面乃遍佈高科技產業。
CO .
LT D
捷胤工業有限公司 NEW JEIN Corp. Corp.

JEI
Intel
Connector
N.
MFC 主要結構
Mass flow sensor
CO .
Bypass
Zero switch
LT D
Control valve Outlet Block
PCB
捷胤工業有限公司 NEW JEIN Corp. Corp.

JEI
? 製程氣體中許多是有腐蝕性或容易液
化的氣體,其與氣體接觸的部份均是 化的氣體 其與氣體接觸的部份均是 以抗腐蝕性強的 SUS‐316L 做為材質, 整顆鑄造而成。
N.
MFC 本體 (Block)
CO .
LT D
捷胤工業有限公司 NEW JEIN Corp. Corp.

MFC视图结构框架分析

MFC文档视图结构框架分析 1:程序的“导火索”---theApp CmyApp theApp; 在声明对象的同时,调用其构造函数。按C++的语法,首先要调用其基类Cwinapp的构造函数. 这个文件主要用于应用程序的一些初始化操作。 class CWinApp : public CWinThread { DECLARE_DYNAMIC(CWinApp) public: // Constructor CWinApp(LPCTSTR lpszAppName = NULL); ………… } CWinApp::CWinApp(LPCTSTR lpszAppName) { if (lpszAppName != NULL) m_pszAppName = _tcsdup(lpszAppName); else m_pszAppName = NULL; // initialize CWinThread state AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE(); AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread; ASSERT(AfxGetThread() == NULL); pThreadState->m_pCurrentWinThread = this; ASSERT(AfxGetThread() == this); m_hThread = ::GetCurrentThread(); m_nThreadID = ::GetCurrentThreadId();

《MFC》综合开发案例分析1

、八 前言 21 世纪最激烈的竞争当属人才的竞争,一个具有多学科知识的复合性人才或许是一个企业发展壮大所不可或缺的重要因素。因此,企业人事管理工作的好坏不但可以直接影响到企业的人力资源管理,而且会间接的影响到企业整体管理。随着社会的发展,科技的进步,计算机的应用在社会各领域中都得到了普及,越来越多的人都感受到利用计算机进行各类管理的科学和便捷;认识到管理信息系统对于管理工作的重要性。利用计算机对企业人事进行管理是必然趋势,人事管理系统是企业管理工作中不可缺少的。所以在这次课程设计中,我选择开发人事管理系统。人事管理系统的功能主要有增加记录,删除记录,筛选记录,排序记录。这就要求它应该能够为用户提供有好美观的窗口界面、充足可靠的信息数据、简单方便的维护手段和灵活多变的查询方式以及快捷而准确的查询结果。所以,对于人事管理系统的设计主要包括数据库的建立、维护以及应用程序的开发两个方面。对于前者而言要求建立起数据一致性及完整性强、数据安全性好的数据库。对于后者而言则要求具备应用程序功能全, 易使用等,运行稳定等特点。因此,拟选用的开发软件是Microsoft 公司出品的Visual C++6.0 MFC 平台进行系统的开发。

目录 1 课题综述 (1) 1.1 人事管理信息系统来源 (1) 1.2 人事管理系统的意义 (1) 1.3 预期目标 (2) 1.4 面对的问题 (2) 1.5 需解决的关键技术等 .............................................. 2 2 人事管理系统分析 (2) 2.1 涉及的基础知识 (3) 2.2 解决问题的基本思路 (11) 2.3 总体方案 (11) 2.4 功能模块框图 (11) 3.1 部署连接(图) (12) 3.2 算法描述 (12) 3.3 详细流程图 .................................................. 14 4 代码编写 4.1 增加记录的代码 . (15) 4.2 删除记录的代码 (16) 4.3 排序记录的代码 (17) 4.4 筛选记录的代码 ................................................ 17 5 运行与测试 3 人事管理系统设计 ....................... 12 15 18

MFC 通用控件祥解解析

CHeadCtrl 表头控制(CHeaderCtrl)通常应用在窗口中的文本或数据的列表之上。一般为数据列的标题,可以包括多个部分,用户可以拖动每个部分并可以控制每列的宽度。表头控制类提供了普通表头控制的基本方法,只有在WINDOWS95以后版本系统中才提供,其方法包含在afxcmn.h文件中,一般与标签控制(CTabCtrl)和列表控制(CListCtrl)组合使用。 (一)表头控制的对象结构 1、表头控制对象的建立方法 CHeaderCtrl &cheaderCtrl 建立表头控制对象 Create 建立表头并绑定对象 CHeaderCtrl::Create的格式如下:BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID ); 其返回值非零时初始化成功,否则失败。 参数dwStyle用来确定表头控制类型;rect用来确定表头控制的大小和位置;ParentWnd 用来确定表头控制的父窗口;nID用来表示表头控制的标志。 表头控制风格包括: HDS_BUTTONS 表示表头控制外观类似按钮; HDS_HORZ 表示表头控制为水平排列; HDS_VERT 表示表头控制为垂直排列; HDS_HIDDEN 表示表头控制为隐藏模式。 它也可以使用普通类控制风格,包括: CCS_BOTTOM 设置控制位置在父窗口的底部并与父窗口同样宽度; CCS_NODIVIDER 在控制顶部形成两个像素的高亮区; CCS_NOHILITE 在控制顶部形成一个像素的高亮区; CCS_NOMOVEY 在响应WM_SIZE消息时重置大小并水平排列;

MFC9.0类别组织框架图

MFC Hierarchy Chart Part 1 of 3 Classes Derived From CObject

MFC Hierarchy Chart Part 2 of 3 Classes That Derive From CCmdTarget or CWnd

? Microsoft Corporation. All Rights Reserved. Structures Run-Time Object Model Support Synchronization/Thread Support OLE Type Wrappers DHTML Support OLE Automation Types Controls Helper Classes Frame Windows Support Helper Template Manager Support Memory Management State Support Managed Types MFC Hierarchy Chart Part 3 of 3 Classes Not Derived From CObject Legend The Version 9.0 Feature Pack adds new classes to the Microsoft Foundation Class Library. New classes are indicated with a star. Managers, Control Support and Helper classes all provide logical and data support for individual controls or groups of controls. Managers have the word “Manager” in their name. They typically aggregate and coordinate functionality that would otherwise be handled by individual classes. Control Support classes usually provide logical and data support for individual controls. Note: All MFC classes are native C++ classes, with the exception of CWin32Windows, a managed type.

相关文档
最新文档