Исходник, когда-то написанного кода под этот макеет. По факту, 70% работы уже сделано) Но я уже наврят-ли буду этим заниматься. Так что при желании - любой может продолжить
Code:
#define _H3API_PATCHER_X86_
#include "../../Headers/H3API.hpp"
#include "era.h"
#include "era dialogs.h"
using namespace h3;
using namespace NH3Dlg;
using namespace EraDlg;
#define FUN
Patcher* _P;
PatcherInstance* _PI;
//CHAR myString[1024];
//#define MyString (PCHAR)myString
const char* CHECKBOX_DEF = "checkbox.def";
const char* RADIOBTN_DEF = "radiobttn.def";
#define RGB_FRAME_COLOR 0x78D4E8
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
/*
* Макет диалога выбора.
* Предполагается постраничная навигация, переход на страницы влево/вправо,
* если пункты не вместились в одну страницу, опциональный переход наверх
* (содержание или уровень выше в помощи, например), опциональная кнопка отмены.
* Шрифт 15 пикс, поддержка картинок через разметку Эры вида {~>....} до 44 пикс (реально и до 50 пикс).
* Один экран — до 8 пунктов.
* Щелчок по любому пространству между разделителями активирует пункт.
* Помещаются все слоты героя или 8 уровней жилищ города.
* Вмещаются дефы артефактов и трёхстрочные тексты пунктов/заголовка
* По клавишам 1-8 можно выбрать любой пункт (для галочек вкл/выкл).
* Стрелки влево, вправо, вверх активируют соответствующие кнопки. Enter/ESC тоже.
* Шрифт medfont.fnt или times08r.fnt. Пока нет поддержки нормальных шрифтов фиксированных размеров.
* Если подтвердим макет, напишу тогда программную спецификацию: структуру инициализации и нужные функции для экспорта.
* CTRL клавишу отслеживаем при щелчках по кнопкам или текущей позиции в постраничной навигации.
* CTRL + Лево будет на первую,
* CTRL + право — на последнюю.
* Home - первая страница,
* End — последняя.
* Вверх — на уровень вверх.
* "A" — выделить все, или, если все уже выделены, снять выделение со всех (в режиме галочек)
*/
// создание процесса диалога
INT32 __stdcall igrikDlgProc(H3Dlg* dlg, H3Msg* msg)
{
if(msg->IsLeftDown() && msg->flags == H3Msg::MessageFlag::MF_Null && msg->item_id >= 10 && msg->item_id <= 18)
{
H3DlgDefButton* button = (H3DlgDefButton*)dlg->GetH3DlgItem(msg->item_id +10);
if (button)
button->Press(msg);
}
if (msg->IsRightClick())
{
sprintf(MyString, "itemID: %d", msg->item_id);
F_MsgBox(MyString, 4);
}
return dlg->DefaultProc(msg);
}
INT32 __stdcall showSelectDialog(TSelectDlgConfig* dlgConfig)
{
////////////////////////////////////
//
// базовые координаты и параметры диалога
//
////////////////////////////////////
INT32 width = 440;
INT32 height = 548;
INT32 startX = 24;
INT32 startY = 88;
INT32 deltaY = 50;
INT32 itemWidth = width - (startX*2);
H3Dlg dlg(width, height, -1, -1, FALSE, igrikDlgProc);
/////////////////////////////////////////////////////////
//
// дополнительные элементы: ОК, ОТМЕНА и другие элементы
//
////////////////////////////////////////////////////////
// заголовок (id: 3)
dlg.CreateText(startX, 22, itemWidth, 62, dlgConfig->caption, Text::MEDIUM, TextColor::REGULARY, 3, TextAlignment::MiddleCenter, 0);
// dlg.CreateFrame(dlg.GetH3DlgItem(3), RGB_FRAME_COLOR, 100, 1);
// кнопка навигации влево (id: 4)
if ( dlgConfig->flags & TSelectDlgFlags::SELECT_DLG_LEFT_BTN )
dlg.CreateButton(width/2 -72, height -52, 44, 44, 4, "ADAG.DEF", 15, 40, 0, NH3VKey::H3VK_LEFT);
// кнопка навигации враво (id: 5)
if ( dlgConfig->flags & TSelectDlgFlags::SELECT_DLG_RIGHT_BTN )
dlg.CreateButton(width/2 +28, height -52, 44, 44, 5, "ADAG.DEF", 11, 36, 0, NH3VKey::H3VK_RIGHT);
// кнопка навигации вверх (id: 6)
if ( dlgConfig->flags & TSelectDlgFlags::SELECT_DLG_UP_BTN )
dlg.CreateButton(width/2 -22, height -52, 44, 44, 6, "ADAG.DEF", 9, 34, 0, NH3VKey::H3VK_UP);
// текст отображения страниц "1/3" (id: 9)
if ( dlgConfig->flags & TSelectDlgFlags::SELECT_DLG_PAGE_NAV ) {
sprintf(MyString, "%d/%d", dlgConfig->page, dlgConfig->numPages);
dlg.CreateText(width -60, height -48, 40, 30, MyString, Text::SMALL, TextColor::REGULAR, 9, TextAlignment::MiddleCenter, 0);
}
// Cancel-рамка (id: 30626) и Cancel-кнопка (id: 30726)
if ( dlgConfig->flags & TSelectDlgFlags::SELECT_DLG_CANCEL_BTN )
dlg.CreateCancelButton(width -70 -64, height -52);
// Ok-рамка (id: 30625) и Ok-кнопка (id: 30725)
if (dlgConfig->flags & TSelectDlgFlags::SELECT_DLG_REQUIRE_ITEM )
dlg.CreateOKButton(60, height -52)->Disable();
else dlg.CreateOKButton(60, height -52);
/////////////////////////////////////////////////////////
//
// тексты (id: 10...18)
// кнопки (id: 20...28)
// разделители (id: 0)
//
////////////////////////////////////////////////////////
dlg.CreateLineSeparator(startX-1, startY -1, itemWidth);
dlg.CreateLineSeparatorYellow(startX, startY, itemWidth);
for (int i = 0; i < dlgConfig->numItems; i++)
{
dlg.CreateLineSeparator(startX-1, deltaY*(i+1) +startY -1, itemWidth);
dlg.CreateLineSeparatorYellow(startX, deltaY*(i+1) +startY, itemWidth);
sprintf(MyString, "{~>un44.def:%d valign=middle} itemCaptions[%d]: Each is null-terminated string.", 250+i, i);
dlg.CreateText(50, deltaY*i + startY , itemWidth -26, deltaY, MyString,
Text::SMALL, TextColor::REGULAR, 10+i, TextAlignment::MiddleLeft, 0);
// dlg.CreateFrame(50, deltaY*i + startY, itemWidth -26, deltaY, 0xFFD700);
H3DlgDefButton* b = dlg.CreateButton(startX, deltaY*i +startY + 18, 16, 16, /* id */ 20+i, Assets::RADIOBTN_DEF, 0, 1, 0, 2+i);
}
// стартуем диалог (после выполнения уничтожается автоматически)
dlg.Start();
return 1;
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
#ifdef FUN
void ShowNewDialog()
{
// создаём структуру диалога
TSelectDlgConfig* dlgConfig = new TSelectDlgConfig;
dlgConfig->caption = "Выберите монстра, которого вы ненавидели с детства, которого не любила Ваша мама, Ваш брат и Ваша собака. Выберите его и принесите в жертву Одину.";
dlgConfig->isMultiple = false;
dlgConfig->flags = 31;
dlgConfig->numItems = 8;
dlgConfig->page = 1;
dlgConfig->numPages = 8;
//dlgConfig->itemCaptions[0] = "text: itemCaptions[0]";
//dlgConfig->itemStates[0] = 1;
showSelectDialog(dlgConfig);
// очищаем выделенную память ...
delete dlgConfig;
}
INT32 __stdcall Y_AdvMgr_KeyDown(HiHook* h, H3AdventureManager* advMgr, H3Msg* msg, INT32 x, INT32 y, INT32 ptrIsHuman)
{
INT32 result = THISCALL_5(INT32, h->GetDefaultFunc(), advMgr, msg, x, y, ptrIsHuman);
if (result)
{
switch(msg->subtype)
{
case NH3VKey::H3VK_5:
// F_sprintf("count: %d \n type: %d", mon->count, mon->type);
// F_MessageBox("Start TSelectDlgResult");
ShowNewDialog();
break;
default:
break;
}
}
return result;
}
INT32 __stdcall Y_DlgMainMenu_Proc(HiHook* hook, H3Msg* msg)
{
if ( msg->IsKeyDown())
{
if ( msg->subtype == NH3VKey::H3VK_T )
{
F_VideoPause();
ShowNewDialog();
F_VideoContinue();
}
}
return THISCALL_1(INT32, hook->GetDefaultFunc(), msg);
}
#endif FUN
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
void HooksInit()
{
#ifdef FUN
// нажатие клавиши на карте приключений
_PI->WriteHiHook(0x4FBDA0, SPLICE_, EXTENDED_, THISCALL_, Y_DlgMainMenu_Proc);
_PI->WriteHiHook(0x4089DC, CALL_, EXTENDED_, THISCALL_, Y_AdvMgr_KeyDown);
#endif FUN
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
const char* PLUGIN_NAME = "era dialogs";
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
static BOOL pluginOn = FALSE;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
if (!pluginOn)
{
_P = GetPatcher();
_PI = _P->CreateInstance(PLUGIN_NAME);
HooksInit();
}
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}