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

  • 相关阅读:
    The xp_cmdshell proxy account information cannot be retrieved or is invalid. Verify that the '##xp_cmdshell_proxy_account##' credential exists and contains valid information.
    SQL SERVER-创建Alwayson
    Powershell-远程操作
    powershell-将powershell脚本排到JOB
    powershell-脚本运行权限政策
    Winserver-默认以管理员运行程序
    Powershell-创建Module
    SQL SERVER-查询爆破sa密码的主机
    power-virus
    141.Linked List Cycle 快慢指针
  • 原文地址:https://www.cnblogs.com/Mayfly-nymph/p/11342567.html
Copyright © 2011-2022 走看看