【MFC】第一个窗口程序(整理)(3)

从控制台程序到窗口程序,还需要解决多个文件的问题。看到MFC创建的很多类型文件,初学者肯定 “忐忑不安”。

整理程序

从结构化编程的思想来看,独立的功能模块,应该封装成函数。同时为了方便管理,类似的功能模块可以集中在一起,不同的功能组应该分开管理。所以,对第一个窗口程序进行整理。

项目按功能划分为三大块:主函数、初始化、窗口函数

每块都按照一个头文件+一个源文件 的格式来设计,块之间功能的调用则只需要包含相应的头文件即可。合计 6 个文件:

【MFC】第一个窗口程序(整理)(3)

1、初始化函数分为两大功能:创建并注册窗口类, 根据注册的窗口类名创建主窗口

头文件 Init.h:

#ifndef INIT_H
#define INIT_H
#include "main.h"

HWND InitInstance(HINSTANCE hInstance,int nCmdShow);
BOOL InitApplication(HINSTANCE hInstance);

#endif

ifndef INIT_H

define INIT_H

……

endif

是通过预编译语句避免重复包含,如 A 包含 X 头文件,B 包含 X 和 A,这样就存在重复包含X的问题,但是可以利用文件名的唯一性(把 点换成 _ ),判断是否定义宏来避免。

还有更简单的方式: #pragma once 可以完成以上功能。

源文件: Init.cpp

#include "init.h"
#include "wndproc.h"

char szAppName[]="AppName"; //指定窗口类名称
char szTitle[]="Second API Application";   //窗口标题

BOOL InitApplication(HINSTANCE hInstance) //自定义函数
{
   WNDCLASS wc;           //利用系统提供的类型定义变量存储窗口类数据

   wc.style=CS_VREDRAW|CS_HREDRAW; //窗口类风格
   wc.lpfnWndProc=MainWndProc;  //指定窗口消息处理函数(Finit.cpp)
   wc.cbClsExtra=0;             //额外分配在类数据结构尾端的字段数
   wc.cbWndExtra=0;             //额外分配在应用程序运行副本尾端的字段数

   wc.hInstance=hInstance;      //应用程序实例句柄(来自WinMain函数)
   wc.hIcon=LoadIcon(hInstance,NULL);  //最小化时图标
   wc.hCursor=LoadCursor(NULL,IDC_ARROW);              //鼠标光标
   wc.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH); //背景颜色
   wc.lpszMenuName=NULL;        //窗口菜单
   wc.lpszClassName=szAppName;  //给窗口类起个名称
   return(RegisterClass(&wc));  //窗口类注册
}

//产生应用程序的主窗口,并以nCmdShow指定方式显示
HWND InitInstance(HINSTANCE hInstance,int nCmdShow) //自定义函数
{
   HWND hwnd;  //利用系统提供的类型定义窗口句柄

   hwnd = CreateWindow(//Windows系统接口函数(Windows API)
         szAppName,              //窗口类名称(在wc.lpszClassName中指定)
         szTitle,                //窗口标题
         WS_OVERLAPPEDWINDOW,               //窗口风格,无标题栏
         0,                      //窗口左上角x坐标
         0,                      //窗口左上角y坐标
         GetSystemMetrics(SM_CXFULLSCREEN),          //窗口宽度
         GetSystemMetrics(SM_CYFULLSCREEN)+60,       //窗口高度
         NULL,                   //父窗口句柄
         NULL,                   //窗口菜单句柄
         hInstance,              //程序实例句柄
         NULL                    //提供窗口使用的额外数据
       );

    if (!hwnd)
       return NULL;             //未能正常产生窗口

    //Windows系统接口函数(Windows API)
    ShowWindow(hwnd,nCmdShow);   //以nCmdShow指定方式显示窗口
    UpdateWindow(hwnd);          //更新用户区
    return hwnd;
}

类名和窗口标题做成了全局变量(尽量避免),另外,函数的命名可能与功能不太匹配。

2、窗口函数用于处理窗口消息,这是窗口应用程序关注的重点,MFC费尽心思就是想让程序员集中精力于处理消息响应,事与愿违,造成了MFC入门困难的窘境。

头文件:wndproc.h

#ifndef WNDPROC_H
#define WNDPROC_H
#include "main.h"

LRESULT CALLBACK MainWndProc(HWND hWnd,UINT message,
                            WPARAM wParam, LPARAM lParam);

#endif

源文件:wndproc.cpp

#include "wndproc.h"

LRESULT CALLBACK MainWndProc(HWND hWnd,UINT message,
                            WPARAM wParam, LPARAM lParam)
{
   switch (message)
   {
   case WM_ERASEBKGND:
       {

           HDC hdc = ::GetDC(hWnd);
           RECT rect;
           ::GetClientRect(hWnd,&rect);
           ::FillRect(hdc,&rect,(HBRUSH)::GetStockObject(WHITE_BRUSH));

           break;
           }
       /*
       case WM_PAINT:
           {
           PAINTSTRUCT ps;
           HDC hdc = ::BeginPaint(hWnd,&ps);
           RECT rect;
           ::GetClientRect(hWnd,&rect);
           ::FillRect(hdc,&rect,(HBRUSH)::GetStockObject(GRAY_BRUSH));
           ::EndPaint(hWnd,&ps);
           break;
           }*/

   case WM_CLOSE:
       {
           ::DestroyWindow(hWnd);
           break;
       }

   case WM_DESTROY:            //如果按下关闭按钮
        {
           PostQuitMessage(0); //发出关闭程序的消息
           break;
        }
   default:  //其他消息发给windows默认窗口处理函数
            return (DefWindowProc(hWnd,message,wParam,lParam));
   }
   return 0;
}

3、主函数,MFC屏蔽了主函数(编译的时候加入),让初学者对程序的流程很难理解,心怀忐忑

头文件:Main.h

#ifndef MAIN_H
#define MAIN_H
#include <windows.h>

#endif</windows.h>

在其他头文件中包含Main.h ,主要是需要 #include

源文件:Main.cpp

#include "main.h"
#include "init.h"

int WINAPI WinMain(HINSTANCE hInstance,    //&#x5E94;&#x7528;&#x7A0B;&#x5E8F;&#x5F53;&#x524D;&#x5B9E;&#x4F8B;&#x53E5;&#x67C4;
               HINSTANCE hPrevInstance,    //&#x5E94;&#x7528;&#x7A0B;&#x5E8F;&#x524D;&#x4E00;&#x4E2A;&#x5B9E;&#x4F8B;&#x53E5;&#x67C4;
               LPSTR lpCmdLine,            //&#x547D;&#x4EE4;&#x884C;&#x5B57;&#x7B26;&#x7A9C;&#x6307;&#x9488;
               int nCmdShow)               //&#x5E94;&#x7528;&#x7A0B;&#x5E8F;&#x7684;&#x663E;&#x793A;&#x65B9;&#x5F0F;
{

   HWND hwnd;       //&#x7A97;&#x53E3;&#x53E5;&#x67C4;
   MSG msg;          //&#x6D88;&#x606F;&#x7ED3;&#x6784;&#x53D8;&#x91CF;

   if (!InitApplication(hInstance))  //&#x82E5;&#x6CE8;&#x518C;&#x7A97;&#x53E3;&#x7C7B;&#x5931;&#x8D25;,&#x81EA;&#x5B9A;&#x4E49;&#x51FD;&#x6570;(Finit.cpp)
      return false;

   //&#x4EA7;&#x751F;&#x5E94;&#x7528;&#x7A0B;&#x5E8F;&#x7684;&#x4E3B;&#x7A97;&#x53E3;,&#x5E76;&#x4EE5;nCmdShow&#x6307;&#x5B9A;&#x65B9;&#x5F0F;&#x663E;&#x793A;,&#x81EA;&#x5B9A;&#x4E49;&#x51FD;&#x6570;(Finit.cpp)
   hwnd=InitInstance(hInstance,nCmdShow);
   if (!hwnd)
      return false;

   while (::GetMessage(&msg,NULL,NULL,NULL))
   {

         if (msg.message==WM_QUIT)  //&#x5982;&#x679C;&#x63A5;&#x53D7;&#x5230;&#x9000;&#x51FA;&#x7684;&#x6D88;&#x606F;WM_QUIT,&#x6574;&#x4E2A;&#x7A0B;&#x5E8F;&#x5C06;&#x7ED3;&#x675F;.

            break;
         TranslateMessage(&msg); //&#x628A;&#x952E;&#x76D8;&#x6D88;&#x606F;&#x7EC4;&#x5408;&#x6210;&#x76F8;&#x5BF9;&#x7684;&#x5B57;&#x7B26;&#x6D88;&#x606F;
         DispatchMessage(&msg);

   }

   return(msg.wParam);
}

Original: https://blog.csdn.net/yixiaobo2001/article/details/127801004
Author: 易老师
Title: 【MFC】第一个窗口程序(整理)(3)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/656771/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球