20

我仍然有启动画面的问题。我不想使用该属性SC.TopMost=true

现在我的应用场景如下:

在 progeram.cs 中:

[STAThread]
static void Main()
{
    new SplashScreen(_tempAL);// where _tempAL is an arrayList
    Application.Run(new Form1(_tempAL));
}

在 SplashScreen 类中:

public SplashScreen(ArrayList _Data)
{
    DisplaySplash()
} 
private void DisplaySplash()
{
    this.Show();
    this.TopMost = true;
    this.CenterToScreen();
    this.SetTopLevel(true);

    _allServerNarrators = new string[10];
    for (int i = 0; i < _allServerNarrators.Length; i++)
        _allServerNarrators[i] = null;

    GetFromServer();

    this.Hide();
    _serverData = new ArrayList();
    _thisData.Add(_allServerNarrators);
    _thisData.Add(_serverNarrators);

}
private void GetFromServer()
{
    _serverNarrators = new ArrayList();
    string _file = "Suras.serverNar";

    if (!Directory.Exists("c:\\ASGAQuraan"))
        Directory.CreateDirectory("c:\\ASGAQuraan");

    while (counter < 4 && _serverFiles == null)
    {
        if (Download("c:\\ASGAQuraan", _ftpServerIP, _file))
        {
            StreamReader _strReader = new StreamReader
                         ("c:\\ASGAQuraan\\"+_file,System.Text.Encoding.Default);
            string _line = _strReader.ReadLine();
            string _word;

            while (true)
            {
                while (_line != null)
                {
                    _word = _line.Substring(0, _line.IndexOf("*"));
                    int _narId = Convert.ToInt32(_word);
                    _line = _line.Substring(2);
                    int k = 0;
                    _serverNarratorNode = new ArrayList();
                    while (true)
                    {
                        int ind = _line.IndexOf("*");
                        if (ind > 0 && ind < _line.Length)
                        {
                            string str = _line.Substring(0, (ind));
                            if (k == 0)
                            {
                                _allServerNarrators[_narId] = str;
                                _serverNarratorNode.Add(str);
                            }
                            else
                            {
                                _serverNarratorNode.Add(str);
                            }
                            _line = _line.Substring(ind + 1);
                            k++;
                        }
                        else
                        {
                            _line = null;
                            break;
                        }
                    }
                    _serverNarrators.Add(_serverNarratorNode);
                    _serverFiles = "added";
                }
                _line = _strReader.ReadLine();
                if (_line == null)
                {
                    break;
                }
            }
        }
        else
            counter++;
    }
}

我想要的是启动屏幕类中的东西,它会等到线程完成。

有关更多详细信息,请告诉我我需要告诉您的内容。

4

5 回答 5

83

同样的问题,同样的答案:

.NET 框架对启动画面具有出色的内置支持。启动一个新的WF项目,Project + Add Reference,选择Microsoft.VisualBasic。添加一个新表单,将其命名为 frmSplash。打开 Project.cs 并使其看起来像这样:

using System;
using System.Windows.Forms;
using Microsoft.VisualBasic.ApplicationServices;

namespace WindowsFormsApplication1 {
  static class Program {
    [STAThread]
    static void Main(string[] args) {
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(false);
      new MyApp().Run(args);
    }
  }
  class MyApp : WindowsFormsApplicationBase {
    protected override void OnCreateSplashScreen() {
      this.SplashScreen = new frmSplash();
    }
    protected override void OnCreateMainForm() {
      // Do your time consuming stuff here...
      //...
      System.Threading.Thread.Sleep(3000);
      // Then create the main form, the splash screen will close automatically
      this.MainForm = new Form1();
    }
  }
}
于 2008-12-26T15:11:46.433 回答
3

在调用 Application.Run() 之前创建 UI,您已进入危险领域。Application.Run 本质上是程序的消息泵。通过在启动应用程序的消息泵之前显示 UI,您可以在不成熟的 UI 上有效地使典型的 UI 交互变得不可能。对于启动画面,这可能看起来无关紧要,但如果(例如)有请求让启动画面在单击时消失,或者您想使用 BackgroundWorker,这将很重要。

这些可以通过在初始屏幕中创建一个消息泵来解决(通过调用 ShowDialog() 而不是 Show() 使其成为模态),但是当治疗问题时,这就是治疗症状真的不是那么困难。

在这种情况下,我强烈鼓励nobugz 的回答。该框架提供您需要的支持。虽然 Microsoft.VisualBasic 命名空间中的功能对于 C# 程序员来说并不总是很容易发现,但对于此类情况,它们可以成为真正的节省时间和救生员。

祝你好运!

于 2008-12-26T15:34:52.317 回答
2

跨越 2 个线程有点令人困惑,但我要试一试,说这个......

我在这里不完全理解您的设计,但是如果问题是当您启动第二个应用程序时,启动屏幕表单会变成白色......这很可能是由于启动屏幕忙于执行 GetFromServer 中的所有代码()。太忙了,没有时间重新粉刷自己。

为了解决这个问题,我建议您使用BackGroundWorker 组件来执行 GetFromServer 方法。这将在单独的线程中运行该方法,并使表单的线程可以自由地重新绘制自身。

于 2008-12-25T15:50:06.937 回答
2

不幸的是,我还没有足够的声誉来评论某人的回答。:(这是对恐慌上校对汉斯·帕桑茨回答的评论的回答

他的问题是在启动画面后面会显示一个MessageBox显示的来源。new FormMain(args)关键是从启动画面运行的线程调用 MessageBox:

splashScreen.Invoke(new Action(() => {
    MessageBox.Show(splashScreen, "the message");
}));

Where splashScreen is a reference to the splash screen object that has been created in OnCreateSplashScreen and obviously has to be given to the new Form1 object.

于 2013-11-26T12:23:10.170 回答
1

你真的应该提供更多关于你的问题的细节。我可能完全错了,但我要在黑暗中开枪。从我想象的情况来看,你想要显示启动画面,在另一个线程中进行一些处理,然后启动画面在完成后消失。

为此,您需要将GetFromServer()调用移至BackgroundWorker. 然后移动

    this.Hide();
    _serverData = new ArrayList();
    _thisData.Add(_allServerNarrators);
    _thisData.Add(_serverNarrators);

BackgroundWorker_RunWorkerCompleted事件处理程序的代码。

要使用BackgroundWorker

1) 初始化BackGroundWorker

  BackgroundWorker myWorker = new BackgroundWorker();

2) 添加事件处理程序

  myWorker.DoWork += new DoWorkEventHandler(myWorker_DoWork);
  //put the work you want done in this one

  myWorker.RunWorkerCompleted += 
      new RunWorkerCompletedEventHandler(myWorker_RunWorkerCompleted);
  //this gets fired when the work is finished

3) 将代码添加到事件处理程序。

4) 打电话myWorker.RunWorkerAsync()开始工作。

作为单独的说明,您似乎没有对ArrayList传递给启动画面的构造函数的内容做任何事情。这是故意的吗?

于 2008-12-25T15:50:24.893 回答