mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-26 22:11:43 +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_xinput.cpp
|
||||
common/platform/win32/i_main.cpp
|
||||
common/platform/win32/i_mainwindow.cpp
|
||||
common/platform/win32/i_system.cpp
|
||||
common/platform/win32/i_specialpaths.cpp
|
||||
common/platform/win32/st_start.cpp
|
||||
|
|
|
@ -77,7 +77,6 @@ public:
|
|||
void NetDone();
|
||||
bool NetLoop(bool (*timer_callback)(void*), void* userdata);
|
||||
protected:
|
||||
long long NetMarqueeMode;
|
||||
int NetMaxPos, NetCurPos;
|
||||
};
|
||||
|
||||
|
|
|
@ -50,9 +50,7 @@
|
|||
#include "base_sysfb.h"
|
||||
#include "win32basevideo.h"
|
||||
#include "c_dispatch.h"
|
||||
|
||||
|
||||
extern HWND Window;
|
||||
#include "i_mainwindow.h"
|
||||
|
||||
extern "C" {
|
||||
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
|
||||
|
@ -85,7 +83,7 @@ EXTERN_CVAR(Int, vid_defheight)
|
|||
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &displaysettings);
|
||||
scrwidth = (int)displaysettings.dmPelsWidth;
|
||||
scrheight = (int)displaysettings.dmPelsHeight;
|
||||
GetWindowRect(Window, &rect);
|
||||
GetWindowRect(mainwindow.GetHandle(), &rect);
|
||||
cx = scrwidth / 2;
|
||||
cy = scrheight / 2;
|
||||
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.
|
||||
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;
|
||||
|
||||
if (GetWindowRect(Window, &wrect))
|
||||
if (GetWindowRect(mainwindow.GetHandle(), &wrect))
|
||||
{
|
||||
// If (win_x,win_y) specify to center the window, don't change them
|
||||
// if the window is still centered.
|
||||
|
@ -171,7 +169,7 @@ void SystemBaseFrameBuffer::SaveWindowedPos()
|
|||
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);
|
||||
}
|
||||
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"))
|
||||
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 exStyle = WS_EX_WINDOWEDGE;
|
||||
SetWindowLong(Window, GWL_STYLE, style);
|
||||
SetWindowLong(Window, GWL_EXSTYLE, exStyle);
|
||||
SetWindowLong(mainwindow.GetHandle(), GWL_STYLE, style);
|
||||
SetWindowLong(mainwindow.GetHandle(), GWL_EXSTYLE, exStyle);
|
||||
|
||||
int winx, winy, winw, winh, scrwidth, scrheight;
|
||||
|
||||
|
@ -250,8 +248,8 @@ void SystemBaseFrameBuffer::SetWindowSize(int w, int h)
|
|||
|
||||
if (!vid_fullscreen)
|
||||
{
|
||||
ShowWindow(Window, SW_SHOWNORMAL);
|
||||
SetWindowPos(Window, nullptr, winx, winy, winw, winh, SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||
ShowWindow(mainwindow.GetHandle(), SW_SHOWNORMAL);
|
||||
SetWindowPos(mainwindow.GetHandle(), nullptr, winx, winy, winw, winh, SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||
win_maximized = false;
|
||||
SetSize(GetClientWidth(), GetClientHeight());
|
||||
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;
|
||||
exStyle = 0;
|
||||
|
||||
|
@ -316,13 +314,13 @@ void SystemBaseFrameBuffer::PositionWindow(bool fullscreen, bool initialcall)
|
|||
exStyle |= WS_EX_WINDOWEDGE;
|
||||
}
|
||||
|
||||
SetWindowLong(Window, GWL_STYLE, style);
|
||||
SetWindowLong(Window, GWL_EXSTYLE, exStyle);
|
||||
SetWindowLong(mainwindow.GetHandle(), GWL_STYLE, style);
|
||||
SetWindowLong(mainwindow.GetHandle(), GWL_EXSTYLE, exStyle);
|
||||
|
||||
if (fullscreen)
|
||||
{
|
||||
SetWindowPos(Window, 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);
|
||||
SetWindowPos(mainwindow.GetHandle(), 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||
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.
|
||||
}
|
||||
|
@ -352,9 +350,9 @@ SystemBaseFrameBuffer::SystemBaseFrameBuffer(void *hMonitor, bool fullscreen) :
|
|||
m_displayDeviceName = 0;
|
||||
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();
|
||||
|
||||
ShowWindow (Window, SW_SHOW);
|
||||
SetWindowLong(Window, GWL_STYLE, WS_VISIBLE | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW);
|
||||
SetWindowLong(Window, GWL_EXSTYLE, WS_EX_WINDOWEDGE);
|
||||
SetWindowPos(Window, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||
ShowWindow (mainwindow.GetHandle(), SW_SHOW);
|
||||
SetWindowLong(mainwindow.GetHandle(), GWL_STYLE, WS_VISIBLE | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW);
|
||||
SetWindowLong(mainwindow.GetHandle(), GWL_EXSTYLE, WS_EX_WINDOWEDGE);
|
||||
SetWindowPos(mainwindow.GetHandle(), 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||
|
||||
static_cast<Win32BaseVideo *>(Video)->Shutdown();
|
||||
}
|
||||
|
@ -407,13 +405,13 @@ void SystemBaseFrameBuffer::ToggleFullscreen(bool yes)
|
|||
int SystemBaseFrameBuffer::GetClientWidth()
|
||||
{
|
||||
RECT rect = { 0 };
|
||||
GetClientRect(Window, &rect);
|
||||
GetClientRect(mainwindow.GetHandle(), &rect);
|
||||
return rect.right - rect.left;
|
||||
}
|
||||
|
||||
int SystemBaseFrameBuffer::GetClientHeight()
|
||||
{
|
||||
RECT rect = { 0 };
|
||||
GetClientRect(Window, &rect);
|
||||
GetClientRect(mainwindow.GetHandle(), &rect);
|
||||
return rect.bottom - rect.top;
|
||||
}
|
||||
|
|
|
@ -49,8 +49,7 @@
|
|||
#include "m_argv.h"
|
||||
#include "engineerrors.h"
|
||||
#include "win32glvideo.h"
|
||||
|
||||
extern HWND Window;
|
||||
#include "i_mainwindow.h"
|
||||
|
||||
extern "C" PROC zd_wglGetProcAddress(LPCSTR name);
|
||||
|
||||
|
@ -71,13 +70,13 @@ PFNWGLSWAPINTERVALEXTPROC myWglSwapIntervalExtProc;
|
|||
|
||||
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");
|
||||
return;
|
||||
}
|
||||
|
||||
HDC hDC = GetDC(Window);
|
||||
HDC hDC = GetDC(mainwindow.GetHandle());
|
||||
const char *wglext = nullptr;
|
||||
|
||||
myWglSwapIntervalExtProc = (PFNWGLSWAPINTERVALEXTPROC)zd_wglGetProcAddress("wglSwapIntervalEXT");
|
||||
|
@ -102,7 +101,7 @@ SystemGLFrameBuffer::SystemGLFrameBuffer(void *hMonitor, bool fullscreen) : Syst
|
|||
SwapInterval = -1;
|
||||
}
|
||||
}
|
||||
ReleaseDC(Window, hDC);
|
||||
ReleaseDC(mainwindow.GetHandle(), hDC);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -52,11 +52,10 @@
|
|||
#endif
|
||||
#include "engineerrors.h"
|
||||
#include "i_system.h"
|
||||
#include "i_mainwindow.h"
|
||||
|
||||
EXTERN_CVAR(Int, vid_preferbackend)
|
||||
|
||||
extern HWND Window;
|
||||
|
||||
IVideo *Video;
|
||||
|
||||
// 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.
|
||||
// (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
|
||||
// already foregrounded but may not be focused.)
|
||||
SetForegroundWindow(Window);
|
||||
SetFocus(Window);
|
||||
SetForegroundWindow(mainwindow.GetHandle());
|
||||
SetFocus(mainwindow.GetHandle());
|
||||
// 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
|
||||
// still receives a WM_ACTIVATEAPP message telling it that it's the
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
#include "zstring.h"
|
||||
#include "printf.h"
|
||||
#include "cmdlib.h"
|
||||
#include "i_mainwindow.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <zlib.h>
|
||||
|
@ -212,9 +213,6 @@ struct MiniDumpThreadData
|
|||
|
||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
|
||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||
void I_FlushBufferedConsoleStuff();
|
||||
|
||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||
|
||||
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;
|
||||
|
||||
file = CreateTempFile();
|
||||
if (file != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
EDITSTREAM streamer = { (DWORD_PTR)file, 0, WriteLogFileStreamer };
|
||||
SendMessage(edit, EM_STREAMOUT, SF_RTF, (LPARAM)&streamer);
|
||||
auto writeFile = [&](const void* data, uint32_t size, uint32_t& written) -> bool
|
||||
{
|
||||
DWORD tmp = 0;
|
||||
BOOL result = WriteFile(file, data, size, &tmp, nullptr);
|
||||
written = tmp;
|
||||
return result == TRUE;
|
||||
};
|
||||
mainwindow.GetLog(writeFile);
|
||||
}
|
||||
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.
|
||||
if (NumFiles != 0)
|
||||
|
@ -560,11 +529,7 @@ void CreateCrashLog (const char *custominfo, DWORD customsize, HWND richlog)
|
|||
AddFile (file, "local.txt");
|
||||
}
|
||||
}
|
||||
if (richlog != NULL)
|
||||
{
|
||||
I_FlushBufferedConsoleStuff();
|
||||
AddFile (WriteLogFile(richlog), "log.rtf");
|
||||
}
|
||||
AddFile (WriteLogFile(), "log.rtf");
|
||||
CloseHandle (DbgProcess);
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,8 @@
|
|||
#include "keydef.h"
|
||||
#include "printf.h"
|
||||
|
||||
#include "i_mainwindow.h"
|
||||
|
||||
#define SAFE_RELEASE(x) { if (x != NULL) { x->Release(); x = NULL; } }
|
||||
|
||||
// WBEMIDL BITS -- because w32api doesn't have this, either -----------------
|
||||
|
@ -266,7 +268,6 @@ protected:
|
|||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||
|
||||
extern LPDIRECTINPUT8 g_pdi;
|
||||
extern HWND Window;
|
||||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
|
||||
|
@ -372,7 +373,7 @@ bool FDInputJoystick::GetDevice()
|
|||
Printf(TEXTCOLOR_ORANGE "Setting data format for %s failed.\n", Name.GetChars());
|
||||
return false;
|
||||
}
|
||||
hr = Device->SetCooperativeLevel(Window, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
|
||||
hr = Device->SetCooperativeLevel(mainwindow.GetHandle(), DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Printf(TEXTCOLOR_ORANGE "Setting cooperative level for %s failed.\n", Name.GetChars());
|
||||
|
|
|
@ -86,6 +86,7 @@
|
|||
#include "printf.h"
|
||||
#include "c_buttons.h"
|
||||
#include "cmdlib.h"
|
||||
#include "i_mainwindow.h"
|
||||
|
||||
// Compensate for w32api's lack
|
||||
#ifndef GET_XBUTTON_WPARAM
|
||||
|
@ -116,7 +117,6 @@ extern bool ToggleFullscreen;
|
|||
bool VidResizing;
|
||||
|
||||
extern BOOL vidactive;
|
||||
extern HWND Window, ConWindow;
|
||||
|
||||
EXTERN_CVAR (String, language)
|
||||
EXTERN_CVAR (Bool, lookstrafe)
|
||||
|
@ -160,7 +160,7 @@ static void I_CheckGUICapture ()
|
|||
|
||||
void I_SetMouseCapture()
|
||||
{
|
||||
SetCapture(Window);
|
||||
SetCapture(mainwindow.GetHandle());
|
||||
}
|
||||
|
||||
void I_ReleaseMouseCapture()
|
||||
|
@ -444,7 +444,7 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||
break;
|
||||
|
||||
case WM_SIZE:
|
||||
InvalidateRect (Window, NULL, FALSE);
|
||||
InvalidateRect (hWnd, NULL, FALSE);
|
||||
break;
|
||||
|
||||
case WM_KEYDOWN:
|
||||
|
@ -820,7 +820,7 @@ IJoystickConfig *I_UpdateDeviceList()
|
|||
|
||||
void I_PutInClipboard (const char *str)
|
||||
{
|
||||
if (str == NULL || !OpenClipboard (Window))
|
||||
if (str == NULL || !OpenClipboard (mainwindow.GetHandle()))
|
||||
return;
|
||||
EmptyClipboard ();
|
||||
|
||||
|
@ -842,7 +842,7 @@ FString I_GetFromClipboard (bool return_nothing)
|
|||
HGLOBAL cliphandle;
|
||||
wchar_t *clipstr;
|
||||
|
||||
if (return_nothing || !IsClipboardFormatAvailable (CF_UNICODETEXT) || !OpenClipboard (Window))
|
||||
if (return_nothing || !IsClipboardFormatAvailable (CF_UNICODETEXT) || !OpenClipboard (mainwindow.GetHandle()))
|
||||
return retstr;
|
||||
|
||||
cliphandle = GetClipboardData (CF_UNICODETEXT);
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
|
||||
#include "i_input.h"
|
||||
#include "d_eventbase.h"
|
||||
#include "i_mainwindow.h"
|
||||
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
@ -87,7 +88,6 @@ protected:
|
|||
|
||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||
|
||||
extern HWND Window;
|
||||
extern LPDIRECTINPUT8 g_pdi;
|
||||
extern LPDIRECTINPUT g_pdi3;
|
||||
extern bool GUICapture;
|
||||
|
@ -347,7 +347,7 @@ ufailit:
|
|||
return false;
|
||||
}
|
||||
|
||||
hr = Device->SetCooperativeLevel(Window, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
|
||||
hr = Device->SetCooperativeLevel(mainwindow.GetHandle(), DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto ufailit;
|
||||
|
@ -379,7 +379,7 @@ void FDInputKeyboard::ProcessInput()
|
|||
DIDEVICEOBJECTDATA od;
|
||||
DWORD dwElements;
|
||||
HRESULT hr;
|
||||
bool foreground = (GetForegroundWindow() == Window);
|
||||
bool foreground = (GetForegroundWindow() == mainwindow.GetHandle());
|
||||
|
||||
for (;;)
|
||||
{
|
||||
|
@ -448,7 +448,7 @@ bool FRawKeyboard::GetDevice()
|
|||
rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE;
|
||||
rid.usUsage = HID_GDP_KEYBOARD;
|
||||
rid.dwFlags = RIDEV_INPUTSINK;
|
||||
rid.hwndTarget = Window;
|
||||
rid.hwndTarget = mainwindow.GetHandle();
|
||||
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
||||
{
|
||||
return false;
|
||||
|
|
|
@ -80,6 +80,8 @@
|
|||
#include "startupinfo.h"
|
||||
#include "printf.h"
|
||||
|
||||
#include "i_mainwindow.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
// The main window's title.
|
||||
|
@ -94,9 +96,8 @@
|
|||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
|
||||
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 I_FlushBufferedConsoleStuff();
|
||||
void DestroyCustomCursor();
|
||||
int GameMain();
|
||||
|
||||
|
@ -120,19 +121,6 @@ HANDLE MainThread;
|
|||
DWORD MainThreadID;
|
||||
HANDLE StdOut;
|
||||
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 Shell32Module{"Shell32"};
|
||||
|
@ -140,7 +128,6 @@ FModule User32Module{"User32"};
|
|||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
||||
static const WCHAR WinClassName[] = WGAMENAME "MainWindow";
|
||||
static HMODULE hwtsapi32; // handle to wtsapi32.dll
|
||||
|
||||
// CODE --------------------------------------------------------------------
|
||||
|
@ -174,155 +161,13 @@ static void UnWTS (void)
|
|||
ursn unreg = (ursn)GetProcAddress (hwtsapi32, "WTSUnRegisterSessionNotification");
|
||||
if (unreg != 0)
|
||||
{
|
||||
unreg (Window);
|
||||
unreg (mainwindow.GetHandle());
|
||||
}
|
||||
FreeLibrary (hwtsapi32);
|
||||
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
|
||||
|
@ -332,431 +177,7 @@ void LayoutMainWindow (HWND hWnd, HWND pane)
|
|||
void I_SetIWADInfo()
|
||||
{
|
||||
// Make the startup banner show itself
|
||||
LayoutMainWindow(Window, NULL);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// 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);
|
||||
mainwindow.UpdateLayout();
|
||||
}
|
||||
|
||||
static void UnTbp()
|
||||
|
@ -904,44 +325,9 @@ int DoMain (HINSTANCE hInstance)
|
|||
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 */
|
||||
FStringf caption("" GAMENAME " %s " X64 " (%s)", GetVersionString(), GetGitTime());
|
||||
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);
|
||||
}
|
||||
mainwindow.Create(caption, x, y, width, height);
|
||||
|
||||
if (kernel != NULL)
|
||||
{
|
||||
|
@ -957,7 +343,7 @@ int DoMain (HINSTANCE hInstance)
|
|||
if (hwtsapi32 != 0)
|
||||
{
|
||||
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);
|
||||
hwtsapi32 = 0;
|
||||
|
@ -970,7 +356,7 @@ int DoMain (HINSTANCE hInstance)
|
|||
}
|
||||
}
|
||||
|
||||
GetClientRect (Window, &cRect);
|
||||
GetClientRect (mainwindow.GetHandle(), &cRect);
|
||||
|
||||
WinWidth = cRect.right;
|
||||
WinHeight = cRect.bottom;
|
||||
|
@ -979,7 +365,7 @@ int DoMain (HINSTANCE hInstance)
|
|||
atexit (UnCOM);
|
||||
|
||||
int ret = GameMain ();
|
||||
CheckForRestart();
|
||||
mainwindow.CheckForRestart();
|
||||
|
||||
DestroyCustomCursor();
|
||||
if (ret == 1337) // special exit code for 'norun'.
|
||||
|
@ -991,7 +377,7 @@ int DoMain (HINSTANCE hInstance)
|
|||
DWORD bytes;
|
||||
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);
|
||||
FlushConsoleInputBuffer(stdinput);
|
||||
SetConsoleMode(stdinput, 0);
|
||||
|
@ -999,7 +385,7 @@ int DoMain (HINSTANCE hInstance)
|
|||
}
|
||||
else if (StdOut == NULL)
|
||||
{
|
||||
ShowErrorPane(NULL);
|
||||
mainwindow.ShowErrorPane(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1009,9 +395,8 @@ int DoMain (HINSTANCE hInstance)
|
|||
void I_ShowFatalError(const char *msg)
|
||||
{
|
||||
I_ShutdownGraphics ();
|
||||
RestoreConView ();
|
||||
mainwindow.RestoreConView();
|
||||
S_StopMusic(true);
|
||||
I_FlushBufferedConsoleStuff();
|
||||
|
||||
if (CVMAbortException::stacktrace.IsNotEmpty())
|
||||
{
|
||||
|
@ -1020,7 +405,7 @@ void I_ShowFatalError(const char *msg)
|
|||
|
||||
if (!batchrun)
|
||||
{
|
||||
ShowErrorPane(msg);
|
||||
mainwindow.ShowErrorPane(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1087,7 +472,7 @@ void CALLBACK ExitFatally (ULONG_PTR dummy)
|
|||
{
|
||||
SetUnhandledExceptionFilter (ExitMessedUp);
|
||||
I_ShutdownGraphics ();
|
||||
RestoreConView ();
|
||||
mainwindow.RestoreConView ();
|
||||
DisplayCrashLog ();
|
||||
exit(-1);
|
||||
}
|
||||
|
@ -1122,7 +507,7 @@ LONG WINAPI CatchAllExceptions (LPEXCEPTION_POINTERS info)
|
|||
|
||||
CrashPointers = *info;
|
||||
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.
|
||||
// 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;
|
||||
}
|
||||
__except(CrashPointers = *GetExceptionInformation(),
|
||||
CreateCrashLog ("TestCrash", 9, NULL), EXCEPTION_EXECUTE_HANDLER)
|
||||
CreateCrashLog ("TestCrash", 9), EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
}
|
||||
DisplayCrashLog ();
|
||||
|
@ -1221,7 +606,7 @@ int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE nothing, LPWSTR cmdline, int
|
|||
infiniterecursion(1);
|
||||
}
|
||||
__except(CrashPointers = *GetExceptionInformation(),
|
||||
CreateCrashLog ("TestStackCrash", 14, NULL), EXCEPTION_EXECUTE_HANDLER)
|
||||
CreateCrashLog ("TestStackCrash", 14), EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
}
|
||||
DisplayCrashLog ();
|
||||
|
@ -1287,5 +672,5 @@ void I_SetWindowTitle(const char* 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 "keydef.h"
|
||||
#include "i_interface.h"
|
||||
#include "i_mainwindow.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
@ -138,7 +139,6 @@ static void CenterMouse(int x, int y, LONG *centx, LONG *centy);
|
|||
|
||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||
|
||||
extern HWND Window;
|
||||
extern LPDIRECTINPUT8 g_pdi;
|
||||
extern LPDIRECTINPUT g_pdi3;
|
||||
extern bool GUICapture;
|
||||
|
@ -193,11 +193,11 @@ CUSTOM_CVAR (Int, in_mouse, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL)
|
|||
static void SetCursorState(bool visible)
|
||||
{
|
||||
CursorState = visible || !m_hidepointer;
|
||||
if (GetForegroundWindow() == Window)
|
||||
if (GetForegroundWindow() == mainwindow.GetHandle())
|
||||
{
|
||||
if (CursorState)
|
||||
{
|
||||
SetCursor((HCURSOR)(intptr_t)GetClassLongPtr(Window, GCLP_HCURSOR));
|
||||
SetCursor((HCURSOR)(intptr_t)GetClassLongPtr(mainwindow.GetHandle(), GCLP_HCURSOR));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -219,7 +219,7 @@ static void CenterMouse(int curx, int cury, LONG *centxp, LONG *centyp)
|
|||
{
|
||||
RECT rect;
|
||||
|
||||
GetWindowRect(Window, &rect);
|
||||
GetWindowRect(mainwindow.GetHandle(), &rect);
|
||||
|
||||
int centx = (rect.left + rect.right) >> 1;
|
||||
int centy = (rect.top + rect.bottom) >> 1;
|
||||
|
@ -258,7 +258,7 @@ void I_CheckNativeMouse(bool preferNative, bool eventhandlerresult)
|
|||
}
|
||||
else
|
||||
{
|
||||
if ((GetForegroundWindow() != Window) || preferNative || !use_mouse)
|
||||
if ((GetForegroundWindow() != mainwindow.GetHandle()) || preferNative || !use_mouse)
|
||||
{
|
||||
want_native = true;
|
||||
}
|
||||
|
@ -490,7 +490,7 @@ bool FRawMouse::GetDevice()
|
|||
rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE;
|
||||
rid.usUsage = HID_GDP_MOUSE;
|
||||
rid.dwFlags = 0;
|
||||
rid.hwndTarget = Window;
|
||||
rid.hwndTarget = mainwindow.GetHandle();
|
||||
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
||||
{
|
||||
return false;
|
||||
|
@ -516,7 +516,7 @@ void FRawMouse::Grab()
|
|||
rid.usUsagePage = HID_GENERIC_DESKTOP_PAGE;
|
||||
rid.usUsage = HID_GDP_MOUSE;
|
||||
rid.dwFlags = RIDEV_CAPTUREMOUSE | RIDEV_NOLEGACY;
|
||||
rid.hwndTarget = Window;
|
||||
rid.hwndTarget = mainwindow.GetHandle();
|
||||
if (RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
||||
{
|
||||
GetCursorPos(&UngrabbedPointerPos);
|
||||
|
@ -718,7 +718,7 @@ ufailit:
|
|||
return false;
|
||||
}
|
||||
|
||||
hr = Device->SetCooperativeLevel(Window, DISCL_EXCLUSIVE | DISCL_FOREGROUND);
|
||||
hr = Device->SetCooperativeLevel(mainwindow.GetHandle(), DISCL_EXCLUSIVE | DISCL_FOREGROUND);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
goto ufailit;
|
||||
|
@ -1066,11 +1066,11 @@ void FWin32Mouse::Grab()
|
|||
|
||||
GetCursorPos(&UngrabbedPointerPos);
|
||||
ClipCursor(NULL); // helps with Win95?
|
||||
GetClientRect(Window, &rect);
|
||||
GetClientRect(mainwindow.GetHandle(), &rect);
|
||||
|
||||
// Reposition the rect so that it only covers the client area.
|
||||
ClientToScreen(Window, (LPPOINT)&rect.left);
|
||||
ClientToScreen(Window, (LPPOINT)&rect.right);
|
||||
ClientToScreen(mainwindow.GetHandle(), (LPPOINT)&rect.left);
|
||||
ClientToScreen(mainwindow.GetHandle(), (LPPOINT)&rect.right);
|
||||
|
||||
ClipCursor(&rect);
|
||||
SetCursorState(false);
|
||||
|
|
|
@ -44,6 +44,8 @@
|
|||
#include "cmdlib.h"
|
||||
#include "keydef.h"
|
||||
|
||||
#include "i_mainwindow.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
#define DEFAULT_DEADZONE 0.25f
|
||||
|
@ -214,8 +216,6 @@ struct PS2Descriptor
|
|||
|
||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||
|
||||
extern HWND Window;
|
||||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
|
||||
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.usUsage = HID_GDP_JOYSTICK;
|
||||
rid.dwFlags = RIDEV_INPUTSINK;
|
||||
rid.hwndTarget = Window;
|
||||
rid.hwndTarget = mainwindow.GetHandle();
|
||||
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
||||
{
|
||||
return false;
|
||||
|
@ -1273,7 +1273,7 @@ void FRawPS2Manager::DoRegister()
|
|||
if (!Registered)
|
||||
{
|
||||
rid.dwFlags = RIDEV_INPUTSINK;
|
||||
rid.hwndTarget = Window;
|
||||
rid.hwndTarget = mainwindow.GetHandle();
|
||||
if (RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
||||
{
|
||||
Registered = true;
|
||||
|
|
|
@ -81,6 +81,7 @@
|
|||
#include "bitmap.h"
|
||||
#include "cmdlib.h"
|
||||
#include "i_interface.h"
|
||||
#include "i_mainwindow.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
@ -92,10 +93,6 @@
|
|||
|
||||
// TYPES -------------------------------------------------------------------
|
||||
|
||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
|
||||
extern void LayoutMainWindow(HWND hWnd, HWND pane);
|
||||
|
||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||
|
||||
void DestroyCustomCursor();
|
||||
|
@ -116,13 +113,11 @@ EXTERN_CVAR (Bool, autoloadbrightmaps)
|
|||
EXTERN_CVAR (Bool, autoloadwidescreen)
|
||||
EXTERN_CVAR (Int, vid_preferbackend)
|
||||
|
||||
extern HWND Window, ConWindow, GameTitleWindow;
|
||||
extern HANDLE StdOut;
|
||||
extern bool FancyStdOut;
|
||||
extern HINSTANCE g_hInst;
|
||||
extern FILE *Logfile;
|
||||
extern bool NativeMouse;
|
||||
extern bool ConWindowHidden;
|
||||
|
||||
// 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;
|
||||
|
||||
wchar_t wbuf[256];
|
||||
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;
|
||||
|
||||
auto outputIt = [&]()
|
||||
{
|
||||
wbuf[bpos] = 0;
|
||||
if (edit != nullptr)
|
||||
{
|
||||
SendMessageW(edit, EM_REPLACESEL, FALSE, (LPARAM)wbuf);
|
||||
}
|
||||
if (con_debugoutput)
|
||||
{
|
||||
OutputDebugStringW(wbuf);
|
||||
|
@ -385,17 +357,6 @@ static void DoPrintStr(const char *cpt, HWND edit, HANDLE StdOut)
|
|||
}
|
||||
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();
|
||||
}
|
||||
|
||||
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)
|
||||
{ // Set text back to gray, in case it was changed.
|
||||
SetConsoleTextAttribute(StdOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||
}
|
||||
}
|
||||
|
||||
static TArray<FString> bufferedConsoleStuff;
|
||||
|
||||
void I_PrintStr(const char *cp)
|
||||
{
|
||||
if (ConWindowHidden)
|
||||
{
|
||||
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();
|
||||
mainwindow.PrintStr(cp);
|
||||
PrintToStdOut(cp, StdOut);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -635,7 +560,7 @@ int I_PickIWad(WadStuff *wads, int numwads, bool showwin, int defaultiwad)
|
|||
DefaultWad = defaultiwad;
|
||||
|
||||
return (int)DialogBox(g_hInst, MAKEINTRESOURCE(IDD_IWADDIALOG),
|
||||
(HWND)Window, (DLGPROC)IWADBoxCallback);
|
||||
(HWND)mainwindow.GetHandle(), (DLGPROC)IWADBoxCallback);
|
||||
}
|
||||
return defaultiwad;
|
||||
}
|
||||
|
@ -682,16 +607,16 @@ bool I_SetCursor(FGameTexture *cursorpic)
|
|||
DestroyCustomCursor();
|
||||
cursor = LoadCursor(NULL, IDC_ARROW);
|
||||
}
|
||||
SetClassLongPtr(Window, GCLP_HCURSOR, (LONG_PTR)cursor);
|
||||
SetClassLongPtr(mainwindow.GetHandle(), GCLP_HCURSOR, (LONG_PTR)cursor);
|
||||
if (NativeMouse)
|
||||
{
|
||||
POINT pt;
|
||||
RECT client;
|
||||
|
||||
// If the mouse pointer is within the window's client rect, set it now.
|
||||
if (GetCursorPos(&pt) && GetClientRect(Window, &client) &&
|
||||
ClientToScreen(Window, (LPPOINT)&client.left) &&
|
||||
ClientToScreen(Window, (LPPOINT)&client.right))
|
||||
if (GetCursorPos(&pt) && GetClientRect(mainwindow.GetHandle(), &client) &&
|
||||
ClientToScreen(mainwindow.GetHandle(), (LPPOINT)&client.left) &&
|
||||
ClientToScreen(mainwindow.GetHandle(), (LPPOINT)&client.right))
|
||||
{
|
||||
if (pt.x >= client.left && pt.x < client.right &&
|
||||
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);
|
||||
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
|
||||
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
|
||||
// directories for IWADs if the user purchased any through Steam.
|
||||
TArray<FString> I_GetSteamPath();
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "startupinfo.h"
|
||||
#include "i_interface.h"
|
||||
#include "texturemanager.h"
|
||||
#include "i_mainwindow.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
@ -67,24 +68,13 @@
|
|||
|
||||
// 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_InvalidateRect (HWND hwnd, BitmapInfo *bitmap_info, int left, int top, int right, int bottom);
|
||||
|
||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||
|
||||
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
||||
|
||||
static INT_PTR CALLBACK NetStartPaneProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||
|
||||
extern HINSTANCE g_hInst;
|
||||
extern HWND Window, ConWindow, ProgressBar, NetStartPane, StartupScreen, GameTitleWindow;
|
||||
|
||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||
|
||||
|
@ -112,7 +102,7 @@ CUSTOM_CVAR(Int, showendoom, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
|||
FStartupScreen *FStartupScreen::CreateInstance(int max_progress)
|
||||
{
|
||||
FStartupScreen *scr = NULL;
|
||||
HRESULT hr = -1;
|
||||
HRESULT hr = E_FAIL;
|
||||
|
||||
if (!Args->CheckParm("-nostartup"))
|
||||
{
|
||||
|
@ -154,12 +144,7 @@ FBasicStartupScreen::FBasicStartupScreen(int max_progress, bool show_bar)
|
|||
{
|
||||
if (show_bar)
|
||||
{
|
||||
ProgressBar = CreateWindowEx(0, PROGRESS_CLASS,
|
||||
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);
|
||||
mainwindow.ShowProgressBar(MaxPos);
|
||||
}
|
||||
NetMaxPos = 0;
|
||||
NetCurPos = 0;
|
||||
|
@ -176,13 +161,8 @@ FBasicStartupScreen::FBasicStartupScreen(int max_progress, bool show_bar)
|
|||
|
||||
FBasicStartupScreen::~FBasicStartupScreen()
|
||||
{
|
||||
if (ProgressBar != NULL)
|
||||
{
|
||||
DestroyWindow (ProgressBar);
|
||||
ProgressBar = NULL;
|
||||
LayoutMainWindow (Window, NULL);
|
||||
}
|
||||
KillTimer(Window, 1337);
|
||||
mainwindow.HideProgressBar();
|
||||
KillTimer(mainwindow.GetHandle(), 1337);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -198,7 +178,7 @@ void FBasicStartupScreen::Progress()
|
|||
if (CurPos < MaxPos)
|
||||
{
|
||||
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)
|
||||
{
|
||||
NetMaxPos = numplayers;
|
||||
if (NetStartPane == NULL)
|
||||
{
|
||||
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;
|
||||
mainwindow.ShowNetStartPane(message, numplayers);
|
||||
|
||||
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;
|
||||
NetCurPos = 0;
|
||||
NetProgress(1); // You always know about yourself
|
||||
|
@ -287,12 +214,7 @@ void FBasicStartupScreen::NetInit(const char *message, int numplayers)
|
|||
|
||||
void FBasicStartupScreen::NetDone()
|
||||
{
|
||||
if (NetStartPane != NULL)
|
||||
{
|
||||
DestroyWindow (NetStartPane);
|
||||
NetStartPane = NULL;
|
||||
LayoutMainWindow (Window, NULL);
|
||||
}
|
||||
mainwindow.HideNetStartPane();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -325,7 +247,7 @@ void FBasicStartupScreen::NetMessage(const char *format, ...)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void FBasicStartupScreen :: NetProgress(int count)
|
||||
void FBasicStartupScreen::NetProgress(int count)
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
|
@ -335,23 +257,8 @@ void FBasicStartupScreen :: NetProgress(int 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);
|
||||
SetDlgItemTextA (NetStartPane, IDC_NETSTARTCOUNT, buf);
|
||||
SendDlgItemMessage (NetStartPane, IDC_NETSTARTPROGRESS, PBM_SETPOS, min(NetCurPos, NetMaxPos), 0);
|
||||
}
|
||||
mainwindow.SetNetStartProgress(count);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -370,59 +277,7 @@ void FBasicStartupScreen :: NetProgress(int count)
|
|||
|
||||
bool FBasicStartupScreen::NetLoop(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 (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;
|
||||
return mainwindow.RunMessageLoop(timer_callback, userdata);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -437,6 +292,7 @@ static INT_PTR CALLBACK NetStartPaneProc (HWND hDlg, UINT msg, WPARAM wParam, LP
|
|||
FGraphicalStartupScreen::FGraphicalStartupScreen(int max_progress)
|
||||
: FBasicStartupScreen(max_progress, false)
|
||||
{
|
||||
mainwindow.ShowStartupScreen();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -447,11 +303,7 @@ FGraphicalStartupScreen::FGraphicalStartupScreen(int max_progress)
|
|||
|
||||
FGraphicalStartupScreen::~FGraphicalStartupScreen()
|
||||
{
|
||||
if (StartupScreen != NULL)
|
||||
{
|
||||
DestroyWindow (StartupScreen);
|
||||
StartupScreen = NULL;
|
||||
}
|
||||
mainwindow.HideStartupScreen();
|
||||
if (StartupBitmap != NULL)
|
||||
{
|
||||
ST_Util_FreeBitmap (StartupBitmap);
|
||||
|
@ -468,8 +320,8 @@ FGraphicalStartupScreen::~FGraphicalStartupScreen()
|
|||
void FHexenStartupScreen::SetWindowSize()
|
||||
{
|
||||
ST_Util_SizeWindowForBitmap(1);
|
||||
LayoutMainWindow(Window, NULL);
|
||||
InvalidateRect(StartupScreen, NULL, TRUE);
|
||||
mainwindow.UpdateLayout();
|
||||
mainwindow.InvalidateStartupScreen();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -481,8 +333,8 @@ void FHexenStartupScreen::SetWindowSize()
|
|||
void FHereticStartupScreen::SetWindowSize()
|
||||
{
|
||||
ST_Util_SizeWindowForBitmap(1);
|
||||
LayoutMainWindow(Window, NULL);
|
||||
InvalidateRect(StartupScreen, NULL, TRUE);
|
||||
mainwindow.UpdateLayout();
|
||||
mainwindow.InvalidateStartupScreen();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -494,8 +346,8 @@ void FHereticStartupScreen::SetWindowSize()
|
|||
void FStrifeStartupScreen::SetWindowSize()
|
||||
{
|
||||
ST_Util_SizeWindowForBitmap(2);
|
||||
LayoutMainWindow(Window, NULL);
|
||||
InvalidateRect(StartupScreen, NULL, TRUE);
|
||||
mainwindow.UpdateLayout();
|
||||
mainwindow.InvalidateStartupScreen();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -532,13 +384,10 @@ int RunEndoom()
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!ST_Util_CreateStartupWindow())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
mainwindow.ShowStartupScreen();
|
||||
|
||||
I_ShutdownGraphics ();
|
||||
RestoreConView ();
|
||||
mainwindow.RestoreConView ();
|
||||
S_StopMusic(true);
|
||||
|
||||
fileSystem.ReadFile (endoom_lump, endoom_screen);
|
||||
|
@ -548,15 +397,11 @@ int RunEndoom()
|
|||
ST_Util_DrawTextScreen (StartupBitmap, endoom_screen);
|
||||
|
||||
// Make the title banner go away.
|
||||
if (GameTitleWindow != NULL)
|
||||
{
|
||||
DestroyWindow (GameTitleWindow);
|
||||
GameTitleWindow = NULL;
|
||||
}
|
||||
mainwindow.HideGameTitleWindow();
|
||||
|
||||
ST_Util_SizeWindowForBitmap (1);
|
||||
LayoutMainWindow (Window, NULL);
|
||||
InvalidateRect (StartupScreen, NULL, TRUE);
|
||||
mainwindow.UpdateLayout();
|
||||
mainwindow.InvalidateStartupScreen();
|
||||
|
||||
// Does this screen need blinking?
|
||||
for (i = 0; i < 80*25; ++i)
|
||||
|
@ -567,7 +412,7 @@ int RunEndoom()
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (blinking && SetTimer (Window, 0x5A15A, BLINK_PERIOD, NULL) == 0)
|
||||
if (blinking && SetTimer (mainwindow.GetHandle(), 0x5A15A, BLINK_PERIOD, NULL) == 0)
|
||||
{
|
||||
blinking = false;
|
||||
}
|
||||
|
@ -581,12 +426,12 @@ int RunEndoom()
|
|||
{
|
||||
if (blinking)
|
||||
{
|
||||
KillTimer (Window, 0x5A15A);
|
||||
KillTimer (mainwindow.GetHandle(), 0x5A15A);
|
||||
}
|
||||
ST_Util_FreeBitmap (StartupBitmap);
|
||||
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);
|
||||
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
|
||||
|
@ -640,16 +464,7 @@ void ST_Util_SizeWindowForBitmap (int scale)
|
|||
int w, h, cx, cy, x, y;
|
||||
RECT rect;
|
||||
|
||||
if (GameTitleWindow != NULL)
|
||||
{
|
||||
GetClientRect (GameTitleWindow, &rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
rect.bottom = 0;
|
||||
}
|
||||
RECT sizerect = { 0, 0, StartupBitmap->bmiHeader.biWidth * scale,
|
||||
StartupBitmap->bmiHeader.biHeight * scale + rect.bottom };
|
||||
RECT sizerect = { 0, 0, StartupBitmap->bmiHeader.biWidth * scale, StartupBitmap->bmiHeader.biHeight * scale + mainwindow.GetGameTitleWindowHeight() };
|
||||
AdjustWindowRectEx(&sizerect, WS_VISIBLE|WS_OVERLAPPEDWINDOW, FALSE, WS_EX_APPWINDOW);
|
||||
w = sizerect.right - sizerect.left;
|
||||
h = sizerect.bottom - sizerect.top;
|
||||
|
@ -659,7 +474,7 @@ void ST_Util_SizeWindowForBitmap (int scale)
|
|||
memset (&displaysettings, 0, sizeof(displaysettings));
|
||||
displaysettings.dmSize = sizeof(displaysettings);
|
||||
EnumDisplaySettings (NULL, ENUM_CURRENT_SETTINGS, &displaysettings);
|
||||
GetWindowRect (Window, &rect);
|
||||
GetWindowRect (mainwindow.GetHandle(), &rect);
|
||||
cx = (rect.left + rect.right) / 2;
|
||||
cy = (rect.top + rect.bottom) / 2;
|
||||
x = cx - w / 2;
|
||||
|
@ -680,7 +495,7 @@ void ST_Util_SizeWindowForBitmap (int scale)
|
|||
{
|
||||
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)
|
||||
{
|
||||
ST_Util_InvalidateRect(StartupScreen , bitmap_info, left, top, right, bottom);
|
||||
mainwindow.InvalidateStartupScreen(left, top, right, bottom);
|
||||
}
|
||||
|
|
|
@ -43,14 +43,12 @@
|
|||
#include "startupinfo.h"
|
||||
#include "palutil.h"
|
||||
#include "i_interface.h"
|
||||
#include "i_mainwindow.h"
|
||||
|
||||
uint8_t* GetHexChar(int codepoint);
|
||||
|
||||
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[] = {
|
||||
0x0000, //#NULL
|
||||
0x0001, //#START OF HEADING
|
||||
|
@ -420,7 +418,7 @@ FHexenStartupScreen::FHexenStartupScreen(int max_progress, long& hr)
|
|||
int notch_lump = fileSystem.CheckNumForName("NOTCH");
|
||||
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 ||
|
||||
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];
|
||||
|
||||
hr = -1;
|
||||
if (loading_lump < 0 || fileSystem.FileLength(loading_lump) != 4000 || !ST_Util_CreateStartupWindow())
|
||||
if (loading_lump < 0 || fileSystem.FileLength(loading_lump) != 4000)
|
||||
{
|
||||
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_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++;
|
||||
I_GetEvent();
|
||||
}
|
||||
|
@ -678,7 +676,7 @@ void FHereticStartupScreen::AppendStatusLine(const char* status)
|
|||
{
|
||||
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;
|
||||
I_GetEvent();
|
||||
}
|
||||
|
@ -711,7 +709,7 @@ FStrifeStartupScreen::FStrifeStartupScreen(int max_progress, long& hr)
|
|||
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;
|
||||
}
|
||||
|
@ -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;
|
||||
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)
|
||||
{ // 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;
|
||||
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)
|
||||
{
|
||||
|
@ -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;
|
||||
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)
|
||||
{
|
||||
|
@ -1165,7 +1163,7 @@ void ST_Util_UpdateTextBlink(BitmapInfo* bitmap_info, const uint8_t* text_screen
|
|||
if (text_screen[1] & 0x80)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "printf.h"
|
||||
#include "win32basevideo.h"
|
||||
#include "cmdlib.h"
|
||||
#include "i_mainwindow.h"
|
||||
|
||||
CVAR(Int, vid_adapter, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
|
||||
|
@ -58,7 +59,7 @@ CVAR(Int, vid_adapter, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
|||
|
||||
Win32BaseVideo::Win32BaseVideo()
|
||||
{
|
||||
I_SetWndProc();
|
||||
mainwindow.ShowGameView();
|
||||
|
||||
GetDisplayDeviceName();
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "hardware.h"
|
||||
#include "engineerrors.h"
|
||||
#include <Windows.h>
|
||||
#include "i_mainwindow.h"
|
||||
|
||||
#ifdef HAVE_SOFTPOLY
|
||||
|
||||
|
@ -10,8 +11,6 @@ EXTERN_CVAR(Bool, vid_vsync)
|
|||
|
||||
bool ViewportLinearScale();
|
||||
|
||||
extern HWND Window;
|
||||
|
||||
#include <d3d9.h>
|
||||
#pragma comment(lib, "d3d9.lib")
|
||||
|
||||
|
@ -41,7 +40,7 @@ void I_PolyPresentInit()
|
|||
}
|
||||
|
||||
RECT rect = {};
|
||||
GetClientRect(Window, &rect);
|
||||
GetClientRect(mainwindow.GetHandle(), &rect);
|
||||
|
||||
ClientWidth = rect.right;
|
||||
ClientHeight = rect.bottom;
|
||||
|
@ -52,10 +51,10 @@ void I_PolyPresentInit()
|
|||
pp.BackBufferWidth = ClientWidth;
|
||||
pp.BackBufferHeight = ClientHeight;
|
||||
pp.BackBufferCount = 1;
|
||||
pp.hDeviceWindow = Window;
|
||||
pp.hDeviceWindow = mainwindow.GetHandle();
|
||||
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))
|
||||
{
|
||||
I_FatalError("IDirect3D9.CreateDevice failed");
|
||||
|
@ -67,7 +66,7 @@ uint8_t *I_PolyPresentLock(int w, int h, bool vsync, int &pitch)
|
|||
HRESULT result;
|
||||
|
||||
RECT rect = {};
|
||||
GetClientRect(Window, &rect);
|
||||
GetClientRect(mainwindow.GetHandle(), &rect);
|
||||
if (rect.right != ClientWidth || rect.bottom != ClientHeight || CurrentVSync != vsync)
|
||||
{
|
||||
if (surface)
|
||||
|
@ -86,7 +85,7 @@ uint8_t *I_PolyPresentLock(int w, int h, bool vsync, int &pitch)
|
|||
pp.BackBufferWidth = ClientWidth;
|
||||
pp.BackBufferHeight = ClientHeight;
|
||||
pp.BackBufferCount = 1;
|
||||
pp.hDeviceWindow = Window;
|
||||
pp.hDeviceWindow = mainwindow.GetHandle();
|
||||
pp.PresentationInterval = CurrentVSync ? D3DPRESENT_INTERVAL_DEFAULT : D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||
device->Reset(&pp);
|
||||
}
|
||||
|
|
|
@ -7,16 +7,14 @@
|
|||
#endif
|
||||
|
||||
#include "volk/volk.h"
|
||||
|
||||
|
||||
extern HWND Window;
|
||||
#include "i_mainwindow.h"
|
||||
|
||||
void I_GetVulkanDrawableSize(int *width, int *height)
|
||||
{
|
||||
assert(Window);
|
||||
|
||||
RECT clientRect = { 0 };
|
||||
GetClientRect(Window, &clientRect);
|
||||
GetClientRect(mainwindow.GetHandle(), &clientRect);
|
||||
|
||||
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.pNext = nullptr;
|
||||
windowCreateInfo.flags = 0;
|
||||
windowCreateInfo.hwnd = Window;
|
||||
windowCreateInfo.hwnd = mainwindow.GetHandle();
|
||||
windowCreateInfo.hinstance = GetModuleHandle(nullptr);
|
||||
|
||||
const VkResult result = vkCreateWin32SurfaceKHR(instance, &windowCreateInfo, nullptr, surface);
|
||||
|
|
|
@ -32,10 +32,6 @@
|
|||
#include "polyrenderer/drawers/poly_triangle.h"
|
||||
#include <chrono>
|
||||
|
||||
#ifdef WIN32
|
||||
void PeekThreadedErrorPane();
|
||||
#endif
|
||||
|
||||
CVAR(Int, r_multithreaded, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
||||
CVAR(Int, r_debug_draw, 0, 0);
|
||||
|
||||
|
@ -101,12 +97,7 @@ void DrawerThreads::WaitForWorkers()
|
|||
std::unique_lock<std::mutex> end_lock(queue->end_mutex);
|
||||
if (!queue->end_condition.wait_for(end_lock, 5s, [&]() { return queue->tasks_left == 0; }))
|
||||
{
|
||||
#ifdef WIN32
|
||||
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;
|
||||
I_FatalError("Drawer threads did not finish within 5 seconds!");
|
||||
}
|
||||
end_lock.unlock();
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@ void D_ConfirmSendStats()
|
|||
|
||||
#else // !NO_SEND_STATS
|
||||
|
||||
#include "i_mainwindow.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
@ -340,8 +342,7 @@ void D_ConfirmSendStats()
|
|||
UCVarValue enabled = { 0 };
|
||||
|
||||
#ifdef _WIN32
|
||||
extern HWND Window;
|
||||
enabled.Int = MessageBoxA(Window, MESSAGE_TEXT, TITLE_TEXT, MB_ICONQUESTION | MB_YESNO) == IDYES;
|
||||
enabled.Int = MessageBoxA(mainwindow.GetHandle(), MESSAGE_TEXT, TITLE_TEXT, MB_ICONQUESTION | MB_YESNO) == IDYES;
|
||||
#elif defined __APPLE__
|
||||
const CFStringRef messageString = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, MESSAGE_TEXT, kCFStringEncodingASCII, kCFAllocatorNull);
|
||||
const CFStringRef titleString = CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, TITLE_TEXT, kCFStringEncodingASCII, kCFAllocatorNull);
|
||||
|
|
|
@ -59,10 +59,6 @@
|
|||
#include "swrenderer/things/r_playersprite.h"
|
||||
#include <chrono>
|
||||
|
||||
#ifdef WIN32
|
||||
void PeekThreadedErrorPane();
|
||||
#endif
|
||||
|
||||
EXTERN_CVAR(Int, r_clearbuffer)
|
||||
EXTERN_CVAR(Int, r_debug_draw)
|
||||
|
||||
|
@ -239,12 +235,7 @@ namespace swrenderer
|
|||
finished_threads++;
|
||||
if (!end_condition.wait_for(end_lock, 5s, [&]() { return finished_threads == Threads.size(); }))
|
||||
{
|
||||
#ifdef WIN32
|
||||
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;
|
||||
I_FatalError("Render threads did not finish within 5 seconds!");
|
||||
}
|
||||
finished_threads = 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue