This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/Tools/LevelEdit/SpecSheet.cpp

1004 lines
23 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/>.
*/
// SpecSheet.cpp : implementation file
//
#include "stdafx.h"
#include "leveledit.h"
#include "specsheet.h"
#include "definition.h"
#include "parameterctrls.h"
#include "wwstring.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//////////////////////////////////////////////////////////////////////////////
// Local prototypes
//////////////////////////////////////////////////////////////////////////////
int __cdecl fnCtrlCompareCallback (void const *ptr1, void const *ptr2);
int Rate_Param_Type (ParameterClass::Type type);
/////////////////////////////////////////////////////////////////////////////
//
// SpecSheetClass
//
/////////////////////////////////////////////////////////////////////////////
SpecSheetClass::SpecSheetClass (DefinitionClass *definition)
: m_IsScrolling (false),
m_ScrollPos (0),
m_MaxScrollPos (0),
m_IsTemp (false),
m_IsReadOnly (false),
m_ShowFileOnly (false),
m_WereFilesChanged (false),
m_AssetTreeOnly (true),
m_Definition (definition)
{
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// ~SpecSheetClass
//
/////////////////////////////////////////////////////////////////////////////
SpecSheetClass::~SpecSheetClass (void)
{
for (int index = 0; index < m_CtrlList.Count (); index ++) {
ParameterCtrlClass *ctrl = m_CtrlList[index];
delete ctrl;
}
//
// Unlock all the parameters in this definition
//
int count = m_Definition->Get_Parameter_Count ();
for (index = 0; index < count; index ++) {
m_Definition->Unlock_Parameter (index);
}
m_CtrlList.Delete_All ();
return ;
}
BEGIN_MESSAGE_MAP(SpecSheetClass, CWnd)
//{{AFX_MSG_MAP(SpecSheetClass)
ON_WM_CREATE()
ON_WM_NCHITTEST()
ON_WM_VSCROLL()
ON_WM_SETCURSOR()
ON_WM_NCMOUSEMOVE()
ON_WM_NCLBUTTONDOWN()
ON_WM_NCLBUTTONUP()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_SIZE()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//
// Is_Filtered
//
/////////////////////////////////////////////////////////////////////////////
bool
SpecSheetClass::Is_Filtered (ParameterClass *parameter)
{
bool retval = false;
if (parameter != NULL) {
if (m_ShowFileOnly) {
int type = parameter->Get_Type ();
if ( type != ParameterClass::TYPE_FILENAME &&
type != ParameterClass::TYPE_SOUND_FILENAME )
{
retval = true;
}
}
}
return retval;
}
/////////////////////////////////////////////////////////////////////////////
//
// Add_Parameter
//
/////////////////////////////////////////////////////////////////////////////
void
SpecSheetClass::Add_Parameter (ParameterClass *parameter)
{
//
// What type of parameter is this?
//
ParameterCtrlClass *parameter_ctrl = NULL;
switch (parameter->Get_Type ()) {
case ParameterClass::TYPE_INT:
parameter_ctrl = new IntParameterCtrlClass ((IntParameterClass *)parameter);
break;
case ParameterClass::TYPE_FLOAT:
parameter_ctrl = new FloatParameterCtrlClass ((FloatParameterClass *)parameter);
break;
case ParameterClass::TYPE_FILENAME:
parameter_ctrl = new FileParameterCtrlClass ((FilenameParameterClass *)parameter);
((FileParameterCtrlClass *)parameter_ctrl)->Get_File_Picker ().Set_Asset_Tree_Only (m_AssetTreeOnly);
break;
case ParameterClass::TYPE_SOUND_FILENAME:
parameter_ctrl = new SoundFileParameterCtrlClass ((SoundFilenameParameterClass *)parameter);
((FileParameterCtrlClass *)parameter_ctrl)->Get_File_Picker ().Set_Asset_Tree_Only (m_AssetTreeOnly);
break;
case ParameterClass::TYPE_STRING:
parameter_ctrl = new StringParameterCtrlClass ((StringParameterClass *)parameter);
break;
case ParameterClass::TYPE_BOOL:
parameter_ctrl = new BoolParameterCtrlClass ((BoolParameterClass *)parameter);
break;
case ParameterClass::TYPE_VECTOR3:
parameter_ctrl = new Vector3ParameterCtrlClass ((Vector3ParameterClass *)parameter);
break;
case ParameterClass::TYPE_VECTOR2:
parameter_ctrl = new Vector2ParameterCtrlClass ((Vector2ParameterClass *)parameter);
break;
case ParameterClass::TYPE_RECT:
parameter_ctrl = new RectParameterCtrlClass ((RectParameterClass *)parameter);
break;
case ParameterClass::TYPE_COLOR:
parameter_ctrl = new ColorParameterCtrlClass ((ColorParameterClass *)parameter);
break;
case ParameterClass::TYPE_ENUM:
parameter_ctrl = new EnumParameterCtrlClass ((EnumParameterClass *)parameter);
break;
case ParameterClass::TYPE_PHYSDEFINITIONID:
parameter_ctrl = new PhysDefParameterCtrlClass ((PhysDefParameterClass *)parameter);
break;
case ParameterClass::TYPE_GENERICDEFINITIONID:
parameter_ctrl = new GenericDefParameterCtrlClass ((GenericDefParameterClass *)parameter);
break;
case ParameterClass::TYPE_GAMEOBJDEFINITIONID:
parameter_ctrl = new GameObjDefParameterCtrlClass ((GameObjDefParameterClass *)parameter);
break;
case ParameterClass::TYPE_WEAPONOBJDEFINITIONID:
parameter_ctrl = new WeaponObjDefParameterCtrlClass ((WeaponObjDefParameterClass *)parameter);
break;
case ParameterClass::TYPE_AMMOOBJDEFINITIONID:
parameter_ctrl = new AmmoObjDefParameterCtrlClass ((AmmoObjDefParameterClass *)parameter);
break;
case ParameterClass::TYPE_EXPLOSIONDEFINITIONID:
parameter_ctrl = new ExplosionObjDefParameterCtrlClass ((ExplosionObjDefParameterClass *)parameter);
break;
case ParameterClass::TYPE_SOUNDDEFINITIONID:
parameter_ctrl = new SoundDefParameterCtrlClass ((SoundDefParameterClass *)parameter);
break;
case ParameterClass::TYPE_SCRIPT:
parameter_ctrl = new ScriptParameterCtrlClass ((ScriptParameterClass *)parameter);
break;
case ParameterClass::TYPE_ANGLE:
parameter_ctrl = new AngleParameterCtrlClass ((AngleParameterClass *)parameter);
break;
case ParameterClass::TYPE_DEFINITIONIDLIST:
parameter_ctrl = new DefIDListParameterCtrlClass ((DefIDListParameterClass *)parameter);
break;
case ParameterClass::TYPE_FILENAMELIST:
parameter_ctrl = new FilenameListParameterCtrlClass ((FilenameListParameterClass *)parameter);
break;
case ParameterClass::TYPE_SEPARATOR:
parameter_ctrl = new SeparatorParameterCtrlClass ((SeparatorParameterClass *)parameter);
break;
case ParameterClass::TYPE_STRINGSDB_ID:
parameter_ctrl = new StringsDBEntryParameterCtrlClass ((StringsDBEntryParameterClass *)parameter);
break;
}
if (parameter_ctrl != NULL) {
parameter_ctrl->Set_Is_Temp (m_IsTemp);
parameter_ctrl->Set_Spec_Sheet (this);
m_CtrlList.Add (parameter_ctrl);
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnCreate
//
/////////////////////////////////////////////////////////////////////////////
int
SpecSheetClass::OnCreate (LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
//
// Set the font for this control
//
HFONT hfont = (HFONT)GetParent()->SendMessage (WM_GETFONT);
SendMessage (WM_SETFONT, (WPARAM)hfont);
CRect client_rect;
GetClientRect (&client_rect);
//
// Create the scrollbar
//
HWND scrollbar = ::CreateWindow ( "SCROLLBAR",
"",
WS_CHILD | WS_VISIBLE | SBS_VERT,
client_rect.right - ::GetSystemMetrics (SM_CXVSCROLL),
0,
::GetSystemMetrics (SM_CXVSCROLL),
client_rect.Height (),
m_hWnd,
(HMENU)878,
::AfxGetInstanceHandle (),
NULL);
//
// Configure the scrollbar
//
::SendMessage (scrollbar, SBM_SETRANGE, (WPARAM)0, (WPARAM)100);
::SendMessage (scrollbar, WM_SETFONT, (WPARAM)hfont, 0L);
//
// Create a control object for every parameter
//
int count = m_Definition->Get_Parameter_Count ();
for (int index = 0; index < count; index ++) {
ParameterClass *parameter = m_Definition->Lock_Parameter (index);
//
// Add this control to the dialog if its not filtered...
//
if (Is_Filtered (parameter) == false) {
Add_Parameter (parameter);
}
}
int start_id = 500;
CRect rect;
GetClientRect (rect);
rect.top += 10;
rect.bottom = rect.top;
//
// Ask each control to create its UI
//
for (index = 0; index < m_CtrlList.Count (); index ++) {
ParameterCtrlClass *parameter_ctrl = m_CtrlList[index];
parameter_ctrl->Set_Read_Only (m_IsReadOnly);
start_id = parameter_ctrl->Create (m_hWnd, start_id, &rect);
rect.top = rect.bottom + 10;
rect.bottom = rect.top;
}
m_MaxScrollPos = rect.bottom;
return 0;
}
/////////////////////////////////////////////////////////////////////////////
//
// Get_Current_Filename_Value
//
/////////////////////////////////////////////////////////////////////////////
void
SpecSheetClass::Get_Current_Filename_Value (int index, CString &value)
{
//
// Is the index valid?
//
ASSERT (index >= 0 && index < Get_Parameter_Count ());
if (index >= 0 && index < Get_Parameter_Count ()) {
//
// Return the parameter that is associated with this ctrl
//
ParameterCtrlClass *ctrl = m_CtrlList[index];
if ( ctrl->Get_Type () == ParameterClass::TYPE_FILENAME ||
ctrl->Get_Type () == ParameterClass::TYPE_SOUND_FILENAME )
{
((FileParameterCtrlClass *)ctrl)->Get_Current_Value (value);
}
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Get_Parameter
//
/////////////////////////////////////////////////////////////////////////////
ParameterClass *
SpecSheetClass::Get_Parameter (int index)
{
ParameterClass *parameter = NULL;
//
// Is the index valid?
//
ASSERT (index >= 0 && index < Get_Parameter_Count ());
if (index >= 0 && index < Get_Parameter_Count ()) {
//
// Return the parameter that is associated with this ctrl
//
ParameterCtrlClass *ctrl = m_CtrlList[index];
parameter = ctrl->Get_Parameter ();
}
return parameter;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnNcHitTest
//
/////////////////////////////////////////////////////////////////////////////
UINT
SpecSheetClass::OnNcHitTest (CPoint point)
{
return HTCLIENT;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnVScroll
//
/////////////////////////////////////////////////////////////////////////////
void
SpecSheetClass::OnVScroll
(
UINT nSBCode,
UINT nPos,
CScrollBar *pScrollBar
)
{
if (pScrollBar != NULL && GetWindowLong (*pScrollBar, GWL_ID) == 878) {
int new_pos = m_ScrollPos;
CRect client_rect;
GetClientRect (&client_rect);
int height = client_rect.Height ();
switch (nSBCode)
{
case SB_BOTTOM:
new_pos = m_MaxScrollPos;
break;
case SB_LINEDOWN:
if (new_pos < (m_MaxScrollPos - 10)) {
new_pos += 10;
} else {
new_pos = m_MaxScrollPos;
}
break;
case SB_LINEUP:
if (new_pos > 10) {
new_pos -= 10;
} else {
new_pos = 0;
}
break;
case SB_PAGEDOWN:
if (new_pos < (m_MaxScrollPos - (height / 2))) {
new_pos += (height / 2);
} else {
new_pos = m_MaxScrollPos;
}
break;
case SB_PAGEUP:
if (new_pos > (height / 2)) {
new_pos -= (height / 2);
} else {
new_pos = 0;
}
break;
case SB_THUMBTRACK:
case SB_THUMBPOSITION:
new_pos = (m_MaxScrollPos * nPos) / 100;
break;
}
//
// Scroll to the new position
//
Set_Scroll_Pos (new_pos);
}
CWnd::OnVScroll (nSBCode, nPos, pScrollBar);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Set_Scroll_Pos
//
/////////////////////////////////////////////////////////////////////////////
void
SpecSheetClass::Set_Scroll_Pos (int new_pos)
{
//
// Scroll the controls
//
Scroll_Controls (m_ScrollPos - new_pos);
m_ScrollPos = new_pos;
//
// Update the scroll bar
//
int sb_pos = ((m_ScrollPos * 100) / m_MaxScrollPos);
SendDlgItemMessage (878, SBM_SETPOS, (WPARAM)sb_pos, (LPARAM)TRUE);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnSetCursor
//
/////////////////////////////////////////////////////////////////////////////
BOOL
SpecSheetClass::OnSetCursor
(
CWnd * pWnd,
UINT nHitTest,
UINT message
)
{
BOOL retval = FALSE;
if (nHitTest == HTCLIENT) {
::SetCursor (::LoadCursor (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDC_OBJ_MOVE)));
//retval = TRUE;
} else {
retval = CWnd::OnSetCursor (pWnd, nHitTest, message);
}
return retval;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnNcMouseMove
//
/////////////////////////////////////////////////////////////////////////////
void
SpecSheetClass::OnNcMouseMove
(
UINT nHitTest,
CPoint point
)
{
CWnd::OnNcMouseMove (nHitTest, point);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnNcLButtonDown
//
/////////////////////////////////////////////////////////////////////////////
void
SpecSheetClass::OnNcLButtonDown
(
UINT nHitTest,
CPoint point
)
{
/*if (nHitTest == HTVSCROLL) {
m_IsScrolling = true;
m_LastPoint = point;
SetCapture ();
}*/
CWnd::OnNcLButtonDown (nHitTest, point);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnNcLButtonDown
//
/////////////////////////////////////////////////////////////////////////////
void
SpecSheetClass::OnNcLButtonUp
(
UINT nHitTest,
CPoint point
)
{
CWnd::OnNcLButtonUp (nHitTest, point);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnLButtonDown
//
/////////////////////////////////////////////////////////////////////////////
void
SpecSheetClass::OnLButtonDown (UINT nFlags, CPoint point)
{
//if (nHitTest == HTVSCROLL) {
m_IsScrolling = true;
m_LastPoint = point;
SetCapture ();
//}
CWnd::OnLButtonDown(nFlags, point);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnLButtonUp
//
/////////////////////////////////////////////////////////////////////////////
void
SpecSheetClass::OnLButtonUp (UINT nFlags, CPoint point)
{
m_IsScrolling = false;
ReleaseCapture ();
CWnd::OnLButtonUp (nFlags, point);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnMouseMove
//
/////////////////////////////////////////////////////////////////////////////
void
SpecSheetClass::OnMouseMove (UINT nFlags, CPoint point)
{
if (m_IsScrolling) {
CPoint delta = m_LastPoint - point;
int scroll_amt = delta.y;
int new_pos = m_ScrollPos + scroll_amt;
//
// Clip the scroll position to the min and max
//
if (new_pos < 0) {
new_pos = 0;
} else if (new_pos > m_MaxScrollPos) {
new_pos = m_MaxScrollPos;
}
//
// Scroll to the new position
//
Set_Scroll_Pos (new_pos);
//
// Remember the last point
//
m_LastPoint = point;
}
CWnd::OnMouseMove (nFlags, point);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Scroll_Controls
//
/////////////////////////////////////////////////////////////////////////////
void
SpecSheetClass::Scroll_Controls (int amount)
{
DynamicVectorClass<HWND> child_wnd_list;
//
// Build a list of all the child windows we want to scroll
//
for ( HWND child_wnd = ::GetWindow (m_hWnd, GW_CHILD);
child_wnd != NULL;
child_wnd = ::GetWindow (child_wnd, GW_HWNDNEXT))
{
//
// If this isn't the scroll-bar, then add it to the list
//
if (::GetWindowLong (child_wnd, GWL_ID) != 878) {
child_wnd_list.Add (child_wnd);
}
}
//
// Build a defer struct so that we can move all the windows in one
// operation
//
int count = child_wnd_list.Count ();
HDWP defer_struct = ::BeginDeferWindowPos (count);
for (int index = 0; index < count; index ++) {
child_wnd = child_wnd_list[index];
//
// Get the current position of the child window
//
CRect rect;
::GetWindowRect (child_wnd, &rect);
ScreenToClient (&rect);
//
// Scroll the window
//
::DeferWindowPos (defer_struct, child_wnd, NULL, rect.left, rect.top + amount, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOREDRAW);
}
//
// Perform the move operations in batch
//
::EndDeferWindowPos (defer_struct);
CRect client_rect;
GetClientRect (&client_rect);
client_rect.right -= ::GetSystemMetrics (SM_CXVSCROLL);
HDC dc = ::GetDC (m_hWnd);
::ScrollDC (dc, 0, amount, &client_rect, &client_rect, NULL, NULL);
::ReleaseDC (m_hWnd, dc);
if (amount > 0) {
client_rect.bottom = client_rect.top + amount;
} else {
client_rect.top = client_rect.bottom + amount;
}
InvalidateRect (client_rect, TRUE);
UpdateWindow ();
/*CRect client_rect;
GetClientRect (&client_rect);
client_rect.right -= ::GetSystemMetrics (SM_CXVSCROLL);
InvalidateRect (client_rect, TRUE);
UpdateWindow ();*/
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnSize
//
/////////////////////////////////////////////////////////////////////////////
void
SpecSheetClass::OnSize
(
UINT nType,
int cx,
int cy
)
{
CRect client_rect;
GetClientRect (&client_rect);
//
// Resize the scrollbar
//
HWND scrollbar = ::GetDlgItem (m_hWnd, 878);
::SetWindowPos ( scrollbar,
NULL,
client_rect.right - ::GetSystemMetrics (SM_CXVSCROLL),
0,
::GetSystemMetrics (SM_CXVSCROLL),
client_rect.Height (),
SWP_NOZORDER);
//
// Resize the controls
//
client_rect.right -= (::GetSystemMetrics (SM_CXVSCROLL) + 10);
for (int index = 0; index < m_CtrlList.Count (); index ++) {
ParameterCtrlClass *ctrl = m_CtrlList[index];
ctrl->Resize (client_rect);
}
CWnd::OnSize (nType, cx, cy);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// PreCreateWindow
//
/////////////////////////////////////////////////////////////////////////////
BOOL
SpecSheetClass::PreCreateWindow (CREATESTRUCT &cs)
{
cs.dwExStyle |= WS_EX_CONTROLPARENT;
return CWnd::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
//
// Apply
//
/////////////////////////////////////////////////////////////////////////////
void
SpecSheetClass::Apply (void)
{
m_WereFilesChanged = false;
for (int index = 0; index < m_CtrlList.Count (); index ++) {
ParameterCtrlClass *ctrl = m_CtrlList[index];
//
// Determine if any file parameters were changed...
//
int type = ctrl->Get_Type ();
if ( type == ParameterClass::TYPE_FILENAME ||
type == ParameterClass::TYPE_SOUND_FILENAME )
{
m_WereFilesChanged |= ctrl->Is_Modified ();
}
//
// Get the control to read its data from the dialog controls
//
ctrl->Read_Data (NULL);
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Rate_Param_Type
//
/////////////////////////////////////////////////////////////////////////////
int
Rate_Param_Type (ParameterClass::Type type)
{
int retval = 100;
switch (type)
{
case ParameterClass::TYPE_FILENAME:
case ParameterClass::TYPE_SOUND_FILENAME:
retval = 0;
break;
case ParameterClass::TYPE_PHYSDEFINITIONID:
retval = 1;
break;
case ParameterClass::TYPE_GAMEOBJDEFINITIONID:
case ParameterClass::TYPE_WEAPONOBJDEFINITIONID:
case ParameterClass::TYPE_AMMOOBJDEFINITIONID:
case ParameterClass::TYPE_SOUNDDEFINITIONID:
retval = 2;
break;
case ParameterClass::TYPE_SCRIPT:
retval = 3;
break;
case ParameterClass::TYPE_STRING:
retval = 4;
break;
case ParameterClass::TYPE_ENUM:
retval = 5;
break;
case ParameterClass::TYPE_COLOR:
retval = 8;
break;
case ParameterClass::TYPE_VECTOR3:
retval = 9;
break;
case ParameterClass::TYPE_INT:
retval = 10;
break;
case ParameterClass::TYPE_ANGLE:
retval = 11;
break;
case ParameterClass::TYPE_FLOAT:
retval = 12;
break;
case ParameterClass::TYPE_BOOL:
retval = 20;
break;
}
return retval;
}
/////////////////////////////////////////////////////////////////////////////
//
// fnCtrlCompareCallback
//
/////////////////////////////////////////////////////////////////////////////
int __cdecl
fnCtrlCompareCallback (void const *ptr1, void const *ptr2)
{
ParameterClass::Type type1 = (*((ParameterCtrlClass **)ptr1))->Get_Type ();
ParameterClass::Type type2 = (*((ParameterCtrlClass **)ptr2))->Get_Type ();
//
// Determine a sort rating based on the param type
//
int rating1 = ::Rate_Param_Type (type1);
int rating2 = ::Rate_Param_Type (type2);
int retval = rating1 - rating2;
//
// If the type is the same, then sort alphanumerically
//
if (retval == 0) {
ParameterClass *param1 = (*((ParameterCtrlClass **)ptr1))->Get_Parameter ();
ParameterClass *param2 = (*((ParameterCtrlClass **)ptr2))->Get_Parameter ();
//
// Compare the param names
//
CString name1 = param1->Get_Name ();
CString name2 = param2->Get_Name ();
retval = name1.CompareNoCase (name2);
}
return retval;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnCommand
//
/////////////////////////////////////////////////////////////////////////////
BOOL
SpecSheetClass::OnCommand
(
WPARAM wParam,
LPARAM lParam
)
{
bool processed = false;
for (int index = 0; (index < m_CtrlList.Count ()) && !processed; index ++) {
ParameterCtrlClass *ctrl = m_CtrlList[index];
processed = ctrl->On_Command (*this, wParam, lParam);
}
return CWnd::OnCommand (wParam, lParam);
}
/////////////////////////////////////////////////////////////////////////////
//
// OnDestroy
//
/////////////////////////////////////////////////////////////////////////////
void
SpecSheetClass::OnDestroy (void)
{
for (int index = 0; index < m_CtrlList.Count (); index ++) {
ParameterCtrlClass *ctrl = m_CtrlList[index];
ctrl->On_Destroy ();
}
CWnd::OnDestroy ();
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// WindowProc
//
/////////////////////////////////////////////////////////////////////////////
LRESULT
SpecSheetClass::WindowProc (UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT result = 0L;
if (message == WM_DRAWITEM) {
//
// Determine which parameter ctrl wants to process this message...
//
for (int index = 0; (index < m_CtrlList.Count ()) && (result == 0L); index ++) {
ParameterCtrlClass *ctrl = m_CtrlList[index];
if (ctrl->On_DrawItem (*this, wParam, lParam)) {
result = 1L;
}
}
}
if (result == 0L) {
result = CWnd::WindowProc(message, wParam, lParam);
}
return result;
}