- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания Программирование на Visual C++. Архив рассылки - Алекс Jenter
Шрифт:
Интервал:
Закладка:
CComPtr<IXMLDOMNode> spXMLChildNode;
hr = spXMLDOM->createNode(CComVariant(NODE_ELEMENT), CComBSTR("xmlchildnode"), NULL, &spXMLChildNode);
if (FAILED(hr)) throw "Unable to create 'xmlchildnode' XML node";
if (spXMLChildNode.p == NULL) throw "Unable to create 'xmlchildnode' XML node";
Если парсеру удалось создать новый узел, следующий шаг – разместить его в дереве XML. Метод IXMLDOMNode::appendChild() – как раз то, что нам нужно.
CComPtr<IXMLDOMNode> spInsertedNode;
hr = spXMLNode->appendChild(spXMLChildNode, &spInsertedNode);
if (FAILED(hr)) throw "Unable to move 'xmlchildnode' XML node";
if (spInsertedNode.p == NULL) throw "Unable to move 'xmlchildnode' XML node";
Если родительский узел принял только что созданный узел в качестве дочернего, он вернёт вам ещё один экземпляр IXMLDOMNode, который представляет новый узел. На самом деле, этот новый узел и узел, который вы передали в appendChild(), в точности совпадают. Тем не менее, проверка указателя на добавленный дочерний узел может быть полезной, так как в случае ошибки он примет значение NULL.
Итак, мы уже нашли требуемый узел и добавили к нему дочерний узел; теперь посмотрим, как работать с атрибутами. Представьте себе, что вам нужно добавить к новому дочернему узлу атрибут:
xml="fun"
Сделать это не сложно, но вам придётся переключиться с IXMLDOMNode на IXMLDOMElement, чтобы поработать с узлом как с элементом. На практике это означает, что вам придётся запросить у интерфейса IXMLDOMNode связанный с ним интерфейс IXMLDOMElement, а потом, получив его, вызвать IXMLDOMElement::setAttribute():
CComQIPtr<IXMLDOMElement> spXMLChildElement;
spXMLChildElement = spInsertedNode;
if (spXMLChildElement.p == NULL)
throw "Unable to query for 'xmlchildnode' XML element interface";
hr = spXMLChildElement->setAttribute(CComBSTR(L"xml"), CComVariant(L"fun"));
if (FAILED(hr)) throw "Unable to insert new attribute";
Ну вот, мы модифицировали исходное XML-дерево, как нам этого хотелось. Приложение уже может сохранить документ на диск, но может сделать и что-нибудь ещё. Например, разыскать ещё один узел и отобразить на экране содержащийся в нём текст. Поскольку искать узлы мы уже умеем, перейдём прямо к извлечению данных.
Для извлечение данных предназначен метод IXMLDOMNode::get_nodeTypedValue(). Данные, которые содержит узел, можно задавать с использованием схемы типов фирмы Microsoft, поэтому вы без труда можете сохранять числа с плавающей точкой, целые числа, строки или любые другие поддерживаемые схемой данные. Тип данных задаётся с использованием атрибута dt:type, например:
<model dt:type="string">SL-2</model>
<year dt:type="int">1992</year>
Если некоторый узел содержит данные заданного типа, вы сможете извлечь их в нужном формате, используя get_nodeTypedValue(). Если тип не задан, по умолчанию он считается текстовым, и парсер вернёт вам VARIANT с содержащимся в нём BSTR. В нашем случае этого достаточно, поскольку узел, который мы ищем, является текстовым и действительно содержит строку. Если нужно, мы всегда сможем отконвертировать её в другое представление, используя средства типа atoi(). А пока просто извлечём строку и отобразим её.
CComVariant varValue(VT_EMPTY);
hr = spXMLNode->get_nodeTypedValue(&varValue);
if (FAILED(hr)) throw "Unable to retrieve 'xmltext' text";
if (varValue.vt == VT_BSTR) {
// Display the results... since we're not using the
// wide version of the STL, we need to convert the
// BSTR to ANSI text for display...
USES_CONVERSION;
LPTSTR lpstrMsg = W2T(varValue.bstrVal);
std::cout << lpstrMsg << std::endl;
} else {
// Some error
throw "Unable to retrieve 'xmltext' text";
}
Если нам удалось извлечь значение, связанное с узлом, и если оно оказалось именно того типа, который мы ожидаем (BSTR), мы выводим текст на экран. В противном случае просто выводится сообщение об ошибке. Но вы, в зависимости от ситуации, можете предпринять и другие действия.
Наша последняя задача – сохранить обновлённое XML-дерево на диск, что мы и делаем, используя IXMLDOMDocument::save():
hr = spXMLDOM->save(CComVariant("updatedxml.xml"));
if (FAILED(hr)) throw "Unable to save updated XML document";
Сохранив документ, программа выдаёт на экран короткое сообщение и завершается.
Эта демонстрационная программа вряд ли поразит ваше воображение. Вы могли бы сделать ещё очень много, но я надеюсь, что этот простой пример показал вам, как использовать MSXML в программах на языке C++. Сам по себе парсер – сложный продукт, и я настоятельно рекомендую вам использовать MSDN как справочное руководство по нему. Парсер предоставляет множество интерфейсов, каждый из которых обычно содержит большое количество методов. Несмотря на это, я широко использую парсер в своих проектах и теперь, поработав и поэкспериментировав с ним, нахожу его простым и удобным в использовании. Я надеюсь, что и вы найдёте ему, а также XML в целом, множество применений.
ВОПРОС-ОТВЕТ
Как разрешить перетаскивание окна за любую точку?
Автор: Алексей Кирюшкин
Демонстрационное приложение DragWin
Пример – приложение DragWin (диалоговое окошко, MFC) иллюстрирует два способа осуществить перемещение окна с захватом его не только за заголовок, но и за любую точку на клиентской области. Идея первого способа проста – при получении сообщения о перемещении мыши передвигаем наше окно в соответствии с новыми координатами. Второй способ поизящнее, и заключается в некотором "обмане" Windows, после которого она считает, что мышь находится над заголовоком окна, даже если реально это уже клиентсткая часть.
Способ 1Реализован для главного окна приложения. Заключается в написании собственных обработчиков нажатия (WM_LBUTTONDOWN), перемещения (WM_MOUSEMOVE) и отпускания (WM_LBUTTONUP) левой кнопки мыши. Обработчики на данные события устанавливаются стандартным образом – через MFC ClassWizard.
void CDragWinDlg::OnLButtonDown(UINT nFlags, CPoint point) {
// выставим флажок – пошло перетаскивание
m_bMoveWindow = TRUE;
// все сообщения от мыши - к нашему окну, независимо от координат
// чтобы мышь не улетала с окна при быстром движении
SetCapture();
// сохраняем координаты окна
GetWindowRect(m_RectDlg);
// сохраняем положение мышки внутри окна программы
ClientToScreen(&point);
m_MouseInDlg = point - m_RectDlg.TopLeft();
// меняем курсор, чтоб веселее было тащить
m_hCursor = m_hCursorDown;
::SetCursor(m_hCursor);
// вызываем обработчик по умолчанию
CDialog::OnLButtonDown(nFlags, point);
}
void CDragWinDlg::OnMouseMove(UINT nFlags, CPoint point) {
if (m_bMoveWindow) // надо тащить
{
// преобразуем координаты мыши в экранные
// именно они нужны будут для SetWindowPos()
ClientToScreen(&point);
// двигаем окно в соответствии с новыми координатами мыши
SetWindowPos(&wndTop, point.x - m_MouseInDlg.x, point.y - m_MouseInDlg.y,
m_RectDlg.right - m_RectDlg.left, m_RectDlg.bottom - m_RectDlg.top,
SWP_SHOWWINDOW);
// поскольку обработчик по умолчанию все равно будет использовать
// первоначальные параметры сообщения
// обратное преобразование ScreenToClient(&point);
// можно не вызывать
}
// вызываем обработчик по умолчанию
CDialog::OnMouseMove(nFlags, point);
}
void CDragWinDlg::OnLButtonUp(UINT nFlags, CPoint point) {
// перетаскивание закончилось
m_bMoveWindow = FALSE;
// "отпускаем" мышку
ReleaseCapture();
// меняем курсор на исходный
m_hCursor = m_hCursorUp;
// вызываем обработчик по умолчанию
CDialog::OnLButtonUp(nFlags, point);
}
BOOL CDragWinDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) {
// заменяем курсор на свой
::SetCursor(m_hCursor);
return TRUE; // !!! было return CDialog::OnSetCursor(pWnd, nHitTest, message);
}
Замена курсора естесственно не является критичной для собственно перетаскивания, а добавлена исключительно для визуализации процесса захвата окошка.
Способ 2Реализован для окна About этого же приложения. Заключается в замене обработчика события WM_NCHITTEST, которое информирует об области, над которой в данный момент находится мышка. Обработчик этого сообщения также можно добавить через MFC ClassWizard. Предварительно на закладке ClassInfo для класса CAboutDlg нужно установить для Message Filter значение Window.
Переписываем функцию – обработчик следующим образом:
UINT CAboutDlg::OnNcHitTest(CPoint point) {
UINT ret = CDialog::OnNcHitTest(point);
// если обработчик по умолчанию говорит нам что мышка
// над клиентской областью окна, заменяем возвращаемое
// значение на HTCAPTION – мышка над заголовком окна,
// а за заголовок перемещать окно можно!
if (ret == HTCLIENT) return HTCAPTION;
return ret;
}
Второй способ проще, первый потенциально гибче, используйте тот, что лучше подходит к вашему конкретному случаю.