我正在使用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;
}
}
注意:我正在开始对此表示赏心,所以如果您要回答,请回答一个有效的解决方案,而不是让我尝试看看它是否有效原理的。为什么?因为如果人们提出你的答案并且没有做任何修改,那么它仍然会被标记为已接受,但它没有帮助。谢谢你的理解。
答案 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_PRINT
和WM_PRINTCLIENT
消息,只是不要问我为什么要在富文本框本身设置捕获并强制刷新解决它......这是MSDN对此的引用:
窗口及其子窗口的窗口过程应该处理任何WM_PRINT或WM_PRINTCLIENT消息。对话框,控件和公共控件已经处理WM_PRINTCLIENT。默认窗口过程已处理WM_PRINT。如果子窗口显示为部分剪裁,则在设置动画时,它将有剪切的孔。
我不知道是否值得给微软指出这个问题并且说“AnimateWindow或.NET中的RichTextBox控件中存在错误”,无论哪种方式,都难以确定,因为在动画完成后,文本框显示正常,但不是富文本框,但在捕获开启时明确使用Capture
和Update
,强制刷新...它会摇摆关于bug本身的两种方式 - 可能在两个地方......非常不寻常和怪异无论如何..希望代码对你有用。
答案 2 :(得分:0)
RichTextBox不处理WM_PRINT消息,我相信AnimateWindow在幕后使用的内容,所以我看不到任何方法在富文本框中显示文本的动画(如果你想要richtext box的话)在动画期间显示文字)。
动画完成后,您可以调用richTextBox1.Refresh(在您的button1_Click中通过Form2类中的帮助方法)重新绘制框 - 带有文本的控件将显示正常,无需双击。