#define _WIN32_WINNT 0x0600 #define WIN32_LEAN_AND_MEAN #define _CRT_SECURE_NO_DEPRECATE 1 #include #include #include #include "dxwnd.h" #include "dxwcore.hpp" #include "dxhelper.h" extern void SuppressIMEWindow(); extern void RecoverScreenMode(); extern void RestoreDDrawSurfaces(); extern void RestoreD3DSurfaces(BOOL); static void dx_ToggleLogging() { // toggle LOGGING if(dxw.dwTFlags & OUTTRACE){ OutTraceDW("Toggle logging OFF\n"); dxw.dwTFlags &= ~OUTTRACE; } else { dxw.dwTFlags |= OUTTRACE; OutTraceDW("Toggle logging ON\n"); } GetHookInfo()->isLogging=(dxw.dwTFlags & OUTTRACE); } LRESULT CALLBACK extDialogWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { static int i=0; static WINDOWPOS *wp; WNDPROC pWindowProc; LRESULT res; static int t = -1; static int iRecursion = 0; if(iRecursion) { iRecursion=0; return NULL; } iRecursion++; if (t == -1) t = (*pGetTickCount)(); int tn = (*pGetTickCount)(); OutTraceW("DEBUG: DialogWinMsg hwnd=%x msg=[0x%x]%s(%x,%x)\n", hwnd, message, ExplainWinMessage(message), wparam, lparam); // optimization: don't invalidate too often! // 200mSec seems a good compromise. if (tn-t > 200) { (*pInvalidateRect)(hwnd, NULL, TRUE); t=tn; } pWindowProc=dxwws.GetProc(hwnd); if(pWindowProc) { res =(*pCallWindowProcA)(pWindowProc, hwnd, message, wparam, lparam); } else { char *sMsg="ASSERT: DialogWinMsg pWindowProc=NULL !!!\n"; OutTraceDW(sMsg); if (IsAssertEnabled) MessageBox(0, sMsg, "WindowProc", MB_OK | MB_ICONEXCLAMATION); res = NULL; } iRecursion=0; return res; } LRESULT CALLBACK extChildWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { static int i=0; static WINDOWPOS *wp; WNDPROC pWindowProc; OutTraceW("DEBUG: ChildWinMsg hwnd=%x msg=[0x%x]%s(%x,%x)\n", hwnd, message, ExplainWinMessage(message), wparam, lparam); if(dxw.Windowize){ switch(message){ // Cybermercs: it seems that all game menus are conveniently handled by the WindowProc routine, // while the action screen get messages processed by the ChildWindowProc, that needs some different // setting .......... // Beware: Cybermercs handles some static info about cursor position handling, so that if you resize // a menu it doesn't work correctly until you don't change screen. case WM_MOUSEMOVE: case WM_MOUSEWHEEL: case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_LBUTTONDBLCLK: case WM_RBUTTONDOWN: case WM_RBUTTONUP: case WM_RBUTTONDBLCLK: case WM_MBUTTONDOWN: case WM_MBUTTONUP: case WM_MBUTTONDBLCLK: // if(dxw.dwFlags1 & MODIFYMOUSE){ // mouse processing //if((dxw.dwFlags1 & MODIFYMOUSE) && !(dxw.dwFlags6 & NOMOUSEPROC)){ // mouse processing if((dxw.dwFlags1 & MODIFYMOUSE) && !(dxw.dwFlags1 & MESSAGEPROC)){ // mouse processing POINT prev, curr; // scale mouse coordinates prev.x = LOWORD(lparam); prev.y = HIWORD(lparam); curr = prev; if(message == WM_MOUSEWHEEL){ // v2.02.33 mousewheel fix POINT upleft={0,0}; (*pClientToScreen)(dxw.GethWnd(), &upleft); curr = dxw.SubCoordinates(curr, upleft); } //OutTraceC("ChildWindowProc: hwnd=%x pos XY prev=(%d,%d)\n", hwnd, prev.x, prev.y); curr=dxw.FixCursorPos(curr); // Warn! the correction must refer to the main window hWnd, not the current hwnd one !!! lparam = MAKELPARAM(curr.x, curr.y); OutTraceC("ChildWindowProc: hwnd=%x pos XY=(%d,%d)->(%d,%d)\n", hwnd, prev.x, prev.y, curr.x, curr.y); } break; default: break; } } pWindowProc=dxwws.GetProc(hwnd); // v2.02.82: use CallWindowProc that handles WinProc handles if(pWindowProc) return(*pCallWindowProcA)(pWindowProc, hwnd, message, wparam, lparam); // should never get here .... OutTraceDW("ChildWindowProc: no WndProc for CHILD hwnd=%x\n", hwnd); return DefWindowProc(hwnd, message, wparam, lparam); } static void dx_UpdatePositionLock(HWND hwnd) { RECT rect; POINT p={0,0}; (*pGetClientRect)(hwnd,&rect); (*pClientToScreen)(hwnd,&p); dxw.dwFlags1 |= LOCKWINPOS; OutTraceDW("Toggle position lock ON\n"); dxw.InitWindowPos(p.x, p.y, rect.right-rect.left, rect.bottom-rect.top); } static void dx_TogglePositionLock(HWND hwnd) { // toggle position locking if(dxw.dwFlags1 & LOCKWINPOS){ // unlock OutTraceDW("Toggle position lock OFF\n"); dxw.dwFlags1 &= ~LOCKWINPOS; } else { OutTraceDW("Toggle position lock ON\n"); dxw.dwFlags1 |= LOCKWINPOS; dx_UpdatePositionLock(hwnd); } } static void dx_ToggleFPS() { if(dxw.dwFlags2 & SHOWFPS){ dxw.dwFlags2 &= ~SHOWFPS; OutTrace("ToggleFPS: SHOWFPS mode OFF\n"); } else { dxw.dwFlags2 |= SHOWFPS; OutTrace("ToggleFPS: SHOWFPS mode ON\n"); } } static void dx_Cornerize(HWND hwnd) { static BOOL bCornerized = FALSE; static RECT WinRect = {0, 0, 0, 0}; static DWORD OldStyle, OldExtStyle; if (bCornerized){ // toggle .... OutTraceDW("DxWnd: exiting corner mode\n"); (*pSetWindowLongA)(hwnd, GWL_STYLE, OldStyle); (*pSetWindowLongA)(hwnd, GWL_EXSTYLE, OldExtStyle); (*pMoveWindow)(hwnd, WinRect.left, WinRect.top, WinRect.right, WinRect.bottom, TRUE); memset(&WinRect, 0, sizeof(WinRect)); } else { OutTraceDW("DxWnd: entering corner mode\n"); (*pGetWindowRect)(hwnd, &WinRect); OldStyle = (*pGetWindowLongA)(hwnd, GWL_STYLE); OldExtStyle = (*pGetWindowLongA)(hwnd, GWL_EXSTYLE); (*pSetWindowLongA)(hwnd, GWL_STYLE, WS_VISIBLE|WS_CLIPSIBLINGS|WS_OVERLAPPED); (*pSetWindowLongA)(hwnd, GWL_EXSTYLE, 0); (*pMoveWindow)(hwnd, 0, 0, dxw.GetScreenWidth(), dxw.GetScreenHeight(), TRUE); } bCornerized = !bCornerized; // switch toggle (*pUpdateWindow)(hwnd); dxw.ScreenRefresh(); } void dx_FullScreenToggle(HWND hwnd) { static BOOL bFullScreen = FALSE; static RECT WinRect = {0, 0, 0, 0}; static DWORD OldStyle, OldExtStyle; static DEVMODE oldDisplayMode; static DWORD OrigFlags; // toggle .... if (bFullScreen){ OutTraceDW("DxWnd: exiting fullscreen mode: style=%x extstyle=%x pos=(%d,%d)-(%d,%d)\n", OldStyle, OldExtStyle, WinRect.left, WinRect.top, WinRect.right, WinRect.bottom); int ChangeDisplayResult = (*pChangeDisplaySettingsA)(&oldDisplayMode, CDS_FULLSCREEN); if(ChangeDisplayResult != DISP_CHANGE_SUCCESSFUL){ MessageBox(NULL,"Error: Failed to recover display mode.", "Error", 0); } // MoveWindow doesn't recover the exact position!!! (*pSetWindowLongA)(hwnd, GWL_STYLE, OldStyle); (*pSetWindowLongA)(hwnd, GWL_EXSTYLE, OldExtStyle); (*pSetWindowPos)(hwnd, HWND_TOP, WinRect.left, WinRect.top, (WinRect.right-WinRect.left), (WinRect.bottom-WinRect.top), SWP_DRAWFRAME|SWP_FRAMECHANGED|SWP_SHOWWINDOW); memset(&WinRect, 0, sizeof(WinRect)); } else { OutTraceDW("DxWnd: entering fullscreen mode\n"); int BestIndex, iCost, iBestCost; if((WinRect.left==0) && (WinRect.right==0) && (WinRect.top==0) && (WinRect.bottom==0)) (*pGetWindowRect)(hwnd, &WinRect); OldStyle = (*pGetWindowLongA)(hwnd, GWL_STYLE); OldExtStyle = (*pGetWindowLongA)(hwnd, GWL_EXSTYLE); (*pSetWindowLongA)(hwnd, GWL_STYLE, WS_VISIBLE|WS_CLIPSIBLINGS|WS_OVERLAPPED); (*pSetWindowLongA)(hwnd, GWL_EXSTYLE, 0); (*pMoveWindow)(hwnd, 0, 0, dxw.GetScreenWidth(), dxw.GetScreenHeight(), TRUE); (*pUpdateWindow)(hwnd); DEVMODE DisplayMode; memset(&oldDisplayMode, 0, sizeof(DEVMODE)); if(!(*pEnumDisplaySettings)(NULL, ENUM_CURRENT_SETTINGS, &oldDisplayMode)){ MessageBox(NULL, "EnumDisplaySettings Failed ???", "Error!", 0); } iBestCost=1000000; // huge for (int i=0; ;i++){ iCost=0; memset(&DisplayMode, 0, sizeof(DEVMODE)); DisplayMode.dmSize = sizeof(DEVMODE); if(!(*pEnumDisplaySettings)(NULL, i, &DisplayMode))break; // no more modes if(DisplayMode.dmPelsWidth < dxw.GetScreenWidth()) continue; // bad: too narrow if(DisplayMode.dmPelsHeight < dxw.GetScreenHeight()) continue; // bad: too low if (DisplayMode.dmBitsPerPel != oldDisplayMode.dmBitsPerPel) continue; // bad: different color depth iCost = (DisplayMode.dmPelsWidth - dxw.GetScreenWidth()) + (DisplayMode.dmPelsHeight - dxw.GetScreenHeight()) + (DisplayMode.dmDisplayFrequency == oldDisplayMode.dmDisplayFrequency) ? 1 : 0; if(iCost < iBestCost){ iBestCost = iCost; BestIndex = i; } if(iBestCost == 0) break; // got the perfect one! } memset(&DisplayMode, 0, sizeof(DEVMODE)); (*pEnumDisplaySettings)(NULL, BestIndex, &DisplayMode); OutTraceDW("DxWnd: selected mode bpp=%d size=(%dx%d) freq=%d\n", DisplayMode.dmBitsPerPel, DisplayMode.dmPelsWidth, DisplayMode.dmPelsHeight, DisplayMode.dmDisplayFrequency); DisplayMode.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFLAGS|DM_DISPLAYFREQUENCY|DM_POSITION; int ChangeDisplayResult = (*pChangeDisplaySettingsA)(&DisplayMode, CDS_FULLSCREEN); if(ChangeDisplayResult != DISP_CHANGE_SUCCESSFUL){ MessageBox(NULL,"Error: Failed to change display mode.", "Error", 0); } } (*pUpdateWindow)(hwnd); RestoreDDrawSurfaces(); RestoreD3DSurfaces(bFullScreen); bFullScreen = !bFullScreen; // switch toggle } static void dx_DesktopToggle(HWND hwnd, BOOL bWorkArea) { static BOOL bDesktopToggle = FALSE; static RECT WinRect = {0, 0, 0, 0}; static DWORD OldStyle, OldExtStyle; if (bDesktopToggle){ // toggle .... OutTraceDW("DxWnd: exiting desktop mode: style=%x extstyle=%x pos=(%d,%d)-(%d,%d)\n", OldStyle, OldExtStyle, WinRect.left, WinRect.top, WinRect.right, WinRect.bottom); (*pSetWindowLongA)(hwnd, GWL_STYLE, OldStyle); (*pSetWindowLongA)(hwnd, GWL_EXSTYLE, OldExtStyle); // MoveWindow doesn't recover the exact position!!! (*pSetWindowPos)(hwnd, HWND_TOP, WinRect.left, WinRect.top, (WinRect.right-WinRect.left), (WinRect.bottom-WinRect.top), SWP_DRAWFRAME|SWP_FRAMECHANGED|SWP_SHOWWINDOW); memset(&WinRect, 0, sizeof(WinRect)); } else { RECT DesktopRect; HWND DesktopWnd; HDC hClientDC; OutTraceDW("DxWnd: entering desktop mode\n"); if((WinRect.left==0) && (WinRect.right==0) && (WinRect.top==0) && (WinRect.bottom==0)) (*pGetWindowRect)(hwnd, &WinRect); OldStyle = (*pGetWindowLongA)(hwnd, GWL_STYLE); OldExtStyle = (*pGetWindowLongA)(hwnd, GWL_EXSTYLE); (*pSetWindowLongA)(hwnd, GWL_STYLE, WS_VISIBLE|WS_CLIPSIBLINGS|WS_OVERLAPPED); (*pSetWindowLongA)(hwnd, GWL_EXSTYLE, 0); (*pUpdateWindow)(hwnd); DesktopWnd = (*pGetDesktopWindow)(); hClientDC=(*pGDIGetDC)(hwnd); if(bWorkArea) (*pSystemParametersInfoA)(SPI_GETWORKAREA, NULL, &DesktopRect, 0); else (*pGetClientRect)(DesktopWnd, &DesktopRect); OutTraceDW("DxWnd: desktop=(%d,%d)-(%d,%d)\n"); (*pSetWindowPos)(hwnd, HWND_TOP, DesktopRect.left, DesktopRect.top, (DesktopRect.right-DesktopRect.left), (DesktopRect.bottom-DesktopRect.top), SWP_DRAWFRAME|SWP_FRAMECHANGED|SWP_SHOWWINDOW); (*pGDIBitBlt)(hClientDC, DesktopRect.left, DesktopRect.top, DesktopRect.right, DesktopRect.bottom, NULL, 0, 0, BLACKNESS); } bDesktopToggle = !bDesktopToggle; // switch toggle (*pUpdateWindow)(hwnd); dxw.ScreenRefresh(); (*pInvalidateRect)(hwnd, NULL, FALSE); // force window update } LRESULT LastCursorPos; LRESULT CALLBACK extWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { POINT prev, curr; RECT rect; static int i=0; static int ClipCursorToggleState = 1; WNDPROC pWindowProc; extern void dxwFixWindowPos(char *, HWND, LPARAM); extern LPRECT lpClipRegion; static BOOL DoOnce = TRUE; static BOOL IsToBeLocked; static int LastTimeShift; static int SaveTimeShift; static BOOL TimeShiftToggle=TRUE; extern void DDrawScreenShot(); if(DoOnce){ DoOnce=FALSE; IsToBeLocked=(dxw.dwFlags1 & LOCKWINPOS); LastTimeShift=SaveTimeShift=dxw.TimeShift; } // v2.1.93: adjust clipping region if(IsTraceW){ char sPos[161]; sPos[160]=0; sPos[0]=0; switch(message){ case WM_WINDOWPOSCHANGING: case WM_WINDOWPOSCHANGED: LPWINDOWPOS wp; wp = (LPWINDOWPOS)lparam; sprintf_s(sPos, 160, " pos=(%d,%d) size=(%dx%d) flags=%x(%s)", wp->x, wp->y, wp->cx, wp->cy, wp->flags, ExplainWPFlags(wp->flags)); break; case WM_MOVE: sprintf_s(sPos, 160, " pos=(%d,%d)", HIWORD(lparam), LOWORD(lparam)); break; case WM_SIZE: static char *modes[5]={"RESTORED", "MINIMIZED", "MAXIMIZED", "MAXSHOW", "MAXHIDE"}; sprintf_s(sPos, 160, " mode=SIZE_%s size=(%dx%d)", modes[wparam % 5], HIWORD(lparam), LOWORD(lparam)); break; } OutTrace("WindowProc[%x]: WinMsg=[0x%x]%s(%x,%x) %s\n", hwnd, message, ExplainWinMessage(message), wparam, lparam, sPos); } if(dxw.dwFlags3 & FILTERMESSAGES){ switch(message){ case WM_NCMOUSEMOVE: case WM_NCLBUTTONDOWN: case WM_NCLBUTTONUP: case WM_NCLBUTTONDBLCLK: case WM_NCRBUTTONDOWN: case WM_NCRBUTTONUP: case WM_NCRBUTTONDBLCLK: case WM_NCMBUTTONDOWN: case WM_NCMBUTTONUP: case WM_NCMBUTTONDBLCLK: OutTraceDW("WindowProc[%x]: SUPPRESS WinMsg=[0x%x]%s(%x,%x)\n", hwnd, message, ExplainWinMessage(message), wparam, lparam); return 0; } } if(LastTimeShift != dxw.TimeShift){ extern void SetVSyncDelays(LPDIRECTDRAW); extern LPDIRECTDRAW lpPrimaryDD; if(dxw.dwFlags4 & STRETCHTIMERS) dxw.RenewTimers(); if(lpPrimaryDD) SetVSyncDelays(lpPrimaryDD); LastTimeShift=dxw.TimeShift; } switch(message){ // v2.02.13: added WM_GETMINMAXINFO/WM_NCCALCSIZE interception - (see Actua Soccer 3 problems...) //case WM_NCDESTROY: // return 0; case WM_GETMINMAXINFO: if(dxw.dwFlags1 & LOCKWINPOS){ extern void dxwFixMinMaxInfo(char *, HWND, LPARAM); dxwFixMinMaxInfo("WindowProc", hwnd, lparam); return 0; } break; case WM_NCCALCSIZE: case WM_NCPAINT: if((dxw.dwFlags1 & LOCKWINPOS) && (hwnd == dxw.GethWnd()) && dxw.IsFullScreen()){ // v2.02.30: don't alter child and other windows.... OutTraceDW("WindowProc: %s wparam=%x\n", ExplainWinMessage(message), wparam); return (*pDefWindowProcA)(hwnd, message, wparam, lparam); } break; case WM_NCCREATE: if(dxw.dwFlags2 & SUPPRESSIME) SuppressIMEWindow(); break; case WM_IME_SETCONTEXT: case WM_IME_NOTIFY: case WM_IME_CONTROL: case WM_IME_COMPOSITIONFULL: case WM_IME_SELECT: case WM_IME_CHAR: case WM_IME_REQUEST: case WM_IME_KEYDOWN: case WM_IME_KEYUP: if(dxw.dwFlags2 & SUPPRESSIME){ OutTraceDW("WindowProc[%x]: SUPPRESS IME WinMsg=[0x%x]%s(%x,%x)\n", hwnd, message, ExplainWinMessage(message), wparam, lparam); return 0; } break; case WM_NCHITTEST: if((dxw.dwFlags2 & FIXNCHITTEST) && (dxw.dwFlags1 & MODIFYMOUSE)){ // mouse processing POINT cursor; LRESULT ret; ret=(*pDefWindowProcA)(hwnd, message, wparam, lparam); if (ret==HTCLIENT) { cursor.x=LOWORD(lparam); cursor.y=HIWORD(lparam); dxw.FixNCHITCursorPos(&cursor); lparam = MAKELPARAM(cursor.x, cursor.y); } else return ret; } break; case WM_ERASEBKGND: if(dxw.Windowize && dxw.IsDesktop(hwnd)){ OutTraceDW("WindowProc: WM_ERASEBKGND(%x,%x) - suppressed\n", wparam, lparam); return 1; // 1 == OK, erased } break; case WM_DISPLAYCHANGE: if (dxw.Windowize && (dxw.dwFlags1 & LOCKWINPOS) && dxw.IsFullScreen()){ OutTraceDW("WindowProc: prevent WM_DISPLAYCHANGE depth=%d size=(%d,%d)\n", wparam, LOWORD(lparam), HIWORD(lparam)); // v2.02.43: unless EMULATESURFACE is set, lock the screen resolution only, but not the color depth! if(dxw.dwFlags1 & EMULATESURFACE) return 0; // let rparam (color depth) change, but override lparam (screen width & height.) lparam = MAKELPARAM((LONG)dxw.GetScreenWidth(), (LONG)dxw.GetScreenHeight()); //return 0; } break; case WM_WINDOWPOSCHANGING: case WM_WINDOWPOSCHANGED: if(dxw.Windowize && dxw.IsFullScreen()){ if(dxw.dwFlags5 & NOWINPOSCHANGES){ OutTraceDW("WindowProc: %s - suppressed\n", message==WM_WINDOWPOSCHANGED ? "WM_WINDOWPOSCHANGED" : "WM_WINDOWPOSCHANGING"); return 0; } extern HWND hControlParentWnd; LPWINDOWPOS wp; wp = (LPWINDOWPOS)lparam; dxwFixWindowPos("WindowProc", hwnd, lparam); OutTraceDW("WindowProc: %s fixed size=(%d,%d)\n", (message == WM_WINDOWPOSCHANGED) ? "WM_WINDOWPOSCHANGED" : "WM_WINDOWPOSCHANGING", wp->cx, wp->cy); // try to lock main wind & control parent together if((message==WM_WINDOWPOSCHANGED) && hControlParentWnd){ if(dxw.IsDesktop(hwnd)) { POINT fo = dxw.GetFrameOffset(); (*pMoveWindow)(hControlParentWnd, wp->x+fo.x, wp->y+fo.y, wp->cx, wp->cy, TRUE); } } // v2.03.30: in window mode, it seems that the WM_ACTIVATEAPP message is not sent to the main win. // this PostMessage call recovers "Thorgal" block at the end of intro movie and "Championship Manager 03 04" cursor if((message==WM_WINDOWPOSCHANGED) && (dxw.dwFlags6 & ACTIVATEAPP)){ PostMessage(hwnd, WM_ACTIVATEAPP, 1, 0); } } break; case WM_ENTERSIZEMOVE: if(IsToBeLocked){ dxw.dwFlags1 &= ~LOCKWINPOS; } while((*pShowCursor)(1) < 0); if(dxw.dwFlags1 & CLIPCURSOR) dxw.EraseClipCursor(); if(dxw.dwFlags1 & ENABLECLIPPING) (*pClipCursor)(NULL); break; case WM_EXITSIZEMOVE: if(IsToBeLocked){ dxw.dwFlags1 |= LOCKWINPOS; dx_UpdatePositionLock(hwnd); } if((dxw.dwFlags1 & HIDEHWCURSOR) && dxw.IsFullScreen()) while((*pShowCursor)(0) >= 0); if(dxw.dwFlags2 & SHOWHWCURSOR) while((*pShowCursor)(1) < 0); if(dxw.dwFlags1 & ENABLECLIPPING) extClipCursor(lpClipRegion); if(dxw.dwFlags2 & REFRESHONRESIZE) dxw.ScreenRefresh(); if(dxw.dwFlags4 & HIDEDESKTOP) dxw.HideDesktop(dxw.GethWnd()); if(dxw.dwFlags5 & CENTERTOWIN) { HDC thdc; HWND w = dxw.GethWnd(); RECT client; (*pGetClientRect)(w, &client); thdc=(*pGDIGetDC)(w); if(thdc) (*pGDIBitBlt)(thdc, client.left, client.top, client.right, client.bottom, 0, 0, 0, BLACKNESS); } break; case WM_ACTIVATE: // turn DirectInput bActive flag on & off ..... dxw.bActive = (LOWORD(wparam) == WA_ACTIVE || LOWORD(wparam) == WA_CLICKACTIVE) ? 1 : 0; case WM_NCACTIVATE: // turn DirectInput bActive flag on & off ..... if(message == WM_NCACTIVATE) dxw.bActive = wparam; if(dxw.bActive) (*pSetWindowPos)(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); if(dxw.dwFlags6 & UNACQUIRE){ ToggleAcquiredDevices(dxw.bActive); } if(dxw.dwFlags1 & UNNOTIFY){ DefWindowProc(hwnd, message, wparam, lparam); return false; } break; case WM_NCMOUSEMOVE: // Posted to a window when the cursor is moved within the nonclient area of the window. // This message is posted to the window that contains the cursor. // If a window has captured the mouse, this message is not posted. // V2.1.90: on nonclient areas the cursor is always shown. while((*pShowCursor)(1) < 0); break; case WM_MOUSEMOVE: if(dxw.Windowize){ prev.x = LOWORD(lparam); prev.y = HIWORD(lparam); if(dxw.IsFullScreen()){ if (dxw.dwFlags1 & HIDEHWCURSOR){ (*pGetClientRect)(hwnd, &rect); if(prev.x >= 0 && prev.x < rect.right && prev.y >= 0 && prev.y < rect.bottom) while((*pShowCursor)(0) >= 0); else while((*pShowCursor)(1) < 0); } if (dxw.dwFlags1 & SHOWHWCURSOR){ while((*pShowCursor)(1) < 0); } } if((dxw.dwFlags1 & MODIFYMOUSE) && !(dxw.dwFlags1 & MESSAGEPROC)){ // mouse processing // scale mouse coordinates curr=dxw.FixCursorPos(prev); //v2.02.30 lparam = MAKELPARAM(curr.x, curr.y); OutTraceC("WindowProc: hwnd=%x pos XY=(%d,%d)->(%d,%d)\n", hwnd, prev.x, prev.y, curr.x, curr.y); } GetHookInfo()->CursorX=LOWORD(lparam); GetHookInfo()->CursorY=HIWORD(lparam); } break; // fall through cases: case WM_MOUSEWHEEL: case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_LBUTTONDBLCLK: case WM_RBUTTONDOWN: case WM_RBUTTONUP: case WM_RBUTTONDBLCLK: case WM_MBUTTONDOWN: case WM_MBUTTONUP: case WM_MBUTTONDBLCLK: if(dxw.Windowize){ if((dxw.dwFlags1 & CLIPCURSOR) && ClipCursorToggleState) dxw.SetClipCursor(); if((dxw.dwFlags1 & MODIFYMOUSE) && !(dxw.dwFlags1 & MESSAGEPROC)){ // mouse processing // scale mouse coordinates prev.x = LOWORD(lparam); prev.y = HIWORD(lparam); curr = prev; if(message == WM_MOUSEWHEEL){ // v2.02.33 mousewheel fix POINT upleft={0,0}; (*pClientToScreen)(dxw.GethWnd(), &upleft); curr = dxw.SubCoordinates(curr, upleft); } curr=dxw.FixCursorPos(curr); //v2.02.30 lparam = MAKELPARAM(curr.x, curr.y); OutTraceC("WindowProc: hwnd=%x pos XY=(%d,%d)->(%d,%d)\n", hwnd, prev.x, prev.y, curr.x, curr.y); } GetHookInfo()->CursorX=LOWORD(lparam); GetHookInfo()->CursorY=HIWORD(lparam); } break; case WM_SETFOCUS: OutTraceDW("WindowProc: hwnd=%x GOT FOCUS\n", hwnd); if(dxw.dwFlags1 & CLIPCURSOR) dxw.SetClipCursor(); if (dxw.dwFlags1 & ENABLECLIPPING) extClipCursor(lpClipRegion); break; case WM_KILLFOCUS: OutTraceDW("WindowProc: hwnd=%x LOST FOCUS\n", hwnd); if (dxw.dwFlags1 & CLIPCURSOR) dxw.EraseClipCursor(); if (dxw.dwFlags1 & ENABLECLIPPING) (*pClipCursor)(NULL); break; case WM_SYSCOMMAND: // v2.03.56.fix1 by FunkyFr3sh: ensure that "C&C Red Alert 2" receives the WM_SYSCOMMAND / SC_CLOSE message // that likely is filtered by the application logic if(dxw.Windowize && (wparam == SC_CLOSE) && (dxw.dwFlags6 & TERMINATEONCLOSE)) { return (*pDefWindowProcA)(hwnd, message, wparam, lparam); } break; case WM_CLOSE: // Beware: closing main window does not always mean that the program is about to terminate!!! extern void gShowHideTaskBar(BOOL); if(dxw.dwFlags6 & CONFIRMONCLOSE){ OutTraceDW("WindowProc: WM_CLOSE - terminating process?\n"); if (MessageBoxA(NULL, "Do you really want to exit the game?", "DxWnd", MB_YESNO | MB_TASKMODAL) != IDYES) return FALSE; } if(dxw.dwFlags6 & HIDETASKBAR) gShowHideTaskBar(FALSE); if(dxw.dwFlags3 & FORCE16BPP) RecoverScreenMode(); if(dxw.dwFlags6 & TERMINATEONCLOSE) TerminateProcess(GetCurrentProcess(),0); break; case WM_SYSKEYDOWN: case WM_KEYDOWN: if(!(dxw.dwFlags4 & ENABLEHOTKEYS)) break; OutTraceW("event %s wparam=%x lparam=%x\n", (message==WM_SYSKEYDOWN)?"WM_SYSKEYDOWN":"WM_KEYDOWN", wparam, lparam); UINT DxWndKey; DxWndKey=dxw.MapKeysConfig(message, lparam, wparam); switch (DxWndKey){ case DXVK_CLIPTOGGLE: if(dxw.dwFlags1 & CLIPCURSOR){ OutTraceDW("WindowProc: WM_SYSKEYDOWN key=%x ToggleState=%x\n",wparam,ClipCursorToggleState); ClipCursorToggleState = !ClipCursorToggleState; ClipCursorToggleState ? dxw.SetClipCursor() : dxw.EraseClipCursor(); } break; case DXVK_REFRESH: dxw.ScreenRefresh(); break; case DXVK_LOGTOGGLE: dx_ToggleLogging(); break; case DXVK_PLOCKTOGGLE: dx_TogglePositionLock(hwnd); break; case DXVK_FPSTOGGLE: dx_ToggleFPS(); break; //case DXVK_FREEZETIME: // dxw.ToggleFreezedTime(); // break; case DXVK_TIMEFAST: case DXVK_TIMESLOW: if (dxw.dwFlags2 & TIMESTRETCH) { if (DxWndKey == DXVK_TIMESLOW && (dxw.TimeShift < 8)) dxw.TimeShift++; if (DxWndKey == DXVK_TIMEFAST && (dxw.TimeShift > -8)) dxw.TimeShift--; GetHookInfo()->TimeShift=dxw.TimeShift; OutTrace("Time Stretch: shift=%d speed=%s\n", dxw.TimeShift, dxw.GetTSCaption()); } break; case DXVK_TIMETOGGLE: if (dxw.dwFlags2 & TIMESTRETCH) { if(TimeShiftToggle){ SaveTimeShift=dxw.TimeShift; dxw.TimeShift=0; } else{ dxw.TimeShift=SaveTimeShift; } TimeShiftToggle = !TimeShiftToggle; GetHookInfo()->TimeShift=dxw.TimeShift; } break; case DXVK_ALTF4: if (dxw.dwFlags1 & HANDLEALTF4) { OutTraceDW("WindowProc: WM_SYSKEYDOWN(ALT-F4) - terminating process\n"); TerminateProcess(GetCurrentProcess(),0); } break; case DXVK_PRINTSCREEN: DDrawScreenShot(); break; case DXVK_CORNERIZE: dx_Cornerize(hwnd); break; case DXVK_FULLSCREEN: dx_FullScreenToggle(hwnd); break; case DXVK_FAKEDESKTOP: dx_DesktopToggle(hwnd, FALSE); break; case DXVK_FAKEWORKAREA: dx_DesktopToggle(hwnd, TRUE); default: break; } default: break; } if (dxw.dwFlags1 & AUTOREFRESH) dxw.ScreenRefresh(); pWindowProc=dxwws.GetProc(hwnd); //OutTraceB("WindowProc: pWindowProc=%x extWindowProc=%x message=%x(%s) wparam=%x lparam=%x\n", // (*pWindowProc), extWindowProc, message, ExplainWinMessage(message), wparam, lparam); if(pWindowProc) { LRESULT ret; // v2.02.36: use CallWindowProc that handles WinProc handles ret=(*pCallWindowProcA)(pWindowProc, hwnd, message, wparam, lparam); // save last NCHITTEST cursor position for use with KEEPASPECTRATIO scaling if(message==WM_NCHITTEST) LastCursorPos=ret; // v2.1.89: if FORCEWINRESIZE add standard processing for the missing WM_NC* messages if(dxw.dwFlags2 & FORCEWINRESIZE){ switch(message){ //case WM_NCHITTEST: //case WM_NCPAINT: //case WM_NCMOUSEMOVE: //case WM_NCCALCSIZE: //case WM_NCACTIVATE: case WM_SETCURSOR: // shows a different cursor when moving on borders case WM_NCLBUTTONDOWN: // intercepts mouse down on borders case WM_NCLBUTTONUP: // intercepts mouse up on borders ret=(*pDefWindowProcA)(hwnd, message, wparam, lparam); break; } } return ret; } //OutTraceDW("ASSERT: WindowProc mismatch hwnd=%x\n", hwnd); // ??? maybe it's a normal condition, whenever you don't have a WindowProc routine // like in Commandos 2. Flag it? char sMsg[81]; sprintf(sMsg,"ASSERT: WindowProc mismatch hwnd=%x\n", hwnd); OutTraceDW(sMsg); if (IsAssertEnabled) MessageBox(0, sMsg, "WindowProc", MB_OK | MB_ICONEXCLAMATION); return (*pDefWindowProcA)(hwnd, message, wparam, lparam); }