C#使用GDI对一个矩形进行任意角度旋转

news2024/11/27 14:45:42

C#对一个矩形进行旋转GDI绘图,可以指定任意角度进行旋转

我们可以认为一张图片Image,本质就是一个矩形Rectangle,旋转矩形也就是旋转图片

在画图密封类 System.Drawing.Graphics中,

矩形旋转的两个关键方法

//设置旋转的中心点

public void TranslateTransform(float dx, float dy);

//旋转指定的角度【单位°】:旋转角度 从 X+ 到 Y+之间的旋转角度认为是正数

public void RotateTransform(float angle);

矩形旋转WindowsForms应用程序

新建窗体应用程序RotatedRectangleDemo,将默认的Form1重命名为FormRotatedRectangle

窗体FormRotatedRectangle设计如图:

窗体设计FormRotatedRectangle设计器代码如下:

文件FormRotatedRectangle.Designer.cs


namespace RotatedRectangleDemo
{
    partial class FormRotatedRectangle
    {
        /// <summary>
        /// 必需的设计器变量。
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// 清理所有正在使用的资源。
        /// </summary>
        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows 窗体设计器生成的代码

        /// <summary>
        /// 设计器支持所需的方法 - 不要修改
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {
            this.btnRotate = new System.Windows.Forms.Button();
            this.label1 = new System.Windows.Forms.Label();
            this.numRotate = new System.Windows.Forms.NumericUpDown();
            ((System.ComponentModel.ISupportInitialize)(this.numRotate)).BeginInit();
            this.SuspendLayout();
            // 
            // btnRotate
            // 
            this.btnRotate.Font = new System.Drawing.Font("宋体", 13F);
            this.btnRotate.Location = new System.Drawing.Point(271, 7);
            this.btnRotate.Name = "btnRotate";
            this.btnRotate.Size = new System.Drawing.Size(75, 33);
            this.btnRotate.TabIndex = 0;
            this.btnRotate.Text = "旋转";
            this.btnRotate.UseVisualStyleBackColor = true;
            this.btnRotate.Click += new System.EventHandler(this.btnRotate_Click);
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(25, 20);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(119, 12);
            this.label1.TabIndex = 1;
            this.label1.Text = "旋转角度(0°~360°)";
            // 
            // numRotate
            // 
            this.numRotate.DecimalPlaces = 2;
            this.numRotate.Location = new System.Drawing.Point(150, 16);
            this.numRotate.Maximum = new decimal(new int[] {
            360,
            0,
            0,
            0});
            this.numRotate.Name = "numRotate";
            this.numRotate.Size = new System.Drawing.Size(97, 21);
            this.numRotate.TabIndex = 2;
            this.numRotate.Value = new decimal(new int[] {
            30,
            0,
            0,
            0});
            // 
            // FormRotatedRectangle
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(945, 508);
            this.Controls.Add(this.numRotate);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.btnRotate);
            this.Name = "FormRotatedRectangle";
            this.Text = "GDI旋转示例:矩形旋转任意角度";
            ((System.ComponentModel.ISupportInitialize)(this.numRotate)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.Button btnRotate;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.NumericUpDown numRotate;
    }
}

旋转矩形示例代码如下:

文件FormRotatedRectangle.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace RotatedRectangleDemo
{
    public partial class FormRotatedRectangle : Form
    {
        public FormRotatedRectangle()
        {
            InitializeComponent();
            /* 定义了一个名为FormRotatedRectangle的窗体类,
             * 它覆盖(override)了OnPaint方法来绘制旋转的矩形。
             * 在OnPaint方法中,我们首先设置矩形的位置和大小,然后保存图形状态,
             * 接着设置旋转变换的中心点,通过RotateTransform方法设置旋转角度,并绘制旋转后的矩形,最后恢复图形状态。
             * 程序运行时,会显示一个旋转了30度的矩形。
            */
        }

        /// <summary>
        /// 窗体重绘事件
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            Graphics g = e.Graphics;

            // 设置矩形的位置和大小
            Rectangle rect = new Rectangle(100, 100, 200, 100);

            RotateRectangle(g, rect, (float)numRotate.Value);
        }

        /// <summary>
        /// 将初始矩形旋转指定的角度数
        /// </summary>
        /// <param name="g">窗体画图对象</param>
        /// <param name="rect">初始矩形对象(x,y,width,height)</param>
        /// <param name="rotateAngle">旋转角度,单位°</param>
        private void RotateRectangle(Graphics g, Rectangle rect, float rotateAngle) 
        {
            // 保存原始状态
            GraphicsState state = g.Save();

            // 设置旋转的中心点为矩形的中心
            g.TranslateTransform(rect.X + rect.Width / 2, rect.Y + rect.Height / 2);

            // 旋转矩形:旋转角度 从 X+ 到 Y+之间的旋转角度认为是正数
            g.RotateTransform(rotateAngle);

            // 恢复变换的中心点
            g.TranslateTransform(-(rect.X + rect.Width / 2), -(rect.Y + rect.Height / 2));

            // 绘制矩形
            g.DrawRectangle(Pens.Black, rect);

            // 恢复图形状态
            g.Restore(state);
        }

        private void btnRotate_Click(object sender, EventArgs e)
        {
            this.Invalidate();//引起触发重绘OnPaint事件
        }
    }
}

程序运行如图:

旋转45°【π/4】

旋转90°【π/2】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1802924.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL-相关日志

官方文档 1、MySQL支持的日志 MySQL有不同类型日志文件&#xff0c;用来存储不同类型的日志&#xff0c;分别为 二进制日志、错误日志、通用查询日志、慢查询日志、中继日志、数据定义语句日志 慢查询日志&#xff1a;记录所有执行时间超过 long_query_time的所有查询&#xf…

单元测试覆盖率

什么是单元测试覆盖率 关于其定义&#xff0c;先来看一下维基百科上的一段描述&#xff1a; 代码覆盖&#xff08;Code coverage&#xff09;是软件测试中的一种度量&#xff0c;描述程序中源代码被测试的比例和程度&#xff0c;所得比例称为代码覆盖率。 简单来理解&#xff…

【微信小程序】事件绑定和事件对象

文章目录 1.什么是事件绑定2.button组件3.事件绑定4.input组件 1.什么是事件绑定 小程序中绑定事件与在网页开发中绑定事件几乎一致&#xff0c;只不过在小程序不能通过on的方式绑定事件&#xff0c;也没有click等事件&#xff0c;小程序中 绑定事件使用bind方法&#xff0c;c…

反转链表 (oj题)

一、题目链接 https://leetcode.cn/problems/reverse-linked-list/submissions/538124207 二、题目思路 1.定义三个指针&#xff0c;p1先指向NULL p2指向头结点 p3指向第二个结点 2.p2的next指向p1。然后移动指针&#xff0c;p1来到p2的位置&#xff0c;p2来到p3的位置&…

双列集合基础知识

package exercise;import java.util.HashMap; import java.util.Map;public class Demo1 {public static void main(String[] args) {Map<String, String> map new HashMap<>();//在添加数据的时候&#xff0c;如果键不存在&#xff0c;那么直接把键值对对象添加到…

小主机折腾记25

10.买了惠普光驱&#xff0c;想给880g5twr安装上&#xff0c;结果发现卡扣不对 880g5twr的卡扣更长一些&#xff0c;比光驱本身长一些&#xff0c;各位如果想买的注意擦亮眼睛&#xff0c;看看卡扣跟你的主机一致与否 后续在闲鱼上买了个卡扣&#xff0c;加邮费12块钱…… 1…

手搓文件格式转换

最初目标&#xff1a; 自己搞一个免费的pdf文件转换 根据现有的开源jar 项目实现思路&#xff1a; 1. 项目原因a. 我想转换文件b. wps 文件转换 2. 最初的状态a. jar运行的b. main,输入文件路径c. 一定的编程能力的人才能得 3. 开始构思项目a. 网页版本b. 想着大家一起用 4. …

Go 编程风格指南 - 最佳实践

Go 编程风格指南 - 最佳实践 原文&#xff1a;https://google.github.io/styleguide/go 概述 | 风格指南 | 风格决策 | 最佳实践 注意&#xff1a; 本文是 Google Go 风格 系列文档的一部分。本文档是 规范性(normative) 但不是强制规范(canonical)&#xff0c;并且从属于Goo…

2003NOIP普及组真题 3. 数字游戏

线上OJ 地址&#xff1a; 【03NOIP普及组】数字游戏 此题考察的是 区间DP 前缀和 核心思想&#xff1a; 1、这道题主要考查了动态规划的思想。通过分析题目&#xff0c;可以发现需要 枚举环上所有划分为m组 的不同方案&#xff0c;来求得最大或最小值。属于 环上动态规划 问…

IEDA 默认集成依赖概述

IEDA 默认集成依赖概述 目录概述需求&#xff1a; 设计思路实现思路分析 1.Developer Tools:GraalVM Native supportGraphQL DGs Code GenerationSpring Boot DevToolsLombokSpring Configuration ProcessorDocker Compose supportSpring Modulith 2.WebWebSpring WebSpring Re…

安卓约束性布局学习

据说这个布局是为了解决各种布局过度前套导致代码复杂的问题的。 我想按照自己想实现的各种效果来逐步学习&#xff0c;那么直接拿微信主页来练手&#xff0c;用约束性布局实现微信首页吧。 先上图 先实现顶部搜索框加号按钮 先实现 在布局中添加一个组件&#xff0c;然后摆放…

java web:springboot mysql开发的一套家政预约上门服务系统源码:家政上门服务系统的运行流程

java web&#xff1a;springboot mysql开发的一套家政预约上门服务系统源码&#xff1a;家政上门服务系统的运行流程 家政上门服务系统的优势 服务质量更稳定&#xff1a;由专业的家政人员提供服务&#xff0c;经过严格的培训和筛选。 价格更透明&#xff1a;采用套餐式收费&…

java的核心机制:JVM

JVM&#xff08;java virtual machine&#xff0c;java虚拟机&#xff09;&#xff1a;是一个虚拟的计算机&#xff0c;是java程序的运行环境。JVM具有指令集并使用不同的存储区域&#xff0c;负责执行指令&#xff0c;管理数据、内存、寄存器。 JVM功能1&#xff1a;实现java程…

以sqlilabs靶场为例,讲解SQL注入攻击原理【54-65关】

【Less-54】 与前面的题目不同是&#xff0c;这里只能提交10次&#xff0c;一旦提交超过十次&#xff0c;数据会重新刷新&#xff0c;所有的步骤需要重来一次。 解题步骤&#xff1a; 根据测试&#xff0c;使用的是单引号闭合。 # 判断字段的数量 ?id1 order by 3 -- aaa# …

力扣 有效的括号 栈

Problem: 20. 有效的括号 文章目录 思路复杂度&#x1f49d; Code 思路 &#x1f468;‍&#x1f3eb; 参考地址 复杂度 时间复杂度: O ( n ) O(n) O(n) 空间复杂度: O ( n ) O(n) O(n) &#x1f49d; Code class Solution {static Map<Character, Character> m…

香橙派 Orange AIpro 测评记录视频硬件解码

香橙派 Orange AIpro 测评记录视频硬件解码 香橙派官网&#xff1a;http://www.orangepi.cn/ 收到了一块Orange Pi AIpro开发板&#xff0c;记录一下我的测评~测评简介如下&#xff1a;1.连接网络2.安装流媒体进行硬件解码测试3.安装IO测试 简介 Orange Pi AI Pro 是香橙派联合…

i.MX8MP平台开发分享(RDC软件配置篇)

Uboot中已经将RDC的配置写入到了OCRAM中&#xff0c;NXP在ATF中预设了SIP服务&#xff0c;SIP服务下有厂商自定义的smc命令ID。例如下面的DDR、GPC、SRC和HAB的smc回调函数。 在SRC中断处理函数中&#xff0c;对于SRC_M4_START指令&#xff0c;先读取OCRAM中的配置&#xff0c;…

web-上传项目文件夹到Git远程仓库

Git初识 概念&#xff1a;一个免费开源&#xff0c;分布式的代码版本控制系统&#xff0c;帮助开发团队维护代码 作用&#xff1a;记录代码内容&#xff0c;切换代码版本&#xff0c;多人开发时高效合并代码内容 检验成功 打开bash终端&#xff08;git专用&#xff09;命令…

中缀表达式和前缀后缀

在中缀表达式中&#xff0c;操作数可能与两个操作符相结合 但是&#xff0c;想要不带括号无歧义&#xff0c;且不需要考虑运算符优先级和结合性 所以考虑 前缀表达式&#xff0c;波兰表达式 后缀表达式 逆波兰表达式 对于人来说&#xff0c;中缀表达式是最容易读懂的。但是对于…

数据库存储过程和锁机制

存储过程 存储过程是事先经过编译并存储在数据库中的一段SQL语句的集合,调用存储过程可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是有好处的&#xff0c;存储过程思想上很简单,就是数据库SQL语言层面的代码封装与有重用 …