Исходник, когда-то написанного кода под этот макеет. По факту, 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;
}