zoukankan      html  css  js  c++  java
  • Windows程序设计--(五)绘图基础

    5.1 GDI的结构

    图形设备接口(GDI:Graphics Device Interface)是Windows的子系统,它负责在视讯显示器和打印机上显示图形。

    5.2 设备环境

    5.2.1 获取设备环境句柄

    最常用的取得并释放设备内容句柄的方法是,在处理WM_PAINT消息时,使用BeginPaint和EndPaint呼叫:

    hdc = BeginPaint (hwnd, &ps) ;
    其它行程序
    EndPaint (hwnd, &ps) ;

    Windows程序还可以在处理非WM_PAINT消息时取得设备内容句柄:

    hdc = GetDC (hwnd) ;
    其它行程序
    ReleaseDC (hwnd, hdc) ;

    Windows程序还可以取得适用于整个窗口(而不仅限于窗口的显示区域)的设备内容句柄:

    hdc = GetWindowDC (hwnd) ;
    其它行程序
    ReleaseDC (hwnd, hdc) ;

    5.3 点和线的绘制

    5.3.1 设定像素

    SetPixel函数在指定的x和y坐标以特定的颜色设定图素:

    SetPixel (hdc, x, y, crColor) ;

    第一个参数是设备内容的句柄。第二个和第三个参数指明了坐标位置。通常要获得窗口显示区域的设备内容,并且x和y相对于该显示区域的左上角。最后一个参数是COLORREF型态指定了颜色。如果在函数中指定的颜色视讯显示器不支持,则函数将图素设定为最接近的纯色并从函数传回该值。

    GetPixel函数传回指定坐标处的图素颜色:

    crColor = GetPixel (hdc, x, y) ;

    5.3.2 直线

    画一条直线,必须呼叫两个函数。第一个函数指定了线的开始点,第二个函数指定了线的终点:

    MoveToEx (hdc, xBeg, yBeg, NULL) ;
    LineTo (hdc, xEnd, yEnd) ;

    绘制直线

    #include <Windows.h>
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);//消息函数声明
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)//主函数
    {
        static TCHAR szAppName[] = TEXT("WNDCLASS NAME");//窗口类名称
        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(NULL, IDI_APPLICATION);//加载图标
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);//鼠标,移入内容区域变成箭头
        wndclass.hbrBackground = (HBRUSH)GetStockObject(DKGRAY_BRUSH);//主窗口背景色
        wndclass.lpszMenuName = NULL;//窗口菜单
        wndclass.lpszClassName = szAppName;//窗口类名
    
        if (!RegisterClass(&wndclass)) {//注册窗口类,如果注册失败弹出窗口
            MessageBox(NULL, TEXT("窗口创建失败!程序需要Windows NT!(传递窗口消息为UNICODE)"), szAppName, MB_ICONERROR);//消息窗口
    
            return 0;
        }
    
        hwnd = CreateWindow(szAppName,                //Windows类名
            TEXT("窗口绘制成功!"),        //窗口标题
            WS_OVERLAPPEDWINDOW,    //窗口风格
            CW_USEDEFAULT,            //初始化窗口位置的X坐标
            CW_USEDEFAULT,            //初始化窗口位置的Y坐标
            500,            //初始化窗口宽度大小
            500,            //初始化窗口长度大小
            NULL,                    //父类窗口句柄
            NULL,                    //窗口菜单句柄
            hInstance,                //程序实例句柄
            NULL);                    //创建参数
        ShowWindow(hwnd, iCmdShow);//显示窗口
        UpdateWindow(hwnd);//更新窗口
    
        while (GetMessage(&msg, NULL, 0, 0)) {//从消息队列中获取消息
            TranslateMessage(&msg);//将虚拟键消息转换为字符消息
            DispatchMessage(&msg);//分发到回调函数
        }
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
        HDC hdc;//设备环境句柄
        int x, y;
        /*
        typedef struct tagRECT
        {
            LONG    left;
            LONG    top;
            LONG    right;
            LONG    bottom;
        } RECT
        其中left,top赋为0,因此right和bottom表示客户区的宽度和高度(像素)
        */
        RECT rect;//矩形结构
    
        switch (message) {//处理得到的消息
        case WM_PAINT://处理窗口绘制
            hdc = GetDC(hwnd);
            GetClientRect(hwnd, &rect);//获取当前位置
            for (x = 0; x < rect.right; x += 50) {//竖线
                MoveToEx(hdc, x, 0, NULL);//设置起点
                LineTo(hdc, x, rect.bottom);//设置终点
            }
            for (y = 0; y < rect.bottom; y += 50) {//横线
                MoveToEx(hdc, 0, y, NULL);
                LineTo(hdc, rect.right, y);
            }
            ReleaseDC(hwnd, hdc);
            return 0;
        case WM_DESTROY://处理窗口关闭时的消息
            PostQuitMessage(0);//将退出消息插入消息队列,程序从消息循环退出,return msg.wParam
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);//执行默认消息处理
    }

    绘制矩形

    #include <Windows.h>
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);//消息函数声明
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)//主函数
    {
        static TCHAR szAppName[] = TEXT("WNDCLASS NAME");//窗口类名称
        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(NULL, IDI_APPLICATION);//加载图标
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);//鼠标,移入内容区域变成箭头
        wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITENESS);//主窗口背景色
        wndclass.lpszMenuName = NULL;//窗口菜单
        wndclass.lpszClassName = szAppName;//窗口类名
    
        if (!RegisterClass(&wndclass)) {//注册窗口类,如果注册失败弹出窗口
            MessageBox(NULL, TEXT("窗口创建失败!程序需要Windows NT!(传递窗口消息为UNICODE)"), szAppName, MB_ICONERROR);//消息窗口
    
            return 0;
        }
    
        hwnd = CreateWindow(szAppName,                //Windows类名
            TEXT("Hk_Mayfly"),        //窗口标题
            WS_OVERLAPPEDWINDOW,    //窗口风格
            CW_USEDEFAULT,            //初始化窗口位置的X坐标
            CW_USEDEFAULT,            //初始化窗口位置的Y坐标
            500,            //初始化窗口宽度大小
            500,            //初始化窗口长度大小
            NULL,                    //父类窗口句柄
            NULL,                    //窗口菜单句柄
            hInstance,                //程序实例句柄
            NULL);                    //创建参数
        ShowWindow(hwnd, iCmdShow);//显示窗口
        UpdateWindow(hwnd);//更新窗口
    
        while (GetMessage(&msg, NULL, 0, 0)) {//从消息队列中获取消息
            TranslateMessage(&msg);//将虚拟键消息转换为字符消息
            DispatchMessage(&msg);//分发到回调函数
        }
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
        HDC hdc;//设备环境句柄
        POINT apt[5] = { 100, 100, 200, 100, 200, 200, 100, 200, 100, 100 };//矩形坐标
        int i;
        /*
        typedef struct tagRECT
        {
            LONG    left;
            LONG    top;
            LONG    right;
            LONG    bottom;
        } RECT
        其中left,top赋为0,因此right和bottom表示客户区的宽度和高度(像素)
        */
        RECT rect;//矩形结构
    
        switch (message) {//处理得到的消息
        case WM_PAINT://处理窗口绘制
            hdc = GetDC(hwnd);
            GetClientRect(hwnd, &rect);//获取当前位置
            MoveToEx(hdc, apt[0].x, apt[0].y, NULL);
            for (i = 1; i < 5; ++i) {
                LineTo(hdc, apt[i].x, apt[i].y);
            }
            ReleaseDC(hwnd, hdc);
            return 0;
        case WM_DESTROY://处理窗口关闭时的消息
            PostQuitMessage(0);//将退出消息插入消息队列,程序从消息循环退出,return msg.wParam
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);//执行默认消息处理
    }
    View Code

    使用Polyline替换,也可以绘制矩形。

    Polyline(hdc, apt, 5);

    或者

    MoveToEx(hdc, apt[0].x, apt[0].y, NULL);
    PolylineTo(hdc, apt, 5);

    绘制正弦曲线

    #include <Windows.h>
    #include <math.h>
    
    #define NUM 1000
    #define TWOPI (2*3.14159)
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);//消息函数声明
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)//主函数
    {
        static TCHAR szAppName[] = TEXT("WNDCLASS NAME");//窗口类名称
        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(NULL, IDI_APPLICATION);//加载图标
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);//鼠标,移入内容区域变成箭头
        wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITENESS);//主窗口背景色
        wndclass.lpszMenuName = NULL;//窗口菜单
        wndclass.lpszClassName = szAppName;//窗口类名
    
        if (!RegisterClass(&wndclass)) {//注册窗口类,如果注册失败弹出窗口
            MessageBox(NULL, TEXT("窗口创建失败!程序需要Windows NT!(传递窗口消息为UNICODE)"), szAppName, MB_ICONERROR);//消息窗口
    
            return 0;
        }
    
        hwnd = CreateWindow(szAppName,                //Windows类名
            TEXT("Hk_Mayfly"),        //窗口标题
            WS_OVERLAPPEDWINDOW,    //窗口风格
            CW_USEDEFAULT,            //初始化窗口位置的X坐标
            CW_USEDEFAULT,            //初始化窗口位置的Y坐标
            1000,            //初始化窗口宽度大小
            500,            //初始化窗口高度大小
            NULL,                    //父类窗口句柄
            NULL,                    //窗口菜单句柄
            hInstance,                //程序实例句柄
            NULL);                    //创建参数
        ShowWindow(hwnd, iCmdShow);//显示窗口
        UpdateWindow(hwnd);//更新窗口
    
        while (GetMessage(&msg, NULL, 0, 0)) {//从消息队列中获取消息
            TranslateMessage(&msg);//将虚拟键消息转换为字符消息
            DispatchMessage(&msg);//分发到回调函数
        }
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
        HDC hdc;//设备环境句柄
        PAINTSTRUCT ps;
        static int cxClient, cyClient;
        int i;
        POINT apt[NUM];
    
        switch (message) {//处理得到的消息
        case WM_SIZE:
            cxClient = LOWORD(lParam);//客户区宽度
            cyClient = HIWORD(lParam);//客户区的高度
            return 0;
        case WM_PAINT://处理窗口绘制
            hdc = BeginPaint(hwnd, &ps);
            MoveToEx(hdc, 0, cyClient / 2, NULL);//中间横线
            LineTo(hdc, cxClient, cyClient / 2);
            
            for (i = 0; i < NUM; i++) {
                apt[i].x = i * cxClient / NUM;
                apt[i].y = (int)(cyClient / 2 * (1 - sin(TWOPI * i / NUM)));
                //apt[i].x = i*15;
                //apt[i].y = (int)cyClient*sin(0.1*i);
            }
            Polyline(hdc, apt, NUM);
            EndPaint(hwnd, &ps);
            return 0;
        case WM_DESTROY://处理窗口关闭时的消息
            PostQuitMessage(0);//将退出消息插入消息队列,程序从消息循环退出,return msg.wParam
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);//执行默认消息处理
    }
    View Code

    5.3.3 边框绘制函数

    #include <Windows.h>
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
    {
        static TCHAR szAppName[] = TEXT("WNDCLASS NAME");
        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(NULL, IDI_APPLICATION);
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wndclass.lpszMenuName = NULL;
        wndclass.lpszClassName = szAppName;
    
        if (!RegisterClass(&wndclass)) {
            MessageBox(NULL, TEXT("窗口创建失败!需要Windows NT!(传递消息为UNICODE)"), szAppName, MB_ICONERROR);
    
            return 0;
        }
    
        hwnd = CreateWindow(
            szAppName,
            TEXT("Hk_Mayfly"),
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            1000,//宽度
            500,//高度
            NULL,
            NULL,
            hInstance,
            NULL
        );
        ShowWindow(hwnd, iCmdShow);
        UpdateWindow(hwnd);
    
        while (GetMessage(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
        HDC hdc;
        PAINTSTRUCT ps;
    
        switch (message) {
        case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);
            //Rectangle(hdc, 100, 200, 500, 400);//矩形
            //Ellipse(hdc, 100, 200, 500, 400);//椭圆
            //RoundRect(hdc, 100, 200, 500, 400, 100, 100);//圆角矩阵
            //Arc(hdc, 100, 200, 500, 400, 500, 350, 100, 350);////Chord(hdc, 100, 200, 500, 400, 500, 350, 100, 350);////Pie(hdc, 100, 200, 500, 400, 500, 350, 100, 350);//
            EndPaint(hwnd, &ps);
            return 0;
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    View Code

    自定义程序

    #include <Windows.h>
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
    {
        static TCHAR szAppName[] = TEXT("WNDCLASS NAME");
        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(NULL, IDI_APPLICATION);
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wndclass.lpszMenuName = NULL;
        wndclass.lpszClassName = szAppName;
    
        if (!RegisterClass(&wndclass)) {
            MessageBox(NULL, TEXT("窗口创建失败!需要Windows NT!(传递消息为UNICODE)"), szAppName, MB_ICONERROR);
    
            return 0;
        }
    
        hwnd = CreateWindow(
            szAppName,
            TEXT("Hk_Mayfly"),
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            800,//宽度
            800,//高度
            NULL,
            NULL,
            hInstance,
            NULL
        );
        ShowWindow(hwnd, iCmdShow);
        UpdateWindow(hwnd);
    
        while (GetMessage(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
        static int cxClient, cyClient;
        HDC hdc;
        PAINTSTRUCT ps;
    
        switch (message) {
        case WM_SIZE:
            cxClient = LOWORD(lParam);
            cyClient = HIWORD(lParam);
            return 0;
        case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);
            Rectangle(hdc, 200, 200, 600, 600);
            MoveToEx(hdc, 0, 0, NULL);
            LineTo(hdc, 200, 200);
            MoveToEx(hdc, cxClient, 0, NULL);
            LineTo(hdc, 600, 200);
            MoveToEx(hdc, 0, cyClient, NULL);
            LineTo(hdc, 200, 600);
            MoveToEx(hdc, cxClient, cyClient, NULL);
            LineTo(hdc, 600, 600);
            Ellipse(hdc, 200, 200, 600, 600);
            Arc(hdc, 300, 200, 500, 400, 400, 200, 400, 400);//弧,逆时针绘制
            Arc(hdc, 300, 400, 500, 600, 400, 600, 400, 400);
            Ellipse(hdc, 388, 288, 412, 312);//小圆圈
            Ellipse(hdc, 388, 488, 412, 512);
            EndPaint(hwnd, &ps);
            return 0;
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
    }

    5.3.4 贝塞尔样条曲线

    一条二维的贝塞尔曲线由四个点定义-两个端点和两个控制点。曲线的端点在两个端点上,控制点就好像「磁石」一样把曲线从两个端点间的直线处拉走。

    #include <Windows.h>
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
    {
        static TCHAR szAppName[] = TEXT("WNDCLASS NAME");
        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(NULL, IDI_APPLICATION);
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wndclass.lpszMenuName = NULL;
        wndclass.lpszClassName = szAppName;
    
        if (!RegisterClass(&wndclass)) {
            MessageBox(NULL, TEXT("窗口创建失败!需要Windows NT!(传递消息为UNICODE)"), szAppName, MB_ICONERROR);
    
            return 0;
        }
    
        hwnd = CreateWindow(
            szAppName,
            TEXT("Hk_Mayfly"),
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,//宽度
            CW_USEDEFAULT,//高度
            NULL,
            NULL,
            hInstance,
            NULL
        );
        ShowWindow(hwnd, iCmdShow);
        UpdateWindow(hwnd);
    
        while (GetMessage(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    
        return msg.wParam;
    }
    
    void DrawBezier(HDC hdc, POINT apt[]) {
        PolyBezier(hdc, apt, 4);
    
        MoveToEx(hdc, apt[0].x, apt[0].y, NULL);
        LineTo(hdc, apt[1].x, apt[1].y);
    
        MoveToEx(hdc, apt[2].x, apt[2].y, NULL);
        LineTo(hdc, apt[3].x, apt[3].y);
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
        static POINT apt[4];
        int cxClient, cyClient;
        HDC hdc;
        PAINTSTRUCT ps;
    
        switch (message) {
        case WM_SIZE:
            cxClient = LOWORD(lParam);
            cyClient = HIWORD(lParam);
    
            apt[0].x = cxClient / 4;
            apt[0].y = cyClient / 2;
    
            apt[1].x = cxClient / 2;
            apt[1].y = cyClient / 4;
    
            apt[2].x = cxClient / 2;
            apt[2].y = 3 * cyClient / 4;
    
            apt[3].x = 3 * cxClient / 4;
            apt[3].y = cyClient / 2;
    
            return 0;
        case WM_LBUTTONDOWN:
        case WM_RBUTTONDOWN:
        case WM_MOUSEMOVE:
            if (wParam & MK_LBUTTON || wParam & MK_RBUTTON) {
                hdc = GetDC(hwnd);
    
                SelectObject(hdc, GetStockObject(WHITE_PEN));
                DrawBezier(hdc, apt);
                if (wParam & MK_LBUTTON) {
                    apt[1].x = LOWORD(lParam);
                    apt[1].y = HIWORD(lParam);
                }
                if (wParam & MK_RBUTTON) {
                    apt[2].x = LOWORD(lParam);
                    apt[2].y = HIWORD(lParam);
                }
                SelectObject(hdc, GetStockObject(BLACK_PEN));
                DrawBezier(hdc, apt);
                ReleaseDC(hwnd, hdc);
            }
    
            return 0;
        case WM_PAINT:
            InvalidateRect(hwnd, NULL, TRUE);
            hdc = BeginPaint(hwnd, &ps);
            DrawBezier(hdc, apt);
            EndPaint(hwnd, &ps);
            return 0;
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    View Code

    5.3.6 创建,选择和删除画笔

    #include <Windows.h>
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
    {
        static TCHAR szAppName[] = TEXT("WNDCLASS NAME");
        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(NULL, IDI_APPLICATION);
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wndclass.lpszMenuName = NULL;
        wndclass.lpszClassName = szAppName;
    
        if (!RegisterClass(&wndclass)) {
            MessageBox(NULL, TEXT("窗口创建失败!需要Windows NT!(传递消息为UNICODE)"), szAppName, MB_ICONERROR);
    
            return 0;
        }
    
        hwnd = CreateWindow(
            szAppName,
            TEXT("Hk_Mayfly"),
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            800,//宽度
            800,//高度
            NULL,
            NULL,
            hInstance,
            NULL
        );
        ShowWindow(hwnd, iCmdShow);
        UpdateWindow(hwnd);
    
        while (GetMessage(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
        static int cxClient, cyClient;
        HDC hdc;
        PAINTSTRUCT ps;
        static HPEN hPen1, hPen2;
    
        switch (message) {
        case WM_CREATE:
            hPen1 = CreatePen(PS_DOT, 0, 0);
            hPen2 = CreatePen(PS_DASH, 1, RGB(255, 0, 0));
        case WM_SIZE:
            cxClient = LOWORD(lParam);
            cyClient = HIWORD(lParam);
            return 0;
        case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);
            SelectObject(hdc, hPen1);
            Ellipse(hdc, 200, 200, 600, 600);
            Ellipse(hdc, 388, 288, 412, 312);//小圆圈
            SelectObject(hdc, hPen2);
            Arc(hdc, 300, 200, 500, 400, 400, 200, 400, 400);//弧,逆时针绘制
            SelectObject(hdc, CreatePen(PS_DASH, 1, RGB(50, 50, 50)));
            Arc(hdc, 300, 400, 500, 600, 400, 600, 400, 400);
            Ellipse(hdc, 388, 488, 412, 512);
            DeleteObject(SelectObject(hdc, CreatePen(PS_DASH, 1, RGB(50, 50, 50))));
            EndPaint(hwnd, &ps);
            return 0;
        case WM_DESTROY:
            DeleteObject(hPen1);
            DeleteObject(hPen2);
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
    }

    5.4 绘制填充区域

    #include <Windows.h>
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
    {
        static TCHAR szAppName[] = TEXT("WNDCLASS NAME");
        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(NULL, IDI_APPLICATION);
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wndclass.lpszMenuName = NULL;
        wndclass.lpszClassName = szAppName;
    
        if (!RegisterClass(&wndclass)) {
            MessageBox(NULL, TEXT("窗口创建失败!需要Windows NT!(传递消息为UNICODE)"), szAppName, MB_ICONERROR);
    
            return 0;
        }
    
        hwnd = CreateWindow(
            szAppName,
            TEXT("Hk_Mayfly"),
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            800,//宽度
            800,//高度
            NULL,
            NULL,
            hInstance,
            NULL
        );
        ShowWindow(hwnd, iCmdShow);
        UpdateWindow(hwnd);
    
        while (GetMessage(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
        static int cxClient, cyClient;
        HDC hdc;
        PAINTSTRUCT ps;
        static HBRUSH hBrush;
    
        switch (message) {
        case WM_CREATE:
            hBrush = GetStockObject(LTGRAY_BRUSH);//获取句柄
        case WM_SIZE:
            cxClient = LOWORD(lParam);
            cyClient = HIWORD(lParam);
            return 0;
        case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);
            SelectObject(hdc, hBrush);//选入设备环境
            Ellipse(hdc, 200, 200, 600, 600);
            Ellipse(hdc, 388, 288, 412, 312);//小圆圈
            Arc(hdc, 300, 200, 500, 400, 400, 200, 400, 400);//弧,逆时针绘制
            Arc(hdc, 300, 400, 500, 600, 400, 600, 400, 400);
            Ellipse(hdc, 388, 488, 412, 512);
            DeleteObject(SelectObject(hdc, CreatePen(PS_DASH, 1, RGB(50, 50, 50))));
            EndPaint(hwnd, &ps);
            return 0;
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    View Code

    5.4.1 Polygon函数和多边形填充模式

    Polygon按照点的顺序连接多边图形,如果数组中最后一个点与第一个点不同,则Windows会再添加一条线连接最后一个点与第一个点。

    #include <Windows.h>
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
    {
        static TCHAR szAppName[] = TEXT("WNDCLASS NAME");
        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(NULL, IDI_APPLICATION);
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wndclass.lpszMenuName = NULL;
        wndclass.lpszClassName = szAppName;
    
        if (!RegisterClass(&wndclass)) {
            MessageBox(NULL, TEXT("窗口创建失败!需要Windows NT!(传递消息为UNICODE)"), szAppName, MB_ICONERROR);
    
            return 0;
        }
    
        hwnd = CreateWindow(
            szAppName,
            TEXT("Hk_Mayfly"),
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,//宽度
            CW_USEDEFAULT,//高度
            NULL,
            NULL,
            hInstance,
            NULL
        );
        ShowWindow(hwnd, iCmdShow);
        UpdateWindow(hwnd);
    
        while (GetMessage(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
        static POINT apt[6] = { 100, 200, 100, 100, 200, 50, 300, 100, 300, 200, 200,  250};
        static int cxClient, cyClient;
        HDC hdc;
        PAINTSTRUCT ps;
    
        switch (message) {
        case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);
            SelectObject(hdc, GetStockObject(GRAY_BRUSH));//获取灰色画刷并设置到环境设备中
            Polygon(hdc, apt, 6);
            EndPaint(hwnd, &ps);
            return 0;
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
    }

    PolyPolygon(hdc, apt, aiCounts, iPolyCount);

    #include <Windows.h>
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
    {
        static TCHAR szAppName[] = TEXT("WNDCLASS NAME");
        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(NULL, IDI_APPLICATION);
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wndclass.lpszMenuName = NULL;
        wndclass.lpszClassName = szAppName;
    
        if (!RegisterClass(&wndclass)) {
            MessageBox(NULL, TEXT("窗口创建失败!需要Windows NT!(传递消息为UNICODE)"), szAppName, MB_ICONERROR);
    
            return 0;
        }
    
        hwnd = CreateWindow(
            szAppName,
            TEXT("Hk_Mayfly"),
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,//宽度
            CW_USEDEFAULT,//高度
            NULL,
            NULL,
            hInstance,
            NULL
        );
        ShowWindow(hwnd, iCmdShow);
        UpdateWindow(hwnd);
    
        while (GetMessage(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
        static POINT apt[10] = { 100, 200, 100, 100, 200, 50, 300, 100, 300, 200, 200,  250, 400, 200, 400, 100, 500, 50, 600, 100 };//六边形(前6组坐标)和四边形
        static int aiCounts[2] = { 6, 4 };//6个顶点,4个顶点
        static int cxClient, cyClient;
        HDC hdc;
        PAINTSTRUCT ps;
    
        switch (message) {
        case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);
            SelectObject(hdc, GetStockObject(GRAY_BRUSH));//获取灰色画刷并设置到环境设备中
            PolyPolygon(hdc, apt, aiCounts, 2);
            EndPaint(hwnd, &ps);
            return 0;
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
    }

    #include <Windows.h>
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
    {
        static TCHAR szAppName[] = TEXT("WNDCLASS NAME");
        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(NULL, IDI_APPLICATION);
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wndclass.lpszMenuName = NULL;
        wndclass.lpszClassName = szAppName;
    
        if (!RegisterClass(&wndclass)) {
            MessageBox(NULL, TEXT("窗口创建失败!需要Windows NT!(传递消息为UNICODE)"), szAppName, MB_ICONERROR);
    
            return 0;
        }
    
        hwnd = CreateWindow(
            szAppName,
            TEXT("Hk_Mayfly"),
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,//宽度
            CW_USEDEFAULT,//高度
            NULL,
            NULL,
            hInstance,
            NULL
        );
        ShowWindow(hwnd, iCmdShow);
        UpdateWindow(hwnd);
    
        while (GetMessage(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
        static POINT aptFigure[10] = { 10, 70, 50, 70, 50, 10, 90, 10, 90, 50, 30, 50, 30, 90, 70, 90, 70, 30, 10, 30 };
        static int cxClient, cyClient;
        HDC hdc;
        PAINTSTRUCT ps;
        int i;
        static POINT apt[10];
    
        switch (message) {
        case WM_SIZE:
            cxClient = LOWORD(lParam);
            cyClient = HIWORD(lParam);
            return 0;
        case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);
            SelectObject(hdc, GetStockObject(GRAY_BRUSH));//获取灰色画刷并设置到环境设备中
            for (i = 0; i < 10; ++i) {
                apt[i].x = cxClient * aptFigure[i].x / 200;
                apt[i].y = cyClient * aptFigure[i].y / 100;
            }
            SetPolyFillMode(hdc, ALTERNATE);//设置填充模式为交替模式
            Polygon(hdc, apt, 10);
            for (i = 0; i < 10; ++i) {
                apt[i].x += cxClient / 2;
            }
            SetPolyFillMode(hdc, WINDING);//设置填充模式为螺旋模式
            Polygon(hdc, apt, 10);
            EndPaint(hwnd, &ps);
            return 0;
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
    }

     

    5.4.2 用画刷填充内部

    #include <Windows.h>
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
    {
        static TCHAR szAppName[] = TEXT("WNDCLASS NAME");
        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(NULL, IDI_APPLICATION);
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wndclass.lpszMenuName = NULL;
        wndclass.lpszClassName = szAppName;
    
        if (!RegisterClass(&wndclass)) {
            MessageBox(NULL, TEXT("窗口创建失败!需要Windows NT!(传递消息为UNICODE)"), szAppName, MB_ICONERROR);
    
            return 0;
        }
    
        hwnd = CreateWindow(
            szAppName,
            TEXT("Hk_Mayfly"),
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,//宽度
            CW_USEDEFAULT,//高度
            NULL,
            NULL,
            hInstance,
            NULL
        );
        ShowWindow(hwnd, iCmdShow);
        UpdateWindow(hwnd);
    
        while (GetMessage(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
        static POINT apt[6] = { 100, 200, 100, 100, 200, 50, 300, 100, 300, 200, 200,  250};
        HDC hdc;
        PAINTSTRUCT ps;
        HBRUSH hBrush;
        static int i;
    
        switch (message) {
        case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);
            //SetBkMode(hdc, TRANSPARENT);
            hBrush = CreateSolidBrush(BLACK_BRUSH);//创建一个纯色画刷,但是这个画刷不一定为纯色
            //SelectObject(hdc, GetStockObject(GRAY_BRUSH));//获取灰色画刷并设置到环境设备中
            SelectObject(hdc, hBrush);//将画刷选入设备环境
            Polygon(hdc, apt, 6);
            for (i = 0; i < 6; ++i) {
                apt[i].x += 300;
            }
            hBrush = CreateHatchBrush(HS_FDIAGONAL, GRAY_BRUSH);//第一个参数是阴影线标记的外观
            SelectObject(hdc, hBrush);
            Polygon(hdc, apt, 6);
            EndPaint(hwnd, &ps);
            return 0;
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
    }

    5.5 GDI映射模式

     Windows定义了8种映像方式,它们在WINGDI.H中相应的标识符和含义如表

    映像方式 逻辑单位 增加值
    x值 y值
    MM_TEXT 图素
    MM_LOMETRIC 0.1 mm
    MM_HIMETRIC 0.01 mm
    MM_LOENGLISH 0.01 in.
    MM_HIENGLISH 0.001 in.
    MM_TWIPS 1/1440 in.
    MM_ISOTROPIC 任意(x = y) 可选 可选
    MM_ANISOTROPIC 任意(x != y) 可选 可选
    #include <Windows.h>
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
    {
        static TCHAR szAppName[] = TEXT("WNDCLASS NAME");
        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(NULL, IDI_APPLICATION);
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wndclass.lpszMenuName = NULL;
        wndclass.lpszClassName = szAppName;
    
        if (!RegisterClass(&wndclass)) {
            MessageBox(NULL, TEXT("窗口创建失败!需要Windows NT!(传递消息为UNICODE)"), szAppName, MB_ICONERROR);
    
            return 0;
        }
    
        hwnd = CreateWindow(
            szAppName,
            TEXT("Hk_Mayfly"),
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,//宽度
            CW_USEDEFAULT,//高度
            NULL,
            NULL,
            hInstance,
            NULL
        );
        ShowWindow(hwnd, iCmdShow);
        UpdateWindow(hwnd);
    
        while (GetMessage(&msg, NULL, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
        HDC hdc;
        PAINTSTRUCT ps;
        static int iMapMode;
        TCHAR szBuffer[] = L"Hk_Mayfly!!!!?";
    
        switch (message) {
        case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);
            iMapMode = GetMapMode(hdc);//获取当前的映射模式
            TextOut(hdc, 1, 400, szBuffer, lstrlen(szBuffer));//逻辑单位1像素, 一像素0.3mm
            
            int iLength = wsprintf(szBuffer, TEXT("Biu biu!!!"));
            iMapMode = MM_TWIPS;
            SetMapMode(hdc, iMapMode);//逻辑单位1/1440in, 一英寸2.54cm
            TextOut(hdc, 1, -400, szBuffer, iLength);
    
            iMapMode = MM_LOMETRIC;
            SetMapMode(hdc, iMapMode);//逻辑单位0.1mm
            TextOut(hdc, 1, -400, szBuffer, wsprintf(szBuffer, TEXT("%s"), L"Test!!!"));
            EndPaint(hwnd, &ps);
            return 0;
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
    }

    5.5.1 设备坐标和逻辑坐标

    在呼叫GetTextMetrics以取得关于字符的宽度和高度信息时,映像方式必须设定成根据这些信息输出文字时所使用的映像方式

    5.5.2 设备坐标系统

    「屏幕坐标」:当我们使用整个屏幕时,就根据「屏幕坐标」进行操作。屏幕的左上角为(0,0)点,屏幕坐标用在WM_MOVE消息(对于非子窗口)以及下列Windows函数中:CreateWindow和MoveWindow(都是对于非子窗口)、GetMessagePos、GetCursorPos、SetCursorPos、GetWindowRect以及WindowFromPoint(这不是全部函数的列表)。它们或者是与窗口无关的函数(如两个光标函数),或者是必须相对于某个屏幕点来移动(或者寻找)窗口的函数。如果以DISPLAY为参数呼叫CreateDC,以取得整个屏幕的设备内容,则内定情况下GDI呼叫中指定的逻辑坐标将被映像为屏幕坐标。

    「全窗口坐标」:以程序的整个窗口为基准,如标题列、菜单、滚动条和窗口框都包括在内。而对于普通窗口,点(0,0)是缩放边框的左上角。全窗口坐标在Windows中极少使用,但是如果用GetWindowDC取得设备内容,GDI函数中的逻辑坐标就会转换为显示区域坐标。

    「显示区域坐标系」:点(0,0)是显示区域的左上角。当使用GetDC或BeginPaint取得设备内容时,GDI函数中的逻辑坐标就会内定转换为显示区域坐标。


    用函数ClientToScreen和ScreenToClient可以将显示区域坐标转换为屏幕坐标,或者反过来,将屏幕坐标转换为显示区域坐标。也可以使用GetWindowRect函数取得屏幕坐标下的整个窗口的位置和大小。这三个函数为一种设备坐标转换为另一种提供了足够的信息。

    5.5.4 使用MM_TEXT

    https://www.cnblogs.com/Mayfly-nymph/p/11414063.html

  • 相关阅读:
    CSS3 target伪类简介
    不用position,让div垂直居中
    css3 在线编辑工具 连兼容都写好了
    a标签伪类的顺序
    oncopy和onpaste
    【leetcode】1523. Count Odd Numbers in an Interval Range
    【leetcode】1518. Water Bottles
    【leetcode】1514. Path with Maximum Probability
    【leetcode】1513. Number of Substrings With Only 1s
    【leetcode】1512. Number of Good Pairs
  • 原文地址:https://www.cnblogs.com/Mayfly-nymph/p/11342567.html
Copyright © 2011-2022 走看看