用Hook解决在VC++与C++Builder方面界面设计的一些问题

 

                                                               Hook解决在VC++C++Builder方面界面设计的一些问题

                                                                                                                                                                 原创作者: cc

 

       最近我们在开发一个项目的过程中,遇到一个问题,我想也是很多人曾经遇到过的问题:比如有的成员擅长于用Microsoft Visual C++进行开发工作,有的成员可能对于Borland C++ Builder 进行开发工作,两种编译器符合C++标准的程序不同,所以在C++语言本身有些不同,更麻烦的是进行界面方面的开发工作,它们的差别就更大了,VCMFC消息机制,C++ BuilderVCL(不知对不对,这个俺不熟悉).因为我们要开发一个类似于XP中的资源管理器左边的用于导航作用的不错的界面,因为我们项目的界面大部分是用CB完成的,而这个东西好像不是那么容易做的呀,我对C++ Builder 不太熟悉,着实让人头疼的呀!下面的这张图片是我写的最终结果,只要稍加修改就可以在C++ Builder中使用,因为我用的是 : SDK+STL+C++,所以只要稍加修改,最主要的是我在这其中所使用的string ,必须改为AnsiString ,还有几个小地方改一下就行了.

        

       无意之间我想到可以用Hook机制来实现我在VC中写的关于界面部分代码很容易的移植到CB中去,我知道CB中好像可以直接用MFC的代码,不过我想没有多少去做的呀!我的思想基于这种想法:

       不管是VC++ 还是 C++ Builder 只要提供一个窗口的句柄就可以了, 上面的图上的那个是在一个static 的控件中, 而在C++ Builder中我用的Panel,效果还不错的哟!在程序启动以后,需要安装一个基于WH_GETMESSAGE 的钩子,同时传入一个需要寄生的窗口的句柄,还有一个父窗口的句柄,同时还有一个用户自定义的消息,例如:

       #define WM_EXTENDUI_MESSAGE WM_USER+1             

       CWndHook::InstallHook(::GetDlgItem(m_hWnd,IDC_TEST),m_hWnd,WM_EXTENDUI_MESSAGE);

       第三个参数是用于单击的时候发送消息通知父窗口.这时就可以了.当程序结束时,只要调用一下:

       CWndHook::UninstallHook();

      

       是不是很容易!用起来容易的东西,其实幕后有很多的工作需要做的了,下面是我的全部代码:

 

/************************************************************************

Module : WndHook.h

Purpose: When I need write some codes about user interface both working at VC++ and Borland C++

               Builder well,I use the Hook mechanism instead of creating new ActiveX

               control.Install a hook and then parasitize at other control such as

               static control to draw ......It's a very good idea.

Date :     7/5/2005

Author:   Chengang

Last Modified : 7/7/2005

History :

 

************************************************************************/

 

#include <string>

#include <vector>

#include <algorithm>

using namespace std;

 

#ifndef __WNDHOOK__H

#define __WNDHOOK__H

 

#pragma  once

 

//The state of ExtendUI item

#define          EXT_UI_COLLPSED              0x01

#define          EXT_UI_EXPANDED             0x02

#define          EXT_UI_MOUSEHOVER       0x04

 

 

//The state of subItem

#define          ITEM_NORMAL                     0x01

#define          ITEM_MOUSEHOVER           0x02

#define          ITEM_CLICKED              0x04

 

//the background color.

#define          GROUP_BKGND_COLOR           RGB(214,223,247)

#define          TOTAL_BKGND_COLOR            RGB(111,139,222)

#define          TEXT_COLOR                        RGB(33,93,198)

#define          WIDTH(rect)                            (rect.right-rect.left)

#define          HEIGHT(rect)                    (rect.bottom-rect.top)

 

#define          BOUND_MARGIN                 5

#define          GROUP_MARGIN                  8

 

#define          ICON_WIDTH                        16

#define          ICON_HEIGHT                       16

             

class CUIManager;

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

class CWndHook {

 

public:

       //Install a Hook

       static      void InstallHook(HWND    hWndHost,HWND hWndParent,UINT uMsg);

 

       //Uninstall the hook

       static      void UninstallHook();

       //Hook function

       static      LRESULT CALLBACK WindowHook(int code,WPARAM wParam,LPARAM lParam);

 

protected:

       static HHOOK            ms_hHook ;

       static HWND              ms_hWndHost ;

       static CUIManager ms_uiMana;

};

 

 

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

class CUISubItem {

 

public:

       UINT            m_uBitmapID ; //the icon of this subitem

       string             m_strText ; //the text of this subitem

       RECT           m_rect    ; //the rect of the subitem

       UINT            m_uState  ; //the state of each item.

       CUISubItem(string const&,UINT uBitID );

       ~CUISubItem();

 

public:

       void        Draw(HDC hDC,RECT const& rect)    ; //draw this subItem .

       void        OnMouseMove(POINT const& pt);

       BOOL          OnLButtonDown(POINT const& pt); 

};

 

 

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

class CUIGroup {

 

public :

       string             m_strCaption ; //the caption of the group item

       vector<CUISubItem*>              m_subItem ; //this group item can includ more than one subitem.

       UINT            m_uItemState ; //state of this group item

       RECT           m_rect;

protected:

       void        GradientFill(HDC hDC ,RECT const& rect);

public:

       CUIGroup(string const& str,UINT   uState =EXT_UI_EXPANDED);

       ~CUIGroup();

       void        Draw(HDC hDC,RECT const& rect)  ;//first draw itself ,then draw each subitem .

 

       int                OnLButtonDown(POINT const& pt) ;

       void        OnMouseMove(POINT const& pt);

};

 

 

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

class CUIManager {

 

public:

       vector<CUIGroup*>   m_groupItem ; //UIManager manage all the group item.

       RECT                         m_rectTotal  ;//The region of this ExtendUI

       HWND                       m_hWnd ; //parent hwnd ,used to post message

       UINT                          m_uMessage ; //this message used to notify the parent window that

                                                                //which item wat clicked ,the wParam is the group NO

                                                                //the start index is 0 ,the lParam is the sub item index

                                                                //the start index also is 0.

       CUIManager(){}

       ~CUIManager();

 

public:

       void Draw(HDC hDC,RECT const& rect);

 

       //add a new group

       void AddGroup(string const&,UINT uState =EXT_UI_EXPANDED);

 

       //add a new item to special group

       void AddItem(int nGroupIndex,string const&,UINT);

 

       void OnLButtonDown(POINT const& pt);

       void OnMouseMove(POINT const& pt);

      

};

#endif //end of __WNDHOOK__H

 

 

/************************************************************************

Module : WndHook.cpp

Purpose: When I need write some codes both working at VC++ and Borland C++

               Builder,I use the Hook mechanism instead of creating new ActiveX

               control.Install a hook and then  parasitize other control such as

               static control to extend the function.It's a very good idea.

Date :     7/5/2005

Author:   Chengang

Last Modified : 7/7/2005

History :

 

************************************************************************/

#include "..\StdAfx.h"

#include "..\Resource.h"

#include "WndHook.h"

#include "DCEx.h"

#include "draw.h"

 

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

HHOOK CWndHook::ms_hHook = NULL ;

HWND  CWndHook::ms_hWndHost = NULL ;

CUIManager CWndHook::ms_uiMana;

 

 

 

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

void CWndHook::InstallHook(HWND hWndHost,HWND hWndParent,UINT uMsg) {

 

       //if hWndHost or hWndParent is NULL,don't install this hook

       if (NULL == hWndHost || NULL == hWndParent ||ms_hHook !=NULL)

              return ;

       ms_hWndHost = hWndHost;

 

       //the user-defined message ,used to notify the parent window when a sub item was clicked.

       ms_uiMana.m_uMessage  = uMsg ;

       ms_uiMana.m_hWnd = hWndParent;

       string str="我的电脑";

       ms_uiMana.AddGroup(str);

       str="添加/删除程序";

       ms_uiMana.AddGroup(str,EXT_UI_COLLPSED);

 

       ms_uiMana.AddItem(0,string("控制面板"),IDB_MIDL);

       ms_uiMana.AddItem(0,string("用户/帐户"),IDB_BAG);

       ms_uiMana.AddItem(0,string("管理工具"),IDB_BUTTERFLY);

 

       ms_uiMana.AddItem(1,string("控制面板"),IDB_CDAUDIO);

       ms_uiMana.AddItem(1,string("用户/帐户"),IDB_MIDL );

       ms_uiMana.AddItem(1,string("管理工具"),IDB_BUTTERFLY);

       ms_uiMana.AddItem(1,string("控制面板"),IDB_CDAUDIO);

       ms_uiMana.AddItem(1,string("控制面板"),IDB_CDAUDIO);

       ms_uiMana.AddItem(1,string("用户/帐户"),IDB_MIDL );

       ms_uiMana.AddItem(1,string("管理工具"),IDB_BUTTERFLY);

       ms_uiMana.AddItem(1,string("控制面板"),IDB_CDAUDIO);

       ms_uiMana.AddItem(1,string("用户/帐户"),IDB_MIDL );

       ms_uiMana.AddItem(1,string("管理工具"),IDB_BUTTERFLY);

 

       ms_uiMana.AddItem(1,string("控制面板"),IDB_MIDL);

       ms_uiMana.AddItem(1,string("用户/帐户"),IDB_BAG);

       ms_uiMana.AddItem(1,string("管理工具"),IDB_BUTTERFLY);

 

       ms_hHook = ::SetWindowsHookEx(WH_GETMESSAGE,WindowHook,(HINSTANCE)::GetModuleHandle(NULL),::GetCurrentThreadId());

}

 

 

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

void CWndHook::UninstallHook() {

 

       if (ms_hHook)

              ::UnhookWindowsHookEx(ms_hHook);

       ms_hHook = NULL;

}

 

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

//Hook function

LRESULT CALLBACK CWndHook::WindowHook(int code,WPARAM wParam,LPARAM lParam) {

 

       MSG  *pMsg = (MSG*)lParam;

      

       if (HC_ACTION == code ) {                                      

                     if (::IsWindow(ms_hWndHost)){

                           

                                   RECT    rectWindow ;

                                   ::GetWindowRect(ms_hWndHost,&rectWindow);

                                   ::MapWindowPoints(NULL,ms_hWndHost,(LPPOINT)&rectWindow,2);

                                  

                                   POINT  pt;

                                   ::GetCursorPos(&pt);

                                   ::ScreenToClient(ms_hWndHost,&pt);

                                  

if (WM_PAINT==pMsg->message||WM_MOUSEMOVE == pMsg->message &&  PtInRect(&rectWindow,pt) ||WM_LBUTTONDOWN == pMsg->message && PtInRect(&rectWindow,pt) ||WM_MOVE==pMsg->message||WM_NCACTIVATE==pMsg->message ||WM_NCPAINT==pMsg->message) {

 

                                          HDC hDC = ::GetDC(ms_hWndHost);

 

                                          CDCEx dc(hDC,rectWindow,TRUE,ms_hWndHost);

                                          if (WM_LBUTTONDOWN == pMsg->message) {

                                                

                                                 ms_uiMana.OnLButtonDown(pt);

                                          }

                                          if (WM_MOUSEMOVE == pMsg->message) {

 

                                                 ms_uiMana.OnMouseMove(pt);

                                          }

                                          ms_uiMana.Draw(dc,rectWindow);

                            }

                     }

       }

 

       return ::CallNextHookEx(ms_hHook,code,wParam,lParam);

}

 

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

CUIGroup::CUIGroup(string const& str,UINT uState) {

 

       m_uItemState = uState ;

       m_strCaption = str;

}

 

 

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

CUIGroup::~CUIGroup() {

 

       vector<CUISubItem*>::iterator iter = m_subItem.begin() ;

       for ( ; iter != m_subItem.end() ; iter++) {

 

              CUISubItem * pItem = *iter;

              delete pItem;

       }

       m_subItem.clear();

}

 

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

void CUIGroup::Draw(HDC hDC,RECT const& rect) {

 

       int nBkMode = ::SetBkMode(hDC,TRANSPARENT);

 

       //draw the frame of this group

       RECT    rectText = rect;

       RECT    rectGrad =rect;

 

       ::DrawText(hDC,m_strCaption.c_str(),-1,&rectText,DT_CALCRECT);

       int nHeight ,nWidth ;

       nHeight = HEIGHT(rectText);

       nWidth  = WIDTH(rectText);

 

       m_rect = rect;

       m_rect.bottom = m_rect.top+nHeight+BOUND_MARGIN;

 

       RECT    rectRectangle = rect;

       rectRectangle.top+=BOUND_MARGIN;

       CBrushDCEx       brush(hDC,GROUP_BKGND_COLOR);

       CPenDCEx   pen(hDC,RGB(255,255,255));

       ::RoundRect(hDC,rectRectangle.left,rectRectangle.top,rectRectangle.right,rectRectangle.bottom,5,5);

       rectText = rect ;

 

       ::InflateRect(&rectText,-BOUND_MARGIN,-BOUND_MARGIN);

       rectText.right = rectText.left+nWidth;

       rectText.bottom = rectText.top+nHeight+BOUND_MARGIN;

 

       rectGrad.bottom = rectGrad.top+nHeight+BOUND_MARGIN*2;

       rectGrad.left = rect.left ;

       rectGrad.right = rect.left+WIDTH(rect);

       GradientFill(hDC,rectGrad);

 

       HBITMAP hBitmap = LoadBitmap(GetModuleHandle(NULL),MAKEINTRESOURCE(m_uItemState&EXT_UI_EXPANDED?IDB_UP:IDB_DOWN));

       BITMAP       bm ;

       GetObject(hBitmap,sizeof(BITMAP),&bm);

       HDC             hMemDC = ::CreateCompatibleDC(hDC);

       HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC,hBitmap);

       ::BitBlt(hDC,rect.right-bm.bmWidth,rect.top,bm.bmWidth,bm.bmHeight,hMemDC,0,0,SRCCOPY);

       SelectObject(hMemDC,hOldBitmap);

       ::DeleteDC(hMemDC);

       ::DeleteObject(hBitmap);

      

       COLORREF clrTextColor = RGB(0,0,123);

       if (m_uItemState & EXT_UI_MOUSEHOVER)

              clrTextColor = MakeXPColor(clrTextColor,0.1);

       int nOldTextColor = ::SetTextColor(hDC,clrTextColor);

       ::DrawText(hDC,m_strCaption.c_str(),-1,&rectText,DT_SINGLELINE|DT_VCENTER|DT_CENTER|DT_TOP);

       ::SetTextColor(hDC,nOldTextColor);

 

       //draw each sub item

       RECT    rectSubItem =rectRectangle;

       rectSubItem.top+=nHeight+BOUND_MARGIN*2;

       rectSubItem.bottom =nHeight+BOUND_MARGIN;

      

       if (m_uItemState & EXT_UI_EXPANDED) {

      

              vector<CUISubItem*>::iterator iter = m_subItem.begin() ;

              for (; iter != m_subItem.end(); iter++) {

 

                     CUISubItem* pItem = *iter ;

                     rectSubItem.bottom = rectSubItem.top+nHeight+BOUND_MARGIN;

                     pItem->Draw(hDC,rectSubItem);

                     rectSubItem.top +=nHeight+BOUND_MARGIN;

              }

       }

       ::SetBkMode(hDC,nBkMode);

}

 

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

//if clicked sub item in this group ,return the index of sub item ,else return

//-1,indicate not click at any subitem in this group

int CUIGroup::OnLButtonDown(POINT const& pt) {

 

       int nReturn = -1;

       if (PtInRect(&m_rect,pt)) {

 

              if (m_uItemState & EXT_UI_EXPANDED)

                     m_uItemState = EXT_UI_COLLPSED;

              else

                     m_uItemState = EXT_UI_EXPANDED;

       } else {

 

              vector<CUISubItem*>::iterator iter = m_subItem.begin() ;

              for (int i= 0; iter != m_subItem.end(); iter++,i++) {

 

                     CUISubItem* pItem = *iter ;

                     if (pItem->OnLButtonDown(pt))

                            return i;

              }

       }

       return     nReturn;

}

 

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

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

void CUISubItem::Draw(HDC hDC,RECT const& rect) {

 

       //if text is null ,return

       if (m_strText.empty()) return ;

 

       //first draw the icon

       HFONT hFont = NULL ,hOldFont = NULL;

       if (m_uState & ITEM_CLICKED) {

 

              //if this item was clicked ,draw the underline text ,so indicate

              //this item was clicked.creae new font that with underlined propery

              hFont = CreatePointSizeFont(hDC,8,string("Arial"),TRUE);

              hOldFont = (HFONT)::SelectObject(hDC,hFont);

       }

       COLORREF clrText = TEXT_COLOR;

       if (m_uState & ITEM_MOUSEHOVER) {

 

              clrText = MakeXPColor(clrText,0.4);

       }

 

       int nOldTextColor = ::SetTextColor(hDC,clrText);

 

       //draw the text

       RECT    rectText = rect;

       rectText.left = rectText.left+BOUND_MARGIN*6;

       ::DrawText(hDC,m_strText.c_str(),-1,&rectText,DT_SINGLELINE|DT_VCENTER);

      

       if (m_uBitmapID) {

 

              DrawBitmap(hDC,m_uBitmapID,rect.left+BOUND_MARGIN,rect.top);

       }

 

       m_rect = rect ;

       ::SetTextColor(hDC,nOldTextColor);

 

       if (hOldFont) ::SelectObject(hDC,hOldFont);

       if (hFont)         ::DeleteObject(hFont);

}

 

CUISubItem::CUISubItem(string const& str,UINT uBitmap) {

      

       m_strText = str;

       m_uBitmapID = uBitmap ;

       m_uState = ITEM_NORMAL;

}

 

CUISubItem::~CUISubItem() {

}

 

void CUISubItem::OnMouseMove(POINT const& pt) {

 

       if (PtInRect(&m_rect,pt)) {

             

              HCURSOR hCursor = ::LoadCursor(GetModuleHandle(NULL),MAKEINTRESOURCE(IDC_HAND));

              ::SetCursor(hCursor);

              m_uState = ITEM_MOUSEHOVER;

       }

       else

              m_uState = ITEM_NORMAL;

}

 

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

//if the mouse in this item 's rect return TRUE ,else return FALSE

BOOL CUISubItem::OnLButtonDown(POINT const& pt) {

 

       if (PtInRect(&m_rect,pt)) {

 

              m_uState |= ITEM_CLICKED;

              return TRUE ;

       } else {

              m_uState = ITEM_NORMAL;

              return FALSE ;

       }

       return FALSE;

}

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

 

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

//Gradient fill

void CUIGroup::GradientFill(HDC hDC ,RECT const& rect){

 

       BYTE    byRed=255;

       BYTE    byGreen = 255;

       BYTE    byBlue = 255;

       for (int x= rect.left,nStep=0;x<rect.right ;x++,nStep++) {

             

              int nInc = 0 ;

              if (nStep < 5)

                     nInc = nStep==1?3:(nStep==4?1:5-nStep);

              else if (rect.right - x < 5)

                     nInc =rect.right-x==0?3:(rect.right-x==5?1:(rect.right-x==4?1:6-(rect.right-x)));

              CPenDCEx dc(hDC,RGB(byRed,byGreen,byBlue));

              ::MoveToEx(hDC,x,rect.top+nInc,NULL);

              ::LineTo(hDC,x,rect.bottom);

 

              if (0 == nStep%2)

                     byRed--;

              if (0 == nStep %4)

                     byGreen--;

              if (0 == nStep %5)

                     byBlue--;

       }

}

 

 

void CUIGroup::OnMouseMove(POINT const& pt) {

 

       if (PtInRect(&m_rect,pt)) {

 

              m_uItemState |= EXT_UI_MOUSEHOVER;

              HCURSOR hCursor = ::LoadCursor(GetModuleHandle(NULL),MAKEINTRESOURCE(IDC_HAND));

              ::SetCursor(hCursor);

       }

       else {

 

              m_uItemState&=~EXT_UI_MOUSEHOVER;

       }

 

       vector<CUISubItem*>::iterator iter = m_subItem.begin() ;

       for (; iter != m_subItem.end(); iter++) {

 

              CUISubItem* pItem = *iter ;

              pItem->OnMouseMove(pt);

       }

}

 

 

void CUIManager::OnMouseMove(POINT const& pt) {

 

       vector<CUIGroup*>::iterator it = m_groupItem.begin();

       for (int i =0 ; it != m_groupItem.end() ; it++,i++ ) {

 

              CUIGroup* pGroup ;

              pGroup= *it;

              pGroup->OnMouseMove(pt);

       }

}

 

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

void CUIManager::Draw(HDC hDC,RECT const& rect) {

 

       if (NULL == hDC)      return ;

 

       //draw the background color

       HBRUSH      hBrush = ::CreateSolidBrush(TOTAL_BKGND_COLOR);

       ::FillRect(hDC,&rect,hBrush);

       ::DeleteObject(hBrush);

       if (m_groupItem.empty())

              return ;

 

       //calculate each region of each group

 

       int nHeight = HEIGHT(rect) - 2*BOUND_MARGIN - (m_groupItem.size()>1?(m_groupItem.size()-1)*GROUP_MARGIN:0);

 

       //if there was not enough space to drawing ,return

       if (nHeight < 0)

              return ;

       int nEachHeight = nHeight/m_groupItem.size();

 

 

       //draw each group item

       vector<CUIGroup*>::iterator it = m_groupItem.begin();

       RECT    rectEach = rect;

       rectEach.left = rect.left + BOUND_MARGIN;

       rectEach.top  = rect.top  + BOUND_MARGIN;

       rectEach.right -=BOUND_MARGIN;

 

       string strFont="Arial";

       HFONT hFont = CreatePointSizeFont(hDC,8,strFont,FALSE);

       HFONT hOldFont = (HFONT)::SelectObject(hDC,hFont);

 

       //calculate the height of each line

       RECT    rectText ;

       ::DrawText(hDC,"dummy",-1,&rectText,DT_CALCRECT);

 

       for (int i =0 ; it != m_groupItem.end() ; it++,i++ ) {

 

              CUIGroup* pGroup ;

              pGroup= *it;

              if (pGroup->m_uItemState & EXT_UI_EXPANDED)

                     rectEach.bottom = rectEach.top+((pGroup->m_subItem.size()+1)*(HEIGHT(rectText)+BOUND_MARGIN*2));

              else

                     rectEach.bottom = rectEach.top+20;

              pGroup->Draw(hDC,rectEach);

              rectEach.top+=rectEach.bottom+GROUP_MARGIN*2;

       }

 

       ::SelectObject(hDC,hOldFont);

       ::DeleteObject(hFont);

}

 

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

CUIManager::~CUIManager() {

 

       vector<CUIGroup*>::iterator iter = m_groupItem.begin();

       CUIGroup* pGroup = NULL;

       while (iter != m_groupItem.end()) {

 

              pGroup = *iter;

              delete pGroup ;

              iter++;

       }

      

       m_groupItem.clear() ;

}

 

 

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

//add a new group

void CUIManager::AddGroup(string const& str,UINT uState) {

 

       CUIGroup* pGroup = new CUIGroup(str,uState);

       m_groupItem.push_back(pGroup);

}

 

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

void CUIManager::AddItem(int nGroupIndex,string const& str,UINT uBitmap) {

 

       if (nGroupIndex > m_groupItem.size()-1)

              return ;

 

       CUIGroup* pGroup = m_groupItem[nGroupIndex];

      

       CUISubItem* pItem = new CUISubItem(str,uBitmap);

       pGroup->m_subItem.push_back(pItem);

}

 

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

void CUIManager::OnLButtonDown(POINT const& pt) {

 

       int nReturnValue  = -1;

       vector<CUIGroup*>::iterator it = m_groupItem.begin();

       for (int i =0 ; it != m_groupItem.end() ; it++,i++ ) {

 

              CUIGroup* pGroup ;

              pGroup= *it;

              nReturnValue = pGroup->OnLButtonDown(pt) ;

 

              if (nReturnValue != -1){

                    

                     ::PostMessage(m_hWnd,m_uMessage,(WPARAM)i,(LPARAM)nReturnValue);

              }

       }

}

 

 

 

 

 

 

 

 

 

 

/************************************************************************

Module : draw.h

Provide many lesser class to convenient drawing.

Author: ChenGang

Date:      4/1/2005

Last modified :7/7/2005

History :

              1. 7/7/2005 : Add DrawBitmap function for draw bitmap in special

                 bitmap more conveience.

*************************************************************************/

 

 

#ifndef CLR_NONE

#define CLR_NONE 0xffffffffL

#endif

 

#pragma  once

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

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

class CPenDCEx

{

protected:

    HPEN   m_pen;

    HDC m_hDC;

    HPEN m_hOldPen;

       int           m_nWidth;

       int           m_nPenStyle;

 

public:

    CPenDCEx (HDC hDC, COLORREF crColor = CLR_NONE,int nWidth =1,int nPenStyle = PS_SOLID)

       {  

              m_hDC = hDC;

              m_pen =CreatePen (nPenStyle, nWidth, crColor);

              m_hOldPen = (HPEN)::SelectObject (m_hDC, m_pen);

              m_nWidth = nWidth ;

              m_nPenStyle = nPenStyle ;

       }

   ~CPenDCEx ()

   {         

         ::SelectObject (m_hDC, m_hOldPen);

         DeleteObject(m_pen);

   }

 

    void Color (COLORREF crColor,int nWidth)

       {

              ::SelectObject (m_hDC, m_hOldPen);

              DeleteObject(m_pen);

              m_pen = CreatePen (m_nPenStyle, nWidth, crColor);

              m_hOldPen = (HPEN)::SelectObject (m_hDC, m_pen);

       }

};

 

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

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

class CBrushDCEx

{

protected:

    HBRUSH m_brush;

    HDC m_hDC;

    HBRUSH m_hOldBrush;

 

public:

    CBrushDCEx (HDC hDC, COLORREF crColor = CLR_NONE)

       {

              m_hDC = hDC;

              if ( crColor == CLR_NONE ) m_brush =(HBRUSH) GetStockObject (NULL_BRUSH);

              else                       m_brush =CreateSolidBrush (crColor);

              m_hOldBrush = (HBRUSH)::SelectObject (m_hDC, m_brush);

       }

 

   ~CBrushDCEx ()

   {

         ::SelectObject (m_hDC, m_hOldBrush);

         DeleteObject(m_brush);

   }

 

   void Color (COLORREF crColor) {

 

              DeleteObject(m_brush);

              if ( crColor == CLR_NONE ) m_brush = (HBRUSH)GetStockObject (NULL_BRUSH);

              else                       m_brush = CreateSolidBrush (crColor);

              m_hOldBrush = (HBRUSH)::SelectObject (m_hDC, m_brush);

              ::SelectObject (m_hDC, m_hOldBrush);

   }

};

 

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

//Use the algorithm ,to calculate the color is very pretty.

COLORREF MakeXPColor(COLORREF cl, double factor)

{

       if(factor>0.0&&factor<=1.0){

              BYTE red,green,blue,lightred,lightgreen,lightblue;

              red = GetRValue(cl);

              green = GetGValue(cl);

              blue = GetBValue(cl);

              lightred = (BYTE)((factor*(255-red)) + red);

              lightgreen = (BYTE)((factor*(255-green)) + green);

              lightblue = (BYTE)((factor*(255-blue)) + blue);

              cl = RGB(lightred,lightgreen,lightblue);

       }

      

       return(cl);

}

 

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

HFONT CreatePointSizeFont(HDC hDC, short shFontSize,string strFontFacename,BOOL fUnderline)

{

       HFONT hFont;

 

       LOGFONT          lf;

       ZeroMemory(&lf,sizeof(LOGFONT));

       lf.lfUnderline = fUnderline ;

       lf.lfHeight = -MulDiv(shFontSize,GetDeviceCaps(hDC,LOGPIXELSY),72);

       strcpy(lf.lfFaceName,strFontFacename.c_str());

       hFont = CreateFontIndirect(&lf) ;

       return hFont;

}

 

 

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

void DrawBitmap(HDC hDC ,UINT nResID,int x ,int y ) {

 

       HBITMAP hBitmap = LoadBitmap(GetModuleHandle(NULL),MAKEINTRESOURCE(nResID));

       BITMAP       bm ;

       GetObject(hBitmap,sizeof(BITMAP),&bm);

       HDC             hMemDC = ::CreateCompatibleDC(hDC);

       HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC,hBitmap);

       ::BitBlt(hDC,x,y,bm.bmWidth,bm.bmHeight,hMemDC,0,0,SRCCOPY);

       ::SelectObject(hMemDC,hOldBitmap);

       ::DeleteDC(hMemDC);

       ::DeleteObject(hBitmap);

}

 

 

 

/*****************************************************************************/

/*                                                                                                                                  */

/* FileName :DCEx.h                                                                                                    */

/*                                                                                                                                  */

/* Purpose : By the famous CMemDC ,I desien CDCEx as a win32 version instead */

/* of CMemDC (By MFC).Use the double buffer technology,to increase the       */

/* velocity of drawing.                                                                                             */

/*                                                                                                                                  */

/* Author : ChenGang                                                                                             */

/* Date :  2/16/2005                                                                                             */

/*                                                                                                                                  */

/* Last Modified : 2/16/2005                                                                                  */

/*****************************************************************************/

 

class CDCEx 

{

private:

       HBITMAP                  m_hBitmap;

       HBITMAP                  m_hOldBitmap;

       HDC                           m_hDC ;

       HDC                           m_hOldDC;

       RECT                  m_rect;

       BOOL                 m_bNeedRelease ;

       HWND                m_hWndNeedRelease;

 

public:

       CDCEx(HDC hDC ,const RECT     rect,BOOL bNeedRelease=FALSE,HWND hWndNeedRelease=NULL)

       {

       //     ATLASSERT(hDC != NULL) ;

              m_hOldDC = hDC;           

              m_bNeedRelease = bNeedRelease ;

              m_hWndNeedRelease = hWndNeedRelease;

 

              m_rect = rect;

              m_hDC = CreateCompatibleDC(hDC);

              LPtoDP(hDC,(LPPOINT)&m_rect,2);

             

              m_hBitmap = CreateCompatibleBitmap(hDC,m_rect.right - m_rect.left ,m_rect.bottom - m_rect.top);

              m_hOldBitmap = (HBITMAP)SelectObject(m_hDC,m_hBitmap);

 

              SetMapMode(m_hDC,GetMapMode(m_hOldDC));

             

              SIZE      size;

              GetWindowExtEx(hDC,&size);

              SetWindowExtEx(m_hDC,size.cx,size.cy,NULL);

 

              GetViewportExtEx(hDC,&size);

              SetViewportExtEx(m_hDC,size.cx,size.cy,NULL);

 

              DPtoLP(hDC,(LPPOINT)&m_rect,2);

              SetWindowOrgEx(m_hDC,m_rect.left,m_rect.top,NULL);

             

              //First fill whole background rect.

              HBRUSH      hBrush =CreateSolidBrush(GetBkColor(hDC));

              FillRect(m_hDC,&m_rect,hBrush);         

              DeleteObject(hBrush);

       }

 

 

       ~CDCEx()

       {

 

              BitBlt(m_hOldDC,m_rect.left,m_rect.top,m_rect.right - m_rect.left,m_rect.bottom - m_rect.top,m_hDC,m_rect.left,m_rect.top,SRCCOPY);                          

              SelectObject(m_hDC,m_hOldBitmap);   

             

              if (m_hBitmap)

                     DeleteObject(m_hBitmap);

              DeleteDC(m_hDC);

              if (m_bNeedRelease)

                     ::ReleaseDC(m_hWndNeedRelease,m_hOldDC);

 

             

              m_hDC =      NULL;

              m_hBitmap = NULL;

              m_hOldBitmap = NULL;

       }

       operator HDC()

       {

              return m_hDC ;

       }

 

};

              这种想法希望能起到抛砖引玉的作用,不要砸到自己..........

              以上就是全部的代码,如果有什么不清楚或者有指教的地方,可以给我E-mail:chengang_011@163.com.

 

 

posted @ 2005-07-07 17:09  CC  阅读(3959)  评论(4编辑  收藏  举报