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

原创作者: cc

最近我们在开发一个项目的过程中,遇到一个问题,我想也是很多人曾经遇到过的问题:比如有的成员擅长于用Microsoft Visual C++进行开发工作,有的成员可能对于Borland C++ Builder 进行开发工作,两种编译器符合C++标准的程序不同,所以在C++语言本身有些不同,更麻烦的是进行界面方面的开发工作,它们的差别就更大了,VC的MFC消息机制,C++ Builder的VCL(不知对不对,这个俺不熟悉).因为我们要开发一个类似于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 :<?xml:namespace prefix = st1 />     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.

转载于:https://www.cnblogs.com/cc011/archive/2005/07/07/188005.html

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

  1. C++builder中简易计算器的界面设计

    下面来介绍一下如何在C++builder中设计一个简易的计算器界面,并实现简单的数学计算,具体步骤如下: 1.首先打开C++builder6.0软件(也可以是高级版本,但我一般习惯用6.0版本的,这个 ...

  2. 解决win10 VC++6.0 应用程序无法正常运行 0xc0000142

    解决win10 VC++6.0 应用程序无法正常运行 0xc0000142 本文转载自:http://blog.csdn.net/w_9449/article/details/52864135,具体方 ...

  3. VC中海量文件读写类设计与应用(转)

    VC中海量文件读写类设计与应用   沈瑞冰 摘要 本文阐述了海量文件读写的一般方法,并分析了该方法中存在的内存耗尽问题和解决办法,并就此设计了一个海量文件读写类,封装了海量文件读写操作,最后给出了一个 ...

  4. VC中海量文件读写类设计与应用

    VC中海量文件读写类设计与应用 文件操作是应用程序最为基本的功能之一,Win32 API和MFC均提供有支持文件处理的函数和类,常用的有Win32 API的CreateFile().WriteFile ...

  5. 基于MATLAB与VC混合编程的数字均衡器设计

    1.概述 随着数字化技术的快速.深入发展,人们对数字化电子产品所产生的图像.图形以及声音等质量的要求越来越高.在实时数字处理过程中,与D/A和A/D转换相关的模拟信号重构过程是决定数字系统输出质量的关 ...

  6. [转]VC无负担实现XP风格界面

    VC无负担实现XP风格界面 有件事情必须说一下,按照上面的方法,test.exe必须先调用InitCommonControls函数(已经废除,不建议使用)或者InitCommonControlsEx函 ...

  7. 解决 WPF 绑定集合后数据变动界面却不更新的问题(使用 ObservableCollection)

    解决 WPF 绑定集合后数据变动界面却不更新的问题 独立观察员 2020 年 9 月 9 日 在 .NET Core 3.1 的 WPF 程序中打算用 ListBox 绑定显示一个集合(满足需求即可, ...

  8. 解决 WPF 绑定集合后数据变动界面却不更新的问题

    解决 WPF 绑定集合后数据变动界面却不更新的问题 独立观察员 2020 年 9 月 9 日 在 .NET Core 3.1 的 WPF 程序中打算用 ListBox 绑定显示一个集合(满足需求即可, ...

  9. 基于html人事管理报告,基于C++builder的课程设计报告 (人事管理系统)

    内容介绍 原文档由会员 bshhty 发布 C++builder课程设计 ( 人事信息管理系统 ) 12页 7000余字 资料包含:完整课程设计报告,源代码等相关设计资料.本课程设计为RAR个文件. ...

最新文章

  1. 给HttpClient添加请求头(HttpClientFactory)
  2. 数据中心新认证出现,UPTIME面临挑战
  3. python程序设计下载_Python程序设计
  4. DWA论文解析(CurvatureVelovityMethod)(3)
  5. python圆柱体_python绘制圆柱体的方法
  6. vs下C# WinForm 解决方案里面生成的文件都是什么作用?干什么的?
  7. matlab转换为exe文件,MATLAB文件转为exe可执行文件(package使用)
  8. 拓端tecdat|R语言分段回归数据分析案例报告
  9. 电子通信协议之CAN总线协议篇
  10. PC端如何双开/多开微信(实测可用)
  11. matlab求极限分布,中心极限定理的Matlab演示
  12. 吴恩达深度学习笔记(五)
  13. iOS中 断点下载详解 韩俊强的博客
  14. 敏捷开发 — Story/Defect
  15. Nodelist转化问题。
  16. 电脑蓝屏,睿频导致CPU温度过高解决方法
  17. 雪花算法的原理和实现Java
  18. 【XML和Java】手写Java程序引用xsd验证xml
  19. Swagger3 API接口文档规范课程(Java1234)(内含教学视频+源代码)
  20. 年薪30w还是白菜价?大数据工程师凭什么?

热门文章

  1. python实现rar解压和压缩
  2. 先进工艺22nm FDSOI和FinFET简介
  3. 2021年危险化学品经营单位主要负责人考试题库及危险化学品经营单位主要负责人考试内容
  4. 【水汐の计算机网络】 实验1小记
  5. 解决win10,64位系统下 PL2303 USB转串口驱动问题
  6. String简单介绍
  7. 国学入门书要目及其读法(梁启超)
  8. 注定与众不同_没有原因的数据注定会使我们失败
  9. 年月日软件测试用例的设计,实验三日期题白盒测试用例设计.doc
  10. 图解最常用的 10 个机器学习算法