581 lines
22 KiB
C++
581 lines
22 KiB
C++
#include "stdafx.h"
|
|
#include "handlers.h"
|
|
|
|
//-------------------------------------------------------------------------//
|
|
// Declare registered message vars **here**
|
|
//-------------------------------------------------------------------------//
|
|
#define __NO_APPHACKS__
|
|
//-------------------------------------------------------------------------//
|
|
// Message Handlers
|
|
//-------------------------------------------------------------------------//
|
|
|
|
// Rules for message handlers [scotthan]:
|
|
//
|
|
// (1) Use DECL_ macros to declare message handler prototype and
|
|
// table entries for message handlers below.
|
|
// (2) A message handler implementation should NOT:
|
|
// 1. call DefWindowProc or CallWindowProc directly,
|
|
// but rather use DoMsgDefault().
|
|
// 2. delete the incoming CThemeWnd* object,
|
|
// (3) A message handler SHOULD:
|
|
// 1. Honor the codepage value in the message block when
|
|
// handling messages that carry string args.
|
|
// If the codepage member is CP_WINUNICODE, the widechar
|
|
// string processing should be assumed; otherwise, multibyte
|
|
// string processing should be assumed.
|
|
// 2. If a message should not be forwarded for default processing,
|
|
// mark the message as handled using MsgHandled().
|
|
// (4) Handlers should be listed in the BEGIN/ENDMSG() block
|
|
// below in decreasing order of expected frequency.
|
|
|
|
|
|
//---------------------//
|
|
// WndProc overrides
|
|
//---------------------//
|
|
|
|
// msg handler decls:
|
|
DECL_MSGHANDLER( OnOwpPostCreate );
|
|
DECL_MSGHANDLER( OnOwpPreStyleChange );
|
|
DECL_MSGHANDLER( OnOwpPreWindowPosChanging );
|
|
DECL_MSGHANDLER( OnOwpPreWindowPosChanged );
|
|
DECL_MSGHANDLER( OnOwpPostWindowPosChanged );
|
|
DECL_MSGHANDLER( OnOwpPostSettingChange );
|
|
DECL_MSGHANDLER( OnOwpPreMeasureItem );
|
|
DECL_MSGHANDLER( OnOwpPreDrawItem );
|
|
DECL_MSGHANDLER( OnOwpPreMenuChar );
|
|
DECL_MSGHANDLER( OnOwpPostThemeChanged );
|
|
DECL_MSGHANDLER( OnOwpPreNcPaint );
|
|
DECL_MSGHANDLER( OnOwpPostNcPaint );
|
|
|
|
// handler table:
|
|
BEGIN_HANDLER_TABLE(_rgOwpHandlers)
|
|
// frequent messages
|
|
DECL_MSGENTRY( WM_NCPAINT, OnOwpPreNcPaint, OnOwpPostNcPaint )
|
|
DECL_MSGENTRY( WM_WINDOWPOSCHANGING, OnOwpPreWindowPosChanging, NULL )
|
|
DECL_MSGENTRY( WM_WINDOWPOSCHANGED, OnOwpPreWindowPosChanged, OnOwpPostWindowPosChanged )
|
|
DECL_MSGENTRY( WM_SETTINGCHANGE, NULL, OnOwpPostSettingChange )
|
|
DECL_MSGENTRY( WM_MEASUREITEM, OnOwpPreMeasureItem, NULL )
|
|
DECL_MSGENTRY( WM_DRAWITEM, OnOwpPreDrawItem, NULL )
|
|
DECL_MSGENTRY( WM_MDISETMENU, NULL, NULL )
|
|
|
|
// rare messages:
|
|
DECL_MSGENTRY( WM_MENUCHAR, OnOwpPreMenuChar, NULL )
|
|
DECL_MSGENTRY( WM_STYLECHANGING, OnOwpPreStyleChange, NULL )
|
|
DECL_MSGENTRY( WM_STYLECHANGED, OnOwpPreStyleChange, NULL )
|
|
DECL_MSGENTRY( WM_NCCREATE, NULL, NULL )
|
|
DECL_MSGENTRY( WM_CREATE, NULL, OnOwpPostCreate )
|
|
DECL_MSGENTRY( WM_NCDESTROY, NULL, NULL )
|
|
DECL_MSGENTRY( WM_THEMECHANGED, NULL, OnOwpPostThemeChanged ) // we handle in line in ThemePreWndProc()
|
|
DECL_MSGENTRY( WM_THEMECHANGED_TRIGGER, NULL, NULL ) // we handle in line in ThemePreWndProc()
|
|
END_HANDLER_TABLE()
|
|
|
|
// Note: values of high owp message must be in sync w/ table.
|
|
#define WNDPROC_MSG_LAST WM_THEMECHANGED_TRIGGER // 0x031B (alias for WM_UAHINIT)
|
|
|
|
|
|
//------------------------//
|
|
// DefDlgProc overrides
|
|
//------------------------//
|
|
|
|
// msg handler decls:
|
|
DECL_MSGHANDLER( OnDdpPostCtlColor );
|
|
DECL_MSGHANDLER( OnDdpCtlColor );
|
|
DECL_MSGHANDLER( OnDdpPrint );
|
|
DECL_MSGHANDLER( OnDdpPostInitDialog );
|
|
|
|
// handler table:
|
|
BEGIN_HANDLER_TABLE(_rgDdpHandlers)
|
|
// frequent messages:
|
|
DECL_MSGENTRY( WM_CTLCOLORDLG, NULL, OnDdpPostCtlColor )
|
|
DECL_MSGENTRY( WM_CTLCOLORSTATIC, NULL, OnDdpCtlColor)
|
|
DECL_MSGENTRY( WM_CTLCOLORBTN, NULL, OnDdpCtlColor)
|
|
DECL_MSGENTRY( WM_CTLCOLORMSGBOX, NULL, OnDdpPostCtlColor )
|
|
DECL_MSGENTRY( WM_PRINTCLIENT, NULL, OnDdpPrint )
|
|
// rare messages:
|
|
DECL_MSGENTRY( WM_INITDIALOG, NULL, OnDdpPostInitDialog )
|
|
END_HANDLER_TABLE()
|
|
|
|
// Note: values of high ddp message must be in sync w/ table.
|
|
#define DEFDLGPROC_MSG_LAST WM_PRINTCLIENT // 0x0318
|
|
|
|
|
|
//--------------------------//
|
|
// DefWindowProc override
|
|
//--------------------------//
|
|
|
|
// msg handler decls:
|
|
DECL_MSGHANDLER( OnDwpNcPaint );
|
|
DECL_MSGHANDLER( OnDwpNcHitTest );
|
|
DECL_MSGHANDLER( OnDwpNcActivate );
|
|
DECL_MSGHANDLER( OnDwpNcLButtonDown );
|
|
DECL_MSGHANDLER( OnDwpNcThemeDrawCaption );
|
|
DECL_MSGHANDLER( OnDwpNcThemeDrawFrame );
|
|
DECL_MSGHANDLER( OnDwpNcMouseMove );
|
|
DECL_MSGHANDLER( OnDwpNcMouseLeave );
|
|
DECL_MSGHANDLER( OnDwpWindowPosChanged );
|
|
DECL_MSGHANDLER( OnDwpSysCommand );
|
|
DECL_MSGHANDLER( OnDwpSetText );
|
|
DECL_MSGHANDLER( OnDwpSetIcon );
|
|
DECL_MSGHANDLER( OnDwpStyleChanged );
|
|
DECL_MSGHANDLER( OnDwpPrint );
|
|
DECL_MSGHANDLER( OnDwpPrintClient );
|
|
DECL_MSGHANDLER( OnDwpContextMenu );
|
|
|
|
// handler table:
|
|
BEGIN_HANDLER_TABLE(_rgDwpHandlers)
|
|
// frequent messages:
|
|
DECL_MSGENTRY( WM_NCHITTEST, OnDwpNcHitTest, NULL )
|
|
DECL_MSGENTRY( WM_NCPAINT, OnDwpNcPaint, NULL )
|
|
DECL_MSGENTRY( WM_NCACTIVATE, OnDwpNcActivate, NULL )
|
|
DECL_MSGENTRY( WM_NCMOUSEMOVE, OnDwpNcMouseMove, NULL )
|
|
DECL_MSGENTRY( WM_NCMOUSELEAVE, OnDwpNcMouseLeave, NULL )
|
|
DECL_MSGENTRY( WM_WINDOWPOSCHANGED, OnDwpWindowPosChanged, NULL )
|
|
DECL_MSGENTRY( WM_SYSCOMMAND, OnDwpSysCommand, NULL )
|
|
DECL_MSGENTRY( WM_NCLBUTTONDOWN, OnDwpNcLButtonDown, NULL )
|
|
DECL_MSGENTRY( WM_NCUAHDRAWCAPTION, OnDwpNcThemeDrawCaption, NULL )
|
|
DECL_MSGENTRY( WM_NCUAHDRAWFRAME, OnDwpNcThemeDrawFrame, NULL )
|
|
DECL_MSGENTRY( WM_PRINT, OnDwpPrint, NULL )
|
|
DECL_MSGENTRY( WM_PRINTCLIENT, OnDwpPrintClient, NULL )
|
|
DECL_MSGENTRY( WM_CTLCOLORMSGBOX, OnDdpPostCtlColor, NULL) // Strange: Sent to DefWindowProc, but is a Dialog message
|
|
DECL_MSGENTRY( WM_CTLCOLORSTATIC, OnDdpCtlColor, NULL)
|
|
DECL_MSGENTRY( WM_CTLCOLORBTN, OnDdpCtlColor, NULL)
|
|
// rare messages:
|
|
DECL_MSGENTRY( WM_SETTEXT, OnDwpSetText, NULL )
|
|
DECL_MSGENTRY( WM_SETICON, OnDwpSetIcon, NULL )
|
|
DECL_MSGENTRY( WM_STYLECHANGED, OnDwpStyleChanged, NULL )
|
|
DECL_MSGENTRY( WM_CONTEXTMENU, OnDwpContextMenu, NULL )
|
|
DECL_MSGENTRY( WM_THEMECHANGED_TRIGGER, NULL, NULL )
|
|
DECL_MSGENTRY( WM_NCDESTROY, NULL, NULL )
|
|
END_HANDLER_TABLE()
|
|
|
|
// Note: values of high dwp message must be in sync w/ handler table.
|
|
#define DEFWNDPROC_MSG_LAST WM_THEMECHANGED_TRIGGER // 0x031B
|
|
|
|
//---------------------------------------------------------------------------
|
|
BOOL _FindMsgHandler( UINT, MSGENTRY [], int, IN HOOKEDMSGHANDLER*, IN HOOKEDMSGHANDLER* );
|
|
BOOL _SetMsgHandler( UINT, MSGENTRY [], int, IN HOOKEDMSGHANDLER, BOOL );
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Special case hook handling
|
|
//---------------------------------------------------------------------------
|
|
|
|
//---------------------------------------------------------------------------
|
|
BOOL _IsExcludedSystemProcess( LPCWSTR pszProcess )
|
|
{
|
|
static const WCHAR* _rgszSystemProcessList[] =
|
|
{
|
|
L"lsass", // Local Security Authority sub-system
|
|
L"services", // Service Control Manager
|
|
L"svchost", // Service Host
|
|
L"mstask", // Microsoft Task Scheduler
|
|
L"dfssvc", // Distributed File System Service
|
|
L"winmgmt", // Windows Management Instrumentation
|
|
L"spoolsv", // Print Spool Service
|
|
L"msdtc", // Microsoft Distributed Transaction Co-ordinator
|
|
L"regsvc", // Remote Registry Service
|
|
L"webclnt", // Web Client
|
|
L"mspmspsv", // WMDM PMSP Service (what is this?)
|
|
L"ntvdm" // NT virtual DOS machine
|
|
};
|
|
|
|
return AsciiScanStringList( pszProcess, _rgszSystemProcessList,
|
|
ARRAYSIZE(_rgszSystemProcessList), TRUE );
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
BOOL _IsProcessOnInteractiveWindowStation() // check if we're on winsta0.
|
|
{
|
|
BOOL fRet = FALSE;
|
|
HWINSTA hWinSta = GetProcessWindowStation();
|
|
|
|
if( hWinSta != NULL )
|
|
{
|
|
DWORD cbLength = 0;
|
|
WCHAR wszName[32];
|
|
|
|
if (GetUserObjectInformationW(hWinSta, UOI_NAME, wszName, sizeof(wszName), &cbLength))
|
|
{
|
|
fRet = (0 == AsciiStrCmpI(wszName, L"winsta0"));
|
|
}
|
|
else
|
|
{
|
|
// Problem! It's either:
|
|
// - our buffer was too small (in which case it can't be winsta0)
|
|
// - or some other failure we cannot overcome anyhow
|
|
}
|
|
}
|
|
return(fRet);
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
BOOL _IsWin16App() // check if this is a 16-bit process
|
|
{
|
|
GUITHREADINFO gti;
|
|
gti.cbSize = sizeof(gti);
|
|
gti.flags = GUI_16BITTASK;
|
|
|
|
return GetGUIThreadInfo( GetCurrentThreadId(), >i ) &&
|
|
TESTFLAG(gti.flags, GUI_16BITTASK );
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
BOOL ApiHandlerInit( const LPCTSTR pszProcess, USERAPIHOOK* puahTheme, const USERAPIHOOK* puahReal )
|
|
{
|
|
// exclude known non-UI system processes
|
|
if( _IsExcludedSystemProcess( pszProcess ) )
|
|
return FALSE;
|
|
|
|
// exclude any process not hosted on winsta0.
|
|
if( !_IsProcessOnInteractiveWindowStation() )
|
|
return FALSE;
|
|
|
|
if( _IsWin16App() )
|
|
return FALSE;
|
|
|
|
// SHIMSHIM [scotthan]:
|
|
|
|
#ifdef _DEBUG
|
|
//---- temp patch against msvcmon ----
|
|
if( 0 == AsciiStrCmpI(pszProcess, L"msvcmon") )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//---- temp patch against msdev ----
|
|
if( 0 == AsciiStrCmpI(pszProcess, L"msdev") )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//---- Aid in debugging classic/themed differences: ---
|
|
if( 0 == AsciiStrCmpI( pszProcess, L"mditest1" ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
#endif
|
|
|
|
#ifndef __NO_APPHACKS__
|
|
|
|
static const WCHAR* _rgszExcludeAppList[] =
|
|
{
|
|
#ifdef THEME_CALCSIZE
|
|
// Invoking SetWindowPos from CThemeWnd::SetFrameTheme on our Post-WM_CREATE handler
|
|
// causes emacs to divide by zero after receiving meaningless rects from two
|
|
// successive calls to AdjustWindowRectEx from his WM_WINDOWPOSCHANGING handler.
|
|
// I don't believe it is related to the fact that AdjustWindowRectEx has yet
|
|
// to be implemented for themed windows (raid# 140989), but rather that the wndproc
|
|
// is not ready for a WM_WINDOWPOSCHANGING message on the abrubtly on the
|
|
// heels of a WM_CREATE handler.
|
|
L"emacs",
|
|
|
|
L"neoplanet", // 247283: We rush in to theme neoplanet's dialogs, which we almost
|
|
L"np", // immediately revoke, but not before sizing the dialog to theme-compatible
|
|
// client rect. When we withdraw, we leave it clipped. No good way to deal
|
|
// with this for beta2.
|
|
|
|
// HTML Editor++ v.8: 286676:
|
|
// This guy recomputes his nonclient area, and then AVs dereferencing a
|
|
// WM_WINDOWPOSCHANGING message under themes.
|
|
L"coffee",
|
|
#endif THEME_CALCSIZE
|
|
|
|
L"refcntr", // 205059: Corel Reference Center; lower 10% of window is clipped.
|
|
|
|
L"KeyFramerPro", // 336456: Regardless of whether themes are enabled, Boris KeyFramer Pro v.5
|
|
// does two SetWindowRgn() calls for every WM_PAINT, the first with a region,
|
|
// the next with NULL, Is the app trying to clip his painting?
|
|
// If so, this is not what SetWindowRgn was intended for, and explains why this
|
|
// app is so clunky at window resizing. Rather, SelectClipRgn is the
|
|
// correct API.
|
|
// When themes are enabled, we keep revoking and re-attatching with each
|
|
// SetWindowRgn call, so we get substantial flicker.
|
|
// The ISV should be notified of this bug.
|
|
|
|
// Applications that do custom non-client painting and hence look broken when
|
|
// themed. Our only recourse at the moment it to exclude them from non-client
|
|
// themeing so that we don't stomp whatever they are trying to do.
|
|
L"RealJBox", // 273370: Real JukeBox
|
|
L"RealPlay", // 285368: Real AudioPlayer
|
|
L"TeamMgr", // 286654: Microsoft Team Manager97
|
|
L"TrpMaker", // 307107: Rand McNally TripMaker 2000
|
|
L"StrFindr", // 307535: Rand McNally StreetFinder 2000
|
|
L"Exceed", // 276244: Hummingbird Exceed 6.2/7.0
|
|
L"VP30", // 328676: Intel Video Phone
|
|
|
|
// 313407: Groove, build 760
|
|
// Calls DefWindowProc for NCPAINT, then paints his own caption over it.
|
|
// Note: this just might work correctly if we had a DrawFrameControl hook.
|
|
L"groove", // filever 1.1.0.760, 1/22/2001 tested.
|
|
|
|
// 303756: Exclude all Lotus SmartSuite apps to provide consistency among their
|
|
// apps. All of them draw into the caption bar.
|
|
L"WordPro", // 285065: Lotus WordPro, a particularly poorly implemented app.
|
|
L"SmartCtr", // It's WordPerfect compat menu is the elephant man of modern software.
|
|
L"123w",
|
|
L"Approach",
|
|
L"FastSite",
|
|
L"F32Main",
|
|
L"Org5",
|
|
|
|
// 358337: Best Technology - GCC Developer Lite. Custom caption bar fights with Luna.
|
|
L"GCCDevL", // install point: http://www.besttechnology.co.jp/download/GDL1_0_3_6.EXE
|
|
|
|
// 360422: J Zenrin The Real Digital Map Z3(T1):Max/Min/Close buttons are overlapped on classic buttons in title bar.
|
|
L"emZmain",
|
|
|
|
// 364337: Encarta World English Dictionary: Luna system buttons are overlaid on top of app's custom ones when mousing over
|
|
L"ewed.exe",
|
|
|
|
// 343171: Reaktor Realtime Instrument: pressing the close button while themed causes this app to
|
|
// spin in a tight loop running at realtime priority, effectively hanging the machine.
|
|
// The message loop for this app is extremely timing sensitive, the additional overhead
|
|
// introduced by theming alters the timing enough to break this app.
|
|
L"Reaktor",
|
|
};
|
|
|
|
if( AsciiScanStringList( pszProcess, _rgszExcludeAppList,
|
|
ARRAYSIZE(_rgszExcludeAppList), TRUE ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
#ifdef THEME_CALCSIZE
|
|
// Winstone 99 needs modified NC_CALCSIZE behavior for Netscape or it will hang.
|
|
if ( 0 == AsciiStrCmpI( pszProcess, L"Netscape" ))
|
|
{
|
|
if (FindWindowEx(NULL, NULL, L"ZDBench32Frame", NULL) != NULL)
|
|
{
|
|
_SetMsgHandler( WM_NCCALCSIZE, _rgDwpHandlers, ARRAYSIZE(_rgDwpHandlers),
|
|
OnDwpNcCalcSize2, FALSE );
|
|
return TRUE;
|
|
}
|
|
}
|
|
#endif THEME_CALCSIZE
|
|
|
|
//-------------------------
|
|
// This AppHack was once fixed, but got broke again with
|
|
// addition of logic for partial-screen maximized windows.
|
|
//
|
|
// Something in our answer to NCCALCSIZE causes quick time player
|
|
// to continously flood its 'control' frame window's winproc with
|
|
// WM_PAINTS by repeatedly calling InvalidateRgn + UpdateWindow. My
|
|
// suspicion is that he looks at what DefWindowProc returns from
|
|
// NCCALCSIZE to determine the area he needs to manage, and when
|
|
// this doesn't hash with other SYSMET values and/or AdjustWindowRect,
|
|
// he redundantly invalidates himself,
|
|
//
|
|
// This only repros if qtp is launched w/ .mov file, works fine if
|
|
// launched without a file and then a file is loaded.
|
|
#ifdef THEME_CALCSIZE
|
|
if( 0 == AsciiStrCmpI( pszProcess, L"QuickTimePlayer" ))
|
|
{
|
|
_SetMsgHandler( WM_NCCALCSIZE, _rgDwpHandlers, ARRAYSIZE(_rgDwpHandlers),
|
|
OnDwpNcCalcSize2, FALSE );
|
|
return TRUE;
|
|
}
|
|
|
|
// SEANHI DID NOT RECEIVE THE S/W FROM APPLIB AND SO WAS UNABLE TO VERIFY THIS
|
|
// NO LONGER REPROS W/ ELIMINATION OF THEMED SYSMETS
|
|
//-------------------------
|
|
// Paradox 9 appHack for nonclient button sizes:
|
|
//
|
|
// Paradox table schema view uses DrawFrameControl to render both
|
|
// a classic toolframe (small) caption and buttons, but uses the
|
|
// themed values of SM_CYSIZE instead of SM_CYSMSIZE to size the buttons.
|
|
// This apphack redirects requests in this process for SM_CX/YSIZE to SM_CX/YSMSIZE.
|
|
if( 0 == AsciiStrCmpI( pszProcess, L"pdxwin32" ) )
|
|
{
|
|
_SetGsmHandler( SM_CXSIZE, OnGsmCxSmBtnSize );
|
|
_SetGsmHandler( SM_CYSIZE, OnGsmCySmBtnSize );
|
|
return TRUE;
|
|
}
|
|
#endif THEME_CALCSIZE
|
|
|
|
|
|
|
|
//-------------------------
|
|
#else
|
|
# pragma message("App hacks disabled")
|
|
#endif __NO_APPHACKS__
|
|
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Handler table utility functions
|
|
//---------------------------------------------------------------------------
|
|
|
|
//---------------------------------------------------------------------------
|
|
void HandlerTableInit() {}
|
|
|
|
//---------------------------------------------------------------------------
|
|
BOOL _InitMsgMask( LPBYTE prgMsgMask, DWORD dwMaskBytes, MSGENTRY* prgEntries, int cEntries,
|
|
IN OUT BOOL& fInit )
|
|
{
|
|
if( !fInit )
|
|
{
|
|
for( int i = 0; i < cEntries; i++ )
|
|
{
|
|
if( -1 == prgEntries[i].nMsg )
|
|
{
|
|
ASSERT(prgEntries[i].pnRegMsg);
|
|
// Initialize registered message entry
|
|
prgEntries[i].nMsg = *prgEntries[i].pnRegMsg;
|
|
|
|
Log(LOG_TMHANDLE, L"InitMsgMsg corrected registered msg: 0x%x", prgEntries[i].nMsg);
|
|
}
|
|
|
|
//---- ensure we set up limit on table correctly ----
|
|
ASSERT((prgEntries[i].nMsg)/8 < dwMaskBytes);
|
|
|
|
SET_MSGMASK( prgMsgMask, prgEntries[i].nMsg );
|
|
}
|
|
fInit = TRUE;
|
|
}
|
|
|
|
return fInit;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Scan of MSG table as linear array:
|
|
inline int _FindMsgHandler(
|
|
UINT nMsg,
|
|
MSGENTRY rgEntries[],
|
|
int cEntries,
|
|
OUT OPTIONAL HOOKEDMSGHANDLER* ppfnHandler,
|
|
OUT OPTIONAL HOOKEDMSGHANDLER* ppfnHandler2 )
|
|
{
|
|
ASSERT( nMsg );
|
|
ASSERT( nMsg != (UINT)-1 );
|
|
|
|
if( ppfnHandler ) *ppfnHandler = NULL;
|
|
if( ppfnHandler2 ) *ppfnHandler2 = NULL;
|
|
|
|
for( int i = 0; i < cEntries; i++ )
|
|
{
|
|
if( rgEntries[i].nMsg == nMsg )
|
|
{
|
|
// If no handler requested, return success
|
|
if( NULL == ppfnHandler && NULL == ppfnHandler2 )
|
|
return i;
|
|
|
|
// Assign outbound handler values
|
|
if( ppfnHandler ) *ppfnHandler = rgEntries[i].pfnHandler;
|
|
if( ppfnHandler2 ) *ppfnHandler2 = rgEntries[i].pfnHandler2;
|
|
|
|
// return TRUE iif caller got what he asked for.
|
|
return ((ppfnHandler && *ppfnHandler) || (ppfnHandler2 && *ppfnHandler2)) ? i : -1;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Modify existing handler
|
|
inline BOOL _SetMsgHandler(
|
|
UINT nMsg,
|
|
MSGENTRY rgEntries[],
|
|
int cEntries,
|
|
IN HOOKEDMSGHANDLER pfnHandler,
|
|
BOOL fHandler2 )
|
|
{
|
|
int i = _FindMsgHandler( nMsg, rgEntries, cEntries, NULL, NULL );
|
|
if( i >= 0 )
|
|
{
|
|
if( fHandler2 )
|
|
rgEntries[i].pfnHandler2 = pfnHandler;
|
|
else
|
|
rgEntries[i].pfnHandler = pfnHandler;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
#define CBMSGMASK(msgHigh) (((msgHigh)+1)/8 + ((((msgHigh)+1) % 8) ? 1: 0))
|
|
|
|
//---------------------------------------------------------------------------
|
|
DWORD GetOwpMsgMask( LPBYTE* prgMsgMask )
|
|
{
|
|
static BOOL _fOwpMask = FALSE; // initialized?
|
|
static BYTE _rgOwpMask[CBMSGMASK(WNDPROC_MSG_LAST)] = {0};
|
|
|
|
if( _InitMsgMask( _rgOwpMask, ARRAYSIZE(_rgOwpMask), _rgOwpHandlers, ARRAYSIZE(_rgOwpHandlers), _fOwpMask ) )
|
|
{
|
|
*prgMsgMask = _rgOwpMask;
|
|
return ARRAYSIZE(_rgOwpMask);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
DWORD GetDdpMsgMask( LPBYTE* prgMsgMask )
|
|
{
|
|
static BOOL _fDdpMask = FALSE; // initialized?
|
|
static BYTE _rgDdpMask[CBMSGMASK(DEFDLGPROC_MSG_LAST)] = {0};
|
|
|
|
if( _InitMsgMask( _rgDdpMask, ARRAYSIZE(_rgDdpMask), _rgDdpHandlers, ARRAYSIZE(_rgDdpHandlers), _fDdpMask ) )
|
|
{
|
|
*prgMsgMask = _rgDdpMask;
|
|
return ARRAYSIZE(_rgDdpMask);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
DWORD GetDwpMsgMask( LPBYTE* prgMsgMask )
|
|
{
|
|
static BOOL _fDwpMask = FALSE; // initialized?
|
|
static BYTE _rgDwpMask[CBMSGMASK(DEFWNDPROC_MSG_LAST)] = {0};
|
|
|
|
if( _InitMsgMask( _rgDwpMask, ARRAYSIZE(_rgDwpMask), _rgDwpHandlers, ARRAYSIZE(_rgDwpHandlers), _fDwpMask ) )
|
|
{
|
|
*prgMsgMask = _rgDwpMask;
|
|
return ARRAYSIZE(_rgDwpMask);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
BOOL FindOwpHandler(
|
|
UINT nMsg, HOOKEDMSGHANDLER* ppfnPre, HOOKEDMSGHANDLER* ppfnPost )
|
|
{
|
|
return _FindMsgHandler( nMsg, _rgOwpHandlers, ARRAYSIZE(_rgOwpHandlers),
|
|
ppfnPre, ppfnPost ) >= 0;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
BOOL FindDdpHandler(
|
|
UINT nMsg, HOOKEDMSGHANDLER* ppfnPre, HOOKEDMSGHANDLER* ppfnPost )
|
|
{
|
|
return _FindMsgHandler( nMsg, _rgDdpHandlers, ARRAYSIZE(_rgDdpHandlers),
|
|
ppfnPre, ppfnPost ) >= 0;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
BOOL FindDwpHandler( UINT nMsg, HOOKEDMSGHANDLER* ppfnPre )
|
|
{
|
|
HOOKEDMSGHANDLER pfnPost;
|
|
return _FindMsgHandler( nMsg, _rgDwpHandlers, ARRAYSIZE(_rgDwpHandlers),
|
|
ppfnPre, &pfnPost ) >= 0;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Performs default message processing.
|
|
LRESULT WINAPI DoMsgDefault( const THEME_MSG *ptm )
|
|
{
|
|
ASSERT( ptm );
|
|
if( ptm->pfnDefProc )
|
|
{
|
|
MsgHandled( ptm );
|
|
if( MSGTYPE_DEFWNDPROC == ptm->type )
|
|
return ptm->pfnDefProc( ptm->hwnd, ptm->uMsg, ptm->wParam, ptm->lParam );
|
|
else
|
|
{
|
|
ASSERT( NULL == ptm->pfnDefProc ); // bad initialization (_InitThemeMsg)
|
|
}
|
|
}
|
|
return 0L;
|
|
}
|