原文链接:http://blog.csdn.net/hurryboylqs/article/details/7853429
前言:
大家知道,win32窗口的内置滚动自绘是个非常棘手的问题,在写这篇文章之前首先感谢下CSDN的mynamelj,他写的那个SkinSB开源的时候我就开始使用来美化一般win32窗口的滚动条,很好用,但是最近有想把自己的应用迁移到x64平台的想法,所以必须把全部源码编译成64位的版本,以便能在win 64位下获得最佳性能,好了废话不多说,继续往下看。
改进SkinSB:
当时遇到两大难题,第一个是API钩子库detours在X64下用不了,第二个是skinsb自有源码小部分不适应64位。
对于第一个难题,当时到微软网站看了下其实detours 3.0版本有支持64位的,但是不是免费的,收费$9999一套,相当于7万RMB左右,这费用我等实在付不起,只好另找其他方法,经同事介绍mhook库,稍微看了下也是开源的,使用方法也很方便,就两个函数,一个Mhook_SetHook加载API钩子,一个Mhook_Unhook
首先申明自己自定义的钩子函数:
//包含头文件
#include "../mhook/mhook.h"
#include "../skinsb/skinsb.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
static int (WINAPI * TrueSetScrollInfo)(HWND hwnd, int fnBar, LPCSCROLLINFO lpsi, BOOL bRedraw) = SetScrollInfo;
static BOOL (WINAPI * TrueGetScrollInfo)(HWND hwnd, int fnBar, LPSCROLLINFO lpsi) = GetScrollInfo;
static int (WINAPI * TrueSetScrollPos)(HWND hwnd, int nBar, int nPos, BOOL bRedraw) = SetScrollPos;
static int (WINAPI * TrueGetScrollPos)(HWND hwnd, int nBar) = GetScrollPos;
static BOOL (WINAPI * TrueSetScrollRange)(HWND hwnd, int nBar, int nMinPos, int nMaxPos, BOOL bRedraw) = SetScrollRange;
static BOOL (WINAPI * TrueGetScrollRange)(HWND hwnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos) = GetScrollRange;
static BOOL (WINAPI * TrueShowScrollBar)(HWND hwnd, int nBar, BOOL bShow) = ShowScrollBar;
static BOOL (WINAPI * TrueEnableScrollBar)(HWND hwnd, UINT wSBflags, UINT wArrows) = EnableScrollBar;
int WINAPI SetScrollInfoD(HWND hwnd, int fnBar, LPCSCROLLINFO lpsi, BOOL bRedraw)
{
if( SkinSB_IsValid(hwnd) )
return SkinSB_SetScrollInfo(hwnd, fnBar, lpsi, bRedraw);
else
return TrueSetScrollInfo(hwnd, fnBar, lpsi, bRedraw);
}
BOOL WINAPI GetScrollInfoD(HWND hwnd, int fnBar, LPSCROLLINFO lpsi)
{
if( SkinSB_IsValid(hwnd) )
return SkinSB_GetScrollInfo(hwnd, fnBar, lpsi);
else
return TrueGetScrollInfo(hwnd, fnBar, lpsi);
}
int WINAPI SetScrollPosD(HWND hwnd, int nBar, int nPos, BOOL bRedraw)
{
if( SkinSB_IsValid(hwnd) )
return SkinSB_SetScrollPos(hwnd, nBar, nPos, bRedraw);
else
return TrueSetScrollPos(hwnd, nBar, nPos, bRedraw);
}
int WINAPI GetScrollPosD(HWND hwnd, int nBar)
{
if( SkinSB_IsValid(hwnd) )
return SkinSB_GetScrollPos(hwnd, nBar);
else
return TrueGetScrollPos(hwnd, nBar);
}
BOOL WINAPI SetScrollRangeD(HWND hwnd, int nBar, int nMinPos, int nMaxPos, BOOL bRedraw)
{
if( SkinSB_IsValid(hwnd) )
return SkinSB_SetScrollRange(hwnd, nBar, nMinPos, nMaxPos, bRedraw);
else
return TrueSetScrollRange(hwnd, nBar, nMinPos, nMaxPos, bRedraw);
}
BOOL WINAPI GetScrollRangeD(HWND hwnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos)
{
if( SkinSB_IsValid(hwnd) )
return SkinSB_GetScrollRange(hwnd, nBar, lpMinPos, lpMaxPos);
else
return TrueGetScrollRange(hwnd, nBar, lpMinPos, lpMaxPos);
}
BOOL WINAPI ShowScrollBarD(HWND hwnd, int nBar, BOOL bShow)
{
if( SkinSB_IsValid(hwnd) )
return SkinSB_ShowScrollBar(hwnd, nBar, bShow);
else
return TrueShowScrollBar(hwnd, nBar, bShow);
}
BOOL WINAPI EnableScrollBarD(HWND hwnd, UINT wSBflags, UINT wArrows)
{
if( SkinSB_IsValid(hwnd) )
return SkinSB_EnableScrollBar(hwnd, wSBflags, wArrows);
else
return TrueEnableScrollBar(hwnd, wSBflags, wArrows);
}
加载钩子:
BOOL CSkinSBDemoApp::InitInstance()
{
// 加载钩子
Mhook_SetHook(&(PVOID&)TrueSetScrollInfo, SetScrollInfoD);
Mhook_SetHook(&(PVOID&)TrueGetScrollInfo, GetScrollInfoD);
Mhook_SetHook(&(PVOID&)TrueSetScrollPos, SetScrollPosD);
Mhook_SetHook(&(PVOID&)TrueGetScrollPos, GetScrollPosD);
Mhook_SetHook(&(PVOID&)TrueSetScrollRange,SetScrollRangeD);
Mhook_SetHook(&(PVOID&)TrueGetScrollRange,GetScrollRangeD);
Mhook_SetHook(&(PVOID&)TrueShowScrollBar, ShowScrollBarD);
Mhook_SetHook(&(PVOID&)TrueEnableScrollBar,EnableScrollBarD);
CSkinSBDemoDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
// dismissed with OK
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
// dismissed with Cancel
}
// Since the dialog has been closed, return FALSE so that we exit the
// application, rather than start the application's message pump.
return FALSE;
}
程序退出时卸载钩子:
<SPAN style="FONT-SIZE: 14px">int CSkinSBDemoApp::ExitInstance()
{
// 卸载钩子
Mhook_Unhook(&(PVOID&)TrueSetScrollInfo);
Mhook_Unhook(&(PVOID&)TrueGetScrollInfo);
Mhook_Unhook(&(PVOID&)TrueSetScrollPos);
Mhook_Unhook(&(PVOID&)TrueGetScrollPos);
Mhook_Unhook(&(PVOID&)TrueSetScrollRange);
Mhook_Unhook(&(PVOID&)TrueGetScrollRange);
Mhook_Unhook(&(PVOID&)TrueShowScrollBar);
Mhook_Unhook(&(PVOID&)TrueEnableScrollBar);
return CWinApp::ExitInstance();
}</SPAN><SPAN style="FONT-SIZE: 18px">
</SPAN>
附mynamelj博客:
http://blog.csdn.net/mynamelj/article/details/3895585#comments
支持X64的SKINSB源码下载:
http://download.csdn.net/detail/hurryboylqs/4491550