[MFC] CMenuXML/CHotKeysXML - меню/акселераторы на основе XML
От: SchweinDeBurg Россия http://zarezky.spb.ru/
Дата: 17.01.05 07:29
Оценка:
В продолжение темы XML-based интерфейсов, начатой [MFC] CDailogXML — диалог на основе XML-"шаблона"
Автор: SchweinDeBurg
Дата: 10.01.05
, еще два класса — CMenuXML и CHotKeysXML.

CMenuXML

Данный класс является потомком CMenu и предназначен для построения меню на основе XML-"шаблона" следующего вида:

<?xml version="1.0" encoding="Windows-1251"?>
<Menu>
    <Popup Text="File">
        <Item Text="New" ID="40001"/>
        <Item Text="Open..." ID="40002"/>
        <Item Text="Save" ID="40003"/>
        <Item Text="Save As..." ID="40004"/>
        <Item Type="Separator"/>
        <Item Text="Page Setup..." ID="40005"/>
        <Item Text="Print..." ID="40006"/>
        <Item Type="Separator"/>
        <Item Text="Exit" ID="40007"/>
    </Popup>
    ...
</Menu>

Для создания меню используется метод

BOOL CreateMenuXML(LPCTSTR pszMenuName);

Через параметр pszMenuName в него необходимо передать "имя" меню, определяющее имя XML-файла (без расширения ".xml"), содержащего информацию об элементах меню и их иерархии. Пример использования:

int CMainFrame::OnCreate(CREATESTRUCT* lpCS)
{
    CMenuXML menuMain;

    if (CFrameWnd::OnCreate(lpCS) != -1) {
        menuMain.CreateMenuXML(_T("MainMenu"));
        SetMenu(&menuMain);
        menuMain.Detach();
        return (0);
    }
    else {
        return (-1);
    }
}

CHotKeysXML

Данный класс является потомком CObject и предназначен для создания таблицы акселераторов на основе XML-"шаблона" следующего вида:

<?xml version="1.0" encoding="Windows-1251"?>
<HotKeys>
    <HotKey ID="40001" Text="Ctrl+N"/>
    <HotKey ID="40002" Text="Ctrl+O"/>
    ...
</HotKeys>

Для создания таблицы акселераторов используется метод

BOOL CreateTable(LPCTSTR pszTableName);

Через параметр pszTableName в него необходимо передать "имя" таблицы, определяющее имя XML-файла (без расширения ".xml"), содержащего информацию о связи акселераторов с идентификаторами команд.

Для "связывания" созданного набора "горячих" клавиш с заданным окном (потомком CFrameWnd) используется метод

void AttachToFrame(CFrameWnd* pFrameWnd, BOOL fShowInMenu = TRUE);

Параметр fShowInMenu определяет, нужно ли дополнить тексты команд главного меню окна pFrameWnd информацией о соответствующих им акселераторах. Пример использования:

class CMainFrame: public CFrameWnd
{
...
    CHotKeysXML m_hotKeys;
};

...

int CMainFrame::OnCreate(CREATESTRUCT* lpCS)
{
    CMenuXML menuMain;

    if (CFrameWnd::OnCreate(lpCS) != -1) {
        menuMain.CreateMenuXML(_T("MainMenu"));
        SetMenu(&menuMain);
        menuMain.Detach();
        m_hotKeys.CreateTable(_T("HotKeys"));
        m_hotKeys.AttachToFrame(this);
        return (0);
    }
    else {
        return (-1);
    }
}

Заметим, что классы CMenuXML и CHotKeysXML никак не связаны друг с другом и могут использоваться совершенно независимо.

Средства реализации и библиотеки:

Демонстрационный проект: XMLMenus.zip (~48 Кб)

"Ключевые" файлы:

Детали реализации

В XML-файле, описывающем меню, допустимы следующие тэги:


Путь к XML-файлу, описывающему меню, определяется в методе
virtual void GetXMLpath(CString& strDest);
и "по умолчанию" строится следующим образом:
%AppData% \ AfxGetApp()->m_pszRegistryKey \ AfxGetAppName() \
Обратите внимание, что данная реализация GetXMLpath() предполагает, что в методе InitInstance() объекта-приложения был выполнен вызов
SetRegistryKey(_T("VendorName_Or_CompanyName"));

Создание в памяти шаблона меню выполняет метод
static const MENUTEMPLATE* CreateMenuExTemplate(LPCTSTR pszFileXML);
Поскольку он является статическим, им можно воспользоваться, не создавая экземпляра CMenuXML, а просто передав возвращенное значение в вызов CMenu::LoadMenuIndirect() — что собственно и делается в CMenuXML::CreateMenuXML() .

Если папка, в которой должен находиться XML-файл, или сам этот файл отсутствуют, то в методе CMenuXML::CreateMenuXML() выполняется их создание; при этом в исполняемом файле приложения или одной из загруженных им MFC extension DLLs должен находиться ресурс типа "MENU_XML", имя которого совпадает с именем меню, переданным в вызов CreateMenuXML() (более подробно детали этого механизма описаны в [MFC] CDialogXML &mdash; rev. 3
Автор: SchweinDeBurg
Дата: 14.01.05
).

В XML-файле, описывающем акселераторы, допустимы следующие тэги:


При разборе атрибутов каждого тэга <HotKey> используется следующая логика:

  1. Вначале читается и запоминается значение атрибута "Text".

  2. Затем выполняется чтение атрибута "Code". Если он присутствует и имеет корректное ненулевое значение, то предполагается, что младшее слово содержит код виртуальной клавиши (VK_*), а старшее — набор флагов HOTKEYF_* (это сделано для облегчения "интеграции" класса CHotKeysXML с элементом управленя "Hot Key"). Если же атрибут "Code" отсутствует или имеет некорректное значение, то код виртуальной клавиши и флаги-модификаторы определяются на основании значения атрибута "Text" — в методе CHotKeysXML::ParseHotKeyText().

  3. Завершающим шагом является чтение атрибута "ID".

Если папка, в которой должен находиться XML-файл, или сам этот файл отсутствуют, то в методе CHotKeysXML::CreateTable() выполняется их создание; при этом в исполняемом файле приложения или одной из загруженных им MFC extension DLLs должен находиться ресурс типа "HOTKEYS_XML", имя которого совпадает с именем таблицы, переданным в вызов CreateTable().
[ posted via RSDN@Home 1.1.4 beta 3 r281 ]
- Искренне ваш, Поросенок Пафнутий ~ ICQ#116846877
In Windows, there’s always a catch… © Paul DiLascia
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.