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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как перехватить нажатие Enter? В ListView 
:(
    Опции темы
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   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "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.0743 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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