418 lines
8.6 KiB
C++
418 lines
8.6 KiB
C++
/*
|
|
** Command & Conquer Renegade(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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
// PickerClass.cpp : implementation file
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "leveledit.h"
|
|
#include "picker.h"
|
|
#include "utils.h"
|
|
#include "filemgr.h"
|
|
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Local constants
|
|
///////////////////////////////////////////////////////////
|
|
const int BUTTON_WIDTH = 22;
|
|
const int BUTTON_ID = 101;
|
|
const int EDIT_ID = 102;
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
//
|
|
// PickerClass
|
|
//
|
|
///////////////////////////////////////////////////////////
|
|
PickerClass::PickerClass (void)
|
|
: m_BrowseButton (NULL),
|
|
m_Icon (NULL),
|
|
CStatic ()
|
|
{
|
|
//
|
|
// By default load the folder icon
|
|
//
|
|
m_Icon = (HICON)::LoadImage (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDI_FOLDER_TINY), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
|
|
return ;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
//
|
|
// ~PickerClass
|
|
//
|
|
///////////////////////////////////////////////////////////
|
|
PickerClass::~PickerClass (void)
|
|
{
|
|
return ;
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(PickerClass, CStatic)
|
|
//{{AFX_MSG_MAP(PickerClass)
|
|
ON_WM_SIZE()
|
|
ON_WM_DRAWITEM()
|
|
ON_WM_ERASEBKGND()
|
|
ON_WM_PAINT()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
//
|
|
// Create_Picker
|
|
//
|
|
///////////////////////////////////////////////////////////
|
|
bool
|
|
PickerClass::Create_Picker
|
|
(
|
|
DWORD style,
|
|
const RECT & rect,
|
|
CWnd * parent,
|
|
UINT id
|
|
)
|
|
{
|
|
//
|
|
// Create the outer window
|
|
//
|
|
BOOL success = CreateEx ( WS_EX_CLIENTEDGE,
|
|
"STATIC",
|
|
"",
|
|
(style | SS_WHITERECT | WS_CLIPCHILDREN) & (~WS_BORDER),
|
|
rect,
|
|
parent,
|
|
id);
|
|
if (success) {
|
|
Initialize_Control ();
|
|
}
|
|
|
|
// Return the true/false result code
|
|
return bool(success == TRUE);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
//
|
|
// WindowProc
|
|
//
|
|
///////////////////////////////////////////////////////////
|
|
LRESULT
|
|
PickerClass::WindowProc
|
|
(
|
|
UINT message,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
//
|
|
// Should we just pass this onto the edit control?
|
|
//
|
|
if ((message == WM_GETTEXT) ||
|
|
(message == WM_GETTEXTLENGTH) ||
|
|
(message == WM_SETTEXT))
|
|
{
|
|
return SendDlgItemMessage (EDIT_ID, message, wParam, lParam);
|
|
|
|
} else if ((message == WM_COMMAND) && (LOWORD (wParam) == EDIT_ID)) {
|
|
|
|
//
|
|
// Translate the message so the dialog thinks it came from an
|
|
// edit control
|
|
//
|
|
LONG id = ::GetWindowLong (m_hWnd, GWL_ID);
|
|
return ::SendMessage (::GetParent (m_hWnd),
|
|
message,
|
|
MAKEWPARAM (id & 0xFFFF, HIWORD (wParam)),
|
|
(LPARAM)m_hWnd);
|
|
|
|
} else if (message == WM_SETFOCUS) {
|
|
::SetFocus (::GetDlgItem (m_hWnd, EDIT_ID));
|
|
}
|
|
|
|
return CStatic::WindowProc (message, wParam, lParam);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
//
|
|
// Initialize_Control
|
|
//
|
|
///////////////////////////////////////////////////////////
|
|
void
|
|
PickerClass::Initialize_Control (void)
|
|
{
|
|
//
|
|
// Set the font for this control
|
|
//
|
|
HFONT hfont = (HFONT)GetParent()->SendMessage (WM_GETFONT);
|
|
SendMessage (WM_SETFONT, (WPARAM)hfont);
|
|
|
|
//
|
|
// Determine how tall to make the edit control
|
|
//
|
|
HDC hdc = ::GetDC (m_hWnd);
|
|
HFONT holdfont = (HFONT)::SelectObject (hdc, hfont);
|
|
CSize size;
|
|
::GetTextExtentPoint32 (hdc, "XgW", 3, &size);
|
|
::SelectObject (hdc, holdfont);
|
|
::ReleaseDC (m_hWnd, hdc);
|
|
|
|
//
|
|
// Create the edit control
|
|
//
|
|
CRect rect;
|
|
GetClientRect (&rect);
|
|
m_EditCtrl = ::CreateWindowEx ( 0,
|
|
"EDIT",
|
|
"",
|
|
WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL,
|
|
2,
|
|
(rect.Height () >> 1) - ((size.cy) >> 1),
|
|
rect.Width () - BUTTON_WIDTH - 3,
|
|
size.cy,
|
|
m_hWnd,
|
|
(HMENU)EDIT_ID,
|
|
::AfxGetInstanceHandle (),
|
|
NULL);
|
|
CRect rect2;
|
|
GetWindowRect (&rect2);
|
|
|
|
|
|
::SendMessage (m_EditCtrl, WM_SETFONT, (WPARAM)hfont, 0L);
|
|
|
|
//
|
|
// Create the picker button
|
|
//
|
|
m_BrowseButton = ::CreateWindow ("BUTTON",
|
|
"",
|
|
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_OWNERDRAW,
|
|
rect.Width () - BUTTON_WIDTH,
|
|
0,
|
|
BUTTON_WIDTH,
|
|
rect.Height (),
|
|
m_hWnd,
|
|
(HMENU)BUTTON_ID,
|
|
::AfxGetInstanceHandle (),
|
|
NULL);
|
|
|
|
ASSERT (m_BrowseButton != NULL);
|
|
return ;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
//
|
|
// Initialize_Control
|
|
//
|
|
///////////////////////////////////////////////////////////
|
|
void
|
|
PickerClass::OnSize
|
|
(
|
|
UINT nType,
|
|
int cx,
|
|
int cy
|
|
)
|
|
{
|
|
|
|
//
|
|
// Set the font for this control
|
|
//
|
|
HFONT hfont = (HFONT)GetParent()->SendMessage (WM_GETFONT);
|
|
SendMessage (WM_SETFONT, (WPARAM)hfont);
|
|
|
|
//
|
|
// Determine how tall to make the edit control
|
|
//
|
|
HDC hdc = ::GetDC (m_hWnd);
|
|
HFONT holdfont = (HFONT)::SelectObject (hdc, hfont);
|
|
CSize size;
|
|
::GetTextExtentPoint32 (hdc, "XgW", 3, &size);
|
|
::SelectObject (hdc, holdfont);
|
|
::ReleaseDC (m_hWnd, hdc);
|
|
|
|
CRect client_rect;
|
|
GetClientRect (&client_rect);
|
|
|
|
//
|
|
// Resize the edit control
|
|
//
|
|
::SetWindowPos ( m_EditCtrl,
|
|
NULL,
|
|
2,
|
|
(client_rect.Height () >> 1) - ((size.cy) >> 1),
|
|
client_rect.Width () - BUTTON_WIDTH - 3,
|
|
size.cy,
|
|
SWP_NOZORDER);
|
|
|
|
//
|
|
// Reposition the file button
|
|
//
|
|
::SetWindowPos ( m_BrowseButton,
|
|
NULL,
|
|
client_rect.Width () - BUTTON_WIDTH,
|
|
0,
|
|
BUTTON_WIDTH,
|
|
client_rect.Height (),
|
|
SWP_NOZORDER);
|
|
|
|
CStatic::OnSize (nType, cx, cy);
|
|
return ;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
//
|
|
// OnCommand
|
|
//
|
|
///////////////////////////////////////////////////////////
|
|
BOOL
|
|
PickerClass::OnCommand
|
|
(
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
//
|
|
// Did the user click the 'picker' button?
|
|
//
|
|
if ((LOWORD (wParam) == BUTTON_ID) &&
|
|
(HIWORD (wParam) == BN_CLICKED))
|
|
{
|
|
On_Pick ();
|
|
}
|
|
|
|
// Allow the base class to process this message
|
|
return CStatic::OnCommand (wParam, lParam);
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
//
|
|
// OnDrawItem
|
|
//
|
|
///////////////////////////////////////////////////////////
|
|
void
|
|
PickerClass::OnDrawItem
|
|
(
|
|
int nIDCtl,
|
|
LPDRAWITEMSTRUCT pDrawItemStruct
|
|
)
|
|
{
|
|
CRect rect;
|
|
::GetClientRect (m_BrowseButton, &rect);
|
|
|
|
//
|
|
// Draw the button frame
|
|
//
|
|
UINT type = (pDrawItemStruct->itemState & ODS_SELECTED) ? (DFCS_SCROLLDOWN | DFCS_PUSHED) : DFCS_SCROLLDOWN;
|
|
::DrawFrameControl (pDrawItemStruct->hDC, &rect, DFC_SCROLL, type);
|
|
|
|
//
|
|
// Calculate the icon's position
|
|
//
|
|
int xpos = (rect.Width () / 2) - 8;
|
|
int ypos = (rect.Height () / 2) - 8;
|
|
|
|
if (pDrawItemStruct->itemState & ODS_SELECTED) {
|
|
xpos ++;
|
|
ypos ++;
|
|
}
|
|
|
|
//
|
|
// Paint the icon
|
|
//
|
|
::DrawIconEx (pDrawItemStruct->hDC,
|
|
xpos,
|
|
ypos,
|
|
m_Icon,
|
|
16,
|
|
16,
|
|
0,
|
|
NULL,
|
|
DI_NORMAL);
|
|
|
|
CStatic::OnDrawItem (nIDCtl, pDrawItemStruct);
|
|
return ;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
//
|
|
// Set_Read_Only
|
|
//
|
|
///////////////////////////////////////////////////////////
|
|
void
|
|
PickerClass::Set_Read_Only (bool readonly)
|
|
{
|
|
::SendMessage (m_EditCtrl, EM_SETREADONLY, (WPARAM)readonly, 0L);
|
|
return ;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
//
|
|
// OnEraseBkgnd
|
|
//
|
|
///////////////////////////////////////////////////////////
|
|
BOOL
|
|
PickerClass::OnEraseBkgnd (CDC *pDC)
|
|
{
|
|
CRect rect;
|
|
::GetClientRect (m_hWnd, &rect);
|
|
|
|
//
|
|
// Use the 'grayed' brush if this control is read-only
|
|
//
|
|
HBRUSH brush = HBRUSH(COLOR_WINDOW+1);
|
|
if (::GetWindowLong (m_EditCtrl, GWL_STYLE) & ES_READONLY) {
|
|
brush = HBRUSH(COLOR_3DFACE+1);
|
|
}
|
|
|
|
//
|
|
// Erase the background
|
|
//
|
|
::FillRect (*pDC, &rect, brush);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
//
|
|
// OnPaint
|
|
//
|
|
///////////////////////////////////////////////////////////
|
|
void
|
|
PickerClass::OnPaint (void)
|
|
{
|
|
//
|
|
// Force the child windows to be repainted
|
|
//
|
|
::InvalidateRect (m_EditCtrl, NULL, TRUE);
|
|
::InvalidateRect (m_BrowseButton, NULL, TRUE);
|
|
|
|
CPaintDC dc (this);
|
|
return ;
|
|
}
|
|
|