Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.78/9: Рейтинг темы: голосов - 9, средняя оценка - 4.78
0 / 0 / 0
Регистрация: 12.03.2015
Сообщений: 10

Сообщение WM_KEYDOWN и таймер

15.03.2015, 17:01. Показов 2080. Ответов 21
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток, пишу тетрис и возникла проблема, после включения таймера не обрабатываются сообщения WM_KEYDOWN, вообще ничего не происходит при нажатии клавиш, даже если выключить таймер. До включения все работает правильно. Поиск по интернету ничем не помог, может есть какие-то особенности которые я упустил или ошибка скорей всего в коде? Заранее спасибо за ответ.

Добавлено через 11 минут
Up, дело не в таймере, а в нажатии кнопки на окне. После сообщения WM_COMMAND не обрабатываются WM_KEYDOWN, но почему так, не понимаю.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
15.03.2015, 17:01
Ответы с готовыми решениями:

WM_KEYDOWN
на мсдн написано что функцию вызывать так, case WM_KEYDOWN: switch (wParam) { case VK_UP: // up was pressed...

WM_KEYDOWN
когда программе поступает сообщение WM_KEYDOWN обрабатываю его так HANDLE_MSG(hwnd,WM_KEYDOWN,OnKeydown); дальше есть функция void...

Таймер на сообщение!!!
Как сделать, чтобы появившийся MsgBox автоматически закрылся через 5-10 секунд? С уважением, Игорь!!!

21
Заблокирован
15.03.2015, 17:47
Цитата Сообщение от Cable_Guy Посмотреть сообщение
После сообщения WM_COMMAND не обрабатываются WM_KEYDOWN, но почему так, не понимаю.
Покажи код, возможно, что где-то не хватает break; или return 0;
0
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
15.03.2015, 19:06
Ты неправильно обрабатываешь сообщения.
0
0 / 0 / 0
Регистрация: 12.03.2015
Сообщений: 10
15.03.2015, 22:53  [ТС]
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
    switch (message)
    {
    case WM_COMMAND:
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        if(LOWORD(wParam) == START_BUTTON_ID)
        {
            SetTimer(hWnd, TIMER_ID, 100, NULL);
        }
        break;
 
    case WM_TIMER:
        if(wParam == TIMER_ID)
        {   
            check = game_obj->move_obj(hWnd);
            if(check == FALSE)
            {
                game_obj->object::new_obj();
                check_score();
                InvalidateRect(hWnd, &score_rect, NULL);
                check = TRUE;
            }
        }
        break;
 
    case WM_KEYDOWN:
        game_obj->change_pos(wParam);
        InvalidateRect(hWnd, &game_disp, NULL);
        break;
 
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
    
        hBrush = CreateSolidBrush(RGB(0, 0, 0)); // Background
        SelectObject(hdc,hBrush);
        Rectangle(hdc, 0, 0, 500,800);
        DeleteObject(hBrush);
 
        hBrush = CreateSolidBrush(RGB(200, 0, 70));
        SelectObject(hdc,hBrush);
        for(int i = 0; i < 10; i++)
            for(int j = 0; j < 20; j++)
                if(field[i][j] == TRUE)
                    Rectangle(hdc, (347 - i * 37), (717 - j * 37), (347 - i * 37) + 35, (717 - j * 37) + 35);
        DeleteObject(hBrush);
 
        FrameRect(hdc, &r, CreateSolidBrush(RGB(0, 150, 255)));
 
        do 
        {
            s /= 10;
            k++;
        } while(s > 0);
 
        sprintf_s(buf, "%d", score);
        score_font = CreateFontA(24, 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, 
                                DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Courier");
        SelectObject(hdc, score_font);
        ::TextOutA(hdc, 392, 60, buf, k);
        DeleteObject(score_font);
 
        EndPaint(hWnd, &ps);
        break;
 
    case WM_DESTROY:
        KillTimer(hWnd, TIMER_ID);
        PostQuitMessage(0);
        break;
 
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}
Добавлено через 4 минуты
Вроде везде хватает break...
0
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
16.03.2015, 08:06
Не замечаю проблему...
0
Модератор
Эксперт по электронике
8981 / 6748 / 921
Регистрация: 14.02.2011
Сообщений: 23,869
16.03.2015, 08:14
Цитата Сообщение от Cable_Guy Посмотреть сообщение
После сообщения WM_COMMAND не обрабатываются WM_KEYDOWN, но почему так, не понимаю.
смотри
Цитата Сообщение от Cable_Guy Посмотреть сообщение
C++
1
2
3
4
5
6
7
8
case WM_COMMAND:
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        if(LOWORD(wParam) == START_BUTTON_ID)
        {
            SetTimer(hWnd, TIMER_ID, 100, NULL);
        }
        break;
если ты не отрабатываешь WM_COMMAND:
то все равно идет выброс из ветки и return 0;
система не отрабатывает другие WM_COMMAND
попробуй так
C++
1
2
3
4
5
6
7
8
case WM_COMMAND:
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        if(LOWORD(wParam) == START_BUTTON_ID)
        {
            SetTimer(hWnd, TIMER_ID, 100, NULL);
        }
        return DefWindowProc(hWnd, message, wParam, lParam);
0
0 / 0 / 0
Регистрация: 12.03.2015
Сообщений: 10
17.03.2015, 01:24  [ТС]
К сожалению не помогло...
0
Модератор
Эксперт по электронике
8981 / 6748 / 921
Регистрация: 14.02.2011
Сообщений: 23,869
17.03.2015, 07:02
Цитата Сообщение от Cable_Guy Посмотреть сообщение
game_obj->object::new_obj();
дайка определение что такое game_obj?
ну и заодно object
что это за метод new_obj()????
он статический?
0
0 / 0 / 0
Регистрация: 12.03.2015
Сообщений: 10
17.03.2015, 21:07  [ТС]
C++
1
object *game_obj = new object();
Класс object, создает кубик в игре (Пока что только по кубикам все, без фигур)
new_obj() создает новый кубик когда предыдущий доходит до нижних кубиков
Нет, не статический

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class object
{
private: 
    int xpos, ypos;
public:
    object()
    {
        srand((unsigned) time(NULL));
        xpos = rand() % 10;
        ypos = 20;
    }
    ~object() {};
    bool move_obj(HWND);
    void new_obj();
    void change_pos(int);
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
bool object::move_obj(HWND hWnd)
{
    if(ypos > 0 && field[xpos][ypos-1] == FALSE)
    {
        field[xpos][ypos] = FALSE;
        field[xpos][ypos-1] = TRUE;
        ypos--;
        InvalidateRect(hWnd, &game_disp, NULL);
        return TRUE;
    }
    else
        return FALSE;
}
 
void object::new_obj()
{
    srand((unsigned) time(NULL));
    xpos = rand() % 10;
    ypos = 20;
}
 
void object::change_pos(int wmId)
{
    switch(wmId)
    {
        case VK_LEFT: field[0][0] = TRUE; break;
        case VK_RIGHT: field[1][0] = TRUE; break;
        case VK_DOWN: field[2][0] = TRUE; break;
    }
}
0
Модератор
Эксперт по электронике
8981 / 6748 / 921
Регистрация: 14.02.2011
Сообщений: 23,869
17.03.2015, 21:52
Цитата Сообщение от Cable_Guy Посмотреть сообщение
game_obj->object::new_obj();
тогда переведи что ты этим хотел сказать?
0
0 / 0 / 0
Регистрация: 12.03.2015
Сообщений: 10
18.03.2015, 00:38  [ТС]
Когда кубик доходит до низа, создается новый кубик, т.е. вызывается функция new_obj()
0
Модератор
Эксперт по электронике
8981 / 6748 / 921
Регистрация: 14.02.2011
Сообщений: 23,869
18.03.2015, 06:17
Цитата Сообщение от Cable_Guy Посмотреть сообщение
Когда кубик доходит до низа, создается новый кубик, т.е. вызывается функция new_obj()
с точки зрения языка скажи, я теряюсь
0
0 / 0 / 0
Регистрация: 12.03.2015
Сообщений: 10
18.03.2015, 18:19  [ТС]
Вызываем функцию new_object() класса object через указатель на объект класса object, *game_obj
Думаю названия не совсем удачно выбрал, выходит запутанно
0
Модератор
Эксперт по электронике
8981 / 6748 / 921
Регистрация: 14.02.2011
Сообщений: 23,869
18.03.2015, 18:51
Цитата Сообщение от Cable_Guy Посмотреть сообщение
Вызываем функцию new_object() класса object через указатель на объект класса object, *game_obj
тогда это должно выглядеть так
C++
1
game_obj->new_object();
0
2838 / 1647 / 254
Регистрация: 03.12.2007
Сообщений: 4,222
18.03.2015, 19:11
Вот ещё такое есть:
Цитата Сообщение от DeleteObject, MSDN
Do not delete a drawing object (pen or brush) while it is still selected into a DC.
0
0 / 0 / 0
Регистрация: 12.03.2015
Сообщений: 10
18.03.2015, 19:38  [ТС]
Ну сути не меняет, но да, object:: лишнее

Стили текста и кисти удаляю после каждого использования, проблема с этим была, но она влияла только на отображения цветов, а так все работало как надо, кроме нажатия на клавиши
C++
1
2
3
        SelectObject(hdc,hBrush);
        Rectangle(hdc, 0, 0, 500,800);
        DeleteObject(hBrush);
C++
1
2
3
4
5
6
    SelectObject(hdc,hBrush);
        for(int i = 0; i < 10; i++)
            for(int j = 0; j < 20; j++)
                if(field[i][j] == TRUE)
                    Rectangle(hdc, (347 - i * 37), (717 - j * 37), (347 - i * 37) + 35, (717 - j * 37) + 35);
        DeleteObject(hBrush);
C++
1
2
3
        SelectObject(hdc, score_font);
        ::TextOutA(hdc, 392, 60, buf, k);
        DeleteObject(score_font);
0
Модератор
Эксперт по электронике
8981 / 6748 / 921
Регистрация: 14.02.2011
Сообщений: 23,869
18.03.2015, 20:27
Цитата Сообщение от Cable_Guy Посмотреть сообщение
SelectObject(hdc,hBrush);
где второй SelectObject???
если не будешь выбирать кисть по умолчанию DeleteObject(hBrush); просто не сработает, кисть выбрана и получишь утечку ресурсов
когда GDI ресурсов много программа виснет
вот так нужно
C++
1
2
3
4
5
6
7
8
   HRBRUSH oldBr=SelectObject(hdc,hBrush);// запомнили объект по умолчанию
        for(int i = 0; i < 10; i++)
            for(int j = 0; j < 20; j++)
                if(field[i][j] == TRUE)
                    Rectangle(hdc, (347 - i * 37), (717 - j * 37), (347 - i * 37) + 35, (717 - j * 37) + 35);
        
    SelectObject(hdc,oldBr);// выбрали объект по умолчанию
   DeleteObject(hBrush);
ну и в остальных местах где работаешь с ресурсами примерно также
чтобы увидеть утечку GDI ресурсов, открой диспетчер задач, войди на вкладку процессы , в меню "вид"- "выбрать столбцы"
там выбери "объекты GDI" и посмотри как они утекают в твоей программе
0
0 / 0 / 0
Регистрация: 12.03.2015
Сообщений: 10
19.03.2015, 17:41  [ТС]
C++
1
HRBRUSH oldBr=SelectObject(hdc,hBrush);// запомнили объект по умолчанию
На присваивание ругается, но утечка и правда есть. Спасибо, не знал об этом.
А решение ошибки нашел случайно, после нажатия клавиши окно оставалось поверх других окон, но было вне фокуса, и нажатие мыши на окно почему-то не брало окно в фокус. Но добавил после WM_COMMAND SetFocus и все работает.
Спасибо за помощь, буду разбираться с утечкой
0
Модератор
Эксперт по электронике
8981 / 6748 / 921
Регистрация: 14.02.2011
Сообщений: 23,869
19.03.2015, 18:04
Цитата Сообщение от Cable_Guy Посмотреть сообщение
На присваивание ругается,
как именно ругается?
может явно привести нужно я давно на WinApi не писал
C++
1
HBRUSH oldBr=(HBRUSH)SelectObject(hdc,hBrush);// запомнили объект по умолчанию
Добавлено через 1 минуту
нашел
Цитата Сообщение от ValeryS Посмотреть сообщение
HRBRUSH oldBr=SelectObject(hdc,hBrush);// запомнили объект по умолчанию
у меня опечатка не HRBRUSH а HBRUSH
0
0 / 0 / 0
Регистрация: 12.03.2015
Сообщений: 10
19.03.2015, 18:27  [ТС]
1>d:\projects\1\tetris\tetris\tetris.cpp (184): error C2440: 'initializing' : cannot convert from 'HGDIOBJ' to 'HBRUSH'
1> Conversion from 'void*' to pointer to non-'void' requires an explicit cast

Сама функция делает присваивание выбранной кисти в hBrush, так что сохранить текущую так не выйдет. Но утечку убрал, создавало много шрифтов, сделал глобальным переменную где шрифт храниться и вместо создания каждый раз новой кисти черного цвета, использовал стандартную черную, теперь все нормально работает.
Не знал о таких свойствах диспетчера, очень помогает
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
19.03.2015, 18:27
Помогаю со студенческими работами здесь

Не работает WM_KEYDOWN
Доброго времени суток! Возникла проблема: после нажатия на кнопку &quot;New Game&quot; программа почему-то перестает принимать сообщения с...

Не работает WM_KEYDOWN
Помогите плиз. Вот кусок кода в оконной процедуре: ... case WM_KEYDOWN: switch (wParam) { case VK_LEFT: if(MatrLine == 2)...

Не отвечает на wm_keydown
procedure TBoard.WndProc(var msg: TMessage); //Оконная процедура. begin inherited WndProc(msg); case msg.Msg of ...

Не работает WM_KEYDOWN
Здравствуите , понимаю что таких тем много , читал и пробывал но все грустно . И вроде есть HANDLE_MSG(WM_KEYDOWN) как его объявить и...

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


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Программа принимает математическое выражение в виде строки и выдаёт его производную в виде строки и вычисляет значение производной при заданном х Логарифм записывается как: (x-2)log(x^2+2) -. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru