创建窗口步骤:

(1)注册窗口类(RegisterClassEx)

(2)创建窗口(CreateWindowEx)

(3)在桌面显示窗口(ShowWindow)

(4)更新窗口客户区(UpdateWindow)

(5)进入无限的消息获取和处理的循环:获取消息(GetMessage);分派消息至窗口函数处理(DisPatchMessage);

如果是WM_QUIT,函数(GetMessage)返回False,消息循环结束,程序退出。

注册窗口类需要初始化一个窗口类结构,将其写成一个函数如下:

ATOM MyRegisterClass(HINSTANCE hInstance)
{WNDCLASSEXW wcex;  //窗口类结构wcex.cbSize = sizeof(WNDCLASSEX); //结构大小wcex.style          = CS_HREDRAW | CS_VREDRAW|CS_OWNDC;//CS:class style此窗口类派生的窗口具有的风格//CS_OWNDC使得windows将每次对DC的设置保存下来,CS_HREDRAW | CS_VREDRAW窗口大小变化就刷新wcex.lpfnWndProc    = WndProc;    //窗口函数指针                     wcex.cbClsExtra     = 0;  //紧跟在窗口类结构后的附加字节数wcex.cbWndExtra     = 0;  //紧跟在窗口事例后的附加字节数wcex.hInstance      = hInstance;//本模块的实例句柄wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_CLOCKWINDOW));//窗口左上角图标句柄wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);//光标句柄wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW); //背景画刷句柄wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_CLOCKWINDOW);//菜单名//wcex.lpszMenuName   =NULL;  //无菜单wcex.lpszClassName  = szWindowClass;  //此窗口类名wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));//小图标句柄return RegisterClassExW(&wcex);  //注册此窗口类
}

创建窗口、显示窗口、刷新客户区写成一个函数如下:

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{hInst = hInstance; // 将实例句柄存储在全局变量中HWND hWnd = CreateWindowW(szWindowClass,       //窗口类名szTitle,             //窗口标题WS_OVERLAPPEDWINDOW, //窗口风格 WS:window style                    CW_USEDEFAULT,       //初始位置X坐标CW_USEDEFAULT,       //初始位置Y坐标500,                 //宽度500,                 //高度nullptr,             //父窗口句柄nullptr,             //菜单句柄hInstance,           //程序实例句柄nullptr);            //用户数据if (!hWnd){return FALSE;}ShowWindow(hWnd, nCmdShow);  //显示窗口UpdateWindow(hWnd);          //刷新客户区return TRUE;
}

因此主函数可以写为:

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,_In_opt_ HINSTANCE hPrevInstance,_In_ LPWSTR    lpCmdLine,_In_ int       nCmdShow)
{UNREFERENCED_PARAMETER(hPrevInstance);UNREFERENCED_PARAMETER(lpCmdLine);// 初始化全局字符串
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);LoadStringW(hInstance, IDC_CLOCKWINDOW, szWindowClass, MAX_LOADSTRING);MyRegisterClass(hInstance);// 执行应用程序初始化: if (!InitInstance (hInstance, nCmdShow)){return FALSE;}HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_CLOCKWINDOW));MSG msg;// 主消息循环: while (GetMessage(&msg, nullptr, 0, 0))//GetMessage返回False程序结束
    {if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)){TranslateMessage(&msg);DispatchMessage(&msg);}}return (int) msg.wParam;  //程序结束时返回最后一个MSG的wParam。
}

在窗口作图

测试一:先打开notepad,之后运行此代码

    HWND hWnd;HDC hDC;hWnd = ::FindWindow(_TEXT("Notepad"), NULL);hDC = ::GetDC(hWnd);while (::IsWindow(hWnd)){    ::SetTextColor(hDC, RGB(255, 0, 0));::SetBkColor(hDC, RGB(0, 0, 0));::TextOut(hDC, 10, 10, _T("this is a test."), sizeof("this is a test.") - 2);HPEN hPen = CreatePen(NULL,4,RGB(255,255,255));::SelectObject(hDC, hPen);::SelectObject(hDC, ::GetStockObject(BLACK_BRUSH));Ellipse(hDC, 0, 0, 500, 500);Sleep(1000);::SelectObject(hDC, ::GetStockObject(WHITE_BRUSH));Ellipse(hDC, 0, 0, 500, 500);Sleep(1000);::SelectObject(hDC, ::GetStockObject(LTGRAY_BRUSH));Ellipse(hDC, 0, 0, 500, 500);Sleep(1000);::SelectObject(hDC, ::GetStockObject(GRAY_BRUSH));Ellipse(hDC, 0, 0, 500, 500);Sleep(1000);::SelectObject(hDC, ::GetStockObject(DKGRAY_BRUSH));Ellipse(hDC, 0, 0, 500, 500);Sleep(1000);::SelectObject(hDC, ::GetStockObject(DKGRAY_BRUSH));Ellipse(hDC, 0, 0, 500, 500);Sleep(1000);}ReleaseDC(hWnd, hDC);

绘图首先要取得设备环境句柄

            PAINTSTRUCT ps;HDC hdc = BeginPaint(hWnd, &ps);  //取得(窗口客户区无效区域)设备环境句柄//绘图代码//EndPaint(hWnd, &ps);HDC hdcW = ::GetWindowDC(hWnd);   //取得整个窗口设备环境句柄HDC hdcD = ::GetDC(hWnd);         //取得窗口客户区设备环境句柄(函数可用在任何地方)        

接着有时为了作图方便需要修改默认坐标系

void SetIsotropic(HWND hWnd,HDC hdc)
{RECT rect;GetClientRect(hWnd, &rect);       //取得客户区大小::SetMapMode(hdc, MM_ANISOTROPIC);  //自定义坐标系MM_ANISOTROPIC:X!=Y,MM_ISOTROPIC:X=Y::SetWindowExtEx(hdc, 500, 500, NULL);   //逻辑刻度,第四个参数可用于返回原来的大小::SetViewportExtEx(hdc, rect.right, -rect.bottom, NULL); //像素刻度(坐标方向),第四个参数可用于返回原来的大小::SetViewportOrgEx(hdc, rect.right / 2, rect.bottom / 2, NULL);  //修改坐标系(参照之前坐标系的位置坐标),第四个参数可用于返回原来的原点
}

修改完坐标系后开始绘制时钟表面

void paintClock(HWND hWnd,HDC hdc)
{HPEN hPenTri, hPenTime, hPenCent;HBRUSH hBrushTr, hBrushTime, hBrushCent;int colorUseR = (rand() % (255 - 0 + 1)) + 0;   //(rand() % (b-a+1))+ a; a~b随机数int colorUseG = (rand() % (255 - 0 + 1)) + 0;int colorUseB = (rand() % (255 - 0 + 1)) + 0;hPenTri = CreatePen(NULL, 4, RGB(255, colorUseG, 240));hBrushTr = ::CreateSolidBrush(RGB(255, colorUseG, 240));bankColor = RGB(255, colorUseG, 240);hPenTime = CreatePen(NULL, 4, RGB(colorUseR, 240, 240));hBrushTime = ::CreateSolidBrush(RGB(colorUseR, 240, 240));hPenCent = ::CreatePen(NULL, 4, RGB(240, 240, colorUseB));hBrushCent = ::CreateSolidBrush(RGB(240, 240, colorUseB));SetIsotropic(hWnd,hdc);
///三角形
    //SetDCBrushColor(hdc, RGB(255, 255, 255));//(无效)
    ::SelectObject(hdc, hPenTri);::SelectObject(hdc, hBrushTr);//POINT Mypoint[12] = { (250,10),(375,33.5),(466.5,125),(490,250),(466.5,375),(375,466.5),(250,490),(125,466.5),(33.5,375),(10,250),(33.5,125),(125,33.5) };//写法错误POINT Mypoint[12] = { 0,240,120,207.84,207.84,120,240,0,207.84,-120,120,-207.84,0,-240,-120,-207.84,-207.84,-120,-240,0,-207.84,120,-120,207.84 };//::ClientToScreen(hWnd, point);   //投射到屏幕坐标,返回至pointPOINT Mypoint1[3] = { Mypoint[0],Mypoint[4],Mypoint[8] };POINT Mypoint2[3] = { Mypoint[1],Mypoint[5],Mypoint[9] };POINT Mypoint3[3] = { Mypoint[2],Mypoint[6],Mypoint[10] };POINT Mypoint4[3] = { Mypoint[3],Mypoint[7],Mypoint[11] };//POINT Mypoint5[4]={ Mypoint1 ,Mypoint2,Mypoint3,Mypoint4}//不好用for循环简化操作,二维数组用不了??Polygon(hdc, Mypoint1, 3);Polygon(hdc, Mypoint2, 3);Polygon(hdc, Mypoint3, 3);Polygon(hdc, Mypoint4, 3);
//圆形===============================================================
::SelectObject(hdc, hPenTime);::SelectObject(hdc, hBrushTime);//图形填充色for (int i = 0; i < 12; i++){Ellipse(hdc, Mypoint[i].x - 10, Mypoint[i].y - 10, Mypoint[i].x + 10, Mypoint[i].y + 10);}
//中心点加文本=======================================================
    ::SelectObject(hdc, hPenCent);::SelectObject(hdc, hBrushCent);::Ellipse(hdc, -5, 5, 5, -5);::SetTextColor(hdc, RGB(0, 0, 0));  //文字颜色//::SetBkColor(hdc, TRANSPARENT);  //文字背景色,设置为透明无效::SetBkMode(hdc, TRANSPARENT);  //文字背景透明
CString strText = _T("时钟");TextOut(hdc, -240, 240, (LPCWSTR)strText, sizeof(strText) - 2);
}

绘制时钟的指针函数

void DrawHand(HDC hdc, int nLength, int nWidth, int nDegrees, COLORREF clrColor)
{double nRadians = (double)nDegrees * 2 * 3.1415926 / 360;POINT pt[2];pt[0].x = (int)(nLength*sin(nRadians));pt[0].y = (int)(nLength*cos(nRadians));pt[1].x = pt[0].x /-5;pt[1].y = pt[0].y /-5;HPEN hPen = ::CreatePen(PS_SOLID, nWidth, clrColor);HPEN oldPen = (HPEN)::SelectObject(hdc, hPen);::MoveToEx(hdc, pt[0].x, pt[0].y, NULL);LineTo(hdc, pt[1].x, pt[1].y);::SelectObject(hdc, oldPen);::DeleteObject(hPen);
}

在窗口函数WM_CREATE下设置定时器

    case WM_CREATE:
//当一个应用程序通过CreateWindowEx函数或者CreateWindow函数请求创建窗口时发送此消息,(此消息在函数返回之前发送)。
        SYSTEMTIME time;::GetLocalTime(&time);s_PreHour = time.wHour%12;//取余s_PreMinute = time.wMinute;s_PreSecond = time.wSecond;SetTimer(hWnd,   //窗口句柄IDT_CLOCK,//TimerID1000,     //间隔NULL);     //计时器函数指针return 0;//它应当返回0以使得窗口的创建过程得以继续。如果对于这个消息程序返回-1,窗口将会被销毁。//并且CreateWindowEx或者CreateWindow函数将会返回一个值为NULL的句柄。

在WM_TIMER下控制指针的变化与重画

    case WM_TIMER:paintClock(hWnd, hDC);//paintClock(hWnd, hDC);重画了时钟面板,使得覆盖了旧的时钟指针if (::IsIconic(hWnd))   //如果窗口是最小化{return 0;}::GetLocalTime(&time);//HDC hDC = ::GetDC(hWnd);//(无法写在这里)SetIsotropic(hWnd, hDC);//建立坐标系if (time.wMinute != s_PreMinute){            //DrawHand(hDC, 140, 8, s_PreHour * 30 + s_PreMinute / 2, bankColor);//使用时钟面板颜色覆盖原指针//DrawHand(hDC, 170, 6, s_PreMinute * 6, bankColor);  //覆盖失败(不能使得指针颜色完全消失,如同在相同的两点好几条画好几条线,看起来线条变粗并不像一条直线)
            s_PreHour = time.wHour;s_PreMinute = time.wMinute;}if (time.wSecond != s_PreSecond){//DrawHand(hDC, 170, 1, s_PreSecond * 6, bankColor);//使用时钟面板颜色覆盖原指针DrawHand(hDC, 80, 6, s_PreHour * 30 + s_PreMinute / 2, RGB(0,0,0));DrawHand(hDC, 120, 4, s_PreMinute * 6, RGB(0, 0, 0));DrawHand(hDC, 170, 2, s_PreSecond * 6, RGB(0, 0, 0));s_PreSecond = time.wSecond;}//::MessageBeep(MB_ICONASTERISK);//发出“嘟嘟”声break;

效果图

转载于:https://www.cnblogs.com/cteng-common/p/Window_Clock.html

VC++窗口创建过程,图形绘制,时钟程序相关推荐

  1. python kivy显示图片_python基于Kivy写一个图形桌面时钟程序代码示例

    本篇文章小编给大家分享一下python基于Kivy写一个图形桌面时钟程序代码示例,文章代码介绍的很详细,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以来看看. Kivy 是一个开源的 ...

  2. python时钟程序的设计总结_python基于Kivy写一个图形桌面时钟程序

    kivy 是一个开源的 python 第三方库,可以用来快速开发应用程序. 它有如下三个特点: 跨平台 kivy 编写的程序可在 linux,windows,os x,android,ios 和 ra ...

  3. 【Windows编程】windows窗口创建过程详解

    文章目录 前言 1 应用程序的分类 2 应用程序分类的对比 3 编译工具 4 windows库文件和头文件 5 WinMain函数和MessageBox函数初始 6 窗口类 7 窗口类的分类 8 注册 ...

  4. Python中Turtle绘图函数-绘制时钟程序

    Turtle常用的一些函数, 参考博客:http://blog.csdn.net/zengxiantao1994/article/details/76588580 时钟代码设计 我们可以通过main函 ...

  5. python开发桌面时钟_python基于Kivy写一个图形桌面时钟程序

    Kivy 是一个开源的 Python 第三方库,可以用来快速开发应用程序. 它有如下三个特点: 跨平台 Kivy 编写的程序可在 Linux,Windows,OS X,Android,iOS 和 Ra ...

  6. pygame的基础知识详解(主窗口创建、图像绘制、时钟对象和事件响应等知识点),请惠存

    各位好,很久没更新博客了,最近较为深入研究pygame库,有些心得体会,想分享给各位,准备做成一个系列知识.欢迎各位查阅. 这篇作为一个基础知识的宣贯,想和各位深入分享一下pygame的基础知识,深入 ...

  7. c++ dll发消息到主窗口_PyQt5学习笔记(五)窗口图形绘制

    PyQt5提供了绘制图形的API,支持绘制: 文本 各种图形(直线,点,椭圆,弧,扇形,多边形等) 图像 绘制图形需要一个类QPainter.基本的绘制过程: # 创建QPainter对象 paint ...

  8. c++ 读文件_第十六节:读文件,文件的创建,写文件,文件的读写以及鼠标键盘事件和图形绘制...

    读文件 //读文件 文件的创建 public 写文件 public 文件的读写 重点: 文件类主要功能:创建,读属性,写属性,删除等 文件读写操作 File类 File类的对象 用来获取文件本身的信息 ...

  9. 使用图形编辑框架GEF创建基于Eclipse的应用程序

    简介: 了解使用图形编辑框架(Graphical Editing Framework,GEF)创建基于 Eclipse 的应用程序涉及的最初步骤.此外,介绍了目前在 Eclipse 中引导创建图形编辑 ...

  10. VC++ 利用MFC的CWindowDC类实现画线功能 在桌面窗口中画线 绘制彩色线条 CPen nPenStyle nWidth crColor

    目录 利用MFC的CWindowDC类实现画线功能 在桌面窗口中画线 绘制彩色线条 CPen nPenStyle nWidth crColor 接上:VC++ 绘制线条 OnLButtonDown函数 ...

最新文章

  1. python模拟键盘输入字符_Python | 根据关键字符串遍历窗口 模拟键盘输入操作
  2. puppet recurse 导致的性能问题一例
  3. 2020-12-29 Linux查找某一关键字在哪个文件
  4. 优秀产品经理(CEO)必须get的财税知识
  5. HDU - 1525
  6. c语言字符串替换问题,C语言中的字符串替换
  7. 经典神经网络 -- GoogLeNet / Inception : 设计原理与pytorch实现
  8. 斐讯K2刷华硕固件教程(最新)
  9. 【广东大学生网络攻防大赛-WriteUp(非官方)】Pwn | jmp_rsp
  10. 程序员必备算法——排列组合
  11. 一文带你搞懂C#多线程的5种写法
  12. idea 占用内存优化调整
  13. 双千兆网口路由器方案开发板香橙派R1 Plus LTS连接USB无线网卡测试说明(OpenWRT 系统)
  14. 美通社企业新闻汇总 | 2019.2.28 | 软银愿景基金15亿美元投资车好多集团;凯悦携手如家创建合资公司...
  15. Java网络编程:TCP,UDP,sock编程
  16. 数组方法 + ES6中数组方法 + 数组的空位
  17. linux 安装yum命令
  18. Android多级列表的实现
  19. 常用的GUI框架(1)
  20. Python3语法笔记(前篇)

热门文章

  1. [svc]证书学习索引
  2. 【CentOS 7笔记26】,打包和压缩工具的使用#171108
  3. 戴尔完成600亿美元与EMC并购交易 戴尔科技正式成立
  4. mysql报错:You must at least set –server-id to enable either a master or a slave
  5. 基于Spark UI性能优化与调试——初级篇
  6. iMindMap12思维导图如何制作导图教程
  7. GET 和 POST请求的本质区别是什么?看完觉得自己太无知了...
  8. 程序员失业一月转行去送外卖,晒出当天收入,还以为看错了
  9. 《Linux就该这么学》正式版电子书发布!
  10. 你没听过的IT技术解读,能秒懂的都是老司机...