如何正确获取 WinForms Button 控件来绘制自定义文本

2023-12-02

我正在尝试创建一个自定义 winforms 按钮控件,该控件将允许通过旋转属性旋转按钮文本。我基本上已经让它工作了,但是它非常笨拙,我想知道执行此操作的正确方法。

特别是现在文本重绘的行为很奇怪。如果控件移出屏幕,然后缓慢移回到文本上,要么变得非常混乱(例如只绘制了一半),要么完全消失,直到鼠标悬停在上面。显然我做错了什么,但不知道是什么。

我从按钮控件继承并重写其 OnPaint 方法。

这是代码:

public class RotateButton : Button
{
    private string text;
    private bool painting = false;

    public enum RotationType { None, Right, Flip, Left}

    [DefaultValue(RotationType.None), Category("Appearance"), Description("Rotates Button Text")]
    public RotationType Rotation { get; set; }

    public override string Text
    {
        get
        {
            if (!painting)
                return text;
            else
                return "";
        }
        set
        {
            text = value;
        }
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        painting = true;

        base.OnPaint(e);

        StringFormat format = new StringFormat();
        Int32 lNum = (Int32)Math.Log((Double)this.TextAlign, 2);
        format.LineAlignment = (StringAlignment)(lNum / 4);
        format.Alignment = (StringAlignment)(lNum % 4);

        int padding = 2;

        SizeF txt = e.Graphics.MeasureString(Text, this.Font);
        SizeF sz = e.Graphics.VisibleClipBounds.Size;

        if (Rotation == RotationType.Right)
        {
            //90 degrees
            e.Graphics.TranslateTransform(sz.Width, 0);
            e.Graphics.RotateTransform(90);
            e.Graphics.DrawString(text, this.Font, Brushes.Black, new RectangleF(padding, padding, sz.Height - padding, sz.Width - padding), format);
            e.Graphics.ResetTransform();
        }
        else if (Rotation == RotationType.Flip)
        {
            //180 degrees
            e.Graphics.TranslateTransform(sz.Width, sz.Height);
            e.Graphics.RotateTransform(180);
            e.Graphics.DrawString(text, this.Font, Brushes.Black, new RectangleF(padding, padding, sz.Width - padding, sz.Height - padding), format);
            e.Graphics.ResetTransform();
        }
        else if (Rotation == RotationType.Left)
        {
            //270 degrees
            e.Graphics.TranslateTransform(0, sz.Height);
            e.Graphics.RotateTransform(270);
            e.Graphics.DrawString(text, this.Font, Brushes.Black, new RectangleF(padding, padding, sz.Height - padding, sz.Width - padding), format);
            e.Graphics.ResetTransform();
        }
        else
        {
            //0 = 360 degrees
            e.Graphics.TranslateTransform(0, 0);
            e.Graphics.RotateTransform(0);
            e.Graphics.DrawString(text, this.Font, Brushes.Black, new RectangleF(padding, padding, sz.Width - padding, sz.Height - padding), format);
            e.Graphics.ResetTransform();
        }

        painting = false;
    }
}

所以我的主要问题是如何解决文本重绘问题?

此外,我对上述代码还有一些其他问题/评论:

  1. 起初,文本显示两次,一次在默认位置,一次在旋转位置。我认为这是因为当base.OnPaint方法被调用。如果是这种情况,我如何防止文本最初绘制?

    我的解决方案是覆盖文本字符串并在调用之前清除它base.OnPaint使用布尔值,这不是我特别满意的解决方案。

  2. 我应该在最后处理 PaintEventArgse.dispose?我想我不确定 PaintEventArgs 对象是如何处理的。

提前致谢!

诗。这是我的第一篇文章/问题,所以如果我无意中忽略了一些礼仪或规则,我提前道歉。


  1. VisibleClipBounds 返回需要重新绘制的区域,例如,如果一半按钮需要重新绘制(覆盖一半按钮的顶部窗体关闭)VisibleClipBounds 仅返回该区域。所以你不能用它来绘制居中的文本。 SizeF sz = new SizeF(宽度, 高度); 应该解决重涂问题。

  2. 按钮不支持所有者绘图,您的方式似乎没问题。

  3. 通常,您不应该处置尚未创建的对象,并且一次性事件参数由创建它们的逻辑处置(并首先调用 On...),因此不必担心处置 PaintEventArgs。

欢迎来到堆栈溢出:)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何正确获取 WinForms Button 控件来绘制自定义文本 的相关文章

  • 将 LUIS 与 FormFlow 集成

    我创建了一个机器人 里面有一个 FormFlow 现在 如果您输入 我想启动产品 LUIS 将告诉它必须转到哪个对话框 internal static IDialog
  • 从值获取键 - Dictionary>

    我无法通过指定值来获取密钥 我实现这一目标的最佳方法是什么 var st1 new List
  • 如何从 C# 可移植类库 (PCL) 添加对 F# 可移植库的引用

    我有一个项目 其中包含两个 F 项目和一个 C 项目 我想在其中编写一些 XUnit 测试 FS PL F 3 1 3 3 1 0 可移植库 FS PL Legacy F 31 2 3 5 1 可移植库 旧版 测试 C NET 4 5 Wi
  • 安全地检查“this”是否为空

    首先 我知道在空指针上调用方法是未定义的行为 我还知道 因为这不应该发生 编译器可以 并且确实 假设this始终为非空 但在实际代码中 有时您会不小心这样做 通常 它没有任何不良影响 当然除了this方法中为 null 并且事情可能会崩溃
  • 如何从 nuget 包中排除子目录和内容

    所以我有一个网站正在尝试打包用于 Octopus Deploy 我有以下文件夹结构 Web Views WantThis Dontwantthis WantThis1 WantThis2 lots more Scripts 我试图排除 Do
  • 如何使用 VB.NET 或 C#.NET 代码从 yahoo 邮件 ID 发送邮件

    我想从我的 yahoomail Id 发送邮件 如何使用 VB NET 或 C NET 代码从 yahoo mail Id 发送邮件 需要善意的帮助 提前谢谢 西瓦库马尔 以下是一些制作基本 html 电子邮件消息的示例 http help
  • send() 使我的程序崩溃

    我正在运行服务器和客户端 我正在我的计算机上测试我的程序 这是服务器中向客户端发送数据的函数 int sendToClient int fd string msg cout lt lt sending to client lt lt fd
  • SQL 选择与带有通配符的 URL 匹配的行

    我在数据库中有一个表 其中一列包含一个 URL 例如http example com users http example com users 轮廓 我得到了一个 URL 例如http example com users 234 profi
  • 将二维整数作为 Readonly/const 存储在单独的类中,同时保持非公开

    这是我在使用这个地方作为我的 去处 以获取关于什么有效 无效 为什么等的一般意见之后的第一个问题 那么让我们试试这个 由于我的经验有限 我一直在尝试寻找更好的方法来创建固定数据字段 我可以在整个程序中引用这些字段 例如我反复显示的最终用户可
  • 不屈不挠的野兽:一个二维字符数组,位于结构内部,位于非托管 dll 的内部

    我束紧腰 冒险进入了遗产之地 砍倒 召唤并集结了各种野兽 现在我站在了一个如此凶猛的生物面前 据我对我的弟兄们进行的详尽调查来看 我现在所面对的生物是如此凶猛 武器中 没有一个代码战士能够幸存 以下是详细信息 我试图将结构内部的二维字符数组
  • 重写 ASP.Net Core 中的 415 响应

    在 ASP net Core 2 1 中 我想返回 Json 响应以及状态代码 415 而不是默认返回的 415 为了实现这一点 我使用资源过滤器 public class MediaTypeResouceFilter Attribute
  • 命名空间中不存在类型或命名空间名称 - 但命名空间确实存在

    我已经工作了很长时间没有任何问题的项目突然开始抛出错误 例如 The type or namespace name xxx does not exist in the namespace yyy are you missing an ass
  • 大表的最佳主键格式

    我正在开发一个 ASP NET 应用程序 它有一些可能很大的数据表 我想知道定义主键的最佳方法是什么 我知道以前已经有人问过这个问题 但由于这是针对特定情况的 所以我认为这个问题是有效的 我在 SQL Server 2008 数据库上使用实
  • const int 列表而不是 enum

    我开始研究大型 C 代码库 并发现使用带有多个 const ints 字段的静态类 这个类的行为与枚举完全一样 我想将类转换为实际的枚举 但权力被拒绝 我想转换它的主要原因是这样我可以将枚举作为数据类型而不是 int 这对可读性有很大帮助
  • 如何将 Activator.CreateInstance 与字符串一起使用?

    在我的反射代码中 我的通用代码部分遇到了问题 特别是当我使用字符串时 var oVal object Test var oType oVal GetType var sz Activator CreateInstance oType oVa
  • 我如何错误地使用 C 中的 round() 函数?

    我从中得到了意想不到的结果round and roundf 中的函数math h图书馆 这是示例代码 include
  • 如何使 RSACryptoServiceProvider 在没有填充(nopadding)的情况下工作?

    我需要使 C 应用程序与 Java 应用程序兼容 Java 应用程序使用Cipher getInstance RSA ECB nopadding 初始化器使密码 ECB 和无填充 但是 在 C 中 您有 2 个填充选项 OAEP 填充或 P
  • C# 多重继承

    目前我正在学习 C 和 ASP NET MVC 4代码优先方法 我是 Visual Basic 开发人员 现在我想开始 C 而且 现在我遇到了必须管理多重继承的情况 但是 对于Class i来说这是不可能的 那么 我应该如何管理我拥有的这些
  • qt 如何知道按钮被点击?

    我正在尝试编写一个程序 用声音进行一些操作 我的问题是我有 3 个播放按钮和 3 个标签 我希望无论我单击 播放 按钮 都应该播放按钮附近标签中名称的声音 我有一个没有任何参数的播放插槽 那么 如何分别连接到每个播放按钮和每个标签呢 实际上
  • 在 Rx 中,如何按 id 对事件进行分组并按多个时间跨度限制每个组?

    可以这么说 我陷入了 Rx 热潮 这个问题与我的相关here https stackoverflow com questions 19425965 rx how to group by a key a complex object and

随机推荐

  • 通过 Actionscript 3.0 使用 HTTP POST 上传 zip 文件

    我有一个 zip 文件 该文件是通过在桌面 Flex 4 6 应用程序中的视图上拖放而创建的 这会触发自动上传 zip 文件的服务 我可以使用以下代码将有关 zip 文件的元数据发送到服务器 var urlRequest URLReques
  • 在 Symfony 2.8、3.0 及更高版本中将数据传递给 buildForm()

    我的应用程序当前使用构造函数将数据传递到我的表单类型 如中所建议的这个答案 但是 那Symfony 2 8 升级指南建议将类型实例传递给createForm函数已弃用 将类型实例传递给 Form add FormBuilder add 和
  • Google Maps API v3 - infoWindows 均具有相同的内容

    我在使用 infoWindows 和 Google Maps API v3 时遇到了问题 最初 我遇到了其他人在打开新窗口时关闭 infoWindows 的问题 我想通过预先定义 infowindow 来解决这个问题 现在 当我单击新标记时
  • file_get_contents 脚本适用于某些网站,但不适用于其他网站

    我正在寻找构建一个 PHP 脚本来解析 HTML 中的特定标签 我一直在使用这个代码块 改编自这个tutorial 该脚本适用于某些网站 例如上面的 google 但是当我尝试使用其他网站 例如 freshdirect 时 我收到此错误 警
  • pyplot散点图标记大小

    在散点图的 pyplot 文档中 matplotlib pyplot scatter x y s 20 c b marker o cmap None norm None vmin None vmax None alpha None line
  • 我想在 React 的画布上录制视频

    我查了很久 觉得有必要在这里问一下 我之前使用的 npm 包什么也没做 有人曾经做过或经历过这样的应用吗 我想做的就是在画布元素上绘图时将其录制为视频 提前致谢 是的 您可以使用媒体流 捕获流 and 媒体记录器为了那个原因 下面是一个示例
  • VBA执行字符串中的代码

    我正在尝试执行字符串内的 vba 代码 而不将代码写入临时文件中 例如 Dim code As String code n 0 e i e 0 For e i e 0 To 100 n 1 Next 我尝试过 Eval Evaluate R
  • 如何更改行尾约定?

    我有一个我认为很简单的任务 我需要创建一个在行尾使用 unix LF 约定的文本文件 然而 当我尝试使用 pandas to csv 来完成此操作时 我最终得到了 CR LF 如果我留在我的机器上并且我使用 python 来处理所有事情 这
  • 动态创建电子表格菜单项

    我正在尝试使用 Google Apps 脚本在 Google 表格中创建动态填充的菜单 我有一张 课程 表 其中列出了我教授的课程 在运行我的脚本时 我让脚本读取这些类并将其加载到数组中 为了仅在原始 类 表中硬编码值 我想为每个类创建一个
  • Google 地图自定义信息框

    我正在尝试按照此示例合并自定义信息框 但我的代码不起作用 有人可以看一下我哪里出错了吗 我已经评论了示例代码的开始 结束位置以及我试图调用它的位置 function initialize var mapOptions zoom 12 cen
  • IntelliJ IDEA 中代码生成的自定义

    我使用 IntelliJ IDEA 12 我可以自定义使用 重构 功能生成的代码吗 例如 我想更改设置生成 封装字段 的模板 public void setField String field this field field to pub
  • 为什么从标准模块(而不是用户窗体)调用 VBA 代码时运行速度更快?

    Alternate Title Why does pressing Esc make my MS Word macro run faster 在等待一些代码运行时 我偶然发现了一些有趣的事情 Code runs slow press Esc
  • 如何在内核空间中使用 netfilter 钩子路由分割的数据包

    我必须在 PRE ROUTING 挂钩中将大数据包拆分为较小的数据包 我已经完成了将数据包分割成更小的数据包 创建 skb 设置 ip 和 udp 标头等的必要步骤 但我不明白的是如何路由数据包 我现在可以在数据包中附加数据 可以在我之前的
  • 转换不带时间的不同时区的日期

    我将日期存储在UTC长并以用户时区显示 但是当我尝试只存储没有时间的日子时 它会误导不同的日期 例如 将活动安排在 05 06 2016 2016 年 5 月 6 日 该日期对于所有没有时区的区域都是唯一的 如果来自 GMT 5 30 时区
  • 如何在 Xcode Story Board 中添加有关多设备的动态字体大小

    我在storyBoard中添加了自动布局 带有 An h 任何 但由于字体大小固定 所有设备上的字体大小都是相同的 4 4 7 5 5 英寸 4寸的看起来不错 但是5 5英寸的 太小了 我想在任何设备中动态增大和减小 UIlabel 字体大
  • 如何在 Woocommerce 中按商品设置运费

    在 Woocommerce 中 当我在购物车中添加多个产品时 运费仅适用于 1 个产品 我应该如何更改它以将成本应用于每个项目 如下图所示 适用打印机的运费 但不适用液晶显示器的运费 如何在 Woocommerce 中按商品设置运费 在 W
  • 具有奇数宽度的 16 位纹理是透明的

    我使用以下 OpenGL 命令上传 35 x 100 16bpp 纹理 glTexImage2D GL TEXTURE 2D 0 GL RG8 35 100 0 GL RG GL UNSIGNED BYTE pixelData 但随着 y
  • 如何更改wpf中的图标扩展器

    有没有办法可以将扩展器的图标更改为 并以白色作为前景色 我一直在到处寻找但找不到简单的解决方案 或者更好的是 如何将扩展器图标的颜色更改为白色 我的背景是深色的 所以这就是我问的原因 您将需要创建自定义控件模板 请参阅此 CodeProje
  • 如何修复:无法推断自动强制的适当生命周期

    我再次遇到了一个我似乎无法独自解决的终生问题 编译器告诉我无法推断自动强制的适当生命周期 我尝试遵循编译器的建议并在handle request method fn handle request lt a gt self req Reque
  • 如何正确获取 WinForms Button 控件来绘制自定义文本

    我正在尝试创建一个自定义 winforms 按钮控件 该控件将允许通过旋转属性旋转按钮文本 我基本上已经让它工作了 但是它非常笨拙 我想知道执行此操作的正确方法 特别是现在文本重绘的行为很奇怪 如果控件移出屏幕 然后缓慢移回到文本上 要么变