/* * Copyright (C) Volition, Inc. 1999. All rights reserved. * * All source code herein is the property of Volition, Inc. You may not sell * or otherwise commercially exploit the source or things you created based on the * source. * */ #include "stdafx.h" #include "FRED.h" #include "MainFrm.h" #include "FREDDoc.h" #include "FREDView.h" #include "EventEditor.h" #include "MessageEditorDlg.h" #include "ShipClassEditorDlg.h" #include "MissionNotesDlg.h" #include "Grid.h" #include "Management.h" #include "species_defs/species_defs.h" #include "iff_defs/iff_defs.h" #include "prop/prop.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd) BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) ON_MESSAGE(WM_MENU_POPUP_EDIT, OnMenuPopupTest) ON_CBN_SELCHANGE(ID_NEW_SHIP_TYPE, OnNewShipTypeChange) //{{AFX_MSG_MAP(CMainFrame) ON_WM_CREATE() ON_COMMAND(ID_FILE_MISSIONNOTES, OnFileMissionnotes) ON_WM_LBUTTONUP() ON_WM_DESTROY() ON_COMMAND(ID_VIEW_STATUS_BAR, OnViewStatusBar) ON_UPDATE_COMMAND_UI(ID_VIEW_STATUS_BAR, OnUpdateViewStatusBar) ON_UPDATE_COMMAND_UI(ID_INDICATOR_LEFT, OnUpdateLeft) ON_UPDATE_COMMAND_UI(ID_INDICATOR_RIGHT, OnUpdateRight) ON_COMMAND(ID_MIKE_GRIDCONTROL, OnMikeGridcontrol) ON_COMMAND(IDR_MENU_POPUP_TOGGLE1, OnMenuPopupToggle1) ON_UPDATE_COMMAND_UI(IDR_MENU_POPUP_TOGGLE1, OnUpdateMenuPopupToggle1) ON_WM_RBUTTONDOWN() ON_WM_CLOSE() ON_WM_INITMENU() ON_COMMAND(ID_HELP_FINDER, OnFredHelp) ON_COMMAND(ID_HELP, OnFredHelp) //ON_COMMAND(ID_CONTEXT_HELP, OnFredHelp) //ON_COMMAND(ID_DEFAULT_HELP, OnFredHelp) //}}AFX_MSG_MAP // Global help commands END_MESSAGE_MAP() #define FRED_HELP_URL "\\data\\freddocs\\index.html" static UINT indicators[] = { ID_SEPARATOR, // status line indicator ID_SEPARATOR, ID_SEPARATOR, ID_INDICATOR_MODIFIED, ID_SEPARATOR, // ID_INDICATOR_LEFT, // ID_INDICATOR_RIGHT, // ID_INDICATOR_CAPS, // ID_INDICATOR_NUM, // ID_INDICATOR_SCRL, }; CMainFrame *Fred_main_wnd; color_combo_box m_new_ship_type_combo_box; size_t ship_type_combo_box_size = 0; color_combo_box_prop m_new_prop_type_combo_box; size_t prop_type_combo_box_size = 0; int Toggle1_var = 0; CPoint Global_point2; CStatic m_ship_label; CStatic m_prop_label; /** * @brief Launches the default browser to open the given URL */ bool url_launch(const char *url); #ifdef _DEBUG void CMainFrame::AssertValid() const { CFrameWnd::AssertValid(); } void CMainFrame::Dump(CDumpContext& dc) const { CFrameWnd::Dump(dc); } #endif // _DEBUG CMainFrame::CMainFrame() {} CMainFrame::~CMainFrame() {} void CMainFrame::init_tools() { // some bizarre Volition check: static int count = 0; count++; if (count == 1) { return; } else if (count >= 3) { Warning(LOCATION, "CMainFrame::init_tools was called more than twice! Trace out and fix."); return; } for (auto it = Ship_info.cbegin(); it != Ship_info.cend(); ++it) { // don't add the pirate ship if (it->flags[Ship::Info_Flags::No_fred]) { //m_new_ship_type_combo_box.AddString(""); continue; } else { m_new_ship_type_combo_box.AddString(it->name); m_new_ship_type_combo_box.SetItemData((int)ship_type_combo_box_size, std::distance(Ship_info.cbegin(), it)); ship_type_combo_box_size++; } } for (auto it = Prop_info.begin(); it != Prop_info.end(); ++it) { if (it->flags[Prop::Info_Flags::No_fred]) { continue; } else { m_new_prop_type_combo_box.AddString(it->name.c_str()); m_new_prop_type_combo_box.SetItemData((int)prop_type_combo_box_size, std::distance(Prop_info.begin(), it)); prop_type_combo_box_size++; } } // No valid props, so disable the dropdown if (prop_type_combo_box_size == 0) { m_new_prop_type_combo_box.EnableWindow(FALSE); m_prop_label.EnableWindow(FALSE); } Id_select_type_waypoint = ship_type_combo_box_size; Id_select_type_jump_node = ship_type_combo_box_size + 1; m_new_ship_type_combo_box.AddString("Waypoint"); m_new_ship_type_combo_box.SetItemData(static_cast(Id_select_type_waypoint), Ship_info.size()); m_new_ship_type_combo_box.AddString("Jump Node"); m_new_ship_type_combo_box.SetItemData(static_cast(Id_select_type_jump_node), Ship_info.size() + 1); /* // now we want to sort special ships (mission disk) ---------------------- highest_terran_index = 0; memset(ship_name, 0, 256); while(m_new_ship_type_combo_box.GetLBText(highest_terran_index, ship_name) != CB_ERR){ ship_index = ship_info_lookup(ship_name); if((ship_index < 0) || (ship_index >= Num_ship_classes) || (Ship_info[ship_index].species != 0)){ break; } highest_terran_index++; } */ m_new_ship_type_combo_box.SetCurSel(0); m_new_prop_type_combo_box.SetCurSel(0); } // The modeless editors are allocated on the heap and only delete themselves when they are closed, so any that // are still open when FRED exits must be deleted here. Their DestroyWindow() overrides clear the global pointer. template static void destroy_modeless_editor(T *&dlg) { if (dlg == nullptr) return; T *ptr = dlg; ptr->DestroyWindow(); delete ptr; dlg = nullptr; } void CMainFrame::OnClose() { // CFrameWnd::OnClose() doesn't provide a way for the caller to tell that the close has been cancelled, // so let's extract that particular logic and do it manually here if (!FREDDoc_ptr->SaveModified()) return; // and now if we *are* closing, prevent the dialog from coming up FREDDoc_ptr->SetModifiedFlag(FALSE); // do the closing stuff theApp.write_ini_file(); SaveBarState("Tools state"); // any changes still pending in these editors are discarded destroy_modeless_editor(Event_editor_dlg); destroy_modeless_editor(Message_editor_dlg); destroy_modeless_editor(Briefing_dialog); destroy_modeless_editor(Debriefing_dialog); destroy_modeless_editor(Bg_bitmap_dialog); CFrameWnd::OnClose(); fred_shutdown(); } int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { int z, zz; CRect rect; if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if (!m_wndToolBar.Create(this) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) { TRACE0("Failed to create toolbar\n"); return -1; // fail to create } // Add static label for "Objects" int ship_label_index = m_wndToolBar.CommandToIndex(ID_NEW_SHIP_TYPE) - 1; m_wndToolBar.SetButtonInfo(ship_label_index, ID_STATIC_SHIP_LABEL, TBBS_SEPARATOR, 70); m_wndToolBar.GetItemRect(ship_label_index, &rect); rect.top = 3; rect.bottom = rect.top + 20; if (!m_ship_label.Create(_T("Objects"), WS_VISIBLE | WS_CHILD, rect, &m_wndToolBar)) { TRACE0("Failed to create 'Objects' label\n"); return -1; } // Create the objects combo box z = m_wndToolBar.CommandToIndex(ID_NEW_SHIP_TYPE); Assert(z != -1); m_wndToolBar.SetButtonInfo(z, ID_NEW_SHIP_TYPE, TBBS_SEPARATOR, 230); // Design guide advises 12 pixel gap between combos and buttons // m_wndToolBar.SetButtonInfo(1, ID_SEPARATOR, TBBS_SEPARATOR, 12); m_wndToolBar.GetItemRect(z, &rect); rect.top = 3; rect.bottom = rect.top + 550; if (!m_new_ship_type_combo_box.Create(CBS_DROPDOWNLIST | WS_VISIBLE | WS_VSCROLL | CBS_HASSTRINGS | LBS_OWNERDRAWFIXED, rect, &m_wndToolBar, ID_NEW_SHIP_TYPE)) { TRACE0("Failed to create new ship type combo-box\n"); return FALSE; } // Add static label for "Props" int prop_label_index = m_wndToolBar.CommandToIndex(ID_NEW_PROP_TYPE) - 1; m_wndToolBar.SetButtonInfo(prop_label_index, ID_STATIC_PROP_LABEL, TBBS_SEPARATOR, 60); m_wndToolBar.GetItemRect(prop_label_index, &rect); rect.top = 3; rect.bottom = rect.top + 20; if (!m_prop_label.Create(_T("Props"), WS_VISIBLE | WS_CHILD, rect, &m_wndToolBar)) { TRACE0("Failed to create 'Props' label\n"); return -1; } // Create the props combo box zz = m_wndToolBar.CommandToIndex(ID_NEW_PROP_TYPE); Assert(zz != -1); m_wndToolBar.SetButtonInfo(zz, ID_NEW_PROP_TYPE, TBBS_SEPARATOR, 230); // Design guide advises 12 pixel gap between combos and buttons // m_wndToolBar.SetButtonInfo(1, ID_SEPARATOR, TBBS_SEPARATOR, 12); m_wndToolBar.GetItemRect(zz, &rect); rect.top = 3; rect.bottom = rect.top + 550; if (!m_new_prop_type_combo_box.Create(CBS_DROPDOWNLIST | WS_VISIBLE | WS_VSCROLL | CBS_HASSTRINGS | LBS_OWNERDRAWFIXED, rect, &m_wndToolBar, ID_NEW_PROP_TYPE)) { TRACE0("Failed to create new prop type combo-box\n"); return FALSE; } /* if (!m_wndStatusBar.Create(this) || !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))) { TRACE0("Failed to create status bar\n"); return -1; // fail to create } */ /* if (!m_wndStatusBar.Create(this, WS_CHILD | WS_VISIBLE | CBRS_BOTTOM, ID_MY_STATUS_BAR) || !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT)))*/ if (!m_wndStatusBar.Create(this) || !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators) / sizeof(UINT))) { TRACE0("Failed to create status bar\n"); return -1; } else { m_wndStatusBar.SetPaneInfo(0, 0, SBPS_STRETCH, 0); m_wndStatusBar.SetPaneInfo(1, 0, SBPS_NORMAL, 80); m_wndStatusBar.SetPaneInfo(2, 0, SBPS_NORMAL, 180); // m_wndStatusBar.SetPaneInfo(3, 0, SBPS_NORMAL, 100); m_wndStatusBar.SetPaneInfo(4, 0, SBPS_NORMAL, 130); } // TODO: Remove this if you don't want tool tips or a resizeable toolbar m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); // TODO: Delete these three lines if you don't want the toolbar to // be dockable m_wndToolBar.EnableDocking(CBRS_ALIGN_TOP | CBRS_ALIGN_BOTTOM); EnableDocking(CBRS_ALIGN_ANY); DockControlBar(&m_wndToolBar); Fred_main_wnd = this; Ship_editor_dialog.Create(); Prop_editor_dialog.Create(); Wing_editor_dialog.Create(); Waypoint_editor_dialog.Create(); Jumpnode_editor_dialog.Create(); Music_player_dialog.Create(); init_tools(); LoadBarState("Tools state"); return 0; } void CMainFrame::OnDestroy() { Fred_main_wnd = NULL; CFrameWnd::OnDestroy(); } void CMainFrame::apply_menu_layout(bool classic) { CMenu menu; if (!menu.LoadMenu(classic ? IDR_MAINMENU_CLASSIC : IDR_MAINMENU)) return; // grab the menu currently on the frame so we can free it after the swap CMenu *old_menu = GetMenu(); SetMenu(&menu); m_hMenuDefault = menu.GetSafeHmenu(); // keep MFC's fallback handle in sync so the bar isn't reverted later menu.Detach(); // the frame now owns the new menu // destroy the menu we just replaced to avoid a GDI leak if (old_menu != nullptr && old_menu->GetSafeHmenu() != nullptr) old_menu->DestroyMenu(); DrawMenuBar(); } void CMainFrame::OnFileMissionnotes() { CMissionNotesDlg dlg; dlg.DoModal(); } void CMainFrame::OnFredHelp() { // try included documentation auto res = cf_find_file_location("index.html", CF_TYPE_FREDDOCS); // We need an actual file location so VP files are not valid if (res.found) { if (res.offset == 0) { url_launch(res.full_name.c_str()); return; } } // try online as a fallback url_launch("https://fredzone.hard-light.net/freddocs/"); } void CMainFrame::OnInitMenu(CMenu* pMenu) { int i; CString str; extern SCP_vector ID_SHOW_IFF; if (Undo_available && !FREDDoc_ptr->undo_desc[1].IsEmpty()) str = "Undo " + FREDDoc_ptr->undo_desc[1] + "\tCtrl+Z"; else str = "Undo\tCtrl+Z"; if (pMenu->GetMenuState(ID_EDIT_UNDO, MF_BYCOMMAND) != -1) pMenu->ModifyMenu(ID_EDIT_UNDO, MF_BYCOMMAND, ID_EDIT_UNDO, str); // Goober5000 - do the IFF menu options for (i = 0; i < (int)ID_SHOW_IFF.size(); i++) { //This should eventually be properly dynamic as well if (i < (int)Iff_info.size()) { char text[NAME_LENGTH + 7]; sprintf(text, "Show %s", Iff_info[i].iff_name); pMenu->ModifyMenu(ID_SHOW_IFF[i], MF_BYCOMMAND | MF_STRING, ID_SHOW_IFF[i], text); } else { pMenu->DeleteMenu(ID_SHOW_IFF[i], MF_BYCOMMAND); } } CFrameWnd::OnInitMenu(pMenu); } void CMainFrame::OnLButtonUp(UINT nFlags, CPoint point) { CFrameWnd::OnLButtonUp(nFlags, point); } LRESULT CMainFrame::OnMenuPopupTest(WPARAM wParam, LPARAM lParam) { CMenu menu; CPoint point; point = *((CPoint*) lParam); ClientToScreen(&point); menu.LoadMenu(IDR_MENU1); menu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this); return 0L; } void CMainFrame::OnMenuPopupToggle1() { if (Toggle1_var == 0) Toggle1_var = 1; else Toggle1_var = 0; } void CMainFrame::OnMikeGridcontrol() { CGrid dlg; dlg.DoModal(); } void CMainFrame::OnNewShipTypeChange() { if (Fred_view_wnd) Fred_view_wnd->SetFocus(); } void CMainFrame::OnRButtonDown(UINT nFlags, CPoint point) { Global_point2 = point; PostMessage(WM_MENU_POPUP_TEST, nFlags, (int) &Global_point2); CFrameWnd::OnRButtonDown(nFlags, point); } void CMainFrame::OnUpdateLeft(CCmdUI* pCmdUI) { pCmdUI->Enable(::GetKeyState(VK_LBUTTON) < 0); } void CMainFrame::OnUpdateMenuPopupToggle1(CCmdUI* pCmdUI) { pCmdUI->SetCheck(Toggle1_var); } void CMainFrame::OnUpdateRight(CCmdUI* pCmdUI) { pCmdUI->Enable(::GetKeyState(VK_RBUTTON) < 0); } void CMainFrame::OnUpdateViewStatusBar(CCmdUI* pCmdUI) { pCmdUI->SetCheck((m_wndStatusBar.GetStyle() & WS_VISIBLE) != 0); } void CMainFrame::OnViewStatusBar() { m_wndStatusBar.ShowWindow((m_wndStatusBar.GetStyle() & WS_VISIBLE) == 0); RecalcLayout(); } BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs return CFrameWnd::PreCreateWindow(cs); } int color_combo_box_prop::CalcMinimumItemHeight() { int nResult = 1; if ((GetStyle() & (LBS_HASSTRINGS | LBS_OWNERDRAWFIXED)) == (LBS_HASSTRINGS | LBS_OWNERDRAWFIXED)) { CClientDC dc(this); CFont* pOldFont = dc.SelectObject(GetFont()); TEXTMETRIC tm; VERIFY(dc.GetTextMetrics(&tm)); dc.SelectObject(pOldFont); nResult = tm.tmHeight; } return nResult; } void color_combo_box_prop::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { int m_cyText = 24; CString strText; // You must override DrawItem and MeasureItem for LBS_OWNERDRAWVARIABLE ASSERT((GetStyle() & (LBS_OWNERDRAWFIXED | CBS_HASSTRINGS)) == (LBS_OWNERDRAWFIXED | CBS_HASSTRINGS)); CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); if ((lpDrawItemStruct->itemID >= 0) && (lpDrawItemStruct->itemAction & (ODA_DRAWENTIRE | ODA_SELECT))) { prop_info* pip = nullptr; // get the ship class corresponding to this item, if any auto itemData = lpDrawItemStruct->itemData; if (itemData >= 0 && itemData < Prop_info.size()) { pip = &Prop_info[itemData]; } int cyItem = GetItemHeight(lpDrawItemStruct->itemID); BOOL fDisabled = !IsWindowEnabled(); COLORREF newTextColor = RGB(0x80, 0x80, 0x80); // light gray if (!fDisabled) { if (pip == nullptr) newTextColor = RGB(0, 0, 0); else { auto cinfo = prop_get_category(pip->category_index); if (cinfo != nullptr) { newTextColor = RGB(cinfo->list_color.red, cinfo->list_color.green, cinfo->list_color.blue); } } } COLORREF oldTextColor = pDC->SetTextColor(newTextColor); COLORREF newBkColor = GetSysColor(COLOR_WINDOW); COLORREF oldBkColor = pDC->SetBkColor(newBkColor); if (newTextColor == newBkColor) { newTextColor = RGB(0xC0, 0xC0, 0xC0); // dark gray } if (!fDisabled && ((lpDrawItemStruct->itemState & ODS_SELECTED) != 0)) { pDC->SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT)); pDC->SetBkColor(GetSysColor(COLOR_HIGHLIGHT)); } if (m_cyText == 0) { VERIFY(cyItem >= CalcMinimumItemHeight()); } if (pip != nullptr) { strText = _T(pip->name.c_str()); } else { if (prop_type_combo_box_size == 0) { strText = _T("No props available"); } else { strText = _T("Invalid index!"); } } pDC->ExtTextOut(lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.top + std::max(0, (cyItem - m_cyText) / 2), ETO_OPAQUE, &(lpDrawItemStruct->rcItem), strText, strText.GetLength(), NULL); pDC->SetTextColor(oldTextColor); pDC->SetBkColor(oldBkColor); } if ((lpDrawItemStruct->itemAction & ODA_FOCUS) != 0) { pDC->DrawFocusRect(&(lpDrawItemStruct->rcItem)); } } void color_combo_box_prop::MeasureItem(LPMEASUREITEMSTRUCT) { // You must override DrawItem and MeasureItem for LBS_OWNERDRAWVARIABLE ASSERT((GetStyle() & (LBS_OWNERDRAWFIXED | CBS_HASSTRINGS)) == (LBS_OWNERDRAWFIXED | CBS_HASSTRINGS)); } int color_combo_box_prop::GetPropClass(int item_index) { if (item_index < 0 || item_index >= GetCount()) return -1; return (int)GetItemData(item_index); } int color_combo_box_prop::GetItemIndex(int prop_class) { for (int i = 0; i < m_new_prop_type_combo_box.GetCount(); i++) if ((int)m_new_prop_type_combo_box.GetItemData(i) == prop_class) return i; return -1; } int color_combo_box::CalcMinimumItemHeight() { int nResult = 1; if ((GetStyle() & (LBS_HASSTRINGS | LBS_OWNERDRAWFIXED)) == (LBS_HASSTRINGS | LBS_OWNERDRAWFIXED)) { CClientDC dc(this); CFont* pOldFont = dc.SelectObject(GetFont()); TEXTMETRIC tm; VERIFY(dc.GetTextMetrics(&tm)); dc.SelectObject(pOldFont); nResult = tm.tmHeight; } return nResult; } void color_combo_box::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { int m_cyText = 24; CString strText; // You must override DrawItem and MeasureItem for LBS_OWNERDRAWVARIABLE ASSERT((GetStyle() & (LBS_OWNERDRAWFIXED | CBS_HASSTRINGS)) == (LBS_OWNERDRAWFIXED | CBS_HASSTRINGS)); CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); if ((lpDrawItemStruct->itemID >= 0) && (lpDrawItemStruct->itemAction & (ODA_DRAWENTIRE | ODA_SELECT))) { ship_info* sip = nullptr; // get the ship class corresponding to this item, if any auto itemData = lpDrawItemStruct->itemData; if (itemData >= 0 && itemData < Ship_info.size()) sip = &Ship_info[itemData]; int cyItem = GetItemHeight(lpDrawItemStruct->itemID); BOOL fDisabled = !IsWindowEnabled(); COLORREF newTextColor = RGB(0x80, 0x80, 0x80); // light gray if (!fDisabled) { if (sip == nullptr) newTextColor = RGB(0, 0, 0); else { auto sinfo = &Species_info[sip->species]; newTextColor = RGB(sinfo->fred_color.rgb.r, sinfo->fred_color.rgb.g, sinfo->fred_color.rgb.b); } } COLORREF oldTextColor = pDC->SetTextColor(newTextColor); COLORREF newBkColor = GetSysColor(COLOR_WINDOW); COLORREF oldBkColor = pDC->SetBkColor(newBkColor); if (newTextColor == newBkColor) newTextColor = RGB(0xC0, 0xC0, 0xC0); // dark gray if (!fDisabled && ((lpDrawItemStruct->itemState & ODS_SELECTED) != 0)) { pDC->SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT)); pDC->SetBkColor(GetSysColor(COLOR_HIGHLIGHT)); } if (m_cyText == 0) VERIFY(cyItem >= CalcMinimumItemHeight()); if (sip != nullptr) strText = _T(sip->name); else if (lpDrawItemStruct->itemID == Id_select_type_jump_node) strText = _T("Jump Node"); else if (lpDrawItemStruct->itemID == Id_select_type_waypoint) strText = _T("Waypoint"); else strText = _T("Invalid index!"); pDC->ExtTextOut(lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.top + std::max(0, (cyItem - m_cyText) / 2), ETO_OPAQUE, &(lpDrawItemStruct->rcItem), strText, strText.GetLength(), NULL); pDC->SetTextColor(oldTextColor); pDC->SetBkColor(oldBkColor); } if ((lpDrawItemStruct->itemAction & ODA_FOCUS) != 0) pDC->DrawFocusRect(&(lpDrawItemStruct->rcItem)); } void color_combo_box::MeasureItem(LPMEASUREITEMSTRUCT) { // You must override DrawItem and MeasureItem for LBS_OWNERDRAWVARIABLE ASSERT((GetStyle() & (LBS_OWNERDRAWFIXED | CBS_HASSTRINGS)) == (LBS_OWNERDRAWFIXED | CBS_HASSTRINGS)); } int color_combo_box::GetShipClass(int item_index) { if (item_index < 0 || item_index >= GetCount()) return -1; return (int)GetItemData(item_index); } int color_combo_box::GetItemIndex(int ship_class) { for (int i = 0; i < m_new_ship_type_combo_box.GetCount(); i++) if ((int)m_new_ship_type_combo_box.GetItemData(i) == ship_class) return i; return -1; } bool url_launch(const char *url) { int r; r = (int) ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOW); if (r < 32) { const char *txt = NULL; switch (r) { case 0: txt = XSTR("The operating system is out of memory or resources.", 1107); break; case ERROR_BAD_FORMAT: txt = XSTR("The .EXE file is invalid (non-Win32 .EXE or error in .EXE image).", 1108); break; case SE_ERR_ACCESSDENIED: txt = XSTR("The operating system denied access to the specified file. ", 1109); break; case SE_ERR_ASSOCINCOMPLETE: txt = XSTR("The filename association is incomplete or invalid.\r\n(You need to have a default Internet browser installed)", 1110); break; case SE_ERR_DDEBUSY: txt = XSTR("The DDE transaction could not be completed because other DDE transactions were being processed.", 1111); break; case SE_ERR_DDEFAIL: txt = XSTR("The DDE transaction failed.", 1112); break; case SE_ERR_DDETIMEOUT: txt = XSTR("The DDE transaction could not be completed because the request timed out.", 1113); break; case SE_ERR_DLLNOTFOUND: txt = XSTR("The specified dynamic-link library was not found.", 1114); break; case SE_ERR_OOM: txt = XSTR("There was not enough memory to complete the operation.", 1115); break; case SE_ERR_SHARE: txt = XSTR("A sharing violation occurred.", 1116); break; // No browser installed message case SE_ERR_NOASSOC: txt = XSTR("\r\nNo web browser found. There isn't one installed or if \r\none is installed, it isn't set to be the default browser.\r\n\r\n", 1117); break; case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: txt = XSTR("\r\nUnable to locate Fred Help file: \\data\\freddocs\\index.html\r\n", 1479); break; default: txt = XSTR("Unknown error occurred.", 1118); break; } AfxMessageBox(txt, MB_OK | MB_ICONERROR); return false; } return true; }