闪屏效果

来源:互联网 发布:淘宝哪家mk代购是正品 编辑:程序博客网 时间:2024/04/30 04:38

张红伟,李晓辉

 

(安徽大学电子工程与信息科学系,安徽合肥  230039)

 

 

摘要:本文介绍了闪屏效果和互斥体的概念及其在应用程序界面设计时的作用;阐述了有关位图的显示机理及互斥体的创建方法;提出了使用VC进行Windows下程序界面设计时闪屏效果的制作方法以及系统在任何时刻只运行某个应用程序的一个实类的实现策略。

关键词:闪屏效果;位图;互斥体

 

1 引言

在一些应用程序如Foxmail、FlashGet以及Office的系列软件中,当用户打开程序运行时,程序并不是直接进入程序运行所需的主界面,而是首先弹出一幅画面,用以显示程序的版本号以及出版公司的版权及标志等信息,此即为“闪屏效果”。如果在应用程序载入文件和初始化所需的一段时间内有一个闪屏效果出现,给用户显示一些内容,用户就不会对载入和初始化的延迟感到厌烦。这样做不仅可以大大增强视觉效果,而且增加了程序界面的友好性。通常一个令人感兴趣的闪屏效果将会给人以持久、深刻的印象。

VC在Gallery中也给出了制作闪屏效果的组件,但是使用此种策略生成的闪屏效果,欲显示的画面和应用程序主框架是同时弹出的,效果不是很理想。本文提出的闪屏效果的制作方案将有效地克服这一缺点,收到良好的视觉效果。另一方面,有些程序如FlashGet、金山词霸系列等,一旦运行后,在运行期间用户是无法再运行一个该程序的实类。也就是说,用户是无法在Windows下连续两次打开、运行上面的程序,同时看到两个运行时的图标的。

闪屏效果是目前一些常用软件在启动运行时弹出的最普遍、常见的用户界面,这些效果可在VC环境下通过调用VC提供的类及Windows的API函数实现。

2 位图的显示机理

2.1 VC中的CBitmap类

CBitmap类是VC中比较常用的一个类。CBitmap类封装了Windows的图形设备接口(GUI),提供管理位图的成员函数。要使用该类的对象,首先要构造该对象,然后通过初始化成员函数,连接位图句柄到该对象,最后调用该对象的成员函数。

使用CBitmap类的LoadBitmap成员函数可以从程序的可执行文件中调入指定的位图资源,并连接位图到对象,初始化对象。用LoadBitmap函数装入DDB(设备相关位图)有如下两种方法:

(1) BOOL CBitmap∷LoadBitmap( LPCTSTR lpszResourceName );

(2) BOOL CBitmap∷LoadBitmap( UNIT nIDResource )。

方法(1)是从一个BMP文件中装入位图,其名为lpszResourceName,若lpszResourceName标识不存在,或无足够内存加载,则返回0;方法(2)是从应用程序的资源中装入位图,nIDResource是ID号标识。DDB资源加载后,连接到CBitmap对象。在本文后面的实现程序中使用的是后一种方法。

为了能正确显示载入的位图,需要确切知道该位图的宽和高,这可以通过使用VC提供的BITMAP这样一种数据结构来实现。可以使用如下语句将所载入位图的相关数据传递给由BITMAP定义的变量。

CBitmap bitmap;

    BITMAP bmInfo;

bitmap.GetObject(sizeof(bmInfo),&bmInfo);

通过对bmInfo.bmWidth,bmInfo.bmHeight的引用便可以得到位图的宽和高。

2.2 显示位图

可以使用CDC类的BitBlt成员函数将位图显示出来。使用该函数前,首先需用CDC的CreateCompatibleDC()函数创建一个与系统显示兼容的内存设备环境。其函数说明如下:

CDC::CreateCompatibleDC(CDC * pDC)

其中pDC是设备环境指针。

为了实现在程序进入运行主界面以前显示位图的目的,需要在应用程序创建框架类和视图类以前将位图显示出来。众所周知,使用VC的AppWizard创建的应用程序,其执行顺序是从应用程序类开始的。因此,位图显示部分的源程序应该放在该类的初始化程序代码中。但是,由于此时应用程序尚未创建视图类,也不存在可供用户显示文本和图像的客户区。欲在此情况下显示位图,需要使用VC提供的CRect类和CWnd类的CreateEx成员函数在屏幕的中央创建一个与位图大小相同的视图区用来显示位图。

在具体的实现程序中,可以为实现闪屏效果的程序段创建一个类(CSplash类)。由于要用到CWnd类的CreateEx成员函数,因此,创建的CSplash类应该是从CWnd类派生而来的。

3 互斥体

在进行应用程序设计时,为程序创建一些唯一的东西,如唯一的ID号。该唯一的ID号在程序运行之前就可以检查出来,用以阻止该程序再次运行。本文中将通过创建互斥体这种唯一资源来达此目的。可以使用C:\Program Files\Microsoft Visual Studio\Common\Tools\GUIDGEN.EXE程序发生器为该程序名提供唯一的ID号。

4 闪屏效果的程序实现

4.1 闪屏效果的实现

(1) 用ClassWizard创建一个从一般CWnd类派生出来的普通窗口类CSplash。该类作为启动窗口类,以供在程序的应用程序类中调用该类对象中的成员函数显示启动窗口。

(2) 在CSplash类中添加Create(UINT nID)函数,在该函数中将装入欲在启动窗口中显示的位图。其中nID是欲装入的位图资源的ID。源程序如下:

v.oid CSplash∷Create(UINT nID)

{

bitmap.LoadBitmap(nID);

bitmap.GetObject(sizeof(bmInfo),&bmInfo);

int x = (∷GetSystemMetrics (SM-CXSCREEN)-bmInfo.bmWidth)/2;

int y = (∷GetSystemMetrics (SM-CYSCREEN)-bmInfo.bmHeight)/2;

  CRect rect(x,y,x+bmInfo.bmWidth,y+bmInfo.bmHeight);

  CreateEx(0,AfxRegisterWndClass(0),“”,WS-POPUP|WS-VISIBLE

|WS-BORDER,rect,NULL,0);

}

(3) 用ClassWizard在该窗口类中添加WM-PAINT消息处理函数,在此成员函数中使用BitBlt()把载入的位图送到屏幕上显示。

void CSplash∷OnPaint( )

{

CPaintDC dc(this); // device context for painting

CDC dcComp;

dcComp.CreateCompatibleDC(&dc);

dcComp.SelectObject(&bitmap);

dc.BitBlt(0,0,bmInfo.bmWidth,bmInfo.bmHeight, &dcComp, 0,0,SRCCOPY);

}

(4) 在应用程序类中的InitInstance()函数的开始处,由上面创建的启动窗口类创建一个实类,然后通过调用该实类中的成员函数Create(UINT nID)和OnPaint( )将位图显示出来。

BOOL CMySplashApp::InitInstance( )

{

CSplash Splash;

Splash.Create(IDB-BITMAP);

AfxGetMainWnd()-> SendMessage(WM-PAINT); //send WM-PAINT

Sleep(2000);

//following code

}

IDB-BITMAP是使用Developer Studio的Insert Resource菜单下的Import命令装入的位图的ID值。通过调用SendMessage( )函数发送WM-PAINT消息,系统响应WM-PAINT消息,执行CSplash类中OnPaint()成员函数的功能,将载入的位图绘制到屏幕上。

4.2 互斥体功能的实现

(1) 在应用程序类中使用define定义一个唯一的名字,该名字就是使用上述GUIDGEN.EXE程序发生器产生的ID。

#defineUNIQUE-SYMBOL“{BEB68660-8D9A-11d4-92E4-0010DC503EC6}”

(2)InitInstance()中创建互斥体。

BOOL CTestApp∷InitInstance()

{

::CreateMutex(NULL,FALSE, UNIQUE-SYMBOL);

if (GetLastError()==ERROR-ALREADY-EXISTS)

{

   AfxMessageBox(“您已经运行了该程序!”);

      return FALSE;

   }

…………………

}

(3) 程序运行结束时,Windows会自动清除所创建的互斥体。也可以在应用程序类的ExitInstance()成员函数中用CloseHandle()关闭互斥体。

5 结束语

友好的程序界面是目前编程人员在编程过程中必须着重考虑的重要一环。在上文介绍的闪屏效果中,如果在启动窗口类中不只创建、显示一个位图文件,而是几个位图依次显示,或者创建一个具有动感的启动窗口,可能会更具有吸引力,取得更好的视觉效果。

 

[参考文献]

[1]Richard C.Leinecker.Visual C++ 5开发技术内幕[M].机械工业出版社,1999.

[2]周长发.精通Visual C++图像编程[M].电子工业出版社,2000.

[3]官章全,刘加明.Visual  C++6.0类库大全[M].电子工业出版社,1999.

 

 

 

## 连接符与# 符

##连接符号由两个井号组成,其功能是在带参数的宏定义中将两个子串(token)联接起来,从而形成一个新的子串。但它不可以是第一个或者最后一个子串。所谓的子串 (token)就是指编译器能够识别的最小语法单元。具体的定义在编译原理里有详尽的解释,但不知道也无所谓。同时值得注意的是#符是把传递过来的参数当成字符串进行替代。下面来看看它们是怎样工作的。这是MSDN上的一个例子。

假设程序中已经定义了这样一个带参数的宏:
#define paster( n ) printf( "token" #n " = %d", token##n )

同时又定义了一个整形变量:
int token9 = 9;

现在在主程序中以下面的方式调用这个宏:
paster( 9 );

那么在编译时,上面的这句话被扩展为:
printf( "token" "9" " = %d", token9 );

注意到在这个例子中,paster(9);中的这个”9”被原封不动的当成了一个字符串,与”token”连接在了一起,从而成为了token9。而#n也被”9”所替代。

可想而知,上面程序运行的结果就是在屏幕上打印出token9=9

 


#include "stdafx.h"
#using <mscorlib.dll>

using namespace std;
 
int   main(void){
 short In, out[16];

 cin >> In;
 for(int i = 0; i < 16; i++){
  out[i] = ((In & (short)1)? 1:0);
  In = In >> 1;
 }
 
 for(int i = 15; i >= 0; i--)
  cout << out[i];
 cout << endl;
}

 

原创粉丝点击