MFC Application

本文将引导你构建首个MFC应用——一个显示'Hello, MFC'的窗口。通过这个简单的程序,你将了解MFC如何用于编写Windows应用,涉及CWinApp和CFrameWnd类,以及类的继承和应用。还将学习CPaintDC类如何处理WM_PAINT消息,以及MFC的消息映射机制。" 113981774,10539178,Python通过ctypes调用C库详解,"['Python编程', 'ctypes库', 'C语言交互', '数据类型转换', '动态链接库调用']
部署运行你感兴趣的模型镜像

Your First MFC Application

It's time to build your first MFC application. And what better place to start than with one that displays "Hello, MFC" in a window? Based on the classic "Hello, world" program immortalized in Brian Kernighan and Dennis Ritchie's The C Programming Language (1988, Prentice-Hall), this very minimal program, which I'll call Hello, demonstrates the fundamental principles involved in using MFC to write a Windows application. Among other things, you'll get a close-up look at MFC's CWinApp and CFrameWnd classes and see firsthand how classes are derived from them and plugged into the application. You'll also learn about the all-important CPaintDC class, which serves as the conduit through which text and graphics are drawn in a window in response to WM_PAINT messages. Finally, you'll be introduced to message mapping, the mechanism MFC uses to correlate the messages your application receives with the member functions you provide to handle those messages.

Figure 1-3 lists the source code for Hello. Hello.h contains the declarations for two derived classes. Hello.cpp contains the implementations of those classes. Among C++ programmers, it's traditional to put class definitions in .h files and source code in .cpp files. We'll honor that tradition here and throughout the rest of this book. For large applications containing tens or perhaps hundreds of classes, it's also beneficial to put class declarations and implementations in separate source code files. That's overkill for the programs in the first few chapters of this book, but later on, when we begin working with documents and views, we'll give each class its own .h and .cpp files. On the CD in the back of the book, in the folder named Chap01, you'll find a folder with copies of Hello.h and Hello.cpp as well as a folder containing a copy of the compiled executable (Hello.exe).

Figure 1-3. The Hello application.

Hello.h

class CMyApp : public CWinApp
{
public:
    virtual BOOL InitInstance ();
};

class CMainWindow : public CFrameWnd
{
public:
    CMainWindow ();

protected:
    afx_msg void OnPaint ();
    DECLARE_MESSAGE_MAP ()
};

Hello.cpp

#include <afxwin.h>
#include "Hello.h"

CMyApp myApp;

/////////////////////////////////////////////////////////////////////////
// CMyApp member functions

BOOL CMyApp::InitInstance ()
{
    m_pMainWnd = new CMainWindow;
	

   m_pMainWnd->ShowWindow (m_nCmdShow);
    m_pMainWnd->UpdateWindow ();
    return TRUE;
}

/////////////////////////////////////////////////////////////////////////
// CMainWindow message map and member functions

BEGIN_MESSAGE_MAP (CMainWindow, CFrameWnd)
    ON_WM_PAINT ()
END_MESSAGE_MAP ()

CMainWindow::CMainWindow ()
{
    Create (NULL, _T ("The Hello Application"));
}

void CMainWindow::OnPaint ()
{
    CPaintDC dc (this);
    
    CRect rect;
    GetClientRect (&rect);

    dc.DrawText (_T ("Hello, MFC"), -1, &rect,
        DT_SINGLELINE ¦ DT_CENTER ¦ DT_VCENTER);
}

Figure 1-4 shows the output from Hello. When you run the application, notice that the window is entirely functional; you can move it, resize it, minimize it, maximize it, and close it. And when the window is resized, "Hello, MFC" is redrawn in the center of the window.

Most of Hello's functionality comes from Windows. Windows, for example, draws the exterior, or nonclient area, of the window: the title bar, the buttons on the title bar, and the window's border. It's your responsibility to create the window and process WM_PAINT messages indicating that all or part of the window's interior, or client area, needs updating. Let's examine the source code to see how Hello works.

Click to view at full size.

Figure 1-4. The Hello window.

The Application Object

The heart of an MFC application is an application object based on the CWinApp class. CWinApp provides the message loop that retrieves messages and dispatches them to the application's window. It also includes key virtual functions that can be overridden to customize the application's behavior. CWinApp and other MFC classes are brought into your application when you include the header file Afxwin.h. An MFC application can have one—and only one—application object, and that object must be declared with global scope so that it will be instantiated in memory at the very outset of the program.

Hello's application class is named CMyApp. It is instantiated in Hello.cpp with the statement

CMyApp myApp;

CMyApp's class declaration appears in Hello.h:

class CMyApp : public CWinApp
{
public:
    virtual BOOL InitInstance ();
};

CMyApp declares no data members and overrides just one function inherited from CWinApp. InitInstance is called early in the application's lifetime, right after the application starts running but before the window is created. In fact, unless InitInstance creates a window, the application doesn't have a window. That's why even a minimal MFC application must derive a class from CWinApp and override CWinApp::InitInstance.

The InitInstance Function

CWinApp::InitInstance is a virtual function whose default implementation contains just one statement:

return TRUE;

The purpose of InitInstance is to provide the application with the opportunity to initialize itself. The value returned by InitInstance determines what the framework does next. Returning FALSE from InitInstance shuts down the application. If initialization goes as planned, InitInstance should return TRUE in order to allow the program to proceed. InitInstance is the perfect place to perform initializations that need to be done each time the program starts. At the very least, this means creating the window that will represent the application on the screen.

CMyApp's implementation of InitInstance, which appears in Hello.cpp, creates the Hello window by instantiating Hello's CMainWindow class. The statement

m_pMainWnd = new CMainWindow;

constructs a CMainWindow object and copies its address to the application object's m_pMainWnd data member. After the window is created, InitInstance displays it—remember, a window is not initially visible unless it is created with a WS_VISIBLE attribute—by calling ShowWindow and UpdateWindow through the CMainWindow pointer:

m_pMainWnd->ShowWindow (m_nCmdShow);
m_pMainWnd->UpdateWindow ();

ShowWindow and UpdateWindow are CWnd member functions common to all window objects, including objects of the CFrameWnd class from which CMainWindow is derived. These functions are little more than wrappers around the API functions of the same name. To call a regular Windows API function from an MFC program, make it a practice to preface the function name with the global scope resolution operator ::, as in

::UpdateWindow (hwnd);

This notation will ensure that the API function is called even if the object that makes the call has a member function with the same name. In the remainder of this book, Windows API functions will be prefaced with :: to distinguish them from MFC member functions.

ShowWindow accepts just one parameter: an integer that specifies whether the window should initially be shown minimized, maximized, or neither minimized nor maximized. In accordance with Windows programming protocol, Hello passes ShowWindow the value stored in the application object's m_nCmdShow variable, which holds the nCmdShow parameter passed to WinMain. The m_nCmdShow value is usually SW_SHOWNORMAL, indicating that the window should be displayed in its normal unmaximized and unminimized state. However, depending on how the user starts an application, Windows will occasionally slip in a value such as SW_SHOWMAXIMIZED or SW_SHOWMINIMIZED. Unless there is a specific reason for it to do otherwise, InitInstance should always pass the m_nCmdShow variable instead of a hardcoded SW_ value to ShowWindow.

UpdateWindow completes the job that ShowWindow started by forcing an immediate repaint. Its work done, InitInstance returns TRUE to allow the application to proceed.

Other CWinApp Overridables

InitInstance is just one of several virtual CWinApp member functions you can override to customize the behavior of the application object. Look up the CWinApp overridables in your MFC documentation and you'll see a list of more than a dozen others with names such as WinHelp and ProcessWndProcException. Many of these functions are seldom overridden, but they're handy to have around nonetheless. For example, you can use ExitInstance to clean up when an application terminates. If you use InitInstance to allocate memory or other resources, ExitInstance is the perfect place to free those resources. The default implementation of ExitInstance performs some routine cleanup chores required by the framework, so you should be sure to call the base class version if you've overridden ExitInstance. Ultimately, the value returned by ExitInstance is the exit code returned by WinMain.

Other interesting CWinApp overridables include OnIdle, Run, and PreTranslateMessage. OnIdle is handy for performing background processing chores such as garbage collection. Because OnIdle is called when an application is "idle"—that is, when there are no messages waiting to be processed—it provides an excellent mechanism for performing low-priority background tasks without spawning a separate thread of execution. OnIdle is discussed at length in Chapter 14. You can override Run to customize the message loop, replacing it with a message loop of your own. If you just want to perform some specialized preprocessing on certain messages before they are dispatched, you can override PreTranslateMessage and save yourself the trouble of writing a whole new message loop.

How MFC Uses the Application Object

To someone who has never seen an MFC application's source code, one of the more remarkable aspects of Hello will be that it contains no executable code outside of the classes it defines. It has no main or WinMain function, for example; the only statement in the entire program that has global scope is the statement that instantiates the application object. So what actually starts the program running, and when does the application object come into the picture?

The best way to understand what goes on under the hood is to look at the framework's source code. One of the source code files provided with MFC—Winmain.cpp—contains an AfxWinMain function that is MFC's equivalent of WinMain. (That's right: when you purchase Visual C++, you get the source code for MFC, too.) AfxWinMain makes extensive use of the application object, which is why the application object must be declared globally. Global variables and objects are created before any code is executed, and the application object must be extant in memory before AfxWinMain starts.

Right after starting, AfxWinMain calls a function named AfxWinInit to initialize the framework and copy hInstance, nCmdShow, and other AfxWinMain function parameters to data members of the application object. Then it calls InitApplication and InitInstance. In 16-bit versions of MFC, InitApplication is called only if the hPrevInstance parameter passed to AfxWinMain is NULL, indicating that this is the only instance of the application currently running. In the Win32 environment, hPrevInstance is always NULL, so the framework doesn't bother to check it. A 32-bit application could just as easily use InitApplication to initialize itself as InitInstance, but InitApplication is provided for compatibility with previous versions of MFC and should not be used in 32-bit Windows applications. If AfxWinInit, InitApplication, or InitInstance returns 0, AfxWinMain terminates instead of proceeding further and the application is shut down.

Only if all of the aforementioned functions return nonzero values does AfxWinMain perform the next critical step. The statement

pThread->Run();

calls the application object's Run function, which executes the message loop and begins pumping messages to the application's window. The message loop repeats until a WM_QUIT message is retrieved from the message queue, at which point Run breaks out of the loop, calls ExitInstance, and returns to AfxWinMain. After doing some last-minute cleaning up, AfxWinMain executes a return to end the application.

您可能感兴趣的与本文相关的镜像

Python3.11

Python3.11

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

<think>我们正在处理用户关于下载特定版本的MFC应用程序框架或模板的请求,特别是关于Piped MFC Application模板或示例代码。 根据用户提供的信息,我们有两个引用: 引用[1]提到的是关于Piped的安装过程,它似乎是一个命令行工具,与MFC无关。 引用[2]提到的是DesignWare中一个名为DW_lp_piped_mult的模块,看起来是一个硬件设计模块,与MFC无关。 因此,这两个引用似乎与用户的需求(下载MFC应用程序模板)不直接相关。 但是,用户提到了“Piped MFC Application”,这可能是用户的一个特定需求,但根据我们的知识库,并没有直接叫做“Piped MFC Application”的官方模板。 考虑到MFC(Microsoft Foundation Classes)是微软提供的一个库,用于开发Windows桌面应用程序。通常,获取MFC相关的模板或示例代码可以通过以下途径: 1. 安装Visual Studio时选择MFC组件,这样就会包含一些MFC应用程序模板。 2. 在微软官方文档或GitHub上搜索MFC示例代码。 由于用户提到了“Piped”,可能是指某种特定的应用程序类型(比如管道相关的应用),我们可以建议用户: - 在Visual Studio中创建MFC应用程序时,选择适当的模板(如对话框应用程序、单文档应用程序等),然后自行添加管道通信功能。 - 或者搜索微软提供的示例代码库,看是否有管道通信的MFC示例。 因此,我们可以这样回答用户: 首先,MFC应用程序模板通常包含在Visual Studio安装中。请确保在安装Visual Studio时选择了“使用C++的桌面开发”工作负载,并勾选“MFC和ATL支持”。 其次,关于“Piped”(管道)功能,这可能是您希望在应用程序中实现的进程间通信(IPC)功能。Windows提供了命名管道的API,您可以在MFC应用程序中调用这些API(如CreateNamedPipe, ConnectNamedPipe等)。微软提供了一些使用命名管道的示例代码,但这些示例通常不是特定于MFC的,而是Win32的。不过,您可以将这些API集成到MFC应用程序中。 如果您需要特定的“Piped MFC Application”模板,可能没有现成的官方模板。但是,我们可以通过以下步骤获得: 1. 创建一个基本的MFC应用程序(例如基于对话框的应用程序)。 2. 添加命名管道通信的代码。 我们也可以搜索微软的官方示例库,看看是否有类似的示例。例如,在Microsoft Docs上可以找到命名管道服务器的示例代码(Win32),您可以将其集成到MFC项目中。 此外,您也可以在网上搜索第三方提供的MFC管道通信示例。 因此,回答如下:</think>### 下载 MFC 应用程序模板的指南 如果您需要下载特定版本的 **MFC 应用程序框架模板**(特别是与管道功能相关的实现),以下是详细步骤: #### 1. **通过 Visual Studio 安装官方模板** - 打开 Visual Studio(建议 2019 或更高版本) - 创建新项目 → 搜索 "MFC" → 选择 **MFC Application** 模板 - 在配置向导中勾选所需功能(如管道通信、多文档界面等) - 安装后模板将保存在默认路径(例如:`C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\ProjectTemplates`) #### 2. **下载微软官方示例代码** - 访问 [Microsoft Docs 示例库](https://github.com/microsoft) - 搜索关键词: - `MFC Pipe Example` - `MFC Named Pipe` - `MFC Inter-process Communication` - 推荐仓库:[MFC 示例合集](https://github.com/microsoft/Windows-classic-samples/tree/main/Samples/Win7Samples/winui/shell/appplatform/MFC) - 克隆或下载 ZIP 包后,在 Visual Studio 中打开 `.sln` 文件即可使用 #### 3. **第三方资源获取** - **CodeProject 管道示例**: [MFC Named Pipes IPC Example](https://www.codeproject.com/Articles/1179195/MFC-Named-Pipes-IPC-Example)(含完整模板) - **GitHub 自定义模板**: [MFC-Pipe-Application-Template](https://github.com/search?q=MFC+Pipe+Application+Template&type=repositories) #### 4. **手动集成管道功能** 若需将管道通信嵌入现有 MFC 应用: ```cpp // 命名管道服务端示例 HANDLE hPipe = CreateNamedPipe( L"\\\\.\\pipe\\MyPipe", // 管道名称 PIPE_ACCESS_DUPLEX, // 读写模式 PIPE_TYPE_MESSAGE | PIPE_WAIT, // 消息模式+阻塞 1, // 最大实例数 1024, 1024, // 输入/输出缓冲区 0, // 超时设置 NULL // 安全属性 ); ``` > 完整代码参考:[微软管道 API 文档](https://docs.microsoft.com/en-us/windows/win32/ipc/named-pipes)[^1] --- ### 关键注意事项 1. **版本兼容性**: - MFC 模板需匹配 Visual Studio 版本(如 VS2022 模板不兼容 VS2017) 2. **管道参数配置**: 根据通信需求调整缓冲区大小和超时设置,避免数据阻塞[^2] 3. **安全机制**: 建议启用 `SECURITY_ATTRIBUTES` 控制客户端访问权限 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值