代碼:
#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;/