告别曾经我已不再彷徨:孙鑫VC视频教程笔记之第九课“程序外观修改及工具栏状态栏编程”

来源:百度文库 编辑:偶看新闻 时间:2024/04/29 03:33:43
1.      在窗口创建之前修改窗口外观:

The framework calls PreCreateWindow just prior to creating the window. By modifying the CREATESTRUCT parameter to PreCreateWindow, your application can change the attributes used to create the window.

 

修改窗口的标题:通过修改CREATESTRUCT结构体中的lpszName,但是注意,FWS_ADDTOTITLE is an MFC-specific style that instructs the framework to add the document title to the window’s caption,所以必须将FWS_ADDTOTITLE从现有的style中去除FWS_ADDTOTITLE即使cs.style & ~FWS_ADDTOTITLE

 

对于窗口的类型和大小,是在创建窗口的时候设定的,而窗口的图标,光标,背景是在设计窗口设计类的时候的设定的,是由MFC底层代码设计,但可以自己创建窗口类,然后让系统按照自己定义的窗口类执行。将以下代码放在CMainFrame类的PreCreateWindow函数中添加:

WNDCLASS wndcls;

      wndcls.cbClsExtra=0;

      wndcls.cbWndExtra=0;

wndcls.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH); //设置窗口背景为黑色

      wndcls.hCursor=LoadCursor(NULL,IDC_CROSS);

      wndcls.hIcon=LoadIcon(NULL,IDI_WARNING);

      wndcls.hInstance=AfxGetInstanceHandle();

      //因为MFC本身也有DefWindowProc函数,但参数不一致,所以还是调用win32的函数

wndcls.lpfnWndProc=::DefWindowProc; //不想修改系统操作,所以调用系统默认的回调函数

      wndcls.lpszClassName="style test";

      wndcls.lpszMenuName=NULL;

      wndcls.style=CS_HREDRAW | CS_VREDRAW;

     

      RegisterClass(&wndcls);

cs.lpszClass="style test"; //按照自己的设计创建

 

运行以上代码后发现窗口图标改变了,但光标和背景没有改变,这是因为上述代码修改是框架类,光标和背景属于View类,所以还要在View类中PreCreateWindow修改。在实现上述代码后,在CView的PreCreateWindow函数中添加如下代码就可以实现修改光标和背景颜色的目的:

cs.lpszClass="style test"; //修改光标和背景

也可以通过以下方式实现:

cs.lpszClass=AfxRegisterWndClass(NULL,LoadCursor(NULL,IDC_CROSS),(HBRUSH)GetStockObject(BLACK_BRUSH),0);

 

注:所以在CMainFrame类中只能修改的是Icon

随意如果采用这种代码实现,编写的代码较多,会比较麻烦,有一种替代的方法:

cs.lpszClass=AfxRegisterWndClass(NULL,0,0,LoadIcon(NULL,IDI_WARNING));

 

2.      在窗口创建之后修改窗口的外观:

窗口创建之后修改窗口外观一般在CMainFrame类的OnCreate函数中

SetWindowLong(m_hWnd,GWL_STYLE,WS_OVERLAPPEDWINDOW); //文档的标题也去掉了

 

下面一种实现是从现有的窗口风格中去除某一种属性:

LONG currentStyle=GetWindowLong(m_hWnd,GWL_STYLE); //得到现有窗口的风格

SetWindowLong(m_hWnd,GWL_STYLE,currentStyle & ~WS_MAXIMIZEBOX ); 去除了最大化框

 

//在创建窗口后修改图标

SetClassLong(m_hWnd,GCL_HICON,(LONG)LoadIcon(NULL,IDI_WARNING));

 

//在创建窗口后修改光标和背景(注:以下代码在CView的OnCreate函数中实现:)

SetClassLong(m_hWnd,GCL_HBRBACKGROUND,(LONG)GetStockObject(BLACK_BRUSH)); //设置背景颜色

SetClassLong(m_hWnd,GCL_HCURSOR,(LONG)LoadCursor(NULL,IDC_CROSS)); //设置光标

 

3.      加载外部导入的图标:

LoadIcon如果加载的是系统图标,则第一个参数是null,但如果是自己的图标,则必须取得实例句柄。MAKEINTRESOURCE宏将资源号转换为字符指针类型

HICON m_hIcon=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_ICON1));

 

      //theApp在别的cpp文件中定义,则必须在本cpp中进行extern CStyleApp theApp声明

HICON m_hIcon=LoadIcon(theApp.m_hInstance,MAKEINTRESOURCE(IDI_ICON2));

 

HICON m_hIcon=LoadIcon(AfxGetApp()->m_hInstance,MAKEINTRESOURCE(IDI_ICON3));

 

4.      工具栏:

给栏上的图标间加上分隔符:按住鼠标左键拖动分隔符后的图标一小段距离即可。

删除栏上的图标:将指定图标拖出工具栏即可。

创建工具栏:在MSDN说明中提供两种方法

Visual C++ provides you with two methods to create a toolbar. To create a toolbar resource using the Resource Editor, follow these steps:

  1. Create a toolbar resource.
  2. Construct the CToolBar object.
  3. Call the Create (or CreateEx) function to create the Windows toolbar and attach it to the CToolBar object.
  4. Call LoadToolBar to load the toolbar resource.

//创建自己的工具栏,具体的创建过程参看MSDN中的CToolBar部分,以下代码模仿向导自动创建的toolbar(代码也是在CMainFrame类的OnCreate函数中)

首先创建ToolBar的资源m_newToolBar

//以下代码放在CMainFrame类的OnCreate函数中:

if (!m_newToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_LEFT| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||!m_newToolBar.LoadToolBar(IDR_TOOLBAR1))

      {

           TRACE0("Failed to create toolbar\n");

            return -1;      // fail to create

      }

      m_newToolBar.EnableDocking(CBRS_ALIGN_ANY); //使新的toolbar可停靠

EnableDocking(CBRS_ALIGN_ANY); //使MainFrame可停靠,因为此段代码已经有了,所以省去

DockControlBar(&m_newToolBar); //是新的toolbar停靠在MainFrame上

 

Otherwise, follow these steps:

  1. Construct the CToolBar object.
  2. Call the Create (or CreateEx) function to create the Windows toolbar and attach it to the CToolBar object.
  3. Call LoadBitmap to load the bitmap that contains the toolbar button images.
  4. Call SetButtons to set the button style and associate each button with an image in the bitmap.

 

显示和隐藏工具栏:

//第一种方法:

      if(m_newToolBar.IsWindowVisible()) //工具栏也是一个窗口

      {

           m_newToolBar.ShowWindow(SW_HIDE);

      }

      else

      {

           m_newToolBar.ShowWindow(SW_SHOW);

      }

      RecalcLayout(TRUE); //整个工具栏所在的控制栏显示或消失

      DockControlBar(&m_newToolBar); //将新的toolbar停靠在MainFrame上

     

      //第二种方法,这种方法是最好的,一行代码实现了上面的功能

ShowControlBar(&m_newToolBar,!m_newToolBar.IsWindowVisible(),FALSE);

 

5.      状态栏:

向导创建状态栏是在CMainFrame类的OnCreate函数中实现的,代码如下:

if (!m_wndStatusBar.Create(this) ||                               !m_wndStatusBar.SetIndicators(indicators,  //indicators

             sizeof(indicators)/sizeof(UINT)))

      {

           TRACE0("Failed to create status bar\n");

           return -1;      // fail to create

}
其中indicators是一个指示器数组,它在CMainFrame的源文件中定义:

static UINT indicators[] =

{

      //以下这些资源在string table中定义

      ID_SEPARATOR,           // status line indicator

 

      IDS_TIMER,  //自定义

      IDS_PROGRESS, //自定义

     

      ID_INDICATOR_CAPS,

      ID_INDICATOR_NUM,

      ID_INDICATOR_SCRL,

};

该指示器表示了在状态栏中显示的许多小面板

 

以下代码实现在状态栏上显示当前时间(该函数也是在OnCreate函数中实现):

CTime currentTime=CTime::GetCurrentTime();

      CString strTime=currentTime.Format("%Y-%m-%d %H:%M:%S");

      CClientDC dc(this);

      CSize size=dc.GetTextExtent(strTime);

int idx=m_wndStatusBar.CommandToIndex(IDS_TIMER); //在不知道索引的前提下

//SetPaneInfo函数是设置面板的style,size等

m_wndStatusBar.SetPaneInfo(idx,IDS_TIMER,SBPS_NORMAL,size.cx); //使宽度合适

      //SetPaneText函数是在指定的面板上显示内容

m_wndStatusBar.SetPaneText(idx,strTime);

 

6.      进度栏:

创建类的成员函数:CProgressCtrl m_progress;

创建水平进度条

m_progress.Create(WS_CHILD|WS_VISIBLE|PBS_SMOOTH,CRect(100,100,200,120),this,IDS_PROGRESS);

      垂直进度条

m_progress.Create(WS_CHILD|WS_VISIBLE|PBS_VERTICAL,CRect(100,100,120,220),this,IDS_PROGRESS);

      m_progress.SetRange(0,100); //设置范围

m_progress.SetStep(10); //设置步进长度

 

将创建的进度栏放在状态栏的指定编号的面板上(以下代码放在OnPaint函数中):

CRect rect;

      m_wndStatusBar.GetItemRect(2,&rect); //得到状态栏上指定面板的矩形大小

      if(!m_progress.m_hWnd)

      m_progress.Create(WS_CHILD|WS_VISIBLE|PBS_SMOOTH,rect,&m_wndStatusBar,IDS_PROGRESS);

      else

           m_progress.MoveWindow(rect); //如果已经创建,则只需要将进度条移动到指定矩形框内

      m_progress.SetRange(0,100);

m_progress.SetStep(10);

注:上述代码没有放在CMainFrame类的OnCreate函数中是因为OnCreate函数创建好的时候窗口上的控件还没有创建好,所以想得到状态栏上指定面板的矩形大小时候,会取不到值(可以想象成状态栏也是窗口上的一个控件)。

 

将鼠标在视图上移动时对应的x,y坐标时时显示在状态栏上

在CView类的OnMouseMove函数中添加:

CString location;

      location.Format("x=%d,y=%d",point.x,point.y);

      方法1:

((CMainFrame*)GetParent())->m_wndStatusBar.SetPaneText(0,location,TRUE);

      方法2:

SetMessageText在MSDN中的解释是这样的:Call this function to place a string in the status-bar pane that has an ID of 0. This is typically the leftmost, and longest, pane of the status bar.

      ((CMainFrame*)GetParent())->SetMessageText(location);

      方法3:

GetMessageBar在MSDN中解释:Call this member function to get a pointer to the status bar.

((CMainFrame*)GetParent())->GetMessageBar()->SetWindowText(location);

 

7.      为程序添加启动画面:

Project->Add To Project->Components and Controls->Visual C++ component->Splash screen

修改启动画面的等待时间,其中在函数OnCreate函数有设置:SetTimer(1, 1000, NULL);

利用上述的向导自动添加了一个新类,CSplashWnd,并且自动在CMainFrame类中的OnCreate函数中添加了CSplashWnd::ShowSplashScreen(this),也就是将启动画面添加到了运行程序框架类中了。