效果:
只实现了对BUTTON的换肤 不过其他的控件基本原理是一样的吧~!
代码有点乱 并且有些部分的设计还不是很合理
帖出来就是希望各位大侠们批评指教
Skin.h
#pragma once
#include <map>
void InstallSkin(HINSTANCE hInst);
#if defined(_PRIVATE_DECLARE_)
class CSkinButton
{
private:
static std::multimap<HWND,CSkinButton*> s_HWND2Class;
static LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
CSkinButton();
~CSkinButton();
void Draw();
WNDPROC m_OldProc;
DWORD m_Style;
DWORD m_Check;
bool m_isHighLight;
bool m_isDefault;
bool m_isPressed;
bool m_isFocus;
bool m_isPushButton;
HWND m_hWnd;
public:
static void Install(HWND hWnd);
};
#endif
Skin.cpp
#define _PRIVATE_DECLARE_
#include "skin.h"
#include <WindowsX.h>
#include "Resource.h"
HHOOK g_hSKinHook = 0;
HINSTANCE g_hInst = 0;
std::multimap<HWND,CSkinButton*> CSkinButton::s_HWND2Class;
CSkinButton::CSkinButton()
: m_isHighLight(false)
, m_isDefault(false)
, m_isPressed(false)
, m_isFocus(false)
, m_isPushButton(true)
{
}
CSkinButton::~CSkinButton()
{
SetWindowLongPtr(m_hWnd,GWLP_WNDPROC,(LONG_PTR)m_OldProc);
s_HWND2Class.erase(m_hWnd);
}
void CSkinButton::Install(HWND hWnd)
{
if(s_HWND2Class.find(hWnd)==s_HWND2Class.end())
{
CSkinButton*inst=new CSkinButton;
s_HWND2Class.insert(std::pair<HWND,CSkinButton*>(hWnd,inst));
inst->m_hWnd=hWnd;
inst->m_OldProc=(WNDPROC)SetWindowLongPtr(hWnd,GWLP_WNDPROC,(LONG_PTR)WndProc);
}
}
LRESULT CSkinButton::WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LONG lReturn;
std::multimap<HWND,CSkinButton*>::iterator pair=s_HWND2Class.find(hWnd);
ASSERT(pair!=s_HWND2Class.end());
CSkinButton*self=pair->second;
switch (uMsg)
{
case BM_SETSTYLE: // 按钮风格改变
self->m_isDefault=((wParam&BS_DEFPUSHBUTTON)!=0);
self->m_isPushButton=((wParam&BS_PUSHBUTTON)!=0);
self->m_Style=wParam;
self->Draw();
break;
case BM_SETSTATE: // 设置按钮状态
lReturn = (LONG) CallWindowProc(self->m_OldProc, hWnd, uMsg, wParam, lParam);
self->m_isPressed=(wParam!=FALSE);
self->Draw();
return lReturn;
case BM_SETCHECK: // 设置选中状态
lReturn = (LONG) CallWindowProc(self->m_OldProc, hWnd, uMsg, wParam, lParam);
self->m_Check=wParam;
self->Draw();
return lReturn;
case WM_SETTEXT: // 设置窗口文本
lReturn = (LONG) DefWindowProc(hWnd, uMsg, wParam, lParam);
self->Draw();
return lReturn;
case WM_PAINT: // 窗口重画
lReturn = (LONG) DefWindowProc(hWnd, uMsg, wParam, lParam);
self->Draw();
return lReturn;
case WM_DESTROY: // 窗口销毁
lReturn = (LONG) CallWindowProc(self->m_OldProc, hWnd, uMsg, wParam, lParam);
delete self;
return lReturn;
case WM_MOUSEMOVE: // 窗口移动
if ( !self->m_isHighLight )
{
self->m_isHighLight=true;
self->Draw();
// 追踪鼠标移出消息一次
TRACKMOUSEEVENT Tme;
Tme.cbSize = sizeof(TRACKMOUSEEVENT);
Tme.dwFlags = TME_LEAVE;
Tme.hwndTrack = hWnd;
TrackMouseEvent(&Tme);
}
break;
case WM_MOUSELEAVE: // 鼠标移出
if (self->m_isHighLight)
{
self->m_isHighLight=false;
self->Draw();
}
break;
case WM_SETFOCUS: // 获得焦点
self->m_isFocus=true;
self->Draw();
break;
case WM_KILLFOCUS: // 丢失焦点
self->m_isFocus=false;
self->Draw();
break;
}
// 调用原来的回调函数
lReturn = (LONG) CallWindowProc(self->m_OldProc, hWnd, uMsg, wParam, lParam);
return lReturn;
}
void CSkinButton::Draw()
{
HDC hDC=GetWindowDC(m_hWnd);
RECT rectWnd;
GetWindowRect(m_hWnd,&rectWnd);
rectWnd.right -= rectWnd.left;
rectWnd.bottom -= rectWnd.top;
rectWnd.left = rectWnd.top = 0;
HBITMAP hBmp=LoadBitmap(g_hInst,MAKEINTRESOURCE(IDB_BUTTON));
HDC hMemDC=CreateCompatibleDC(hDC);
SelectBitmap(hMemDC,hBmp);
int idx=0;
if(m_isDefault)
idx=4;
if(m_isHighLight)
idx=1;
if(m_isPressed)
idx=2;
if(!IsWindowEnabled(m_hWnd))
idx=3;
const int roundw=4;
const int roundh=4;
const int bmpw=18;
const int bmph=21;
idx*=bmph;
BitBlt( hDC, 0, 0, roundw, roundh,
hMemDC, 0, idx+0, SRCCOPY);
BitBlt( hDC, 0, rectWnd.bottom-roundh, roundw, roundh,
hMemDC, 0, idx+bmph-roundh, SRCCOPY);
BitBlt(hDC, rectWnd.right-roundw, 0, roundw, roundh,
hMemDC, bmpw-roundw, idx+0, SRCCOPY);
BitBlt(hDC, rectWnd.right-roundw, rectWnd.bottom-roundh, roundw, roundh,
hMemDC, bmpw-roundw, idx+bmph-roundh, SRCCOPY);
StretchBlt( hDC, 0, roundh, roundw, rectWnd.bottom-roundh*2,
hMemDC, 0, idx+roundh, roundw, bmph-roundh*2, SRCCOPY);
StretchBlt( hDC, rectWnd.right-roundw, roundh, roundw, rectWnd.bottom-roundh*2,
hMemDC, bmpw-roundw, idx+roundh, roundw, bmph-roundh*2, SRCCOPY);
StretchBlt( hDC, roundw, 0, rectWnd.right-roundw*2, roundh,
hMemDC, roundw, idx+0, bmpw-roundw*2, roundh, SRCCOPY);
StretchBlt( hDC, roundw, rectWnd.bottom-roundh, rectWnd.right-roundw*2, roundh,
hMemDC, roundw, idx+bmph-roundh, bmpw-roundw*2, roundh, SRCCOPY);
StretchBlt( hDC, roundw, roundh, rectWnd.right-roundw*2, rectWnd.bottom-roundh*2,
hMemDC, roundw, idx+roundh, bmpw-roundw*2, bmph-roundh*2, SRCCOPY);
//if(m_isFocus)
//{
// RECT r;
// r.left=r.top=3;
// r.right=rectWnd.right-3;
// r.bottom=rectWnd.bottom-3;
// DrawFocusRect(hDC, &r );
//}
SetBkMode(hDC,TRANSPARENT);
HFONT hFont=GetWindowFont(m_hWnd);
SelectFont(hDC,hFont);
char szWinText[0x1000];
GetWindowText(m_hWnd,szWinText,0x1000);
DrawText(hDC,szWinText,strlen(szWinText),&rectWnd,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
DeleteDC(hMemDC);
DeleteObject(hBmp);
}
LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
LONG lReturn;
if( nCode == HC_ACTION )
{
PCWPSTRUCT pcwps=(PCWPSTRUCT)lParam;
switch(pcwps->message)
{
case WM_CREATE:
{
CHAR szClass[MAX_PATH];
GetClassName(pcwps->hwnd, szClass, MAX_PATH);
if ( lstrcmpi(szClass, "Button") == 0 )
{
lReturn = GetWindowLong(pcwps->hwnd, GWL_STYLE);
switch (lReturn & SS_TYPEMASK)
{
case BS_DEFPUSHBUTTON: // 默认按钮
case BS_PUSHBUTTON: // 普通按钮
CSkinButton::Install(pcwps->hwnd);
break;
}
}
}
break;
}
}
return CallNextHookEx(g_hSKinHook, nCode, wParam, lParam);
}
void InstallSkin(HINSTANCE hInst)
{
g_hInst=hInst;
if (g_hSKinHook)
UnhookWindowsHookEx(g_hSKinHook);
g_hSKinHook = SetWindowsHookEx(WH_CALLWNDPROC, HookProc, 0, GetCurrentThreadId());
}
VC7.1工程
下载
posted on 2006-09-20 03:14
shaker(太子) 阅读(2871)
评论(0) 编辑 收藏 引用 所属分类:
C++