Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> События в C 
:(
    Опции темы
Compositum
Дата 11.6.2011, 20:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Senior developer
**


Профиль
Группа: Awaiting Authorisation
Сообщений: 430
Регистрация: 6.1.2008
Где: Санкт-Петербург

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



Добрый день. Как в C89/C99 можно определять различного рода события и подписываться на них (с последующей обратной отпиской)? В C# имеются events, работа с ними очевидна и удобна, а как это реализовано на C? Функции, структуры, объединения, перечисления, декларация typedef - это всё не то (во всяком случае я не вижу как с их помощью ответить на интересующий меня вопрос). Ведь на C и интерфейсы (GUI) пишут (в том же линухе), а уж в GUI без событий никак... Т.е. и в C это как-то решается, но как?

п.с. Речь именно о C, а не о C++.

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

Вроде всё логично, правда я пока не знаю, как там со временем жизни регистрируемых функций... Да и как это с GUI состыковано (т.е. реакция на движения курсора, нажатие кнопки и т.п.)... Хотелось бы до конца понять...

Это сообщение отредактировал(а) Compositum - 11.6.2011, 20:29
PM   Вверх
borisbn
Дата 11.6.2011, 23:41 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Вот как это реализуется на чистом Си в Windows
Код

#include<windows.h>

typedef enum {
    MOUSE_EVENT_ID,
    KEYBOARD_EVENT_ID,
    ...
    MAX_EVENT_ID
};

typedef void (*event_t)( WPARAM wParam, LPARAM lParam );
event_t registeredEvents[ MAX_EVENT_ID ];

void onMouseMove( WPARAM wParam, LPARAM lParam ) {
   ...
}
void onKeyboard( WPARAM wParam, LPARAM lParam ) {
   ...
}

LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
   // вот тут и вызываются зарегистрированные события
   switch ( msg )
   {
        case WM_MOUSEMOVE:
            if ( registeredEvents[ MOUSE_EVENT_ID ] ) {
                registeredEvents[ MOUSE_EVENT_ID ]( wParam, lParam );
            }
        break;
        case WM_KEYDOWN:
            if ( registeredEvents[ KEYBOARD_EVENT_ID ] ) {
                registeredEvents[ KEYBOARD_EVENT_ID ]( wParam, lParam );
            }
        break;
        default:
            return( DefWindowProc( hWnd, msg, wParam, lParam ) );
   }
}

int WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, int )
{
    HWND hWnd;
    MSG msg;
    WNDCLASS winClass;

    ZeroMemory( registeredEvents, sizeof( registeredEvents ) );
    registeredEvents[ MOUSE_EVENT_ID ] = onMouseMove;
    registeredEvents[ KEYBOARD_EVENT_ID ] = onKeyboard;

    ZeroMemory( &winClass, sizeof( winClass ) );
    winClass.lpfnWndProc = WndProc;
    winClass.lpszClassName = "MyWnd";
    winClass.hInst = hInst;
    RegisterClass( &winClass );
    hWnd = CreateWindow( "MyWnd", "caption", 0, 0, 0, 100, 100, NULL, NULL, hInst, NULL );
    while ( GetMessage( &msg, 0, 0, 0 ) ) {
        TranslateMessage( &msg ); 
        DispatchMessage( &msg );
    }
    return 0;
}


думаю в linux точно также, только функции по-другому называются


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
bsa
Дата 13.6.2011, 19:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


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

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



Вообще-то, все зависит от архитектуры проекта. Самый простой способ - использовать указатели на функции. Т.е. у тебя внутри структуры хранятся указатели на обработчики событий. Они должны иметь вид: type1 eventHandler(void *userData, type2 data1, type3 data2...), где userData это некие данные, переданные регистратору обработчика события вместе с указателем на функцию. Они нужны, например, когда у тебя на одно и тоже событие подписано должно быть более одного обработчика, или один обработчик используется для работы с событиями от разных подсистем.
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

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


 




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


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

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