Windows画图

1 图形绘制
  
    1.1 图形绘制的方式
      获取到画图句柄-设备描写叙述表(DC),使用对应的画图的API,在设备上绘制图形.
      
    1.2 颜色
      R\G\B三色, 每种颜色8位, 共24位颜色.
      32位颜色: 颜色数量24位颜色, 多出来的8位表示灰度.
      16位: 颜色数量2的16次方.
      
      Win32下,颜色的定义 COLORREF(DWORD), RGB宏定义颜色
       COLORREF nColor = RGB( 0,  0,  0 );
        COLORREF nColor = RGB( 255,255,255 );
        COLORREF nColor = RGB( 255,0,  0 );
      从一个颜色中获取RGB三色:
        int nBlue = GetBValue( nColor );
        int nRed  = GetRValue( nColor );
        int nGreen= GetGValue( nColor );

以下是详细的代码

// winDraw.cpp.cpp : 定义应用程序的入口点。

//

#include "stdafx.h"
#include "winDraw.cpp.h"
#include <stdio.h> #define MAX_LOADSTRING 100 // 全局变量:
HINSTANCE hInst; // 当前实例
TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗体类名
int g_nDrawType = 0; //画图命令
COLORREF g_nPenColor = RGB( 0, 0, 0 ); //默认画笔颜色
int g_nPenStyle = PS_SOLID; //默认画笔类型
int g_nPenWdith = 1; //默认画笔宽度
COLORREF g_nBrushColor = RGB( 255, 255, 255 ); //默认画笔颜色 // 此代码模块中包括的函数的前向声明:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine); // TODO: 在此放置代码。
MSG msg;
HACCEL hAccelTable; // 初始化全局字符串
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_WINDRAWCPP, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance); // 运行应用程序初始化:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
} hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDRAWCPP)); // 主消息循环:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
} return (int) msg.wParam;
} //
// 函数: MyRegisterClass()
//
// 目的: 注冊窗体类。
//
// 凝视:
//
// 仅当希望
// 此代码与加入到 Windows 95 中的“RegisterClassEx”
// 函数之前的 Win32 系统兼容时,才须要此函数及其使用方法。调用此函数十分重要,
// 这样应用程序就能够获得关联的
// “格式正确的”小图标。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WINDRAWCPP));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
/*载入菜单项 也能够在创建windows的时候载入菜单*/
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_WINDRAWCPP);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassEx(&wcex);
} //
// 函数: InitInstance(HINSTANCE, int)
//
// 目的: 保存实例句柄并创建主窗体
//
// 凝视:
//
// 在此函数中。我们在全局变量中保存实例句柄并
// 创建和显示主程序窗体。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd; hInst = hInstance; // 将实例句柄存储在全局变量中 hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd)
{
return FALSE;
} ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd); return TRUE;
} void OnCommand(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent; //命令ID
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 分析菜单选择:
switch (wmId){
case ID_32774://绘制点
case ID_32775:
case ID_32772:
case ID_32776://绘制圆弧
case ID_32777://绘制折线
case ID_32780://绘制曲线
case ID_32781://绘制多样式曲线
case ID_32782://绘制矩形
case ID_32783://绘制圆
case ID_32785://绘制饼
case ID_32786://绘制炫
case ID_32787://绘制多边形 //保存图形绘制类型
g_nDrawType = wmId;
InvalidateRect(hWnd,NULL,TRUE);//刷新窗体。会触发WM_PAINT
break; case ID_32790://绘制画笔红色 //保存图形绘制类型
g_nPenColor = RGB(255,0,0);
InvalidateRect(hWnd,NULL,TRUE);//刷新窗体。会触发WM_PAINT
break; case ID_32792://画笔样式
g_nPenStyle = PS_SOLID;
InvalidateRect(hWnd,NULL,TRUE);//刷新窗体,会触发WM_PAINT
break;
case ID_32794://画笔样式
g_nPenStyle = PS_DASH;
InvalidateRect(hWnd,NULL,TRUE);//刷新窗体,会触发WM_PAINT
break;
case ID_32796://画笔样式
g_nPenWdith = 1;
InvalidateRect(hWnd,NULL,TRUE);//刷新窗体,会触发WM_PAINT
break;
case ID_32797://画笔样式
g_nPenWdith = 5;
InvalidateRect(hWnd,NULL,TRUE);//刷新窗体。会触发WM_PAINT
break;
case ID_32799://画刷颜色
g_nBrushColor = RGB(255,0,0);
InvalidateRect(hWnd,NULL,TRUE);//刷新窗体,会触发WM_PAINT
break;
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
DefWindowProc(hWnd, message, wParam, lParam);
break;
}
} //点的绘制
void DrawPixel(HDC hDC)
{
COLORREF nColor = RGB(255,0,0);
/*
*绘制: COLORREF SetPixel(
* HDC hdc, //DC句柄
* int X, //x坐标
* int Y, //y坐标
* COLORREF crColor ); // 点的颜色
*/ SetPixel(hDC,100,100,nColor);
} void GetPixelColor(HDC hDC)
{
DrawPixel(hDC);
/*获取点的颜色
*获取: COLORREF GetPixel(
* HDC hdc, //DC句柄
* int XPos, //x坐标
* int nYPos ); //y坐标
* 返回指定坐标位置的点的颜色
*/
COLORREF nColor =
GetPixel( hDC, 100, 100 );
//获取颜色的三色值
int nRed = GetRValue( nColor );
int nGreen = GetGValue( nColor );
int nBlue = GetBValue( nColor ); CHAR szText[260] = { 0 };
sprintf_s( szText, "COLOR=%08X, RED=%d GREEN=%d BLUE=%d",
nColor, nRed, nGreen, nBlue );
MessageBox( NULL, szText, "GetPixelColor", MB_OK );
} //绘制直线
void DrawLine( HDC hDC )
{
MoveToEx( hDC, 0, 0, NULL );
LineTo( hDC, 500, 500 );
MoveToEx( hDC, 500, 0, NULL );
LineTo( hDC, 0, 500 );
} //绘制圆弧
void DrawArc(HDC hDC )
{
//逆时针的方式
SetArcDirection( hDC, AD_COUNTERCLOCKWISE );
//通过外切矩形和分割线
/*BOOL Arc( HDC hdc,
* int nLeftRect, // 外切矩形的坐标
* int nTopRect,//外切矩形的坐标
* int nRightRect,//外切矩形的坐标
* int nBottomRect,//外切矩形的坐标
* int nXStartArc,//起始分割半径的X坐标
* int nYStartArc,//起始分割半径的Y坐标
* int nXEndArc, //终止分割半径的X坐标
* int nYEndArc ); //终止分割半径的X坐标
* 能够使用SetArcDirection函数,设置Arc函数
* 分割方向:顺时针和逆时针
*/
Arc( hDC, 400, 200, 500, 300,500, 200, 400, 200); //顺时针的方式
SetArcDirection( hDC, AD_CLOCKWISE );
Arc( hDC, 500, 200, 600, 300,600, 200, 500, 200); /*没有这个话会出现0,0 到200,200 的一条直线*/
MoveToEx( hDC, 200, 200, NULL );
/* 还有一种绘制圆的方法。
*BOOL AngleArc(
* HDC hdc, // handle to device context
* int X, //圆心的X坐标
* int Y, //圆心的Y坐标
* DWORD dwRadius,//圆的半径
* FLOAT eStartAngle,//開始角度
* FLOAT eSweepAngle );//夹角
*/
AngleArc(hDC,200,200,100,60,120);
LineTo( hDC, 200, 200 );
} //绘制折线
void DrawPolyLine(HDC hDC)
{
POINT ptPolyLine[7] = { 0 };
ptPolyLine[0].x = 100;
ptPolyLine[0].y = 100;
ptPolyLine[1].x = 200;
ptPolyLine[1].y = 100;
ptPolyLine[2].x = 200;
ptPolyLine[2].y = 200;
ptPolyLine[3].x = 300;
ptPolyLine[3].y = 200;
ptPolyLine[4].x = 300;
ptPolyLine[4].y = 300;
ptPolyLine[5].x = 400;
ptPolyLine[5].y = 300;
ptPolyLine[6].x = 400;
ptPolyLine[6].y = 400; /*
*BOOL Polyline(
* HDC hdc, //DC句柄
* CONST POINT *lppt,//Polyline顶点的坐标数组
* int cPoints ); //顶点数组的长度
* PolylineTo 与Polyline相似, 仅仅是在绘制Polyline前
* ,从当前点使用LineTo绘制直线到Polyline的第一个顶点
*/
Polyline( hDC, ptPolyLine, 7 );
//PolylineTo( hDC, ptPolyLine, 3 ); /*
*绘制多组折线 PolyPolyline
* BOOL PolyPolyline( HDC hdc,
* CONST POINT *lppt,//全部点的数组
* CONST DWORD *lpdwPolyPoints,//每组点的数量
* DWORD cCount );//分组的数量
*/ //DWORD nGroup[] = { 4, 3 };
//PolyPolyline( hDC, ptPolyLine,nGroup, 2 );
} void DrawBizer( HDC hDC )
{
POINT ptBizer[7] = { 0 };
ptBizer[0].x = 100; //端点
ptBizer[0].y = 100; //
ptBizer[1].x = 100; //控制点
ptBizer[1].y = 50; //
ptBizer[2].x = 300; //控制点
ptBizer[2].y = 150; //
ptBizer[3].x = 300; //端点
ptBizer[3].y = 100; //
ptBizer[4].x = 300; //控制点
ptBizer[4].y = 400;
ptBizer[5].x = 400; //控制点
ptBizer[5].y = 200;
ptBizer[6].x = 500; //端点
ptBizer[6].y = 300; /*
Bezier曲线
BOOL PolyBezier(HDC hdc,
CONST POINT *lppt,//点数组,最少4个点
DWORD cPoints );//点的数量
4个点: 1和4是端点,2.3点是控制点
7个点: 1.4.7是端点,其余是控制点
*/
PolyBezier( hDC, ptBizer, 7 );
MoveToEx( hDC, ptBizer[0].x, ptBizer[0].y, NULL );
LineTo( hDC, ptBizer[1].x, ptBizer[1].y );
MoveToEx( hDC, ptBizer[3].x, ptBizer[3].y, NULL );
LineTo( hDC, ptBizer[2].x, ptBizer[2].y );
} //多样式线
void DrawPolyDraw( HDC hDC )
{
POINT ptDraw[4] = { 0 };
ptDraw[0].x = 100;
ptDraw[0].y = 100;
ptDraw[1].x = 200;
ptDraw[1].y = 100;
ptDraw[2].x = 200;
ptDraw[2].y = 200;
ptDraw[3].x = 300;
ptDraw[3].y = 200; BYTE ptType[4] = {0};
ptType[0] = PT_MOVETO;
ptType[1] = PT_LINETO;
ptType[2] = PT_LINETO;
ptType[3] = PT_LINETO;
/*
* BOOL PolyDraw( HDC hdc,
* CONST POINT *lppt,//各个点的数组
* CONST BYTE *lpbTypes, //从某点到下一点的绘制方式 pointer to line and curve identifiers
* int cCount); //点的数量
*
* lpbTypes - PT_MOVETO 移动到该点
* PT_LINETO 绘直线
* PT_BIZERTO Biezer曲线
*/
PolyDraw( hDC, ptDraw, ptType, 4 );
} void DrawRect( HDC hDC )
{ //矩形
Rectangle( hDC, 100, 100, 200, 200 );
//带圆角矩形
/*
带圆角的矩形
BOOL RoundRect( HDC hdc,
int nLeftRect, //左上X坐标
int nTopRect, //左上Y坐标
int nRightRect,//右下X坐标
int nBottomRect, //右下Y坐标
int nWidth, //生成圆角的椭圆的宽度
int nHeight );//生成圆角的椭圆的高度
*/
RoundRect( hDC, 300, 100, 400, 200, 50, 50 );
} void DrawEllipse( HDC hDC )
{ //圆
/*
BOOL Ellipse( HDC hdc,
int nLeftRect, //外切矩形左上X坐标
int nTopRect,//外切矩形左上Y坐标
int nRightRect, //外切矩形右下X坐标
int nBottomRect); //外切矩形右下Y坐标
*/
Ellipse( hDC, 100, 100, 200, 200 );
//椭圆
Ellipse( hDC, 300, 100, 500, 200 );
} void DrawPie( HDC hDC )
{
Pie( hDC, 100, 100, 500, 400,
500, 100, 100, 100 );
} void DrawChord( HDC hDC )
{
/* 弦
* BOOL Chord( HDC hdc,
* int nLeftRect, //外切矩形左上X坐标
* int nTopRect, //外切矩形左上Y坐标
* int nRightRect, //外切矩形右下X坐标
* int nBottomRect, //外切矩形右下Y坐标
* int nXRadial1,//分割起始半径X坐标
* int nYRadial1,//分割起始半径Y坐标
* int nXRadial2,//分割终止半径X坐标
* int nYRadial2 );//分割终止半径Y坐标
*/
Chord( hDC, 100, 100, 500, 400,
500, 100, 100, 100 );
} void DrawPloygon( HDC hDC )
{
POINT ptPloygon[4] = { 0 };
ptPloygon[0].x = 100;
ptPloygon[0].y = 100;
ptPloygon[1].x = 200;
ptPloygon[1].y = 100;
ptPloygon[3].x = 600;
ptPloygon[3].y = 300;
ptPloygon[2].x = 500;
ptPloygon[2].y = 300;
/* 多边形
* BOOL Polygon( HDC hdc,
* CONST POINT *lpPoints, //多边形的顶点
* int nCount ); //顶点的数量
* PolyPolygon 能够绘制多组多边形
*/
Polygon( hDC, ptPloygon, 4 );
} void OnPaint(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps; hDC = BeginPaint(hWnd,&ps); /*创建画笔
* HPEN CreatePen(
* int fnPenStyle, //画笔的样式
* int nWidth, //画笔的宽度
* COLORREF crColor);//画笔的颜色
*/
HPEN hPen = CreatePen(g_nPenStyle,g_nPenWdith,g_nPenColor); /*设置画笔到当前DC
* HGDIOBJ SelectObject(
* HDC hdc, // 当前DC的句柄
* HGDIOBJ hgdiobj );//要使用的GDI对象句柄
* 返回当前DC原来使用的同类型的GDI对象句柄。 */
HPEN hOldPen = (HPEN)SelectObject(hDC,hPen); //创建画刷,画刷仅仅对填充物有效果。圆,多边形,矩形等
HBRUSH hBrush = CreateSolidBrush(g_nBrushColor); //设置画刷到当前DC
HBRUSH hOldBrush = (HBRUSH)SelectObject(hDC,hBrush);
// 依据不同的绘制类型,来做不同的指令
switch(g_nDrawType){
case ID_32774://绘制点
DrawPixel(hDC);
break;
case ID_32775://获取点颜色
GetPixelColor(hDC);
break;
case ID_32772://绘制直线
DrawLine(hDC);
break;
case ID_32776://绘制圆弧
DrawArc(hDC);
break;
case ID_32777://绘制折线
DrawPolyLine(hDC);
break;
case ID_32780://绘制曲线
DrawBizer( hDC );
break;
case ID_32781://绘制多样式曲线
DrawPolyDraw( hDC );
break;
case ID_32782://绘制矩形
DrawRect( hDC );
break;
case ID_32783://绘制圆和椭圆
DrawEllipse( hDC );
break;
case ID_32785://绘制饼丝
DrawPie( hDC );
break;
case ID_32786://绘制炫
DrawChord( hDC );
break;
case ID_32787://绘制多边形
DrawPloygon( hDC );
break;
default: break;
} //取出画刷
SelectObject( hDC, hOldBrush );
//删除画刷
DeleteObject( hBrush );
//取出画笔。旧画笔放进去,新画笔就会释放
SelectObject( hDC, hOldPen );
//销毁画笔
DeleteObject( hPen );
EndPaint(hWnd,&ps);
} //
// 函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 目的: 处理主窗体的消息。
//
// WM_COMMAND - 处理应用程序菜单
// WM_PAINT - 绘制主窗体
// WM_DESTROY - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{ switch (message)
{
case WM_COMMAND:/*菜单的信息处理*/ OnCommand(hWnd,message,wParam,lParam); #if 0
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
#endif
break;
case WM_PAINT:
/*画图指令*/
OnPaint(hWnd, message, wParam, lParam);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
} // “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE; case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}

05-11 13:48