【问题标题】:Valid use of bitwise operators for CreateParams, undesired behavior?对 CreateParams 有效使用位运算符,不希望的行为?
【发布时间】:2026-02-13 04:20:02
【问题描述】:

我正在为 ProgressBar 控件编写一个包装器(不是真正的包装器,而是正确实现 Vista 功能)。这是我的代码:

    /// <summary>
    /// Encapsulates the information needed when creating a control
    /// </summary>
    protected override CreateParams CreateParams {
        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        get {
            CreateParams cp = base.CreateParams;
            if (SmoothReverse) {
                // Add using bitwise OR
                cp.Style = cp.Style | PBS_SMOOTHREVERSE;
            }
            else {
                // Remove using bitwise XOR
                cp.Style = cp.Style ^ PBS_SMOOTHREVERSE;
            }
            if (Vertical) {
                // Add using bitwise OR
                cp.Style = cp.Style | PBS_VERTICAL;
            }
            else {
                // Remove using bitwise XOR
                cp.Style = cp.Style ^ PBS_VERTICAL;
            }
            return cp;
        }
    }

    private bool m_SmoothReverse = false;
    /// <summary>
    /// Gets or sets a System.Boolean value indicating whether the SmoothReverse style is used
    /// </summary>
    [Category("Behavior")]
    [DefaultValue(false)]
    [Description("Gets or sets a System.Boolean value indicating whether the SmoothReverse style is used")]
    public bool SmoothReverse {
        get {
            return m_SmoothReverse;
        }
        set {
            m_SmoothReverse = value;
        }
    }

    private bool m_Vertical = false;
    /// <summary>
    /// Gets or sets a System.Boolean value indicating whether the progress bar will be rendered vertically
    /// </summary>
    [Category("Behavior")]
    [DefaultValue(false)]
    [Description("Gets or sets a System.Boolean value indicating whether the progress bar will be rendered vertically")]
    public bool Vertical {
        get {
            return m_Vertical;
        }
        set {
            m_Vertical = value;
        }
    }

问题是,当您将控件放在窗体上时,它以垂直方式开始,带有 PBS_SMOOTH。所以我的问题是,在使用按位运算设置 CreateParams.Style 的值之前,我应该做哪些额外的检查,或者我的按位运算(或事实上的代码)是否正确?

感谢 Jon Skeet 更新 能够得到这个完全修复和工作,并应用 UpdateStyles() 来强制新样式在属性中按需 apply(),控件现在可以按预期工作并被打磨:)

    /// <summary>
    /// Encapsulates the information needed when creating a control
    /// </summary>
    protected override CreateParams CreateParams {
        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        get {
            CreateParams cp = base.CreateParams;
            if (SmoothReverse) {
                cp.Style |= PBS_SMOOTHREVERSE;
            }
            else {
                cp.Style &= ~PBS_SMOOTHREVERSE;
            }
            if (Vertical) {
                cp.Style |= PBS_VERTICAL;
            }
            else {
                cp.Style &= ~PBS_VERTICAL;
            }
            return cp;
        }
    }

    private bool m_SmoothReverse = false;
    /// <summary>
    /// Gets or sets a System.Boolean value indicating whether the SmoothReverse style is used
    /// </summary>
    [Category("Behavior")]
    [DefaultValue(false)]
    [Description("Gets or sets a System.Boolean value indicating whether the SmoothReverse style is used")]
    public bool SmoothReverse {
        get {
            return m_SmoothReverse;
        }
        set {
            m_SmoothReverse = value;
            UpdateStyles();
        }
    }

    private bool m_Vertical = false;
    /// <summary>
    /// Gets or sets a System.Boolean value indicating whether the progress bar will be rendered vertically
    /// </summary>
    [Category("Behavior")]
    [DefaultValue(false)]
    [Description("Gets or sets a System.Boolean value indicating whether the progress bar will be rendered vertically")]
    public bool Vertical {
        get {
            return m_Vertical;
        }
        set {
            m_Vertical = value;
            UpdateStyles();
        }
    }

【问题讨论】:

    标签: c# bit-manipulation createparams


    【解决方案1】:

    | 操作是正确的(虽然我会使用 |=),^ 不是。

    这个:

    cp.Style = cp.Style ^ PBS_SMOOTHREVERSE;
    

    只会反转已经存在的任何内容。你想要:

    cp.Style &= ~PBS_SMOOTHREVERSE;
    

    这就是说,“用一个设置了所有位的掩码来屏蔽值除了 PBS_SMOOTHREVERSE”。

    【讨论】:

    • @David:呃——我没有看到它是一个现有的财产。这太可怕了——但不是你的错 :) 会删掉那一点。
    • 糟糕的双向飞碟!开玩笑,每个人都在吹嘘;没有汗水! :)
    • CreateParams 导致我的 CPU 使用率上升到 30% 以上,当我使用动态控件填充 TableLayout 面板时使用它来避免闪烁,无论如何要减少这个.....,