步骤:
1.设计窗口
2.注册窗口
3.创建窗口
4.显示和更新窗口
5.消息循环
消息机制图:
发送消息:
SendMessage:
1.返回值 LRESULT //result 消息处理完的返回结果
2.阻塞函数
PostMessage:
1.返回的是一个成功或失败
2.是一个非阻塞函数(因此跨进程最好用PostMessage)
用户自定义消息:
使用SendMessage或者PostMessage来发送自定义消息
#define _CRT_SECURE_NO_WARNINGS
#include<Windows.h>
#include"resource.h"
#include<time.h>
#define TIME_ID 1
#define UM_TEST WM_USER+1
/*
WNDPROC typedef LRESULT(CALLBACK* WNDPROC)(hWnd, UINT, WPARAM, LPARAM); 函数指针类型
WPARAM UINT_PTR =>unsigned int
LPARAM LONG_PTR=>long
HICON DECLARE_HANDLE(HICON)
LPCTSTR LPCWSTR=> CONST WCHAR *=>const wchar_t*(宽字符)
ATOM WORD(字)=》unsigned short
DWORD 双字 double word =>unsigned long
*/
//窗口处理函数
//第一个参数:窗口句柄,创建的这个窗口
//第二个参数:消息编号,数值
//第三个参数:附加消息
//第四个参数:附加信息
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE preHinstance, LPSTR lpCmdLine, int nCmdShow)
{
//1.设计窗口类
WNDCLASS wc = { 0 };
wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; //窗口类的风格
wc.lpfnWndProc = WindowProc; //窗口处理函数
wc.cbClsExtra = 0; //窗口类这个结构体,额外拓展空间
wc.cbWndExtra = 0; //窗口实例额外空间大小
wc.hInstance = hinstance; //当前应用程序实例句柄
wc.hIcon = LoadIcon(hinstance,MAKEINTRESOURCE( IDI_ICON1)); //图标句柄
wc.hCursor = LoadCursor(NULL,IDC_HAND); //光标句柄
wc.hbrBackground = CreateSolidBrush(RGB(250, 250, 0)); //背景句柄
wc.lpszMenuName = NULL; //菜单名
wc.lpszClassName = L"皮蛋"; //窗口类型名
//2.注册窗口类
if (0 == RegisterClass(&wc))
{
MessageBox(NULL, L"此程序不能运行在windows NT 上", L"温馨提示", MB_OK | MB_ICONWARNING);
return 0;
}
//3.创建窗口
/*
hWnd CreateWindow(
LPCTSTR lpClassName, // pointer to registered class name
LPCTSTR lpWindowName, // pointer to window name
DWORD dwStyle, // window style
int x, // horizontal position of window
int y, // vertical position of window
int nWidth, // window width
int nHeight, // window height
hWnd hWndParent, // handle to parent or owner window
HMENU hMenu, // handle to menu or child-window identifier
HANDLE hInstance, // handle to application instance
LPVOID lpParam // pointer to window-creation data
);
*/
HWND hWnd=CreateWindow(
L"皮蛋", //窗口类型名
L"我的第一个windows程序窗口", //标题
WS_BORDER | WS_CAPTION |WS_SYSMENU
| WS_MAXIMIZEBOX | WS_MINIMIZEBOX, //窗口的风格
300, 200, //窗口左上角坐标
800, 600, 窗口左上宽和高
NULL, //父窗口句柄
NULL, //菜单句柄
hinstance, //当前应用程序实例句柄
NULL //创建窗口传递的附加数据
);
if (hWnd == NULL)
{
MessageBox(NULL, L"窗口创建失败", L"温馨提示", MB_OK);
return 0;
}
//4.显示和更新窗口
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
//5.消息循环
/*
typedef struct tagMSG { // msg
hWnd hWnd;
UINT message;
WPARAM wParam;
LPARAM lParam;
DWORD time; //消息放入消息队列的时间
POINT pt; //鼠标坐标
} MSG;
*/
//GetMessage函数的返回值要为0,只有接收到这个消息的时候:WM_QUIT
MSG msg;
while (GetMessage(&msg,NULL,0,0)) //NULL 该线程所有窗口消息都取出来,//0,0消息都取出来
{
//将虚拟键消息转化为字符消息
TranslateMessage(&msg);
//将消息分发给窗口处理函数
DispatchMessage(&msg);
}
return 0;//退出
}
//窗口处理函数
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
//输出消息参数信息
TCHAR szMsg[256];
wsprintf(szMsg, L"消息:%#x,窗口句柄:%#x,WAPARM:%d,LPARAM:%d\n", uMsg, hWnd, wParam, lParam);
OutputDebugString(szMsg);
switch (uMsg)
{
//............窗口消息....
case WM_CREATE:
{
//窗口创建消息,由CreateWindow或者CreateWindowEx发出这个消息,发出的时间非常早,在
// 窗口还没有创建就已经发出来了
CREATESTRUCT *lpcs = (CREATESTRUCT*)lParam;
//MessageBox(hWnd, L"这是窗口创建消息", L"提示", MB_OK);
//开启定时器
SetTimer(hWnd, TIME_ID, 1000, NULL);
break;
}
case WM_CLOSE://窗口关闭消息,点击窗口关闭按钮时发送此消息,响应此消息时,窗口并没有真正销毁
{
int result = MessageBox(hWnd, L"你确定要关闭嘛?", L"提示", MB_YESNO);
if (IDYES == result)
{
break;
}
else
{
//showWindow(hWnd,SW_MAXIMIZE);
return 1;//返回真,表示我自己处理了,系统不需要再处理
//return 0;//返回假,表示我自己没有处理,系统也不需要再处理
}
//DestroyWindow(hWnd);
break;
}
case WM_DESTROY://窗口销毁消息,窗口退出去的时候,清理工作
//发出一个退出消息
PostQuitMessage(0);//WM_QUIT
break;
//...........鼠标消息........
case WM_LBUTTONDOWN://鼠标左键按下消息
{
//关闭定时器
KillTimer(hWnd,TIME_ID);
//LPARAM 双字 四个字节
int x = LOWORD(lParam);
int y = HIWORD(lParam);
TCHAR szInfo[256];
wsprintf(szInfo, L"坐标:(%d,%d)", x, y);
//其它建响应建立在左键响应的前提之上
if (wParam&MK_CONTROL)
{
wcscat(szInfo, L"按下了ctrl键");
}
if (wParam&MK_LBUTTON)
{
wcscat(szInfo, L"按下了左键");
}
if (wParam&MK_RBUTTON)
{
wcscat(szInfo, L"按下了右键");
}
SetWindowText(hWnd, szInfo);
break;
}
case WM_LBUTTONUP://鼠标左键抬起
{
break;
}
case WM_RBUTTONDOWN:
{
/*TCHAR ch = 'A';
int result=SendMessage(hWnd, WM_CHAR, ch, 0);*/
SendMessage(hWnd, UM_TEST, 12, 96);
break;
}
case WM_LBUTTONDBLCLK://左键双击
{
SetWindowText(hWnd, L"鼠标左键双击了");
break;
}
case WM_RBUTTONDBLCLK:
{
SetWindowText(hWnd, L"鼠标右键双击了");
break;
}
//.........键盘按下............
case WM_KEYDOWN:
{
switch (wParam)
{
case VK_SPACE://空格
{
//LRESULT SendMessage(
// HWND hWnd, // handle of destination window
// UINT Msg, // message to send
// WPARAM wParam, // first message parameter
// LPARAM lParam // second message parameter
//);
//模拟鼠标点击
//发送消息
//int x = 50;
//int y = 100;
result 消息处理完的返回结果
//int result=SendMessage(hWnd,WM_LBUTTONDOWN ,0, MAKELPARAM(x, y));
//int a=10;
//a++;
//查找一个窗口
HWND hNotepadWnd=FindWindow(L"Notepad",L"*1.txt - 记事本");
if (hNotepadWnd == NULL)
{
MessageBox(hWnd, L"没有找到记事本", NULL, MB_OK);
return 0;
}
SendMessage(hNotepadWnd,WM_CLOSE,0,0);
}
break;
case VK_F1:
MessageBox(hWnd, L"按下了F1键", L"提示", MB_YESNO);
break;
case VK_LEFT:
MessageBox(hWnd, L"按下了left键", L"提示", MB_YESNO);
break;
case 0x30:
MessageBox(hWnd, L"按下了0键", L"提示", MB_YESNO);
break;
case VK_NUMPAD0:
MessageBox(hWnd, L"按下了右边的0", L"提示", MB_YESNO);
break;
}
}
//......键盘抬起....
/*case WM_KEYUP:
{
if(wParam==VK_SPACE)
MessageBox(hWnd, L"抬起了右边的空格键", L"提示", MB_YESNO);
break;
}
*/
//....字符消息....由一次按下和抬起组成.....
//Value of wParam. Specifies the character code of the key.
//wParam的值。指定键的字符代码。
case WM_CHAR:
{
TCHAR ch = (TCHAR)wParam;
TCHAR szInfo[256];
wsprintf(szInfo, L"字符:%c", ch);
SetWindowText(hWnd, szInfo);
break;
}
//.......绘图消息.......
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
Rectangle(hdc, 20, 20, 100, 100);
EndPaint(hWnd, &ps);
}
//........定时器消息.........
case WM_TIMER:
{
int nTimerID = wParam;
switch (nTimerID)
{
case TIME_ID:
//返回当前时间的时间戳
time_t time1 = time(NULL);
/*time_t time2;
time(&time2);*/
tm*t = localtime(&time1);
TCHAR szInfo[256];
wsprintf(szInfo, L"北京时间:%02d-%02d-%d %02d:%02d:%02d", t->tm_year + 1900, t->tm_mon + 1,
t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
SetWindowText(hWnd, szInfo);
break;
}
}
case UM_TEST://用户自定义消息
{
//干掉定时器
KillTimer(hWnd, TIME_ID);
int x = wParam;
int y = lParam;
int result = x + y;
//设置标题
SetWindowText(hWnd,L"这是用户自定义消息");
}
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
/*
SendMessage:
1.返回值 LRESULT //result 消息处理完的返回结果
2.阻塞函数
PostMessage:
1.返回的是一个成功或失败
2.是一个非阻塞函数(因此跨进程最好用PostMessage)
*/