代码:
#include<Windows.h> //底层实现窗口的头文件
#include<tchar.h>
const TCHAR szWindowClass[] = L"第一个窗口";
const TCHAR szWindowTitle[] = L"时钟";
const int IDM_TOPMOST = 101;
const int IDTIMER = 1;
#define KEY_DOWN(vk_code)(GetAsyncKeyState(vk_code)&0x8000)
//6.处理消息(窗口过程)
//CALLBACK 代表__stdcall 指的是WinMain函数参数的传递顺序 从右向左,依次入栈,并且在函数返回前 清空堆栈
LRESULT CALLBACK WindowProc(
HWND hwnd, // 消息所属的窗口句柄
UINT Msg, //具体的消息名称 WM_XXX 消息名
WPARAM wParam, //键盘的附加消息
LPARAM lParam //鼠标的附加消息
)
{
static HBRUSH hBrushRed;
static BOOL bTopMost = FALSE;//是否最前端,默认是最前端
switch (Msg)
{
case WM_CREATE:
{
HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
AppendMenu(hSysMenu, MF_SEPARATOR, 0, NULL);
AppendMenu(hSysMenu, MF_STRING, IDM_TOPMOST, L"保持在其他窗口前端");
CheckMenuItem(hSysMenu, IDM_TOPMOST, MF_UNCHECKED);
// HINSTANCE hInst = ((LPCREATESTRUCT)lParam)->hInstance;
hBrushRed = CreateSolidBrush(RGB(255, 0, 0));
SetTimer(hwnd, IDTIMER, 1000, NULL);
return 0;
}
case WM_TIMER:
{
switch (wParam) //判断定时器的ID
{
case IDTIMER:
InvalidateRect(hwnd, NULL, TRUE);
}
return 0;
}
case WM_DESTROY:
{
KillTimer(hwnd, IDTIMER);
PostQuitMessage(0);
return 0;
}
case WM_CONTEXTMENU:
{
POINTS p = MAKEPOINTS(lParam);
HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
int nID = TrackPopupMenu(hSysMenu, TPM_LEFTALIGN | TPM_RETURNCMD, p.x, p.y, 0, hwnd, NULL);
if (nID > 0)
{
SendMessage(hwnd, WM_SYSCOMMAND, nID, 0);
}
return 0;
}
case WM_SYSCOMMAND:
{
HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
switch (wParam)
{
case IDM_TOPMOST:
{
bTopMost = !bTopMost;
if (bTopMost) {
CheckMenuItem(hSysMenu, IDM_TOPMOST, MF_CHECKED);
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE);
}
else
{
CheckMenuItem(hSysMenu, IDM_TOPMOST, MF_UNCHECKED);
SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE);
}
break;
}
return DefWindowProc(hwnd, Msg, wParam, lParam);
}
}
case WM_NCHITTEST:
{
LRESULT nHitTest = DefWindowProc(hwnd, Msg, wParam, lParam);
if(nHitTest == HTCLIENT && KEY_DOWN(MK_LBUTTON))
nHitTest = HTCAPTION;
return nHitTest;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd,&ps);
SelectObject(hdc, GetStockObject(NULL_PEN));
SelectObject(hdc, hBrushRed);
SYSTEMTIME t; //
GetLocalTime(&t);//获取系统时间
TCHAR str[20];
//_stprintf(str, L"%d:%d:%d", t.wHour, t.wMinute, t.wSecond);
swprintf_s(str, L"%d:%d:%d", t.wHour, t.wMinute, t.wSecond);
RECT r;
GetClientRect(hwnd, &r);//获取客户区的矩形
//单行,垂直居中,水平输出字符串
DrawText(hdc,str,-1,&r,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
EndPaint(hwnd, &ps);
return 0;
}
default:
return DefWindowProc(hwnd, Msg, wParam, lParam);
}
}
//程序的入门函数
/*
WINAPI: 代表__stdcall 指的是WinMain函数参数的传递顺序 从右向左,依次入栈,并且在函数返回前 清空堆栈
*/
int WINAPI WinMain(
HINSTANCE hInstance, //应用程序的实例句柄
HINSTANCE hPrevInstance,//上一个应用程序句柄,在 win32 环境下,一般为NULL,不起作用了
LPSTR lpCmdLine, //char * argv[]
int nCmdShow) //窗口的显示方式:最大化、最小化、正常
{
//1.设计窗口
WNDCLASS wc = {0};
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //设置背景
wc.hCursor = LoadCursor(NULL, IDC_HAND);//设置光标,第一个参数为NULL表示使用系统提供的光标
wc.hIcon = LoadIcon(NULL, IDI_ERROR);//图标
wc.hInstance = hInstance;//应用程序的实例句柄,传入winmain中的形参即可
wc.lpfnWndProc = WindowProc;//回调函数 窗口过程
wc.lpszClassName = szWindowClass;//窗口类名称
wc.lpszMenuName = NULL;//菜单名称
wc.style = 0;//显示风格, 最大化、最小化、正常
//2.注册窗口
RegisterClass(&wc);
HWND hwnd = CreateWindow(szWindowClass,
szWindowTitle,
WS_POPUP | WS_BORDER | WS_SYSMENU,
200, 200,
200, 100,
NULL, NULL,
hInstance, NULL);
if (!hwnd) return FALSE;
//4.显示和更新
ShowWindow(hwnd, SW_SHOWNORMAL);
UpdateWindow(hwnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
运行结果:

总结和分析:
- 添加#include<Windows.h>头文件:底层实现窗口的头文件,和 #include<tchar.h>:是一个在TCHAR.h里面,目的是为了简化代码方便国际使用。
- 全局区
const TCHAR szWindowClass[] = L"第一个窗口";
const TCHAR szWindowTitle[] = L"时钟";
const int IDM_TOPMOST = 101;保证菜单在其他窗口的前面
const int IDTIMER = 1;///定时器的ID
#define KEY_DOWN(vk_code)(GetAsyncKeyState(vk_code)&0x8000)//判断是否按下的宏
关于KEYDOWN(VK_CODE)
- 用于消息处理的回调函数
LRESULT CALLBACK WindowProc(
HWND hwnd, // 消息所属的窗口句柄
UINT Msg, //具体的消息名称 WM_XXX 消息名
WPARAM wParam, //键盘的附加消息
LPARAM lParam //鼠标的附加消息
)
{
//static HBRUSH hBrushRed;
static BOOL bTopMost = FALSE;//是否最前端,默认是最前端
switch (Msg)
{
case WM_CREATE: // 应用程序创建一个窗口 创建窗口的消息
{
HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
AppendMenu(hSysMenu, MF_SEPARATOR, 0, NULL);
AppendMenu(hSysMenu, MF_STRING, IDM_TOPMOST, L"保持在其他窗口前端");
CheckMenuItem(hSysMenu, IDM_TOPMOST, MF_UNCHECKED);
// HINSTANCE hInst = ((LPCREATESTRUCT)lParam)->hInstance;
hBrushRed = CreateSolidBrush(RGB(255, 0, 0));
SetTimer(hwnd, IDTIMER, 1000, NULL);
return 0;
}
case WM_TIMER: //定时器的消息
{
switch (wParam) //判断定时器的ID
{
case IDTIMER:
InvalidateRect(hwnd, NULL, TRUE);
}
return 0;
}
case WM_DESTROY: //窗口销毁的VM消息
{
KillTimer(hwnd, IDTIMER);
PostQuitMessage(0);
return 0;
}
case WM_CONTEXTMENU:
{
POINTS p = MAKEPOINTS(lParam);
HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
int nID = TrackPopupMenu(hSysMenu, TPM_LEFTALIGN | TPM_RETURNCMD, p.x, p.y, 0, hwnd, NULL);
if (nID > 0)
{
SendMessage(hwnd, WM_SYSCOMMAND, nID, 0);
}
return 0;
}
case WM_SYSCOMMAND:
{
HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
switch (wParam)
{
case IDM_TOPMOST:
{
bTopMost = !bTopMost;
if (bTopMost) {
CheckMenuItem(hSysMenu, IDM_TOPMOST, MF_CHECKED);
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE);
}
else
{
CheckMenuItem(hSysMenu, IDM_TOPMOST, MF_UNCHECKED);
SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSIZE);
}
break;
}
return DefWindowProc(hwnd, Msg, wParam, lParam);
}
}
case WM_NCHITTEST:
{
LRESULT nHitTest = DefWindowProc(hwnd, Msg, wParam, lParam);
if(nHitTest == HTCLIENT && KEY_DOWN(MK_LBUTTON))
nHitTest = HTCAPTION;
return nHitTest;
}
case WM_PAINT: // 要求一个窗口重画自己
{
PAINTSTRUCT ps;//
HDC hdc = BeginPaint(hwnd,&ps);
// SelectObject(hdc, GetStockObject(NULL_PEN));
//SelectObject(hdc, hBrushRed);
SYSTEMTIME t;//系统时间变量
GetLocalTime(&t);//获取系统时间
TCHAR str[20];
//_stprintf(str, L"%d:%d:%d", t.wHour, t.wMinute, t.wSecond);
swprintf_s(str, L"%d:%d:%d", t.wHour, t.wMinute, t.wSecond);
RECT r;
GetClientRect(hwnd, &r);//获取客户区的矩形
//单行,垂直居中,水平输出字符串
DrawText(hdc,str,-1,&r,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
EndPaint(hwnd, &ps);
return 0;
}
default:
return DefWindowProc(hwnd, Msg, wParam, lParam);
}
}
/typedef struct _SYSTEMTIME {
WORD wYear;
WORD wMonth;
WORD wDayOfWeek;
WORD wDay;
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds;
} SYSTEMTIME;/