mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-30 07:41:22 +00:00
Create a MainWindow class that manages the main win32 window of the application
This commit is contained in:
parent
3ad6793ba3
commit
018fb2917f
24 changed files with 1187 additions and 1108 deletions
|
@ -446,6 +446,7 @@ set( PLAT_WIN32_SOURCES
|
||||||
common/platform/win32/i_rawps2.cpp
|
common/platform/win32/i_rawps2.cpp
|
||||||
common/platform/win32/i_xinput.cpp
|
common/platform/win32/i_xinput.cpp
|
||||||
common/platform/win32/i_main.cpp
|
common/platform/win32/i_main.cpp
|
||||||
|
common/platform/win32/i_mainwindow.cpp
|
||||||
common/platform/win32/i_system.cpp
|
common/platform/win32/i_system.cpp
|
||||||
common/platform/win32/i_specialpaths.cpp
|
common/platform/win32/i_specialpaths.cpp
|
||||||
common/platform/win32/st_start.cpp
|
common/platform/win32/st_start.cpp
|
||||||
|
|
|
@ -77,7 +77,6 @@ public:
|
||||||
void NetDone();
|
void NetDone();
|
||||||
bool NetLoop(bool (*timer_callback)(void*), void* userdata);
|
bool NetLoop(bool (*timer_callback)(void*), void* userdata);
|
||||||
protected:
|
protected:
|
||||||
long long NetMarqueeMode;
|
|
||||||
int NetMaxPos, NetCurPos;
|
int NetMaxPos, NetCurPos;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -50,9 +50,7 @@
|
||||||
#include "base_sysfb.h"
|
#include "base_sysfb.h"
|
||||||
#include "win32basevideo.h"
|
#include "win32basevideo.h"
|
||||||
#include "c_dispatch.h"
|
#include "c_dispatch.h"
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
extern HWND Window;
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
|
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
|
||||||
|
@ -85,7 +83,7 @@ EXTERN_CVAR(Int, vid_defheight)
|
||||||
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &displaysettings);
|
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &displaysettings);
|
||||||
scrwidth = (int)displaysettings.dmPelsWidth;
|
scrwidth = (int)displaysettings.dmPelsWidth;
|
||||||
scrheight = (int)displaysettings.dmPelsHeight;
|
scrheight = (int)displaysettings.dmPelsHeight;
|
||||||
GetWindowRect(Window, &rect);
|
GetWindowRect(mainwindow.GetHandle(), &rect);
|
||||||
cx = scrwidth / 2;
|
cx = scrwidth / 2;
|
||||||
cy = scrheight / 2;
|
cy = scrheight / 2;
|
||||||
if (in_w > 0) winw = in_w;
|
if (in_w > 0) winw = in_w;
|
||||||
|
@ -139,11 +137,11 @@ void SystemBaseFrameBuffer::SaveWindowedPos()
|
||||||
}
|
}
|
||||||
// Make sure we only save the window position if it's not fullscreen.
|
// Make sure we only save the window position if it's not fullscreen.
|
||||||
static const int WINDOW_STYLE = WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX;
|
static const int WINDOW_STYLE = WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX;
|
||||||
if ((GetWindowLong(Window, GWL_STYLE) & WINDOW_STYLE) == WINDOW_STYLE)
|
if ((GetWindowLong(mainwindow.GetHandle(), GWL_STYLE) & WINDOW_STYLE) == WINDOW_STYLE)
|
||||||
{
|
{
|
||||||
RECT wrect;
|
RECT wrect;
|
||||||
|
|
||||||
if (GetWindowRect(Window, &wrect))
|
if (GetWindowRect(mainwindow.GetHandle(), &wrect))
|
||||||
{
|
{
|
||||||
// If (win_x,win_y) specify to center the window, don't change them
|
// If (win_x,win_y) specify to center the window, don't change them
|
||||||
// if the window is still centered.
|
// if the window is still centered.
|
||||||
|
@ -171,7 +169,7 @@ void SystemBaseFrameBuffer::SaveWindowedPos()
|
||||||
win_h = wrect.bottom - wrect.top;
|
win_h = wrect.bottom - wrect.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
win_maximized = IsZoomed(Window) == TRUE;
|
win_maximized = IsZoomed(mainwindow.GetHandle()) == TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,10 +202,10 @@ void SystemBaseFrameBuffer::RestoreWindowedPos()
|
||||||
}
|
}
|
||||||
KeepWindowOnScreen(winx, winy, winw, winh, scrwidth, scrheight);
|
KeepWindowOnScreen(winx, winy, winw, winh, scrwidth, scrheight);
|
||||||
}
|
}
|
||||||
SetWindowPos(Window, nullptr, winx, winy, winw, winh, SWP_NOZORDER | SWP_FRAMECHANGED);
|
SetWindowPos(mainwindow.GetHandle(), nullptr, winx, winy, winw, winh, SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||||
|
|
||||||
if (win_maximized && !Args->CheckParm("-0"))
|
if (win_maximized && !Args->CheckParm("-0"))
|
||||||
ShowWindow(Window, SW_MAXIMIZE);
|
ShowWindow(mainwindow.GetHandle(), SW_MAXIMIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -226,8 +224,8 @@ void SystemBaseFrameBuffer::SetWindowSize(int w, int h)
|
||||||
{
|
{
|
||||||
LONG style = WS_VISIBLE | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW;
|
LONG style = WS_VISIBLE | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW;
|
||||||
LONG exStyle = WS_EX_WINDOWEDGE;
|
LONG exStyle = WS_EX_WINDOWEDGE;
|
||||||
SetWindowLong(Window, GWL_STYLE, style);
|
SetWindowLong(mainwindow.GetHandle(), GWL_STYLE, style);
|
||||||
SetWindowLong(Window, GWL_EXSTYLE, exStyle);
|
SetWindowLong(mainwindow.GetHandle(), GWL_EXSTYLE, exStyle);
|
||||||
|
|
||||||
int winx, winy, winw, winh, scrwidth, scrheight;
|
int winx, winy, winw, winh, scrwidth, scrheight;
|
||||||
|
|
||||||
|
@ -250,8 +248,8 @@ void SystemBaseFrameBuffer::SetWindowSize(int w, int h)
|
||||||
|
|
||||||
if (!vid_fullscreen)
|
if (!vid_fullscreen)
|
||||||
{
|
{
|
||||||
ShowWindow(Window, SW_SHOWNORMAL);
|
ShowWindow(mainwindow.GetHandle(), SW_SHOWNORMAL);
|
||||||
SetWindowPos(Window, nullptr, winx, winy, winw, winh, SWP_NOZORDER | SWP_FRAMECHANGED);
|
SetWindowPos(mainwindow.GetHandle(), nullptr, winx, winy, winw, winh, SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||||
win_maximized = false;
|
win_maximized = false;
|
||||||
SetSize(GetClientWidth(), GetClientHeight());
|
SetSize(GetClientWidth(), GetClientHeight());
|
||||||
SaveWindowedPos();
|
SaveWindowedPos();
|
||||||
|
@ -302,9 +300,9 @@ void SystemBaseFrameBuffer::PositionWindow(bool fullscreen, bool initialcall)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ShowWindow(Window, SW_SHOW);
|
ShowWindow(mainwindow.GetHandle(), SW_SHOW);
|
||||||
|
|
||||||
GetWindowRect(Window, &r);
|
GetWindowRect(mainwindow.GetHandle(), &r);
|
||||||
style = WS_VISIBLE | WS_CLIPSIBLINGS;
|
style = WS_VISIBLE | WS_CLIPSIBLINGS;
|
||||||
exStyle = 0;
|
exStyle = 0;
|
||||||
|
|
||||||
|
@ -316,13 +314,13 @@ void SystemBaseFrameBuffer::PositionWindow(bool fullscreen, bool initialcall)
|
||||||
exStyle |= WS_EX_WINDOWEDGE;
|
exStyle |= WS_EX_WINDOWEDGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetWindowLong(Window, GWL_STYLE, style);
|
SetWindowLong(mainwindow.GetHandle(), GWL_STYLE, style);
|
||||||
SetWindowLong(Window, GWL_EXSTYLE, exStyle);
|
SetWindowLong(mainwindow.GetHandle(), GWL_EXSTYLE, exStyle);
|
||||||
|
|
||||||
if (fullscreen)
|
if (fullscreen)
|
||||||
{
|
{
|
||||||
SetWindowPos(Window, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
SetWindowPos(mainwindow.GetHandle(), 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||||
MoveWindow(Window, monRect.left, monRect.top, monRect.right-monRect.left, monRect.bottom-monRect.top, FALSE);
|
MoveWindow(mainwindow.GetHandle(), monRect.left, monRect.top, monRect.right-monRect.left, monRect.bottom-monRect.top, FALSE);
|
||||||
|
|
||||||
// And now, seriously, it IS in the right place. Promise.
|
// And now, seriously, it IS in the right place. Promise.
|
||||||
}
|
}
|
||||||
|
@ -352,9 +350,9 @@ SystemBaseFrameBuffer::SystemBaseFrameBuffer(void *hMonitor, bool fullscreen) :
|
||||||
m_displayDeviceName = 0;
|
m_displayDeviceName = 0;
|
||||||
PositionWindow(fullscreen, true);
|
PositionWindow(fullscreen, true);
|
||||||
|
|
||||||
HDC hDC = GetDC(Window);
|
HDC hDC = GetDC(mainwindow.GetHandle());
|
||||||
|
|
||||||
ReleaseDC(Window, hDC);
|
ReleaseDC(mainwindow.GetHandle(), hDC);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -367,10 +365,10 @@ SystemBaseFrameBuffer::~SystemBaseFrameBuffer()
|
||||||
{
|
{
|
||||||
if (!m_Fullscreen) SaveWindowedPos();
|
if (!m_Fullscreen) SaveWindowedPos();
|
||||||
|
|
||||||
ShowWindow (Window, SW_SHOW);
|
ShowWindow (mainwindow.GetHandle(), SW_SHOW);
|
||||||
SetWindowLong(Window, GWL_STYLE, WS_VISIBLE | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW);
|
SetWindowLong(mainwindow.GetHandle(), GWL_STYLE, WS_VISIBLE | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW);
|
||||||
SetWindowLong(Window, GWL_EXSTYLE, WS_EX_WINDOWEDGE);
|
SetWindowLong(mainwindow.GetHandle(), GWL_EXSTYLE, WS_EX_WINDOWEDGE);
|
||||||
SetWindowPos(Window, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
SetWindowPos(mainwindow.GetHandle(), 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||||
|
|
||||||
static_cast<Win32BaseVideo *>(Video)->Shutdown();
|
static_cast<Win32BaseVideo *>(Video)->Shutdown();
|
||||||
}
|
}
|
||||||
|
@ -407,13 +405,13 @@ void SystemBaseFrameBuffer::ToggleFullscreen(bool yes)
|
||||||
int SystemBaseFrameBuffer::GetClientWidth()
|
int SystemBaseFrameBuffer::GetClientWidth()
|
||||||
{
|
{
|
||||||
RECT rect = { 0 };
|
RECT rect = { 0 };
|
||||||
GetClientRect(Window, &rect);
|
GetClientRect(mainwindow.GetHandle(), &rect);
|
||||||
return rect.right - rect.left;
|
return rect.right - rect.left;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SystemBaseFrameBuffer::GetClientHeight()
|
int SystemBaseFrameBuffer::GetClientHeight()
|
||||||
{
|
{
|
||||||
RECT rect = { 0 };
|
RECT rect = { 0 };
|
||||||
GetClientRect(Window, &rect);
|
GetClientRect(mainwindow.GetHandle(), &rect);
|
||||||
return rect.bottom - rect.top;
|
return rect.bottom - rect.top;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,8 +49,7 @@
|
||||||
#include "m_argv.h"
|
#include "m_argv.h"
|
||||||
#include "engineerrors.h"
|
#include "engineerrors.h"
|
||||||
#include "win32glvideo.h"
|
#include "win32glvideo.h"
|
||||||
|
#include "i_mainwindow.h"
|
||||||
extern HWND Window;
|
|
||||||
|
|
||||||
extern "C" PROC zd_wglGetProcAddress(LPCSTR name);
|
extern "C" PROC zd_wglGetProcAddress(LPCSTR name);
|
||||||
|
|
||||||
|
@ -71,13 +70,13 @@ PFNWGLSWAPINTERVALEXTPROC myWglSwapIntervalExtProc;
|
||||||
|
|
||||||
SystemGLFrameBuffer::SystemGLFrameBuffer(void *hMonitor, bool fullscreen) : SystemBaseFrameBuffer(hMonitor, fullscreen)
|
SystemGLFrameBuffer::SystemGLFrameBuffer(void *hMonitor, bool fullscreen) : SystemBaseFrameBuffer(hMonitor, fullscreen)
|
||||||
{
|
{
|
||||||
if (!static_cast<Win32GLVideo*>(Video)->InitHardware(Window, 0))
|
if (!static_cast<Win32GLVideo*>(Video)->InitHardware(mainwindow.GetHandle(), 0))
|
||||||
{
|
{
|
||||||
I_FatalError("Unable to initialize OpenGL");
|
I_FatalError("Unable to initialize OpenGL");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
HDC hDC = GetDC(Window);
|
HDC hDC = GetDC(mainwindow.GetHandle());
|
||||||
const char *wglext = nullptr;
|
const char *wglext = nullptr;
|
||||||
|
|
||||||
myWglSwapIntervalExtProc = (PFNWGLSWAPINTERVALEXTPROC)zd_wglGetProcAddress("wglSwapIntervalEXT");
|
myWglSwapIntervalExtProc = (PFNWGLSWAPINTERVALEXTPROC)zd_wglGetProcAddress("wglSwapIntervalEXT");
|
||||||
|
@ -102,7 +101,7 @@ SystemGLFrameBuffer::SystemGLFrameBuffer(void *hMonitor, bool fullscreen) : Syst
|
||||||
SwapInterval = -1;
|
SwapInterval = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ReleaseDC(Window, hDC);
|
ReleaseDC(mainwindow.GetHandle(), hDC);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -52,11 +52,10 @@
|
||||||
#endif
|
#endif
|
||||||
#include "engineerrors.h"
|
#include "engineerrors.h"
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
EXTERN_CVAR(Int, vid_preferbackend)
|
EXTERN_CVAR(Int, vid_preferbackend)
|
||||||
|
|
||||||
extern HWND Window;
|
|
||||||
|
|
||||||
IVideo *Video;
|
IVideo *Video;
|
||||||
|
|
||||||
// do not include GL headers here, only declare the necessary functions.
|
// do not include GL headers here, only declare the necessary functions.
|
||||||
|
@ -117,12 +116,12 @@ void I_InitGraphics ()
|
||||||
|
|
||||||
// If the focus window is destroyed, it doesn't go back to the active window.
|
// If the focus window is destroyed, it doesn't go back to the active window.
|
||||||
// (e.g. because the net pane was up, and a button on it had focus)
|
// (e.g. because the net pane was up, and a button on it had focus)
|
||||||
if (GetFocus() == NULL && GetActiveWindow() == Window)
|
if (GetFocus() == NULL && GetActiveWindow() == mainwindow.GetHandle())
|
||||||
{
|
{
|
||||||
// Make sure it's in the foreground and focused. (It probably is
|
// Make sure it's in the foreground and focused. (It probably is
|
||||||
// already foregrounded but may not be focused.)
|
// already foregrounded but may not be focused.)
|
||||||
SetForegroundWindow(Window);
|
SetForegroundWindow(mainwindow.GetHandle());
|
||||||
SetFocus(Window);
|
SetFocus(mainwindow.GetHandle());
|
||||||
// Note that when I start a 2-player game on the same machine, the
|
// Note that when I start a 2-player game on the same machine, the
|
||||||
// window for the game that isn't focused, active, or foregrounded
|
// window for the game that isn't focused, active, or foregrounded
|
||||||
// still receives a WM_ACTIVATEAPP message telling it that it's the
|
// still receives a WM_ACTIVATEAPP message telling it that it's the
|
||||||
|
|
|
@ -65,6 +65,7 @@
|
||||||
#include "zstring.h"
|
#include "zstring.h"
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
@ -212,9 +213,6 @@ struct MiniDumpThreadData
|
||||||
|
|
||||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||||
|
|
||||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
|
||||||
void I_FlushBufferedConsoleStuff();
|
|
||||||
|
|
||||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||||
|
|
||||||
static void AddFile (HANDLE file, const char *filename);
|
static void AddFile (HANDLE file, const char *filename);
|
||||||
|
@ -445,41 +443,6 @@ void Writef (HANDLE file, const char *format, ...)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
static DWORD CALLBACK WriteLogFileStreamer(DWORD_PTR cookie, LPBYTE buffer, LONG cb, LONG *pcb)
|
|
||||||
{
|
|
||||||
DWORD didwrite;
|
|
||||||
LONG p, pp;
|
|
||||||
|
|
||||||
// Replace gray foreground color with black.
|
|
||||||
static const char *badfg = "\\red223\\green223\\blue223;";
|
|
||||||
// 4321098 765432109 876543210
|
|
||||||
// 2 1 0
|
|
||||||
for (p = pp = 0; p < cb; ++p)
|
|
||||||
{
|
|
||||||
if (buffer[p] == badfg[pp])
|
|
||||||
{
|
|
||||||
++pp;
|
|
||||||
if (pp == 25)
|
|
||||||
{
|
|
||||||
buffer[p - 1] = buffer[p - 2] = buffer[p - 3] =
|
|
||||||
buffer[p - 9] = buffer[p -10] = buffer[p -11] =
|
|
||||||
buffer[p -18] = buffer[p -19] = buffer[p -20] = '0';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pp = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!WriteFile((HANDLE)cookie, buffer, cb, &didwrite, NULL))
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
*pcb = didwrite;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -489,15 +452,21 @@ static DWORD CALLBACK WriteLogFileStreamer(DWORD_PTR cookie, LPBYTE buffer, LONG
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
HANDLE WriteLogFile(HWND edit)
|
HANDLE WriteLogFile()
|
||||||
{
|
{
|
||||||
HANDLE file;
|
HANDLE file;
|
||||||
|
|
||||||
file = CreateTempFile();
|
file = CreateTempFile();
|
||||||
if (file != INVALID_HANDLE_VALUE)
|
if (file != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
EDITSTREAM streamer = { (DWORD_PTR)file, 0, WriteLogFileStreamer };
|
auto writeFile = [&](const void* data, uint32_t size, uint32_t& written) -> bool
|
||||||
SendMessage(edit, EM_STREAMOUT, SF_RTF, (LPARAM)&streamer);
|
{
|
||||||
|
DWORD tmp = 0;
|
||||||
|
BOOL result = WriteFile(file, data, size, &tmp, nullptr);
|
||||||
|
written = tmp;
|
||||||
|
return result == TRUE;
|
||||||
|
};
|
||||||
|
mainwindow.GetLog(writeFile);
|
||||||
}
|
}
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
@ -510,7 +479,7 @@ HANDLE WriteLogFile(HWND edit)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void CreateCrashLog (const char *custominfo, DWORD customsize, HWND richlog)
|
void CreateCrashLog (const char *custominfo, DWORD customsize)
|
||||||
{
|
{
|
||||||
// Do not collect information more than once.
|
// Do not collect information more than once.
|
||||||
if (NumFiles != 0)
|
if (NumFiles != 0)
|
||||||
|
@ -560,11 +529,7 @@ void CreateCrashLog (const char *custominfo, DWORD customsize, HWND richlog)
|
||||||
AddFile (file, "local.txt");
|
AddFile (file, "local.txt");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (richlog != NULL)
|
AddFile (WriteLogFile(), "log.rtf");
|
||||||
{
|
|
||||||
I_FlushBufferedConsoleStuff();
|
|
||||||
AddFile (WriteLogFile(richlog), "log.rtf");
|
|
||||||
}
|
|
||||||
CloseHandle (DbgProcess);
|
CloseHandle (DbgProcess);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,8 @@
|
||||||
#include "keydef.h"
|
#include "keydef.h"
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
|
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
#define SAFE_RELEASE(x) { if (x != NULL) { x->Release(); x = NULL; } }
|
#define SAFE_RELEASE(x) { if (x != NULL) { x->Release(); x = NULL; } }
|
||||||
|
|
||||||
// WBEMIDL BITS -- because w32api doesn't have this, either -----------------
|
// WBEMIDL BITS -- because w32api doesn't have this, either -----------------
|
||||||
|
@ -266,7 +268,6 @@ protected:
|
||||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||||
|
|
||||||
extern LPDIRECTINPUT8 g_pdi;
|
extern LPDIRECTINPUT8 g_pdi;
|
||||||
extern HWND Window;
|
|
||||||
|
|
||||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||||
|
|
||||||
|
@ -372,7 +373,7 @@ bool FDInputJoystick::GetDevice()
|
||||||
Printf(TEXTCOLOR_ORANGE "Setting data format for %s failed.\n", Name.GetChars());
|
Printf(TEXTCOLOR_ORANGE "Setting data format for %s failed.\n", Name.GetChars());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
hr = Device->SetCooperativeLevel(Window, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
|
hr = Device->SetCooperativeLevel(mainwindow.GetHandle(), DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
Printf(TEXTCOLOR_ORANGE "Setting cooperative level for %s failed.\n", Name.GetChars());
|
Printf(TEXTCOLOR_ORANGE "Setting cooperative level for %s failed.\n", Name.GetChars());
|
||||||
|
|
|
@ -86,6 +86,7 @@
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
#include "c_buttons.h"
|
#include "c_buttons.h"
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
// Compensate for w32api's lack
|
// Compensate for w32api's lack
|
||||||
#ifndef GET_XBUTTON_WPARAM
|
#ifndef GET_XBUTTON_WPARAM
|
||||||
|
@ -116,7 +117,6 @@ extern bool ToggleFullscreen;
|
||||||
bool VidResizing;
|
bool VidResizing;
|
||||||
|
|
||||||
extern BOOL vidactive;
|
extern BOOL vidactive;
|
||||||
extern HWND Window, ConWindow;
|
|
||||||
|
|
||||||
EXTERN_CVAR (String, language)
|
EXTERN_CVAR (String, language)
|
||||||
EXTERN_CVAR (Bool, lookstrafe)
|
EXTERN_CVAR (Bool, lookstrafe)
|
||||||
|
@ -160,7 +160,7 @@ static void I_CheckGUICapture ()
|
||||||
|
|
||||||
void I_SetMouseCapture()
|
void I_SetMouseCapture()
|
||||||
{
|
{
|
||||||
SetCapture(Window);
|
SetCapture(mainwindow.GetHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
void I_ReleaseMouseCapture()
|
void I_ReleaseMouseCapture()
|
||||||
|
@ -444,7 +444,7 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_SIZE:
|
case WM_SIZE:
|
||||||
InvalidateRect (Window, NULL, FALSE);
|
InvalidateRect (hWnd, NULL, FALSE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_KEYDOWN:
|
case WM_KEYDOWN:
|
||||||
|
@ -820,7 +820,7 @@ IJoystickConfig *I_UpdateDeviceList()
|
||||||
|
|
||||||
void I_PutInClipboard (const char *str)
|
void I_PutInClipboard (const char *str)
|
||||||
{
|
{
|
||||||
if (str == NULL || !OpenClipboard (Window))
|
if (str == NULL || !OpenClipboard (mainwindow.GetHandle()))
|
||||||
return;
|
return;
|
||||||
EmptyClipboard ();
|
EmptyClipboard ();
|
||||||
|
|
||||||
|
@ -842,7 +842,7 @@ FString I_GetFromClipboard (bool return_nothing)
|
||||||
HGLOBAL cliphandle;
|
HGLOBAL cliphandle;
|
||||||
wchar_t *clipstr;
|
wchar_t *clipstr;
|
||||||
|
|
||||||
if (return_nothing || !IsClipboardFormatAvailable (CF_UNICODETEXT) || !OpenClipboard (Window))
|
if (return_nothing || !IsClipboardFormatAvailable (CF_UNICODETEXT) || !OpenClipboard (mainwindow.GetHandle()))
|
||||||
return retstr;
|
return retstr;
|
||||||
|
|
||||||
cliphandle = GetClipboardData (CF_UNICODETEXT);
|
cliphandle = GetClipboardData (CF_UNICODETEXT);
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
|
|
||||||
#include "i_input.h"
|
#include "i_input.h"
|
||||||
#include "d_eventbase.h"
|
#include "d_eventbase.h"
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
@ -87,7 +88,6 @@ protected:
|
||||||
|
|
||||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||||
|
|
||||||
extern HWND Window;
|
|
||||||
extern LPDIRECTINPUT8 g_pdi;
|
extern LPDIRECTINPUT8 g_pdi;
|
||||||
extern LPDIRECTINPUT g_pdi3;
|
extern LPDIRECTINPUT g_pdi3;
|
||||||
extern bool GUICapture;
|
extern bool GUICapture;
|
||||||
|
@ -347,7 +347,7 @@ ufailit:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = Device->SetCooperativeLevel(Window, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
|
hr = Device->SetCooperativeLevel(mainwindow.GetHandle(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
goto ufailit;
|
goto ufailit;
|
||||||
|
@ -379,7 +379,7 @@ void FDInputKeyboard::ProcessInput()
|
||||||
DIDEVICEOBJECTDATA od;
|
DIDEVICEOBJECTDATA od;
|
||||||
DWORD dwElements;
|
DWORD dwElements;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
bool foreground = (GetForegroundWindow() == Window);
|
bool foreground = (GetForegroundWindow() == mainwindow.GetHandle());
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
@ -448,7 +448,7 @@ bool FRawKeyboard::GetDevice()
|
||||||
rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE;
|
rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE;
|
||||||
rid.usUsage = HID_GDP_KEYBOARD;
|
rid.usUsage = HID_GDP_KEYBOARD;
|
||||||
rid.dwFlags = RIDEV_INPUTSINK;
|
rid.dwFlags = RIDEV_INPUTSINK;
|
||||||
rid.hwndTarget = Window;
|
rid.hwndTarget = mainwindow.GetHandle();
|
||||||
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -80,6 +80,8 @@
|
||||||
#include "startupinfo.h"
|
#include "startupinfo.h"
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
|
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
// The main window's title.
|
// The main window's title.
|
||||||
|
@ -94,9 +96,8 @@
|
||||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||||
|
|
||||||
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
|
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
|
||||||
void CreateCrashLog (const char *custominfo, DWORD customsize, HWND richedit);
|
void CreateCrashLog (const char *custominfo, DWORD customsize);
|
||||||
void DisplayCrashLog ();
|
void DisplayCrashLog ();
|
||||||
void I_FlushBufferedConsoleStuff();
|
|
||||||
void DestroyCustomCursor();
|
void DestroyCustomCursor();
|
||||||
int GameMain();
|
int GameMain();
|
||||||
|
|
||||||
|
@ -120,19 +121,6 @@ HANDLE MainThread;
|
||||||
DWORD MainThreadID;
|
DWORD MainThreadID;
|
||||||
HANDLE StdOut;
|
HANDLE StdOut;
|
||||||
bool FancyStdOut, AttachedStdOut;
|
bool FancyStdOut, AttachedStdOut;
|
||||||
bool ConWindowHidden;
|
|
||||||
|
|
||||||
// The main window
|
|
||||||
HWND Window;
|
|
||||||
|
|
||||||
// The subwindows used for startup and error output
|
|
||||||
HWND ConWindow, GameTitleWindow;
|
|
||||||
HWND ErrorPane, ProgressBar, NetStartPane, StartupScreen, ErrorIcon;
|
|
||||||
|
|
||||||
HFONT GameTitleFont;
|
|
||||||
LONG GameTitleFontHeight;
|
|
||||||
LONG DefaultGUIFontHeight;
|
|
||||||
LONG ErrorIconChar;
|
|
||||||
|
|
||||||
FModule Kernel32Module{"Kernel32"};
|
FModule Kernel32Module{"Kernel32"};
|
||||||
FModule Shell32Module{"Shell32"};
|
FModule Shell32Module{"Shell32"};
|
||||||
|
@ -140,7 +128,6 @@ FModule User32Module{"User32"};
|
||||||
|
|
||||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||||
|
|
||||||
static const WCHAR WinClassName[] = WGAMENAME "MainWindow";
|
|
||||||
static HMODULE hwtsapi32; // handle to wtsapi32.dll
|
static HMODULE hwtsapi32; // handle to wtsapi32.dll
|
||||||
|
|
||||||
// CODE --------------------------------------------------------------------
|
// CODE --------------------------------------------------------------------
|
||||||
|
@ -174,155 +161,13 @@ static void UnWTS (void)
|
||||||
ursn unreg = (ursn)GetProcAddress (hwtsapi32, "WTSUnRegisterSessionNotification");
|
ursn unreg = (ursn)GetProcAddress (hwtsapi32, "WTSUnRegisterSessionNotification");
|
||||||
if (unreg != 0)
|
if (unreg != 0)
|
||||||
{
|
{
|
||||||
unreg (Window);
|
unreg (mainwindow.GetHandle());
|
||||||
}
|
}
|
||||||
FreeLibrary (hwtsapi32);
|
FreeLibrary (hwtsapi32);
|
||||||
hwtsapi32 = 0;
|
hwtsapi32 = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// LayoutErrorPane
|
|
||||||
//
|
|
||||||
// Lays out the error pane to the desired width, returning the required
|
|
||||||
// height.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
static int LayoutErrorPane (HWND pane, int w)
|
|
||||||
{
|
|
||||||
HWND ctl, ctl_two;
|
|
||||||
RECT rectc, rectc_two;
|
|
||||||
|
|
||||||
// Right-align the Quit button.
|
|
||||||
ctl = GetDlgItem (pane, IDOK);
|
|
||||||
GetClientRect (ctl, &rectc); // Find out how big it is.
|
|
||||||
MoveWindow (ctl, w - rectc.right - 1, 1, rectc.right, rectc.bottom, TRUE);
|
|
||||||
|
|
||||||
// Second-right-align the Restart button
|
|
||||||
ctl_two = GetDlgItem (pane, IDC_BUTTON1);
|
|
||||||
GetClientRect (ctl_two, &rectc_two); // Find out how big it is.
|
|
||||||
MoveWindow (ctl_two, w - rectc.right - rectc_two.right - 2, 1, rectc.right, rectc.bottom, TRUE);
|
|
||||||
|
|
||||||
InvalidateRect (ctl, NULL, TRUE);
|
|
||||||
InvalidateRect (ctl_two, NULL, TRUE);
|
|
||||||
|
|
||||||
// Return the needed height for this layout
|
|
||||||
return rectc.bottom + 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// LayoutNetStartPane
|
|
||||||
//
|
|
||||||
// Lays out the network startup pane to the specified width, returning
|
|
||||||
// its required height.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
int LayoutNetStartPane (HWND pane, int w)
|
|
||||||
{
|
|
||||||
HWND ctl;
|
|
||||||
RECT margin, rectc;
|
|
||||||
int staticheight, barheight;
|
|
||||||
|
|
||||||
// Determine margin sizes.
|
|
||||||
SetRect (&margin, 7, 7, 0, 0);
|
|
||||||
MapDialogRect (pane, &margin);
|
|
||||||
|
|
||||||
// Stick the message text in the upper left corner.
|
|
||||||
ctl = GetDlgItem (pane, IDC_NETSTARTMESSAGE);
|
|
||||||
GetClientRect (ctl, &rectc);
|
|
||||||
MoveWindow (ctl, margin.left, margin.top, rectc.right, rectc.bottom, TRUE);
|
|
||||||
|
|
||||||
// Stick the count text in the upper right corner.
|
|
||||||
ctl = GetDlgItem (pane, IDC_NETSTARTCOUNT);
|
|
||||||
GetClientRect (ctl, &rectc);
|
|
||||||
MoveWindow (ctl, w - rectc.right - margin.left, margin.top, rectc.right, rectc.bottom, TRUE);
|
|
||||||
staticheight = rectc.bottom;
|
|
||||||
|
|
||||||
// Stretch the progress bar to fill the entire width.
|
|
||||||
ctl = GetDlgItem (pane, IDC_NETSTARTPROGRESS);
|
|
||||||
barheight = GetSystemMetrics (SM_CYVSCROLL);
|
|
||||||
MoveWindow (ctl, margin.left, margin.top*2 + staticheight, w - margin.left*2, barheight, TRUE);
|
|
||||||
|
|
||||||
// Center the abort button underneath the progress bar.
|
|
||||||
ctl = GetDlgItem (pane, IDCANCEL);
|
|
||||||
GetClientRect (ctl, &rectc);
|
|
||||||
MoveWindow (ctl, (w - rectc.right) / 2, margin.top*3 + staticheight + barheight, rectc.right, rectc.bottom, TRUE);
|
|
||||||
|
|
||||||
return margin.top*4 + staticheight + barheight + rectc.bottom;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// LayoutMainWindow
|
|
||||||
//
|
|
||||||
// Lays out the main window with the game title and log controls and
|
|
||||||
// possibly the error pane and progress bar.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void LayoutMainWindow (HWND hWnd, HWND pane)
|
|
||||||
{
|
|
||||||
RECT rect;
|
|
||||||
int errorpaneheight = 0;
|
|
||||||
int bannerheight = 0;
|
|
||||||
int progressheight = 0;
|
|
||||||
int netpaneheight = 0;
|
|
||||||
int leftside = 0;
|
|
||||||
int w, h;
|
|
||||||
|
|
||||||
GetClientRect (hWnd, &rect);
|
|
||||||
w = rect.right;
|
|
||||||
h = rect.bottom;
|
|
||||||
|
|
||||||
if (GameStartupInfo.Name.IsNotEmpty() && GameTitleWindow != NULL)
|
|
||||||
{
|
|
||||||
bannerheight = GameTitleFontHeight + 5;
|
|
||||||
MoveWindow (GameTitleWindow, 0, 0, w, bannerheight, TRUE);
|
|
||||||
InvalidateRect (GameTitleWindow, NULL, FALSE);
|
|
||||||
}
|
|
||||||
if (ProgressBar != NULL)
|
|
||||||
{
|
|
||||||
// Base the height of the progress bar on the height of a scroll bar
|
|
||||||
// arrow, just as in the progress bar example.
|
|
||||||
progressheight = GetSystemMetrics (SM_CYVSCROLL);
|
|
||||||
MoveWindow (ProgressBar, 0, h - progressheight, w, progressheight, TRUE);
|
|
||||||
}
|
|
||||||
if (NetStartPane != NULL)
|
|
||||||
{
|
|
||||||
netpaneheight = LayoutNetStartPane (NetStartPane, w);
|
|
||||||
SetWindowPos (NetStartPane, HWND_TOP, 0, h - progressheight - netpaneheight, w, netpaneheight, SWP_SHOWWINDOW);
|
|
||||||
}
|
|
||||||
if (pane != NULL)
|
|
||||||
{
|
|
||||||
errorpaneheight = LayoutErrorPane (pane, w);
|
|
||||||
SetWindowPos (pane, HWND_TOP, 0, h - progressheight - netpaneheight - errorpaneheight, w, errorpaneheight, 0);
|
|
||||||
}
|
|
||||||
if (ErrorIcon != NULL)
|
|
||||||
{
|
|
||||||
leftside = GetSystemMetrics (SM_CXICON) + 6;
|
|
||||||
MoveWindow (ErrorIcon, 0, bannerheight, leftside, h - bannerheight - errorpaneheight - progressheight - netpaneheight, TRUE);
|
|
||||||
}
|
|
||||||
// If there is a startup screen, it covers the log window
|
|
||||||
if (StartupScreen != NULL)
|
|
||||||
{
|
|
||||||
SetWindowPos (StartupScreen, HWND_TOP, leftside, bannerheight, w - leftside,
|
|
||||||
h - bannerheight - errorpaneheight - progressheight - netpaneheight, SWP_SHOWWINDOW);
|
|
||||||
InvalidateRect (StartupScreen, NULL, FALSE);
|
|
||||||
MoveWindow (ConWindow, 0, 0, 0, 0, TRUE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// The log window uses whatever space is left.
|
|
||||||
MoveWindow (ConWindow, leftside, bannerheight, w - leftside,
|
|
||||||
h - bannerheight - errorpaneheight - progressheight - netpaneheight, TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// I_SetIWADInfo
|
// I_SetIWADInfo
|
||||||
|
@ -332,431 +177,7 @@ void LayoutMainWindow (HWND hWnd, HWND pane)
|
||||||
void I_SetIWADInfo()
|
void I_SetIWADInfo()
|
||||||
{
|
{
|
||||||
// Make the startup banner show itself
|
// Make the startup banner show itself
|
||||||
LayoutMainWindow(Window, NULL);
|
mainwindow.UpdateLayout();
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// LConProc
|
|
||||||
//
|
|
||||||
// The main window's WndProc during startup. During gameplay, the WndProc
|
|
||||||
// in i_input.cpp is used instead.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
LRESULT CALLBACK LConProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
||||||
{
|
|
||||||
HWND view;
|
|
||||||
HDC hdc;
|
|
||||||
HBRUSH hbr;
|
|
||||||
HGDIOBJ oldfont;
|
|
||||||
RECT rect;
|
|
||||||
SIZE size;
|
|
||||||
LOGFONT lf;
|
|
||||||
TEXTMETRIC tm;
|
|
||||||
HINSTANCE inst = (HINSTANCE)(LONG_PTR)GetWindowLongPtr(hWnd, GWLP_HINSTANCE);
|
|
||||||
DRAWITEMSTRUCT *drawitem;
|
|
||||||
CHARFORMAT2W format;
|
|
||||||
|
|
||||||
switch (msg)
|
|
||||||
{
|
|
||||||
case WM_CREATE:
|
|
||||||
// Create game title static control
|
|
||||||
memset (&lf, 0, sizeof(lf));
|
|
||||||
hdc = GetDC (hWnd);
|
|
||||||
lf.lfHeight = -MulDiv(12, GetDeviceCaps(hdc, LOGPIXELSY), 72);
|
|
||||||
lf.lfCharSet = ANSI_CHARSET;
|
|
||||||
lf.lfWeight = FW_BOLD;
|
|
||||||
lf.lfPitchAndFamily = VARIABLE_PITCH | FF_ROMAN;
|
|
||||||
wcscpy (lf.lfFaceName, L"Trebuchet MS");
|
|
||||||
GameTitleFont = CreateFontIndirect (&lf);
|
|
||||||
|
|
||||||
oldfont = SelectObject (hdc, GetStockObject (DEFAULT_GUI_FONT));
|
|
||||||
GetTextMetrics (hdc, &tm);
|
|
||||||
DefaultGUIFontHeight = tm.tmHeight;
|
|
||||||
if (GameTitleFont == NULL)
|
|
||||||
{
|
|
||||||
GameTitleFontHeight = DefaultGUIFontHeight;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SelectObject (hdc, GameTitleFont);
|
|
||||||
GetTextMetrics (hdc, &tm);
|
|
||||||
GameTitleFontHeight = tm.tmHeight;
|
|
||||||
}
|
|
||||||
SelectObject (hdc, oldfont);
|
|
||||||
|
|
||||||
// Create log read-only edit control
|
|
||||||
view = CreateWindowExW (WS_EX_NOPARENTNOTIFY, L"RichEdit20W", nullptr,
|
|
||||||
WS_CHILD | WS_VISIBLE | WS_VSCROLL |
|
|
||||||
ES_LEFT | ES_MULTILINE | WS_CLIPSIBLINGS,
|
|
||||||
0, 0, 0, 0,
|
|
||||||
hWnd, NULL, inst, NULL);
|
|
||||||
HRESULT hr;
|
|
||||||
hr = GetLastError();
|
|
||||||
if (view == NULL)
|
|
||||||
{
|
|
||||||
ReleaseDC (hWnd, hdc);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
SendMessage (view, EM_SETREADONLY, TRUE, 0);
|
|
||||||
SendMessage (view, EM_EXLIMITTEXT, 0, 0x7FFFFFFE);
|
|
||||||
SendMessage (view, EM_SETBKGNDCOLOR, 0, RGB(70,70,70));
|
|
||||||
// Setup default font for the log.
|
|
||||||
//SendMessage (view, WM_SETFONT, (WPARAM)GetStockObject (DEFAULT_GUI_FONT), FALSE);
|
|
||||||
format.cbSize = sizeof(format);
|
|
||||||
format.dwMask = CFM_BOLD | CFM_COLOR | CFM_FACE | CFM_SIZE | CFM_CHARSET;
|
|
||||||
format.dwEffects = 0;
|
|
||||||
format.yHeight = 200;
|
|
||||||
format.crTextColor = RGB(223,223,223);
|
|
||||||
format.bCharSet = ANSI_CHARSET;
|
|
||||||
format.bPitchAndFamily = FF_SWISS | VARIABLE_PITCH;
|
|
||||||
wcscpy(format.szFaceName, L"DejaVu Sans"); // At least I have it. :p
|
|
||||||
SendMessageW(view, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&format);
|
|
||||||
|
|
||||||
ConWindow = view;
|
|
||||||
ReleaseDC (hWnd, hdc);
|
|
||||||
|
|
||||||
view = CreateWindowExW (WS_EX_NOPARENTNOTIFY, L"STATIC", NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SS_OWNERDRAW, 0, 0, 0, 0, hWnd, nullptr, inst, nullptr);
|
|
||||||
if (view == nullptr)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
SetWindowLong (view, GWL_ID, IDC_STATIC_TITLE);
|
|
||||||
GameTitleWindow = view;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case WM_SIZE:
|
|
||||||
if (wParam != SIZE_MAXHIDE && wParam != SIZE_MAXSHOW)
|
|
||||||
{
|
|
||||||
LayoutMainWindow (hWnd, ErrorPane);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case WM_DRAWITEM:
|
|
||||||
// Draw title banner.
|
|
||||||
if (wParam == IDC_STATIC_TITLE && GameStartupInfo.Name.IsNotEmpty())
|
|
||||||
{
|
|
||||||
const PalEntry *c;
|
|
||||||
|
|
||||||
// Draw the game title strip at the top of the window.
|
|
||||||
drawitem = (LPDRAWITEMSTRUCT)lParam;
|
|
||||||
|
|
||||||
// Draw the background.
|
|
||||||
rect = drawitem->rcItem;
|
|
||||||
rect.bottom -= 1;
|
|
||||||
c = (const PalEntry *)&GameStartupInfo.BkColor;
|
|
||||||
hbr = CreateSolidBrush (RGB(c->r,c->g,c->b));
|
|
||||||
FillRect (drawitem->hDC, &drawitem->rcItem, hbr);
|
|
||||||
DeleteObject (hbr);
|
|
||||||
|
|
||||||
// Calculate width of the title string.
|
|
||||||
SetTextAlign (drawitem->hDC, TA_TOP);
|
|
||||||
oldfont = SelectObject (drawitem->hDC, GameTitleFont != NULL ? GameTitleFont : (HFONT)GetStockObject (DEFAULT_GUI_FONT));
|
|
||||||
auto widename = GameStartupInfo.Name.WideString();
|
|
||||||
GetTextExtentPoint32W (drawitem->hDC, widename.c_str(), (int)widename.length(), &size);
|
|
||||||
|
|
||||||
// Draw the title.
|
|
||||||
c = (const PalEntry *)&GameStartupInfo.FgColor;
|
|
||||||
SetTextColor (drawitem->hDC, RGB(c->r,c->g,c->b));
|
|
||||||
SetBkMode (drawitem->hDC, TRANSPARENT);
|
|
||||||
TextOutW (drawitem->hDC, rect.left + (rect.right - rect.left - size.cx) / 2, 2, widename.c_str(), (int)widename.length());
|
|
||||||
SelectObject (drawitem->hDC, oldfont);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
// Draw startup screen
|
|
||||||
else if (wParam == IDC_STATIC_STARTUP)
|
|
||||||
{
|
|
||||||
if (StartupScreen != NULL)
|
|
||||||
{
|
|
||||||
drawitem = (LPDRAWITEMSTRUCT)lParam;
|
|
||||||
|
|
||||||
rect = drawitem->rcItem;
|
|
||||||
// Windows expects DIBs to be bottom-up but ours is top-down,
|
|
||||||
// so flip it vertically while drawing it.
|
|
||||||
StretchDIBits (drawitem->hDC, rect.left, rect.bottom - 1, rect.right - rect.left, rect.top - rect.bottom,
|
|
||||||
0, 0, StartupBitmap->bmiHeader.biWidth, StartupBitmap->bmiHeader.biHeight,
|
|
||||||
ST_Util_BitsForBitmap(StartupBitmap), reinterpret_cast<const BITMAPINFO*>(StartupBitmap), DIB_RGB_COLORS, SRCCOPY);
|
|
||||||
|
|
||||||
// If the title banner is gone, then this is an ENDOOM screen, so draw a short prompt
|
|
||||||
// where the command prompt would have been in DOS.
|
|
||||||
if (GameTitleWindow == NULL)
|
|
||||||
{
|
|
||||||
auto quitmsg = WideString(GStrings("TXT_QUITENDOOM"));
|
|
||||||
|
|
||||||
SetTextColor (drawitem->hDC, RGB(240,240,240));
|
|
||||||
SetBkMode (drawitem->hDC, TRANSPARENT);
|
|
||||||
oldfont = SelectObject (drawitem->hDC, (HFONT)GetStockObject (DEFAULT_GUI_FONT));
|
|
||||||
TextOutW (drawitem->hDC, 3, drawitem->rcItem.bottom - DefaultGUIFontHeight - 3, quitmsg.c_str(), (int)quitmsg.length());
|
|
||||||
SelectObject (drawitem->hDC, oldfont);
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Draw stop icon.
|
|
||||||
else if (wParam == IDC_ICONPIC)
|
|
||||||
{
|
|
||||||
HICON icon;
|
|
||||||
POINTL char_pos;
|
|
||||||
drawitem = (LPDRAWITEMSTRUCT)lParam;
|
|
||||||
|
|
||||||
// This background color should match the edit control's.
|
|
||||||
hbr = CreateSolidBrush (RGB(70,70,70));
|
|
||||||
FillRect (drawitem->hDC, &drawitem->rcItem, hbr);
|
|
||||||
DeleteObject (hbr);
|
|
||||||
|
|
||||||
// Draw the icon aligned with the first line of error text.
|
|
||||||
SendMessage (ConWindow, EM_POSFROMCHAR, (WPARAM)&char_pos, ErrorIconChar);
|
|
||||||
icon = (HICON)LoadImage (0, IDI_ERROR, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
|
|
||||||
DrawIcon (drawitem->hDC, 6, char_pos.y, icon);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
case WM_COMMAND:
|
|
||||||
if (ErrorIcon != NULL && (HWND)lParam == ConWindow && HIWORD(wParam) == EN_UPDATE)
|
|
||||||
{
|
|
||||||
// Be sure to redraw the error icon if the edit control changes.
|
|
||||||
InvalidateRect (ErrorIcon, NULL, TRUE);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_CLOSE:
|
|
||||||
PostQuitMessage (0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WM_DESTROY:
|
|
||||||
if (GameTitleFont != NULL)
|
|
||||||
{
|
|
||||||
DeleteObject (GameTitleFont);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return DefWindowProc (hWnd, msg, wParam, lParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// ErrorPaneProc
|
|
||||||
//
|
|
||||||
// DialogProc for the error pane.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
bool restartrequest;
|
|
||||||
|
|
||||||
void CheckForRestart()
|
|
||||||
{
|
|
||||||
if (restartrequest)
|
|
||||||
{
|
|
||||||
HMODULE hModule = GetModuleHandleW(NULL);
|
|
||||||
WCHAR path[MAX_PATH];
|
|
||||||
GetModuleFileNameW(hModule, path, MAX_PATH);
|
|
||||||
ShellExecuteW(NULL, L"open", path, GetCommandLineW(), NULL, SW_SHOWNORMAL);
|
|
||||||
}
|
|
||||||
restartrequest = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
INT_PTR CALLBACK ErrorPaneProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
||||||
{
|
|
||||||
switch (msg)
|
|
||||||
{
|
|
||||||
case WM_INITDIALOG:
|
|
||||||
// Appear in the main window.
|
|
||||||
LayoutMainWindow (GetParent (hDlg), hDlg);
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
case WM_COMMAND:
|
|
||||||
if (HIWORD(wParam) == BN_CLICKED)
|
|
||||||
{
|
|
||||||
if (LOWORD(wParam) == IDC_BUTTON1) // we pressed the restart button, so run GZDoom again
|
|
||||||
{
|
|
||||||
restartrequest = true;
|
|
||||||
}
|
|
||||||
PostQuitMessage (0);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// I_SetWndProc
|
|
||||||
//
|
|
||||||
// Sets the main WndProc, hides all the child windows, and starts up
|
|
||||||
// in-game input.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void I_SetWndProc()
|
|
||||||
{
|
|
||||||
if (GetWindowLongPtr (Window, GWLP_USERDATA) == 0)
|
|
||||||
{
|
|
||||||
SetWindowLongPtr (Window, GWLP_USERDATA, 1);
|
|
||||||
SetWindowLongPtr (Window, GWLP_WNDPROC, (WLONG_PTR)WndProc);
|
|
||||||
ShowWindow (ConWindow, SW_HIDE);
|
|
||||||
ShowWindow(ProgressBar, SW_HIDE);
|
|
||||||
ConWindowHidden = true;
|
|
||||||
ShowWindow (GameTitleWindow, SW_HIDE);
|
|
||||||
I_InitInput (Window);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// RestoreConView
|
|
||||||
//
|
|
||||||
// Returns the main window to its startup state.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void RestoreConView()
|
|
||||||
{
|
|
||||||
HDC screenDC = GetDC(0);
|
|
||||||
int dpi = GetDeviceCaps(screenDC, LOGPIXELSX);
|
|
||||||
ReleaseDC(0, screenDC);
|
|
||||||
int width = (512 * dpi + 96 / 2) / 96;
|
|
||||||
int height = (384 * dpi + 96 / 2) / 96;
|
|
||||||
|
|
||||||
// Make sure the window has a frame in case it was fullscreened.
|
|
||||||
SetWindowLongPtr (Window, GWL_STYLE, WS_VISIBLE|WS_OVERLAPPEDWINDOW);
|
|
||||||
if (GetWindowLong (Window, GWL_EXSTYLE) & WS_EX_TOPMOST)
|
|
||||||
{
|
|
||||||
SetWindowPos (Window, HWND_BOTTOM, 0, 0, width, height,
|
|
||||||
SWP_DRAWFRAME | SWP_NOCOPYBITS | SWP_NOMOVE);
|
|
||||||
SetWindowPos (Window, HWND_TOP, 0, 0, 0, 0, SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOSIZE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SetWindowPos (Window, NULL, 0, 0, width, height,
|
|
||||||
SWP_DRAWFRAME | SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOZORDER);
|
|
||||||
}
|
|
||||||
|
|
||||||
SetWindowLongPtr (Window, GWLP_WNDPROC, (WLONG_PTR)LConProc);
|
|
||||||
ShowWindow (ConWindow, SW_SHOW);
|
|
||||||
ConWindowHidden = false;
|
|
||||||
ShowWindow (GameTitleWindow, SW_SHOW);
|
|
||||||
I_ShutdownInput (); // Make sure the mouse pointer is available.
|
|
||||||
// Make sure the progress bar isn't visible.
|
|
||||||
DeleteStartupScreen();
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// ShowErrorPane
|
|
||||||
//
|
|
||||||
// Shows an error message, preferably in the main window, but it can
|
|
||||||
// use a normal message box too.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void ShowErrorPane(const char *text)
|
|
||||||
{
|
|
||||||
auto widetext = WideString(text);
|
|
||||||
if (Window == nullptr || ConWindow == nullptr)
|
|
||||||
{
|
|
||||||
if (text != NULL)
|
|
||||||
{
|
|
||||||
MessageBoxW (Window, widetext.c_str(),
|
|
||||||
WGAMENAME " Fatal Error", MB_OK|MB_ICONSTOP|MB_TASKMODAL);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StartScreen != NULL) // Ensure that the network pane is hidden.
|
|
||||||
{
|
|
||||||
StartScreen->NetDone();
|
|
||||||
}
|
|
||||||
if (text != NULL)
|
|
||||||
{
|
|
||||||
FStringf caption("Fatal Error - " GAMENAME " %s " X64 " (%s)", GetVersionString(), GetGitTime());
|
|
||||||
auto wcaption = caption.WideString();
|
|
||||||
SetWindowTextW (Window, wcaption.c_str());
|
|
||||||
ErrorIcon = CreateWindowExW (WS_EX_NOPARENTNOTIFY, L"STATIC", NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SS_OWNERDRAW, 0, 0, 0, 0, Window, NULL, g_hInst, NULL);
|
|
||||||
if (ErrorIcon != NULL)
|
|
||||||
{
|
|
||||||
SetWindowLong (ErrorIcon, GWL_ID, IDC_ICONPIC);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ErrorPane = CreateDialogParam (g_hInst, MAKEINTRESOURCE(IDD_ERRORPANE), Window, ErrorPaneProc, (LONG_PTR)NULL);
|
|
||||||
|
|
||||||
if (text != NULL)
|
|
||||||
{
|
|
||||||
CHARRANGE end;
|
|
||||||
CHARFORMAT2 oldformat, newformat;
|
|
||||||
PARAFORMAT2 paraformat;
|
|
||||||
|
|
||||||
// Append the error message to the log.
|
|
||||||
end.cpMax = end.cpMin = GetWindowTextLength (ConWindow);
|
|
||||||
SendMessage (ConWindow, EM_EXSETSEL, 0, (LPARAM)&end);
|
|
||||||
|
|
||||||
// Remember current charformat.
|
|
||||||
oldformat.cbSize = sizeof(oldformat);
|
|
||||||
SendMessage (ConWindow, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&oldformat);
|
|
||||||
|
|
||||||
// Use bigger font and standout colors.
|
|
||||||
newformat.cbSize = sizeof(newformat);
|
|
||||||
newformat.dwMask = CFM_BOLD | CFM_COLOR | CFM_SIZE;
|
|
||||||
newformat.dwEffects = CFE_BOLD;
|
|
||||||
newformat.yHeight = oldformat.yHeight * 5 / 4;
|
|
||||||
newformat.crTextColor = RGB(255,170,170);
|
|
||||||
SendMessage (ConWindow, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&newformat);
|
|
||||||
|
|
||||||
// Indent the rest of the text to make the error message stand out a little more.
|
|
||||||
paraformat.cbSize = sizeof(paraformat);
|
|
||||||
paraformat.dwMask = PFM_STARTINDENT | PFM_OFFSETINDENT | PFM_RIGHTINDENT;
|
|
||||||
paraformat.dxStartIndent = paraformat.dxOffset = paraformat.dxRightIndent = 120;
|
|
||||||
SendMessage (ConWindow, EM_SETPARAFORMAT, 0, (LPARAM)¶format);
|
|
||||||
SendMessageW (ConWindow, EM_REPLACESEL, FALSE, (LPARAM)L"\n");
|
|
||||||
|
|
||||||
// Find out where the error lines start for the error icon display control.
|
|
||||||
SendMessage (ConWindow, EM_EXGETSEL, 0, (LPARAM)&end);
|
|
||||||
ErrorIconChar = end.cpMax;
|
|
||||||
|
|
||||||
// Now start adding the actual error message.
|
|
||||||
SendMessageW (ConWindow, EM_REPLACESEL, FALSE, (LPARAM)L"Execution could not continue.\n\n");
|
|
||||||
|
|
||||||
// Restore old charformat but with light yellow text.
|
|
||||||
oldformat.crTextColor = RGB(255,255,170);
|
|
||||||
SendMessage (ConWindow, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&oldformat);
|
|
||||||
|
|
||||||
// Add the error text.
|
|
||||||
SendMessageW (ConWindow, EM_REPLACESEL, FALSE, (LPARAM)widetext.c_str());
|
|
||||||
|
|
||||||
// Make sure the error text is not scrolled below the window.
|
|
||||||
SendMessage (ConWindow, EM_LINESCROLL, 0, SendMessage (ConWindow, EM_GETLINECOUNT, 0, 0));
|
|
||||||
// The above line scrolled everything off the screen, so pretend to move the scroll
|
|
||||||
// bar thumb, which clamps to not show any extra lines if it doesn't need to.
|
|
||||||
SendMessage (ConWindow, EM_SCROLL, SB_PAGEDOWN, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL bRet;
|
|
||||||
MSG msg;
|
|
||||||
|
|
||||||
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
|
|
||||||
{
|
|
||||||
if (bRet == -1)
|
|
||||||
{
|
|
||||||
MessageBoxW (Window, widetext.c_str(), WGAMENAME " Fatal Error", MB_OK|MB_ICONSTOP|MB_TASKMODAL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (!IsDialogMessage (ErrorPane, &msg))
|
|
||||||
{
|
|
||||||
TranslateMessage (&msg);
|
|
||||||
DispatchMessage (&msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PeekThreadedErrorPane()
|
|
||||||
{
|
|
||||||
// Allow SendMessage from another thread to call its message handler so that it can display the crash dialog
|
|
||||||
MSG msg;
|
|
||||||
PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void UnTbp()
|
static void UnTbp()
|
||||||
|
@ -904,44 +325,9 @@ int DoMain (HINSTANCE hInstance)
|
||||||
x = y = 0;
|
x = y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
WNDCLASS WndClass;
|
|
||||||
WndClass.style = 0;
|
|
||||||
WndClass.lpfnWndProc = LConProc;
|
|
||||||
WndClass.cbClsExtra = 0;
|
|
||||||
WndClass.cbWndExtra = 0;
|
|
||||||
WndClass.hInstance = hInstance;
|
|
||||||
WndClass.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE(IDI_ICON1));
|
|
||||||
WndClass.hCursor = LoadCursor (NULL, IDC_ARROW);
|
|
||||||
WndClass.hbrBackground = NULL;
|
|
||||||
WndClass.lpszMenuName = NULL;
|
|
||||||
WndClass.lpszClassName = WinClassName;
|
|
||||||
|
|
||||||
/* register this new class with Windows */
|
|
||||||
if (!RegisterClass((LPWNDCLASS)&WndClass))
|
|
||||||
{
|
|
||||||
MessageBoxA(nullptr, "Could not register window class", "Fatal", MB_ICONEXCLAMATION|MB_OK);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* create window */
|
/* create window */
|
||||||
FStringf caption("" GAMENAME " %s " X64 " (%s)", GetVersionString(), GetGitTime());
|
FStringf caption("" GAMENAME " %s " X64 " (%s)", GetVersionString(), GetGitTime());
|
||||||
std::wstring wcaption = caption.WideString();
|
mainwindow.Create(caption, x, y, width, height);
|
||||||
Window = CreateWindowExW(
|
|
||||||
WS_EX_APPWINDOW,
|
|
||||||
WinClassName,
|
|
||||||
wcaption.c_str(),
|
|
||||||
WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN,
|
|
||||||
x, y, width, height,
|
|
||||||
(HWND) NULL,
|
|
||||||
(HMENU) NULL,
|
|
||||||
hInstance,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (!Window)
|
|
||||||
{
|
|
||||||
MessageBoxA(nullptr, "Unable to create main window", "Fatal", MB_ICONEXCLAMATION|MB_OK);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kernel != NULL)
|
if (kernel != NULL)
|
||||||
{
|
{
|
||||||
|
@ -957,7 +343,7 @@ int DoMain (HINSTANCE hInstance)
|
||||||
if (hwtsapi32 != 0)
|
if (hwtsapi32 != 0)
|
||||||
{
|
{
|
||||||
FARPROC reg = GetProcAddress (hwtsapi32, "WTSRegisterSessionNotification");
|
FARPROC reg = GetProcAddress (hwtsapi32, "WTSRegisterSessionNotification");
|
||||||
if (reg == 0 || !((BOOL(WINAPI *)(HWND, DWORD))reg) (Window, NOTIFY_FOR_THIS_SESSION))
|
if (reg == 0 || !((BOOL(WINAPI *)(HWND, DWORD))reg) (mainwindow.GetHandle(), NOTIFY_FOR_THIS_SESSION))
|
||||||
{
|
{
|
||||||
FreeLibrary (hwtsapi32);
|
FreeLibrary (hwtsapi32);
|
||||||
hwtsapi32 = 0;
|
hwtsapi32 = 0;
|
||||||
|
@ -970,7 +356,7 @@ int DoMain (HINSTANCE hInstance)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GetClientRect (Window, &cRect);
|
GetClientRect (mainwindow.GetHandle(), &cRect);
|
||||||
|
|
||||||
WinWidth = cRect.right;
|
WinWidth = cRect.right;
|
||||||
WinHeight = cRect.bottom;
|
WinHeight = cRect.bottom;
|
||||||
|
@ -979,7 +365,7 @@ int DoMain (HINSTANCE hInstance)
|
||||||
atexit (UnCOM);
|
atexit (UnCOM);
|
||||||
|
|
||||||
int ret = GameMain ();
|
int ret = GameMain ();
|
||||||
CheckForRestart();
|
mainwindow.CheckForRestart();
|
||||||
|
|
||||||
DestroyCustomCursor();
|
DestroyCustomCursor();
|
||||||
if (ret == 1337) // special exit code for 'norun'.
|
if (ret == 1337) // special exit code for 'norun'.
|
||||||
|
@ -991,7 +377,7 @@ int DoMain (HINSTANCE hInstance)
|
||||||
DWORD bytes;
|
DWORD bytes;
|
||||||
HANDLE stdinput = GetStdHandle(STD_INPUT_HANDLE);
|
HANDLE stdinput = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
|
||||||
ShowWindow(Window, SW_HIDE);
|
ShowWindow(mainwindow.GetHandle(), SW_HIDE);
|
||||||
WriteFile(StdOut, "Press any key to exit...", 24, &bytes, NULL);
|
WriteFile(StdOut, "Press any key to exit...", 24, &bytes, NULL);
|
||||||
FlushConsoleInputBuffer(stdinput);
|
FlushConsoleInputBuffer(stdinput);
|
||||||
SetConsoleMode(stdinput, 0);
|
SetConsoleMode(stdinput, 0);
|
||||||
|
@ -999,7 +385,7 @@ int DoMain (HINSTANCE hInstance)
|
||||||
}
|
}
|
||||||
else if (StdOut == NULL)
|
else if (StdOut == NULL)
|
||||||
{
|
{
|
||||||
ShowErrorPane(NULL);
|
mainwindow.ShowErrorPane(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1009,9 +395,8 @@ int DoMain (HINSTANCE hInstance)
|
||||||
void I_ShowFatalError(const char *msg)
|
void I_ShowFatalError(const char *msg)
|
||||||
{
|
{
|
||||||
I_ShutdownGraphics ();
|
I_ShutdownGraphics ();
|
||||||
RestoreConView ();
|
mainwindow.RestoreConView();
|
||||||
S_StopMusic(true);
|
S_StopMusic(true);
|
||||||
I_FlushBufferedConsoleStuff();
|
|
||||||
|
|
||||||
if (CVMAbortException::stacktrace.IsNotEmpty())
|
if (CVMAbortException::stacktrace.IsNotEmpty())
|
||||||
{
|
{
|
||||||
|
@ -1020,7 +405,7 @@ void I_ShowFatalError(const char *msg)
|
||||||
|
|
||||||
if (!batchrun)
|
if (!batchrun)
|
||||||
{
|
{
|
||||||
ShowErrorPane(msg);
|
mainwindow.ShowErrorPane(msg);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1087,7 +472,7 @@ void CALLBACK ExitFatally (ULONG_PTR dummy)
|
||||||
{
|
{
|
||||||
SetUnhandledExceptionFilter (ExitMessedUp);
|
SetUnhandledExceptionFilter (ExitMessedUp);
|
||||||
I_ShutdownGraphics ();
|
I_ShutdownGraphics ();
|
||||||
RestoreConView ();
|
mainwindow.RestoreConView ();
|
||||||
DisplayCrashLog ();
|
DisplayCrashLog ();
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
@ -1122,7 +507,7 @@ LONG WINAPI CatchAllExceptions (LPEXCEPTION_POINTERS info)
|
||||||
|
|
||||||
CrashPointers = *info;
|
CrashPointers = *info;
|
||||||
if (sysCallbacks.CrashInfo && custominfo) sysCallbacks.CrashInfo(custominfo, 16384, "\r\n");
|
if (sysCallbacks.CrashInfo && custominfo) sysCallbacks.CrashInfo(custominfo, 16384, "\r\n");
|
||||||
CreateCrashLog (custominfo, (DWORD)strlen(custominfo), ConWindow);
|
CreateCrashLog (custominfo, (DWORD)strlen(custominfo));
|
||||||
|
|
||||||
// If the main thread crashed, then make it clean up after itself.
|
// If the main thread crashed, then make it clean up after itself.
|
||||||
// Otherwise, put the crashing thread to sleep and signal the main thread to clean up.
|
// Otherwise, put the crashing thread to sleep and signal the main thread to clean up.
|
||||||
|
@ -1208,7 +593,7 @@ int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE nothing, LPWSTR cmdline, int
|
||||||
*(int *)0 = 0;
|
*(int *)0 = 0;
|
||||||
}
|
}
|
||||||
__except(CrashPointers = *GetExceptionInformation(),
|
__except(CrashPointers = *GetExceptionInformation(),
|
||||||
CreateCrashLog ("TestCrash", 9, NULL), EXCEPTION_EXECUTE_HANDLER)
|
CreateCrashLog ("TestCrash", 9), EXCEPTION_EXECUTE_HANDLER)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
DisplayCrashLog ();
|
DisplayCrashLog ();
|
||||||
|
@ -1221,7 +606,7 @@ int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE nothing, LPWSTR cmdline, int
|
||||||
infiniterecursion(1);
|
infiniterecursion(1);
|
||||||
}
|
}
|
||||||
__except(CrashPointers = *GetExceptionInformation(),
|
__except(CrashPointers = *GetExceptionInformation(),
|
||||||
CreateCrashLog ("TestStackCrash", 14, NULL), EXCEPTION_EXECUTE_HANDLER)
|
CreateCrashLog ("TestStackCrash", 14), EXCEPTION_EXECUTE_HANDLER)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
DisplayCrashLog ();
|
DisplayCrashLog ();
|
||||||
|
@ -1287,5 +672,5 @@ void I_SetWindowTitle(const char* caption)
|
||||||
{
|
{
|
||||||
widecaption = WideString(caption);
|
widecaption = WideString(caption);
|
||||||
}
|
}
|
||||||
SetWindowText(Window, widecaption.c_str());
|
SetWindowText(mainwindow.GetHandle(), widecaption.c_str());
|
||||||
}
|
}
|
||||||
|
|
935
src/common/platform/win32/i_mainwindow.cpp
Normal file
935
src/common/platform/win32/i_mainwindow.cpp
Normal file
|
@ -0,0 +1,935 @@
|
||||||
|
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
#include "resource.h"
|
||||||
|
#include "startupinfo.h"
|
||||||
|
#include "gstrings.h"
|
||||||
|
#include "palentry.h"
|
||||||
|
#include "st_start.h"
|
||||||
|
#include "i_input.h"
|
||||||
|
#include "version.h"
|
||||||
|
#include "utf8.h"
|
||||||
|
#include "v_font.h"
|
||||||
|
#include <richedit.h>
|
||||||
|
#include <shellapi.h>
|
||||||
|
#include <commctrl.h>
|
||||||
|
|
||||||
|
#ifdef _M_X64
|
||||||
|
#define X64 " 64-bit"
|
||||||
|
#else
|
||||||
|
#define X64 ""
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MainWindow mainwindow;
|
||||||
|
|
||||||
|
void MainWindow::Create(const FString& caption, int x, int y, int width, int height)
|
||||||
|
{
|
||||||
|
static const WCHAR WinClassName[] = L"MainWindow";
|
||||||
|
|
||||||
|
HINSTANCE hInstance = GetModuleHandle(0);
|
||||||
|
|
||||||
|
WNDCLASS WndClass;
|
||||||
|
WndClass.style = 0;
|
||||||
|
WndClass.lpfnWndProc = LConProc;
|
||||||
|
WndClass.cbClsExtra = 0;
|
||||||
|
WndClass.cbWndExtra = 0;
|
||||||
|
WndClass.hInstance = hInstance;
|
||||||
|
WndClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
|
||||||
|
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||||
|
WndClass.hbrBackground = NULL;
|
||||||
|
WndClass.lpszMenuName = NULL;
|
||||||
|
WndClass.lpszClassName = WinClassName;
|
||||||
|
|
||||||
|
/* register this new class with Windows */
|
||||||
|
if (!RegisterClass((LPWNDCLASS)&WndClass))
|
||||||
|
{
|
||||||
|
MessageBoxA(nullptr, "Could not register window class", "Fatal", MB_ICONEXCLAMATION | MB_OK);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring wcaption = caption.WideString();
|
||||||
|
Window = CreateWindowExW(
|
||||||
|
WS_EX_APPWINDOW,
|
||||||
|
WinClassName,
|
||||||
|
wcaption.c_str(),
|
||||||
|
WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN,
|
||||||
|
x, y, width, height,
|
||||||
|
(HWND)NULL,
|
||||||
|
(HMENU)NULL,
|
||||||
|
hInstance,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (!Window)
|
||||||
|
{
|
||||||
|
MessageBoxA(nullptr, "Unable to create main window", "Fatal", MB_ICONEXCLAMATION | MB_OK);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::HideGameTitleWindow()
|
||||||
|
{
|
||||||
|
if (GameTitleWindow != 0)
|
||||||
|
{
|
||||||
|
DestroyWindow(GameTitleWindow);
|
||||||
|
GameTitleWindow = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int MainWindow::GetGameTitleWindowHeight()
|
||||||
|
{
|
||||||
|
if (GameTitleWindow != 0)
|
||||||
|
{
|
||||||
|
RECT rect;
|
||||||
|
GetClientRect(GameTitleWindow, &rect);
|
||||||
|
return rect.bottom;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the main WndProc, hides all the child windows, and starts up in-game input.
|
||||||
|
void MainWindow::ShowGameView()
|
||||||
|
{
|
||||||
|
if (GetWindowLongPtr(Window, GWLP_USERDATA) == 0)
|
||||||
|
{
|
||||||
|
SetWindowLongPtr(Window, GWLP_USERDATA, 1);
|
||||||
|
SetWindowLongPtr(Window, GWLP_WNDPROC, (LONG_PTR)WndProc);
|
||||||
|
ShowWindow(ConWindow, SW_HIDE);
|
||||||
|
ShowWindow(ProgressBar, SW_HIDE);
|
||||||
|
ConWindowHidden = true;
|
||||||
|
ShowWindow(GameTitleWindow, SW_HIDE);
|
||||||
|
I_InitInput(Window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the main window to its startup state.
|
||||||
|
void MainWindow::RestoreConView()
|
||||||
|
{
|
||||||
|
HDC screenDC = GetDC(0);
|
||||||
|
int dpi = GetDeviceCaps(screenDC, LOGPIXELSX);
|
||||||
|
ReleaseDC(0, screenDC);
|
||||||
|
int width = (512 * dpi + 96 / 2) / 96;
|
||||||
|
int height = (384 * dpi + 96 / 2) / 96;
|
||||||
|
|
||||||
|
// Make sure the window has a frame in case it was fullscreened.
|
||||||
|
SetWindowLongPtr(Window, GWL_STYLE, WS_VISIBLE | WS_OVERLAPPEDWINDOW);
|
||||||
|
if (GetWindowLong(Window, GWL_EXSTYLE) & WS_EX_TOPMOST)
|
||||||
|
{
|
||||||
|
SetWindowPos(Window, HWND_BOTTOM, 0, 0, width, height, SWP_DRAWFRAME | SWP_NOCOPYBITS | SWP_NOMOVE);
|
||||||
|
SetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOSIZE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetWindowPos(Window, NULL, 0, 0, width, height, SWP_DRAWFRAME | SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOZORDER);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetWindowLongPtr(Window, GWLP_WNDPROC, (LONG_PTR)LConProc);
|
||||||
|
ShowWindow(ConWindow, SW_SHOW);
|
||||||
|
ConWindowHidden = false;
|
||||||
|
ShowWindow(GameTitleWindow, SW_SHOW);
|
||||||
|
I_ShutdownInput(); // Make sure the mouse pointer is available.
|
||||||
|
// Make sure the progress bar isn't visible.
|
||||||
|
DeleteStartupScreen();
|
||||||
|
|
||||||
|
FlushBufferedConsoleStuff();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shows an error message, preferably in the main window, but it can use a normal message box too.
|
||||||
|
void MainWindow::ShowErrorPane(const char* text)
|
||||||
|
{
|
||||||
|
auto widetext = WideString(text);
|
||||||
|
if (Window == nullptr || ConWindow == nullptr)
|
||||||
|
{
|
||||||
|
if (text != NULL)
|
||||||
|
{
|
||||||
|
FStringf caption("Fatal Error - " GAMENAME " %s " X64 " (%s)", GetVersionString(), GetGitTime());
|
||||||
|
MessageBoxW(Window, widetext.c_str(),caption.WideString().c_str(), MB_OK | MB_ICONSTOP | MB_TASKMODAL);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StartScreen != NULL) // Ensure that the network pane is hidden.
|
||||||
|
{
|
||||||
|
StartScreen->NetDone();
|
||||||
|
}
|
||||||
|
if (text != NULL)
|
||||||
|
{
|
||||||
|
FStringf caption("Fatal Error - " GAMENAME " %s " X64 " (%s)", GetVersionString(), GetGitTime());
|
||||||
|
auto wcaption = caption.WideString();
|
||||||
|
SetWindowTextW(Window, wcaption.c_str());
|
||||||
|
ErrorIcon = CreateWindowExW(WS_EX_NOPARENTNOTIFY, L"STATIC", NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SS_OWNERDRAW, 0, 0, 0, 0, Window, NULL, GetModuleHandle(0), NULL);
|
||||||
|
if (ErrorIcon != NULL)
|
||||||
|
{
|
||||||
|
SetWindowLong(ErrorIcon, GWL_ID, IDC_ICONPIC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ErrorPane = CreateDialogParam(GetModuleHandle(0), MAKEINTRESOURCE(IDD_ERRORPANE), Window, ErrorPaneProc, (LONG_PTR)NULL);
|
||||||
|
|
||||||
|
if (text != NULL)
|
||||||
|
{
|
||||||
|
CHARRANGE end;
|
||||||
|
CHARFORMAT2 oldformat, newformat;
|
||||||
|
PARAFORMAT2 paraformat;
|
||||||
|
|
||||||
|
// Append the error message to the log.
|
||||||
|
end.cpMax = end.cpMin = GetWindowTextLength(ConWindow);
|
||||||
|
SendMessage(ConWindow, EM_EXSETSEL, 0, (LPARAM)&end);
|
||||||
|
|
||||||
|
// Remember current charformat.
|
||||||
|
oldformat.cbSize = sizeof(oldformat);
|
||||||
|
SendMessage(ConWindow, EM_GETCHARFORMAT, SCF_SELECTION, (LPARAM)&oldformat);
|
||||||
|
|
||||||
|
// Use bigger font and standout colors.
|
||||||
|
newformat.cbSize = sizeof(newformat);
|
||||||
|
newformat.dwMask = CFM_BOLD | CFM_COLOR | CFM_SIZE;
|
||||||
|
newformat.dwEffects = CFE_BOLD;
|
||||||
|
newformat.yHeight = oldformat.yHeight * 5 / 4;
|
||||||
|
newformat.crTextColor = RGB(255, 170, 170);
|
||||||
|
SendMessage(ConWindow, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&newformat);
|
||||||
|
|
||||||
|
// Indent the rest of the text to make the error message stand out a little more.
|
||||||
|
paraformat.cbSize = sizeof(paraformat);
|
||||||
|
paraformat.dwMask = PFM_STARTINDENT | PFM_OFFSETINDENT | PFM_RIGHTINDENT;
|
||||||
|
paraformat.dxStartIndent = paraformat.dxOffset = paraformat.dxRightIndent = 120;
|
||||||
|
SendMessage(ConWindow, EM_SETPARAFORMAT, 0, (LPARAM)¶format);
|
||||||
|
SendMessageW(ConWindow, EM_REPLACESEL, FALSE, (LPARAM)L"\n");
|
||||||
|
|
||||||
|
// Find out where the error lines start for the error icon display control.
|
||||||
|
SendMessage(ConWindow, EM_EXGETSEL, 0, (LPARAM)&end);
|
||||||
|
ErrorIconChar = end.cpMax;
|
||||||
|
|
||||||
|
// Now start adding the actual error message.
|
||||||
|
SendMessageW(ConWindow, EM_REPLACESEL, FALSE, (LPARAM)L"Execution could not continue.\n\n");
|
||||||
|
|
||||||
|
// Restore old charformat but with light yellow text.
|
||||||
|
oldformat.crTextColor = RGB(255, 255, 170);
|
||||||
|
SendMessage(ConWindow, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&oldformat);
|
||||||
|
|
||||||
|
// Add the error text.
|
||||||
|
SendMessageW(ConWindow, EM_REPLACESEL, FALSE, (LPARAM)widetext.c_str());
|
||||||
|
|
||||||
|
// Make sure the error text is not scrolled below the window.
|
||||||
|
SendMessage(ConWindow, EM_LINESCROLL, 0, SendMessage(ConWindow, EM_GETLINECOUNT, 0, 0));
|
||||||
|
// The above line scrolled everything off the screen, so pretend to move the scroll
|
||||||
|
// bar thumb, which clamps to not show any extra lines if it doesn't need to.
|
||||||
|
SendMessage(ConWindow, EM_SCROLL, SB_PAGEDOWN, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL bRet;
|
||||||
|
MSG msg;
|
||||||
|
|
||||||
|
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
|
||||||
|
{
|
||||||
|
if (bRet == -1)
|
||||||
|
{
|
||||||
|
MessageBoxW(Window, widetext.c_str(), WGAMENAME " Fatal Error", MB_OK | MB_ICONSTOP | MB_TASKMODAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (!IsDialogMessage(ErrorPane, &msg))
|
||||||
|
{
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::ShowProgressBar(int maxpos)
|
||||||
|
{
|
||||||
|
if (ProgressBar == 0)
|
||||||
|
ProgressBar = CreateWindowEx(0, PROGRESS_CLASS, 0, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS, 0, 0, 0, 0, Window, 0, GetModuleHandle(0), 0);
|
||||||
|
SendMessage(ProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0, maxpos));
|
||||||
|
LayoutMainWindow(Window, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::HideProgressBar()
|
||||||
|
{
|
||||||
|
if (ProgressBar != 0)
|
||||||
|
{
|
||||||
|
DestroyWindow(ProgressBar);
|
||||||
|
ProgressBar = 0;
|
||||||
|
LayoutMainWindow(Window, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::SetProgressPos(int pos)
|
||||||
|
{
|
||||||
|
if (ProgressBar != 0)
|
||||||
|
SendMessage(ProgressBar, PBM_SETPOS, pos, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// DialogProc for the network startup pane. It just waits for somebody to click a button, and the only button available is the abort one.
|
||||||
|
static INT_PTR CALLBACK NetStartPaneProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
if (msg == WM_COMMAND && HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDCANCEL)
|
||||||
|
{
|
||||||
|
PostQuitMessage(0);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::ShowNetStartPane(const char* message, int maxpos)
|
||||||
|
{
|
||||||
|
// Create the dialog child window
|
||||||
|
if (NetStartPane == NULL)
|
||||||
|
{
|
||||||
|
NetStartPane = CreateDialogParam(GetModuleHandle(0), MAKEINTRESOURCE(IDD_NETSTARTPANE), Window, NetStartPaneProc, 0);
|
||||||
|
if (ProgressBar != 0)
|
||||||
|
{
|
||||||
|
DestroyWindow(ProgressBar);
|
||||||
|
ProgressBar = 0;
|
||||||
|
}
|
||||||
|
RECT winrect;
|
||||||
|
GetWindowRect(Window, &winrect);
|
||||||
|
SetWindowPos(Window, NULL, 0, 0,
|
||||||
|
winrect.right - winrect.left, winrect.bottom - winrect.top + LayoutNetStartPane(NetStartPane, 0),
|
||||||
|
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER);
|
||||||
|
LayoutMainWindow(Window, NULL);
|
||||||
|
SetFocus(NetStartPane);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the message text
|
||||||
|
std::wstring wmessage = WideString(message);
|
||||||
|
SetDlgItemTextW(NetStartPane, IDC_NETSTARTMESSAGE, wmessage.c_str());
|
||||||
|
|
||||||
|
// Set the progress bar range
|
||||||
|
NetStartMaxPos = maxpos;
|
||||||
|
HWND ctl = GetDlgItem(NetStartPane, IDC_NETSTARTPROGRESS);
|
||||||
|
if (maxpos == 0)
|
||||||
|
{
|
||||||
|
SendMessage(ctl, PBM_SETMARQUEE, TRUE, 100);
|
||||||
|
SetWindowLong(ctl, GWL_STYLE, GetWindowLong(ctl, GWL_STYLE) | PBS_MARQUEE);
|
||||||
|
SetDlgItemTextW(NetStartPane, IDC_NETSTARTCOUNT, L"");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendMessage(ctl, PBM_SETMARQUEE, FALSE, 0);
|
||||||
|
SetWindowLong(ctl, GWL_STYLE, GetWindowLong(ctl, GWL_STYLE) & (~PBS_MARQUEE));
|
||||||
|
|
||||||
|
SendMessage(ctl, PBM_SETRANGE, 0, MAKELPARAM(0, maxpos));
|
||||||
|
if (maxpos == 1)
|
||||||
|
{
|
||||||
|
SendMessage(ctl, PBM_SETPOS, 1, 0);
|
||||||
|
SetDlgItemTextW(NetStartPane, IDC_NETSTARTCOUNT, L"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::HideNetStartPane()
|
||||||
|
{
|
||||||
|
if (NetStartPane != 0)
|
||||||
|
{
|
||||||
|
DestroyWindow(NetStartPane);
|
||||||
|
NetStartPane = 0;
|
||||||
|
LayoutMainWindow(Window, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::SetNetStartProgress(int pos)
|
||||||
|
{
|
||||||
|
if (NetStartPane != 0 && NetStartMaxPos > 1)
|
||||||
|
{
|
||||||
|
char buf[16];
|
||||||
|
mysnprintf(buf, countof(buf), "%d/%d", pos, NetStartMaxPos);
|
||||||
|
SetDlgItemTextA(NetStartPane, IDC_NETSTARTCOUNT, buf);
|
||||||
|
SendDlgItemMessage(NetStartPane, IDC_NETSTARTPROGRESS, PBM_SETPOS, min(pos, NetStartMaxPos), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MainWindow::RunMessageLoop(bool (*timer_callback)(void*), void* userdata)
|
||||||
|
{
|
||||||
|
BOOL bRet;
|
||||||
|
MSG msg;
|
||||||
|
|
||||||
|
if (SetTimer(Window, 1337, 500, NULL) == 0)
|
||||||
|
{
|
||||||
|
I_FatalError("Could not set network synchronization timer.");
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
|
||||||
|
{
|
||||||
|
if (bRet == -1)
|
||||||
|
{
|
||||||
|
KillTimer(Window, 1337);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (msg.message == WM_TIMER && msg.hwnd == Window && msg.wParam == 1337)
|
||||||
|
{
|
||||||
|
if (timer_callback(userdata))
|
||||||
|
{
|
||||||
|
KillTimer(Window, 1337);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!IsDialogMessage(NetStartPane, &msg))
|
||||||
|
{
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
KillTimer(Window, 1337);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::ShowStartupScreen()
|
||||||
|
{
|
||||||
|
StartupScreen = CreateWindowEx(WS_EX_NOPARENTNOTIFY, L"STATIC", 0, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SS_OWNERDRAW, 0, 0, 0, 0, Window, 0, GetModuleHandle(0), 0);
|
||||||
|
if (StartupScreen != 0)
|
||||||
|
SetWindowLong(StartupScreen, GWL_ID, IDC_STATIC_STARTUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::HideStartupScreen()
|
||||||
|
{
|
||||||
|
if (StartupScreen != 0)
|
||||||
|
{
|
||||||
|
DestroyWindow(StartupScreen);
|
||||||
|
StartupScreen = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::InvalidateStartupScreen()
|
||||||
|
{
|
||||||
|
InvalidateRect(StartupScreen, 0, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::InvalidateStartupScreen(int left, int top, int right, int bottom)
|
||||||
|
{
|
||||||
|
RECT rect;
|
||||||
|
GetClientRect(StartupScreen, &rect);
|
||||||
|
rect.left = left * rect.right / StartupBitmap->bmiHeader.biWidth - 1;
|
||||||
|
rect.top = top * rect.bottom / StartupBitmap->bmiHeader.biHeight - 1;
|
||||||
|
rect.right = right * rect.right / StartupBitmap->bmiHeader.biWidth + 1;
|
||||||
|
rect.bottom = bottom * rect.bottom / StartupBitmap->bmiHeader.biHeight + 1;
|
||||||
|
InvalidateRect(StartupScreen, &rect, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::UpdateLayout()
|
||||||
|
{
|
||||||
|
LayoutMainWindow(Window, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lays out the main window with the game title and log controls and possibly the error pane and progress bar.
|
||||||
|
void MainWindow::LayoutMainWindow(HWND hWnd, HWND pane)
|
||||||
|
{
|
||||||
|
RECT rect;
|
||||||
|
int errorpaneheight = 0;
|
||||||
|
int bannerheight = 0;
|
||||||
|
int progressheight = 0;
|
||||||
|
int netpaneheight = 0;
|
||||||
|
int leftside = 0;
|
||||||
|
int w, h;
|
||||||
|
|
||||||
|
GetClientRect(hWnd, &rect);
|
||||||
|
w = rect.right;
|
||||||
|
h = rect.bottom;
|
||||||
|
|
||||||
|
if (GameStartupInfo.Name.IsNotEmpty() && GameTitleWindow != NULL)
|
||||||
|
{
|
||||||
|
bannerheight = GameTitleFontHeight + 5;
|
||||||
|
MoveWindow(GameTitleWindow, 0, 0, w, bannerheight, TRUE);
|
||||||
|
InvalidateRect(GameTitleWindow, NULL, FALSE);
|
||||||
|
}
|
||||||
|
if (ProgressBar != NULL)
|
||||||
|
{
|
||||||
|
// Base the height of the progress bar on the height of a scroll bar
|
||||||
|
// arrow, just as in the progress bar example.
|
||||||
|
progressheight = GetSystemMetrics(SM_CYVSCROLL);
|
||||||
|
MoveWindow(ProgressBar, 0, h - progressheight, w, progressheight, TRUE);
|
||||||
|
}
|
||||||
|
if (NetStartPane != NULL)
|
||||||
|
{
|
||||||
|
netpaneheight = LayoutNetStartPane(NetStartPane, w);
|
||||||
|
SetWindowPos(NetStartPane, HWND_TOP, 0, h - progressheight - netpaneheight, w, netpaneheight, SWP_SHOWWINDOW);
|
||||||
|
}
|
||||||
|
if (pane != NULL)
|
||||||
|
{
|
||||||
|
errorpaneheight = LayoutErrorPane(pane, w);
|
||||||
|
SetWindowPos(pane, HWND_TOP, 0, h - progressheight - netpaneheight - errorpaneheight, w, errorpaneheight, 0);
|
||||||
|
}
|
||||||
|
if (ErrorIcon != NULL)
|
||||||
|
{
|
||||||
|
leftside = GetSystemMetrics(SM_CXICON) + 6;
|
||||||
|
MoveWindow(ErrorIcon, 0, bannerheight, leftside, h - bannerheight - errorpaneheight - progressheight - netpaneheight, TRUE);
|
||||||
|
}
|
||||||
|
// If there is a startup screen, it covers the log window
|
||||||
|
if (StartupScreen != NULL)
|
||||||
|
{
|
||||||
|
SetWindowPos(StartupScreen, HWND_TOP, leftside, bannerheight, w - leftside, h - bannerheight - errorpaneheight - progressheight - netpaneheight, SWP_SHOWWINDOW);
|
||||||
|
InvalidateRect(StartupScreen, NULL, FALSE);
|
||||||
|
MoveWindow(ConWindow, 0, 0, 0, 0, TRUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The log window uses whatever space is left.
|
||||||
|
MoveWindow(ConWindow, leftside, bannerheight, w - leftside, h - bannerheight - errorpaneheight - progressheight - netpaneheight, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lays out the error pane to the desired width, returning the required height.
|
||||||
|
int MainWindow::LayoutErrorPane(HWND pane, int w)
|
||||||
|
{
|
||||||
|
HWND ctl, ctl_two;
|
||||||
|
RECT rectc, rectc_two;
|
||||||
|
|
||||||
|
// Right-align the Quit button.
|
||||||
|
ctl = GetDlgItem(pane, IDOK);
|
||||||
|
GetClientRect(ctl, &rectc); // Find out how big it is.
|
||||||
|
MoveWindow(ctl, w - rectc.right - 1, 1, rectc.right, rectc.bottom, TRUE);
|
||||||
|
|
||||||
|
// Second-right-align the Restart button
|
||||||
|
ctl_two = GetDlgItem(pane, IDC_BUTTON1);
|
||||||
|
GetClientRect(ctl_two, &rectc_two); // Find out how big it is.
|
||||||
|
MoveWindow(ctl_two, w - rectc.right - rectc_two.right - 2, 1, rectc.right, rectc.bottom, TRUE);
|
||||||
|
|
||||||
|
InvalidateRect(ctl, NULL, TRUE);
|
||||||
|
InvalidateRect(ctl_two, NULL, TRUE);
|
||||||
|
|
||||||
|
// Return the needed height for this layout
|
||||||
|
return rectc.bottom + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lays out the network startup pane to the specified width, returning its required height.
|
||||||
|
int MainWindow::LayoutNetStartPane(HWND pane, int w)
|
||||||
|
{
|
||||||
|
HWND ctl;
|
||||||
|
RECT margin, rectc;
|
||||||
|
int staticheight, barheight;
|
||||||
|
|
||||||
|
// Determine margin sizes.
|
||||||
|
SetRect(&margin, 7, 7, 0, 0);
|
||||||
|
MapDialogRect(pane, &margin);
|
||||||
|
|
||||||
|
// Stick the message text in the upper left corner.
|
||||||
|
ctl = GetDlgItem(pane, IDC_NETSTARTMESSAGE);
|
||||||
|
GetClientRect(ctl, &rectc);
|
||||||
|
MoveWindow(ctl, margin.left, margin.top, rectc.right, rectc.bottom, TRUE);
|
||||||
|
|
||||||
|
// Stick the count text in the upper right corner.
|
||||||
|
ctl = GetDlgItem(pane, IDC_NETSTARTCOUNT);
|
||||||
|
GetClientRect(ctl, &rectc);
|
||||||
|
MoveWindow(ctl, w - rectc.right - margin.left, margin.top, rectc.right, rectc.bottom, TRUE);
|
||||||
|
staticheight = rectc.bottom;
|
||||||
|
|
||||||
|
// Stretch the progress bar to fill the entire width.
|
||||||
|
ctl = GetDlgItem(pane, IDC_NETSTARTPROGRESS);
|
||||||
|
barheight = GetSystemMetrics(SM_CYVSCROLL);
|
||||||
|
MoveWindow(ctl, margin.left, margin.top * 2 + staticheight, w - margin.left * 2, barheight, TRUE);
|
||||||
|
|
||||||
|
// Center the abort button underneath the progress bar.
|
||||||
|
ctl = GetDlgItem(pane, IDCANCEL);
|
||||||
|
GetClientRect(ctl, &rectc);
|
||||||
|
MoveWindow(ctl, (w - rectc.right) / 2, margin.top * 3 + staticheight + barheight, rectc.right, rectc.bottom, TRUE);
|
||||||
|
|
||||||
|
return margin.top * 4 + staticheight + barheight + rectc.bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::CheckForRestart()
|
||||||
|
{
|
||||||
|
if (restartrequest)
|
||||||
|
{
|
||||||
|
HMODULE hModule = GetModuleHandleW(NULL);
|
||||||
|
WCHAR path[MAX_PATH];
|
||||||
|
GetModuleFileNameW(hModule, path, MAX_PATH);
|
||||||
|
ShellExecuteW(NULL, L"open", path, GetCommandLineW(), NULL, SW_SHOWNORMAL);
|
||||||
|
}
|
||||||
|
restartrequest = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The main window's WndProc during startup. During gameplay, the WndProc in i_input.cpp is used instead.
|
||||||
|
LRESULT MainWindow::LConProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
return mainwindow.OnMessage(hWnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
INT_PTR MainWindow::ErrorPaneProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
switch (msg)
|
||||||
|
{
|
||||||
|
case WM_INITDIALOG:
|
||||||
|
// Appear in the main window.
|
||||||
|
mainwindow.LayoutMainWindow(GetParent(hDlg), hDlg);
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case WM_COMMAND:
|
||||||
|
if (HIWORD(wParam) == BN_CLICKED)
|
||||||
|
{
|
||||||
|
if (LOWORD(wParam) == IDC_BUTTON1) // we pressed the restart button, so run GZDoom again
|
||||||
|
{
|
||||||
|
mainwindow.restartrequest = true;
|
||||||
|
}
|
||||||
|
PostQuitMessage(0);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT MainWindow::OnMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
switch (msg)
|
||||||
|
{
|
||||||
|
case WM_CREATE: return OnCreate(hWnd, msg, wParam, lParam);
|
||||||
|
case WM_SIZE: return OnSize(hWnd, msg, wParam, lParam);
|
||||||
|
case WM_DRAWITEM: return OnDrawItem(hWnd, msg, wParam, lParam);
|
||||||
|
case WM_COMMAND: return OnCommand(hWnd, msg, wParam, lParam);
|
||||||
|
case WM_CLOSE: return OnClose(hWnd, msg, wParam, lParam);
|
||||||
|
case WM_DESTROY: return OnDestroy(hWnd, msg, wParam, lParam);
|
||||||
|
default: return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT MainWindow::OnCreate(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
HWND view;
|
||||||
|
HDC hdc;
|
||||||
|
HGDIOBJ oldfont;
|
||||||
|
LOGFONT lf;
|
||||||
|
TEXTMETRIC tm;
|
||||||
|
CHARFORMAT2W format;
|
||||||
|
|
||||||
|
HINSTANCE inst = (HINSTANCE)(LONG_PTR)GetWindowLongPtr(hWnd, GWLP_HINSTANCE);
|
||||||
|
|
||||||
|
// Create game title static control
|
||||||
|
memset(&lf, 0, sizeof(lf));
|
||||||
|
hdc = GetDC(hWnd);
|
||||||
|
lf.lfHeight = -MulDiv(12, GetDeviceCaps(hdc, LOGPIXELSY), 72);
|
||||||
|
lf.lfCharSet = ANSI_CHARSET;
|
||||||
|
lf.lfWeight = FW_BOLD;
|
||||||
|
lf.lfPitchAndFamily = VARIABLE_PITCH | FF_ROMAN;
|
||||||
|
wcscpy(lf.lfFaceName, L"Trebuchet MS");
|
||||||
|
GameTitleFont = CreateFontIndirect(&lf);
|
||||||
|
|
||||||
|
oldfont = SelectObject(hdc, GetStockObject(DEFAULT_GUI_FONT));
|
||||||
|
GetTextMetrics(hdc, &tm);
|
||||||
|
DefaultGUIFontHeight = tm.tmHeight;
|
||||||
|
if (GameTitleFont == NULL)
|
||||||
|
{
|
||||||
|
GameTitleFontHeight = DefaultGUIFontHeight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SelectObject(hdc, GameTitleFont);
|
||||||
|
GetTextMetrics(hdc, &tm);
|
||||||
|
GameTitleFontHeight = tm.tmHeight;
|
||||||
|
}
|
||||||
|
SelectObject(hdc, oldfont);
|
||||||
|
|
||||||
|
// Create log read-only edit control
|
||||||
|
view = CreateWindowExW(WS_EX_NOPARENTNOTIFY, L"RichEdit20W", nullptr,
|
||||||
|
WS_CHILD | WS_VISIBLE | WS_VSCROLL |
|
||||||
|
ES_LEFT | ES_MULTILINE | WS_CLIPSIBLINGS,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
hWnd, NULL, inst, NULL);
|
||||||
|
HRESULT hr;
|
||||||
|
hr = GetLastError();
|
||||||
|
if (view == NULL)
|
||||||
|
{
|
||||||
|
ReleaseDC(hWnd, hdc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
SendMessage(view, EM_SETREADONLY, TRUE, 0);
|
||||||
|
SendMessage(view, EM_EXLIMITTEXT, 0, 0x7FFFFFFE);
|
||||||
|
SendMessage(view, EM_SETBKGNDCOLOR, 0, RGB(70, 70, 70));
|
||||||
|
// Setup default font for the log.
|
||||||
|
//SendMessage (view, WM_SETFONT, (WPARAM)GetStockObject (DEFAULT_GUI_FONT), FALSE);
|
||||||
|
format.cbSize = sizeof(format);
|
||||||
|
format.dwMask = CFM_BOLD | CFM_COLOR | CFM_FACE | CFM_SIZE | CFM_CHARSET;
|
||||||
|
format.dwEffects = 0;
|
||||||
|
format.yHeight = 200;
|
||||||
|
format.crTextColor = RGB(223, 223, 223);
|
||||||
|
format.bCharSet = ANSI_CHARSET;
|
||||||
|
format.bPitchAndFamily = FF_SWISS | VARIABLE_PITCH;
|
||||||
|
wcscpy(format.szFaceName, L"DejaVu Sans"); // At least I have it. :p
|
||||||
|
SendMessageW(view, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&format);
|
||||||
|
|
||||||
|
ConWindow = view;
|
||||||
|
ReleaseDC(hWnd, hdc);
|
||||||
|
|
||||||
|
view = CreateWindowExW(WS_EX_NOPARENTNOTIFY, L"STATIC", NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SS_OWNERDRAW, 0, 0, 0, 0, hWnd, nullptr, inst, nullptr);
|
||||||
|
if (view == nullptr)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
SetWindowLong(view, GWL_ID, IDC_STATIC_TITLE);
|
||||||
|
GameTitleWindow = view;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT MainWindow::OnSize(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
if (wParam != SIZE_MAXHIDE && wParam != SIZE_MAXSHOW)
|
||||||
|
{
|
||||||
|
LayoutMainWindow(hWnd, ErrorPane);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT MainWindow::OnDrawItem(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
HGDIOBJ oldfont;
|
||||||
|
HBRUSH hbr;
|
||||||
|
DRAWITEMSTRUCT* drawitem;
|
||||||
|
RECT rect;
|
||||||
|
SIZE size;
|
||||||
|
|
||||||
|
// Draw title banner.
|
||||||
|
if (wParam == IDC_STATIC_TITLE && GameStartupInfo.Name.IsNotEmpty())
|
||||||
|
{
|
||||||
|
const PalEntry* c;
|
||||||
|
|
||||||
|
// Draw the game title strip at the top of the window.
|
||||||
|
drawitem = (LPDRAWITEMSTRUCT)lParam;
|
||||||
|
|
||||||
|
// Draw the background.
|
||||||
|
rect = drawitem->rcItem;
|
||||||
|
rect.bottom -= 1;
|
||||||
|
c = (const PalEntry*)&GameStartupInfo.BkColor;
|
||||||
|
hbr = CreateSolidBrush(RGB(c->r, c->g, c->b));
|
||||||
|
FillRect(drawitem->hDC, &drawitem->rcItem, hbr);
|
||||||
|
DeleteObject(hbr);
|
||||||
|
|
||||||
|
// Calculate width of the title string.
|
||||||
|
SetTextAlign(drawitem->hDC, TA_TOP);
|
||||||
|
oldfont = SelectObject(drawitem->hDC, GameTitleFont != NULL ? GameTitleFont : (HFONT)GetStockObject(DEFAULT_GUI_FONT));
|
||||||
|
auto widename = GameStartupInfo.Name.WideString();
|
||||||
|
GetTextExtentPoint32W(drawitem->hDC, widename.c_str(), (int)widename.length(), &size);
|
||||||
|
|
||||||
|
// Draw the title.
|
||||||
|
c = (const PalEntry*)&GameStartupInfo.FgColor;
|
||||||
|
SetTextColor(drawitem->hDC, RGB(c->r, c->g, c->b));
|
||||||
|
SetBkMode(drawitem->hDC, TRANSPARENT);
|
||||||
|
TextOutW(drawitem->hDC, rect.left + (rect.right - rect.left - size.cx) / 2, 2, widename.c_str(), (int)widename.length());
|
||||||
|
SelectObject(drawitem->hDC, oldfont);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
// Draw startup screen
|
||||||
|
else if (wParam == IDC_STATIC_STARTUP)
|
||||||
|
{
|
||||||
|
if (StartupScreen != NULL)
|
||||||
|
{
|
||||||
|
drawitem = (LPDRAWITEMSTRUCT)lParam;
|
||||||
|
|
||||||
|
rect = drawitem->rcItem;
|
||||||
|
// Windows expects DIBs to be bottom-up but ours is top-down,
|
||||||
|
// so flip it vertically while drawing it.
|
||||||
|
StretchDIBits(drawitem->hDC, rect.left, rect.bottom - 1, rect.right - rect.left, rect.top - rect.bottom,
|
||||||
|
0, 0, StartupBitmap->bmiHeader.biWidth, StartupBitmap->bmiHeader.biHeight,
|
||||||
|
ST_Util_BitsForBitmap(StartupBitmap), reinterpret_cast<const BITMAPINFO*>(StartupBitmap), DIB_RGB_COLORS, SRCCOPY);
|
||||||
|
|
||||||
|
// If the title banner is gone, then this is an ENDOOM screen, so draw a short prompt
|
||||||
|
// where the command prompt would have been in DOS.
|
||||||
|
if (GameTitleWindow == NULL)
|
||||||
|
{
|
||||||
|
auto quitmsg = WideString(GStrings("TXT_QUITENDOOM"));
|
||||||
|
|
||||||
|
SetTextColor(drawitem->hDC, RGB(240, 240, 240));
|
||||||
|
SetBkMode(drawitem->hDC, TRANSPARENT);
|
||||||
|
oldfont = SelectObject(drawitem->hDC, (HFONT)GetStockObject(DEFAULT_GUI_FONT));
|
||||||
|
TextOutW(drawitem->hDC, 3, drawitem->rcItem.bottom - DefaultGUIFontHeight - 3, quitmsg.c_str(), (int)quitmsg.length());
|
||||||
|
SelectObject(drawitem->hDC, oldfont);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Draw stop icon.
|
||||||
|
else if (wParam == IDC_ICONPIC)
|
||||||
|
{
|
||||||
|
HICON icon;
|
||||||
|
POINTL char_pos;
|
||||||
|
drawitem = (LPDRAWITEMSTRUCT)lParam;
|
||||||
|
|
||||||
|
// This background color should match the edit control's.
|
||||||
|
hbr = CreateSolidBrush(RGB(70, 70, 70));
|
||||||
|
FillRect(drawitem->hDC, &drawitem->rcItem, hbr);
|
||||||
|
DeleteObject(hbr);
|
||||||
|
|
||||||
|
// Draw the icon aligned with the first line of error text.
|
||||||
|
SendMessage(ConWindow, EM_POSFROMCHAR, (WPARAM)&char_pos, ErrorIconChar);
|
||||||
|
icon = (HICON)LoadImage(0, IDI_ERROR, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
|
||||||
|
DrawIcon(drawitem->hDC, 6, char_pos.y, icon);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT MainWindow::OnCommand(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
if (ErrorIcon != NULL && (HWND)lParam == ConWindow && HIWORD(wParam) == EN_UPDATE)
|
||||||
|
{
|
||||||
|
// Be sure to redraw the error icon if the edit control changes.
|
||||||
|
InvalidateRect(ErrorIcon, NULL, TRUE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT MainWindow::OnClose(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
PostQuitMessage(0);
|
||||||
|
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT MainWindow::OnDestroy(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
if (GameTitleFont != NULL)
|
||||||
|
{
|
||||||
|
DeleteObject(GameTitleFont);
|
||||||
|
}
|
||||||
|
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::PrintStr(const char* cp)
|
||||||
|
{
|
||||||
|
if (ConWindowHidden)
|
||||||
|
{
|
||||||
|
bufferedConsoleStuff.Push(cp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DoPrintStr(cp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::FlushBufferedConsoleStuff()
|
||||||
|
{
|
||||||
|
for (unsigned i = 0; i < bufferedConsoleStuff.Size(); i++)
|
||||||
|
{
|
||||||
|
DoPrintStr(bufferedConsoleStuff[i]);
|
||||||
|
}
|
||||||
|
bufferedConsoleStuff.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::DoPrintStr(const char* cpt)
|
||||||
|
{
|
||||||
|
wchar_t wbuf[256];
|
||||||
|
int bpos = 0;
|
||||||
|
CHARRANGE selection = {};
|
||||||
|
CHARRANGE endselection = {};
|
||||||
|
LONG lines_before = 0, lines_after = 0;
|
||||||
|
|
||||||
|
// Store the current selection and set it to the end so we can append text.
|
||||||
|
SendMessage(ConWindow, EM_EXGETSEL, 0, (LPARAM)&selection);
|
||||||
|
endselection.cpMax = endselection.cpMin = GetWindowTextLength(ConWindow);
|
||||||
|
SendMessage(ConWindow, EM_EXSETSEL, 0, (LPARAM)&endselection);
|
||||||
|
|
||||||
|
// GetWindowTextLength and EM_EXSETSEL can disagree on where the end of
|
||||||
|
// the text is. Find out what EM_EXSETSEL thought it was and use that later.
|
||||||
|
SendMessage(ConWindow, EM_EXGETSEL, 0, (LPARAM)&endselection);
|
||||||
|
|
||||||
|
// Remember how many lines there were before we added text.
|
||||||
|
lines_before = (LONG)SendMessage(ConWindow, EM_GETLINECOUNT, 0, 0);
|
||||||
|
|
||||||
|
const uint8_t* cptr = (const uint8_t*)cpt;
|
||||||
|
|
||||||
|
auto outputIt = [&]()
|
||||||
|
{
|
||||||
|
wbuf[bpos] = 0;
|
||||||
|
SendMessageW(ConWindow, EM_REPLACESEL, FALSE, (LPARAM)wbuf);
|
||||||
|
bpos = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
while (int chr = GetCharFromString(cptr))
|
||||||
|
{
|
||||||
|
if ((chr == TEXTCOLOR_ESCAPE && bpos != 0) || bpos == 255)
|
||||||
|
{
|
||||||
|
outputIt();
|
||||||
|
}
|
||||||
|
if (chr != TEXTCOLOR_ESCAPE)
|
||||||
|
{
|
||||||
|
if (chr >= 0x1D && chr <= 0x1F)
|
||||||
|
{ // The bar characters, most commonly used to indicate map changes
|
||||||
|
chr = 0x2550; // Box Drawings Double Horizontal
|
||||||
|
}
|
||||||
|
wbuf[bpos++] = chr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EColorRange range = V_ParseFontColor(cptr, CR_UNTRANSLATED, CR_YELLOW);
|
||||||
|
|
||||||
|
if (range != CR_UNDEFINED)
|
||||||
|
{
|
||||||
|
// Change the color of future text added to the control.
|
||||||
|
PalEntry color = V_LogColorFromColorRange(range);
|
||||||
|
|
||||||
|
// Change the color.
|
||||||
|
CHARFORMAT format;
|
||||||
|
format.cbSize = sizeof(format);
|
||||||
|
format.dwMask = CFM_COLOR;
|
||||||
|
format.dwEffects = 0;
|
||||||
|
format.crTextColor = RGB(color.r, color.g, color.b);
|
||||||
|
SendMessage(ConWindow, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&format);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bpos != 0)
|
||||||
|
{
|
||||||
|
outputIt();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the old selection was at the end of the text, keep it at the end and
|
||||||
|
// scroll. Don't scroll if the selection is anywhere else.
|
||||||
|
if (selection.cpMin == endselection.cpMin && selection.cpMax == endselection.cpMax)
|
||||||
|
{
|
||||||
|
selection.cpMax = selection.cpMin = GetWindowTextLength(ConWindow);
|
||||||
|
lines_after = (LONG)SendMessage(ConWindow, EM_GETLINECOUNT, 0, 0);
|
||||||
|
if (lines_after > lines_before)
|
||||||
|
{
|
||||||
|
SendMessage(ConWindow, EM_LINESCROLL, 0, lines_after - lines_before);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Restore the previous selection.
|
||||||
|
SendMessage(ConWindow, EM_EXSETSEL, 0, (LPARAM)&selection);
|
||||||
|
// Give the edit control a chance to redraw itself.
|
||||||
|
I_GetEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD CALLBACK WriteLogFileStreamer(DWORD_PTR cookie, LPBYTE buffer, LONG cb, LONG* pcb)
|
||||||
|
{
|
||||||
|
uint32_t didwrite;
|
||||||
|
LONG p, pp;
|
||||||
|
|
||||||
|
// Replace gray foreground color with black.
|
||||||
|
static const char* badfg = "\\red223\\green223\\blue223;";
|
||||||
|
// 4321098 765432109 876543210
|
||||||
|
// 2 1 0
|
||||||
|
for (p = pp = 0; p < cb; ++p)
|
||||||
|
{
|
||||||
|
if (buffer[p] == badfg[pp])
|
||||||
|
{
|
||||||
|
++pp;
|
||||||
|
if (pp == 25)
|
||||||
|
{
|
||||||
|
buffer[p - 1] = buffer[p - 2] = buffer[p - 3] =
|
||||||
|
buffer[p - 9] = buffer[p - 10] = buffer[p - 11] =
|
||||||
|
buffer[p - 18] = buffer[p - 19] = buffer[p - 20] = '0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pp = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& writeData = *reinterpret_cast<std::function<bool(const void* data, uint32_t size, uint32_t& written)>*>(cookie);
|
||||||
|
if (!writeData((const void*)buffer, cb, didwrite))
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
*pcb = didwrite;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::GetLog(std::function<bool(const void* data, uint32_t size, uint32_t& written)> writeData)
|
||||||
|
{
|
||||||
|
FlushBufferedConsoleStuff();
|
||||||
|
|
||||||
|
EDITSTREAM streamer = { (DWORD_PTR)&writeData, 0, WriteLogFileStreamer };
|
||||||
|
SendMessage(ConWindow, EM_STREAMOUT, SF_RTF, (LPARAM)&streamer);
|
||||||
|
}
|
93
src/common/platform/win32/i_mainwindow.h
Normal file
93
src/common/platform/win32/i_mainwindow.h
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "zstring.h"
|
||||||
|
#include "printf.h"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
// The WndProc used when the game view is active
|
||||||
|
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
class MainWindow
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Create(const FString& title, int x, int y, int width, int height);
|
||||||
|
|
||||||
|
void ShowGameView();
|
||||||
|
void RestoreConView();
|
||||||
|
|
||||||
|
void ShowErrorPane(const char* text);
|
||||||
|
void CheckForRestart();
|
||||||
|
|
||||||
|
void HideGameTitleWindow();
|
||||||
|
int GetGameTitleWindowHeight();
|
||||||
|
|
||||||
|
void PrintStr(const char* cp);
|
||||||
|
void GetLog(std::function<bool(const void* data, uint32_t size, uint32_t& written)> writeFile);
|
||||||
|
|
||||||
|
void UpdateLayout();
|
||||||
|
|
||||||
|
void ShowProgressBar(int maxpos);
|
||||||
|
void HideProgressBar();
|
||||||
|
void SetProgressPos(int pos);
|
||||||
|
|
||||||
|
void ShowNetStartPane(const char* message, int maxpos);
|
||||||
|
void SetNetStartProgress(int pos);
|
||||||
|
bool RunMessageLoop(bool (*timer_callback)(void*), void* userdata);
|
||||||
|
void HideNetStartPane();
|
||||||
|
|
||||||
|
void ShowStartupScreen();
|
||||||
|
void HideStartupScreen();
|
||||||
|
void InvalidateStartupScreen();
|
||||||
|
void InvalidateStartupScreen(int left, int top, int right, int bottom);
|
||||||
|
|
||||||
|
HWND GetHandle() { return Window; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void LayoutMainWindow(HWND hWnd, HWND pane);
|
||||||
|
int LayoutErrorPane(HWND pane, int w);
|
||||||
|
int LayoutNetStartPane(HWND pane, int w);
|
||||||
|
|
||||||
|
void DoPrintStr(const char* cpt);
|
||||||
|
void FlushBufferedConsoleStuff();
|
||||||
|
|
||||||
|
LRESULT OnMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
LRESULT OnCreate(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
LRESULT OnSize(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
LRESULT OnDrawItem(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
LRESULT OnCommand(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
LRESULT OnClose(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
LRESULT OnDestroy(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
static LRESULT CALLBACK LConProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
static INT_PTR CALLBACK ErrorPaneProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
HWND Window = 0;
|
||||||
|
|
||||||
|
HFONT GameTitleFont = 0;
|
||||||
|
LONG GameTitleFontHeight = 0;
|
||||||
|
LONG DefaultGUIFontHeight = 0;
|
||||||
|
LONG ErrorIconChar = 0;
|
||||||
|
|
||||||
|
bool restartrequest = false;
|
||||||
|
|
||||||
|
HWND GameTitleWindow = 0;
|
||||||
|
HWND ErrorPane = 0;
|
||||||
|
HWND ErrorIcon = 0;
|
||||||
|
|
||||||
|
bool ConWindowHidden = false;
|
||||||
|
HWND ConWindow = 0;
|
||||||
|
TArray<FString> bufferedConsoleStuff;
|
||||||
|
|
||||||
|
HWND ProgressBar = 0;
|
||||||
|
|
||||||
|
HWND NetStartPane = 0;
|
||||||
|
int NetStartMaxPos = 0;
|
||||||
|
|
||||||
|
HWND StartupScreen = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern MainWindow mainwindow;
|
|
@ -46,6 +46,7 @@
|
||||||
#include "menustate.h"
|
#include "menustate.h"
|
||||||
#include "keydef.h"
|
#include "keydef.h"
|
||||||
#include "i_interface.h"
|
#include "i_interface.h"
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -138,7 +139,6 @@ static void CenterMouse(int x, int y, LONG *centx, LONG *centy);
|
||||||
|
|
||||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||||
|
|
||||||
extern HWND Window;
|
|
||||||
extern LPDIRECTINPUT8 g_pdi;
|
extern LPDIRECTINPUT8 g_pdi;
|
||||||
extern LPDIRECTINPUT g_pdi3;
|
extern LPDIRECTINPUT g_pdi3;
|
||||||
extern bool GUICapture;
|
extern bool GUICapture;
|
||||||
|
@ -193,11 +193,11 @@ CUSTOM_CVAR (Int, in_mouse, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL)
|
||||||
static void SetCursorState(bool visible)
|
static void SetCursorState(bool visible)
|
||||||
{
|
{
|
||||||
CursorState = visible || !m_hidepointer;
|
CursorState = visible || !m_hidepointer;
|
||||||
if (GetForegroundWindow() == Window)
|
if (GetForegroundWindow() == mainwindow.GetHandle())
|
||||||
{
|
{
|
||||||
if (CursorState)
|
if (CursorState)
|
||||||
{
|
{
|
||||||
SetCursor((HCURSOR)(intptr_t)GetClassLongPtr(Window, GCLP_HCURSOR));
|
SetCursor((HCURSOR)(intptr_t)GetClassLongPtr(mainwindow.GetHandle(), GCLP_HCURSOR));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -219,7 +219,7 @@ static void CenterMouse(int curx, int cury, LONG *centxp, LONG *centyp)
|
||||||
{
|
{
|
||||||
RECT rect;
|
RECT rect;
|
||||||
|
|
||||||
GetWindowRect(Window, &rect);
|
GetWindowRect(mainwindow.GetHandle(), &rect);
|
||||||
|
|
||||||
int centx = (rect.left + rect.right) >> 1;
|
int centx = (rect.left + rect.right) >> 1;
|
||||||
int centy = (rect.top + rect.bottom) >> 1;
|
int centy = (rect.top + rect.bottom) >> 1;
|
||||||
|
@ -258,7 +258,7 @@ void I_CheckNativeMouse(bool preferNative, bool eventhandlerresult)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((GetForegroundWindow() != Window) || preferNative || !use_mouse)
|
if ((GetForegroundWindow() != mainwindow.GetHandle()) || preferNative || !use_mouse)
|
||||||
{
|
{
|
||||||
want_native = true;
|
want_native = true;
|
||||||
}
|
}
|
||||||
|
@ -490,7 +490,7 @@ bool FRawMouse::GetDevice()
|
||||||
rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE;
|
rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE;
|
||||||
rid.usUsage = HID_GDP_MOUSE;
|
rid.usUsage = HID_GDP_MOUSE;
|
||||||
rid.dwFlags = 0;
|
rid.dwFlags = 0;
|
||||||
rid.hwndTarget = Window;
|
rid.hwndTarget = mainwindow.GetHandle();
|
||||||
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -516,7 +516,7 @@ void FRawMouse::Grab()
|
||||||
rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE;
|
rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE;
|
||||||
rid.usUsage = HID_GDP_MOUSE;
|
rid.usUsage = HID_GDP_MOUSE;
|
||||||
rid.dwFlags = RIDEV_CAPTUREMOUSE | RIDEV_NOLEGACY;
|
rid.dwFlags = RIDEV_CAPTUREMOUSE | RIDEV_NOLEGACY;
|
||||||
rid.hwndTarget = Window;
|
rid.hwndTarget = mainwindow.GetHandle();
|
||||||
if (RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
if (RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
||||||
{
|
{
|
||||||
GetCursorPos(&UngrabbedPointerPos);
|
GetCursorPos(&UngrabbedPointerPos);
|
||||||
|
@ -718,7 +718,7 @@ ufailit:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = Device->SetCooperativeLevel(Window, DISCL_EXCLUSIVE | DISCL_FOREGROUND);
|
hr = Device->SetCooperativeLevel(mainwindow.GetHandle(), DISCL_EXCLUSIVE | DISCL_FOREGROUND);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
goto ufailit;
|
goto ufailit;
|
||||||
|
@ -1066,11 +1066,11 @@ void FWin32Mouse::Grab()
|
||||||
|
|
||||||
GetCursorPos(&UngrabbedPointerPos);
|
GetCursorPos(&UngrabbedPointerPos);
|
||||||
ClipCursor(NULL); // helps with Win95?
|
ClipCursor(NULL); // helps with Win95?
|
||||||
GetClientRect(Window, &rect);
|
GetClientRect(mainwindow.GetHandle(), &rect);
|
||||||
|
|
||||||
// Reposition the rect so that it only covers the client area.
|
// Reposition the rect so that it only covers the client area.
|
||||||
ClientToScreen(Window, (LPPOINT)&rect.left);
|
ClientToScreen(mainwindow.GetHandle(), (LPPOINT)&rect.left);
|
||||||
ClientToScreen(Window, (LPPOINT)&rect.right);
|
ClientToScreen(mainwindow.GetHandle(), (LPPOINT)&rect.right);
|
||||||
|
|
||||||
ClipCursor(&rect);
|
ClipCursor(&rect);
|
||||||
SetCursorState(false);
|
SetCursorState(false);
|
||||||
|
|
|
@ -44,6 +44,8 @@
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
#include "keydef.h"
|
#include "keydef.h"
|
||||||
|
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
#define DEFAULT_DEADZONE 0.25f
|
#define DEFAULT_DEADZONE 0.25f
|
||||||
|
@ -214,8 +216,6 @@ struct PS2Descriptor
|
||||||
|
|
||||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||||
|
|
||||||
extern HWND Window;
|
|
||||||
|
|
||||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||||
|
|
||||||
CUSTOM_CVAR(Bool, joy_ps2raw, true, CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_NOINITCALL)
|
CUSTOM_CVAR(Bool, joy_ps2raw, true, CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_NOINITCALL)
|
||||||
|
@ -905,7 +905,7 @@ bool FRawPS2Manager::GetDevice()
|
||||||
rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE;
|
rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE;
|
||||||
rid.usUsage = HID_GDP_JOYSTICK;
|
rid.usUsage = HID_GDP_JOYSTICK;
|
||||||
rid.dwFlags = RIDEV_INPUTSINK;
|
rid.dwFlags = RIDEV_INPUTSINK;
|
||||||
rid.hwndTarget = Window;
|
rid.hwndTarget = mainwindow.GetHandle();
|
||||||
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -1273,7 +1273,7 @@ void FRawPS2Manager::DoRegister()
|
||||||
if (!Registered)
|
if (!Registered)
|
||||||
{
|
{
|
||||||
rid.dwFlags = RIDEV_INPUTSINK;
|
rid.dwFlags = RIDEV_INPUTSINK;
|
||||||
rid.hwndTarget = Window;
|
rid.hwndTarget = mainwindow.GetHandle();
|
||||||
if (RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
if (RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
||||||
{
|
{
|
||||||
Registered = true;
|
Registered = true;
|
||||||
|
|
|
@ -81,6 +81,7 @@
|
||||||
#include "bitmap.h"
|
#include "bitmap.h"
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
#include "i_interface.h"
|
#include "i_interface.h"
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -92,10 +93,6 @@
|
||||||
|
|
||||||
// TYPES -------------------------------------------------------------------
|
// TYPES -------------------------------------------------------------------
|
||||||
|
|
||||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
|
||||||
|
|
||||||
extern void LayoutMainWindow(HWND hWnd, HWND pane);
|
|
||||||
|
|
||||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||||
|
|
||||||
void DestroyCustomCursor();
|
void DestroyCustomCursor();
|
||||||
|
@ -116,13 +113,11 @@ EXTERN_CVAR (Bool, autoloadbrightmaps)
|
||||||
EXTERN_CVAR (Bool, autoloadwidescreen)
|
EXTERN_CVAR (Bool, autoloadwidescreen)
|
||||||
EXTERN_CVAR (Int, vid_preferbackend)
|
EXTERN_CVAR (Int, vid_preferbackend)
|
||||||
|
|
||||||
extern HWND Window, ConWindow, GameTitleWindow;
|
|
||||||
extern HANDLE StdOut;
|
extern HANDLE StdOut;
|
||||||
extern bool FancyStdOut;
|
extern bool FancyStdOut;
|
||||||
extern HINSTANCE g_hInst;
|
extern HINSTANCE g_hInst;
|
||||||
extern FILE *Logfile;
|
extern FILE *Logfile;
|
||||||
extern bool NativeMouse;
|
extern bool NativeMouse;
|
||||||
extern bool ConWindowHidden;
|
|
||||||
|
|
||||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||||
|
|
||||||
|
@ -281,42 +276,19 @@ void CalculateCPUSpeed()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
static void DoPrintStr(const char *cpt, HWND edit, HANDLE StdOut)
|
static void PrintToStdOut(const char *cpt, HANDLE StdOut)
|
||||||
{
|
{
|
||||||
if (edit == nullptr && StdOut == nullptr && !con_debugoutput)
|
if (StdOut == nullptr && !con_debugoutput)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wchar_t wbuf[256];
|
wchar_t wbuf[256];
|
||||||
int bpos = 0;
|
int bpos = 0;
|
||||||
CHARRANGE selection = {};
|
|
||||||
CHARRANGE endselection = {};
|
|
||||||
LONG lines_before = 0, lines_after;
|
|
||||||
CHARFORMAT format;
|
|
||||||
|
|
||||||
if (edit != NULL)
|
|
||||||
{
|
|
||||||
// Store the current selection and set it to the end so we can append text.
|
|
||||||
SendMessage(edit, EM_EXGETSEL, 0, (LPARAM)&selection);
|
|
||||||
endselection.cpMax = endselection.cpMin = GetWindowTextLength(edit);
|
|
||||||
SendMessage(edit, EM_EXSETSEL, 0, (LPARAM)&endselection);
|
|
||||||
|
|
||||||
// GetWindowTextLength and EM_EXSETSEL can disagree on where the end of
|
|
||||||
// the text is. Find out what EM_EXSETSEL thought it was and use that later.
|
|
||||||
SendMessage(edit, EM_EXGETSEL, 0, (LPARAM)&endselection);
|
|
||||||
|
|
||||||
// Remember how many lines there were before we added text.
|
|
||||||
lines_before = (LONG)SendMessage(edit, EM_GETLINECOUNT, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint8_t *cptr = (const uint8_t*)cpt;
|
const uint8_t *cptr = (const uint8_t*)cpt;
|
||||||
|
|
||||||
auto outputIt = [&]()
|
auto outputIt = [&]()
|
||||||
{
|
{
|
||||||
wbuf[bpos] = 0;
|
wbuf[bpos] = 0;
|
||||||
if (edit != nullptr)
|
|
||||||
{
|
|
||||||
SendMessageW(edit, EM_REPLACESEL, FALSE, (LPARAM)wbuf);
|
|
||||||
}
|
|
||||||
if (con_debugoutput)
|
if (con_debugoutput)
|
||||||
{
|
{
|
||||||
OutputDebugStringW(wbuf);
|
OutputDebugStringW(wbuf);
|
||||||
|
@ -385,17 +357,6 @@ static void DoPrintStr(const char *cpt, HWND edit, HANDLE StdOut)
|
||||||
}
|
}
|
||||||
SetConsoleTextAttribute(StdOut, (WORD)attrib);
|
SetConsoleTextAttribute(StdOut, (WORD)attrib);
|
||||||
}
|
}
|
||||||
if (edit != NULL)
|
|
||||||
{
|
|
||||||
// GDI uses BGR colors, but color is RGB, so swap the R and the B.
|
|
||||||
std::swap(color.r, color.b);
|
|
||||||
// Change the color.
|
|
||||||
format.cbSize = sizeof(format);
|
|
||||||
format.dwMask = CFM_COLOR;
|
|
||||||
format.dwEffects = 0;
|
|
||||||
format.crTextColor = color;
|
|
||||||
SendMessage(edit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&format);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -404,52 +365,16 @@ static void DoPrintStr(const char *cpt, HWND edit, HANDLE StdOut)
|
||||||
outputIt();
|
outputIt();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (edit != NULL)
|
|
||||||
{
|
|
||||||
// If the old selection was at the end of the text, keep it at the end and
|
|
||||||
// scroll. Don't scroll if the selection is anywhere else.
|
|
||||||
if (selection.cpMin == endselection.cpMin && selection.cpMax == endselection.cpMax)
|
|
||||||
{
|
|
||||||
selection.cpMax = selection.cpMin = GetWindowTextLength (edit);
|
|
||||||
lines_after = (LONG)SendMessage(edit, EM_GETLINECOUNT, 0, 0);
|
|
||||||
if (lines_after > lines_before)
|
|
||||||
{
|
|
||||||
SendMessage(edit, EM_LINESCROLL, 0, lines_after - lines_before);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Restore the previous selection.
|
|
||||||
SendMessage(edit, EM_EXSETSEL, 0, (LPARAM)&selection);
|
|
||||||
// Give the edit control a chance to redraw itself.
|
|
||||||
I_GetEvent();
|
|
||||||
}
|
|
||||||
if (StdOut != NULL && FancyStdOut)
|
if (StdOut != NULL && FancyStdOut)
|
||||||
{ // Set text back to gray, in case it was changed.
|
{ // Set text back to gray, in case it was changed.
|
||||||
SetConsoleTextAttribute(StdOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
SetConsoleTextAttribute(StdOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static TArray<FString> bufferedConsoleStuff;
|
|
||||||
|
|
||||||
void I_PrintStr(const char *cp)
|
void I_PrintStr(const char *cp)
|
||||||
{
|
{
|
||||||
if (ConWindowHidden)
|
mainwindow.PrintStr(cp);
|
||||||
{
|
PrintToStdOut(cp, StdOut);
|
||||||
bufferedConsoleStuff.Push(cp);
|
|
||||||
DoPrintStr(cp, NULL, StdOut);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DoPrintStr(cp, ConWindow, StdOut);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void I_FlushBufferedConsoleStuff()
|
|
||||||
{
|
|
||||||
for (unsigned i = 0; i < bufferedConsoleStuff.Size(); i++)
|
|
||||||
{
|
|
||||||
DoPrintStr(bufferedConsoleStuff[i], ConWindow, NULL);
|
|
||||||
}
|
|
||||||
bufferedConsoleStuff.Clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -635,7 +560,7 @@ int I_PickIWad(WadStuff *wads, int numwads, bool showwin, int defaultiwad)
|
||||||
DefaultWad = defaultiwad;
|
DefaultWad = defaultiwad;
|
||||||
|
|
||||||
return (int)DialogBox(g_hInst, MAKEINTRESOURCE(IDD_IWADDIALOG),
|
return (int)DialogBox(g_hInst, MAKEINTRESOURCE(IDD_IWADDIALOG),
|
||||||
(HWND)Window, (DLGPROC)IWADBoxCallback);
|
(HWND)mainwindow.GetHandle(), (DLGPROC)IWADBoxCallback);
|
||||||
}
|
}
|
||||||
return defaultiwad;
|
return defaultiwad;
|
||||||
}
|
}
|
||||||
|
@ -682,16 +607,16 @@ bool I_SetCursor(FGameTexture *cursorpic)
|
||||||
DestroyCustomCursor();
|
DestroyCustomCursor();
|
||||||
cursor = LoadCursor(NULL, IDC_ARROW);
|
cursor = LoadCursor(NULL, IDC_ARROW);
|
||||||
}
|
}
|
||||||
SetClassLongPtr(Window, GCLP_HCURSOR, (LONG_PTR)cursor);
|
SetClassLongPtr(mainwindow.GetHandle(), GCLP_HCURSOR, (LONG_PTR)cursor);
|
||||||
if (NativeMouse)
|
if (NativeMouse)
|
||||||
{
|
{
|
||||||
POINT pt;
|
POINT pt;
|
||||||
RECT client;
|
RECT client;
|
||||||
|
|
||||||
// If the mouse pointer is within the window's client rect, set it now.
|
// If the mouse pointer is within the window's client rect, set it now.
|
||||||
if (GetCursorPos(&pt) && GetClientRect(Window, &client) &&
|
if (GetCursorPos(&pt) && GetClientRect(mainwindow.GetHandle(), &client) &&
|
||||||
ClientToScreen(Window, (LPPOINT)&client.left) &&
|
ClientToScreen(mainwindow.GetHandle(), (LPPOINT)&client.left) &&
|
||||||
ClientToScreen(Window, (LPPOINT)&client.right))
|
ClientToScreen(mainwindow.GetHandle(), (LPPOINT)&client.right))
|
||||||
{
|
{
|
||||||
if (pt.x >= client.left && pt.x < client.right &&
|
if (pt.x >= client.left && pt.x < client.right &&
|
||||||
pt.y >= client.top && pt.y < client.bottom)
|
pt.y >= client.top && pt.y < client.bottom)
|
||||||
|
@ -912,7 +837,7 @@ bool I_WriteIniFailed()
|
||||||
);
|
);
|
||||||
errortext.Format ("The config file %s could not be written:\n%s", GameConfig->GetPathName(), lpMsgBuf);
|
errortext.Format ("The config file %s could not be written:\n%s", GameConfig->GetPathName(), lpMsgBuf);
|
||||||
LocalFree (lpMsgBuf);
|
LocalFree (lpMsgBuf);
|
||||||
return MessageBoxA(Window, errortext.GetChars(), GAMENAME " configuration not saved", MB_ICONEXCLAMATION | MB_RETRYCANCEL) == IDRETRY;
|
return MessageBoxA(mainwindow.GetHandle(), errortext.GetChars(), GAMENAME " configuration not saved", MB_ICONEXCLAMATION | MB_RETRYCANCEL) == IDRETRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -43,9 +43,6 @@ int I_PickIWad (WadStuff *wads, int numwads, bool queryiwad, int defaultiwad);
|
||||||
// The ini could not be saved at exit
|
// The ini could not be saved at exit
|
||||||
bool I_WriteIniFailed ();
|
bool I_WriteIniFailed ();
|
||||||
|
|
||||||
// [RH] Used by the display code to set the normal window procedure
|
|
||||||
void I_SetWndProc();
|
|
||||||
|
|
||||||
// [RH] Checks the registry for Steam's install path, so we can scan its
|
// [RH] Checks the registry for Steam's install path, so we can scan its
|
||||||
// directories for IWADs if the user purchased any through Steam.
|
// directories for IWADs if the user purchased any through Steam.
|
||||||
TArray<FString> I_GetSteamPath();
|
TArray<FString> I_GetSteamPath();
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
#include "startupinfo.h"
|
#include "startupinfo.h"
|
||||||
#include "i_interface.h"
|
#include "i_interface.h"
|
||||||
#include "texturemanager.h"
|
#include "texturemanager.h"
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -67,24 +68,13 @@
|
||||||
|
|
||||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||||
|
|
||||||
void RestoreConView();
|
|
||||||
void LayoutMainWindow (HWND hWnd, HWND pane);
|
|
||||||
int LayoutNetStartPane (HWND pane, int w);
|
|
||||||
|
|
||||||
bool ST_Util_CreateStartupWindow ();
|
|
||||||
void ST_Util_SizeWindowForBitmap (int scale);
|
void ST_Util_SizeWindowForBitmap (int scale);
|
||||||
void ST_Util_InvalidateRect (HWND hwnd, BitmapInfo *bitmap_info, int left, int top, int right, int bottom);
|
|
||||||
|
|
||||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||||
|
|
||||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
|
||||||
|
|
||||||
static INT_PTR CALLBACK NetStartPaneProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
|
|
||||||
|
|
||||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||||
|
|
||||||
extern HINSTANCE g_hInst;
|
extern HINSTANCE g_hInst;
|
||||||
extern HWND Window, ConWindow, ProgressBar, NetStartPane, StartupScreen, GameTitleWindow;
|
|
||||||
|
|
||||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||||
|
|
||||||
|
@ -112,7 +102,7 @@ CUSTOM_CVAR(Int, showendoom, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
FStartupScreen *FStartupScreen::CreateInstance(int max_progress)
|
FStartupScreen *FStartupScreen::CreateInstance(int max_progress)
|
||||||
{
|
{
|
||||||
FStartupScreen *scr = NULL;
|
FStartupScreen *scr = NULL;
|
||||||
HRESULT hr = -1;
|
HRESULT hr = E_FAIL;
|
||||||
|
|
||||||
if (!Args->CheckParm("-nostartup"))
|
if (!Args->CheckParm("-nostartup"))
|
||||||
{
|
{
|
||||||
|
@ -154,12 +144,7 @@ FBasicStartupScreen::FBasicStartupScreen(int max_progress, bool show_bar)
|
||||||
{
|
{
|
||||||
if (show_bar)
|
if (show_bar)
|
||||||
{
|
{
|
||||||
ProgressBar = CreateWindowEx(0, PROGRESS_CLASS,
|
mainwindow.ShowProgressBar(MaxPos);
|
||||||
NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
|
|
||||||
0, 0, 0, 0,
|
|
||||||
Window, 0, g_hInst, NULL);
|
|
||||||
SendMessage (ProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0,MaxPos));
|
|
||||||
LayoutMainWindow (Window, NULL);
|
|
||||||
}
|
}
|
||||||
NetMaxPos = 0;
|
NetMaxPos = 0;
|
||||||
NetCurPos = 0;
|
NetCurPos = 0;
|
||||||
|
@ -176,13 +161,8 @@ FBasicStartupScreen::FBasicStartupScreen(int max_progress, bool show_bar)
|
||||||
|
|
||||||
FBasicStartupScreen::~FBasicStartupScreen()
|
FBasicStartupScreen::~FBasicStartupScreen()
|
||||||
{
|
{
|
||||||
if (ProgressBar != NULL)
|
mainwindow.HideProgressBar();
|
||||||
{
|
KillTimer(mainwindow.GetHandle(), 1337);
|
||||||
DestroyWindow (ProgressBar);
|
|
||||||
ProgressBar = NULL;
|
|
||||||
LayoutMainWindow (Window, NULL);
|
|
||||||
}
|
|
||||||
KillTimer(Window, 1337);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -198,7 +178,7 @@ void FBasicStartupScreen::Progress()
|
||||||
if (CurPos < MaxPos)
|
if (CurPos < MaxPos)
|
||||||
{
|
{
|
||||||
CurPos++;
|
CurPos++;
|
||||||
SendMessage (ProgressBar, PBM_SETPOS, CurPos, 0);
|
mainwindow.SetProgressPos(CurPos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,61 +197,8 @@ void FBasicStartupScreen::Progress()
|
||||||
void FBasicStartupScreen::NetInit(const char *message, int numplayers)
|
void FBasicStartupScreen::NetInit(const char *message, int numplayers)
|
||||||
{
|
{
|
||||||
NetMaxPos = numplayers;
|
NetMaxPos = numplayers;
|
||||||
if (NetStartPane == NULL)
|
mainwindow.ShowNetStartPane(message, numplayers);
|
||||||
{
|
|
||||||
NetStartPane = CreateDialogParam (g_hInst, MAKEINTRESOURCE(IDD_NETSTARTPANE), Window, NetStartPaneProc, 0);
|
|
||||||
// We don't need two progress bars.
|
|
||||||
if (ProgressBar != NULL)
|
|
||||||
{
|
|
||||||
DestroyWindow (ProgressBar);
|
|
||||||
ProgressBar = NULL;
|
|
||||||
}
|
|
||||||
RECT winrect;
|
|
||||||
GetWindowRect (Window, &winrect);
|
|
||||||
SetWindowPos (Window, NULL, 0, 0,
|
|
||||||
winrect.right - winrect.left, winrect.bottom - winrect.top + LayoutNetStartPane (NetStartPane, 0),
|
|
||||||
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER);
|
|
||||||
LayoutMainWindow (Window, NULL);
|
|
||||||
SetFocus (NetStartPane);
|
|
||||||
}
|
|
||||||
if (NetStartPane != NULL)
|
|
||||||
{
|
|
||||||
HWND ctl;
|
|
||||||
|
|
||||||
std::wstring wmessage = WideString(message);
|
|
||||||
SetDlgItemTextW (NetStartPane, IDC_NETSTARTMESSAGE, wmessage.c_str());
|
|
||||||
ctl = GetDlgItem (NetStartPane, IDC_NETSTARTPROGRESS);
|
|
||||||
|
|
||||||
if (numplayers == 0)
|
|
||||||
{
|
|
||||||
// PBM_SETMARQUEE is only available under XP and above, so this might fail.
|
|
||||||
NetMarqueeMode = SendMessage (ctl, PBM_SETMARQUEE, TRUE, 100);
|
|
||||||
if (NetMarqueeMode == FALSE)
|
|
||||||
{
|
|
||||||
SendMessage (ctl, PBM_SETRANGE, 0, MAKELPARAM(0,16));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If we don't set the PBS_MARQUEE style, then the marquee will never show up.
|
|
||||||
SetWindowLong (ctl, GWL_STYLE, GetWindowLong (ctl, GWL_STYLE) | PBS_MARQUEE);
|
|
||||||
}
|
|
||||||
SetDlgItemTextW (NetStartPane, IDC_NETSTARTCOUNT, L"");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
NetMarqueeMode = FALSE;
|
|
||||||
SendMessage (ctl, PBM_SETMARQUEE, FALSE, 0);
|
|
||||||
// Make sure the marquee really is turned off.
|
|
||||||
SetWindowLong (ctl, GWL_STYLE, GetWindowLong (ctl, GWL_STYLE) & (~PBS_MARQUEE));
|
|
||||||
|
|
||||||
SendMessage (ctl, PBM_SETRANGE, 0, MAKELPARAM(0,numplayers));
|
|
||||||
if (numplayers == 1)
|
|
||||||
{
|
|
||||||
SendMessage (ctl, PBM_SETPOS, 1, 0);
|
|
||||||
SetDlgItemTextW (NetStartPane, IDC_NETSTARTCOUNT, L"");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NetMaxPos = numplayers;
|
NetMaxPos = numplayers;
|
||||||
NetCurPos = 0;
|
NetCurPos = 0;
|
||||||
NetProgress(1); // You always know about yourself
|
NetProgress(1); // You always know about yourself
|
||||||
|
@ -287,12 +214,7 @@ void FBasicStartupScreen::NetInit(const char *message, int numplayers)
|
||||||
|
|
||||||
void FBasicStartupScreen::NetDone()
|
void FBasicStartupScreen::NetDone()
|
||||||
{
|
{
|
||||||
if (NetStartPane != NULL)
|
mainwindow.HideNetStartPane();
|
||||||
{
|
|
||||||
DestroyWindow (NetStartPane);
|
|
||||||
NetStartPane = NULL;
|
|
||||||
LayoutMainWindow (Window, NULL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -325,7 +247,7 @@ void FBasicStartupScreen::NetMessage(const char *format, ...)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void FBasicStartupScreen :: NetProgress(int count)
|
void FBasicStartupScreen::NetProgress(int count)
|
||||||
{
|
{
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
{
|
{
|
||||||
|
@ -335,23 +257,8 @@ void FBasicStartupScreen :: NetProgress(int count)
|
||||||
{
|
{
|
||||||
NetCurPos = count;
|
NetCurPos = count;
|
||||||
}
|
}
|
||||||
if (NetStartPane == NULL)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (NetMaxPos == 0 && !NetMarqueeMode)
|
|
||||||
{
|
|
||||||
// PBM_SETMARQUEE didn't work, so just increment the progress bar endlessly.
|
|
||||||
SendDlgItemMessage (NetStartPane, IDC_NETSTARTPROGRESS, PBM_SETPOS, NetCurPos & 15, 0);
|
|
||||||
}
|
|
||||||
else if (NetMaxPos > 1)
|
|
||||||
{
|
|
||||||
char buf[16];
|
|
||||||
|
|
||||||
mysnprintf (buf, countof(buf), "%d/%d", NetCurPos, NetMaxPos);
|
mainwindow.SetNetStartProgress(count);
|
||||||
SetDlgItemTextA (NetStartPane, IDC_NETSTARTCOUNT, buf);
|
|
||||||
SendDlgItemMessage (NetStartPane, IDC_NETSTARTPROGRESS, PBM_SETPOS, min(NetCurPos, NetMaxPos), 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -370,59 +277,7 @@ void FBasicStartupScreen :: NetProgress(int count)
|
||||||
|
|
||||||
bool FBasicStartupScreen::NetLoop(bool (*timer_callback)(void *), void *userdata)
|
bool FBasicStartupScreen::NetLoop(bool (*timer_callback)(void *), void *userdata)
|
||||||
{
|
{
|
||||||
BOOL bRet;
|
return mainwindow.RunMessageLoop(timer_callback, userdata);
|
||||||
MSG msg;
|
|
||||||
|
|
||||||
if (SetTimer (Window, 1337, 500, NULL) == 0)
|
|
||||||
{
|
|
||||||
I_FatalError ("Could not set network synchronization timer.");
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0)
|
|
||||||
{
|
|
||||||
if (bRet == -1)
|
|
||||||
{
|
|
||||||
KillTimer (Window, 1337);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (msg.message == WM_TIMER && msg.hwnd == Window && msg.wParam == 1337)
|
|
||||||
{
|
|
||||||
if (timer_callback (userdata))
|
|
||||||
{
|
|
||||||
KillTimer (NetStartPane, 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!IsDialogMessage (NetStartPane, &msg))
|
|
||||||
{
|
|
||||||
TranslateMessage (&msg);
|
|
||||||
DispatchMessage (&msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
KillTimer (Window, 1337);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// NetStartPaneProc
|
|
||||||
//
|
|
||||||
// DialogProc for the network startup pane. It just waits for somebody to
|
|
||||||
// click a button, and the only button available is the abort one.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
static INT_PTR CALLBACK NetStartPaneProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
||||||
{
|
|
||||||
if (msg == WM_COMMAND && HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDCANCEL)
|
|
||||||
{
|
|
||||||
PostQuitMessage (0);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -437,6 +292,7 @@ static INT_PTR CALLBACK NetStartPaneProc (HWND hDlg, UINT msg, WPARAM wParam, LP
|
||||||
FGraphicalStartupScreen::FGraphicalStartupScreen(int max_progress)
|
FGraphicalStartupScreen::FGraphicalStartupScreen(int max_progress)
|
||||||
: FBasicStartupScreen(max_progress, false)
|
: FBasicStartupScreen(max_progress, false)
|
||||||
{
|
{
|
||||||
|
mainwindow.ShowStartupScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -447,11 +303,7 @@ FGraphicalStartupScreen::FGraphicalStartupScreen(int max_progress)
|
||||||
|
|
||||||
FGraphicalStartupScreen::~FGraphicalStartupScreen()
|
FGraphicalStartupScreen::~FGraphicalStartupScreen()
|
||||||
{
|
{
|
||||||
if (StartupScreen != NULL)
|
mainwindow.HideStartupScreen();
|
||||||
{
|
|
||||||
DestroyWindow (StartupScreen);
|
|
||||||
StartupScreen = NULL;
|
|
||||||
}
|
|
||||||
if (StartupBitmap != NULL)
|
if (StartupBitmap != NULL)
|
||||||
{
|
{
|
||||||
ST_Util_FreeBitmap (StartupBitmap);
|
ST_Util_FreeBitmap (StartupBitmap);
|
||||||
|
@ -468,8 +320,8 @@ FGraphicalStartupScreen::~FGraphicalStartupScreen()
|
||||||
void FHexenStartupScreen::SetWindowSize()
|
void FHexenStartupScreen::SetWindowSize()
|
||||||
{
|
{
|
||||||
ST_Util_SizeWindowForBitmap(1);
|
ST_Util_SizeWindowForBitmap(1);
|
||||||
LayoutMainWindow(Window, NULL);
|
mainwindow.UpdateLayout();
|
||||||
InvalidateRect(StartupScreen, NULL, TRUE);
|
mainwindow.InvalidateStartupScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -481,8 +333,8 @@ void FHexenStartupScreen::SetWindowSize()
|
||||||
void FHereticStartupScreen::SetWindowSize()
|
void FHereticStartupScreen::SetWindowSize()
|
||||||
{
|
{
|
||||||
ST_Util_SizeWindowForBitmap(1);
|
ST_Util_SizeWindowForBitmap(1);
|
||||||
LayoutMainWindow(Window, NULL);
|
mainwindow.UpdateLayout();
|
||||||
InvalidateRect(StartupScreen, NULL, TRUE);
|
mainwindow.InvalidateStartupScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -494,8 +346,8 @@ void FHereticStartupScreen::SetWindowSize()
|
||||||
void FStrifeStartupScreen::SetWindowSize()
|
void FStrifeStartupScreen::SetWindowSize()
|
||||||
{
|
{
|
||||||
ST_Util_SizeWindowForBitmap(2);
|
ST_Util_SizeWindowForBitmap(2);
|
||||||
LayoutMainWindow(Window, NULL);
|
mainwindow.UpdateLayout();
|
||||||
InvalidateRect(StartupScreen, NULL, TRUE);
|
mainwindow.InvalidateStartupScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -532,13 +384,10 @@ int RunEndoom()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ST_Util_CreateStartupWindow())
|
mainwindow.ShowStartupScreen();
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
I_ShutdownGraphics ();
|
I_ShutdownGraphics ();
|
||||||
RestoreConView ();
|
mainwindow.RestoreConView ();
|
||||||
S_StopMusic(true);
|
S_StopMusic(true);
|
||||||
|
|
||||||
fileSystem.ReadFile (endoom_lump, endoom_screen);
|
fileSystem.ReadFile (endoom_lump, endoom_screen);
|
||||||
|
@ -548,15 +397,11 @@ int RunEndoom()
|
||||||
ST_Util_DrawTextScreen (StartupBitmap, endoom_screen);
|
ST_Util_DrawTextScreen (StartupBitmap, endoom_screen);
|
||||||
|
|
||||||
// Make the title banner go away.
|
// Make the title banner go away.
|
||||||
if (GameTitleWindow != NULL)
|
mainwindow.HideGameTitleWindow();
|
||||||
{
|
|
||||||
DestroyWindow (GameTitleWindow);
|
|
||||||
GameTitleWindow = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ST_Util_SizeWindowForBitmap (1);
|
ST_Util_SizeWindowForBitmap (1);
|
||||||
LayoutMainWindow (Window, NULL);
|
mainwindow.UpdateLayout();
|
||||||
InvalidateRect (StartupScreen, NULL, TRUE);
|
mainwindow.InvalidateStartupScreen();
|
||||||
|
|
||||||
// Does this screen need blinking?
|
// Does this screen need blinking?
|
||||||
for (i = 0; i < 80*25; ++i)
|
for (i = 0; i < 80*25; ++i)
|
||||||
|
@ -567,7 +412,7 @@ int RunEndoom()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (blinking && SetTimer (Window, 0x5A15A, BLINK_PERIOD, NULL) == 0)
|
if (blinking && SetTimer (mainwindow.GetHandle(), 0x5A15A, BLINK_PERIOD, NULL) == 0)
|
||||||
{
|
{
|
||||||
blinking = false;
|
blinking = false;
|
||||||
}
|
}
|
||||||
|
@ -581,12 +426,12 @@ int RunEndoom()
|
||||||
{
|
{
|
||||||
if (blinking)
|
if (blinking)
|
||||||
{
|
{
|
||||||
KillTimer (Window, 0x5A15A);
|
KillTimer (mainwindow.GetHandle(), 0x5A15A);
|
||||||
}
|
}
|
||||||
ST_Util_FreeBitmap (StartupBitmap);
|
ST_Util_FreeBitmap (StartupBitmap);
|
||||||
return int(bRet == 0 ? mess.wParam : 0);
|
return int(bRet == 0 ? mess.wParam : 0);
|
||||||
}
|
}
|
||||||
else if (blinking && mess.message == WM_TIMER && mess.hwnd == Window && mess.wParam == 0x5A15A)
|
else if (blinking && mess.message == WM_TIMER && mess.hwnd == mainwindow.GetHandle() && mess.wParam == 0x5A15A)
|
||||||
{
|
{
|
||||||
ST_Util_UpdateTextBlink (StartupBitmap, endoom_screen, blinkstate);
|
ST_Util_UpdateTextBlink (StartupBitmap, endoom_screen, blinkstate);
|
||||||
blinkstate = !blinkstate;
|
blinkstate = !blinkstate;
|
||||||
|
@ -604,27 +449,6 @@ void ST_Endoom()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// ST_Util_CreateStartupWindow
|
|
||||||
//
|
|
||||||
// Creates the static control that will draw the startup screen.
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
bool ST_Util_CreateStartupWindow ()
|
|
||||||
{
|
|
||||||
StartupScreen = CreateWindowEx (WS_EX_NOPARENTNOTIFY, L"STATIC", NULL,
|
|
||||||
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SS_OWNERDRAW,
|
|
||||||
0, 0, 0, 0, Window, NULL, g_hInst, NULL);
|
|
||||||
if (StartupScreen == NULL)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
SetWindowLong (StartupScreen, GWL_ID, IDC_STATIC_STARTUP);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// ST_Util_SizeWindowForBitmap
|
// ST_Util_SizeWindowForBitmap
|
||||||
|
@ -640,16 +464,7 @@ void ST_Util_SizeWindowForBitmap (int scale)
|
||||||
int w, h, cx, cy, x, y;
|
int w, h, cx, cy, x, y;
|
||||||
RECT rect;
|
RECT rect;
|
||||||
|
|
||||||
if (GameTitleWindow != NULL)
|
RECT sizerect = { 0, 0, StartupBitmap->bmiHeader.biWidth * scale, StartupBitmap->bmiHeader.biHeight * scale + mainwindow.GetGameTitleWindowHeight() };
|
||||||
{
|
|
||||||
GetClientRect (GameTitleWindow, &rect);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rect.bottom = 0;
|
|
||||||
}
|
|
||||||
RECT sizerect = { 0, 0, StartupBitmap->bmiHeader.biWidth * scale,
|
|
||||||
StartupBitmap->bmiHeader.biHeight * scale + rect.bottom };
|
|
||||||
AdjustWindowRectEx(&sizerect, WS_VISIBLE|WS_OVERLAPPEDWINDOW, FALSE, WS_EX_APPWINDOW);
|
AdjustWindowRectEx(&sizerect, WS_VISIBLE|WS_OVERLAPPEDWINDOW, FALSE, WS_EX_APPWINDOW);
|
||||||
w = sizerect.right - sizerect.left;
|
w = sizerect.right - sizerect.left;
|
||||||
h = sizerect.bottom - sizerect.top;
|
h = sizerect.bottom - sizerect.top;
|
||||||
|
@ -659,7 +474,7 @@ void ST_Util_SizeWindowForBitmap (int scale)
|
||||||
memset (&displaysettings, 0, sizeof(displaysettings));
|
memset (&displaysettings, 0, sizeof(displaysettings));
|
||||||
displaysettings.dmSize = sizeof(displaysettings);
|
displaysettings.dmSize = sizeof(displaysettings);
|
||||||
EnumDisplaySettings (NULL, ENUM_CURRENT_SETTINGS, &displaysettings);
|
EnumDisplaySettings (NULL, ENUM_CURRENT_SETTINGS, &displaysettings);
|
||||||
GetWindowRect (Window, &rect);
|
GetWindowRect (mainwindow.GetHandle(), &rect);
|
||||||
cx = (rect.left + rect.right) / 2;
|
cx = (rect.left + rect.right) / 2;
|
||||||
cy = (rect.top + rect.bottom) / 2;
|
cy = (rect.top + rect.bottom) / 2;
|
||||||
x = cx - w / 2;
|
x = cx - w / 2;
|
||||||
|
@ -680,7 +495,7 @@ void ST_Util_SizeWindowForBitmap (int scale)
|
||||||
{
|
{
|
||||||
y = 0;
|
y = 0;
|
||||||
}
|
}
|
||||||
MoveWindow (Window, x, y, w, h, TRUE);
|
MoveWindow (mainwindow.GetHandle(), x, y, w, h, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -692,19 +507,7 @@ void ST_Util_SizeWindowForBitmap (int scale)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void ST_Util_InvalidateRect (HWND hwnd, BitmapInfo *bitmap_info, int left, int top, int right, int bottom)
|
|
||||||
{
|
|
||||||
RECT rect;
|
|
||||||
|
|
||||||
GetClientRect (hwnd, &rect);
|
|
||||||
rect.left = left * rect.right / bitmap_info->bmiHeader.biWidth - 1;
|
|
||||||
rect.top = top * rect.bottom / bitmap_info->bmiHeader.biHeight - 1;
|
|
||||||
rect.right = right * rect.right / bitmap_info->bmiHeader.biWidth + 1;
|
|
||||||
rect.bottom = bottom * rect.bottom / bitmap_info->bmiHeader.biHeight + 1;
|
|
||||||
InvalidateRect (hwnd, &rect, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ST_Util_InvalidateRect(BitmapInfo* bitmap_info, int left, int top, int right, int bottom)
|
void ST_Util_InvalidateRect(BitmapInfo* bitmap_info, int left, int top, int right, int bottom)
|
||||||
{
|
{
|
||||||
ST_Util_InvalidateRect(StartupScreen , bitmap_info, left, top, right, bottom);
|
mainwindow.InvalidateStartupScreen(left, top, right, bottom);
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,14 +43,12 @@
|
||||||
#include "startupinfo.h"
|
#include "startupinfo.h"
|
||||||
#include "palutil.h"
|
#include "palutil.h"
|
||||||
#include "i_interface.h"
|
#include "i_interface.h"
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
uint8_t* GetHexChar(int codepoint);
|
uint8_t* GetHexChar(int codepoint);
|
||||||
|
|
||||||
void I_GetEvent(); // i_input.h pulls in too much garbage.
|
void I_GetEvent(); // i_input.h pulls in too much garbage.
|
||||||
|
|
||||||
void ST_Util_InvalidateRect(BitmapInfo* bitmap_info, int left, int top, int right, int bottom);
|
|
||||||
bool ST_Util_CreateStartupWindow();
|
|
||||||
|
|
||||||
static const uint16_t IBM437ToUnicode[] = {
|
static const uint16_t IBM437ToUnicode[] = {
|
||||||
0x0000, //#NULL
|
0x0000, //#NULL
|
||||||
0x0001, //#START OF HEADING
|
0x0001, //#START OF HEADING
|
||||||
|
@ -420,7 +418,7 @@ FHexenStartupScreen::FHexenStartupScreen(int max_progress, long& hr)
|
||||||
int notch_lump = fileSystem.CheckNumForName("NOTCH");
|
int notch_lump = fileSystem.CheckNumForName("NOTCH");
|
||||||
hr = -1;
|
hr = -1;
|
||||||
|
|
||||||
if (startup_lump < 0 || fileSystem.FileLength(startup_lump) != 153648 || !ST_Util_CreateStartupWindow() ||
|
if (startup_lump < 0 || fileSystem.FileLength(startup_lump) != 153648 ||
|
||||||
netnotch_lump < 0 || fileSystem.FileLength(netnotch_lump) != ST_NETNOTCH_WIDTH / 2 * ST_NETNOTCH_HEIGHT ||
|
netnotch_lump < 0 || fileSystem.FileLength(netnotch_lump) != ST_NETNOTCH_WIDTH / 2 * ST_NETNOTCH_HEIGHT ||
|
||||||
notch_lump < 0 || fileSystem.FileLength(notch_lump) != ST_NOTCH_WIDTH / 2 * ST_NOTCH_HEIGHT)
|
notch_lump < 0 || fileSystem.FileLength(notch_lump) != ST_NOTCH_WIDTH / 2 * ST_NOTCH_HEIGHT)
|
||||||
{
|
{
|
||||||
|
@ -585,7 +583,7 @@ FHereticStartupScreen::FHereticStartupScreen(int max_progress, long& hr)
|
||||||
uint8_t loading_screen[4000];
|
uint8_t loading_screen[4000];
|
||||||
|
|
||||||
hr = -1;
|
hr = -1;
|
||||||
if (loading_lump < 0 || fileSystem.FileLength(loading_lump) != 4000 || !ST_Util_CreateStartupWindow())
|
if (loading_lump < 0 || fileSystem.FileLength(loading_lump) != 4000)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -657,7 +655,7 @@ void FHereticStartupScreen::LoadingStatus(const char* message, int colors)
|
||||||
{
|
{
|
||||||
ST_Util_DrawChar(StartupBitmap, 17 + x, HMsgY, message[x], colors);
|
ST_Util_DrawChar(StartupBitmap, 17 + x, HMsgY, message[x], colors);
|
||||||
}
|
}
|
||||||
ST_Util_InvalidateRect(StartupBitmap, 17 * 8, HMsgY * 16, (17 + x) * 8, HMsgY * 16 + 16);
|
mainwindow.InvalidateStartupScreen(17 * 8, HMsgY * 16, (17 + x) * 8, HMsgY * 16 + 16);
|
||||||
HMsgY++;
|
HMsgY++;
|
||||||
I_GetEvent();
|
I_GetEvent();
|
||||||
}
|
}
|
||||||
|
@ -678,7 +676,7 @@ void FHereticStartupScreen::AppendStatusLine(const char* status)
|
||||||
{
|
{
|
||||||
ST_Util_DrawChar(StartupBitmap, SMsgX + x, 24, status[x], 0x1f);
|
ST_Util_DrawChar(StartupBitmap, SMsgX + x, 24, status[x], 0x1f);
|
||||||
}
|
}
|
||||||
ST_Util_InvalidateRect(StartupBitmap, SMsgX * 8, 24 * 16, (SMsgX + x) * 8, 25 * 16);
|
mainwindow.InvalidateStartupScreen(SMsgX * 8, 24 * 16, (SMsgX + x) * 8, 25 * 16);
|
||||||
SMsgX += x;
|
SMsgX += x;
|
||||||
I_GetEvent();
|
I_GetEvent();
|
||||||
}
|
}
|
||||||
|
@ -711,7 +709,7 @@ FStrifeStartupScreen::FStrifeStartupScreen(int max_progress, long& hr)
|
||||||
StartupPics[i] = NULL;
|
StartupPics[i] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (startup_lump < 0 || fileSystem.FileLength(startup_lump) != 64000 || !ST_Util_CreateStartupWindow())
|
if (startup_lump < 0 || fileSystem.FileLength(startup_lump) != 64000)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -887,7 +885,7 @@ void ST_Util_DrawBlock(BitmapInfo* bitmap_info, const uint8_t* src, int x, int y
|
||||||
int destpitch = bitmap_info->bmiHeader.biWidth;
|
int destpitch = bitmap_info->bmiHeader.biWidth;
|
||||||
uint8_t* dest = ST_Util_BitsForBitmap(bitmap_info) + x + y * destpitch;
|
uint8_t* dest = ST_Util_BitsForBitmap(bitmap_info) + x + y * destpitch;
|
||||||
|
|
||||||
ST_Util_InvalidateRect(bitmap_info, x, y, x + bytewidth, y + height);
|
mainwindow.InvalidateStartupScreen(x, y, x + bytewidth, y + height);
|
||||||
|
|
||||||
if (bytewidth == 8)
|
if (bytewidth == 8)
|
||||||
{ // progress notches
|
{ // progress notches
|
||||||
|
@ -935,7 +933,7 @@ void ST_Util_DrawBlock4(BitmapInfo* bitmap_info, const uint8_t* src, int x, int
|
||||||
int destpitch = bitmap_info->bmiHeader.biWidth;
|
int destpitch = bitmap_info->bmiHeader.biWidth;
|
||||||
uint8_t* dest = ST_Util_BitsForBitmap(bitmap_info) + x + y * destpitch;
|
uint8_t* dest = ST_Util_BitsForBitmap(bitmap_info) + x + y * destpitch;
|
||||||
|
|
||||||
ST_Util_InvalidateRect(bitmap_info, x, y, x + bytewidth * 2, y + height);
|
mainwindow.InvalidateStartupScreen(x, y, x + bytewidth * 2, y + height);
|
||||||
|
|
||||||
for (; height > 0; --height)
|
for (; height > 0; --height)
|
||||||
{
|
{
|
||||||
|
@ -961,7 +959,7 @@ void ST_Util_ClearBlock(BitmapInfo* bitmap_info, uint8_t fill, int x, int y, int
|
||||||
int destpitch = bitmap_info->bmiHeader.biWidth;
|
int destpitch = bitmap_info->bmiHeader.biWidth;
|
||||||
uint8_t* dest = ST_Util_BitsForBitmap(bitmap_info) + x + y * destpitch;
|
uint8_t* dest = ST_Util_BitsForBitmap(bitmap_info) + x + y * destpitch;
|
||||||
|
|
||||||
ST_Util_InvalidateRect(bitmap_info, x, y, x + bytewidth, y + height);
|
mainwindow.InvalidateStartupScreen(x, y, x + bytewidth, y + height);
|
||||||
|
|
||||||
while (height > 0)
|
while (height > 0)
|
||||||
{
|
{
|
||||||
|
@ -1165,7 +1163,7 @@ void ST_Util_UpdateTextBlink(BitmapInfo* bitmap_info, const uint8_t* text_screen
|
||||||
if (text_screen[1] & 0x80)
|
if (text_screen[1] & 0x80)
|
||||||
{
|
{
|
||||||
ST_Util_DrawChar(bitmap_info, x, y, on ? IBM437ToUnicode[text_screen[0]] : ' ', text_screen[1]);
|
ST_Util_DrawChar(bitmap_info, x, y, on ? IBM437ToUnicode[text_screen[0]] : ' ', text_screen[1]);
|
||||||
ST_Util_InvalidateRect(bitmap_info, x * 8, y * 16, x * 8 + 8, y * 16 + 16);
|
mainwindow.InvalidateStartupScreen(x * 8, y * 16, x * 8 + 8, y * 16 + 16);
|
||||||
}
|
}
|
||||||
text_screen += 2;
|
text_screen += 2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
#include "win32basevideo.h"
|
#include "win32basevideo.h"
|
||||||
#include "cmdlib.h"
|
#include "cmdlib.h"
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
CVAR(Int, vid_adapter, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
CVAR(Int, vid_adapter, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
|
|
||||||
|
@ -58,7 +59,7 @@ CVAR(Int, vid_adapter, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
|
|
||||||
Win32BaseVideo::Win32BaseVideo()
|
Win32BaseVideo::Win32BaseVideo()
|
||||||
{
|
{
|
||||||
I_SetWndProc();
|
mainwindow.ShowGameView();
|
||||||
|
|
||||||
GetDisplayDeviceName();
|
GetDisplayDeviceName();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
#include "engineerrors.h"
|
#include "engineerrors.h"
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
#ifdef HAVE_SOFTPOLY
|
#ifdef HAVE_SOFTPOLY
|
||||||
|
|
||||||
|
@ -10,8 +11,6 @@ EXTERN_CVAR(Bool, vid_vsync)
|
||||||
|
|
||||||
bool ViewportLinearScale();
|
bool ViewportLinearScale();
|
||||||
|
|
||||||
extern HWND Window;
|
|
||||||
|
|
||||||
#include <d3d9.h>
|
#include <d3d9.h>
|
||||||
#pragma comment(lib, "d3d9.lib")
|
#pragma comment(lib, "d3d9.lib")
|
||||||
|
|
||||||
|
@ -41,7 +40,7 @@ void I_PolyPresentInit()
|
||||||
}
|
}
|
||||||
|
|
||||||
RECT rect = {};
|
RECT rect = {};
|
||||||
GetClientRect(Window, &rect);
|
GetClientRect(mainwindow.GetHandle(), &rect);
|
||||||
|
|
||||||
ClientWidth = rect.right;
|
ClientWidth = rect.right;
|
||||||
ClientHeight = rect.bottom;
|
ClientHeight = rect.bottom;
|
||||||
|
@ -52,10 +51,10 @@ void I_PolyPresentInit()
|
||||||
pp.BackBufferWidth = ClientWidth;
|
pp.BackBufferWidth = ClientWidth;
|
||||||
pp.BackBufferHeight = ClientHeight;
|
pp.BackBufferHeight = ClientHeight;
|
||||||
pp.BackBufferCount = 1;
|
pp.BackBufferCount = 1;
|
||||||
pp.hDeviceWindow = Window;
|
pp.hDeviceWindow = mainwindow.GetHandle();
|
||||||
pp.PresentationInterval = CurrentVSync ? D3DPRESENT_INTERVAL_DEFAULT : D3DPRESENT_INTERVAL_IMMEDIATE;
|
pp.PresentationInterval = CurrentVSync ? D3DPRESENT_INTERVAL_DEFAULT : D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||||
|
|
||||||
HRESULT result = d3d9->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, Window, D3DCREATE_HARDWARE_VERTEXPROCESSING, &pp, nullptr, &device);
|
HRESULT result = d3d9->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, mainwindow.GetHandle(), D3DCREATE_HARDWARE_VERTEXPROCESSING, &pp, nullptr, &device);
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
I_FatalError("IDirect3D9.CreateDevice failed");
|
I_FatalError("IDirect3D9.CreateDevice failed");
|
||||||
|
@ -67,7 +66,7 @@ uint8_t *I_PolyPresentLock(int w, int h, bool vsync, int &pitch)
|
||||||
HRESULT result;
|
HRESULT result;
|
||||||
|
|
||||||
RECT rect = {};
|
RECT rect = {};
|
||||||
GetClientRect(Window, &rect);
|
GetClientRect(mainwindow.GetHandle(), &rect);
|
||||||
if (rect.right != ClientWidth || rect.bottom != ClientHeight || CurrentVSync != vsync)
|
if (rect.right != ClientWidth || rect.bottom != ClientHeight || CurrentVSync != vsync)
|
||||||
{
|
{
|
||||||
if (surface)
|
if (surface)
|
||||||
|
@ -86,7 +85,7 @@ uint8_t *I_PolyPresentLock(int w, int h, bool vsync, int &pitch)
|
||||||
pp.BackBufferWidth = ClientWidth;
|
pp.BackBufferWidth = ClientWidth;
|
||||||
pp.BackBufferHeight = ClientHeight;
|
pp.BackBufferHeight = ClientHeight;
|
||||||
pp.BackBufferCount = 1;
|
pp.BackBufferCount = 1;
|
||||||
pp.hDeviceWindow = Window;
|
pp.hDeviceWindow = mainwindow.GetHandle();
|
||||||
pp.PresentationInterval = CurrentVSync ? D3DPRESENT_INTERVAL_DEFAULT : D3DPRESENT_INTERVAL_IMMEDIATE;
|
pp.PresentationInterval = CurrentVSync ? D3DPRESENT_INTERVAL_DEFAULT : D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||||
device->Reset(&pp);
|
device->Reset(&pp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,16 +7,14 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "volk/volk.h"
|
#include "volk/volk.h"
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
extern HWND Window;
|
|
||||||
|
|
||||||
void I_GetVulkanDrawableSize(int *width, int *height)
|
void I_GetVulkanDrawableSize(int *width, int *height)
|
||||||
{
|
{
|
||||||
assert(Window);
|
assert(Window);
|
||||||
|
|
||||||
RECT clientRect = { 0 };
|
RECT clientRect = { 0 };
|
||||||
GetClientRect(Window, &clientRect);
|
GetClientRect(mainwindow.GetHandle(), &clientRect);
|
||||||
|
|
||||||
if (width != nullptr)
|
if (width != nullptr)
|
||||||
{
|
{
|
||||||
|
@ -67,7 +65,7 @@ bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface)
|
||||||
windowCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
|
windowCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
|
||||||
windowCreateInfo.pNext = nullptr;
|
windowCreateInfo.pNext = nullptr;
|
||||||
windowCreateInfo.flags = 0;
|
windowCreateInfo.flags = 0;
|
||||||
windowCreateInfo.hwnd = Window;
|
windowCreateInfo.hwnd = mainwindow.GetHandle();
|
||||||
windowCreateInfo.hinstance = GetModuleHandle(nullptr);
|
windowCreateInfo.hinstance = GetModuleHandle(nullptr);
|
||||||
|
|
||||||
const VkResult result = vkCreateWin32SurfaceKHR(instance, &windowCreateInfo, nullptr, surface);
|
const VkResult result = vkCreateWin32SurfaceKHR(instance, &windowCreateInfo, nullptr, surface);
|
||||||
|
|
|
@ -32,10 +32,6 @@
|
||||||
#include "polyrenderer/drawers/poly_triangle.h"
|
#include "polyrenderer/drawers/poly_triangle.h"
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
void PeekThreadedErrorPane();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CVAR(Int, r_multithreaded, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
CVAR(Int, r_multithreaded, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
||||||
CVAR(Int, r_debug_draw, 0, 0);
|
CVAR(Int, r_debug_draw, 0, 0);
|
||||||
|
|
||||||
|
@ -101,12 +97,7 @@ void DrawerThreads::WaitForWorkers()
|
||||||
std::unique_lock<std::mutex> end_lock(queue->end_mutex);
|
std::unique_lock<std::mutex> end_lock(queue->end_mutex);
|
||||||
if (!queue->end_condition.wait_for(end_lock, 5s, [&]() { return queue->tasks_left == 0; }))
|
if (!queue->end_condition.wait_for(end_lock, 5s, [&]() { return queue->tasks_left == 0; }))
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
I_FatalError("Drawer threads did not finish within 5 seconds!");
|
||||||
PeekThreadedErrorPane();
|
|
||||||
#endif
|
|
||||||
// Invoke the crash reporter so that we can capture the call stack of whatever the hung worker thread is doing
|
|
||||||
int *threadCrashed = nullptr;
|
|
||||||
*threadCrashed = 0xdeadbeef;
|
|
||||||
}
|
}
|
||||||
end_lock.unlock();
|
end_lock.unlock();
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,8 @@ void D_ConfirmSendStats()
|
||||||
|
|
||||||
#else // !NO_SEND_STATS
|
#else // !NO_SEND_STATS
|
||||||
|
|
||||||
|
#include "i_mainwindow.h"
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
@ -340,8 +342,7 @@ void D_ConfirmSendStats()
|
||||||
UCVarValue enabled = { 0 };
|
UCVarValue enabled = { 0 };
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
extern HWND Window;
|
enabled.Int = MessageBoxA(mainwindow.GetHandle(), MESSAGE_TEXT, TITLE_TEXT, MB_ICONQUESTION | MB_YESNO) == IDYES;
|
||||||
enabled.Int = MessageBoxA(Window, MESSAGE_TEXT, TITLE_TEXT, MB_ICONQUESTION | MB_YESNO) == IDYES;
|
|
||||||
#elif defined __APPLE__
|
#elif defined __APPLE__
|
||||||
const CFStringRef messageString = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, MESSAGE_TEXT, kCFStringEncodingASCII, kCFAllocatorNull);
|
const CFStringRef messageString = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, MESSAGE_TEXT, kCFStringEncodingASCII, kCFAllocatorNull);
|
||||||
const CFStringRef titleString = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, TITLE_TEXT, kCFStringEncodingASCII, kCFAllocatorNull);
|
const CFStringRef titleString = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, TITLE_TEXT, kCFStringEncodingASCII, kCFAllocatorNull);
|
||||||
|
|
|
@ -59,10 +59,6 @@
|
||||||
#include "swrenderer/things/r_playersprite.h"
|
#include "swrenderer/things/r_playersprite.h"
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
void PeekThreadedErrorPane();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
EXTERN_CVAR(Int, r_clearbuffer)
|
EXTERN_CVAR(Int, r_clearbuffer)
|
||||||
EXTERN_CVAR(Int, r_debug_draw)
|
EXTERN_CVAR(Int, r_debug_draw)
|
||||||
|
|
||||||
|
@ -239,12 +235,7 @@ namespace swrenderer
|
||||||
finished_threads++;
|
finished_threads++;
|
||||||
if (!end_condition.wait_for(end_lock, 5s, [&]() { return finished_threads == Threads.size(); }))
|
if (!end_condition.wait_for(end_lock, 5s, [&]() { return finished_threads == Threads.size(); }))
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
I_FatalError("Render threads did not finish within 5 seconds!");
|
||||||
PeekThreadedErrorPane();
|
|
||||||
#endif
|
|
||||||
// Invoke the crash reporter so that we can capture the call stack of whatever the hung worker thread is doing
|
|
||||||
int *threadCrashed = nullptr;
|
|
||||||
*threadCrashed = 0xdeadbeef;
|
|
||||||
}
|
}
|
||||||
finished_threads = 0;
|
finished_threads = 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue