Модераторы: feodorv, GremlinProg, xvr, Fixin

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как перехватить нажатие Enter? В ListView 
:(
    Опции темы
0x07L
Дата 10.6.2006, 22:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 10.6.2006
Где: Москва

Репутация: 4
Всего: 5



Почему-то в ListView не перехватывается нажатие Enter. Я смотрел нотификационное сообшение LVN_KEYDOWN, использовал subclassing и перехватывал посылаемые ListView сообщения WM_SYSKEYDOWN, WM_KEYDOWN, WM_CHAR, но нажатие Enter нигде обнаружено не было. Интересно, что нажатие Enter в Edit'е успешно перехватывается в WM_KEYDOWN. Может, кто подскажет, что с этим делать? 
PM MAIL   Вверх
Pulse69
Дата 11.6.2006, 06:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 138
Регистрация: 28.4.2006
Где: Хабаровск

Репутация: 8
Всего: 10



Наш любимый МСДН:

NM_RETURN (list view) Notification

--------------------------------------------------------------------------------

Notifies a list-view control's parent window that the control has the input focus and that the user has pressed the ENTER key. NM_RETURN is sent in the form of a WM_NOTIFY message. 

 
--------------------
Ctrl+Alt+Reset 
PM MAIL   Вверх
0x07L
Дата 11.6.2006, 12:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 10.6.2006
Где: Москва

Репутация: 4
Всего: 5



Это очень странно, но NM_RETURN тоже не перехватывается...

Добавлено @ 12:20 
Вот моя тестовая программка

Код

#include <windows.h>
#include <tchar.h>
#include <commctrl.h>
#include "resource.h"

#pragma comment (lib, "ComCtl32.Lib")

int APIENTRY _tWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR strCmdLine, int CmdShow);
LRESULT CALLBACK DlgProc (HWND hDlg, UINT MessageCode, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK ListViewSubclassWndProc (HWND hListView, UINT MessageCode, WPARAM wParam, LPARAM lParam);

WNDPROC OriginalListViewWndProc;

int APIENTRY _tWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR strCmdLine, int CmdShow)
{
    INITCOMMONCONTROLSEX InitComCtl;
    InitComCtl.dwSize = sizeof InitComCtl;
    InitComCtl.dwICC = ICC_LISTVIEW_CLASSES;
    InitCommonControlsEx (&InitComCtl);

    return static_cast<int>(DialogBox(
        hInstance,
        MAKEINTRESOURCE(IDD_DIALOG1),
        0, reinterpret_cast<DLGPROC>(DlgProc)));
}

LRESULT CALLBACK DlgProc (HWND hDlg, UINT MessageCode, WPARAM wParam, LPARAM lParam)
{
    const int LinesInListView = 20;
    const int ColumnsInListView = 15;
    const int ColumnWidth = 35;
    
    const int cchBuffer = 40;
    TCHAR strBuffer [cchBuffer];

    static HWND hListView;
    
    switch (MessageCode)
    {
    case WM_INITDIALOG:
        {

        RECT rcClient;
        GetClientRect (hDlg, &rcClient);
            
        hListView = CreateWindowW (
            WC_LISTVIEW, 0, WS_CHILD | WS_VISIBLE | LVS_REPORT,
            0, 0, rcClient.right, rcClient.bottom,
            hDlg, 0, 0, 0);

        ListView_SetExtendedListViewStyle (hListView, LVS_EX_GRIDLINES);

        LVITEM Item;
        Item.iItem = LinesInListView;
        Item.iSubItem = 0;
        Item.mask = 0;
        
        for (int i=0; i<LinesInListView; i++)
        {
            ListView_InsertItem (hListView, &Item);
        }

        LVCOLUMN Column;
        Column.mask = LVCF_WIDTH;
        Column.cx = ColumnWidth;

        for (int i=0; i<ColumnsInListView; i++)
        {
            ListView_InsertColumn (hListView, ColumnsInListView, &Column);
        }

        ::OriginalListViewWndProc = reinterpret_cast<WNDPROC>(SetWindowLongPtr (
            hListView, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(ListViewSubclassWndProc)));
        
        return true;

        } // case WM_INITDIALOG

    case WM_NOTIFY:
        {

        LPNMHDR pHeader = reinterpret_cast<LPNMHDR>(lParam);

        if (pHeader->hwndFrom == hListView)
        {
            switch (pHeader->code)
            {
            case LVN_KEYDOWN:
                {

                LPNMLVKEYDOWN pKeyDown = reinterpret_cast<LPNMLVKEYDOWN>(lParam);

                if (pKeyDown->wVKey == VK_RETURN)
                {
                    MessageBox (hDlg, _TEXT("Поймано нажатие ENTER"), _TEXT("LVN_KEYDOWN"), MB_OK | MB_ICONINFORMATION);
                }
                else
                {
                    _stprintf_s (
                        strBuffer, cchBuffer,
                        _TEXT("Нажата клавиша %X"),
                        pKeyDown->wVKey);

                    MessageBox (hDlg, strBuffer, _TEXT("LVN_KEYDOWN"), MB_OK | MB_ICONINFORMATION);
                }

                return true;

                } // case LVN_KEYDOWN

            case NM_RETURN:

                MessageBox (hDlg, _TEXT("Поймано нажатие ENTER"), _TEXT("NM_RETURN"), MB_OK | MB_ICONINFORMATION);
                return true;

            } // switch (pHeader->code)

        } // if (... == hListView)

        return false;

        } // case WM_NOTIFY
    
    case WM_SIZE:

        MoveWindow (hListView, 0, 0, LOWORD(lParam), HIWORD(lParam), true);
        return true;

    case WM_CLOSE:

        DestroyWindow (hDlg);
        return true;

    case WM_DESTROY:

        EndDialog (hDlg, 0);
        return true;

    } // switch (MessageCode

    return false;
}

LRESULT CALLBACK ListViewSubclassWndProc (HWND hListView, UINT MessageCode, WPARAM wParam, LPARAM lParam)
{
    const int cchBuffer = 40;
    TCHAR strBuffer [cchBuffer];
    
    switch (MessageCode)
    {
    case WM_SYSKEYDOWN:

        if (wParam == VK_RETURN)
        {
            if ((lParam >> 28) << (sizeof(lParam)*8-1) == 0)
                // 29ый бит установлен в 0 - Alt не нажат
                // (см. описание WM_SYSKEYDOWN в MSDN)
            {
                MessageBox (hListView, _TEXT("Поймано нажатие ENTER"), _TEXT("WM_SYSKEYDOWN"), MB_OK | MB_ICONINFORMATION);
                return true;
            }
        }
        else
        {
            _stprintf_s (strBuffer, cchBuffer, _TEXT("Нажата клавиша %X"), wParam);

            MessageBox (hListView, strBuffer, _TEXT("WM_SYSKEYDOWN"), MB_OK | MB_ICONINFORMATION);
        }
        break;

    case WM_KEYDOWN:

        if (wParam == VK_RETURN)
        {
            MessageBox (hListView, _TEXT("Поймано нажатие ENTER"), _TEXT("WM_KEYDOWN"), MB_OK | MB_ICONINFORMATION);
            return true;
        }
        else
        {
            _stprintf_s (strBuffer, cchBuffer, _TEXT("Нажата клавиша %X"), wParam);

            MessageBox (hListView, strBuffer, _TEXT("WM_KEYDOWN"), MB_OK | MB_ICONINFORMATION);
        }
        break;
    
    case WM_CHAR:

        if (wParam == _T('\n'))
        {
            MessageBox (hListView, _TEXT("Поймано нажатие ENTER"), _TEXT("WM_CHAR"), MB_OK | MB_ICONINFORMATION);
            return true;
        }
        else
        {
            _stprintf_s (strBuffer, cchBuffer, _TEXT("Нажата клавиша '%C'"), wParam);

            MessageBox (hListView, strBuffer, _TEXT("WM_CHAR"), MB_OK | MB_ICONINFORMATION);
        }
        break;
    }

    return ::OriginalListViewWndProc (hListView, MessageCode, wParam, lParam);
}
 
PM MAIL   Вверх
Pulse69
Дата 11.6.2006, 15:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 138
Регистрация: 28.4.2006
Где: Хабаровск

Репутация: 8
Всего: 10



У тебя List-View в диалоге, вся проблема именно в этом. Я с таким как-то сталкивался. В MSDN Magazine есть статья примерно на такую тему. Если у тебя VS2005, посмотри эту ссылку:

ms-help://MS.MSDNQTR.v80.en/MS.MSDN.v80/dnmag00/html/c0700.htm

Суть в том, что мне пришлось создавать таблицу акселераторов с VK_RETURN, а затем обрабатывать сообщение от акселератора. По-другому я не знаю как.

PS: Xотя нет, знаю. Не пиши для диалога =) 
--------------------
Ctrl+Alt+Reset 
PM MAIL   Вверх
0x07L
Дата 11.6.2006, 15:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 10.6.2006
Где: Москва

Репутация: 4
Всего: 5



Спасибо большое! 
PM MAIL   Вверх
0x07L
Дата 15.6.2006, 16:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 10.6.2006
Где: Москва

Репутация: 4
Всего: 5



Кстати, в MFC, оказывается, перехватить нажатие Enter еще сложнее, потому что диалоговое окно при его нажатии закрывается  smile 
Даже, если нет кнопки по кмолчанию... 
PM MAIL   Вверх
Earnest
Дата 15.6.2006, 18:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 33
Всего: 183



В MFC как раз проще - там есть волшебная функция PreTranslateMessage. 


--------------------
...
PM   Вверх
0x07L
Дата 15.6.2006, 19:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 10.6.2006
Где: Москва

Репутация: 4
Всего: 5



Буду знать 
PM MAIL   Вверх
0x07L
Дата 7.7.2006, 19:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 10.6.2006
Где: Москва

Репутация: 4
Всего: 5



Есть решение проблемы! Оказывается, существует сообщение WM_GETDLGCODE. Оно посылается функции окна элемента управления. Возвращенное из функции окна значение говорит, какие клавиши ты хочешь обрабатывать сам. Windows при нажатии этих клавиш не будет сам ничего делать (кроме как ставить очередное сообщение в очередь). С моим ListView это проходит! 
PM MAIL   Вверх
0x07L
Дата 7.7.2006, 19:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 10.6.2006
Где: Москва

Репутация: 4
Всего: 5



Обнаружилась странная вещь
Код


// ===============================================
//
// (добавлено 11.07.2006)
//
// Код смотреть не рекомендуется, поскольку ошибка
// Дополнительную инфу смотри в обработчике WM_GETDLGCODE
//
// ===============================================

#include <windows.h>
#include <tchar.h>

#include "resource.h"

int APIENTRY _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int);
LRESULT CALLBACK DialogProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR CmdLine, int CmdShow)
{
    return static_cast<int>(DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG), 0, reinterpret_cast<DLGPROC>(DialogProc)));
}

LRESULT CALLBACK DialogProc(HWND hDialog, UINT Message, WPARAM wParam, LPARAM lParam)
{
    switch(Message)
    {
    case WM_INITDIALOG:

        return TRUE;

    case WM_GETDLGCODE:

// ===============================================
//
// (добавлено 11.07.2006)
//
// Ошибка: ну ка скажите мне,
// как возвращать значение
// из функции диалогового окна :-)
//
// ===============================================

        return DLGC_WANTALLKEYS;

    case WM_KEYDOWN:

        if (wParam /* virtual key code */ == VK_RETURN)
        {
            Beep(1500, 50);
        }
        return TRUE;

    case WM_CLOSE:

        DestroyWindow(hDialog);
        return TRUE;

    case WM_DESTROY:

        EndDialog(hDialog, 0);
        return TRUE;
    }
    return FALSE;
}


Функции диалогового окна, несмотря на то что она не есть "the window procedure associated with a control" (MSDN), WM_GETDLGCODE все равно приходит. Правда, толку от него мало: Enter в диалоговом окне не ловится smile  

Это сообщение отредактировал(а) 0x07L - 11.7.2006, 09:41
PM MAIL   Вверх
Earnest
Дата 10.7.2006, 17:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 33
Всего: 183



Ты немного не так понял. Существует стандартная обработка некоторых клавиш в диалоге
Цитата

the system interprets certain types of keyboard input as dialog box navigation keys

Но если в оконной функции контрола в ответ на WM_GETDLGCODE возвратить определенные значения, то это стандартное поведение можно изменить. 

А ENTER попробуй ловить как WM_CHAR с соответствующим ASCII-кодом, а не WM_KEYDOWN. 


--------------------
...
PM   Вверх
0x07L
Дата 10.7.2006, 22:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 10.6.2006
Где: Москва

Репутация: 4
Всего: 5



Глупый вопрос: а как сделать так, чтобы в функцию диалога приходил WM_CHAR? 
PM MAIL   Вверх
DeadSoul
Дата 10.7.2006, 22:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1217
Регистрация: 25.9.2005
Где: Москва

Репутация: нет
Всего: 11



Цитата(0x07L @  10.7.2006,  22:25 Найти цитируемый пост)
Глупый вопрос: а как сделать так, чтобы в функцию диалога приходил WM_CHAR?  

Создать обработчик этого сообщения? 


--------------------
 Если Вы получили ответ на Ваш вопрос, то нажмите на "Вопрос решен". 

Бьем спамеров их же оружием. Пусть весь спам сыпется им
[email protected] 
PM   Вверх
0x07L
Дата 10.7.2006, 22:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 272
Регистрация: 10.6.2006
Где: Москва

Репутация: 4
Всего: 5



Обработчик-то есть:
Код


// ===============================================
//
// (добавлено 11.07.2006)
//
// Код смотреть не рекомендуется, поскольку ошибка
// Дополнительную инфу смотри во вставке кода
// в моем предыдущем посте
//
// ===============================================

#include <windows.h>
#include <tchar.h>

#include "resource.h"

int APIENTRY _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int);
LRESULT CALLBACK DialogProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR CmdLine, int CmdShow)
{
    return static_cast<int>(DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG), 0, reinterpret_cast<DLGPROC>(DialogProc)));
}

LRESULT CALLBACK DialogProc(HWND hDialog, UINT Message, WPARAM wParam, LPARAM lParam)
{
    switch(Message)
    {
    case WM_INITDIALOG:

        return TRUE;

    case WM_GETDLGCODE:

        return DLGC_WANTALLKEYS;

    case WM_KEYDOWN:

        if (wParam /* virtual key code */ == VK_RETURN)
        {
            Beep(1500, 50);
        }
        return TRUE;

    case WM_CHAR:

        if (wParam /* ASCII code */ == _T('\n'))
        {
            Beep(500, 50);
        }
        return TRUE;

    case WM_CLOSE:

        DestroyWindow(hDialog);
        return TRUE;

    case WM_DESTROY:

        EndDialog(hDialog, 0);
        return TRUE;
    }
    return FALSE;
}
  

Это сообщение отредактировал(а) 0x07L - 11.7.2006, 09:43
PM MAIL   Вверх
DeadSoul
Дата 10.7.2006, 22:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник
Сообщений: 1217
Регистрация: 25.9.2005
Где: Москва

Репутация: нет
Всего: 11



А WM_KEYDOWN тоже не ловится? Spy++ смотрел какие сообщения приходят? 


--------------------
 Если Вы получили ответ на Ваш вопрос, то нажмите на "Вопрос решен". 

Бьем спамеров их же оружием. Пусть весь спам сыпется им
[email protected] 
PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0630 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.