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

Тут можно читать онлайн Алекс Jenter - Программирование на Visual C++. Архив рассылки - бесплатно полную версию книги (целиком) без сокращений. Жанр: comp-programming. Здесь Вы можете читать полную версию (весь текст) онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    Программирование на Visual C++. Архив рассылки
  • Автор:
  • Жанр:
  • Издательство:
    неизвестно
  • Год:
    неизвестен
  • ISBN:
    нет данных
  • Рейтинг:
    4.33/5. Голосов: 91
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

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

Программирование на Visual C++. Архив рассылки - описание и краткое содержание, автор Алекс Jenter, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

РАССЫЛКА ЯВЛЯЕТСЯ ЧАСТЬЮ ПРОЕКТА RSDN, НА САЙТЕ КОТОРОГО ВСЕГДА МОЖНО НАЙТИ ВСЮ НЕОБХОДИМУЮ РАЗРАБОТЧИКУ ИНФОРМАЦИЮ, СТАТЬИ, ФОРУМЫ, РЕСУРСЫ, ПОЛНЫЙ АРХИВ ПРЕДЫДУЩИХ ВЫПУСКОВ РАССЫЛКИ И МНОГОЕ ДРУГОЕ.

Программирование на Visual C++. Архив рассылки - читать онлайн бесплатно полную версию (весь текст целиком)

Программирование на Visual C++. Архив рассылки - читать книгу онлайн бесплатно, автор Алекс Jenter
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

template

LRESULT CALLBACK CDialogImplBaseT::StartDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){

CDialogImplBaseT* pThis = (CDialogImplBaseT*)_Module.ExtractCreateWndData();

ATLASSERT(pThis != NULL);

pThis->m_hWnd = hWnd;

pThis->m_thunk.Init(pThis->GetDialogProc(), pThis);

WNDPROC pProc = (WNDPROC)&(pThis->m_thunk.thunk);

WNDPROC pOldProc = (WNDPROC)::SetWindowLong(hWnd, DWL_DLGPROC, (LONG)pProc);

#ifdef _DEBUG

// check if somebody has subclassed us already since we discard it

if (pOldProc != StartDialogProc)

ATLTRACE2(atlTraceWindowing, 0, _T("Subclassing through a hook discarded.\n"));

#else

pOldProc; // avoid unused warning

#endif

return pProc(hWnd, uMsg, wParam, lParam);

}

template LRESULT CALLBACK CDialogImplBaseT::DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){

CDialogImplBaseT* pThis = (CDialogImplBaseT*)hWnd;

// set a ptr to this message and save the old value

MSG msg = { pThis->m_hWnd, uMsg, wParam, lParam, 0, { 0, 0 } };

const MSG* pOldMsg = pThis->m_pCurrentMsg;

pThis->m_pCurrentMsg = &msg;

// pass to the message map to process

LRESULT lRes;

BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0);

// restore saved value for the current message

ATLASSERT(pThis->m_pCurrentMsg == &msg);

pThis->m_pCurrentMsg = pOldMsg;

// set result if message was handled

if (bRet) {

switch (uMsg) {

case WM_COMPAREITEM:

case WM_VKEYTOITEM:

case WM_CHARTOITEM:

case WM_INITDIALOG:

case WM_QUERYDRAGICON:

case WM_CTLCOLORMSGBOX:

case WM_CTLCOLOREDIT:

case WM_CTLCOLORLISTBOX:

case WM_CTLCOLORBTN:

case WM_CTLCOLORDLG:

case WM_CTLCOLORSCROLLBAR:

case WM_CTLCOLORSTATIC:

return lRes;

break;

}

::SetWindowLong(pThis->m_hWnd, DWL_MSGRESULT, lRes);

return TRUE;

}

if (uMsg == WM_NCDESTROY) {

// clear out window handle

HWND hWnd = pThis->m_hWnd;

pThis->m_hWnd = NULL;

// clean up after dialog is destroyed

pThis->OnFinalMessage(hWnd);

}

return FALSE;

}

Статическая функция StartDialogProcназначается диалогу при его создании. Для этого её адрес передаётся функциям, подобным DialogBoxи CreateDialog, или задаётся в качестве хука для стандартных диалогов. Получив управление, эта функция извлекает хэндл диалога из объекта _Moduleи сохраняет его в переменной m_hWnd, затем инициализирует переходник и передаёт управление штатной диалоговой процедуре DialogProc, которая и выполняет дальнейшее обслуживание диалога. Каждое полученное сообщение она "пропускает" через карту сообщений вызовом ProcessWindowMessage. Возвращаемое после обработки сообщения значение интерпретируется в зависимости от типа сообщения. Тем самым обеспечивается небольшое, но весьма приятное удобство: программист не должен помнить, каким образом нужно передать операционной системе LRESULTиз диалоговой процедуры (напрямую или с помощью SetWindowLong). Достаточно вернуть его из функции-обработчика, а об остальном позаботится WTL.

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

После уничтожения диалога WTL вызывает виртуальную функцию OnFinalMessage. Вы можете переопределить её в производном классе и возложить на неё "очистительные" работы. Следует только иметь в виду, что во время работы этой функции диалог уже не существует, и даже переменная m_hWndсодержит NULL. Поэтому в функции OnFinalMessageнельзя, к примеру, загружать данные из контролов диалога в переменные.

Класс CDialogImpl<>

Класс CDialogImpl<>– основное средство для работы с диалогами в WTL. Он используется как с модальными, так и с немодальными диалогами. Соответственно, в нём содержатся обёртки для функций DialogBoxParam, EndDialog, CreateDialogParamи DestroyWindow. Механизм обработки сообщений наследуется от класса CDialogImplBaseT<>.

Для создания модального диалога используется метод DoModal. Уничтожить модальный диалог можно, используя метод EndDialog(можно вызывать этот метод из любого обработчика сообщений, в том числе из обработчика сообщения WM_INITDIALOG). Реализация обоих методов более чем прямолинейна:

// modal dialogs

int DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL) {

ATLASSERT(m_hWnd == NULL);

_Module.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT*)this);

#ifdef _DEBUG

m_bModal = true;

#endif //_DEBUG

return

::DialogBoxParam(_Module.GetResourceInstance(), MAKEINTRESOURCE(T::IDD),

hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam);

}

BOOL EndDialog(int nRetCode) {

ATLASSERT(::IsWindow(m_hWnd));

ATLASSERT(m_bModal); // must be a modal dialog

return ::EndDialog(m_hWnd, nRetCode);

}

Здесь следует обратить внимание всего на две вещи. Во-первых, в качестве диалоговой процедуры задаётся StartDialogProc. Благодаря этому к создаваемому диалогу подключается механизм обработки сообщений, рассмотренный в предыдущем разделе. Во-вторых, в качестве идентификатора ресурса диалога используется константа IDD. Вам необходимо определить её в производном классе, чтобы WTL знала, какой диалог требуется создать. В принципе, можно сделать IDDи статической переменной производного класса, но прибегать к этому приёму на практике приходится не часто.

ПРИМЕЧАНИЕ

Библиотека MFC не использует функцию DialogBox(Param). Вместо этого она создаёт немодальный диалог, а затем эмулирует поведение модального. Благодаря этому программировать модальные диалоги в MFC гораздо удобнее, чем на "чистом" Win32 API (а значит, и в WTL). Проблема в том, что функция DialogBox(Param)создаёт свой собственный цикл сообщений, до которого не так-то просто добраться. Если нам потребуется, к примеру, внедрить в него трансляцию акселераторов, придётся прибегать к различным неочевидным приёмам.

Немодальный диалог создаётся с использованием функции Createи разрушается вызовом DestroyWindow. Реализация обоих методов также достаточно очевидна.

// modeless dialogs

HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL) {

ATLASSERT(m_hWnd == NULL);

_Module.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT*)this);

#ifdef _DEBUG

m_bModal = false;

#endif //_DEBUG

HWND hWnd = ::CreateDialogParam(_Module.GetResourceInstance(), MAKEINTRESOURCE(T::IDD),

hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam);

ATLASSERT(m_hWnd == hWnd);

return hWnd;

}

BOOL DestroyWindow() {

ATLASSERT(::IsWindow(m_hWnd));

ATLASSERT(!m_bModal); // must not be a modal dialog

return ::DestroyWindow(m_hWnd);

}

С учётом всего сказанного, типичный класс диалога, порождённый от CDialogImpl<>, выглядит так (в качестве параметра шаблона задаётся имя класса, который вы порождаете).

class CMyDialog : public CDialogImpl {

public:

enum { IDD = IDIDD_MY_DIALOG };

BEGIN_MSG_MAP(CMyDialog)

// Карта сообщений

END_MSG_MAP()

};

Обратите внимание, что константа IDDописывается в секции public. Если описать её в private-секции, функция базового класса CDialogImpl<>::DoModalне сможет к ней обратиться, что приведёт к ошибке.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Алекс Jenter читать все книги автора по порядку

Алекс Jenter - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




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


Отзывы читателей о книге Программирование на Visual C++. Архив рассылки, автор: Алекс Jenter. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x