RichTextBox的AnimateWindow API透明度问题

时间:2010-08-17 22:05:49

标签: c# winforms winapi textbox richtextbox

我正在使用AnimateWindow API来显示或隐藏带有幻灯片动画的Form。问题是如果表单包含RichTextBox控件,则它不会正确显示此控件。它是透明的,不显示任何文字。

动画完成后,双击控件中的某个位置将显示文本行。

我已经创建了一个完整的示例,任何人都可以使用它来编译和测试自己。除非你已经知道答案,否则没有更好的方法来调试它。

主窗体中有2个按钮,一个用于显示另一个窗体,另一个用于隐藏相同的窗体。我已将RichTextBox添加为简单的TextBox。如您所见,问题只发生在RichTextBox

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace WindowsFormsApplication1 {
    static class Program {
        public const int AW_ACTIVATE = 0x00020000;
        public const int AW_HIDE = 0x00010000;
        public const int AW_HOR_NEGATIVE = 0x00000002;
        public const int AW_HOR_POSITIVE = 0x00000001;
        public const int AW_SLIDE = 0x00040000;

        [DllImport("user32")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool AnimateWindow(IntPtr hWnd, int time, int awFlags);

        [STAThread]
        public static void Main() {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }

    public class Form1 : Form {
        public Form form;

        public Form1() {
            InitializeComponent();
            form = new Form2();
            form.Show();
            form.Hide();
        }

        private void button1_Click(object sender, EventArgs e) {
            form.Location = new Point(Location.X, Location.Y + form.Height + 100);
            Program.AnimateWindow(form.Handle, 1000, Program.AW_SLIDE | Program.AW_HOR_NEGATIVE | Program.AW_ACTIVATE);
            form.Show();
        }

        private void button2_Click(object sender, EventArgs e) {
            Program.AnimateWindow(form.Handle, 1000, Program.AW_HIDE | Program.AW_HOR_POSITIVE);
            form.Hide();
        }

        #region Windows Form Designer generated code

        private void InitializeComponent() {
            this.button1 = new System.Windows.Forms.Button();
            this.button2 = new System.Windows.Forms.Button();
            this.SuspendLayout();
            this.button1.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.button1.Location = new System.Drawing.Point(11, 12);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(133, 114);
            this.button1.TabIndex = 0;
            this.button1.Text = "SHOW";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            this.button2.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.button2.Location = new System.Drawing.Point(150, 12);
            this.button2.Name = "button2";
            this.button2.Size = new System.Drawing.Size(133, 114);
            this.button2.TabIndex = 1;
            this.button2.Text = "HIDE";
            this.button2.UseVisualStyleBackColor = true;
            this.button2.Click += new System.EventHandler(this.button2_Click);
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(294, 138);
            this.Controls.Add(this.button2);
            this.Controls.Add(this.button1);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
            this.MaximizeBox = false;
            this.MinimizeBox = false;
            this.Name = "Form1";
            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
            this.Text = "Form1";
            this.ResumeLayout(false);
        }

        #endregion

        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.Button button2;
    }

    public class Form2 : Form {
        public Form2() {
            InitializeComponent();
        }

        #region Windows Form Designer generated code

        private void InitializeComponent() {
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form2));
            this.richTextBox1 = new System.Windows.Forms.RichTextBox();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.SuspendLayout();
            this.richTextBox1.Dock = System.Windows.Forms.DockStyle.Top;
            this.richTextBox1.Location = new System.Drawing.Point(0, 0);
            this.richTextBox1.Name = "richTextBox1";
            this.richTextBox1.Size = new System.Drawing.Size(240, 50);
            this.richTextBox1.TabIndex = 0;
            this.richTextBox1.Text = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.";
            this.textBox1.Dock = System.Windows.Forms.DockStyle.Bottom;
            this.textBox1.Location = new System.Drawing.Point(0, 57);
            this.textBox1.Multiline = true;
            this.textBox1.Name = "textBox1";
            this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
            this.textBox1.Size = new System.Drawing.Size(240, 50);
            this.textBox1.TabIndex = 1;
            this.textBox1.Text = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.";
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(240, 107);
            this.ControlBox = false;
            this.Controls.Add(this.textBox1);
            this.Controls.Add(this.richTextBox1);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
            this.Name = "Form2";
            this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
            this.Text = "Form2";
            this.ResumeLayout(false);
            this.PerformLayout();
        }

        #endregion

        private System.Windows.Forms.RichTextBox richTextBox1;
        private System.Windows.Forms.TextBox textBox1;
    }
}

注意:我正在开始对此表示赏心,所以如果您要回答,请回答一个有效的解决方案,而不是让我尝试看看它是否有效原理的。为什么?因为如果人们提出你的答案并且没有做任何修改,那么它仍然会被标记为已接受,但它没有帮助。谢谢你的理解。

3 个答案:

答案 0 :(得分:0)

WPF不包含您需要的幻灯片动画吗?

像AnimateWindow这样的API ......在微软没有得到很多关注 - 通常支持'更好'的.NET / WPF方法。使用本机/非托管API来动画窗口可以快速让您陷入痛苦的世界: - Microsoft在本机控件和窗口中不支持闪烁控制动画或alpha效果。

如果目标窗口具有航空玻璃,则原生AnimateWindow会倾覆。任何非客户元素。任何儿童控制。任何透明度(窗口区域,带有alpha或masking的分层窗口)。

它实际上根本不起作用。


解决它的唯一方法是做AnimateWindow的工作。 AnimateWindow不是一个API调用,而是一个可以“轻松”实现的功能的便利包装。

所有AnimateWindow都会这样做,好吧,在计时器上重新定位动画窗口。根据动画,它将使用剪辑区域,或者在动画持续时间内添加WS_EX_LAYERED样式(以执行Alpha混合)。这就是为什么AnimateWindow在给定已使用这些效果的窗口时失败的原因。

自己动手制作动画,您可以尝试调整参数,使其与丰富的编辑绘画要求更加兼容。

答案 1 :(得分:0)

请看这段代码......这是我见过的最奇怪的错误...唯一的区别是我必须为RichTextBox捕获VisibleChanged事件,并设置Capture属性,更新它,然后关闭Capture,我的想法是向控件发送一条消息强制双击事件,但发现这不是必需的...我还必须覆盖OnActivated事件form2本身为了让事件陷入 AFTER 动画完成并强制刷新......奇怪的奇怪的错误....

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Text;

namespace WindowsFormsApplication1
{
    static class Program
    {
        public const int AW_ACTIVATE = 0x00020000;
        public const int AW_HIDE = 0x00010000;
        public const int AW_HOR_NEGATIVE = 0x00000002;
        public const int AW_HOR_POSITIVE = 0x00000001;
        public const int AW_SLIDE = 0x00040000;

        [DllImport("user32")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool AnimateWindow(IntPtr hWnd, int time, int awFlags);

        [STAThread]
        public static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }

    public class Form1 : Form
    {
        public Form form;

        public Form1()
        {
            InitializeComponent();
            form = new Form2();
            form.Show();
            form.Hide();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            form.Location = new Point(Location.X, Location.Y + form.Height + 100);
            Program.AnimateWindow(form.Handle, 1000, Program.AW_SLIDE | Program.AW_HOR_NEGATIVE | Program.AW_ACTIVATE);
            form.Show();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Program.AnimateWindow(form.Handle, 1000, Program.AW_HIDE | Program.AW_HOR_POSITIVE);
            form.Hide();
        }

        #region Windows Form Designer generated code

        private void InitializeComponent()
        {
            this.button1 = new System.Windows.Forms.Button();
            this.button2 = new System.Windows.Forms.Button();
            this.SuspendLayout();
            this.button1.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.button1.Location = new System.Drawing.Point(11, 12);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(133, 114);
            this.button1.TabIndex = 0;
            this.button1.Text = "SHOW";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            this.button2.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.button2.Location = new System.Drawing.Point(150, 12);
            this.button2.Name = "button2";
            this.button2.Size = new System.Drawing.Size(133, 114);
            this.button2.TabIndex = 1;
            this.button2.Text = "HIDE";
            this.button2.UseVisualStyleBackColor = true;
            this.button2.Click += new System.EventHandler(this.button2_Click);
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(294, 138);
            this.Controls.Add(this.button2);
            this.Controls.Add(this.button1);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
            this.MaximizeBox = false;
            this.MinimizeBox = false;
            this.Name = "Form1";
            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
            this.Text = "Form1";
            this.ResumeLayout(false);
        }

        #endregion

        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.Button button2;
    }

    public class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
            this.richTextBox1.VisibleChanged += new EventHandler(richTextBox1_VisibleChanged);
        }

        void richTextBox1_VisibleChanged(object sender, EventArgs e)
        {
            if (this.richTextBox1.Visible)
            {
                System.Diagnostics.Debug.WriteLine("Visible!");
                this.richTextBox1.Capture = true;
                this.richTextBox1.Update();
                this.richTextBox1.Capture = false;
                this.richTextBox1.Refresh();
            }
            else System.Diagnostics.Debug.WriteLine("InVisible!");
        }

        #region Windows Form Designer generated code

        private void InitializeComponent()
        {
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form2));
            this.richTextBox1 = new System.Windows.Forms.RichTextBox();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.SuspendLayout();
            this.richTextBox1.Dock = System.Windows.Forms.DockStyle.Top;
            this.richTextBox1.Location = new System.Drawing.Point(0, 0);
            this.richTextBox1.Name = "richTextBox1";
            this.richTextBox1.Size = new System.Drawing.Size(240, 50);
            this.richTextBox1.TabIndex = 0;
            this.richTextBox1.Text = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.";
            this.textBox1.Dock = System.Windows.Forms.DockStyle.Bottom;
            this.textBox1.Location = new System.Drawing.Point(0, 57);
            this.textBox1.Multiline = true;
            this.textBox1.Name = "textBox1";
            this.textBox1.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
            this.textBox1.Size = new System.Drawing.Size(240, 50);
            this.textBox1.TabIndex = 1;
            this.textBox1.Text = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.";
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(240, 107);
            this.ControlBox = false;
            this.Controls.Add(this.textBox1);
            this.Controls.Add(this.richTextBox1);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
            this.Name = "Form2";
            this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
            this.Text = "Form2";
            this.ResumeLayout(false);
            this.PerformLayout();
        }

        #endregion

        protected override void OnActivated(EventArgs e)
        {
            base.OnActivated(e);
            System.Diagnostics.Debug.WriteLine("OnActivated");
            this.Refresh();
        }

        private System.Windows.Forms.RichTextBox richTextBox1;
        private System.Windows.Forms.TextBox textBox1;
    }
}

代码仍然有用 - 一个非常模糊的东西 - 有趣的是在VisibleChanged处理程序中,当我点击“隐藏”按钮时,我期望调试输出说“InVisible”,但事实并非如此。我确实尝试使用富文本框失败的WM_PRINTWM_PRINTCLIENT消息,只是不要问我为什么要在富文本框本身设置捕获并强制刷新解决它......这是MSDN对此的引用:

  

窗口及其子窗口的窗口过程应该处理任何WM_PRINT或WM_PRINTCLIENT消息。对话框,控件和公共控件已经处理WM_PRINTCLIENT。默认窗口过程已处理WM_PRINT。如果子窗口显示为部分剪裁,则在设置动画时,它将有剪切的孔。

我不知道是否值得给微软指出这个问题并且说“AnimateWindow或.NET中的RichTextBox控件中存在错误”,无论哪种方式,都难以确定,因为在动画完成后,文本框显示正常,但不是富文本框,但在捕获开启时明确使用CaptureUpdate,强制刷新...它会摇摆关于bug本身的两种方式 - 可能在两个地方......非常不寻常和怪异无论如何..希望代码对你有用。

答案 2 :(得分:0)

RichTextBox不处理WM_PRINT消息,我相信AnimateWindow在幕后使用的内容,所以我看不到任何方法在富文本框中显示文本的动画(如果你想要richtext box的话)在动画期间显示文字)。

动画完成后,您可以调用richTextBox1.Refresh(在您的button1_Click中通过Form2类中的帮助方法)重新绘制框 - 带有文本的控件将显示正常,无需双击。