- 了解窗口
每个GUI应用程序至少要创建一个窗口,称为主窗口。每个窗口都在显示输出和从用户取得输入方面起着一定的作用。
窗口客户区是应用程序显示输出的部分。应用程序必须提供一个称为窗口函数的回调函数来处理窗口的输入,向客户区显示输出。
- 第一个窗口程序
int APIENTRY WinMain(
HINSTANCE hInstance, //本模块的实例句柄
HINSTANCE hPrevInstance, //win16留下的产物,现在已经不用了
LPSTR lpCmdLine, //命令行参数
int nCmdShow //主窗口初始化时的显示方式
)
GUI应用程序的入口函数是WinMain,这是一个自定义的回调函数。
APIENTRY的宏定义是__stdcall
hInstance = (HINSTANCE)GetModuleHandle(NULL); //取得应用程序的实例句柄(即模块句柄)
参数为NULL时,返回可执行文件所在模块的模块句柄,而不管是在哪个模块中做调用的。
int MessageBox(
HWND hWnd, //一个窗口句柄,它指定哪一个窗口将拥有要创建的消息框
LPCTSTR lpText, //将要显示的消息
LPCTSTR lpCaption, //对话框标题
UINT uType //指定对话框的内容和行为
);
返回值:
IDOK、IDYES、IDNO、IDCANCEL、IDABORT、IDRETRY、IDIGNORE等
-
MessageBox中的uType参数
-
示例:简单的win32
// 04Win32AppDemo.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// 弹出一个对话框
MessageBox(NULL,"Hello,Win32 Application","04Win32AppDemo",MB_OK);
MessageBox(NULL,"Hello,Win32 Application","04Win32AppDemo",MB_YESNOCANCEL|MB_ICONQUESTION|MB_DEFBUTTON3)
return 0;
}
- windows消息驱动
鼠标或键盘在桌面操作时,windows会源源不段地向程序发送消息,操作这个过程的函数为窗口函数。原型如下:
LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
CALLBACK 宏定义是__stdcall
uMsg:消息ID号,诸如MessageBox中的IDYES等等
wParam和lParam是消息ID的附加参数
- 示例:收到WM_CLOSE消息关闭窗口
// 04TellToClose.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "windows.h"
#include "stdio.h"
int main(int argc, char* argv[])
{
HWND hWnd = FindWindow(NULL,"无标题 - 记事本");
if(hWnd != NULL)
{
//向目标窗口发送WM_CLOSE消息
SendMessage(hWnd,WM_CLOSE,0,0);
}
return 0;
}
桌面显示一个窗口的具体步骤:
- 注册窗口类(RegisterClassEx)
- 创建窗口 (CreateWindowEx)
- 在桌面显示窗口 (ShowWindow)
- 更新窗口客户区(UpdateWindow)
- 进入无限的消息循环处理
- 获取消息GetMessage
- DispatchMessage
- 消息处理MainWndProc函数
示例:最简单的windows程序
// 04FirstWindow.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "windows.h"
#include "stdio.h"
LRESULT CALLBACK MainWndProc(HWND,UINT,WPARAM,LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
char szClassName[] = "MainClass";
WNDCLASSEX wndclass;
//用于描述主窗口的参数填充WNDCLASSEX结构
wndclass.cbSize = sizeof(wndclass); //结构的大小
wndclass.style = CS_HREDRAW | CS_VREDRAW; //指定如果大小改变就重画
wndclass.lpfnWndProc = MainWndProc; //窗口函数指针
wndclass.cbClsExtra = 0; //没有额外的类内存
wndclass.cbWndExtra = 0; //没有额外的窗口内存
wndclass.hInstance = hInstance; //实例句柄
wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION); //使用预定义图标
wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); //使用预定义光标
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //使用白色背景画刷
wndclass.lpszMenuName = NULL; //不指定菜单
wndclass.lpszClassName = szClassName; //窗口类的名称
wndclass.hIconSm = NULL; //没有类的小图标
//注册这个窗口类
RegisterClassEx(&wndclass);
//创建主窗口
HWND hwnd = CreateWindowEx(
0, //dwExSytle,扩展
szClassName, //lpClassName,窗口类名
"My first Window!", //lpWindowName,标题
WS_OVERLAPPEDWINDOW, //dwStyle,窗口风格
CW_USEDEFAULT, //X,初始化X坐标
CW_USEDEFAULT, //y,初始化Y坐标
CW_USEDEFAULT, //nWidth,宽度
CW_USEDEFAULT, //nHeight,高度
NULL, //hWindParent 父窗口句柄
NULL, //hMenu 菜单句柄
hInstance, //hInstance,程序实例句柄
NULL //lpParam,用户数据
);
if(hwnd == NULL)
{
MessageBox(NULL,"创建窗口出错!","error",MB_OK);
return -1;
}
//显示窗口,刷新窗口客户区
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
//从消息队列中取出消息,交给窗口函数处理,直到GetMessage返回FALSE,结束消息循环
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
//转化为键盘消息
TranslateMessage(&msg);
//将消息发送到相应的窗口函数
DispatchMessage(&msg);
}
//当GetMessage返回FALSE时程序结束
return msg.wParam;
}
LRESULT CALLBACK MainWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
char szText[] = "最简单的窗口程序";
switch(message)
{
case WM_PAINT: //窗口客户区需要重画
{
HDC hdc;
PAINTSTRUCT ps;
//使无效的客户区变的有效,并取得设备环境句柄
hdc = BeginPaint(hwnd,&ps);
//显示文字
TextOut(hdc,10,10,szText,strlen(szText));
EndPaint(hwnd,&ps);
return 0;
}
case WM_DESTROY: //正在销毁窗口
//向消息队列发送一个WM_QUIT消息,促使GetMessage函数返回0,结束消息循环
PostQuitMessage(0);
return 0;
}
//我们不处理的消息交给系统做默认处理
return DefWindowProc(hwnd,message,wParam,lParam);
}
- 使用资源
资源是一些二进制数据,它能够添加到基于窗口的应用程序的可执行文件中。资源的源文件是以.rc为扩展名的脚本文件。
在原来的工程下新建一个资源脚本,命令为resource
程序左侧会生成一个resource.rc文件和resource.h文件(隐藏,得去工程目录下查找)
IDI_ICON1和IDR_TYPER可以自定义,且在函数中会使用到
然后右键resource.rc文件,选择插入图标和菜单
插入菜单举例右键打开:
里面的内容通过修改标明项即可自定义内容
ID可以设置为ID_FILE_EXIT
#include "stdafx.h"
#include "windows.h"
#include "stdio.h"
#include "resource.h"
LRESULT CALLBACK MainWndProc(HWND,UINT,WPARAM,LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
char szClassName[] = "MainClass";
WNDCLASSEX wndclass;
//用于描述主窗口的参数填充WNDCLASSEX结构
wndclass.cbSize = sizeof(wndclass); //结构的大小
wndclass.style = CS_HREDRAW | CS_VREDRAW; //指定如果大小改变就重画
wndclass.lpfnWndProc = MainWndProc; //窗口函数指针
wndclass.cbClsExtra = 0; //没有额外的类内存
wndclass.cbWndExtra = 0; //没有额外的窗口内存
wndclass.hInstance = hInstance; //实例句柄
wndclass.hIcon = LoadIcon(hInstance,(LPSTR)IDI_ICON1); //使用预定义图标
wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); //使用预定义光标
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //使用白色背景画刷
wndclass.lpszMenuName = (LPSTR)IDR_TYPER; //指定自定义的菜单
wndclass.lpszClassName = szClassName; //窗口类的名称
wndclass.hIconSm = NULL; //没有类的小图标
//注册这个窗口类
RegisterClassEx(&wndclass);
//创建主窗口
HWND hwnd = CreateWindowEx(
0, //dwExSytle,扩展
szClassName, //lpClassName,窗口类名
"My first Window!", //lpWindowName,标题
WS_OVERLAPPEDWINDOW, //dwStyle,窗口风格
CW_USEDEFAULT, //X,初始化X坐标
CW_USEDEFAULT, //y,初始化Y坐标
CW_USEDEFAULT, //nWidth,宽度
CW_USEDEFAULT, //nHeight,高度
NULL, //hWindParent 父窗口句柄
NULL, //hMenu 菜单句柄
hInstance, //hInstance,程序实例句柄
NULL //lpParam,用户数据
);
if(hwnd == NULL)
{
MessageBox(NULL,"创建窗口出错!","error",MB_OK);
return -1;
}
//显示窗口,刷新窗口客户区
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
//从消息队列中取出消息,交给窗口函数处理,直到GetMessage返回FALSE,结束消息循环
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
//转化为键盘消息
TranslateMessage(&msg);
//将消息发送到相应的窗口函数
DispatchMessage(&msg);
}
//当GetMessage返回FALSE时程序结束
return msg.wParam;
}
LRESULT CALLBACK MainWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
char szText[] = "最简单的窗口程序";
switch(message)
{
case WM_PAINT: //窗口客户区需要重画
{
HDC hdc;
PAINTSTRUCT ps;
//使无效的客户区变的有效,并取得设备环境句柄
hdc = BeginPaint(hwnd,&ps);
//显示文字
TextOut(hdc,10,10,szText,strlen(szText));
EndPaint(hwnd,&ps);
return 0;
}
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_FILE_EXIT:
//向hwnd指定的窗口发送一个WM_CLOSE消息
SendMessage(hwnd,WM_CLOSE,0,0);
break;
}
return 0;
case WM_CLOSE: //任务管理器还是能干掉
return 0;
case WM_DESTROY: //正在销毁窗口
//向消息队列发送一个WM_QUIT消息,促使GetMessage函数返回0,结束消息循环
PostQuitMessage(0);
return 0;
}
//我们不处理的消息交给系统做默认处理
return DefWindowProc(hwnd,message,wParam,lParam);
}
生成的图标和菜单如下所示:图标是瞎画的
单击菜单会发送WM_COMMAND消息,而wParam低字节包含了用户单击菜单的ID号
- 接受键盘输入消息
按下一个键时,windows会获得窗口消息队列中传递的WM_KEYDOWN或WM_SYSKEYDOWN消息。释放这个键时,会产生WM_KEYUP或WM_SYSTEMKEYUP消息。 - wParam
wParam包含敲击键的虚拟键码,也包含按键的ANSI码,比如敲“A”键,窗口会受到3个消息:
WM_KETDOWN lParam的含义为虚拟键码“A”(0x41)
WM_CHAR lParam的含义为虚拟键码“a”(0x61)
WM_KEYUP lParam的含义为虚拟键码“A”(0x41)
示例:打字程序
#include "stdafx.h"
#include "windows.h"
#include "stdio.h"
#include "resource.h"
#include <string>
LRESULT CALLBACK MainWndProc(HWND,UINT,WPARAM,LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
char szClassName[] = "MainClass";
WNDCLASSEX wndclass;
//用于描述主窗口的参数填充WNDCLASSEX结构
wndclass.cbSize = sizeof(wndclass); //结构的大小
wndclass.style = CS_HREDRAW | CS_VREDRAW; //指定如果大小改变就重画
wndclass.lpfnWndProc = MainWndProc; //窗口函数指针
wndclass.cbClsExtra = 0; //没有额外的类内存
wndclass.cbWndExtra = 0; //没有额外的窗口内存
wndclass.hInstance = hInstance; //实例句柄
wndclass.hIcon = LoadIcon(hInstance,(LPSTR)IDI_ICON1); //使用预定义图标
wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); //使用预定义光标
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //使用白色背景画刷
wndclass.lpszMenuName = (LPSTR)IDR_TYPER; //指定自定义的菜单
wndclass.lpszClassName = szClassName; //窗口类的名称
wndclass.hIconSm = NULL; //没有类的小图标
//注册这个窗口类
RegisterClassEx(&wndclass);
//创建主窗口
HWND hwnd = CreateWindowEx(
0, //dwExSytle,扩展
szClassName, //lpClassName,窗口类名
"My first Window!", //lpWindowName,标题
WS_OVERLAPPEDWINDOW, //dwStyle,窗口风格
CW_USEDEFAULT, //X,初始化X坐标
CW_USEDEFAULT, //y,初始化Y坐标
CW_USEDEFAULT, //nWidth,宽度
CW_USEDEFAULT, //nHeight,高度
NULL, //hWindParent 父窗口句柄
NULL, //hMenu 菜单句柄
hInstance, //hInstance,程序实例句柄
NULL //lpParam,用户数据
);
if(hwnd == NULL)
{
MessageBox(NULL,"创建窗口出错!","error",MB_OK);
return -1;
}
//显示窗口,刷新窗口客户区
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
//从消息队列中取出消息,交给窗口函数处理,直到GetMessage返回FALSE,结束消息循环
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
//转化为键盘消息
TranslateMessage(&msg);
//将消息发送到相应的窗口函数
DispatchMessage(&msg);
}
//当GetMessage返回FALSE时程序结束
return msg.wParam;
}
LRESULT CALLBACK MainWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
//str对象用于保存窗口客户区显示的字符串
//为了使用string类,包含头文件#include <string>
static std::string str;
char szText[] = "最简单的窗口程序";
switch(message)
{
case WM_CREATE:
{
//设置窗口的标题
SetWindowText(hwnd,"最简陋的打字程序");
return 0;
}
case WM_PAINT: //窗口客户区需要重画
{
HDC hdc;
PAINTSTRUCT ps;
//使无效的客户区变的有效,并取得设备环境句柄
hdc = BeginPaint(hwnd,&ps);
//显示文字
TextOut(hdc,0,0,str.c_str(),str.length());
EndPaint(hwnd,&ps);
return 0;
}
case WM_CHAR:
{
//保存ANSI码
str = str + char(wParam);
//使整个客户区无效
InvalidateRect(hwnd,NULL,0);
return 0;
}
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_FILE_EXIT:
//向hwnd指定的窗口发送一个WM_CLOSE消息
SendMessage(hwnd,WM_CLOSE,0,0);
break;
}
return 0;
//case WM_CLOSE: //任务管理器还是能干掉
// return 0;
case WM_DESTROY: //正在销毁窗口
//向消息队列发送一个WM_QUIT消息,促使GetMessage函数返回0,结束消息循环
PostQuitMessage(0);
return 0;
}
//我们不处理的消息交给系统做默认处理
return DefWindowProc(hwnd,message,wParam,lParam);
}
- 接受鼠标输入
按下 | 弹起 | 双击 | |
---|---|---|---|
左键 | WM_LBUTTONDOWN | WM_LBUTTONUP | WM_LBUTTONBLCLK |
中键 | WM_MBUTTONDOWN | WM_MBUTTONUP | WM_MBUTTONBLCLK |
右键 | WM_RBUTTONDOWN | WM_RBUTTONUP | WM_RBUTTONBLCLK |
发送这些消息时,lParam包含了客户区坐标信息
xPos = LOWORD(lParam);
yPos = HIWORD(lParam);
转化为屏幕的坐标信息
BOOL ClientToScreen(HWND hWnd,LPPOINT lpPoint); //客户区转化为屏幕坐标
BOOL ScreenToClient(HWND hWnd,LPPOINT lpPoint); //屏幕坐标转化为客户区
- wParam参数鼠标按钮信息,以MK_为前缀
MK_LBUTTON 左键按下
MK_MBUTTON 中间的键按下
MK_RBUTTON 右键按下
MK_SHIFT <Shift>键按下
MK_CONTROL <Ctrl>键按下
- 示例:简陋打字程序之鼠标位置显示
#include "stdafx.h"
#include "windows.h"
#include "stdio.h"
#include "resource.h"
#include <string>
LRESULT CALLBACK MainWndProc(HWND,UINT,WPARAM,LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
char szClassName[] = "MainClass";
WNDCLASSEX wndclass;
//用于描述主窗口的参数填充WNDCLASSEX结构
wndclass.cbSize = sizeof(wndclass); //结构的大小
wndclass.style = CS_HREDRAW | CS_VREDRAW; //指定如果大小改变就重画
wndclass.lpfnWndProc = MainWndProc; //窗口函数指针
wndclass.cbClsExtra = 0; //没有额外的类内存
wndclass.cbWndExtra = 0; //没有额外的窗口内存
wndclass.hInstance = hInstance; //实例句柄
wndclass.hIcon = LoadIcon(hInstance,(LPSTR)IDI_ICON1); //使用预定义图标
wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); //使用预定义光标
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //使用白色背景画刷
wndclass.lpszMenuName = (LPSTR)IDR_TYPER; //指定自定义的菜单
wndclass.lpszClassName = szClassName; //窗口类的名称
wndclass.hIconSm = NULL; //没有类的小图标
//注册这个窗口类
RegisterClassEx(&wndclass);
//创建主窗口
HWND hwnd = CreateWindowEx(
0, //dwExSytle,扩展
szClassName, //lpClassName,窗口类名
"My first Window!", //lpWindowName,标题
WS_OVERLAPPEDWINDOW, //dwStyle,窗口风格
CW_USEDEFAULT, //X,初始化X坐标
CW_USEDEFAULT, //y,初始化Y坐标
CW_USEDEFAULT, //nWidth,宽度
CW_USEDEFAULT, //nHeight,高度
NULL, //hWindParent 父窗口句柄
NULL, //hMenu 菜单句柄
hInstance, //hInstance,程序实例句柄
NULL //lpParam,用户数据
);
if(hwnd == NULL)
{
MessageBox(NULL,"创建窗口出错!","error",MB_OK);
return -1;
}
//显示窗口,刷新窗口客户区
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
//从消息队列中取出消息,交给窗口函数处理,直到GetMessage返回FALSE,结束消息循环
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
//转化为键盘消息
TranslateMessage(&msg);
//将消息发送到相应的窗口函数
DispatchMessage(&msg);
}
//当GetMessage返回FALSE时程序结束
return msg.wParam;
}
LRESULT CALLBACK MainWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
//str对象用于保存窗口客户区显示的字符串
//为了使用string类,包含头文件#include <string>
static std::string str;
char szText[] = "最简单的窗口程序";
switch(message)
{
case WM_CREATE:
{
//设置窗口的标题
SetWindowText(hwnd,"最简陋的打字程序");
return 0;
}
case WM_PAINT: //窗口客户区需要重画
{
HDC hdc;
PAINTSTRUCT ps;
//使无效的客户区变的有效,并取得设备环境句柄
hdc = BeginPaint(hwnd,&ps);
//显示文字
TextOut(hdc,0,0,str.c_str(),str.length());
EndPaint(hwnd,&ps);
return 0;
}
case WM_CHAR:
{
//保存ANSI码
str = str + char(wParam);
//使整个客户区无效
InvalidateRect(hwnd,NULL,0);
return 0;
}
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_FILE_EXIT:
//向hwnd指定的窗口发送一个WM_CLOSE消息
SendMessage(hwnd,WM_CLOSE,0,0);
break;
}
return 0;
case WM_LBUTTONDOWN: //用户单击鼠标左键
{
char szPoint[56];
//保存坐标信息
wsprintf(szPoint,"X = %d,Y = %d",LOWORD(lParam),HIWORD(lParam));
str = szPoint;
if(wParam & MK_SHIFT)
str = str+" Shift Key is down";
InvalidateRect(hwnd,NULL,1);
return 0;
}
//case WM_CLOSE: //任务管理器还是能干掉
// return 0;
case WM_DESTROY: //正在销毁窗口
//向消息队列发送一个WM_QUIT消息,促使GetMessage函数返回0,结束消息循环
PostQuitMessage(0);
return 0;
}
//我们不处理的消息交给系统做默认处理
return DefWindowProc(hwnd,message,wParam,lParam);
}
- 示例:简陋打字程序完成版
#include "stdafx.h"
#include "windows.h"
#include "stdio.h"
#include "resource.h"
#include <string>
LRESULT CALLBACK MainWndProc(HWND,UINT,WPARAM,LPARAM);
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
char szClassName[] = "MainClass";
WNDCLASSEX wndclass;
//用于描述主窗口的参数填充WNDCLASSEX结构
wndclass.cbSize = sizeof(wndclass); //结构的大小
wndclass.style = CS_HREDRAW | CS_VREDRAW; //指定如果大小改变就重画
wndclass.lpfnWndProc = MainWndProc; //窗口函数指针
wndclass.cbClsExtra = 0; //没有额外的类内存
wndclass.cbWndExtra = 0; //没有额外的窗口内存
wndclass.hInstance = hInstance; //实例句柄
wndclass.hIcon = LoadIcon(hInstance,(LPSTR)IDI_ICON1); //使用预定义图标
wndclass.hCursor = LoadCursor(NULL,IDC_ARROW); //使用预定义光标
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //使用白色背景画刷
wndclass.lpszMenuName = (LPSTR)IDR_TYPER; //指定自定义的菜单
wndclass.lpszClassName = szClassName; //窗口类的名称
wndclass.hIconSm = NULL; //没有类的小图标
//注册这个窗口类
RegisterClassEx(&wndclass);
//创建主窗口
HWND hwnd = CreateWindowEx(
0, //dwExSytle,扩展
szClassName, //lpClassName,窗口类名
"My first Window!", //lpWindowName,标题
WS_OVERLAPPEDWINDOW, //dwStyle,窗口风格
CW_USEDEFAULT, //X,初始化X坐标
CW_USEDEFAULT, //y,初始化Y坐标
CW_USEDEFAULT, //nWidth,宽度
CW_USEDEFAULT, //nHeight,高度
NULL, //hWindParent 父窗口句柄
NULL, //hMenu 菜单句柄
hInstance, //hInstance,程序实例句柄
NULL //lpParam,用户数据
);
if(hwnd == NULL)
{
MessageBox(NULL,"创建窗口出错!","error",MB_OK);
return -1;
}
//显示窗口,刷新窗口客户区
ShowWindow(hwnd,nCmdShow);
UpdateWindow(hwnd);
//从消息队列中取出消息,交给窗口函数处理,直到GetMessage返回FALSE,结束消息循环
MSG msg;
while(GetMessage(&msg,NULL,0,0))
{
//转化为键盘消息
TranslateMessage(&msg);
//将消息发送到相应的窗口函数
DispatchMessage(&msg);
}
//当GetMessage返回FALSE时程序结束
return msg.wParam;
}
LRESULT CALLBACK MainWndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
//str对象用于保存窗口客户区显示的字符串
//为了使用string类,包含头文件#include <string>
static std::string str;
char szText[] = "最简单的窗口程序";
switch(message)
{
case WM_CREATE:
{
//设置窗口的标题
SetWindowText(hwnd,"最简陋的打字程序");
return 0;
}
case WM_PAINT: //窗口客户区需要重画
{
HDC hdc;
PAINTSTRUCT ps;
//使无效的客户区变的有效,并取得设备环境句柄
hdc = BeginPaint(hwnd,&ps);
//设置输出文本的背景颜色和文字颜色
SetTextColor(hdc,RGB(255,0,0)); //红色文本
SetBkColor(hdc,GetSysColor(COLOR_3DFACE)); //windows预定显示元素COLOR_3DFACE
//显示文字
TextOut(hdc,0,0,str.c_str(),str.length());
EndPaint(hwnd,&ps);
return 0;
}
case WM_CHAR:
{
//保存ANSI码
str = str + char(wParam);
//使整个客户区无效
InvalidateRect(hwnd,NULL,0);
return 0;
}
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_FILE_EXIT:
//向hwnd指定的窗口发送一个WM_CLOSE消息
SendMessage(hwnd,WM_CLOSE,0,0);
break;
}
return 0;
case WM_LBUTTONDOWN: //用户单击鼠标左键
{
char szPoint[56];
//保存坐标信息
wsprintf(szPoint,"X = %d,Y = %d",LOWORD(lParam),HIWORD(lParam));
str = szPoint;
if(wParam & MK_SHIFT)
str = str+" Shift Key is down";
InvalidateRect(hwnd,NULL,1);
return 0;
}
//case WM_CLOSE: //任务管理器还是能干掉
// return 0;
case WM_DESTROY: //正在销毁窗口
//向消息队列发送一个WM_QUIT消息,促使GetMessage函数返回0,结束消息循环
PostQuitMessage(0);
return 0;
}
//我们不处理的消息交给系统做默认处理
return DefWindowProc(hwnd,message,wParam,lParam);
}