158 lines
5.3 KiB
C++
158 lines
5.3 KiB
C++
|
|
#include "pc.menus.hpp"
|
|
#include <map>
|
|
#include <SFML/Graphics/RenderWindow.hpp>
|
|
#include "pcresource.h"
|
|
#include "universe.hpp"
|
|
#include "winutil.hpp"
|
|
#include "menu_accel.win.hpp"
|
|
|
|
// Include this last because some #defines in the Windows headers cause compile errors in my headers.
|
|
// Fortunately they're on symbols not used in this file, so this should work.
|
|
#include <windows.h>
|
|
|
|
// This is the index of each menu on the menubar
|
|
enum {
|
|
FILE_MENU_POS = 0,
|
|
PARTY_MENU_POS = 1,
|
|
SCEN_MENU_POS = 2,
|
|
HELP_MENU_POS = 3,
|
|
};
|
|
|
|
extern sf::RenderWindow mainPtr;
|
|
extern cUniverse univ;
|
|
extern bool scen_items_loaded, party_in_scen;
|
|
extern fs::path file_in_mem;
|
|
LONG_PTR mainProc;
|
|
HMENU menuHandle = NULL;
|
|
accel_table_t accel;
|
|
std::map<int,eMenu> menuChoices;
|
|
|
|
LRESULT CALLBACK menuProc(HWND handle, UINT message, WPARAM wParam, LPARAM lParam);
|
|
|
|
void setMenuCommand(HMENU& menu, int i, eMenu cmd) {
|
|
static char title[256];
|
|
MENUITEMINFOA item;
|
|
item.cbSize = sizeof(MENUITEMINFOA);
|
|
item.cch = 255;
|
|
item.dwTypeData = title;
|
|
item.fMask = MIIM_ID | MIIM_FTYPE | MIIM_STRING;
|
|
GetMenuItemInfoA(menu, i++, true, &item);
|
|
if(item.fType == MFT_SEPARATOR) return;
|
|
menuChoices[item.wID] = cmd;
|
|
// Now set up the accelerator, if any
|
|
std::string item_name = item.dwTypeData;
|
|
size_t pos = item_name.find_last_of('\t');
|
|
if(pos == std::string::npos) return;
|
|
pos++;
|
|
if(pos >= item_name.size()) return;
|
|
std::string key_name = item_name.substr(pos);
|
|
accel.add(item.wID, key_name);
|
|
}
|
|
|
|
void init_menubar() {
|
|
HWND winHandle = mainPtr.getSystemHandle();
|
|
if(winHandle == NULL) return;
|
|
if(menuHandle == NULL)
|
|
menuHandle = LoadMenu(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_MENU1));
|
|
SetMenu(winHandle, menuHandle);
|
|
// Now we have to do a little hack to handle menu messages.
|
|
// We replace SFML's window procedure with our own, which checks for menu events and then forwards to SFML's procedure.
|
|
mainProc = SetWindowLongPtr(winHandle, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&menuProc));
|
|
// Fix the window's viewport so that everything is drawn correctly
|
|
sf::Vector2u sz = mainPtr.getSize();
|
|
double menubarHeight = getMenubarHeight();
|
|
double usableHeight = sz.y - menubarHeight;
|
|
sf::View view(sf::FloatRect(0, 0, sz.x, usableHeight));
|
|
mainPtr.setView(view);
|
|
|
|
// And now initialize the mapping from Windows menu commands to eMenu constants
|
|
static bool inited = false;
|
|
if(inited) return;
|
|
inited = true;
|
|
|
|
static const eMenu file_choices[] = {
|
|
eMenu::FILE_OPEN, eMenu::FILE_CLOSE, eMenu::NONE, eMenu::FILE_SAVE, eMenu::FILE_SAVE_AS, eMenu::FILE_REVERT, eMenu::NONE, eMenu::QUIT,
|
|
};
|
|
static const eMenu party_choices[] = {
|
|
eMenu::EDIT_GOLD, eMenu::EDIT_FOOD, eMenu::EDIT_ALCHEMY, eMenu::NONE,
|
|
eMenu::HEAL_DAMAGE, eMenu::RESTORE_MANA, eMenu::RAISE_DEAD, eMenu::CURE_CONDITIONS, eMenu::NONE,
|
|
eMenu::EDIT_MAGE, eMenu::EDIT_PRIEST, eMenu::EDIT_ITEM, eMenu::EDIT_TRAITS, eMenu::EDIT_SKILLS, eMenu::EDIT_XP, eMenu::NONE,
|
|
eMenu::REUNITE_PARTY,
|
|
};
|
|
static const eMenu scen_choices[] = {
|
|
eMenu::EDIT_DAY, eMenu::NONE, eMenu::LEAVE_TOWN, eMenu::RESET_TOWNS, eMenu::ADD_OUT_MAPS, eMenu::ADD_TOWN_MAPS, eMenu::OWN_VEHICLES,
|
|
eMenu::NONE, eMenu::LEAVE_SCENARIO, eMenu::SET_SDF,
|
|
};
|
|
static const eMenu help_choices[] = {
|
|
eMenu::ABOUT, eMenu::HELP_TOC
|
|
};
|
|
|
|
HMENU file_menu = GetSubMenu(menuHandle, FILE_MENU_POS);
|
|
HMENU party_menu = GetSubMenu(menuHandle, PARTY_MENU_POS);
|
|
HMENU scen_menu = GetSubMenu(menuHandle, SCEN_MENU_POS);
|
|
HMENU help_menu = GetSubMenu(menuHandle, HELP_MENU_POS);
|
|
|
|
int i = 0;
|
|
for(eMenu opt : file_choices)
|
|
setMenuCommand(file_menu, i++, opt);
|
|
i = 0;
|
|
for(eMenu opt : party_choices)
|
|
setMenuCommand(party_menu, i++, opt);
|
|
i = 0;
|
|
for(eMenu opt : scen_choices)
|
|
setMenuCommand(scen_menu, i++, opt);
|
|
i = 0;
|
|
for(eMenu opt : help_choices)
|
|
setMenuCommand(help_menu, i++, opt);
|
|
|
|
accel.build();
|
|
}
|
|
|
|
void menu_activate() {
|
|
if(menuHandle == NULL) return;
|
|
HMENU file_menu = GetSubMenu(menuHandle, FILE_MENU_POS);
|
|
if(file_in_mem.empty()) {
|
|
EnableMenuItem(menuHandle, PARTY_MENU_POS, MF_BYPOSITION | MF_GRAYED);
|
|
EnableMenuItem(menuHandle, SCEN_MENU_POS, MF_BYPOSITION | MF_GRAYED);
|
|
for(int i = 1; i < GetMenuItemCount(file_menu) - 1; i++)
|
|
EnableMenuItem(file_menu, i, MF_BYPOSITION | MF_GRAYED);
|
|
} else {
|
|
EnableMenuItem(menuHandle, PARTY_MENU_POS, MF_BYPOSITION | MF_ENABLED);
|
|
EnableMenuItem(menuHandle, SCEN_MENU_POS, MF_BYPOSITION | (party_in_scen ? MF_ENABLED : MF_GRAYED));
|
|
for(int i = 1; i < GetMenuItemCount(file_menu) - 1; i++)
|
|
EnableMenuItem(file_menu, i, MF_BYPOSITION | MF_ENABLED);
|
|
}
|
|
DrawMenuBar(mainPtr.getSystemHandle());
|
|
}
|
|
|
|
#include "cursors.hpp"
|
|
|
|
LRESULT CALLBACK menuProc(HWND handle, UINT message, WPARAM wParam, LPARAM lParam) {
|
|
MSG msg = {handle, message, wParam, lParam};
|
|
if(HIWORD(wParam) != 1 || message != WM_COMMAND) {
|
|
if(TranslateAccelerator(handle, accel.handle, &msg))
|
|
return 0;
|
|
}
|
|
if(message == WM_COMMAND) {
|
|
int cmd = LOWORD(wParam);
|
|
handle_menu_choice(menuChoices[cmd]);
|
|
} else if(message == WM_SETCURSOR) {
|
|
// Windows resets the cursor to an arrow whenever the mouse moves, unless we do this.
|
|
// Note: By handling this message, sf::Window::setMouseCursorVisible() will NOT work.
|
|
restore_cursor();
|
|
return true;
|
|
}
|
|
return CallWindowProc(reinterpret_cast<WNDPROC>(mainProc), handle, message, wParam, lParam);
|
|
}
|
|
|
|
bool menuBarProcessEvent(const sf::Event&) {
|
|
return false;
|
|
}
|
|
|
|
void drawMenuBar() {
|
|
}
|
|
|
|
void set_up_apple_events() {
|
|
}
|