Чтение онлайн

ЖАНРЫ

Программирование на Visual C++. Архив рассылки

Jenter Алекс

Шрифт:

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.

Поделиться с друзьями: