/* ** Command & Conquer Generals Zero Hour(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ //////////////////////////////////////////////////////////////////////////////// // // // (c) 2001-2003 Electronic Arts Inc. // // // //////////////////////////////////////////////////////////////////////////////// // FILE: WinMain.cpp ////////////////////////////////////////////////////////// //----------------------------------------------------------------------------- // // Westwood Studios Pacific. // // Confidential Information // Copyright (C) 2001 - All Rights Reserved // //----------------------------------------------------------------------------- // // Project: RTS3 // // File name: GUIEdit.cpp // // Created: Colin Day, July 2001 // // Desc: GUI Edit and window layout entry point // //----------------------------------------------------------------------------- /////////////////////////////////////////////////////////////////////////////// // SYSTEM INCLUDES //////////////////////////////////////////////////////////// #include #include #include // USER INCLUDES ////////////////////////////////////////////////////////////// #include "Common/Debug.h" #include "Common/GameMemory.h" #include "Common/GameEngine.h" #include "GameClient/GameWindowManager.h" #include "Win32Device/GameClient/Win32Mouse.h" #include "Resource.h" #include "Lib/BaseType.h" #include "GUIEdit.h" #include "EditWindow.h" #include "DialogProc.h" #include "LayoutScheme.h" // DEFINES //////////////////////////////////////////////////////////////////// // PRIVATE TYPES ////////////////////////////////////////////////////////////// // PRIVATE DATA /////////////////////////////////////////////////////////////// static char *szWindowClass = "GUIEdit"; // PUBLIC DATA //////////////////////////////////////////////////////////////// HINSTANCE ApplicationHInstance; ///< main application instance HWND ApplicationHWnd; ///< main application HWnd Win32Mouse *TheWin32Mouse = NULL; ///< for Win32 mouse char *gAppPrefix = "ge_"; /// So GuiEdit can have a different debug log file name if we need it const Char *g_strFile = "data\\Generals.str"; const Char *g_csfFile = "data\\%s\\Generals.csf"; /////////////////////////////////////////////////////////////////////////////// // PRIVATE PROTOTYPES ///////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK AboutCallback(HWND, UINT, WPARAM, LPARAM); /////////////////////////////////////////////////////////////////////////////// // PRIVATE FUNCTIONS ////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // initInstance =============================================================== // // FUNCTION: initInstance(HANDLE, int) // // PURPOSE: Saves instance handle and creates main window // // COMMENTS: // // In this function, we save the instance handle in a global variable and // create and display the main program window. // //============================================================================= static BOOL initInstance( HINSTANCE hInstance, int nCmdShow ) { // store application instance ApplicationHInstance = hInstance; // create app window and keep handle ApplicationHWnd = CreateWindowEx( 0, // extended style szWindowClass, // window class name "GUIEdit", // window name WS_OVERLAPPEDWINDOW, // window styles 0, // x position 0, // y position GetSystemMetrics( SM_CXSCREEN ), // width GetSystemMetrics( SM_CYSCREEN ), // height NULL, // parent NULL, // menu ApplicationHInstance, // instance NULL ); // creation data if( ApplicationHWnd == NULL ) return FALSE; // display the window ShowWindow( ApplicationHWnd, SW_MAXIMIZE ); UpdateWindow( ApplicationHWnd ); return TRUE; } // end initInstance // registerClass ============================================================== // // FUNCTION: registerClass() // // PURPOSE: Registers the window class. // // COMMENTS: // // This function and its usage is only necessary if you want this code // to be compatible with Win32 systems prior to the 'RegisterClassEx' // function that was added to Windows 95. It is important to call this function // so that the application will get 'well formed' small icons associated // with it. // //============================================================================= static ATOM registerClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof( WNDCLASSEX ); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)GUIEDIT_LARGE_ICON); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH ); wcex.lpszMenuName = (LPCSTR)GUIEDIT_MENU; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)GUIEDIT_SMALL_ICON); return RegisterClassEx( &wcex ); } // registerClass /////////////////////////////////////////////////////////////////////////////// // PUBLIC FUNCTIONS /////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // WinMain ==================================================================== /** Entry point for application */ //============================================================================= Int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG msg; Int returnValue; HACCEL hAccelTable; Bool quit = FALSE; /// @todo remove this force set of working directory later Char buffer[ _MAX_PATH ]; GetModuleFileName( NULL, buffer, sizeof( buffer ) ); Char *pEnd = buffer + strlen( buffer ); while( pEnd != buffer ) { if( *pEnd == '\\' ) { *pEnd = 0; break; } pEnd--; } ::SetCurrentDirectory(buffer); // start the log DEBUG_INIT(DEBUG_FLAGS_DEFAULT); initMemoryManager(); // register a class for our window with the OS registerClass( hInstance ); // Perform application initialization: if( !initInstance( hInstance, nCmdShow ) ) return FALSE; // load accellerator table hAccelTable = LoadAccelerators( hInstance, (LPCTSTR)GUIEDIT_ACCELERATORS ); // initialize the common controls INITCOMMONCONTROLSEX controls; controls.dwSize = sizeof( controls ); controls.dwICC = ICC_BAR_CLASSES; InitCommonControlsEx( &controls ); // initialize GUIEdit data TheEditor = new GUIEdit; if( TheEditor == NULL ) return FALSE; TheEditor->init(); // // see if we have any messages to process, a NULL window handle tells the // OS to look at the main window associated with the calling thread, us! // while( quit == FALSE ) { // is there is message ready for us? if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) ) { // process ALL messages waiting while( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) ) { // get the message returnValue = GetMessage( &msg, NULL, 0, 0 ); // check for quitting if( returnValue == 0 ) quit = TRUE; // translate accelerator messages if( !TranslateAccelerator( msg.hwnd, hAccelTable, &msg ) ) { // translate and dispatch the message TranslateMessage( &msg ); DispatchMessage( &msg ); } // end if } // end while } // end if else { // udpate our universe TheEditor->update(); Sleep(1); } // end else } // end while // shutdown GUIEdit data delete TheEditor; TheEditor = NULL; // close the log shutdownMemoryManager(); DEBUG_SHUTDOWN(); return msg.wParam; } // end WinMain // WndProc ==================================================================== // // FUNCTION: WndProc(HWND, unsigned, WORD, LONG) // // PURPOSE: Processes messages for the main window. // // WM_COMMAND - process the application menu // WM_PAINT - Paint the main window // WM_DESTROY - post a quit message and return // //============================================================================= LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { switch( message ) { // ------------------------------------------------------------------------ case WM_MOUSEMOVE: { // keep focus in our app if( GetFocus() != hWnd ) SetFocus( hWnd ); return 0; } // end move mouse // ------------------------------------------------------------------------ case WM_COMMAND: { Int controlID = LOWORD( wParam ); // Int nofifyCode = HIWORD( wParam ); // HWND hWndControl = (HWND)lParam; switch( controlID ) { // -------------------------------------------------------------------- case MENU_EXIT: TheEditor->menuExit(); break; //--------------------------------------------------------------------- case MENU_NEW: TheEditor->menuNew(); break; // -------------------------------------------------------------------- case MENU_OPEN: TheEditor->menuOpen(); break; // -------------------------------------------------------------------- case MENU_SAVE: TheEditor->menuSave(); break; // -------------------------------------------------------------------- case MENU_SAVEAS: TheEditor->menuSaveAs(); break; // -------------------------------------------------------------------- case MENU_COPY: TheEditor->menuCopy(); break; // -------------------------------------------------------------------- case MENU_CUT: TheEditor->menuCut(); break; // -------------------------------------------------------------------- case MENU_PASTE: TheEditor->menuPaste(); break; // -------------------------------------------------------------------- case MENU_CALLBACKS: DialogBox( TheEditor->getInstance(), (LPCTSTR)CALLBACK_EDITOR_DIALOG, TheEditor->getWindowHandle(), CallbackEditorDialogProc ); break; // -------------------------------------------------------------------- case MENU_GRID_SETTINGS: DialogBox( TheEditor->getInstance(), (LPCTSTR)GRID_SETTINGS_DIALOG, TheEditor->getWindowHandle(), GridSettingsDialogProc ); break; // -------------------------------------------------------------------- case MENU_SHOW_HIDDEN_OUTLINES: TheEditor->setShowHiddenOutlines( !TheEditor->getShowHiddenOutlines() ); break; // -------------------------------------------------------------------- case MENU_SHOW_SEE_THRU_OUTLINES: TheEditor->setShowSeeThruOutlines( !TheEditor->getShowSeeThruOutlines() ); break; // -------------------------------------------------------------------- case MENU_TEST_MODE: // switch to test mode or edit mode if( TheEditor) { EditMode mode = TheEditor->getMode(); if( mode != MODE_TEST_RUN ) TheEditor->setMode( MODE_TEST_RUN ); else TheEditor->setMode( MODE_EDIT ); } // end if break; // -------------------------------------------------------------------- case MENU_BACKGROUND_COLOR: if( TheEditWindow ) { RGBColorReal color = TheEditWindow->getBackgroundColor(); RGBColorInt *newColor; POINT mouse; // get mouse point GetCursorPos( &mouse ); // select a new color newColor = SelectColor( (Int)(255.0f * color.red), (Int)(255.0f * color.green), (Int)(255.0f * color.blue), (Int)(255.0f * color.alpha), mouse.x, mouse.y ); if( newColor ) { color.red = (Real)newColor->red / 255.0f; color.green = (Real)newColor->green / 255.0f; color.blue = (Real)newColor->blue / 255.0f; color.alpha = (Real)newColor->alpha / 255.0f; TheEditWindow->setBackgroundColor( color ); } // end if } // end if break; // -------------------------------------------------------------------- case MENU_SCHEME: { // open the default scheme information if( TheDefaultScheme ) TheDefaultScheme->openDialog(); break; } // end scheme // -------------------------------------------------------------------- case MENU_ABOUT: { DialogBox( ApplicationHInstance, (LPCTSTR)ABOUT_DIALOG, hWnd, (DLGPROC)AboutCallback ); break; } // end about // -------------------------------------------------------------------- default: { return DefWindowProc( hWnd, message, wParam, lParam ); } // end default } // end switch( controlID ) return 0; } // end command // ------------------------------------------------------------------------ case WM_CLOSE: { // close gets initiated from the 'x' in the top right of the window TheEditor->menuExit(); return 0; } // end close // ------------------------------------------------------------------------ case WM_KEYDOWN: { Int virtualKey = wParam; // Int keyData = lParam; Bool controlDown = BitTest( GetKeyState( VK_CONTROL ), 0x1000 ); switch( virtualKey ) { // -------------------------------------------------------------------- case VK_ESCAPE: { // unselect all windows if( TheEditor ) if(TheEditor->getMode() == MODE_KEYBOARD_MOVE) TheEditor->setMode( MODE_EDIT ); else TheEditor->clearSelections(); break; } // end escape // -------------------------------------------------------------------- case VK_DELETE: { // delete all selected windows if( TheEditor ) TheEditor->deleteSelected(); break; } // end delete // -------------------------------------------------------------------- case VK_LEFT: { // delete all selected windows if( TheEditor && TheEditWindow) { if(TheEditor->getMode() == MODE_EDIT) { if(TheEditor->selectionCount() <= 0 ) break; ICoord2D zero; zero.x = zero.y = 0; TheEditWindow->setDragMoveOrigin(&zero); TheEditWindow->setDragMoveDest(&zero); TheEditor->setMode(MODE_KEYBOARD_MOVE); } if(TheEditor->getMode() == MODE_KEYBOARD_MOVE) { ICoord2D temp; temp = TheEditWindow->getDragMoveDest(); if(!controlDown && TheEditor->isGridSnapOn()) { temp.x -= TheEditor->getGridResolution(); TheEditor->gridSnapLocation(&temp,&temp); } else { temp.x--; } TheEditWindow->setDragMoveDest(&temp); } } break; } // end Left // -------------------------------------------------------------------- case VK_RIGHT: { // delete all selected windows if( TheEditor && TheEditWindow) { if(TheEditor->getMode() == MODE_EDIT) { if(TheEditor->selectionCount() <= 0 ) break; ICoord2D zero; zero.x = zero.y = 0; TheEditWindow->setDragMoveOrigin(&zero); TheEditWindow->setDragMoveDest(&zero); TheEditor->setMode(MODE_KEYBOARD_MOVE); } if(TheEditor->getMode() == MODE_KEYBOARD_MOVE) { ICoord2D temp; temp = TheEditWindow->getDragMoveDest(); if(!controlDown && TheEditor->isGridSnapOn()) { temp.x += TheEditor->getGridResolution(); TheEditor->gridSnapLocation(&temp,&temp); } else { temp.x++; } TheEditWindow->setDragMoveDest(&temp); } } break; } // end RIGHT // -------------------------------------------------------------------- case VK_UP: { // delete all selected windows if( TheEditor && TheEditWindow) { if(TheEditor->getMode() == MODE_EDIT) { if(TheEditor->selectionCount() <= 0 ) break; ICoord2D zero; zero.x = zero.y = 0; TheEditWindow->setDragMoveOrigin(&zero); TheEditWindow->setDragMoveDest(&zero); TheEditor->setMode(MODE_KEYBOARD_MOVE); } if(TheEditor->getMode() == MODE_KEYBOARD_MOVE) { ICoord2D temp; temp = TheEditWindow->getDragMoveDest(); if(!controlDown && TheEditor->isGridSnapOn()) { temp.y -= TheEditor->getGridResolution(); TheEditor->gridSnapLocation(&temp,&temp); } else { temp.y--; } TheEditWindow->setDragMoveDest(&temp); } } break; } // end Up // -------------------------------------------------------------------- case VK_DOWN: { // delete all selected windows if( TheEditor && TheEditWindow) { if(TheEditor->getMode() == MODE_EDIT) { if(TheEditor->selectionCount() <= 0 ) break; ICoord2D zero; zero.x = zero.y = 0; TheEditWindow->setDragMoveOrigin(&zero); TheEditWindow->setDragMoveDest(&zero); TheEditor->setMode(MODE_KEYBOARD_MOVE); } if(TheEditor->getMode() == MODE_KEYBOARD_MOVE) { ICoord2D temp; temp = TheEditWindow->getDragMoveDest(); if(!controlDown && TheEditor->isGridSnapOn()) { temp.y += TheEditor->getGridResolution(); TheEditor->gridSnapLocation(&temp,&temp); } else { temp.y++; } TheEditWindow->setDragMoveDest(&temp); } } break; } // end Down // -------------------------------------------------------------------- case VK_RETURN: { if( TheEditor && TheEditWindow && TheEditor->getMode() == MODE_KEYBOARD_MOVE ) { ICoord2D tempOrigin, tempDest; tempDest = TheEditWindow->getDragMoveDest(); tempOrigin = TheEditWindow->getDragMoveOrigin(); // move the windows TheEditor->dragMoveSelectedWindows( &tempOrigin, &tempDest ); // go back to normal mode TheEditor->setMode( MODE_EDIT ); } break; }// end Enter } // end switch( virtualKey ) return 0; } // end key down // ------------------------------------------------------------------------ case WM_SIZE: { Int width = LOWORD( lParam ); Int height = HIWORD( lParam ); // resize status bar if( TheEditor ) { HWND statusBar = TheEditor->getStatusBarWindowHandle(); if( statusBar ) { RECT rect; Int barX, barY; Int barWidth, barHeight; // keep status window height the same GetWindowRect( statusBar, &rect ); barWidth = width; barHeight = rect.bottom - rect.top; barX = 0; barY = height - barHeight; MoveWindow( statusBar, barX, barY, barWidth, barHeight, TRUE ); } // end if } // end if return 0; } // end size // ------------------------------------------------------------------------ case WM_PAINT: { PAINTSTRUCT ps; HDC hdc; hdc = BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); break; } // end paint // ------------------------------------------------------------------------ case WM_DESTROY: { PostQuitMessage(0); break; } // end destroy // ------------------------------------------------------------------------ default: { return DefWindowProc(hWnd, message, wParam, lParam); } // end default } // end switch( message ) return DefWindowProc( hWnd, message, wParam, lParam ); } // end WndProc // AboutCallback ============================================================== /** Mesage handler for about box. */ //============================================================================= LRESULT CALLBACK AboutCallback( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) { switch (message) { case WM_INITDIALOG: return TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return TRUE; } break; } return FALSE; } // end AboutCallback