Алекс Jenter - Программирование на Visual C++. Архив рассылки
- Название:Программирование на Visual C++. Архив рассылки
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Алекс Jenter - Программирование на Visual C++. Архив рассылки краткое содержание
РАССЫЛКА ЯВЛЯЕТСЯ ЧАСТЬЮ ПРОЕКТА RSDN, НА САЙТЕ КОТОРОГО ВСЕГДА МОЖНО НАЙТИ ВСЮ НЕОБХОДИМУЮ РАЗРАБОТЧИКУ ИНФОРМАЦИЮ, СТАТЬИ, ФОРУМЫ, РЕСУРСЫ, ПОЛНЫЙ АРХИВ ПРЕДЫДУЩИХ ВЫПУСКОВ РАССЫЛКИ И МНОГОЕ ДРУГОЕ.
Программирование на Visual C++. Архив рассылки - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
ПРИМЕЧАНИЕ
Обратите внимание, окно редактирования должно иметь стиль ES_MULTILINE.
Для реализации поведения приложения, аналогичного только что описанному, необходимо создать класс, производный от CEdit, имеющий собственные обработчики сообщений WM_KEYDOWNи WM_CHAR(при создании класса и добавлении обработчиков используйте ClassWizard).
// .h-файл класса ////////////////////////////////////////////////
...
class CEnterEdit : public CEdit {
public:
CEnterEdit();
public:
virtual ~CEnterEdit();
protected:
//{{AFX_MSG(CEnterEdit)
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
// .cpp-файл класса //////////////////////////////////////////////
...
BEGIN_MESSAGE_MAP(CEnterEdit, CEdit)
//{{AFX_MSG_MAP(CEnterEdit)
ON_WM_KEYDOWN()
ON_WM_CHAR()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CEnterEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {
if (nChar == VK_RETURN) {
// Предполагаем, что родительское окно эдит-бокса -
// диалог класса CEditDlgDlg, который имеет буфер хранения
// введенного текста m_edText типа CString.
CEditDlgDlg* pDlg = (CEditDlgDlg*) GetParent();
GetWindowText(pDlg->m_edText);
pDlg->GetNextDlgTabItem(this)->SetFocus();
return; // запрет обработки по-умолчанию
}
CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
}
void CEnterEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) {
if (nChar == VK_RETURN) return; // запрет обработки по-умолчанию
CEdit::OnChar(nChar, nRepCnt, nFlags);
}
ПРИМЕЧАНИЕ
Подмена оконной процедуры – универсальный метод для получения необходимой функциональности. Если же есть возможность получить доступ к циклу сообщений, то можно воспользоваться альтернативной методикой – обработкой сообщения WM_KEYDOWNв самом цикле (см. далее – Альтернативный вариант).
Пример EditDlg демонстрирует обработку нажатия клавиши Enter. Он содержит два проекта – WinAPI и MFC.
Не всегда целесообразно обработку нажатия Enter возлагать на окно редактирования. Если в поведение приложения необходимо добавить указанную реакцию, но для самого окна достаточно обычной функциональности (однострочное окно редактирования), можно, не меняя стиля окна редактирования, самостоятельно обрабатывать нажатие Enter, анализируя содержимое сообщений в цикле обработки сообщений.
Необходимо помнить, что цикл обработки сообщений модального диалога реализуется самой системой и недоступен для программиста. В этом случае остается единственное средство – подмена оконной процедуры окна редактирования, описанная выше (см. Основной вариант).
Детали реализации этого метода очень сильно зависят от постановки задачи, среды разработки и организации цикла обработки сообщений. Общая схема такова:
1. До выполнения DispacthMessage(&msg)необходимо проанализировать поле msg.message на приход сообщения WM_KEYDOWN.
2. Если получено сообщение WM_KEYDOWN, и поле msg.wParamсодержит VK_RETURN, то выполнить вызов функции-диспетчера нажатия enter. При этом обычно необходимо избегать передачи полученного сообщения в функцию DispatchMessage(), чтобы не выполнялась обработка по-умолчанию.
3. Для всех иных сообщений выполнить стандартную обработку.
Для программ, использующих MFC, все необходимые проверки выполняются в методе PreTranslateMessage()класса приложения или окна.
BOOL CMyWinApp::PreTranslateMessage(MSG* pMsg) {
if ((WM_KEYDOWN == pMsg->message) && (VK_RETURN == pMsg->wParam)) {
OnEnterPressed(); // вызов диспетчера нажатия Enter
return TRUE; // запрет дальнейшей обработки
}
// стандартная обработка сообщения
return CWinApp::PreTranslateMessage(pMsg);
}
Для приложений WinAPI реализация цикла обработки сообщений может выглядеть таким образом:
...
while (GetMessage(&msg, NULL, 0, 0)) {
if ((WM_KEYDOWN == pMsg->message) && (VK_RETURN == pMsg->wParam)) {
OnEnterPressed(); // вызов диспетчера нажатия Enter
continue; // запрет дальнейшей обработки
}
// стандартная обработка сообщения
TranslateMessage(&msg);
DispatchMessage(&msg);
}
...
В функции OnEnterPressed()вы можете анализировать, которое из окон ввода в момент нажатия имеет фокус, и в зависимости от этого принимать решение о выполнении необходимых действий, обеспечивающих логику работы приложения.
ПРИМЕЧАНИЕ
Поскольку этот вариант является существенным только для модальных диалогов, в которых, для того чтобы добраться до цикла сообщений, необходимо применить то (сабклассинг окна диалога) или иное (постановка локального хука) ухищрение, и поскольку сказанное совершенно не относится к MFC, где модальные диалоги "от системы" практически не применяются, то мы рассмотрим только WinAPI-вариант.
Условимся заранее, что теорию применения хуков вы получите из любых других источников (например, из статьи Kyle Marsh Хуки в Win32или Dr. Joseph M. Newcomer Хуки и DLLна нашем сайте). Там же вы познакомитесь и с их разновидностями. Мы же продолжим решать нашу задачу – перехват нажатия Enter в модальном диалоге.
Итак, в качестве необходимого теоретического минимума заметим, что механизм "крюков" (hook – англ., крюк) позволяет приложению зарегистрировать некий обработчик, который система будет вызывать в ответ на события, происходящие в ее недрах, с целью оповещения пользовательского кода об этих событиях. Локальный хук вызывается только для событий, относящихся к процессу, поставившему хук, что практически никак не ухудшает общую производительность системы вцелом. И потому именно этот механизм подходит нам для наших целей.
Нам необходимо поставить хук типа , который позволяет проводить мониторинг событий в диалогах (в том числе и MessageBox), меню и полосах прокрутки. Код логически распадается на относительно стандартную часть, имеющую сходное строение для хуков любого типа, и специфическую часть, которая будет выполнять для нас полезную работу. Стандартный код может выглядеть следующим образом:
LRESULT DlgBoxMsgFilter(UINT code, WPARAM wParam, LPARAM lParam);
HHOOK g_hHook = NULL;
LRESULT CALLBACK HookProc(int code, WPARAM wParam, LPARAM lParam) {
LRESULT res = 0;
// служебная обработка
if (0 > code) return CallNextHookEx(WH_MSGFILTER, code, wParam, lParam);
// вызов пользовательской процедуры "полезного действия"
res = DlgBoxMsgFilter(code, wParam, lParam);
if (res > -1) return res;
return CallNextHookEx(WH_MSGFILTER, code, wParam, lParam);
}
BOOL CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_INITDIALOG:
Интервал:
Закладка: