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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Классы и WindowProc 
:(
    Опции темы
Vizator
Дата 10.12.2007, 16:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



В структуре WNDCLASS есть параметр lpfnWndProc.
У меня есть класс, который будет рулить всеми действимя с окном, хотлеосьбы чтобы и калл бэк функция была внутри класса, возможно ли это и как это сделать ?
PM MAIL   Вверх
Lazin
Дата 10.12.2007, 16:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



Можно, но только если она статическая.
PM MAIL Skype GTalk   Вверх
Vizator
Дата 10.12.2007, 16:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(Lazin @  10.12.2007,  16:50 Найти цитируемый пост)
Можно, но только если она статическая. 


Как это сделать ?
PM MAIL   Вверх
Lazin
Дата 10.12.2007, 17:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



Вот так
Код

class MyClass
{
 static LRESULT CALLBACK MainWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
    return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
 }
};

Если метод не будет статическим, его нельзя будет передать в качестве ф-ии обратного вызова, так как там неявно передается указатель на this
PM MAIL Skype GTalk   Вверх
Vizator
Дата 10.12.2007, 17:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Спасибо, разобрался

Добавлено через 14 минут
А не статический вариант невозможен ?
PM MAIL   Вверх
SABROG
Дата 10.12.2007, 17:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

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



Сначала как-то так
Код

LRESULT APIENTRY CallbackProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 

...


или

LRESULT CALLBACK MainWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
...
}


а потом как-то так

Код

MyClass *pClass = new MyClass((WNDPROC) CallbackProc);


И там уже присваиваешь переданную ссылку внутреннему указателю-члену класса.

Или попробывать объявить статический метод:

Код

#include

class menu

{
public:
static void clear_screen(void);
// Здесь должны быть другие методы
private:
int number_of_menu_options;
};

void menu::clear_screen(void)

{
cout << '\033' << "[2J";
}

void main(void)

{
menu::clear_screen();
}



--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
Vizator
Дата 10.12.2007, 17:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Это немного не то, хотелось бы чтобы кал бэк функция лежала внутри класса и принадлежала ему. Т.е. что то типа

Код

class cMainWnd
{
private:
       WNDCLASS wnd;
       .......
       LRESULT CALLBACK WindowProc(HWND,UINT,WPARAM,LPARAM); 

}


и чтобы в wnd.lpfnWndProc указывать именно ее , а не определенную в глобальном контексте, а статический метод накладывает ряд ограничений и неудобств
PM MAIL   Вверх
SABROG
Дата 10.12.2007, 17:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Hacker
****


Профиль
Группа: Завсегдатай
Сообщений: 2481
Регистрация: 18.9.2006

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



Вот, почитай, может поможет http://www.gamedev.ru/faq/?id=34


--------------------
Национальная группа Russian Federation на QtCentre.
PM MAIL   Вверх
586
Дата 10.12.2007, 19:20 (ссылка) |   (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2243
Регистрация: 8.5.2006

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



Код
wc.cbWndExtra=sizeof(long);
...
CMyClass *MyClass;
...
SetWindowLong(hWnd, 0, (long)MyClass);
...
LRESULT CALLBACK CMyClass::StaticWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    return ((CMyClass*)GetWindowLong(hWnd, 0))->WndProc(hWnd, uMsg, wParam, lParam);
}


Это сообщение отредактировал(а) 586 - 11.12.2007, 16:46
PM   Вверх
Cycle
Дата 11.12.2007, 13:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



586, Правильно пишет. Добавлю только маленькое замечание. Для использования SetWindowLong необходимо установить значение атрибута cbWndExtra равным sizeof(LONG) при регистрации класса окна.


Это сообщение отредактировал(а) Cycle - 11.12.2007, 13:30
PM MAIL   Вверх
Simargl
Дата 13.12.2007, 00:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



там ещё с помощью "асма" можно сделать.
PM MAIL   Вверх
EnergoHokum
Дата 14.12.2007, 09:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



А там, где
Код

CMyClass* MyClass;
...
SetWindowLong(hWnd, 0, (long)MyClass);
...

Не должно-ли быть
Код

CMyClass* MyClass;
...
MyClass=(CMyClass*)SetWindowLong(hWnd, 0, (long)MyClass);
...


Хотя нет, что-то у меня не так. Что именно --  не пойму пока.

Это сообщение отредактировал(а) EnergoHokum - 14.12.2007, 11:22
PM MAIL ICQ   Вверх
586
Дата 14.12.2007, 15:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2243
Регистрация: 8.5.2006

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



Цитата(EnergoHokum @  14.12.2007,  09:14 Найти цитируемый пост)
Не должно-ли быть ...

НЕТ. 
Цитата
Что именно --  не пойму пока.

Может внутри класса?

Код
void CMyClass::Create()
{
    ...
    SetWindowLong(hWnd, 0, (long)this);
    ...
}

PM   Вверх
EnergoHokum
Дата 14.12.2007, 15:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Использую MinGW и GCC, не получилось внутрь класса вкрячить перенастройку на собственную нестатическую функцию (тоже внутри класса) обработки сообщений. Тут ведь что получается (в моём понимании):

1. Создаём замещающую функцию-обработчик сообщений
2. Получаем указатель на стандартную функцию-обработчик сообщений графпримитива, который тоже в классе создаётся  (GetWindowLong)
3. Перенастраиваем (SetWindowLong) графпримитив на новую функцию-обработчик

Так вот, уже при получении указателя на стандартный обработчик начиналась ругань. Сейчас наворотил костылей, вынес и создание графпримитивов, и новые обработчики, и перенастройку за пределы класса. Но это костыли, а как нормально сделать -- пока не знаю.
PM MAIL ICQ   Вверх
586
Дата 14.12.2007, 16:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2243
Регистрация: 8.5.2006

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



Цитата(EnergoHokum @  14.12.2007,  15:46 Найти цитируемый пост)
Так вот, уже при получении указателя на стандартный обработчик начиналась ругань.

Можно подробнее? И код, где ошибка.

Это сообщение отредактировал(а) 586 - 20.2.2008, 11:54
PM   Вверх
EnergoHokum
Дата 14.12.2007, 16:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Я определил указатель на функцию-обработчик (которая внутри класса) вне класса,
Код

typedef LRESULT (TestClass::*pButton10Proc) (HWND,UINT,WPARAM,LPARAM);
pButton10Proc pTCB10P;

В классе определил саму функцию-обработчик
Код

// dll5.h
class TestClass
{
 public:
    TestClass(HWND hwnd);
    ~TestClass();
    LRESULT CALLBACK Button10Proc(HWND hwnd,UINT message,            \
                            WPARAM wParam,LPARAM lParam    \
                            );
};

Код

// dll5.cpp

TestClass::TestClass(HWND hwnd)
{
    hButton10=::CreateWindowEx(WS_EX_STATICEDGE,                \
                             "Button","Button 10",        \
                             WS_CHILD | WS_VISIBLE,        \
                             180,25,180,35,                        \
                             hWnd,0,NULL,NULL                    \
                             );

    pTCB10P=(pButton10Proc) (::SetWindowLong(hButton10,GWL_WNDPROC,(LONG)pTC));// pTC - указатель на TestClass, определён в h-ке
}

LRESULT CALLBACK TestClass::Button10Proc(HWND hwnd,UINT message,        \
                                 WPARAM wParam,LPARAM lParam    \
                                 )
{// пока пустая, потому что не работает
    return 0;
}


И на вызове SetWindowLong говорит, что не может привести результат SetWindowLong (LONG) к указателю, и про (LONG)pTC тоже говорит, что так нельзя.
Я скоро уйду, приду только в понедельник (может, в воскресенье). Если что надумаю -- напишу.
PM MAIL ICQ   Вверх
586
Дата 14.12.2007, 16:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2243
Регистрация: 8.5.2006

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



Код
class TestClass
{
 public:
    TestClass(HWND hwnd);
    ~TestClass();
    static LRESULT  CALLBACK StaticButton10Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    LRESULT Button10Proc(HWND hwnd,UINT message,            \
                            WPARAM wParam,LPARAM lParam    \
                            );
};


Код
TestClass::TestClass(HWND hwnd)
{
    hButton10=::CreateWindowEx(WS_EX_STATICEDGE,                \
                             "Button","Button 10",        \
                             WS_CHILD | WS_VISIBLE,        \
                             180,25,180,35,                        \
                             hWnd,0,NULL,NULL                    \
                             );

    pTCB10P=(pButton10Proc) (::SetWindowLong(hButton10,GWL_WNDPROC,(LONG)StaticButton10Proc));
    SetWindowLong(hButton10, GWL_USERDATA, (long)this);
}

LRESULT CALLBACK TestClass::StaticButton10Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
     return ((TestClass*)GetWindowLong(hWnd, GWL_USERDATA))->Button10Proc(hWnd, uMsg, wParam, lParam);
}

LRESULT TestClass::Button10Proc(HWND hwnd,UINT message,        \
                                 WPARAM wParam,LPARAM lParam    \
                                 )
{
    return CallWindowProc(pTCB10P, hWnd, uMsg, wParam, lParam);
}

Код не проверял, могут быть ошибки

Это сообщение отредактировал(а) 586 - 14.12.2007, 17:07
PM   Вверх
Earnest
Дата 14.12.2007, 18:50 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



EnergoHokum, ты с упорством, достойным лучшего применения, пытаешься таки подсунуть метод класса в качестве WndProc. Что показывает, что ты не понимаешь сути. Это не просто придурь компилятора. Ты думаешь, раз сигнатуры статической или глобальной функции выглядят так же как сигнатура метода, то одно можно подсунуть вместо другого? У метода есть дополнительный неявный аргумент - this, который и нарушает похожесть сигнатур. При вызове метода он идет первым аргументом. А CALLBACK-функции его просто взять неокуда. Поэтому оконная функция может быть только статической. Далее, она может как-то определить, какой объект твоего класса соответствует hWnd и вызвать для этого объекта метод. Как определить - дело техники. Можно, как тебе показали, засунуть указатель в доп. память hWnd. Можно поддерживать внешний глобальный map hWnd->pWnd. Можно еще что-нибуль придумать. Но обойтись без этого "что-нибудь" не удастся. 


--------------------
...
PM   Вверх
EnergoHokum
Дата 17.12.2007, 07:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Я понимал, но "местами" (какими -- не скажу smile). Теперь ясно. Спасибо за разъяснение!
PM MAIL ICQ   Вверх
Страницы: (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.

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


 




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


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

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