从控制台程序到窗口程序,还需要解决多个文件的问题。看到MFC创建的很多类型文件,初学者肯定 “忐忑不安”。
整理程序
从结构化编程的思想来看,独立的功能模块,应该封装成函数。同时为了方便管理,类似的功能模块可以集中在一起,不同的功能组应该分开管理。所以,对第一个窗口程序进行整理。
项目按功能划分为三大块:主函数、初始化、窗口函数
每块都按照一个头文件+一个源文件 的格式来设计,块之间功能的调用则只需要包含相应的头文件即可。合计 6 个文件:
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, //应用程序当前实例句柄
HINSTANCE hPrevInstance, //应用程序前一个实例句柄
LPSTR lpCmdLine, //命令行字符窜指针
int nCmdShow) //应用程序的显示方式
{
HWND hwnd; //窗口句柄
MSG msg; //消息结构变量
if (!InitApplication(hInstance)) //若注册窗口类失败,自定义函数(Finit.cpp)
return false;
//产生应用程序的主窗口,并以nCmdShow指定方式显示,自定义函数(Finit.cpp)
hwnd=InitInstance(hInstance,nCmdShow);
if (!hwnd)
return false;
while (::GetMessage(&msg,NULL,NULL,NULL))
{
if (msg.message==WM_QUIT) //如果接受到退出的消息WM_QUIT,整个程序将结束.
break;
TranslateMessage(&msg); //把键盘消息组合成相对的字符消息
DispatchMessage(&msg);
}
return(msg.wParam);
}
Original: https://blog.csdn.net/yixiaobo2001/article/details/127801004
Author: 易老师
Title: 【MFC】第一个窗口程序(整理)(3)
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/656771/
转载文章受原作者版权保护。转载请注明原作者出处!