1.画刷和画笔的应用:
新建一个空的Win32项目,手动添加一个源文件Source.cpp,键入以下代码:
#include<Windows.h>
#include<stdlib.h>
#include<string.h>
long WINAPI WndProc(HWND hWnd, UINT iMessage, UINT wParam, LONG lParam);
BOOL InitWindowsClass(HINSTANCE hInstance);
BOOL InitWindows(HINSTANCE hInstance, int nCmdShow);
//主函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
{
MSG Message;
if (!InitWindowsClass(hInstance))return FALSE; //窗口类初始化或者叫注册
if (!InitWindows(hInstance, nCmdShow))return FALSE; //初始化窗口
while (GetMessage(&Message, 0, 0, 0)) //消息循环
{
TranslateMessage(&Message);
DispatchMessage(&Message);
}
return Message.wParam;
}
long WINAPI WndProc(HWND hWnd, UINT iMessage, UINT wParam, LONG lParam)
{
HDC hDC; //定义设备环境句柄
HBRUSH hBrush; //定义画刷句柄
HPEN hPen; //定义画笔句柄
PAINTSTRUCT PtStr; //定义指向包含绘图信息的结构体变量
//定义一个POINT数组,包括6个点
POINT points[6] = { { 100, 212 }, { 70, 227 }, { 70, 250 }, { 130, 250 }, { 130, 227 }, { 100, 212 } };
switch (iMessage) //消息处理
{
case WM_PAINT: //处理绘图消息
hDC = BeginPaint(hWnd, &PtStr);
hPen = (HPEN)GetStockObject(NULL_BRUSH); //获取系统定义的空画笔
SelectObject(hDC, hPen); //选择画笔
hBrush = (HBRUSH)GetStockObject(BLACK_BRUSH); //获取系统定义的画刷
SelectObject(hDC, hBrush); //选择画刷
LineTo(hDC, 50, 50); //画线
DeleteObject(hPen); //删除画笔
hPen = CreatePen(PS_SOLID, 2, RGB(255, 0, 0)); //创建画笔
SelectObject(hDC, hPen); //选择画笔
//画一个三角形
LineTo(hDC, 150, 50);
LineTo(hDC, 100, 137);
LineTo(hDC, 50, 50);
Polyline(hDC, points, 6); //画一个五边形
Arc(hDC, 63, 137, 138, 212, 100, 137, 100, 137); //画一个圆
Pie(hDC, 213, 137, 288, 212, 240, 137, 260, 137); //画一个圆饼
Rectangle(hDC, 213, 212, 287, 250); //画一个长方形
RoundRect(hDC, 213, 100, 287, 137, 20, 20); //画一个圆角长方形
DeleteObject(hPen); //删除画笔
DeleteObject(hBrush); //删除画刷
EndPaint(hWnd, &PtStr); //结束绘图
return 0;
case WM_DESTROY: //结束应用程序
PostQuitMessage(0);
return 0;
default://其他消息处理程序
return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
}
//初始化窗口
BOOL InitWindows(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hWnd = CreateWindow(L"WinFill", L"填充示例", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if(!hWnd)
return FALSE;
ShowWindow(hWnd, nCmdShow); //显示窗口
UpdateWindow(hWnd);
return TRUE;
}
BOOL InitWindowsClass(HINSTANCE hInstance)
{
WNDCLASS WndClass;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hbrBackground = (HBRUSH)(GetStockObject(WHITE_BRUSH)); //窗口背景:白色
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hIcon = LoadIcon(NULL, L"END");
WndClass.hInstance = hInstance;
WndClass.lpfnWndProc = WndProc; //消息处理函数
WndClass.lpszClassName = L"WinFill";
WndClass.lpszMenuName = NULL;
WndClass.style = CS_HREDRAW | CS_VREDRAW;
return RegisterClass(&WndClass);
}
执行结果如图:
2.设置映像模式
映像模式定义了将逻辑单位转化为设备的度量单位以及设备的x方向和y方向。缺省的模式为TEXT绘图模式。
#include<Windows.h>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, UINT wParam, LONG lParam);
BOOL InitWindowsClass(HINSTANCE hInstance);
BOOL InitWindows(HINSTANCE hInstance, int nCmdShow);
int nMode; //记录映射模式
//主函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
{
MSG Message;
if (!InitWindowsClass(hInstance))return FALSE; //窗口类初始化或者叫注册
if (!InitWindows(hInstance, nCmdShow))return FALSE; //初始化窗口
while (GetMessage(&Message, 0, 0, 0)) //消息循环
{
TranslateMessage(&Message);
DispatchMessage(&Message);
}
return Message.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, UINT wParam, LONG lParam)
{
HDC hDC; //定义设备环境句柄
HBRUSH hB1,hB2; //定义画刷句柄
PAINTSTRUCT ps; //定义指向包含绘图信息的结构体变量
switch (iMessage) //消息处理
{
case WM_LBUTTONDOWN: //鼠标左键单击消息
nMode = MM_ISOTROPIC; //更改映射模式为MM_ISOTROPIC
InvalidateRect(hWnd, NULL, 1); //刷新用户区
break;
case WM_RBUTTONDOWN: //单击鼠标右键消息
nMode = MM_ANISOTROPIC; //更改显示模式为MM_ANISOTROPIC
InvalidateRect(hWnd, NULL, 1); //刷新用户区
break;
case WM_DESTROY: //结束应用程序
PostQuitMessage(0);
return 0;
case WM_PAINT:
hDC = BeginPaint(hWnd, &ps); //取得设备环境句柄
SetMapMode(hDC, nMode); //设置映射模式
SetWindowExtEx(hDC, 150, 150, NULL); //设置窗口区域
SetViewportExtEx(hDC, 150, 100, NULL); //设置视口区域
SetViewportOrgEx(hDC, 150, 60, NULL); //设置视口原点
hB1 = (HBRUSH)GetStockObject(WHITE_BRUSH); //定义白色画刷
hB2 = (HBRUSH)GetStockObject(BLACK_BRUSH); //定义黑色画刷
SelectObject(hDC, hB1); //将黑白刷选入设备环境
RoundRect(hDC, 0, 0, 150, 150, 30, 30); //绘制圆角矩形并填充
SelectObject(hDC, hB2); //更改当前画刷为黑色画刷
Ellipse(hDC, 0, 10, 150, 140); //绘制椭圆并填充
EndPaint(hWnd, &ps); //释放设备环境句柄
DeleteObject(hB1); //删除画刷句柄
DeleteObject(hB2);
break;
default://其他消息处理程序
return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
}
//初始化窗口
BOOL InitWindows(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hWnd = CreateWindow(L"映射模式", L"My_Map_Mode", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if(!hWnd)
return FALSE;
ShowWindow(hWnd, nCmdShow); //显示窗口
UpdateWindow(hWnd);
return TRUE;
}
BOOL InitWindowsClass(HINSTANCE hInstance)
{
WNDCLASS WndClass;
WndClass.cbClsExtra = 0;
WndClass.cbWndExtra = 0;
WndClass.hbrBackground = (HBRUSH)(GetStockObject(WHITE_BRUSH)); //窗口背景:白色
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
WndClass.hIcon = LoadIcon(NULL, L"END");
WndClass.hInstance = hInstance;
WndClass.lpfnWndProc = WndProc; //消息处理函数
WndClass.lpszClassName = L"映射模式";
WndClass.lpszMenuName = NULL;
WndClass.style = CS_HREDRAW | CS_VREDRAW;
return RegisterClass(&WndClass);
}
执行结果:
按下左键:
按下鼠标右键:
3.实现一个圆沿着正玄曲线移动的试验,并且每四分之一周期颜色发生变化。
#include<Windows.h>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<cmath>
#define Pi 3.1415926
long WINAPI WndProc(HWND hWnd, UINT iMessage, UINT wParam, LONG lParam); //消息处理函数声明.
double dfTheta = 0, dfRange = 100.0; //正弦曲线的角度变量.
long i = 0, j = 0;
long lCentreX = 0, lCentreY = 0, lRadious = (long)(0.2*dfRange);//定义圆心坐标和圆坐标.
POINT lpSin[100]; //定义正弦曲线的点坐标.
//主函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
{
MSG Message; //定义消息变量.
HWND hWnd; //定义窗口句柄.
WNDCLASS WndClass; //定义窗口类.
WndClass.cbClsExtra = 0; //无窗口类扩展.
WndClass.cbWndExtra = 0; //无窗口实例扩展.
WndClass.hbrBackground = (HBRUSH)(GetStockObject(WHITE_BRUSH));//背景为白色.
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); //窗口采用箭头光标.
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); //采用缺省图标.
WndClass.hInstance = hInstance; //当前应用程序句柄.
WndClass.lpfnWndProc = WndProc; //窗口处理函数.
WndClass.lpszClassName = L"SIN"; //窗口类名称.
WndClass.lpszMenuName = NULL; //无窗口菜单.
WndClass.style = 0; //窗口类型为缺省类型.
if (!RegisterClass(&WndClass)) //注册窗口.
{
MessageBeep(0);
return FALSE;
}
hWnd = CreateWindow(L"SIN", //窗口类名.
L"4_6", //标题名.
WS_OVERLAPPEDWINDOW, //带标题栏,最大和最小按钮的窗口.
CW_USEDEFAULT, //窗口左上角坐标.
0,
CW_USEDEFAULT, //采用缺省的宽度和高度.
0,
NULL, //无父窗口.
NULL, //无主菜单.
hInstance, //当前实例句柄.
NULL); //不要此参数.
ShowWindow(hWnd, nCmdShow); //显示窗口.
UpdateWindow(hWnd); //更新并绘制用户区.
for (int j = 0; j<100; j++) //生成正弦曲线的点坐标.
{
lpSin[j].x = (long)(j * 2 * Pi / 100 * 60);
lpSin[j].y = (long)(dfRange*sin(j * 2 * Pi / 100));
}
while (GetMessage(&Message, 0, 0, 0))
{
TranslateMessage(&Message); //消息循环.
DispatchMessage(&Message);
}
return Message.wParam;
}
long WINAPI WndProc(HWND hWnd, UINT iMessage, UINT wParam, LONG lParam) //消息处理函数.
{
HDC hDC; //定义设备环境句柄.
HBRUSH hBrush; //定义画刷句柄
HPEN hPen; //定义画笔句柄
PAINTSTRUCT PtStr; //定义包含绘图信息的结构体变量
switch (iMessage)
{
case WM_PAINT: //处理绘图消息.
hDC = BeginPaint(hWnd, &PtStr); //获得设备环境指针.
SetWindowOrgEx(hDC, -100, -100, NULL); //设置原点坐标为(-100,-100).
hPen = CreatePen(PS_DASH, 1, RGB(255, 0, 0)); //创新画笔.
SelectObject(hDC, hPen); //选入画笔.
Polyline(hDC, lpSin, 100); //绘制正弦曲线.
if (i <= 25) //第一个1/4周期.
{
hPen = CreatePen(PS_DASH, 1, RGB(255, 0, 0));//创新红笔.
hBrush = CreateHatchBrush(HS_BDIAGONAL, RGB(255, 0, 0));//创新红画刷.
lRadious = (long)(dfRange*0.2 + i % 25 * dfRange*0.4 / 25);//计算半径.
}
else if (i <= 50)//第二个1/4周期.
{
hPen = CreatePen(PS_DASH, 1, RGB(0, 255, 0));//创新绿笔.
hBrush = CreateHatchBrush(HS_DIAGCROSS, RGB(0, 255, 0));//创新绿刷.
lRadious = (long)(dfRange*0.2 + i % 25 * dfRange*0.4 / 25);//计算半径.
}
else if (i <= 75)//第三个周期.
{
hPen = CreatePen(PS_DASH, 1, RGB(0, 0, 255));//创新蓝笔
hBrush = CreateHatchBrush(HS_CROSS, RGB(0, 0, 255));//创新蓝刷.
lRadious = (long)(dfRange*0.2 + i % 25 * dfRange*0.4 / 25);//计算半径.
}
else//第四个周期.
{
hPen = CreatePen(PS_DASH, 1, RGB(255, 255, 0));//创新黄笔
hBrush = CreateHatchBrush(HS_VERTICAL, RGB(255, 255, 0));//创新黄刷.
lRadious = (long)(dfRange*0.2 + i % 25 * dfRange*0.4 / 25);//计算半径.
}
SelectObject(hDC, hBrush); //选入画刷.
SelectObject(hDC, hPen); //选入画笔.
lCentreX = lpSin[i].x; //圆心x坐标.
lCentreY = lpSin[i].y; //圆心y坐标.
Ellipse(hDC, lCentreX - lRadious, lCentreY - lRadious,lCentreX + lRadious, lCentreY + lRadious); //画圆,当椭圆的长短轴相等时为圆
i++;
DeleteObject(hPen); //删除画笔.
DeleteObject(hBrush); //删除画刷.
EndPaint(hWnd, &PtStr); //删除设备环境指针.
Sleep(100); //停0.1秒.
if (i<100) InvalidateRect(hWnd, NULL, 1); //刷新用户区.
return 0;
case WM_DESTROY: //关闭窗口.
PostQuitMessage(0);
return 0;
default:
return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
}
运行结果:
4.字符消息的响应,以及不同的映射模式下的图形显示
#include <windows.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int nMode = MM_TEXT; //初始绘图模式
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst,
LPSTR lpszCmdLine, int nCmdShow)
{
HWND hwnd;
MSG Msg;
WNDCLASS wndclass;
//char lpszClassName[] ="映射模式";
//char lpszTitle[] = "My_Map_Mode";
wndclass.style = 0;
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 = L"映射模式";
if (!RegisterClass(&wndclass))
{
MessageBeep(0);
return FALSE;
}
hwnd = CreateWindow(L"映射模式" ,//lpszClassName
L"My_Map_Mode",//lpszTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hwnd, nCmdShow); //显示窗口
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;
HPEN hPen;
switch (message){
case WM_CHAR: //字符消息
if (wParam == 'a' || wParam == 'A')
nMode = MM_ISOTROPIC;
else if (wParam == 'b' || wParam == 'B')
nMode = MM_ANISOTROPIC;
else if (wParam == 'c' || wParam == 'C')
nMode = MM_LOMETRIC;
else
;
InvalidateRect(hwnd, NULL, 1); //刷新用户区
break;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps); //取得设备环境句柄
SetMapMode(hdc, nMode); //设置映射模式
SetWindowExtEx(hdc, 15, 15, NULL); //设置窗口区域
SetViewportExtEx(hdc, 15, 10, NULL); //设置视口区域
SetViewportOrgEx(hdc, 120, 120, NULL); //设置视口原点
hPen = CreatePen(PS_SOLID, 2, RGB(255, 0, 0)); //创建红色画笔
SelectObject(hdc, hPen); //将画笔选入设备环境
//画坐标系,原点在视口原点
LineTo(hdc, 200, 0);
LineTo(hdc, 195, -5);
MoveToEx(hdc, 200, 0, NULL);
LineTo(hdc, 195, 5);
MoveToEx(hdc, 0, 0, NULL);
LineTo(hdc, 0, 200);
LineTo(hdc, -5, 195);
MoveToEx(hdc, 0, 200, NULL);
LineTo(hdc, 5, 195);
DeleteObject(hPen); //删除画笔
EndPaint(hwnd, &ps); //释放设备环境句柄
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
下图为原始状态、按下A/a键、按下B/b键、按下C/c键后的效果
清华大学MOOC课件