Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.88/8: Рейтинг темы: голосов - 8, средняя оценка - 4.88
 Аватар для Igor-84
28 / 27 / 11
Регистрация: 04.03.2010
Сообщений: 199

Подмена установленной оконной процедуры на процедуру, являющуюся членом класса

29.05.2014, 18:17. Показов 1872. Ответов 5
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте! У меня проблема с подменой установленной оконной процедуры на процедуру, являющуюся членом класса. Делал по разным примерам, но всё равно должным образом не работает. Итак код следующий:
C++
1
2
3
4
5
6
7
8
9
//.h
class TMyClass
{
public:
TMyClass();
~TMyClass();
LRESULT CALLBACK myWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
private:
};
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
75
76
77
78
79
80
81
82
83
//.cpp
static LRESULT CALLBACK common_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
TMyClass *myclass_ptr = (TMyClass *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
    if(myclass_ptr != NULL)
    {
    return myclass_ptr->myWndProc(hwnd, msg, wParam, lParam);
    }
 
switch(msg)
{
    case WM_CREATE:
    {
    LPCREATESTRUCT lpcs;
    lpcs = (LPCREATESTRUCT)lParam;
    SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)lpcs->lpCreateParams);
    return 0;
    }
 
    case WM_DESTROY:
    {
    PostQuitMessage(0);
    return 0;
    }
}
 
return DefWindowProc(hwnd, msg, wParam, lParam);
//----------------------------
TMyClass::TMyClass()
{
const wchar_t *WndClassName = L"MyWndClassName";
WNDCLASSEX WndClassStruct;
WNDCLASSEX CheckClassStruct;
 
    if(GetClassInfoEx(hInstance, WndClassName, &CheckClassStruct) == 0)
    {
    ZeroMemory(&WndClassStruct, sizeof(WNDCLASSEX));
    WndClassStruct.style = CS_CLASSDC | CS_DBLCLKS;
    WndClassStruct.cbSize = sizeof(WNDCLASSEX);
    WndClassStruct.lpfnWndProc = (WNDPROC)common_WndProc;
    WndClassStruct.cbClsExtra = 0;
    WndClassStruct.cbWndExtra = 0;
    WndClassStruct.hInstance = hInstance;
    WndClassStruct.hIcon = NULL;
    WndClassStruct.hCursor = LoadCursor(NULL, IDC_ARROW);
    WndClassStruct.hbrBackground = (HBRUSH)(COLOR_WINDOW);
    WndClassStruct.lpszMenuName = NULL;
    WndClassStruct.lpszClassName = WndClassName;
 
        if (!RegisterClassEx(&WndClassStruct))
        {
        MessageBox(0, L"Ошибка регистрации класса", L"Ошибка", MB_OK);
        return;
        }
    }
 
HWND my_Wnd = NULL;
my_Wnd = CreateWindowEx(0, WndClassName, L"WndName", WS_POPUPWINDOW | WS_VISIBLE, 100, 100, 200, 200, NULL, NULL, hInstance, this);
 
UpdateWindow(my_Wnd);
ShowWindow(my_Wnd, SW_SHOW);
}
//----------------------------
LRESULT CALLBACK TMyClass::myWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
    {
    case (WM_LBUTTONDOWN):
        {
        MessageBox(0, L"WM_LBUTTONDOWN", L"cap", MB_OK);
        }
        break;
 
        case (WM_LBUTTONDBLCLK):
        {
        MessageBox(0, L"WM_LBUTTONDBLCLK", L"cap", MB_OK);
        PostMessage(hwnd, WM_CLOSE, 0, 0);
        return 0;
        }
    }
    return 0;
}
//----------------------------
При этом окно создаётся, но оно не отвечает на сообщения WM_LBUTTONDOWN, WM_LBUTTONDBLCLK, описанные в новой процедуре TMyClass::myWndProc.
Я пробовал в конце функции TMyClass() добавить цикл обработки сообщений:
C++
1
2
3
4
5
6
MSG msg;
while(PeekMessage(&msg, my_Wnd, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Но это также ничего не даёт.
Также я заметил, что всё-таки происходит вход в case WM_CREATE, а затем всё время выполняется этот участок кода старой оконной процедуры:
C++
1
2
3
4
    if(myclass_ptr != NULL)
    {
    return myclass_ptr->myWndProc(hwnd, msg, wParam, lParam);
    }
Напрашивается вывод, что новая оконная процедура не была назначена указанному окну. Ума не приложу, что здесь не так?
Подскажите, пожалуйста, где здесь ошибка?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
29.05.2014, 18:17
Ответы с готовыми решениями:

Подмена оконной процедуры для кнопки
Доброго времени суток! Пытаюсь написать обёртку над WINAPI для будущего проекта, который должен спокойно работать на WinXP на очень...

Какое число нужно возвращать из оконной процедуры?
Возвращается результат вызова DefWindowProc() в тех случаях, когда сообщение не обрабатывает пользователь. А если сообщение...

Каковы в x64 типы параметров оконной процедуры?
По-прежнему HWND, UINT, WPARAM, LPARAM?

5
60 / 60 / 6
Регистрация: 28.05.2012
Сообщений: 222
29.05.2014, 20:02
Цитата Сообщение от Igor-84 Посмотреть сообщение
Напрашивается вывод, что новая оконная процедура не была назначена указанному окну.
Не согласен. Процедура назначается, но в ней нет обработки перерисовки окна. Другими словами система шлет окну сообщение WM_PAINT, а оно в ответ возвращает 0 (что означает неудачу). Получив такой результат система вновь шлет WM_PAINT, и .т.д. Поставь обработчик по умолчанию.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
switch(msg)
    {
    case (WM_LBUTTONDOWN):
        {
        MessageBox(0, L"WM_LBUTTONDOWN", L"cap", MB_OK);
        }
        break;
 
        case (WM_LBUTTONDBLCLK):
        {
        MessageBox(0, L"WM_LBUTTONDBLCLK", L"cap", MB_OK);
        PostMessage(hwnd, WM_CLOSE, 0, 0);
        return 0;
        }
    }
    return DefWindowProc(hwnd, msg, wParam, lParam);
Всегда ставь обработчик по умолчанию на сообщения, которые не обрабатываешь.
P.S. Сегодня эпидемия? Все обертки на winapi пишут!
1
 Аватар для Igor-84
28 / 27 / 11
Регистрация: 04.03.2010
Сообщений: 199
29.05.2014, 23:20  [ТС]
Demy85, большое спасибо! Теперь работает, как нужно. Ещё один момент - а это нормально, что код:
C++
1
2
3
4
if(myclass_ptr != NULL)
{
return myclass_ptr->myWndProc(hwnd, msg, wParam, lParam);
}
продолжает выполняться при любых действиях с окном - кликах, перемещениях мышью и пр.? Правильно ли я понимаю, что "старая" оконная процедура common_WndProc, продолжает получать сообщения от целевого окна, только перенаправляя обработку этих сообщений в новую процедуру TMyClass::myWndProc?
0
60 / 60 / 6
Регистрация: 28.05.2012
Сообщений: 222
30.05.2014, 09:05
Цитата Сообщение от Igor-84 Посмотреть сообщение
Правильно ли я понимаю, что "старая" оконная процедура common_WndProc, продолжает получать сообщения от целевого окна, только перенаправляя обработку этих сообщений в новую процедуру TMyClass::myWndProc?
Правильно, ведь мы не заменили оконную процедуру, а только установили пользовательские данные (указатель на экземпляр класса). Поэтому задача оконной процедуры, после инициализации, просто перенаправлять сообщение экземпляру класса TMyClass, связанному с данным окном.
1
 Аватар для Igor-84
28 / 27 / 11
Регистрация: 04.03.2010
Сообщений: 199
09.09.2014, 11:48  [ТС]
После подмены оконной функции функцией-членом класса, появилась задача установить хук на события мыши. И здесь в качестве второго параметра функции SetWindowsHookEx нужно передать указатель на колбек-функцию:
C++
1
SetWindowsHookEx (WH_MOUSE, (HOOKPROC)MouseWndProc, //...);
Demy85, подскажи, пожалуйста, как, и можно ли вообще сделать MouseWndProc членом класса и использовать её в SetWindowsHookEx?
0
60 / 60 / 6
Регистрация: 28.05.2012
Сообщений: 222
10.09.2014, 11:54
Цитата Сообщение от Igor-84 Посмотреть сообщение
Demy85, подскажи, пожалуйста, как, и можно ли вообще сделать MouseWndProc членом класса и использовать её в SetWindowsHookEx?
Редко работал с hook-ами. Могу сказать только что судя по описанию этой функции MouseWndProc можно сделать только статическим членом класса, это при условии что будешь перехватывать события своего приложения. Иначе функция MouseWndProc должна содержаться в DLL и членом класса соответственно быть не может.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
10.09.2014, 11:54
Помогаю со студенческими работами здесь

Отправка сообщения главному окну (SendMessage) из оконной процедуры дочернего окна
При нажатии Энтера в дочернем окне управления hwndEditFKern, главное окно hwnd должно обработать нажатие Энтера, но почему то как я понимаю...

Получить константу из экземпляра класса, который является членом другого класса
class test { const STATUS = 1; } $a = new test(); echo $a::STATUS . PHP_EOL; // работает class bar {

Как получить private переменную класса, функцей членом другого класса
Игра змейка: Есть класс поле в котором содержится размеры поля: class field { private: int FIELD_START; int...

Ввод вывод переменной класса, являющейся членом другого класса
Приветствую! У меня есть 2 класса: подкласс filling: class filling { private: int number; char *name; float filmass;

Как сделать членом класса экземпляр этого же класса
class Operation { public: bool type; //true = operation, false = number char Operator; Operation L_Op; Operation R_Op; ...


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

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
Установка Emscripten SDK (emsdk) и CMake на Windows для сборки C и C++ приложений в WebAssembly (Wasm)
8Observer8 30.01.2026
Чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. Система контроля версиями Git. . .
Подключение Box2D v3 к SDL3 для Android: физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
Влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru