1
0
mirror of https://github.com/DxWnd/DxWnd.reloaded synced 2024-12-30 09:25:35 +01:00
DxWnd.reloaded/dll/winproc.cpp

738 lines
24 KiB
C++
Raw Normal View History

#define _WIN32_WINNT 0x0600
#define WIN32_LEAN_AND_MEAN
#define _CRT_SECURE_NO_DEPRECATE 1
#include <windows.h>
#include <stdio.h>
#include <stdarg.h>
#include "dxwnd.h"
#include "dxwcore.hpp"
#include "dxhelper.h"
extern void SuppressIMEWindow();
extern void RecoverScreenMode();
extern void dx_FullScreenToggle(HWND);
extern void dx_DesktopToggle(HWND, BOOL);
extern BOOL JoyProcessMouseWheelMessage(WPARAM, LPARAM);
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) {
t=tn;
(*pInvalidateRect)(hwnd, NULL, TRUE);
}
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");
(*pSetWindowLong)(hwnd, GWL_STYLE, OldStyle);
(*pSetWindowLong)(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 = (*pGetWindowLong)(hwnd, GWL_STYLE);
OldExtStyle = (*pGetWindowLong)(hwnd, GWL_EXSTYLE);
(*pSetWindowLong)(hwnd, GWL_STYLE, WS_VISIBLE|WS_CLIPSIBLINGS|WS_OVERLAPPED);
(*pSetWindowLong)(hwnd, GWL_EXSTYLE, 0);
(*pMoveWindow)(hwnd, 0, 0, dxw.GetScreenWidth(), dxw.GetScreenHeight(), TRUE);
}
bCornerized = !bCornerized; // switch toggle
(*pUpdateWindow)(hwnd);
dxw.ScreenRefresh();
}
LRESULT LastCursorPos;
void SetIdlePriority(BOOL idle)
{
OutTrace("Setting priority class to %s\n", idle ? "IDLE_PRIORITY_CLASS" : "NORMAL_PRIORITY_CLASS");
if(!SetPriorityClass(GetCurrentProcess(), idle ? IDLE_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS))
OutTraceE("SetPriorityClass ERROR: err=%d at %d\n", GetLastError(), __LINE__);
}
void ExplainMsg(char *ApiName, HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
2017-03-25 09:58:54 -04:00
char sPos[321];
sPos[320]=0;
sPos[0]=0;
switch(Msg){
case WM_WINDOWPOSCHANGING:
case WM_WINDOWPOSCHANGED:
LPWINDOWPOS wp;
wp = (LPWINDOWPOS)lParam;
2017-03-25 09:58:54 -04:00
sprintf_s(sPos, 320, " 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:
2017-03-25 09:58:54 -04:00
sprintf_s(sPos, 320, " pos=(%d,%d)", HIWORD(lParam), LOWORD(lParam));
break;
case WM_STYLECHANGING:
case WM_STYLECHANGED:
LPSTYLESTRUCT style;
style = (LPSTYLESTRUCT)lParam;
if(wParam == GWL_STYLE) sprintf_s(sPos, 320, "style=%x(%s)->%x(%s)",
style->styleOld, ExplainStyle(style->styleOld), style->styleNew, ExplainStyle(style->styleNew));
if(wParam == GWL_EXSTYLE) sprintf_s(sPos, 320, "exstyle=%x(%s)->%x(%s)",
style->styleOld, ExplainExStyle(style->styleOld), style->styleNew, ExplainExStyle(style->styleNew));
break;
case WM_SIZE:
static char *modes[5]={"RESTORED", "MINIMIZED", "MAXIMIZED", "MAXSHOW", "MAXHIDE"};
2017-03-25 09:58:54 -04:00
sprintf_s(sPos, 320, " mode=SIZE_%s size=(%dx%d)", modes[wParam % 5], HIWORD(lParam), LOWORD(lParam));
break;
}
OutTrace("%s[%x]: WinMsg=[0x%x]%s(%x,%x) %s\n", ApiName, hwnd, Msg, ExplainWinMessage(Msg), wParam, lParam, sPos);
}
static BOOL IsWindowMovingMessage(int msg)
{
switch(msg){
// minimum set for win move/resize on Win10
case WM_NCLBUTTONDOWN:
case WM_NCLBUTTONUP:
case WM_WINDOWPOSCHANGED:
case WM_WINDOWPOSCHANGING:
case WM_STYLECHANGING:
case WM_STYLECHANGED:
return TRUE;
break;
}
return FALSE;
}
LRESULT CALLBACK extWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
POINT prev, curr;
RECT rect;
static int i=0;
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(int);
if(DoOnce){
DoOnce=FALSE;
IsToBeLocked=(dxw.dwFlags1 & LOCKWINPOS);
LastTimeShift=SaveTimeShift=dxw.TimeShift;
}
// v2.1.93: adjust clipping region
if(IsTraceW) ExplainMsg("WindowProc", hwnd, message, wparam, lparam);
if(dxw.dwFlags3 & (FILTERMESSAGES|DEFAULTMESSAGES)){
switch(message){
2017-03-25 09:59:46 -04:00
case WM_NCMOUSELEAVE:
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:
case WM_MOVE:
case WM_MOVING:
if(dxw.dwFlags3 & FILTERMESSAGES){
OutTraceDW("WindowProc[%x]: SUPPRESS WinMsg=[0x%x]%s(%x,%x)\n", hwnd, message, ExplainWinMessage(message), wparam, lparam);
return 0;
}
else {
OutTraceDW("WindowProc[%x]: DEFAULT WinMsg=[0x%x]%s(%x,%x)\n", hwnd, message, ExplainWinMessage(message), wparam, lparam);
return (*pDefWindowProcA)(hwnd, message, wparam, lparam);
}
}
}
// v2.04.11: the processing of al least WM_WINPOSCHANG-ING/ED for "Man TT Superbike" must be placed
// here, before and avoiding the call to the original callback because of the AdjustWindowRect that
// is inside the callback and would keep the position fixed.
if(dxw.dwFlags2 & FORCEWINRESIZE){
//ExplainMsg("WindowProc", hwnd, message, wparam, lparam);
if(IsWindowMovingMessage(message)){
return (*pDefWindowProcA)(hwnd, message, wparam, lparam);
}
}
if(LastTimeShift != dxw.TimeShift){
extern void SetVSyncDelays(int, LPDIRECTDRAW);
extern LPDIRECTDRAW lpPrimaryDD;
extern int iBakBufferVersion;
if(dxw.dwFlags4 & STRETCHTIMERS) dxw.RenewTimers();
if(lpPrimaryDD) SetVSyncDelays(iBakBufferVersion, 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:
// v2.02.30: don't alter child and other windows....
// v2.04.09: comment inconsistent with code. Added '!' to if expression ....
if(!((dxw.dwFlags1 & LOCKWINPOS) && (hwnd == dxw.GethWnd()) && dxw.IsFullScreen())){
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:
// which one is good ?
if((dxw.dwFlags2 & FIXNCHITTEST) && (dxw.dwFlags1 & MODIFYMOUSE)){ // mouse processing
//if((dxw.dwFlags2 & FIXNCHITTEST) && (dxw.dwFlags1 & MODIFYMOUSE) && !(dxw.dwFlags1 & MESSAGEPROC)){ // 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);
OutTraceC("WindowProc[%x]: fixed WM_NCHITTEST pt=(%d,%d)\n", hwnd, cursor.x, cursor.y);
}
else
return ret;
}
break;
case WM_ERASEBKGND:
// v2.03.97: fix for Adrenix lost backgrounds, thanks to Riitaoja hunt!
if(dxw.Windowize && dxw.IsRealDesktop(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;
2017-03-25 09:58:54 -04:00
case WM_STYLECHANGING:
case WM_STYLECHANGED:
if(dxw.dwFlags1 & LOCKWINSTYLE) {
OutTraceDW("WindowProc: %s - suppressed\n", message==WM_STYLECHANGING ? "WM_STYLECHANGING" : "WM_STYLECHANGED");
return 1;
}
break;
case WM_WINDOWPOSCHANGING:
case WM_WINDOWPOSCHANGED:
if(dxw.Windowize && dxw.IsFullScreen()){
LPWINDOWPOS wp = (LPWINDOWPOS)lparam;
extern HWND hControlParentWnd;
if(dxw.dwFlags5 & NOWINPOSCHANGES){
OutTraceDW("WindowProc: %s - suppressed\n", message==WM_WINDOWPOSCHANGED ? "WM_WINDOWPOSCHANGED" : "WM_WINDOWPOSCHANGING");
return 0;
}
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);
if(message==WM_WINDOWPOSCHANGED) {
// try to lock main wind & control parent together
if(dxw.IsDesktop(hwnd) && hControlParentWnd) {
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 (dxw.dwFlags6 & ACTIVATEAPP){
PostMessage(hwnd, WM_ACTIVATEAPP, 1, 0);
}
// v2.03.91.fx4: keep position coordinates updated!
if(!(wp->flags & (SWP_NOMOVE|SWP_NOSIZE))) dxw.UpdateDesktopCoordinates();
}
}
break;
case WM_ENTERSIZEMOVE:
if(IsToBeLocked){
dxw.dwFlags1 &= ~LOCKWINPOS;
}
while((*pShowCursor)(1) < 0);
if (
((dxw.dwFlags1 & CLIPCURSOR) && !(dxw.dwFlags8 & CLIPLOCKED)) ||
(dxw.dwFlags1 & DISABLECLIPPING)) {
dxw.EraseClipCursor();
}
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 & DISABLECLIPPING) 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);
}
dxw.UpdateDesktopCoordinates();
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:
if(dxw.dwFlags6 & VIRTUALJOYSTICK) {
if(dxw.Windowize && (dxw.dwFlags1 & CLIPCURSOR) && !dxw.IsClipCursorActive()) dxw.SetClipCursor();
if (JoyProcessMouseWheelMessage(wparam, lparam)) return 0;
} // fall through
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) && !dxw.IsClipCursorActive()) {
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 & DISABLECLIPPING) extClipCursor(lpClipRegion);
if (dxw.dwFlags8 & BACKGROUNDPRIORITY) SetIdlePriority(FALSE);
break;
case WM_KILLFOCUS:
OutTraceDW("WindowProc: hwnd=%x LOST FOCUS\n", hwnd);
if (
((dxw.dwFlags1 & CLIPCURSOR) && !(dxw.dwFlags8 & CLIPLOCKED)) ||
(dxw.dwFlags1 & DISABLECLIPPING)){
dxw.EraseClipCursor();
}
if (dxw.dwFlags8 & BACKGROUNDPRIORITY) SetIdlePriority(TRUE);
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
// v2.03.91: from msdn - In WM_SYSCOMMAND messages, the four low-order bits of the wParam parameter are used
// internally by the system. To obtain the correct result when testing the value of wParam, an application
// must combine the value 0xFFF0 with the wParam value by using the bitwise AND operator.
if(dxw.Windowize && ((wparam & 0xFFF0)== SC_CLOSE) && (dxw.dwFlags6 & TERMINATEONCLOSE)) {
LRESULT lres;
lres = (*pDefWindowProcA)(hwnd, message, wparam, lparam);
return lres;
}
if(dxw.Windowize){
static int iLastX, iLastY, iLastW, iLastH;
switch(wparam & 0xFFF0){
case SC_MINIMIZE:
dxw.IsVisible = FALSE;
iLastX = dxw.iPosX; iLastY = dxw.iPosY;
iLastW = dxw.iSizX; iLastH = dxw.iSizY;
dxw.iPosX = dxw.iPosY = dxw.iSizX = dxw.iSizY = 0;
break;
case SC_RESTORE:
dxw.IsVisible = TRUE;
dxw.iPosX = iLastX; dxw.iPosY = iLastY;
dxw.iSizX = iLastW; dxw.iSizY = iLastH;
break;
case SC_MAXIMIZE:
dxw.IsVisible = TRUE;
break;
}
}
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:
if ((dxw.dwFlags1 & HANDLEALTF4) && (wparam == VK_F4)) {
OutTraceDW("WindowProc: WM_SYSKEYDOWN(ALT-F4) - terminating process\n");
TerminateProcess(GetCurrentProcess(),0);
}
// fall through
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:
OutTraceDW("WindowProc: WM_SYSKEYDOWN key=%x clipper=%x\n", wparam, dxw.IsClipCursorActive());
dxw.IsClipCursorActive() ? dxw.EraseClipCursor() : dxw.SetClipCursor();
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(virtual Alt-F4) - terminating process\n");
TerminateProcess(GetCurrentProcess(),0);
}
break;
case DXVK_PRINTSCREEN:
DDrawScreenShot(dxw.dwDDVersion);
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);
switch(message){
case WM_SIZE:
//case WM_WINDOWPOSCHANGED: - no good!!!!
// update new coordinates
if (dxw.IsFullScreen()) dxw.UpdateDesktopCoordinates();
break;
case WM_NCHITTEST:
// save last NCHITTEST cursor position for use with KEEPASPECTRATIO scaling
LastCursorPos=ret;
break;
}
// 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);
}