Отправляет email-рассылки с помощью сервиса Sendsay

Программирование. Форум !!!

MFC+гоячие клавиши

Glad to greet!

Ситуация такова: написал заготовку класса наследуемого от CDialog и
захотелось добавить реакцию на нажатие клавиш. Поставил реакцию на
WM_CHAR, WM_KEYDOWN/UP - ни один из методов не вызывается (окно в
фокусе). Решил пойти через Accelerator, но обнаружил, что
LoadAccelTable есть только у CFrameWnd. Каким образом обрабатывать
нажатие клавиш и как их отлавливать? Заранее спасибо!

Alles Gute!

...In Code We Trust...

Ответить   Sat, 16 Apr 2005 10:50:56 +0400 (#352139)

 

Ответы:

Здравствуйте !


Для WM_KEYDOWN/UP обычно делают в PreTranslateMessage:

BOOL CMyDlg::PreTranslateMessage(MSG* pMsg)
{
if(pMsg->message == WM_KEYDOWN)
{
if(((int) pMsg->wParam) == VK_DELETE)
{
MessageBox("VK_DELETE");
return TRUE;
}
}

return CDialog::PreTranslateMessage(pMsg);
}

Но ! Тут будут обрабатываться также все сообщения WM_KEYDOWN с кодом
виртуальной клавиши VK_DELETE дочерних окон диалога (кнопок, и.т.д.),
поэтому надо проверять pMsg->hwnd на соответствие дескриптору
конкретного окна.

С акселераторами немного больше сделать надо.

В самом классе объявить дескриптор акселераторов:

class CMyDlg : public CDialog
{
...
HACCEL m_hAccel;

В конструкторе инициализируем:

CMyDlg::CMyDlg(CWnd* pParent /*=NULL*/) : CDialog(CMyDlg::IDD, pParent)
{
...
m_hAccel = NULL;


В OnCreate - загружаем, в OnDestroy - удаляем акселераторную таблицу:


int CMyDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialog::OnCreate(lpCreateStruct) == -1)
return -1;

m_hAccel = ::LoadAccelerators(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDR_ACCELERATOR1));

#ifdef _DEBUG
if(m_hAccel == NULL)
TRACE("акселераторы не загружены\n");
#endif

return 0;
}

void CMyDlg::OnDestroy()
{
if(m_hAccel != NULL)
{
::DestroyAcceleratorTable(m_hAccel);
m_hAccel = NULL;
}

CDialog::OnDestroy();
}


Ну, а в PreTranslateMessage - обрабатываем:

BOOL CMyDlg::PreTranslateMessage(MSG* pMsg)
{
if( (WM_KEYFIRST <= pMsg->message) &&
(WM_KEYLAST >= pMsg->message))
{
if (m_hAccel &&
::TranslateAccelerator(GetSafeHwnd(), m_hAccel, pMsg))
return TRUE;
}

return CDialog::PreTranslateMessage(pMsg);
}

Я в таблицу акселераторов IDR_ACCELERATOR1 добавил один акселератор
на кнопку VK_DELETE с ID = ID_MY_DELETE. После этого ID_MY_DELETE становится

виден в класс визарде. Обычным путем добавляется обработчик в класс диалога.

Ну... и все работает :)

void CMyDlg::OnMyDelete()
{
MessageBox("OnMyDelete");
}

--
С уважением, Вахтуров Виктор.

Номер выпуска : 4371
Возраст листа : 574 (дней)
Количество подписчиков : 517
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/352535
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Sun, 17 Apr 2005 10:08:46 +0400 (#352535)

 

Glad to greet, Victor!

You seem to have written (Sunday, April 17, 2005):

Огромное спасибо за столь подробный ответ!
Кстати, можно еще один ;). Хотел узнать, как можно получить прямой
доступ к данным CDC. То есть, хочется считать данные, которые там есть
(например, выведенный текст). Есть, конечно, вариант считывать тьму
раз с помощью GetPixel, но есть ли возможность считать сразу всё в
свой буфер (у CDC подобных методов не обнаружил)? Заранее спасибо!

Alles Gute!

...In Code We Trust...

Ответить   Mon, 18 Apr 2005 16:15:11 +0400 (#353152)

 

Здравствуйте !


Это, конечно, лучше в новом треде обсуждать :)

Как таковой прямой доступ именно к _данным_контекста_устройства
невозможен (контекст устройства - просто структура; вся структура
лежит в област памяти режима ядра, но часть ее дублируется
в пользовательский режим; можно получить ее содержимое через
таблицу объектов GDI - вроде функция GdiQueryTable возвращает
указатель (она недокументированная)).

То что в данной задаче надо - получить данные битмапа, выбранного
в данный момент в контексте. Можно конечно и через GetPixel, но это
очень долго (GetPixel создает однопиксельный растр, копирует туда 1
пиксел исходного контекста через BitBlt (или аналогичную функцию),
потом его данные получает и возвращает результат).
Кстати, такое получение данных имеет смысл именно если
в контексте выбран битмап (то есть если создали битмап при помощи
CreateCompatibleBitmap и выбрали его в контекст). В других
случаях получить эти самые данные нельзя (например, контекст
устройства - метафайловый или принтерный).

Короче, к данным битмапа, выбранного в контексте можно получить
доступ например так:

1. Использовать функцию GetDIBits (просто получает данные в буфер
в формате аппаратно-независимого растра).
2. Создать DIB секцию нужного формата (CreateDIBSection - при вызове
CreateDIBSection как раз указывается буфер, в котором будут храниться
данные изображения). А потом скопировать в нее исходный
аппаратно-зависимый растр при помощи BitBlt.

Кстати, если задача сводится к "нарисовать при помощи GDI и получить
то, что нарисовано в виде буфера", то удобнее вообще сразу создать
DIB-секцию и выбрать ее в контекст устройства. Потом на этом контексте
рисовать. Кстати, можно и обратное действие совершать - генерить изображение

в буфере, а потом при помощи DIB секции блиттить его куда угодно.
Кстати, DIB секции - вообще самое простое решение при обработке изображений,

т.к. позволяет с буфером работать.

--
С уважением, Вахтуров Виктор.

Номер выпуска : 4414
Возраст листа : 589 (дней)
Количество подписчиков : 514
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/360531
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Sun, 2 Jun 2002 22:49:25 +0400 (#360531)

 

Glad to greet, Victor!

You seem to have written (Sunday, June 02, 2002):

Сказано - сделано ;)


Да, я про неё уже читал, но меня смутило, что :
"
...function retrieves the bits of the specified compatible bitmap...
"
, а не непосредственно данные HDC.
Вообще я с GDI серьёзно никогда не работал, так что в голове большая
путаница (заранее прошу прощения), а справки MSDN не всегда
"дружелюбны" ;).

Но ведь в BitBlt надо передавать 2 HDC, а после CreateDIBSection есть
только HBITMAP?

В смысле сделать SelectObject(hDC,DIBitmap)?
Можно немного подробнее... Я попробовал, после CreateDIBSection буфер
заполняется полностью черным (ранее туда были выведены несколько
прямоугольников с разными кистями). Спасибо!

Alles Gute!

...In Code We Trust...

Ответить   Thu, 5 May 2005 13:00:06 +0400 (#362054)

 

Добрый день.
Как в Диалоговом Окне реализовать форматированный ввод даты и времени
в один Контролл в формате 05.04.20 12:00. То есть Как задать
маску ввода для поля ?
Спасибо.

Номер выпуска : 4378
Возраст листа : 576 (дней)
Количество подписчиков : 517
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/354055
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Tue, 19 Apr 2005 12:30:54 +0400 (#354055)

 

On Tue, 19 Apr 2005 12:30:54 +0400
"gogo" <gog***@m*****.ru> wrote:

В делфи всё очень просто - TDateTimePicker (кажется так компонент
называется)
умеет всё что тебе нужно!
в вижал студио - очевидно тоже компонент,,,, как называется не
помню.

Номер выпуска : 4384
Возраст листа : 578 (дней)
Количество подписчиков : 515
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/354783
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Wed, 20 Apr 2005 03:35:36 +0400 (#354783)

 

Hello gogo,

Tuesday, April 19, 2005, 12:30:54 PM, you wrote:

советую воспользоваться двумя контролами Date Time Picker (для Visual
С++)

Ответить   Wed, 20 Apr 2005 20:06:10 +0400 (#354792)

 

Здравствуйте !


Можно просто отформатировать дату с помощью CString::Format или
CTime::Format (вроде, есть такой метод у CTime) и вывести в Edit.
Можно использовать специальный элемент управления для задания
времени и даты (он есть на панели инструментов редактирования
ресурсов диалога в VC). Если надо все на API, то можно
создать в VC объект класса, связываемый с элементом управления
диалогового окна при помощи визарда и посмотреть какой там класс
окна используется для этого контрола в исходниках MFC.

--
С уважением, Вахтуров Виктор.

Номер выпуска : 4389
Возраст листа : 578 (дней)
Количество подписчиков : 515
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/354800
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Wed, 20 Apr 2005 22:12:16 +0400 (#354800)

 

Привет, gogo,

Tuesday, April 19, 2005, 2:30:54 PM, Вы писали:

Может, так: на свою форму кинуть компонент TDateTimePicker, маска: dd:MM:yyyy
hh:mm

Ответить   Wed, 20 Apr 2005 15:52:50 +0600 (#354850)