学习windows 程序设计方面的知识,觉得还挺有意思。不仅加深了自己对window的了解,还了解了windows窗口与用户之间消息传递机制。
下面是学习过程中做的一个Clock的程序,有兴趣的可以参考一下:// ClockDemo.cpp : 定义应用程序的入口点。 // #include "stdafx.h" #include "ClockDemo.h" #include <math.h> // 全局变量: #define MAX_LOADSTRING 100 HINSTANCE hInst; // 当前实例 TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本 TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名 // 此代码模块中包含的函数的前向声明: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: 在此放置代码。 MSG msg; HACCEL hAccelTable; // 初始化全局字符串 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_CLOCKDEMO, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // 执行应用程序初始化: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_CLOCKDEMO)); // 主消息循环: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } // // 函数: MyRegisterClass() // // 目的: 注册窗口类。 // // 注释: // // 仅当希望 // 此代码与添加到 Windows 95 中的“RegisterClassEx” // 函数之前的 Win32 系统兼容时,才需要此函数及其用法。调用此函数十分重要, // 这样应用程序就可以获得关联的 // “格式正确的”小图标。 // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_CLOCKDEMO)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); wcex.lpszMenuName = NULL; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassEx(&wcex); } // // 函数: InitInstance(HINSTANCE, int) // // 目的: 保存实例句柄并创建主窗口 // // 注释: // // 在此函数中,我们在全局变量中保存实例句柄并 // 创建和显示主程序窗口。 // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; // 将实例句柄存储在全局变量中 hWnd = CreateWindow(szWindowClass, szTitle, WS_POPUP|WS_SYSMENU|WS_SIZEBOX, 100,100, 300, 300, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // 函数: WndProc(HWND, UINT, WPARAM, LPARAM) // // 目的: 处理主窗口的消息。 // // WM_COMMAND - 处理应用程序菜单 // WM_PAINT - 绘制主窗口 // WM_DESTROY - 发送退出消息并返回 #define IDT_CLOCK 1 #define PI 3.1415926 #define IDM_TOPMOST 100 #define IDM_HELP 101 static int s_nPreHour; static int s_nPreMinute; static int s_nPreSecond; //窗口客户区的大小 static int s_cxClient; static int s_cyClient; //是否位于最顶层 static BOOL s_bTopMost; void drawClockFace(HDC hdc); void setIsotropic(HDC hdc,int cx,int cy); void DrawHand(HDC hdc,int nLength, int nWidth,int nDegrees,COLORREF clrColor); // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_CREATE: { //向系统菜单中添加自定义的项 HMENU hSysMenu; hSysMenu =::GetSystemMenu(hWnd,FALSE); ::AppendMenu(hSysMenu,MF_SEPARATOR,0,NULL); ::AppendMenu(hSysMenu,MF_STRING,IDM_TOPMOST,"Always in front"); ::AppendMenu(hSysMenu,MF_STRING,IDM_HELP,"Help"); //设置时间 SYSTEMTIME time; ::GetLocalTime(&time); s_nPreHour = time.wHour %12; s_nPreMinute = time.wMinute ; s_nPreSecond = time.wSecond; //创建定时器 ::SetTimer(hWnd,IDT_CLOCK,1000,NULL); return 0; } case WM_CLOSE: { ::KillTimer(hWnd,IDT_CLOCK); ::DestroyWindow(hWnd); return 0; } case WM_SIZE: { s_cxClient = LOWORD(lParam); s_cyClient = HIWORD(lParam); return 0; } case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // 分析菜单选择: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: { hdc = BeginPaint(hWnd, &ps); // TODO: 在此添加任意绘图代码... //设置坐标系 setIsotropic(hdc,s_cxClient,s_cyClient); //绘制时钟外观 drawClockFace(hdc); //绘制指针 //经过1个小时时钟走了30度(360/12),经过1分钟时针走了0.5度(30/6); DrawHand(hdc,200,8,s_nPreHour*30+s_nPreMinute/2,RGB(0,0,0)); //经过了1分钟分针走了6度(360/60); DrawHand(hdc,400,6,s_nPreMinute*6,RGB(0,0,0)); //进过了1秒秒针走了6度(360/60) DrawHand(hdc,400,1,s_nPreSecond*6,RGB(0,0,0)); EndPaint(hWnd, &ps); return 0; } case WM_TIMER: { //如果窗口处于最小化的状态下就什么都不做 if(::IsIconic(hWnd))//IsIconic函数是用来判断窗口是否处于最小化状态 { return 0; } //取得系统时间 SYSTEMTIME time; ::GetLocalTime(&time); //建立坐标系 HDC hdc = ::GetDC(hWnd); setIsotropic(hdc,s_cxClient,s_cyClient); //以COLOR_3DFACE 为背景颜色就可以擦除指针了(因为窗口的背景色也是COLOR_3DFACE) COLORREF crfColor =::GetSysColor(COLOR_3DFACE); //如果分针改变的话就擦除时针和分针 if(time.wMinute != s_nPreMinute) { //擦除时针和分针 DrawHand(hdc,200,8,s_nPreHour*30+s_nPreMinute/2,crfColor); DrawHand(hdc,400,6,s_nPreMinute*6,crfColor); s_nPreHour = time.wHour ; s_nPreMinute = time.wMinute ; } //如果秒针改变的话就擦除秒针,然后重新绘制所有指针 if(time.wSecond != s_nPreSecond) { //擦除秒针 DrawHand(hdc,400,1,s_nPreSecond*6,crfColor); //重新绘制所有指针 DrawHand(hdc,400,1,time.wSecond*6,RGB(0,0,0)); DrawHand(hdc,200,8,time.wHour*30+ time.wMinute/2,RGB(0,0,0)); DrawHand(hdc,400,8,time.wMinute*6,RGB(0,0,0)); s_nPreSecond = time.wSecond ; } return 0; } //创建捕获鼠标左键点击函数 case WM_NCHITTEST: { UINT nHitTest; nHitTest = ::DefWindowProc(hWnd,WM_NCHITTEST,wParam,lParam); //如果鼠标左键点击一下,GetAsyncKeyState函数返回值小于0 if(nHitTest == HTCLIENT&&::GetAsyncKeyState(MK_LBUTTON)<0) nHitTest = HTCAPTION; return nHitTest; } case WM_CONTEXTMENU: { POINT pt; pt.x = LOWORD(lParam); pt.y = HIWORD(lParam); //取得系统菜单的句柄 HMENU hSysMenu = ::GetSystemMenu(hWnd,FALSE); //弹出系统菜单 int nID = ::TrackPopupMenu(hSysMenu,TPM_LEFTALIGN|TPM_RETURNCMD,pt.x,pt.y,0,hWnd,NULL); if(nID > 0) { ::SendMessage(hWnd,WM_SYSCOMMAND,nID,0); } return 0; } case WM_SYSCOMMAND: { int nID = wParam; if(nID == IDM_HELP) { ::MessageBox(hWnd,"A clock example","clock",0); } else if(nID == IDM_TOPMOST) { HMENU hSysMenu = ::GetSystemMenu(hWnd,FALSE); if(s_bTopMost) { //设置ID号为IDM_TOPMOST的菜单项为未选中状态 ::CheckMenuItem(hSysMenu,IDM_TOPMOST,MF_UNCHECKED); //将窗口提到所有窗口的最顶层 ::SetWindowPos(hWnd,HWND_NOTOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOREDRAW|SWP_NOSIZE); s_bTopMost = FALSE; } else { ::CheckMenuItem(hSysMenu,IDM_TOPMOST,MF_CHECKED); ::SetWindowPos(hWnd,HWND_NOTOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOREDRAW|SWP_NOSIZE); s_bTopMost = TRUE; } } return ::DefWindowProc(hWnd,WM_SYSCOMMAND,nID,0); } case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // “关于”框的消息处理程序。 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE; } void drawClockFace(HDC hdc) { const int SQUARESIZE = 20; static POINT pt[] = {0 , 450, //12 225 , 390, //1 390 , 225, //2 450 , 0 , //3 390 ,-225, //下面的坐标是上面的点的对称点(关于X轴和Y轴或者原点的对称点) 225 ,-390, 0 ,-450, -255,-390, -390,-225, -450, 0 , -390, 225, -225, 390 }; //select a black brush ::SelectObject (hdc,::GetStockObject(BLACK_BRUSH)); //draw 12 circles for(int i = 0; i < 12; i++) { ::Ellipse(hdc,pt[i].x - SQUARESIZE,pt[i].y+ SQUARESIZE,pt[i].x+SQUARESIZE,pt[i].y - SQUARESIZE); } } void setIsotropic(HDC hdc,int cx,int cy) { ::SetMapMode (hdc,MM_ISOTROPIC); ::SetWindowExtEx (hdc,1000,1000,NULL); ::SetViewportExtEx (hdc,cx,-cy,NULL); ::SetViewportOrgEx (hdc,cx/2,cy/2,NULL); } void DrawHand(HDC hdc,int nLength, int nWidth,int nDegrees,COLORREF clrColor) { //将角度nDegrees 转化为弧度. 2* 3.1415926/360 = 0.0174533 double nRadius = (double)nDegrees * PI/180; POINT pt[2]; pt[0].x = (int)(nLength* sin(nRadius)); pt[0].y = (int)(nLength* cos(nRadius)); pt[1].x = -pt[0].x/5; pt[1].y = -pt[0].y/5; //创建画笔,并选入DC结构中 HPEN hPen = ::CreatePen(PS_SOLID,nWidth,clrColor); HPEN hOldPen = (HPEN)SelectObject(hdc,hPen); //画线 ::MoveToEx(hdc,pt[0].x,pt[0].y,NULL); ::LineTo(hdc,pt[1].x,pt[1].y); ::SelectObject(hdc,hOldPen); ::DeleteObject(hPen); }
如果有疑问,请联系wl_soft50@163.com。