中年人学C语言Windows程序设计,11绘图函数:贝塞尔曲线

PolyBezie

函数功能:

PolyBezier 函数用于绘制一个或多个贝塞尔曲线。

贝赛尔曲线是一种非常优美的曲线,一条贝赛尔样条由4个定义点定义:两个端点和两个控制点。

API 函数原型:

注释:In 说明该参数是输入的。

BOOL PolyBezier(
  _In_  HDC hdc,
  _In_  const POINT *lppt,
  _In_  DWORD cPoints
);

参数解析:

参数 含义
hdc 指定设备环境句柄
lppt 1. 一个指向 POINT 结构的数组的指针,该数组包含端点和控制点的坐标
2. 顺序是起点、第一控制点、第二控制点和终点
cPoints 指明 lppt 指向的数组中点的个数

返回值:

  1. 如果函数调用成功,返回值是非 0;

  2. 如果函数调用失败,返回值是 0。

备注:

  1. PolyBezier 函数通过使用由 lppt 参数指定的端点和控制点绘制一条或多条三次贝塞尔曲线。

  2. 第一条贝塞尔曲线的四个点依次是:起点、第一控制点、第二控制点和终点;随后的每一条贝塞尔曲线则只需给出三个点,因为前一条贝塞尔曲线的终点会被当作后一条贝塞尔曲线的起点,以此类推。

  3. 绘制一系列相连的贝塞尔曲线时,仅当第一条贝塞尔曲线的第二个控点、第一条贝塞尔曲线的终点(也就是第二条贝塞尔曲线的起点)与第二条贝塞尔曲线的第一个控点是线性关系时(即三点共线时),曲线在连接点处才是平滑的。

【API档案】版权归鱼C工作室(www.fishc.com)所有,转载请注明来源。

绘制贝塞尔曲线

点击鼠标左键或者拖动,改变第一个控制点,
点击鼠标右键或者拖动,改变第二个控制点,

#define _CRT_SECURE_NO_WARNINGS 1
/* -------------------------------------------------------------------
                   中年人学C语言Windows程序设计
--------------------------------------------------------------------*/

#include <windows.h>
#include<strsafe.h>
//#include"sysmets.h"
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
//主函数
// 四个参数:
//hInstance : 程序当前实例的句柄(handle to current instance),以后随时可以用GetModuleHandle(0)来获得
//hPrevInstance : 前一个实例的句柄(handle to previous instance),在Win32中,每一个进程都有一个独立的4G地址空间,从0到2G属于进程私有,对其他进程来说是不可见的。所以,在Win32中,hPrevInstance总是为NULL。
//szCmdLine : 指向以 / 0结尾的命令行,不包括EXE本身的文件名(pointer to command line),以后随时可以用GetCommandLine()来获取完整的命令行。
//iCmdShow : 指明应该以什么方式显示主窗口(show state of window)。

{
    static TCHAR szAppName[] = TEXT("MyWindows");
    HWND hwnd;//句柄
    MSG msg;//消息
    WNDCLASS wndclass;//定义窗口类结构
    //HBRUSH hCulorBrush = CreateSolidBrush(RGB(200, 200, 200));//设定背景颜色

    //结构成员:
    wndclass.style = CS_HREDRAW | CS_VREDRAW; //窗口类型
    wndclass.lpfnWndProc = WndProc;  //窗口过程(必须是回调函数)
    wndclass.cbClsExtra = 0;//预留的额外空间,一般为0
    wndclass.cbWndExtra = 0;//预留的额外空间,一般为0
    wndclass.hInstance = hInstance;//应用程序的实例句柄
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);//为所有基于该窗口类的窗口设定一个图标
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);//为所有基于该窗口类的窗口设定一个鼠标指针
    //wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);//指定窗口背景色
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//指定窗口背景色
    wndclass.lpszMenuName = NULL; //指定窗口菜单
    wndclass.lpszClassName = szAppName; //指定窗口类名

    //注册窗口类
    if (!RegisterClass(&wndclass))
        /*  RegisterClass:注册在随后调用CreateWindow函数和CreateWindowEx函数中使用的窗口类。
          参数为lpWndClass,指向一个WNDCLASS结构的指针
          返回值:ATOM的宏定义
          typedef WORD ATOM;
          typedef unsigned short WORD;
          关于RegisterClassEx:参数lpwcx指向一个WNDCLASSEX结构的指针如果函数成功,返回这个窗口类型的标识号;
          如果函数失败,返回值为0。若想获得更多错误信息,请调用GetLastError函数。*/
    {
        MessageBox(NULL, TEXT("这个程序需要在Windows系统执行!"), szAppName, MB_ICONERROR);
        return 0;
    }
    //实例化创建窗口
    hwnd = CreateWindow(szAppName,// 窗口类名称
        TEXT("中年人学C语言Windows程序设计"),// 窗口标题
        WS_OVERLAPPEDWINDOW | WS_VSCROLL,// 窗口风格,或称窗口格式
        CW_USEDEFAULT,// 初始 x 坐标
        CW_USEDEFAULT, // 初始 y 坐标
        CW_USEDEFAULT,// 初始 x 方向尺寸
        CW_USEDEFAULT,// 初始 y 方向尺寸
        NULL,// 父窗口句柄
        NULL,// 窗口菜单句柄
        hInstance,// 程序实例句柄
        NULL);// 创建参数

    /*_In_说明该参数是输入的,_opt_说明该参数是可选参数
        函数成功返回窗口句柄,否则返回NULL*/

        //显示窗口
    ShowWindow(hwnd, iCmdShow);
    /* 第一次调用时应使用WinMain的参数nCmdShow作为参数
         如果窗口之前可见,则返回非0否则返回0*/

         //更新窗口
    UpdateWindow(hwnd);
    /* 绕过消息队列直接向窗口过程发送WM_PAINT消息
         函数调用成功返回非0*/

         //消息循环
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    /*作用:从当前线程的消息队列里取出一个消息并放入MSG结构中,不能获得其他线程的消息
        若消息队列为空,函数会一直等待到有消息到来才有返回值
        返回值:
        函数出现错误则返回 - 1,
        获得WM_QUIT消息返回0
        否则返回非0*/
    return msg.wParam;
}


LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    回调函数
    参数:
    hwnd : 窗口句柄
    message : 消息ID
    wParam和lParam:消息参数
        //int i;
        //size_t j;
    HDC hdc;//定义设备环境句柄  
    static TCHAR  szBuffer[128];
    //TEXTMETRIC tm;
   // SCROLLINFO si;
    PAINTSTRUCT ps;
    //RECT rect;
    size_t iStrLength;
    static int cxChar, cyChar, cxClient, cyClient;
    static POINT apt[4];
    switch (message)
    {
        case WM_SIZE://窗体大小改变
            cxClient = LOWORD(lParam);//当前x像素
            cyClient = HIWORD(lParam);//当前y像素
            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 = cyClient *3/ 4;
            apt[3].x = cxClient *3/ 4;
            apt[3].y= cyClient / 2;
           
            hdc = GetDC(hWnd);
            //GetClientRect(hwnd, &rect);
            
            StringCchPrintf(szBuffer, 128, TEXT("当前客户区的分辨率:%d * %d px"), cxClient, cyClient);
            StringCchLength(szBuffer, 128, &iStrLength);
            SetTextAlign(hdc, TA_CENTER | TA_TOP);
            TextOut(hdc, cxClient / 2, 0, szBuffer, iStrLength);
            ReleaseDC(hWnd, hdc);
            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));
                PolyBezier(hdc, apt,4);
                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));
                PolyBezier(hdc, apt, 4);
                ReleaseDC(hWnd, hdc);
            }
            return 0;

        case WM_PAINT://窗口绘画:点
        {
            //int x, xLast;
            hdc = BeginPaint(hWnd, &ps);//函数为指定窗口进行绘画作准备,并用将和绘画有关的信息填充到一个 PAINTSTRUCT 结构中。
            PolyBezier(hdc, apt, 4);
            EndPaint(hWnd, &ps);
            return 0;
        }
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
    return 0;
}

实例效果

在这里插入图片描述
拖动鼠标左键,改变曲线在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值