Skip to content

Commit fdba69f

Browse files
committed
fix(window): enable easy border grabbing and show standard cursors outside client area
1 parent d342273 commit fdba69f

3 files changed

Lines changed: 142 additions & 27 deletions

File tree

Core/GameEngineDevice/Source/Win32Device/GameClient/Win32Mouse.cpp

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -435,23 +435,30 @@ void Win32Mouse::capture()
435435
{
436436

437437
RECT rect;
438-
::GetClientRect(ApplicationHWnd, &rect);
438+
if (TheGlobalData && TheGlobalData->m_windowed)
439+
{
440+
::GetWindowRect(ApplicationHWnd, &rect);
441+
}
442+
else
443+
{
444+
::GetClientRect(ApplicationHWnd, &rect);
439445

440-
POINT leftTop;
441-
leftTop.x = rect.left;
442-
leftTop.y = rect.top;
446+
POINT leftTop;
447+
leftTop.x = rect.left;
448+
leftTop.y = rect.top;
443449

444-
POINT rightBottom;
445-
rightBottom.x = rect.right;
446-
rightBottom.y = rect.bottom;
450+
POINT rightBottom;
451+
rightBottom.x = rect.right;
452+
rightBottom.y = rect.bottom;
447453

448-
::ClientToScreen(ApplicationHWnd, &leftTop);
449-
::ClientToScreen(ApplicationHWnd, &rightBottom);
454+
::ClientToScreen(ApplicationHWnd, &leftTop);
455+
::ClientToScreen(ApplicationHWnd, &rightBottom);
450456

451-
rect.left = leftTop.x;
452-
rect.top = leftTop.y;
453-
rect.right = rightBottom.x;
454-
rect.bottom = rightBottom.y;
457+
rect.left = leftTop.x;
458+
rect.top = leftTop.y;
459+
rect.right = rightBottom.x;
460+
rect.bottom = rightBottom.y;
461+
}
455462

456463
if (::ClipCursor(&rect))
457464
{

Generals/Code/Main/WinMain.cpp

Lines changed: 61 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@
5858
#include "GameClient/GameClient.h"
5959
#include "GameLogic/GameLogic.h" ///< @todo for demo, remove
6060
#include "GameClient/Mouse.h"
61+
#include "GameClient/Display.h"
62+
#include "GameClient/HeaderTemplate.h"
63+
#include "GameClient/Shell.h"
6164
#include "GameClient/IMEManager.h"
6265
#include "Win32Device/GameClient/Win32Mouse.h"
6366
#include "Win32Device/Common/Win32GameEngine.h"
@@ -294,6 +297,7 @@ static const char *messageToString(unsigned int message)
294297
LRESULT CALLBACK WndProc( HWND hWnd, UINT message,
295298
WPARAM wParam, LPARAM lParam )
296299
{
300+
static Bool gInSizeMove = FALSE;
297301

298302
try
299303
{
@@ -402,7 +406,7 @@ LRESULT CALLBACK WndProc( HWND hWnd, UINT message,
402406
//-------------------------------------------------------------------------
403407
case WM_MOVE:
404408
{
405-
if (TheMouse)
409+
if (TheMouse && !gInSizeMove)
406410
TheMouse->refreshCursorCapture();
407411

408412
break;
@@ -415,12 +419,60 @@ LRESULT CALLBACK WndProc( HWND hWnd, UINT message,
415419
if (!gInitializing)
416420
gDoPaint = false;
417421

418-
if (TheMouse)
422+
if (TheMouse && !gInSizeMove)
419423
TheMouse->refreshCursorCapture();
420424

421425
break;
422426
}
423427

428+
case WM_ENTERSIZEMOVE:
429+
{
430+
gInSizeMove = TRUE;
431+
::ClipCursor(nullptr);
432+
break;
433+
}
434+
435+
case WM_EXITSIZEMOVE:
436+
{
437+
gInSizeMove = FALSE;
438+
if (TheDisplay && TheGlobalData && TheGlobalData->m_windowed)
439+
{
440+
RECT rect;
441+
if (GetClientRect(hWnd, &rect))
442+
{
443+
Int newWidth = rect.right - rect.left;
444+
Int newHeight = rect.bottom - rect.top;
445+
if (newWidth > 0 && newHeight > 0 && (newWidth != TheDisplay->getWidth() || newHeight != TheDisplay->getHeight()))
446+
{
447+
if (TheDisplay->setDisplayMode(newWidth, newHeight, TheDisplay->getBitDepth(), TRUE))
448+
{
449+
TheWritableGlobalData->m_xResolution = newWidth;
450+
TheWritableGlobalData->m_yResolution = newHeight;
451+
452+
if (TheHeaderTemplateManager)
453+
TheHeaderTemplateManager->onResolutionChanged();
454+
if (TheMouse)
455+
TheMouse->onResolutionChanged();
456+
457+
if (TheShell)
458+
TheShell->recreateWindowLayouts();
459+
460+
if (TheInGameUI)
461+
{
462+
TheInGameUI->recreateControlBar();
463+
TheInGameUI->refreshCustomUiResources();
464+
}
465+
}
466+
}
467+
}
468+
}
469+
if (TheMouse)
470+
{
471+
TheMouse->refreshCursorCapture();
472+
}
473+
break;
474+
}
475+
424476
// ------------------------------------------------------------------------
425477
case WM_SETFOCUS:
426478
{
@@ -593,12 +645,14 @@ LRESULT CALLBACK WndProc( HWND hWnd, UINT message,
593645
return 0;
594646
}
595647

596-
//-------------------------------------------------------------------------
597648
case WM_SETCURSOR:
598649
{
599-
if (TheWin32Mouse && (HWND)wParam == ApplicationHWnd)
650+
if (TheWin32Mouse && (HWND)wParam == ApplicationHWnd && LOWORD(lParam) == HTCLIENT)
651+
{
600652
TheWin32Mouse->setCursor(TheWin32Mouse->getMouseCursor());
601-
return TRUE; //tell Windows not to reset mouse cursor image to default.
653+
return TRUE; //tell Windows not to reset mouse cursor image to default.
654+
}
655+
break;
602656
}
603657

604658
case WM_PAINT:
@@ -706,10 +760,10 @@ static Bool initializeAppWindows( HINSTANCE hInstance, Int nCmdShow, Bool runWin
706760
TEXT("Game Window") };
707761
RegisterClass( &wndClass );
708762

709-
// Create our main window
763+
// Create our main window
710764
windowStyle = WS_POPUP|WS_VISIBLE;
711765
if (runWindowed)
712-
windowStyle |= WS_MINIMIZEBOX | WS_SYSMENU | WS_DLGFRAME | WS_CAPTION;
766+
windowStyle |= WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_SYSMENU | WS_DLGFRAME | WS_CAPTION;
713767
else
714768
windowStyle |= WS_EX_TOPMOST | WS_SYSMENU;
715769

GeneralsMD/Code/Main/WinMain.cpp

Lines changed: 61 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@
5959
#include "GameClient/GameClient.h"
6060
#include "GameLogic/GameLogic.h" ///< @todo for demo, remove
6161
#include "GameClient/Mouse.h"
62+
#include "GameClient/Display.h"
63+
#include "GameClient/HeaderTemplate.h"
64+
#include "GameClient/Shell.h"
6265
#include "GameClient/IMEManager.h"
6366
#include "Win32Device/GameClient/Win32Mouse.h"
6467
#include "Win32Device/Common/Win32GameEngine.h"
@@ -296,6 +299,7 @@ static const char *messageToString(unsigned int message)
296299
LRESULT CALLBACK WndProc( HWND hWnd, UINT message,
297300
WPARAM wParam, LPARAM lParam )
298301
{
302+
static Bool gInSizeMove = FALSE;
299303

300304
try
301305
{
@@ -404,7 +408,7 @@ LRESULT CALLBACK WndProc( HWND hWnd, UINT message,
404408
//-------------------------------------------------------------------------
405409
case WM_MOVE:
406410
{
407-
if (TheMouse)
411+
if (TheMouse && !gInSizeMove)
408412
TheMouse->refreshCursorCapture();
409413

410414
break;
@@ -417,12 +421,60 @@ LRESULT CALLBACK WndProc( HWND hWnd, UINT message,
417421
if (!gInitializing)
418422
gDoPaint = false;
419423

420-
if (TheMouse)
424+
if (TheMouse && !gInSizeMove)
421425
TheMouse->refreshCursorCapture();
422426

423427
break;
424428
}
425429

430+
case WM_ENTERSIZEMOVE:
431+
{
432+
gInSizeMove = TRUE;
433+
::ClipCursor(nullptr);
434+
break;
435+
}
436+
437+
case WM_EXITSIZEMOVE:
438+
{
439+
gInSizeMove = FALSE;
440+
if (TheDisplay && TheGlobalData && TheGlobalData->m_windowed)
441+
{
442+
RECT rect;
443+
if (GetClientRect(hWnd, &rect))
444+
{
445+
Int newWidth = rect.right - rect.left;
446+
Int newHeight = rect.bottom - rect.top;
447+
if (newWidth > 0 && newHeight > 0 && (newWidth != TheDisplay->getWidth() || newHeight != TheDisplay->getHeight()))
448+
{
449+
if (TheDisplay->setDisplayMode(newWidth, newHeight, TheDisplay->getBitDepth(), TRUE))
450+
{
451+
TheWritableGlobalData->m_xResolution = newWidth;
452+
TheWritableGlobalData->m_yResolution = newHeight;
453+
454+
if (TheHeaderTemplateManager)
455+
TheHeaderTemplateManager->onResolutionChanged();
456+
if (TheMouse)
457+
TheMouse->onResolutionChanged();
458+
459+
if (TheShell)
460+
TheShell->recreateWindowLayouts();
461+
462+
if (TheInGameUI)
463+
{
464+
TheInGameUI->recreateControlBar();
465+
TheInGameUI->refreshCustomUiResources();
466+
}
467+
}
468+
}
469+
}
470+
}
471+
if (TheMouse)
472+
{
473+
TheMouse->refreshCursorCapture();
474+
}
475+
break;
476+
}
477+
426478
// ------------------------------------------------------------------------
427479
case WM_SETFOCUS:
428480
{
@@ -595,12 +647,14 @@ LRESULT CALLBACK WndProc( HWND hWnd, UINT message,
595647
return 0;
596648
}
597649

598-
//-------------------------------------------------------------------------
599650
case WM_SETCURSOR:
600651
{
601-
if (TheWin32Mouse && (HWND)wParam == ApplicationHWnd)
652+
if (TheWin32Mouse && (HWND)wParam == ApplicationHWnd && LOWORD(lParam) == HTCLIENT)
653+
{
602654
TheWin32Mouse->setCursor(TheWin32Mouse->getMouseCursor());
603-
return TRUE; //tell Windows not to reset mouse cursor image to default.
655+
return TRUE; //tell Windows not to reset mouse cursor image to default.
656+
}
657+
break;
604658
}
605659

606660
case WM_PAINT:
@@ -708,10 +762,10 @@ static Bool initializeAppWindows( HINSTANCE hInstance, Int nCmdShow, Bool runWin
708762
TEXT("Game Window") };
709763
RegisterClass( &wndClass );
710764

711-
// Create our main window
765+
// Create our main window
712766
windowStyle = WS_POPUP|WS_VISIBLE;
713767
if (runWindowed)
714-
windowStyle |= WS_MINIMIZEBOX | WS_SYSMENU | WS_DLGFRAME | WS_CAPTION;
768+
windowStyle |= WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_SYSMENU | WS_DLGFRAME | WS_CAPTION;
715769
else
716770
windowStyle |= WS_EX_TOPMOST | WS_SYSMENU;
717771

0 commit comments

Comments
 (0)