Модераторы: 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   Вверх
0x07L
Дата 10.7.2006, 22:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Что за чушь? В Spy есть WM_KEYDOWN, WM_CHAR, WM_KEYUP. Причем нажатие Enter там тоже видно  smile

Добавлено @ 22:49 
А, кстати, при нажатии на Enter не приходит WM_CHAR  smile

Добавлено @ 22:57 
Вот как (засунуть это в обработчик WM_GETDLGCODE):
Код

LPMSG pMsg = reinterpret_cast<LPMSG>(lParam);
if (pMsg && pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN)
{
    Beep(2000, 50);
}
[S]return DLGC_WANTALLKEYS | DLGC_WANTCHARS | DLGC_WANTMESSAGE[/S];
  

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


Опытный
**


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

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



Дописал я тут свою программку
Код

#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)
{
    const int BufferSize = 120;
    TCHAR Buffer [BufferSize];
    
    switch(Message)
    {
    case WM_INITDIALOG:

        return TRUE;

    case WM_GETDLGCODE:
        {
            LPMSG pMsg = reinterpret_cast<LPMSG>(lParam);
            
            if (pMsg)
            {
                _stprintf_s(Buffer, BufferSize, _TEXT(
                    "Received:\tWM_GETDLGCODE\nMessage:\t\t%d (dec)\nwParam:\t\t%p (hex)"),
                    pMsg->message, pMsg->wParam);

                MessageBox(hDialog, Buffer, _TEXT("Catch ENTER in dialog"), MB_OK | MB_ICONINFORMATION);
            }
            else
            {
                Beep(1500, 50);
            }
        }
        SetWindowLongPtr(hDialog, DWLP_MSGRESULT, DLGC_WANTALLKEYS);
        return TRUE;

    case WM_KEYDOWN:

        _stprintf_s(Buffer, BufferSize, _TEXT(
            "Received:\tWM_KEYDOWN\nwParam:\t\t%p (hex)"),
            wParam);

        MessageBox(hDialog, Buffer, _TEXT("Catch ENTER in dialog"), MB_OK | MB_ICONINFORMATION);

        return TRUE;

    case WM_CHAR:

        _stprintf_s(Buffer, BufferSize, _TEXT(
            "Received:\tWM_CHAR\nwParam:\t\t%p (hex)"),
            wParam);

        MessageBox(hDialog, Buffer, _TEXT("Catch ENTER in dialog"), MB_OK | MB_ICONINFORMATION);

        return TRUE;

    case WM_KEYUP:

        _stprintf_s(Buffer, BufferSize, _TEXT(
            "Received:\tWM_KEYUP\nwParam:\t\t%p (hex)"),
            wParam);

        MessageBox(hDialog, Buffer, _TEXT("Catch ENTER in dialog"), MB_OK | MB_ICONINFORMATION);

        return TRUE;

    case WM_CLOSE:

        DestroyWindow(hDialog);
        return TRUE;

    case WM_DESTROY:

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


Теперь все работает. Рзве что почему-то не приходит WM_KEYUP  smile 

Кстати, WM_GETDLGCODE, сообщающий о нажатии Enter, приходит всегда (независимо от того, что возвращено в обработчике). Так что буду юзать WM_GETDLGCODE.

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

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


Опытный
**


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

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



Никогда не думал, что Windows тоже может посылать сообщения с таймаутом. Он как раз и делает так с WM_KEYUP. Из-за моих MessageBox'ов (да и из-за отладчика) таймаут просто уже проходит.  smile  
PM MAIL   Вверх
Earnest
Дата 11.7.2006, 08:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Не из-за тайм-аутов, а из-за переключения окна: сообщения ввода (клавиатуры и мыши) всегда приходят активному окну. Т.е. WM_KEYDOWN приходит твоему диалогу, а WM_KEYUP - уже MessageBox. Или отладчику. Тоже самое будет с WM_BUTTONDOWN \ UP.  

Так все-таки ENTER в WM_KEYDOWN приходит или нет? Или ты получаешь его только через lParam
от WM_GETDLGCODE? Я с чистым API давно не работала, так что интересно... Похоже, его функция TranslateMessage во что-то преобразует...
 


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


Опытный
**


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

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



Ответы на предыдущие посты

Enter приходит и с WM_GETDLGCODE, и с WM_KEYDOWN, и с WM_CHAR, но, как я уже говорил, без WM_KEYUP.

Насчет переключения окна. Исправил свою программку, добавив перед каждым MessageBox'ом вызов Sleep(500):

Код

#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)
{
    const int BufferSize = 120;
    TCHAR Buffer [BufferSize];
    
    switch(Message)
    {
    case WM_INITDIALOG:

        return TRUE;

    case WM_GETDLGCODE:
        {
            LPMSG pMsg = reinterpret_cast<LPMSG>(lParam);
            
            if (pMsg)
            {
                Sleep(500);
                
                _stprintf_s(Buffer, BufferSize, _TEXT(
                    "Received:\tWM_GETDLGCODE\nMessage:\t\t%d (dec)\nwParam:\t\t%p (hex)"),
                    pMsg->message, pMsg->wParam);

                MessageBox(hDialog, Buffer, _TEXT("Catch ENTER in dialog"), MB_OK | MB_ICONINFORMATION);
            }
            else
            {
                Beep(1500, 50);
            }
        }
        SetWindowLongPtr(hDialog, DWLP_MSGRESULT, DLGC_WANTALLKEYS | DLGC_WANTCHARS);
        return TRUE;

    case WM_CHAR:

        Sleep(500);
        
        _stprintf_s(Buffer, BufferSize, _TEXT(
            "Received:\tWM_CHAR\nwParam:\t\t%p (hex)"),
            wParam);

        MessageBox(hDialog, Buffer, _TEXT("Catch ENTER in dialog"), MB_OK | MB_ICONINFORMATION);

        return TRUE;

    case WM_KEYDOWN:

        Sleep(500);
        
        _stprintf_s(Buffer, BufferSize, _TEXT(
            "Received:\tWM_KEYDOWN\nwParam:\t\t%p (hex)"),
            wParam);

        MessageBox(hDialog, Buffer, _TEXT("Catch ENTER in dialog"), MB_OK | MB_ICONINFORMATION);

        return TRUE;

    case WM_KEYUP:

        Sleep(500);

        _stprintf_s(Buffer, BufferSize, _TEXT(
            "Received:\tWM_KEYUP\nwParam:\t\t%p (hex)"),
            wParam);

        MessageBox(hDialog, Buffer, _TEXT("Catch ENTER in dialog"), MB_OK | MB_ICONINFORMATION);

        return TRUE;

    case WM_CLOSE:

        DestroyWindow(hDialog);
        return TRUE;

    case WM_DESTROY:

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

Таким образом добиваемся того, что клавиша отжимается до того, как показывается MessageBox. Между тем сообщения WM_KEYUP как не было, так и нет (и в Spy++ его тоже не видно).

Новые наблюдения

1)

Опытным путем установлено, что если закомментировать Sleep и MessageBox в обработчике WM_KEYDOWN, не приходит не только WM_KEYUP, но и WM_CHAR (в Spy++ последний, однако, виден):

Код

#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)
{
    const int BufferSize = 120;
    TCHAR Buffer [BufferSize];
    
    switch(Message)
    {
    case WM_INITDIALOG:

        return TRUE;

    case WM_GETDLGCODE:
        {
            LPMSG pMsg = reinterpret_cast<LPMSG>(lParam);
            
            if (pMsg)
            {
                Sleep(500);
                
                _stprintf_s(Buffer, BufferSize, _TEXT(
                    "Received:\tWM_GETDLGCODE\nMessage:\t\t%d (dec)\nwParam:\t\t%p (hex)"),
                    pMsg->message, pMsg->wParam);

                MessageBox(hDialog, Buffer, _TEXT("Catch ENTER in dialog"), MB_OK | MB_ICONINFORMATION);
            }
            else
            {
                Beep(1500, 50);
            }
        }
        SetWindowLongPtr(hDialog, DWLP_MSGRESULT, DLGC_WANTALLKEYS | DLGC_WANTCHARS);
        return TRUE;

    case WM_CHAR:

        Sleep(500);
        
        _stprintf_s(Buffer, BufferSize, _TEXT(
            "Received:\tWM_CHAR\nwParam:\t\t%p (hex)"),
            wParam);

        MessageBox(hDialog, Buffer, _TEXT("Catch ENTER in dialog"), MB_OK | MB_ICONINFORMATION);

        return TRUE;

    case WM_KEYDOWN:

        /*Sleep(500);
        
        _stprintf_s(Buffer, BufferSize, _TEXT(
            "Received:\tWM_KEYDOWN\nwParam:\t\t%p (hex)"),
            wParam);

        MessageBox(hDialog, Buffer, _TEXT("Catch ENTER in dialog"), MB_OK | MB_ICONINFORMATION);*/

        return TRUE;

    case WM_KEYUP:

        Sleep(500);

        _stprintf_s(Buffer, BufferSize, _TEXT(
            "Received:\tWM_KEYUP\nwParam:\t\t%p (hex)"),
            wParam);

        MessageBox(hDialog, Buffer, _TEXT("Catch ENTER in dialog"), MB_OK | MB_ICONINFORMATION);

        return TRUE;

    case WM_CLOSE:

        DestroyWindow(hDialog);
        return TRUE;

    case WM_DESTROY:

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

Замечу, что WM_KEYDOWN приходит (ставил точку останова)

2)

Если же вдобавок к этому закомментировать WM_GETDLGCODE, то посылается только WM_KEYUP:

Код

#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)
{
    const int BufferSize = 120;
    TCHAR Buffer [BufferSize];
    
    switch(Message)
    {
    case WM_INITDIALOG:

        return TRUE;

    case WM_GETDLGCODE:
        {
            LPMSG pMsg = reinterpret_cast<LPMSG>(lParam);
            
            if (pMsg)
            {
                /*Sleep(500);
                
                _stprintf_s(Buffer, BufferSize, _TEXT(
                    "Received:\tWM_GETDLGCODE\nMessage:\t\t%d (dec)\nwParam:\t\t%p (hex)"),
                    pMsg->message, pMsg->wParam);

                MessageBox(hDialog, Buffer, _TEXT("Catch ENTER in dialog"), MB_OK | MB_ICONINFORMATION);*/
            }
            else
            {
                Beep(1500, 50);
            }
        }
        SetWindowLongPtr(hDialog, DWLP_MSGRESULT, DLGC_WANTALLKEYS | DLGC_WANTCHARS);
        return TRUE;

    case WM_CHAR:

        Sleep(500);
        
        _stprintf_s(Buffer, BufferSize, _TEXT(
            "Received:\tWM_CHAR\nwParam:\t\t%p (hex)"),
            wParam);

        MessageBox(hDialog, Buffer, _TEXT("Catch ENTER in dialog"), MB_OK | MB_ICONINFORMATION);

        return TRUE;

    case WM_KEYDOWN:

        /*Sleep(500);
        
        _stprintf_s(Buffer, BufferSize, _TEXT(
            "Received:\tWM_KEYDOWN\nwParam:\t\t%p (hex)"),
            wParam);

        MessageBox(hDialog, Buffer, _TEXT("Catch ENTER in dialog"), MB_OK | MB_ICONINFORMATION);*/

        return TRUE;

    case WM_KEYUP:

        Sleep(500);

        _stprintf_s(Buffer, BufferSize, _TEXT(
            "Received:\tWM_KEYUP\nwParam:\t\t%p (hex)"),
            wParam);

        MessageBox(hDialog, Buffer, _TEXT("Catch ENTER in dialog"), MB_OK | MB_ICONINFORMATION);

        return TRUE;

    case WM_CLOSE:

        DestroyWindow(hDialog);
        return TRUE;

    case WM_DESTROY:

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

Замечу, что WM_GETDLGCODE и WM_KEYDOWN здесь приходят (ставил точку останова). Что неприятно, с включенной точкой останова WM_KEYUP не посылается (таймаут или переключение окна?). В Spy++ видны WM_KEYDOWN, WM_CHAR (что же он до меня-то не доходит?) и, соответственно, WM_KEYUP.

3)

Если закомментировать WM_GETDLGCODE, а WM_KEYDOWN оставить, то все проходит, как будто комментариев нет вообще.
В смысле, как в изначальном варианте (в том, который приведен в первой вставке в данном посте)

Примечание: результаты приводятся для символьной клавиши (если говорить точнее, клавиши I)

Выводы из наблюдений и вопросы

Не слишком ясная картина, не так ли. Особенно возмутил меня пункт (1). Каким образом комментарии в WM_KEYDOWN влияют на WM_CHAR? Возникает нахальная мысль: может это проделки Visual Studio?

Если кто-нибудь поймет, в чем дело, напишите. Мне это хоть и надоело, но интерес еще остался.

Искренне надеюсь, что не напортачил очередной раз.

А, чуть не забыл. Может кто-нибудь откомпилить мой код, дабы проверить результаты? 

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


Эксперт
****


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

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



Компилировать и проверять, честно говоря, в лом, да и некогда, но вот еще пара вопросов:
1) Что будет, если возвращать в WM_KEYDOWN FALSE?
2) Сделать "чистый тест" поступления сообщений, без MessageBox и точек останова, а просто выводить диагностику с помощью OutputDebugString.

Нужно добавить, что картина не совсем стандартная, но и цикл обработки сообщений у тебя непонятно какой: стандартного цикла GetMessage - TranslateMessage - DispatchMessage нет, а что там Windows делает внутри DialogBox - хто знает.
Самое интересное, конечно, это исчезновение WM_KEYUP... Просто удивительно... 


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


Опытный
**


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

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



1) Пробовал возвращать FALSE. Ничего от этого не меняется.

2) Чистый тест поступления сообщений

Новая тестовая программка:
Код

// ============================================================================

//#define _ENABLE_SLEEP_
//#define _ENABLE_MESSAGE_BOX_
#define _ENABLE_OUTPUT_DEBUG_STRING_

// ============================================================================

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

#include "resource.h"

#ifdef _ENABLE_SLEEP_
#define _SLEEP_IF_DEFINED_ Sleep(500);
#else
#define _SLEEP_IF_DEFINED_ ;
#endif

#if defined (_ENABLE_MESSAGE_BOX_) || defined (_ENABLE_OUTPUT_DEBUG_STRING_)
#define _FILL_BUFFER_IF_DEFINED_
#endif

#ifdef _ENABLE_MESSAGE_BOX_
#define _SHOW_MESSAGE_BOX_IF_DEFINED_ MessageBox(hDialog, Buffer, _TEXT("Catch ENTER in dialog"), MB_OK | MB_ICONINFORMATION);
#else
#define _SHOW_MESSAGE_BOX_IF_DEFINED_ ;
#endif

#ifdef _ENABLE_OUTPUT_DEBUG_STRING_
#define _OUTPUT_DEBUG_STRING_IF_DEFINED_ OutputDebugString(Buffer);
#else
#define _OUTPUT_DEBUG_STRING_IF_DEFINED_ ;
#endif

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)
{
#ifdef _FILL_BUFFER_IF_DEFINED_

    const int BufferSize = 120;
    TCHAR Buffer [BufferSize];

#endif
    
    switch(Message)
    {

    case WM_INITDIALOG:

        return TRUE;

    case WM_GETDLGCODE:
        {
            LPMSG pMsg = reinterpret_cast<LPMSG>(lParam);
            
            if (pMsg)
            {

                _SLEEP_IF_DEFINED_
                
#ifdef _FILL_BUFFER_IF_DEFINED_

                _stprintf_s(Buffer, BufferSize, _TEXT(
                    "Received:     WM_GETDLGCODE\nMessage:      %d (dec)\nwParam:       %p (hex)\n\n"),
                    pMsg->message, pMsg->wParam);
#endif
                _SHOW_MESSAGE_BOX_IF_DEFINED_
                _OUTPUT_DEBUG_STRING_IF_DEFINED_
            }
            else
            {
                Beep(1500, 50);
            }
        }
        SetWindowLongPtr(hDialog, DWLP_MSGRESULT, DLGC_WANTALLKEYS | DLGC_WANTCHARS);
        return TRUE;

    case WM_CHAR:

        _SLEEP_IF_DEFINED_
                
#ifdef _FILL_BUFFER_IF_DEFINED_

        _stprintf_s(Buffer, BufferSize, _TEXT(
            "Received:     WM_CHAR\nwParam:       %p (hex)\n\n"),
            wParam);
#endif
        _SHOW_MESSAGE_BOX_IF_DEFINED_
        _OUTPUT_DEBUG_STRING_IF_DEFINED_
        return TRUE;

    case WM_KEYDOWN:

        _SLEEP_IF_DEFINED_

#ifdef _FILL_BUFFER_IF_DEFINED_
        
        _stprintf_s(Buffer, BufferSize, _TEXT(
            "Received:     WM_KEYDOWN\nwParam:       %p (hex)\n\n"),
            wParam);
#endif
        _SHOW_MESSAGE_BOX_IF_DEFINED_
        _OUTPUT_DEBUG_STRING_IF_DEFINED_
        return TRUE;

    case WM_KEYUP:

        _SLEEP_IF_DEFINED_

#ifdef _FILL_BUFFER_IF_DEFINED_

        _stprintf_s(Buffer, BufferSize, _TEXT(
            "Received:     WM_KEYUP\nwParam:       %p (hex)\n\n"),
            wParam);
#endif

        _SHOW_MESSAGE_BOX_IF_DEFINED_
        _OUTPUT_DEBUG_STRING_IF_DEFINED_
        return TRUE;

    case WM_CLOSE:

        DestroyWindow(hDialog);
        return TRUE;

    case WM_DESTROY:

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

Прошу извинить на низкую читабельность кода.

В этот раз все просто. Комментируй WM_KEYDOWN или нет, получаем следующее:

В окошке Output:
Код

Received:     WM_GETDLGCODE
Message:      256 (dec)
wParam:       00000049 (hex)

Received:     WM_KEYDOWN
wParam:       00000049 (hex)

Received:     WM_KEYUP
wParam:       00000049 (hex)

В Spy++:
Код

WM_KEYDOWN
WM_CHAR
WM_KEYUP

Что тут сказать? Опять пропал WM_CHAR smile 

Ради эксперимента вновь включил MessageBox'ы. Получил следующее

В окошке Output и в MessageBox'ах
Код

Received:     WM_GETDLGCODE
Message:      256 (dec)
wParam:       00000049 (hex)

Received:     WM_CHAR
wParam:       00000069 (hex)

Received:     WM_KEYDOWN
wParam:       00000049 (hex)

В Spy++
Код

WM_KEYDOWN
WM_CHAR

Как я понял, WM_CHAR и WM_KEYUP не могут существовать вместе smile (разве что в случае, описанном несколько постов назад)

3) 
Цитата(Earnest @  11.7.2006,  16:55 Найти цитируемый пост)
 но и цикл обработки сообщений у тебя непонятно какой: стандартного цикла GetMessage - TranslateMessage - DispatchMessage нет, а что там Windows делает внутри DialogBox - хто знает

Мы в данном топике рассматриваем особенности диалоговых окон. В обычном окне все должно быть OK, поскольку там нет этой самой обработки клавиш по умолчанию. С немодальном диалоговом окном я попробовал. Если применять IsDislogMessage, ничего не меняется. Если обходится без IsDialogMessage, окно функционирует как обычное, не диалоговое (приходят, как и должно быть, WM_KEYDOWN, WM_CHAR, WM_KEYUP). WM_GETDLGCODE не приходит.

Если включить MessageBox'ы, то и в окошке Output, и в MessageBox'ах, и в Spy++:
Код

Received:     WM_CHAR
wParam:       00000069 (hex)

Received:     WM_KEYDOWN
wParam:       00000049 (hex)

Есть что-то общее с диалоговыми окнами, не правда ли?

4) Общие вопросы и предложения

Earnest, спасибо за OutputDebugString. Про эту функцию я тоже не знал.

Кто знает, почему Spy++ не поддерживает помещение текста в буфер обмена? Такая полезная возможность была бы.

Вопрос. Как отлаживать код, подобный моему (с макросами)?     

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


Эксперт
****


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

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



0x07L, молодец, вот уж не поленился!

Цитата(0x07L @  11.7.2006,  19:13 Найти цитируемый пост)
Вопрос. Как отлаживать код, подобный моему (с макросами)?  

А в чем, собственно, вопрос? Я вижу только одну проблему: отладочные макросы сильно замусоривают код... Лучше, конечно, делать их более незаметными.

Во-первых, нет смысла выводить отладочную информацию в MessageBox - это всегда нарушает нормальный ход выполнения (переключение активных окон и т.д.). От использования Sleep - тоже польза сомнительная (разве что с разными потоками работаешь). Т.е. для вывода достаточно трассировочных сообщений. Приходим к следующему:

Код

// чтобы отключить отладочный вывод, нужно эту строчку закомментировать
#define DUMP_ENABLED
#ifdef DUMP_ENABLED
   #define DEBUG_DUMP   TRACE
#else
   #define DEBUG_DUMP __noop
#endif

// Здесь я использую MFC-шный макрос TRACE, который в конце концов превращается 
// в OutputDebugString; если не использовать MFC, несложно написать аналог, чтобы сразу иметь 
// форматированный вывод, без всяких буферов

// далее, использование

 ...
 case WM_KEYDOWN:
     DEBUG_DUMP (_TEXT("Received:     WM_KEYDOWN\nwParam:       %p (hex)\n\n"),  wParam);
     // делаем что-то полезное
     ...
     return TRUE;


При желании все же иметь MessageBox, можно эту возможность включить в функцию, которая выполняет DEBUG_DUMP. Если отладкой управляют несколько макросов (разными опциями) их реализацию нужно выносить в вспомогательную функцию:

Код

void DoDebugDump (LPCTSTR psFmt, ...)
{
   va_list args; 
   va_start (args, psFmt);

   CString buf;
   buf.FormatV (psFmt, args);
   va_end (args);

   #ifdef USE_MESSAGE_BOX
      MessaegBox(...buf ...);
   #endif

   OutputDebugString (buf); 

   // возможно, что-то еще,... вывод в файл, например
}

#define DEBUG_DUMP DoDebugDump

Коротко, смысл в следущем. 
Никаких #ifdef\#endif внутри полезного кода.
Никаких временных переменных для отладки. Если в них все же возникает необходимость, написать вспомогательные функции, классы и т.д., за пределами полезного кода.
Отладочный макрос должен записываться одним предложением, желательно покороче.
И т.д. 
Тогда полезный код сохраняет прозрачность, отладка включается \ отключается легко и очевидно. И проблем с отладкой не возникает. 

 


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


Опытный
**


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

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



Здорово!

А я тут заметил еще момент. Флажок DLGC_WANTCHARS (один из тех, которые мы возвращаем из обработчика WM_GETDLGCODE) вообще не играет роли. Если его не указывать, все остается так, как было. Интересно, почему в MSDN об этом не упоминается. 
PM MAIL   Вверх
Earnest
Дата 11.7.2006, 19:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Да? А если вообще GetDlgCode не обрабатывать, тоже? По идее, вроде, должно.
Т.е. меня изначально удивило, что в диалоге что-то меняется от наличия\отсутствия обработчика GETDLGCODE. А в MSDN это как раз написано, но не прямо: GETDLGCODE стандартно имеет смысл для контролов, диалог по-умолчанию вроде должен получать весь ввод (который контролы схватить не успели). 
Только почему-то у тебя в самом начале вроде не получалось получить ENTER. Я ранний код не очень внимательно смотрела (большой  smile ), так в чем там разница? 


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


Опытный
**


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

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



Если не использовать в обработчике WM_GETDLGCODE SetWindowLong(...MSGRESULT...WANTALLKEYS...), то Enter будет приходить только через lParam этого самого WM_GETDLGCODE и больше его не будет видно нигде. 
PM MAIL   Вверх
Earnest
Дата 11.7.2006, 20:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Понятно, т.е. WANTALLKEYS нужно, а WANTCHARS нет...

Интересно, откуда все же разница между выводом Spy и твоей DialogProc? По идее, Spy подключает хук к процессу и выводит все проходящие сообщения. Остается только предположить, что внутри цикла DialogBox происходит какая-то трансляция сообщений. Т.е. Spy, видимо, подключается непосредственно к очереди, а в диалоговую процедуру попадают уже процеженные сообщения ... 


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


Опытный
**


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

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



Причем сообщения могут не только процеживаться, но еще и добавляться (WM_GETDLGCODE). Без SendMessage и PostMessage, кстати.

Что мы имеем:
1) WM_KEYUP не посылается из-за переключения окна или истечения времени ожидания.
2) Что происходит с WM_CHAR, непонятно. Ясно только то, что с ним что-то делает цикл обработки сообщений диалогового окна 

Это сообщение отредактировал(а) 0x07L - 11.7.2006, 20:38
PM MAIL   Вверх
diverkaz
Дата 26.11.2007, 15:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 26.11.2007

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



У меня тоже проблема с Enter  и ListView, почитал эту тему и попробова... И в результате он у меня в WM_GETDLGCODE ВОБЩЕ не заходит.. подскажите в чем проблемма... может у диалога стиль кокойнить особый нужен... 
Пробовал даже копиваровать ваш исходник... но все равно не заходит ни в WM_GETDLGCODE ни в WM_KEYDOWN?
PM MAIL   Вверх
AndreyK
Дата 26.11.2007, 16:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 102
Регистрация: 15.3.2007

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



У меня была та-же проблема, но с другими элементами - они сначала сами обрабатывают свои сообщения, а потом только соизволяют передать (ненужное), обработчику.

Я эту проблему решил, при помощи перехвата всех сообщений в программе (SetWindowsHook).
При старте диалога я включаю режим фильтрации и сравниваю хендл окна, если совпадает - обрабатываю.

Код

int CALLBACK FilterFunc(int nCode,WORD wParam,DWORD lParam)
{
    LPMSG lpmsg = (LPMSG)lParam;

    if (lpmsg->message == WM_COMMAND||lpmsg->message == WM_KEYDOWN||lpmsg->message == WM_SYSKEYDOWN ) { //&& lpmsg->wParam == VK_F1
      if (dlgHWnd!=0) {
            if (OnMyKeydown(dlgZakazHWnd, lpmsg->message,lpmsg->wParam,lpmsg->lParam)) {
             //это функция обработки события
          return true;
        };
      };
    }

    DefHookProc(nCode, wParam, lParam, &lpFilterFunc);

    return 0;
}

//это начальный перехват (при запуске программы)
bool RunStopHook(bool State, HINSTANCE hInstance) {
 
  if (State) {
    lpProcInstance = (HOOKPROC) MakeProcInstance(FilterFunc, hInstance);
    if (lpProcInstance == NULL)
      return FALSE;
    lpFilterFunc = SetWindowsHook(WH_MSGFILTER, lpProcInstance);
  } else {
    UnhookWindowsHookEx(lpFilterFunc);
  };
 return true;
};

//а так я в диалоге включаю обработку перехвата события
...
  case WM_INITDIALOG:
      dlgHWnd = hDlg;
...
//а так выключаю
     dlgHWnd = 0;
     EndDialog(hDlg, LOWORD(wParam));
...



Это сообщение отредактировал(а) AndreyK - 26.11.2007, 16:34
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "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.0922 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


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

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