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);//执行默认消息处理
}

使用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);//执行默认消息处理
}

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);
}

自定义程序

#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);
}

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);
}

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函数取得屏幕坐标下的整个窗口的位置和大小。这三个函数为一种设备坐标转换为另一种提供了足够的信息。

原文地址:https://www.cnblogs.com/Mayfly-nymph/p/11342567.html

时间: 2024-10-12 12:15:43

Windows程序设计--(五)绘图基础的相关文章

Windows GDI绘图基础知识

一.Windows可以画直线.椭圆线(椭圆圆周上的曲线)和贝塞尔曲线.////////////7 个画线函式是:(1)画直线LineTo    BOOL LineTo(HDC hdc,int nXEnd,int nYEnd);结合MoveToEx函数使用BOOL MoveToEx(HDC hdc,int X,int Y,LPPOINT lpPoint);Point记录了旧的坐标点(先前的当前位置).///注意:GetCurrentPositionEx (hdc, &pt) ;获得当前位置. (2

关于《Windows程序设计(第五版)》中一个实例程序的疑问

最近一直在看Charlse Petzold的<Windows程序设计>,作为一个新得不能再新的新手,只能先照着书的抄抄源码了,之前的例子一直都很正常,但昨天遇到一个很诡异的BUG. 先看实例源码吧: 1 /*----------------------------------------------------------------- 2 ENVIRON.C -- Environment List Box 3 (c) Charles Petzold,1998 4 Copy by XXXX,2

《Windows程序设计》复习题

<Windows程序设计>模拟题 一.单项选择题 1. 在VC++中,项目文件的扩展名是(B). A)exe                                             B)dsp C) dsw                                             D)cpp 2. 在MFC中,利用ClassWizard不能(D ). A)建立新类                                    B)进行消息映射 C) 增加类

Android中Canvas绘图基础详解(附源码下载)

Android中,如果我们想绘制复杂的自定义View或游戏,我们就需要熟悉绘图API.Android通过Canvas类暴露了很多drawXXX方法,我们可以通过这些方法绘制各种各样的图形.Canvas绘图有三个基本要素:Canvas.绘图坐标系以及Paint.Canvas是画布,我们通过Canvas的各种drawXXX方法将图形绘制到Canvas上面,在drawXXX方法中我们需要传入要绘制的图形的坐标形状,还要传入一个画笔Paint.drawXXX方法以及传入其中的坐标决定了要绘制的图形的形状

QT绘图基础(一)

2D绘图 Qt4中的2D绘图部分称为Arthur绘图系统.它由3个类支撑整个框架,QPainter,QPainterDevice和QPainterEngine.QPainter用来执行具体的绘图相关操作如画点,画线,填充,变换,alpha通道等.QPainterDevice是QPainter用来绘图的绘图设备,Qt中有几种预定义的绘图设备,如QWidget,QPixamp,QPrinter等.他们都从QPaintDevice继承.QPaintEngine类提供了不同类型设备的接口,QPaintE

Win32 Windows编程 五

一 Win32消息机制 1 消息机制 过程驱动:程序是按照我们预先定义好的顺序执行,每执行一步,下一步都已经按照预定的顺序继续执行,直到程序结束 事件驱动: 程序的执行顺序是无序的.某个事件点所执行的代码,是由外界通知.由于我们无法决定用户执行顺序,所以代码的执行也是无序 Win32的消息机制 - 事件驱动 2 Win32消息程序 2.1 Win32 窗口注册 2.2 Win32窗口创建 2.3 Win32消息循环 2.3.1 GetMessage BOOL GetMessage( LPMSG

windows 程序设计自学:添加图标资源

1 #include <windows.h> 2 #include "resource.h" 3 4 LRESULT CALLBACK MyWndProc( HWND hwnd, // handle to window 5 UINT uMsg, // message identifier 6 WPARAM wParam, // first message parameter 7 LPARAM lParam // second message parameter 8 ); 9

Windows 程序设计 复习笔记(共 77 问)

Windows 程序设计 复习笔记(共 77 问) (个人整理,仅做复习用 :D,转载注明出处:http://blog.csdn.net/hcbbt/article/details/42706501) 知识点 双字节字符集和Unicode字符集有何区别?采用双字节字符集有何问题 双字节字符集(DBCS)编码是0-255,DBCS含有1字节代码与2字节代码,而Unicode是统一的16位系统,这样就允许表示 65536个字符.Unicode中的每个字符都是16位宽而不是8位宽.在Unicode中,

2017-2018-2 20155225《网络对抗技术》实验五 MSF基础应用

2017-2018-2 20155225<网络对抗技术>实验五 MSF基础应用 ms08_067 用search命令,搜索与ms08_067相关的模块,如图: 找到了对应的攻击模块exploit/windows/smb/ms08_067_netapi ,可知这是一个针对windows下,SMB服务的攻击模块. 服务器信息块(SMB)是一个网络文件共享协议,它允许应用程序和终端用户从远端的文件服务器访问文件资源. 描述里说,这是一个微软服务器服务相对路径堆栈损坏漏洞. 具体什么原理也不清楚,反正

Windows程序设计核心总结(打印机-2018.5.5)

本人大三学生,自学Windows程序设计有两三个月了,我是看鱼C工作室发布的Windows程序设计视频入门的,这视频集数虽然不是特别多,目前只有前面九章的视频内容,但小甲鱼老师讲解书本内容十分详细.入微,能让我们学习到不少知识.我开发Win32的环境是VS2013. 一.打印机工作机理 在Windows中使用打印机时,实际上启动了一系列模块之间复杂的交互过程,包括GDI32模块.打印机设备驱动程序模块.Windows后台打印处理程序和其他模块.应用程序想要开始使用打印机,首先调用CreateDC