zoukankan      html  css  js  c++  java
  • 基于MFC的对话框程序加启动进度条

    对于比较大的程序,在启动的时候都会显示一个画面,以告诉用户程序正在加载,或者显示一些关于软件的信息,如Visual C++,Word, PhotoShop等。

    这些启动画面在Visual C++中怎么实现呢?对于文档/视图结构的程序,可以直接使用VC提供的SplashWnd组件。可是在基于对话框的程序却不能使用SplashWnd组件。因此只能自己来实现此功能。

    因为显示启动画面的同时还要进行程序的加载工作,所以要用到多线程。MFC区分了两种不同类型的多线程:用户界面(UI)线程和工作者线程。两者的区别是UI线程有消息循环,而工作者线程没有,UI线程能够创建窗口并处理发送给窗口的消息。工作者线程用来执行后台任务,这些后台任务不直接接受用户输入,因此不需要窗口和消息循环。 因为这里要显示一个画面,所以要使用UI线程。

    下面结合我做的一个小软件“实用闹钟”来说明如何为对话框程序制作启动画面。

    打开Visual C++建立一个对话框工程Page. 

    首先准备一副位图资源插入到工程中,作为启动时显示的画面。再插入一个对话框,设置ID为IDD_SPLASH。在上面放一个picture控件,类型设为”Bitmap”,图象选择刚才插入的位图。

    设置对话框的Style为Popup,Border 为None,去掉Title Bar属性,并调整对话框的大小与位图等大,这样对话框显示的时候,你看到的只是图片。打开 ClassWizard为此对话框建立一个新类CSplashDlg, 基类为CDialog.

    UI线程是由一个动态可创建的类来控制,该类是从CWinThread派生的,非常类似从CWinApp派生的一个应用程序类.打开ClassWizard建立一个由CWinThread派生的类----CSplashThread,在SplashThread.h 中加入 #include"SplashDlg.h",并添加一个protected型指针变量:

    CSplashDlg*  m_pSplashDlg;  //声明一个对话框指针

    下面我们将在UI线程的InitInstance()函数中调用刚才创建的对话框并显示。

    BOOL CSplashThread::InitInstance()

    {

      ::AttachThreadInput(m_nThreadID, AfxGetApp()->m_nThreadID, TRUE );

    //:通常系统内的每个线程都有自己的输入队列。本函数允许线程和进程共享输入队列。连接了线程后,输入焦点、窗口激活、鼠标捕获、键盘状态以及输入队列状态都会进入共享状态 . (这个函数可以不用)

      m_pSplashDlg=new CSplashDlg;   

      m_pSplashDlg->SetEnable(true);

      m_pSplashDlg->Create(IDD_SPLASH);

      m_pSplashDlg->ShowWindow(SW_SHOW);

      return true;

    }

    为CSplashThread类添加一个函数HideSplash(), 用来隐藏启动画面(即关闭对话框)

    void CSplashThread::HideSplash()

    {

          m_pSplashDlg->SendMessage(WM_CLOSE);

    }

    在ExitInstance()中释放资源:

    int CSplashThread::ExitInstance()

    {

        m_pSplashDlg->DestroyWindow();

        delete m_pSplashDlg;

               return CWinThread::ExitInstance();

    }

    在应用程序类CPageApp中包含头文件:   #include “SplashThread.h”

    并添加两个变量:

    public:        //设为pulic类型,是为了在其他类中能够访问

       CSplashThread* pSplashThread;

       CSplashDlg* m_pSplashDlg;

    在InitInstance()中启动UI线程:

        pSplashThread = (CSplashThread*) AfxBeginThread(

    RUNTIME_CLASS(CSplashThread),

                                                                             THREAD_PRIORITY_NORMAL,

    0, CREATE_SUSPENDED); 

       ASSERT(pSplashThread->IsKindOf(RUNTIME_CLASS(CSplashThread)));

       pSplashThread->ResumeThread(); 

       Sleep(1); 

    为了让程序一起动就显示启动画面,这段代码应该放在InitInstance()最开头的地方.

    启动画面是显示了,可是结束代码应该放在什么地方呢?如果放在InitInstance()的CPageDlg dlg; m_pMainWnd = &dlg; 后面,即在构造了主对话框之后隐藏启动画面, 程序运行时会发现,启动画面结束后,还要等一会才能显示出主对话框,这样就达不到启动画面应有的效果. 最好应该在即将显示主对话框的时候隐藏启动画面. 我的这个软件中在主对话框中定义了5个子对话框类的对象,分别是page1,page2,…page5.

    程序启动时的流程如下:

    Page1构造 --->Page2构造 --->Page3构造---> Page4构造---> Page5构造---> 主对话框构造 --->主对话框初始化---> Page1初始化---> Page2初始化 --->Page3初始化 Page4初始化---> Page5初始化

    由此可见,启动画面结束的最好地方应该是在 page5的初始化函数中

    BOOL CPage5::OnInitDialog()

    {

           CDialog::OnInitDialog();

           if ( ((CPageApp*)AfxGetApp())->pSplashThread != NULL)

                  ((CPageApp*)AfxGetApp())->pSplashThread->HideSplash();   

           return TRUE;              

    }

    到此,一个对话框程序的启动画面就这样完成了.由于是用对话框作为启动画面,所以你可以你可以发挥你的想象力,在对话框上设计出丰富多才的效果来,比如加上Flash,Gif动画等.

  • 相关阅读:
    【leetcode】1295. Find Numbers with Even Number of Digits
    【leetcode】427. Construct Quad Tree
    【leetcode】1240. Tiling a Rectangle with the Fewest Squares
    【leetcode】1292. Maximum Side Length of a Square with Sum Less than or Equal to Threshold
    【leetcode】1291. Sequential Digits
    【leetcode】1290. Convert Binary Number in a Linked List to Integer
    【leetcode】1269. Number of Ways to Stay in the Same Place After Some Steps
    【leetcode】1289. Minimum Falling Path Sum II
    【leetcode】1288. Remove Covered Intervals
    【leetcode】1287. Element Appearing More Than 25% In Sorted Array
  • 原文地址:https://www.cnblogs.com/tuncaysanli/p/1611556.html
Copyright © 2011-2022 走看看