• 用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.

     

     

  • 相关阅读:
    人件阅读笔记之三
    明日计划:团队开发Fooks第十天
    明日计划:团队开发Fooks第九天
    明日计划:团队开发Fooks第八天
    明日计划:团队开发Fooks第七天
    明日计划:团队开发Fooks第六天
    优先队列
    KMP
    django-中间件
    Ajax--参数,csrf跨站请求伪造,serialize(),上传文件formdata
  • 原文地址:https://www.cnblogs.com/cc011/p/188005.html
Copyright © 2020-2023  润新知