浙江财经大学
信工学院ACM集训队

Win32 Api 学习记录

本文由 Ocrosoft 于 2018-05-08 15:46:00 发表

摘要:计时器函数SetTimer,KillTimer的使用

1.1.显示一个电子时钟

1.2.第一次看着头疼的代码…好久才看懂_(:з」∠)_

1.3.源码

#include <windows.h>

#define LPARAMX ((int)(short)LOWORD(lParam))
#define LPARAMY ((int)(short)HIWORD(lParam))
#define ID_TIMER 1

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
	static TCHAR szAppName[] = TEXT("DigClock");
	HWND hwnd;
	MSG msg;
	WNDCLASS wndclass;

	wndclass.style = CS_HREDRAW | CS_VREDRAW;
	wndclass.lpfnWndProc = WndProc;
	wndclass.cbClsExtra = 0;
	wndclass.cbWndExtra = 0;
	wndclass.hInstance = hInstance;
	wndclass.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
	wndclass.hCursor = LoadCursor(nullptr, IDC_ARROW);
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wndclass.lpszMenuName = nullptr;
	wndclass.lpszClassName = szAppName;

	if (!RegisterClass(&wndclass))
	{
		MessageBox(nullptr, TEXT("Program requires Windows NT!"), szAppName, MB_ICONERROR);
		return 0;
	}

	hwnd = CreateWindow(szAppName, TEXT("DigClock"),
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
		NULL, NULL, hInstance, NULL);

	ShowWindow(hwnd, iCmdShow);
	UpdateWindow(hwnd);

	while (GetMessage(&msg, nullptr, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}

void DisplayDigit(HDC hdc, int iNumber)
{
	static BOOL fSevenSegment[10][7] = {
		1,1,1,0,1,1,1,   // 0
		0,0,1,0,0,1,0,   // 1
		1,0,1,1,1,0,1,   // 2
		1,0,1,1,0,1,1,   // 3
		0,1,1,1,0,1,0,   // 4
		1,1,0,1,0,1,1,   // 5
		1,1,0,1,1,1,1,   // 6
		1,0,1,0,0,1,0,   // 7
		1,1,1,1,1,1,1,   // 8
		1,1,1,1,0,1,1 }; // 9
	static POINT ptSegment[7][6] = {
		 7, 6,11, 2,31, 2,35, 6,31,10,11,10,
		 6, 7,10,11,10,31, 6,35, 2,31, 2,11,
		36, 7,40,11,40,31,36,35,32,31,32,11,
		 7,36,11,32,31,32,35,36,31,40,11,40,
		 6,37,10,41,10,61, 6,65, 2,61, 2,41,
		36,37,40,41,40,61,36,65,32,61,32,41,
		 7,66,11,62,31,62,35,66,31,70,11,70 };

	int iSeg;
	for (iSeg = 0; iSeg < 7; iSeg++)
		if (fSevenSegment[iNumber][iSeg])
			Polygon(hdc, ptSegment[iSeg], 6);
}

void DisplayTwoDigits(HDC hdc, int iNumber, BOOL fSuppress)
{
	// 有前导零 或 有十位,显示十位
	if (!fSuppress || (iNumber / 10 != 0))
		DisplayDigit(hdc, iNumber / 10);

	// 窗口原点移动x,y逻辑单位的距离
	OffsetWindowOrgEx(hdc, -42, 0, NULL);
	// 显示各位
	DisplayDigit(hdc, iNumber % 10);
	OffsetWindowOrgEx(hdc, -42, 0, NULL);
}

void DisplayColon(HDC hdc)
{
	POINT ptColon[2][4] = { 2, 21,6,17,10,21,6,25,
							2,51,6,47,10,51,6,55 };

	Polygon(hdc, ptColon[0], 4); // 两个点
	Polygon(hdc, ptColon[1], 4);

	OffsetWindowOrgEx(hdc, -12, 0, NULL);
}

void DisplayTime(HDC hdc, BOOL f24Hour, BOOL fSuppress)
{
	SYSTEMTIME st;

	// 获取系统时间
	GetLocalTime(&st);

	// 显示小时
	if (f24Hour) // 是24小时制直接显示
		DisplayTwoDigits(hdc, st.wHour, fSuppress);
	else // 是12小时制,mod12,,12小时制没有0点,只有12点
		DisplayTwoDigits(hdc, (st.wHour %= 12) ? st.wHour : 12, fSuppress);

	// 冒号
	DisplayColon(hdc);
	// 显示分钟
	DisplayTwoDigits(hdc, st.wMinute, FALSE);
	// 冒号
	DisplayColon(hdc);
	// 显示秒
	DisplayTwoDigits(hdc, st.wSecond, FALSE);
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static BOOL f24Hour, fSuppress; // 是否24小时制,是否无前导零
	static HBRUSH hBrushRed;
	static int cxClient, cyClient;
	HDC hdc;
	PAINTSTRUCT ps;
	TCHAR szBuffer[2];

	switch (message)
	{
	case WM_CREATE:
		// 创建红色画刷
		hBrushRed = CreateSolidBrush(RGB(255, 0, 0));
		// 设置定时器,(伪)1秒一次
		SetTimer(hwnd, ID_TIMER, 1000, NULL);
		// fall through

	case WM_SETTINGCHANGE:
		// 0表示12小时制,1表示24小时制
		GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ITIME, szBuffer, 2);
		f24Hour = (szBuffer[0] == '1');

		// 0表示没有前导零,1表示有前导零
		GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ITLZERO, szBuffer, 2);
		fSuppress = (szBuffer[0] == '0');

		InvalidateRect(hwnd, NULL, TRUE);
		return 0;

	case WM_SIZE:
		cxClient = LOWORD(lParam);
		cyClient = HIWORD(lParam);
		return 0;

	case WM_TIMER:
		InvalidateRect(hwnd, NULL, TRUE);
		return 0;

	case WM_PAINT:
		hdc = BeginPaint(hwnd, &ps);

		// 这一段使用的参考:https://blog.csdn.net/lp310018931/article/details/17004733

		// 映射模式
		// 原来是MM_TEXT,逻辑坐标对应1像素
		// MM_ISOTROPIC为自定义,但XY轴单位相同。(还有一个MM_ANISOTROPIC,也是自定义,但XY轴单位可以不同)
		// 当需要绘制内容随窗口大小自动改变的时候,选择上面这两个映射模式
		// 如果使用MM_TEXT,时间会居中,且大小固定
		SetMapMode(hdc, MM_ISOTROPIC);
		// 定义逻辑窗口的区域,即宽为276个逻辑单位,高为72个逻辑单位
		SetWindowExtEx(hdc, 276, 72, NULL);
		// 设定逻辑窗口XY轴的像素范围
		SetViewportExtEx(hdc, cxClient, cyClient, NULL);
		// 以上的设定,会出现绘制的图像等比缩放的情况(保证完全显示的情况下,显示最大的图像)

		// 设置逻辑窗口原点
		SetWindowOrgEx(hdc, 138, 36, NULL);
		// 设置视口原点
		SetViewportOrgEx(hdc, cxClient / 2, cyClient / 2, NULL);
		// 以上两句,会是图像出现在窗口的中间
		SelectObject(hdc, GetStockObject(NULL_PEN)); // 使用空画笔
		SelectObject(hdc, hBrushRed); // 使用红色画刷

		DisplayTime(hdc, f24Hour, fSuppress); // 绘制时间

		EndPaint(hwnd, &ps);
		return 0;

	case WM_DESTROY:
		KillTimer(hwnd, ID_TIMER); // 清除定时器
		DeleteObject(hBrushRed); // 释放红色画刷
		PostQuitMessage(0);
		return 0;
	}
	return DefWindowProc(hwnd, message, wParam, lParam);
}

欢迎转载,请保留出处与链接。Ocrosoft » Win32 Api 学习记录

点赞 (0)or拍砖 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址