代码改变世界

Smartphone2003开发总结一:Form总结

2009-06-11 01:13  老羽  阅读(1748)  评论(5编辑  收藏  举报

       在过去的几个月中,完成了一款较旧的手机smartphone2003的项目开发。smartphone2003项目只能以.net cf1.1框架创建,所以导致有不少麻烦和诡异的情况发生。这里总结一下自己的经验。

       一.启动主界面还不简单,有什么好讲的。我也是这么认为的,但是我碰到的情况并非如此(我用的机器是多普达585, 环境:vs2005 CF1.1)。请看我的代码:

public class Program
    {
        static void Main()
        {
            LoginForm login = new LoginForm();
            if (login.ShowDialog() == DialogResult.OK)
            {
                login.Dispose();
                login = null;
                MainForm main = new MainForm();
                Application.Run(main);
            }
        }
    }

没有任何问题吧,但是MainForm始终都显示不出来。后来测试了隐藏LoginForm,然后显示MainForm,可以正常显示(但是这样写不符合习惯)。后来我想利用API函数SetForegroundWindow显示MainForm,结果发现Form中没有Handle属性,也就是获取不到窗体Hwnd,API函数也用不了,郁闷吧!如何得到窗体句柄呢?可以通过GetCapture获取某个Control的句柄。

       [DllImport("coredll.dll")]
        public static extern IntPtr GetCapture();
        public static IntPtr GetHandle(Control ctl)
        {
            if (ctl != null)
            {
                ctl.Capture = true;
                try
                {
                    return GetCapture();
                }
                finally
                {
                    ctl.Capture = false;
                }
            }
            return IntPtr.Zero;
        }

Ok,终于得到了窗体句柄,这个窗体句柄非常重要,在以后的介绍中还要用到它。

这样第一段代码不用修改,在MainForm的FormLoad事件中或OnLoad方法中调用API函数SetForegroundWindow可以正常显示主界面了。

二.显示Form

请看下面测试代码,MainForm中menuItem1_Click事件。

private void menuItem1_Click(object sender, EventArgs e)
        {
            Form2 form = new Form2();
            //form.Parent = this;
            form.ShowDialog();
        }

 这个代码显示窗体没有问题,但是smartphone2003手机中有个返回键(<—),很容易按到,模态对话框的窗体就会关闭,影响操作。

如是,代码就改成了:

Form2 form = new Form2();
form.Show();

这样的代码又有什么不妥呢?这样显示Form2,会导致在任务管理器中看到2个任务(MainForm和Form2),请注意:CF1.1中Form没有Owner属性的.

接着修改,Hide当前窗体,Show新窗体,可以避免任务栏中有多个任务显示。但是一定要封装,否则新窗体关闭后,如何显示当前窗体???

我们利用继承基类窗体来实现,建立一个基类窗体BaseForm,重载Show的方法,实现隐藏当前窗体,Show新窗体,并且在新窗体关闭时,显示当前窗体。

/// <summary>
    /// BaseForm 的摘要说明。
    /// </summary>
    public class BaseForm : System.Windows.Forms.Form
    {
        private IntPtr _handler;
        private BaseForm _parentForm;

        public IntPtr Handler
        {
            get 
            { 
                return _handler; 
            }
        }

        protected override void OnLoad(EventArgs e)
        {
            _handler = FormUtility.GetHandle(this);
            base.OnLoad(e);
            FormUtility.SetForegroundWindow(_handler);
        }

        public void Show(BaseForm parent)
        {
            _parentForm = parent;
            parent.Hide();
            this.Show();
        }

        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);
            ShowParentForm();
        }

        protected virtual void ShowParentForm()
        {
            try
            {
                if (_parentForm != null)
                {
                    _parentForm.Show();
                    FormUtility.SetForegroundWindow(_parentForm.Handler);
                    Application.DoEvents();
                }
            }
            catch (Exception)
            {
            }
        }
    }
这样就隐藏了Show Form 的细节,完善后的代码如下(Form2继承BaseForm):
 Form2 form = new Form2();
 form.Show(this);

 

三.Dispose Form

在CF2.0中,调用Form.Close()方法后,会调用Dispose方法。但是CF1.1中,则不会。为什么呢?我们来看看。

public class Component : MarshalByRefObject

 关键就是Compoent没有继承IDispose接口,所以Form.Close()调用后,是不会调用Dispose()方法的。我们在BaseForm中封装调用Dispose的实现:

protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);
            ShowParentForm();
            this.Dispose(true);
        }
DEMO下载请点击这里