熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

用Visual C++實現帶陰影彈出窗口的技術

2013-11-13 09:42:22  來源: .NET編程 

  一.問題的提出

   在WINDOWS的WINHELPER幫助系統中大量使用一類帶陰影的彈出窗口 這類窗口非常簡潔並具有立體感它們用來顯示一些只讀信息此類彈出窗口不同於一般的窗口它們沒有標題和滾動桿但都具有帶陰影的邊框 並且其窗口的大小隨顯示字符串多少而自動調節當顯示信息彈出之後任何來自鍵盤或鼠標的消息都將導致彈出窗口的消失 然而WINDOWS API接口中沒有現成的函數來實現此項功能即使是最新版的 VISUAL C++ MFC也沒有提供現成的類和函數來實現帶陰影的此類窗口為此筆者基於面向對象的程序設計思想從CWnd派生一個新類來實現這個功能並且將該類窗口的所有函數完全封裝在一起使用就像調用 MessageBox()函數顯示信息一樣簡單


二.實現方法的幾個關鍵部分說明如下

  要解決怎樣畫非用戶區的問題:當WINDOWS需要創建一個窗口時它發送兩個消息WM_NCPAINT和 WM_PAINT到應用程序消息隊列WM_NCPAINT用於重畫窗口的非用戶區如標題邊框和滾動桿本程序正是響應WM_NCPAINT消息來重畫帶陰影的彈出窗口的邊框畫客戶區很簡單只需響應WM_PAINT消息處理字符的顯示即可如何動態調整彈出窗口的尺寸:大家知道在一個矩形內顯示文本串時常用函數DrawText(HDC hDCLPTSTR lpszTextint cbCountRECT FAR* lpRectUINT fuFormat)但是此時我們的帶陰影的彈出窗口並為建立當然不能利用它來顯示然而我們注意到上述函數中的最後一個參數FuFormat 它是文字格式的組合其中有一個鮮為人知的參數 DT_CALCRECT 使用這個參數字符串不顯示但它根據當前字體測量待顯示串的高度 本程序正是根據這個參數來確定彈出窗口的大小並以此建立一個隨字符串大小而變化的窗口下面給出其實現該功能的片斷:

  void CShadowWnd::ShowText(CString sText)
dcCreateDC(DISPLAYNULLNULLNULL); //創建一個顯示設備描述表
dcSelectObject(GetStockObject(SYSTEM_FONT)); //選擇字體到設備描述表
CRect rect(MAXWIDTH);// 

//獲得待顯示的字符串 sText 的實際高度和寬度並將其存入矩形rect中   

  dcDrawText(sTextrectDT_WORDBREAK|DT_CENTER|DT_CALCRECT|DT_NOPREFIX);


怎樣獲取對系統的控制權:

   在帶陰影的彈出窗口顯示之後怎樣獲取對系統的控制權使得當用戶按下鍵盤任意鍵或鼠標時都將使帶陰影的彈出窗口消失這裡采取的方法是當彈出窗口創建和顯示之後立即進入一個消息循環從應用程序隊列中獲取所有消息並判斷是否為鼠標消息或鍵盤消息如是則摧毀窗口結束並將控制權歸還給調用程序實現片斷如下:
//進入消息循環獲取全部消息控制整個系統



  MSG Msg;

  BOOL bDone;

  SetCapture();

  bDone=FALSE;

  while(!bDone)

  {

    if(PeekMessage(&MsgNULLPM_REMOVE))

      if(ssage==WM_KEYDOWN||ssage==WM_SYSKEYDOWN||

        ssage==WM_LBUTTONDOWN||ssage==WM_RBUTTONDOWN)

        bDone=TRUE;

      else

      {

        TranslateMessage(&Msg);

        DispatchMessage(&Msg);

      }

  }

  ReleaseCapture();

  DestroyWindow();

……



 
帶陰影的類 CShadowWnd 類的頭文件及其實現文件的全部細節

 

//頭文件:
#if !defined(AFX_SHADOWWND_H__BA_CC_D_ACF_F__INCLUDED_)

#define AFX_SHADOWWND_H__BA_CC_D_ACF_F__INCLUDED_

 

#if _MSC_VER >=

#pragma once

#endif // _MSC_VER >=

// ShadowWndh : header file

//

 

/////////////////////////////////////////////////////////////////////////////

// CShadowWnd window

 

class CShadowWnd : public CWnd

{

// Construction

public:

  CShadowWnd();

 

// Attributes

public:

 

// Operations

public:

 

// Overrides

  // ClassWizard generated virtual function overrides

  //{{AFX_VIRTUAL(CShadowWnd)

  public:

  virtual BOOL Create(const RECT& rect CWnd* pParentWnd);

  //}}AFX_VIRTUAL

 

// Implementation

public:

  CString m_sShowText;

  void ShowReadOnlyText(CString sText);

  CBrush m_bmpBrush;

  virtual ~CShadowWnd();

  // Generated message map functions

protected:

  //{{AFX_MSG(CShadowWnd)

  afx_msg void OnNcPaint();

  afx_msg void OnPaint();

  afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

  //}}AFX_MSG

  DECLARE_MESSAGE_MAP()

};

 

/////////////////////////////////////////////////////////////////////////////

 

//{{AFX_INSERT_LOCATION}}

// Microsoft Developer Studio will insert additional declarations immediately before the previous line

 

#endif // !defined(AFX_SHADOWWND_H__BA_CC_D_ACF_F__INCLUDED_)


 

//實現文件
}

// ShadowWndcpp : implementation file

//

 

#include stdafxh

#include Shadowh

#include ShadowWndh

 

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

 

//定義常數

 

static int aPattern[]={xAAxxAAxxAAxxAAx};//陰影位圖數組

#define SPOPUP_SHADOWWIDTH  //陰影寬度

#define SPOPUP_SHADOWHEIGHT  //陰影高度

#define MAXWIDTH   //顯示字符矩形的最大寬度

 

/////////////////////////////////////////////////////////////////////////////

// CShadowWnd

 

CShadowWnd::CShadowWnd()

{

  CBitmap bmp;

  bmpCreateBitmap((void* )aPattern);//創建一個陰影位圖

  m_bmpBrushCreatePatternBrush(&bmp); //創建一把陰影刷

 

}

 

CShadowWnd::~CShadowWnd()

{

}

 

 

BEGIN_MESSAGE_MAP(CShadowWnd CWnd)

  //{{AFX_MSG_MAP(CShadowWnd)

  ON_WM_NCPAINT()

  ON_WM_PAINT()

  ON_WM_CREATE()

  //}}AFX_MSG_MAP

END_MESSAGE_MAP()

 

 

/////////////////////////////////////////////////////////////////////////////

// CShadowWnd message handlers

 

BOOL CShadowWnd::Create(const RECT& rect CWnd* pParentWnd)

{

  // TODO: Add your specialized code here and/or call the base class

  const char*  pClassName=AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW);

  return CWnd::CreateEx(WS_EX_STATICEDGEpClassName Shadow window WS_POPUP

    rectleftrecttoprectrightrectbottom

    pParentWnd>GetSafeHwnd()NULL);




void CShadowWnd::OnNcPaint()

{

  // TODO: Add your message handler code here

  CWindowDC dc(this);

  CRect rc;

  GetWindowRect(&rc);

 

  rcright=rcleft; //width

  rcbottom=rctop; //height

  rctop=;

  rcleft=;

  m_bmpBrushUnrealizeObject();

  CBrush* OldBrush=dcSelectObject(&m_bmpBrush);

//畫底部陰影

  dcPatBlt(rcleft+SPOPUP_SHADOWWIDTHrcbottomSPOPUP_SHADOWHEIGHT

    rcrightSPOPUP_SHADOWWIDTHSPOPUP_SHADOWHEIGHTPATCOPY);

//畫右邊陰影

  dcPatBlt(rcrightSPOPUP_SHADOWWIDTHrctop+SPOPUP_SHADOWHEIGHT

    SPOPUP_SHADOWWIDTHrcbottomPATCOPY);

  dcSelectObject(OldBrush); //restore old brush

  CBrush* pBrush=CBrush::FromHandle(GetSysColorBrush(COLOR_WINDOWFRAME));

  rcright=SPOPUP_SHADOWWIDTH;

  rcbottom=SPOPUP_SHADOWHEIGHT;

  dcFrameRect(rcpBrush); //畫邊框

  // Do not call CWnd::OnNcPaint() for painting messages

}

 

void CShadowWnd::OnPaint()

{

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

  

  // TODO: Add your message handler code here

  CRect rect;

  GetClientRect(&rect);

  rectleft+=; recttop+=;

  rectright=SPOPUP_SHADOWWIDTH;

  rectbottom=SPOPUP_SHADOWHEIGHT;

  dcSetTextColor(RGB());//設置顯示文本顏色

  dcDrawText(m_sShowTextrectDT_WORDBREAK|DT_NOPREFIX);

  // Do not call CWnd::OnPaint() for painting messages

}

 

void CShadowWnd::ShowReadOnlyText(CString sText)

{

  m_sShowText=sText; //存入顯示字符串

  CDC dc;

  dcCreateDC(DISPLAYNULLNULLNULL); //創建一個顯示設備描述表

  dcSelectObject(GetStockObject(SYSTEM_FONT)); //選擇字體到設備描述表

  CRect rect(MAXWIDTH);

//獲得待顯示的字符串 sText 的實際高度和寬度

  dcDrawText(sTextrectDT_WORDBREAK|DT_CENTER|DT_CALCRECT|DT_NOPREFIX);

//為矩形留些余量

  rectright+=*SPOPUP_SHADOWWIDTH;

  rectbottom+=*SPOPUP_SHADOWHEIGHT;

  this>Create(rect);//創建窗口

  this>ShowWindow(SW_SHOW); //顯示窗口

  this>UpdateWindow(); //立刻更新窗口

//進入消息循環獲取全部消息控制整個系統

  MSG Msg;

  BOOL bDone;

  SetCapture();

  bDone=FALSE;

  while(!bDone)

  {

    if(PeekMessage(&MsgNULLPM_REMOVE))

      if(ssage==WM_KEYDOWN||ssage==WM_SYSKEYDOWN||

        ssage==WM_LBUTTONDOWN||ssage==WM_RBUTTONDOWN)

        bDone=TRUE;

      else

      {

        TranslateMessage(&Msg);

        DispatchMessage(&Msg);

      }

  }

  ReleaseCapture();

  DestroyWindow();

 

}

 

int CShadowWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

  if (CWnd::OnCreate(lpCreateStruct) == )

    return ;

  

  // TODO: Add your specialized creation code here

  CenterWindow();

  return ;

}


 

使用方法:

   將該類增加到一個項目文件中

在你欲使用函數的類(一般為視類或框架窗口類)中增加一個成員變量(如:CshadowWnd m_ShadowWnd)當需要使用帶陰影的彈出窗口顯示信息時調用成員函數(如: m_ShadowWndShowText(String sText)即可無須考慮其實現細節 


   本程序在Visual C++ 環境下編譯通過

    此例也說明了對於WINDOWS 下的程序設計必須掌握OOP 方法同時也體現   出VISUAL C++ MFC類庫的強大功能


From:http://tw.wingwit.com/Article/program/net/201311/11375.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.