// Win32_test1.cpp : Defines the entry point for the application.
//修改时间:2017年9月26日17:29:48
#include "stdafx.h"
#include "resource.h"
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text
// Foward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance,//应用程序当前实例句柄
HINSTANCE hPrevInstance,//无用
LPSTR lpCmdLine,//命令行参数
int nCmdShow)//显示窗口风格
{
// TODO: Place code here.
MSG msg; //信息传送相关结构体
HACCEL hAccelTable; //快捷键
// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE/*字符串编号*/, szTitle/*接受资源的缓冲区*/, MAX_LOADSTRING/*缓冲区大小*/);/*字符串资源录入信息,这个信息是Win32_test1标题名(相当于别名)*/
LoadString(hInstance, IDC_WIN32_TEST1, szWindowClass, MAX_LOADSTRING);//szWindowClass是缓冲区名,IDC_WIN32_TEST1是菜单资源的ID,同时又是WIN32_TEST1的别名(有点神奇为什么要这样设计这个字串表?我测试过改变它菜单没有任何变化...*/
MyRegisterClass(hInstance);//初始化窗口并且注册窗口!
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow)) //创建窗口 返回0失败退出程序, 否则成功显示窗口
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_WIN32_TEST1);/*如果你很仔细会发现IDC_WIN32_TEST1这些ID名字可以和其他资源ID名相同,例如这个Hello!World代码,IDC_WIN32_TEST1有2个,一个是快捷键资源,另一个就是菜单栏资源.*/
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0)) //主消息循环
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))/*处理当前响应的窗口菜单栏快捷键消息(任何)处理时,需要把消息结构体msg的其他信息也录入*/
{
TranslateMessage(&msg);//翻译消息:虚拟键消息(msg)转换为字符消息
DispatchMessage(&msg);//分派消息:把这个已转化为字符的msg消息,给窗口程序并且窗口程序会作相应处理.
}
}
return msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
// COMMENTS:
//
// This function and its usage is only necessary if you want this code
// to be compatible with Win32 systems prior to the 'RegisterClassEx'
// function that was added to Windows 95. It is important to call this function
// so that the application will get 'well formed' small icons associated
// with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)//注册窗口类 就是在这里面引用自定义资源
{
WNDCLASSEX wcex; //定义窗口类
wcex.cbSize = sizeof(WNDCLASSEX); //窗口大小
wcex.style = CS_HREDRAW | CS_VREDRAW; //窗口风格
wcex.lpfnWndProc = (WNDPROC)WndProc; //窗口过程(消息循环)
wcex.cbClsExtra = 0; //分配类额外空间(字节数)
wcex.cbWndExtra = 0; //分配窗口实例额外空间(字节数)
wcex.hInstance = hInstance; //当前窗口实例句柄
wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_WIN32_TEST1);/*隐藏程序窗口时,显示在你桌面菜单栏的图标初始化,LPCTSTR强制转化ID为指向字符串的32位常量指针(Unicode编码)*/
wcex.hCursor = LoadCursor(NULL, IDC_ARROW); //初始窗口光标,NULL表示全部应用程序窗口的光标为这个
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); //初始画刷(用来画客户区的)
wcex.lpszMenuName = (LPCSTR)IDC_WIN32_TEST1; //菜单栏初始化(LPCSTR)强制转化为指向字符串的32位常量指针
wcex.lpszClassName = szWindowClass; //菜单类资源缓冲区,大概是把这个菜单句柄给系统申请空间.
wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); //初始化显示程序窗口左上角的小图标
return RegisterClassEx(&wcex);//注册窗口 以上是窗口初始化。
}
//
// FUNCTION: InitInstance(HANDLE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)//return false or true,成功返回true.
{
//窗口初始化:先创建窗口,成功后 显示出窗口
HWND hWnd;//用于保存当前窗口句柄
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, //创建窗口 并返回窗口句柄保存于hWnd.层叠方式
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);//默认窗口大小 无父窗口 无菜单 当前程序实例句柄 命令行参数
if (!hWnd)//判断是否创建成功若成功则继续
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);//显示窗口信息
UpdateWindow(hWnd); //更新窗口
return TRUE;
}
//
// FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
//
// PURPOSE: Processes messages for the main window.主窗口的消息过程
//
// WM_COMMAND - process the application menu 应用程序菜单过程 ??某些命令
// WM_PAINT - Paint the main window 画窗口工作
// WM_DESTROY - post a quit message and return //传送一个停止信息并且返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)//返回消息处理的结果,与收到的消息有关
{
int wmId, wmEvent;
PAINTSTRUCT ps;//存放绘制窗口的信息,有绘制句柄HDC,有绘制范围,之类的
HDC hdc;//hdc是客户区绘制范围的句柄。又称为:窗口的"设备描述表"的句柄
TCHAR szHello[MAX_LOADSTRING];//建立字串表资源 名字叫szHello 大小为MAX_LOADSTRING
LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);//存放进
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam); //低位命令?
wmEvent = HIWORD(wParam); //高位命令?这个还没用到.
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT://子对话框ABOUTBOX创建
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);//从一个对话框资源创建一个模态对话框
break;
case IDM_EXIT:
DestroyWindow(hWnd);//关闭对话框函数,在关闭对话框时会发出WM_DESTORY消息给hWnd句柄相应的窗口处理消息,
break; //而DefWindowProc是不处理WM_DESTORY的,而是消息循环函数WndProc
//会对WM_DESTORY消息进行处理!下面有WM_DESTORY处理
default: //正常按钮方式关闭对话框先后循序:WM_CLOSE,WM_DESTORY,WM_QUIT.
return DefWindowProc(hWnd, message, wParam, lParam);//返回句柄?
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);//绘图准备函数,指定将要绘图的窗口hWnd,指定要绘图的信息存放于结构体ps中。
// TODO: Add any drawing code here...
RECT rt;
GetClientRect(hWnd, &rt);//获取窗口客户区的大小,除了标题栏和菜单栏之外的地方。
DrawText(hdc/*设备描述表句柄*/, szHello/*将要绘制的字符串*/, strlen(szHello)/*字符串长度*/, &rt/*窗口客户区结构体*/, /*正文绘制选项*/DT_CENTER);//画文本水平居中显示Hello World!
EndPaint(hWnd, &ps);//释放绘图区["设备描述表"占的内存释放]
break;
case WM_DESTROY:
PostQuitMessage(0);//送一个WM_QUIT消息到消息队列,当线程从消息队列里得到WM_QUIT时,会退出消息循环将控制权返回系统
//返回给系统的值是消息WM_QUIT的wParam参数,而这个wParam参数就是这个nExitCode,称谓应用程序退出代码.
//return 0 的意思??补充:PostQuitMessage(nExitCode);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);//处理其他命令,我理解为是让下一条消息继续进来,无变化。
}
return 0;
}
// Mesage handler for about box.
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)//子窗口(通过按菜单栏的Help-About.弹出)
{
switch (message)
{
case WM_INITDIALOG://初始化窗口消息
return TRUE;
case WM_COMMAND://处理命令
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) //按OK或者右上角红X都会执行关闭窗口信息并返回TRUE
{
EndDialog(hDlg, LOWORD(wParam));//取消对话框
return TRUE;
}
break;
}
return FALSE;
}