Lilypad: Implemented full support for child-window GS viewports (fixes windows messaging being broken from the prev rev).

DevNotes: The main change here was to turn WndProcEater into a class and create multiple instances of it, so that it could manage the WndProcs for multiple windows concurrently.  The "frame" (top-level window) gets a WndProc that sets title and handles screensaver/alt-enter hacks.  The "viewport" (provided by PCSX2) gets the usual keyboard input handler WndProc.  Config buttons also have their own WndProc that avoid fuzzy logic conflicts with the other two.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2277 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-11-30 20:52:09 +00:00
parent ee4d5075db
commit 1ea29b0e62
10 changed files with 230 additions and 142 deletions

View File

@ -1250,7 +1250,7 @@ void EndBinding(HWND hWnd) {
dm->ReleaseInput();
ClearKeyQueue();
ReleaseEatenProc();
hWndButtonProc.Release();
// Safest to do this last.
if (needRefreshDevices) {
@ -1300,6 +1300,9 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l
}
break;
case WM_TIMER:
// ignore generic timer callback and handle the hwnd-specific one which comes later
if(hWnd == 0) return 0;
if (!selected || selected == 0xFF) {
// !selected is mostly for device added/removed when binding.
selected = 0xFF;
@ -1308,7 +1311,15 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l
else {
unsigned int uid;
int value;
InitInfo info = {selected==0x7F, 1, hWndProp, hWnd, GetDlgItem(hWnd, selected)};
// The old code re-bound our button hWndProcEater to GetDlgItem(hWnd, selected). But at best hWnd
// was null (WM_TIMER is passed twice, once with a null parameter, and a second time that is hWnd
// specific), and at worst 'selected' is a post-processed code "based" on cmd, so GetDlgItem
// *always* returned NULL anyway. This resulted in hWndButton being null, which meant Device code
// used hWnd instead. This may have caused odd behavior since the callbacks were still all eaten
// by the initial GetDlgItem(hWnd, cmd) selection made when the timer was initialized.
InitInfo info = {selected==0x7F, 1, hWndProp, &hWndButtonProc};
Device *dev = dm->GetActiveDevice(&info, &uid, &index, &value);
if (dev) {
int command = selected;
@ -1517,8 +1528,8 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l
if (selIndex >= 0) {
if (GetBinding(port, slot, selIndex, dev, b, ffb)) {
selected = 0xFF;
InitInfo info = {0, 1, hWndProp, hWnd, GetDlgItem(hWnd, cmd)};
EatWndProc(info.hWndButton, DoNothingWndProc, 0);
hWndButtonProc.SetWndHandle(GetDlgItem(hWnd, cmd));
InitInfo info = {0, 1, hWndProp, &hWndButtonProc};
for (int i=0; i<dm->numDevices; i++) {
if (dm->devices[i] != dev) {
dm->DisableDevice(i);
@ -1554,8 +1565,9 @@ INT_PTR CALLBACK DialogProc(HWND hWnd, unsigned int msg, WPARAM wParam, LPARAM l
}
}
InitInfo info = {selected==0x7F, 1, hWndProp, hWnd, GetDlgItem(hWnd, cmd)};
EatWndProc(info.hWndButton, DoNothingWndProc, 0);
hWndButtonProc.SetWndHandle(GetDlgItem(hWnd, cmd));
hWndButtonProc.Eat(DoNothingWndProc, 0);
InitInfo info = {selected==0x7F, 1, hWndProp, &hWndButtonProc};
int w = timeGetTime();
dm->Update(&info);
dm->PostRead();

View File

@ -4,6 +4,7 @@
#include "resource.h"
#include "InputManager.h"
#include "WndProcEater.h"
Device *dev;
@ -39,7 +40,8 @@ INT_PTR CALLBACK DiagDialog(HWND hWnd, unsigned int uMsg, WPARAM wParam, LPARAM
//break;
case WM_TIMER:
{
InitInfo info = {0, 1, hWnd, hWnd, hWndList};
hWndButtonProc.SetWndHandle(hWndList);
InitInfo info = {0, 1, hWnd, &hWndButtonProc};
dm->Update(&info);
LVITEMW item;
item.mask = LVIF_TEXT;

View File

@ -37,6 +37,8 @@ Device::Device(DeviceAPI api, DeviceType d, const wchar_t *displayName, const wc
attached = 1;
enabled = 0;
hWndProc = 0;
virtualControls = 0;
numVirtualControls = 0;
virtualControlState = 0;

View File

@ -171,6 +171,8 @@ struct PadBindings {
int numFFBindings;
};
class WndProcEater;
struct InitInfo {
// 1 when binding key to ignore.
int bindingIgnore;
@ -178,9 +180,11 @@ struct InitInfo {
int binding;
HWND hWndTop;
HWND hWnd;
// For config screen, need to eat button's message handling.
HWND hWndButton;
//HWND hWndButton;
WndProcEater* hWndProc;
};
@ -194,6 +198,11 @@ public:
char attached;
// Based on input modes.
char enabled;
// Not all devices need to subclass the windproc, but most do so might as well
// put it here... --air
WndProcEater* hWndProc;
union {
// Allows for one loop to compare all 3 in order.
wchar_t *IDs[3];

View File

@ -40,10 +40,12 @@ public:
int Activate(InitInfo *initInfo) {
if (ikhd) ikhd->Deactivate();
binding = initInfo->bindingIgnore;
if (initInfo->hWndButton)
EatWndProc(initInfo->hWndButton, StartHooksWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
else
EatWndProc(initInfo->hWnd, StartHooksWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
hWndProc = initInfo->hWndProc;
return 0;
printf( "(Lilypad) StartHook\n" );
hWndProc->Eat(StartHooksWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
InitState();
ikhd = this;
active = 1;
@ -51,6 +53,8 @@ public:
}
void Deactivate() {
printf( "(Lilypad) KillHook\n" );
FreeState();
if (active) {
if (hHook) {
@ -74,9 +78,11 @@ ExtraWndProcResult StartHooksWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
static int counter = 0;
if (ikhd && !ikhd->hHook && ikhd->active) {
counter = 0;
ikhd->hHook = SetWindowsHookEx(WH_KEYBOARD_LL, IgnoreKeyboardHook, hInst, 0);
printf( "(Lilypad) SetHook\n" );
ikhd->hHook = SetWindowsHookEx(WH_KEYBOARD_LL, IgnoreKeyboardHook, hInst, 0);//GetCurrentThreadId());
if (ikhd->hHook == 0) ikhd->Deactivate();
}
printf( "(Lilypad) HookThinking!\n" );
counter ++;
if (counter % 1000 == 0)
return CONTINUE_BLISSFULLY_AND_RELEASE_PROC;
@ -87,6 +93,7 @@ ExtraWndProcResult StartHooksWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
LRESULT CALLBACK IgnoreKeyboardHook(int code, WPARAM wParam, LPARAM lParam) {
HHOOK hHook = 0;
if (ikhd) {
printf( "(Lilypad) Hooked!!\n" );
hHook = ikhd->hHook;
if (hHook) {
if (code == HC_ACTION) {

View File

@ -24,6 +24,14 @@
HINSTANCE hInst;
HWND hWnd;
HWND hWndTop;
WndProcEater hWndGSProc;
WndProcEater hWndTopProc;
// ButtonProc is used mostly by the Config panel for eating the procedures of the
// button with keyboard focus.
WndProcEater hWndButtonProc;
// Keeps the various sources for Update polling (PADpoll, PADupdate, etc) from wreaking
// havoc on each other...
@ -447,7 +455,7 @@ void Update(unsigned int port, unsigned int slot) {
s[i&1][i>>1] = pads[i&1][i>>1].lockedSum;
}
InitInfo info = {
0, 0, hWnd, hWnd, 0
0, 0, hWndTop, &hWndGSProc
};
dm->Update(&info);
@ -801,9 +809,40 @@ static const u8 queryMode[7] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static const u8 setNativeMode[7] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A};
// Implements a couple of the hacks, also responsible for monitoring device addition/removal and focus
// changes.
ExtraWndProcResult HackWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *output) {
// Implements a couple of the hacks that affect whatever top-level window
// the GS viewport belongs to (title, screensaver)
ExtraWndProcResult TitleHackWndProc(HWND hWndTop, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *output) {
switch (uMsg) {
case WM_SETTEXT:
if (config.saveStateTitle) {
wchar_t text[200];
int len;
if (IsWindowUnicode(hWndTop)) {
len = wcslen((wchar_t*) lParam);
if (len < sizeof(text)/sizeof(wchar_t)) wcscpy(text, (wchar_t*) lParam);
}
else {
len = MultiByteToWideChar(CP_ACP, 0, (char*) lParam, -1, text, sizeof(text)/sizeof(wchar_t));
}
if (len > 0 && len < 150 && !wcsstr(text, L" | State ")) {
wsprintfW(text+len, L" | State %i", saveStateIndex);
SetWindowText(hWndTop, text);
return NO_WND_PROC;
}
}
break;
case WM_SYSCOMMAND:
if ((wParam == SC_SCREENSAVE || wParam == SC_MONITORPOWER) && config.disableScreenSaver)
return NO_WND_PROC;
break;
default:
break;
}
return CONTINUE_BLISSFULLY;
}
// responsible for monitoring device addition/removal, focus changes, and viewport closures.
ExtraWndProcResult StatusWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *output) {
switch (uMsg) {
case WMA_FORCE_UPDATE:
if (wParam == FORCE_UPDATE_WPARAM && lParam == FORCE_UPDATE_LPARAM) {
@ -813,24 +852,6 @@ ExtraWndProcResult HackWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
}
return NO_WND_PROC;
}
case WM_SETTEXT:
if (config.saveStateTitle) {
wchar_t text[200];
int len;
if (IsWindowUnicode(hWnd)) {
len = wcslen((wchar_t*) lParam);
if (len < sizeof(text)/sizeof(wchar_t)) wcscpy(text, (wchar_t*) lParam);
}
else {
len = MultiByteToWideChar(CP_ACP, 0, (char*) lParam, -1, text, sizeof(text)/sizeof(wchar_t));
}
if (len > 0 && len < 150 && !wcsstr(text, L" | State ")) {
wsprintfW(text+len, L" | State %i", saveStateIndex);
SetWindowText(hWnd, text);
return NO_WND_PROC;
}
}
break;
case WM_DEVICECHANGE:
if (wParam == DBT_DEVNODES_CHANGED) {
UpdateEnabledDevices(1);
@ -855,10 +876,6 @@ ExtraWndProcResult HackWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara
return NO_WND_PROC;
}
break;
case WM_SYSCOMMAND:
if ((wParam == SC_SCREENSAVE || wParam == SC_MONITORPOWER) && config.disableScreenSaver)
return NO_WND_PROC;
break;
case WM_DESTROY:
QueueKeyEvent(VK_ESCAPE, KEYPRESS);
break;
@ -897,12 +914,12 @@ void CALLBACK PADconfigure() {
DWORD WINAPI RenameWindowThreadProc(void *lpParameter) {
wchar_t newTitle[200];
if (hWnd) {
int len = GetWindowTextW(hWnd, newTitle, 200);
if (hWndTop) {
int len = GetWindowTextW(hWndTop, newTitle, 200);
if (len > 0 && len < 199) {
wchar_t *end;
if (end = wcsstr(newTitle, L" | State ")) *end = 0;
SetWindowTextW(hWnd, newTitle);
SetWindowTextW(hWndTop, newTitle);
}
}
return 0;
@ -940,26 +957,33 @@ s32 CALLBACK PADopen(void *pDsp) {
"Non-LilyPad Error", MB_OK | MB_ICONERROR);
return -1;
}
while (GetWindowLong (hWnd, GWL_STYLE) & WS_CHILD)
hWnd = GetParent (hWnd);
// Implements most hacks, as well as enabling/disabling mouse
// capture when focus changes.
updateQueued = 0;
if (!EatWndProc(hWnd, HackWndProc, 0)) {
hWndTop = hWnd;
while (GetWindowLong (hWndTop, GWL_STYLE) & WS_CHILD)
hWndTop = GetParent (hWndTop);
if (!hWndGSProc.SetWndHandle(hWnd) || !hWndTopProc.SetWndHandle(hWndTop)) {
openCount = 0;
return -1;
}
// Implements most hacks, as well as enabling/disabling mouse
// capture when focus changes.
updateQueued = 0;
hWndGSProc.Eat(StatusWndProc, 0);
hWndTopProc.Eat(TitleHackWndProc, 0);
if (config.forceHide) {
EatWndProc(hWnd, HideCursorProc, 0);
hWndGSProc.Eat(HideCursorProc, 0);
}
SaveStateChanged();
windowThreadId = GetWindowThreadProcessId(hWnd, 0);
windowThreadId = GetWindowThreadProcessId(hWndTop, 0);
}
if (restoreFullScreen) {
if (!IsWindowMaximized(hWnd)) {
HANDLE hThread = CreateThread(0, 0, MaximizeWindowThreadProc, hWnd, 0, 0);
if (!IsWindowMaximized(hWndTop)) {
HANDLE hThread = CreateThread(0, 0, MaximizeWindowThreadProc, hWndTop, 0, 0);
if (hThread) CloseHandle(hThread);
}
restoreFullScreen = 0;
@ -989,9 +1013,11 @@ void CALLBACK PADclose() {
if (openCount && !--openCount) {
DEBUG_TEXT_OUT("LilyPad closed\n\n");
updateQueued = 0;
ReleaseEatenProc();
hWndGSProc.Release();
hWndTopProc.Release();
dm->ReleaseInput();
hWnd = 0;
hWndTop = 0;
ClearKeyQueue();
}
}
@ -1327,7 +1353,7 @@ keyEvent* CALLBACK PADkeyEvent() {
if (!GetQueuedKeyEvent(&ev)) return 0;
if ((ev.key == VK_ESCAPE || (int)ev.key == -2) && ev.evt == KEYPRESS && config.escapeFullscreenHack) {
static int t;
if ((int)ev.key != -2 && IsWindowMaximized(hWnd)) {
if ((int)ev.key != -2 && IsWindowMaximized(hWndTop)) {
t = timeGetTime();
QueueKeyEvent(-2, KEYPRESS);
HANDLE hThread = CreateThread(0, 0, MaximizeWindowThreadProc, 0, 0, 0);

View File

@ -76,17 +76,15 @@ public:
int Activate(InitInfo *initInfo) {
Deactivate();
HWND hWnd = initInfo->hWnd;
if (initInfo->hWndButton) {
hWnd = initInfo->hWndButton;
}
hWndProc = initInfo->hWndProc;
active = 1;
if (!rawKeyboardActivatedCount++) {
if (!rawMouseActivatedCount && !EatWndProc(hWnd, RawInputWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES)) {
Deactivate();
return 0;
}
if (!GetRawKeyboards(hWnd)) {
if (!rawMouseActivatedCount)
hWndProc->Eat(RawInputWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
if (!GetRawKeyboards(hWndProc->hWndEaten)) {
Deactivate();
return 0;
}
@ -104,7 +102,7 @@ public:
if (!rawKeyboardActivatedCount) {
ReleaseRawKeyboards();
if (!rawMouseActivatedCount)
ReleaseExtraProc(RawInputWndProc);
hWndProc->ReleaseExtraProc(RawInputWndProc);
}
}
}
@ -120,10 +118,8 @@ public:
int Activate(InitInfo *initInfo) {
Deactivate();
HWND hWnd = initInfo->hWnd;
if (initInfo->hWndButton) {
hWnd = initInfo->hWndButton;
}
hWndProc = initInfo->hWndProc;
active = 1;
@ -131,12 +127,11 @@ public:
// EatWndProc fail. In all other cases, no unmatched initialization/cleanup
// lines.
if (!rawMouseActivatedCount++) {
GetMouseCapture(hWnd);
if (!rawKeyboardActivatedCount && !EatWndProc(hWnd, RawInputWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES)) {
Deactivate();
return 0;
}
if (!GetRawMice(hWnd)) {
GetMouseCapture(hWndProc->hWndEaten);
if (!rawKeyboardActivatedCount)
hWndProc->Eat(RawInputWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
if (!GetRawMice(hWndProc->hWndEaten)) {
Deactivate();
return 0;
}
@ -155,7 +150,7 @@ public:
ReleaseRawMice();
ReleaseMouseCapture();
if (!rawKeyboardActivatedCount) {
ReleaseExtraProc(RawInputWndProc);
hWndProc->ReleaseExtraProc(RawInputWndProc);
}
}
}

View File

@ -25,14 +25,11 @@ public:
// Redundant. Should match the next line.
// Deactivate();
if (wmk) wmk->Deactivate();
HWND hWnd = initInfo->hWnd;
if (initInfo->hWndButton) {
hWnd = initInfo->hWndButton;
}
if (!wmm && !EatWndProc(hWnd, WindowsMessagingWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES)) {
Deactivate();
return 0;
}
hWndProc = initInfo->hWndProc;
if (!wmm)
hWndProc->Eat(WindowsMessagingWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
wmk = this;
InitState();
@ -44,7 +41,7 @@ public:
void Deactivate() {
if (active) {
if (!wmm)
ReleaseExtraProc(WindowsMessagingWndProc);
hWndProc->ReleaseExtraProc(WindowsMessagingWndProc);
wmk = 0;
active = 0;
FreeState();
@ -67,16 +64,12 @@ public:
// Redundant. Should match the next line.
// Deactivate();
if (wmm) wmm->Deactivate();
HWND hWnd = initInfo->hWnd;
if (initInfo->hWndButton) {
hWnd = initInfo->hWndButton;
}
hWndProc = initInfo->hWndProc;
if (!wmk && !EatWndProc(hWnd, WindowsMessagingWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES)) {
Deactivate();
return 0;
}
GetMouseCapture(hWnd);
if (!wmk)
hWndProc->Eat(WindowsMessagingWndProc, EATPROC_NO_UPDATE_WHILE_UPDATING_DEVICES);
GetMouseCapture(hWndProc->hWndEaten);
active = 1;
@ -89,7 +82,7 @@ public:
void Deactivate() {
if (active) {
if (!wmk)
ReleaseExtraProc(WindowsMessagingWndProc);
hWndProc->ReleaseExtraProc(WindowsMessagingWndProc);
ReleaseMouseCapture();
wmm = 0;
active = 0;

View File

@ -1,24 +1,31 @@
#include "Global.h"
#include "WndProcEater.h"
static HWND hWndEaten = 0;
static WNDPROC eatenWndProc = 0;
WndProcEater::WndProcEater()
{
hWndEaten = 0;
eatenWndProc = 0;
struct ExtraWndProcInfo {
ExtraWndProc proc;
DWORD flags;
};
extraProcs = 0;
numExtraProcs = 0;
static ExtraWndProcInfo* extraProcs = 0;
static int numExtraProcs = 0;
hMutex = CreateMutex(0, 0, L"LilyPad");
}
void ReleaseExtraProc(ExtraWndProc proc) {
WndProcEater::~WndProcEater() throw()
{
if (hMutex) {
ReleaseMutex(hMutex);
CloseHandle(hMutex);
}
}
void WndProcEater::ReleaseExtraProc(ExtraWndProc proc) {
// Probably isn't needed, but just in case...
// Creating and destroying the mutex adds some inefficiency,
// but this function is only called on emulation start and on focus/unfocus.
HANDLE hMutex = CreateMutexA(0, 0, "LilyPad");
if (hMutex) WaitForSingleObject(hMutex, 100);
//printf( "(Lilypad) Regurgitating! -> 0x%x\n", proc );
for (int i=0; i<numExtraProcs; i++) {
if (extraProcs[i].proc == proc) {
extraProcs[i] = extraProcs[--numExtraProcs];
@ -34,18 +41,18 @@ void ReleaseExtraProc(ExtraWndProc proc) {
hWndEaten = 0;
eatenWndProc = 0;
}
if (hMutex) {
ReleaseMutex(hMutex);
CloseHandle(hMutex);
}
}
void ReleaseEatenProc() {
void WndProcEater::Release() {
while (numExtraProcs) ReleaseExtraProc(extraProcs[0].proc);
RemoveProp( hWndEaten, L"LilyHaxxor" );
}
LRESULT CALLBACK OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
LRESULT WndProcEater::_OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if( hWnd != hWndEaten )
fprintf( stderr, "Totally mismatched window handles on OverrideWndProc!\n" );
ExtraWndProcResult res = CONTINUE_BLISSFULLY;
LRESULT out = 0;
// Here because want it for binding, even when no keyboard mode is selected.
@ -71,7 +78,7 @@ LRESULT CALLBACK OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa
if (res != NO_WND_PROC) {
if (out == WM_DESTROY) {
ReleaseEatenProc();
Release();
}
if (res == CONTINUE_BLISSFULLY)
out = CallWindowProc(eatenWndProc, hWnd, uMsg, wParam, lParam);
@ -81,32 +88,41 @@ LRESULT CALLBACK OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa
return out;
}
static LRESULT CALLBACK OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
WndProcEater* obj = (WndProcEater*)GetProp(hWnd, L"LilyHaxxor");
return (obj == NULL) ?
DefWindowProc(hWnd, uMsg, wParam, lParam) :
obj->_OverrideWndProc( hWnd, uMsg, wParam, lParam );
}
bool WndProcEater::SetWndHandle(HWND hWnd)
{
if(hWnd == hWndEaten) return true;
//printf( "(Lilypad) (Re)-Setting window handle! -> this=0x%08x, hWnd=0x%08x\n", this, hWnd );
Release();
SetProp(hWnd, L"LilyHaxxor", (HANDLE)this);
eatenWndProc = (WNDPROC) SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)OverrideWndProc);
hWndEaten = (eatenWndProc) ? hWnd : 0;
return !!hWndEaten;
}
void WndProcEater::Eat(ExtraWndProc proc, DWORD flags) {
// check if Subclassing failed to init during SetWndHandle
if (!hWndEaten) return;
int EatWndProc(HWND hWnd, ExtraWndProc proc, DWORD flags) {
// Probably isn't needed, but just in case...
// Creating and destroying the mutex adds some inefficiency,
// but this function is only called on emulation start and on focus/unfocus.
HANDLE hMutex = CreateMutexA(0, 0, "LilyPad");
if (hMutex) WaitForSingleObject(hMutex, 100);
if (hWnd != hWndEaten) {
ReleaseEatenProc();
eatenWndProc = (WNDPROC) SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)OverrideWndProc);
// ???
if (eatenWndProc)
hWndEaten = hWnd;
}
if (hWndEaten == hWnd) {
//printf( "(Lilypad) EatingWndProc! -> 0x%x\n", proc );
extraProcs = (ExtraWndProcInfo*) realloc(extraProcs, sizeof(ExtraWndProcInfo)*(numExtraProcs+1));
extraProcs[numExtraProcs].proc = proc;
extraProcs[numExtraProcs].flags = flags;
numExtraProcs++;
}
if (hMutex) {
ReleaseMutex(hMutex);
CloseHandle(hMutex);
}
return hWndEaten == hWnd;
}

View File

@ -11,8 +11,34 @@ enum ExtraWndProcResult {
};
typedef ExtraWndProcResult (*ExtraWndProc)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *out);
int EatWndProc(HWND hWnd, ExtraWndProc proc, DWORD flags);
struct ExtraWndProcInfo {
ExtraWndProc proc;
DWORD flags;
};
class WndProcEater
{
public:
HWND hWndEaten;
WNDPROC eatenWndProc;
ExtraWndProcInfo* extraProcs;
int numExtraProcs;
HANDLE hMutex;
public:
WndProcEater();
virtual ~WndProcEater() throw();
bool SetWndHandle(HWND hWnd);
void Eat(ExtraWndProc proc, DWORD flags);
void ReleaseExtraProc(ExtraWndProc proc);
void ReleaseEatenProc();
void Release();
LRESULT _OverrideWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
};
extern WndProcEater hWndGSProc;
extern WndProcEater hWndTopProc;
extern WndProcEater hWndButtonProc;