Страница 1 из 1

Определить адресс функции

Добавлено: 14 сен 2009, 23:17
l.rod
Вообщем хочу сделать небольшую обертку для winAPI, и появились проблема. В моем классе есть оконная функция (WndProc), а как определить ее адресс, чтоб указать его в структуре WNDCLASSEX?

и еще один вопрос - скажем есть класс A и создаем 2 новых класса на основе А

class B : public A.......

так вот, в классе А есть функция, которую определить нужно в классах В и С
где то так.

Код: Выделить всё

class A
{
		void f(void);
};

class В : public A
{
	void f(void)
	{
		int i = 1+1;
	}
};

class С : public A
{
	void f(void)
	{
		int i = 4+5;
	}
};

при этом будет ли определена функция в класса-потомках - не извесно

Re: Определить адресс функции

Добавлено: 15 сен 2009, 08:50
WinMain
В моем классе есть оконная функция (WndProc), а как определить ее адресс, чтоб указать его в структуре WNDCLASSEX?
Функция GetClassInfo используется для получения информации об уже существующем (зарегистрированном) классе.
Если сам создаёшь оконный класс, то полю lpfnWndProc структуры WNDCLASS просто указываешь имя твоей функции - это и есть её адрес.

Re: Определить адресс функции

Добавлено: 15 сен 2009, 13:46
l.rod
видимо не так обьяснил, вот что мне нужно:

я создал свой класс Window, у которого есть метод

LRESULT CALLBACK Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

и свойство WNDCLASS wc;

так вот, как что мне указать в полу этой структуры?

если написать

Код: Выделить всё

wc.lpfnWndProc = Window::WndProc
компилятор говорит, что ошибка и надо написать так

Код: Выделить всё

wc.lpfnWndProc = &Window::WndProc
но тогда пишет что несоответствие типов

Re: Определить адресс функции

Добавлено: 15 сен 2009, 15:59
Romeo
Сделай так:

Код: Выделить всё

static LRESULT CALLBACK Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
А this прикрепи к окну с помощью SetWindowLong и параметра GWL_USERDATA.

Re: Определить адресс функции

Добавлено: 15 сен 2009, 16:54
l.rod
Romeo писал(а):Сделай так:

Код: Выделить всё

static LRESULT CALLBACK Window::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
А this прикрепи к окну с помощью SetWindowLong и параметра GWL_USERDATA.
а как поможет GWL_USERDATA и this? может тогда уж нужно GWL_WNDPROC ???

Re: Определить адресс функции

Добавлено: 15 сен 2009, 17:31
Romeo
Если ты хочешь, чтобы для данного окна вызвались функции данного объекта класса, то нужно каким-то образом связать this и окно. Так как, функция-обработчик оконных сообщений обязана быть статической (в силу строго задания её прототипа), то единственное, как можно привязать this к окну, это через GWL_USERDATA. Если не ошибаюсь, то именно так выполняет привязку MFC.

Подход состоит в следующем:

Код: Выделить всё

class CMyWindow
{
public:
   void CreateWindow( /* some parameters, i.g. window title */)
   {
      WNDCLASSEX wcl;
      wcl.lpfnWndProc = &GlobalWndProc;

      ...

      HWND hWnd = ::CreateWindowEx( /* do not set WS_VISIBLE style */ , wcl, ...);
      ::SetWindowLong(hWnd, GWL_USERDATA, (long)this);
      ::ShowWindow(hWnd, SW_SHOW);
   }

private:
   static LRESULT CALLBACK GlobalWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
   {
      long nThis = GetWindowLong(hWnd, GWL_USERDATA);
      CMyWindow* pThis = (CMyWindow*)nThis;
      if (pThis)
      {
         return pThis->WndProc(hWnd, message, wParam, lParam);
      }
      return ::WindowProc(hWnd, message, wParam, lParam);
   }

   LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
   {
      // your impelentation
   }
}
При таком подходе есть свои тонкости, например, WM_CREATE твоя процедура не получит. Это можно обойти, если послать в CreateWindow в качестве последнего параметра тоже this и предусмотреть этот вариант развития событий в GlobalWndProc.

Re: Определить адресс функции

Добавлено: 15 сен 2009, 19:46
l.rod
вот теперь понял, только непонятно, кочему моя функция не получит сообщение WM_CREATE, ведь все, что получит глобальная, передастся WndProc?


да, а это почему?

/* do not set WS_VISIBLE style */

и как я понял, глобальная функция даже не должна быть членом класса?

Re: Определить адресс функции

Добавлено: 16 сен 2009, 12:43
Romeo
Дело в том, что нету возможности проставить User Data для окна до его создания. Так, как WM_CREATE генерируется внутри функции CreateWindow сразу после физического создания окна , то это сообщение прилетит в GlobalWndProc ещё до того, как this был проставлен в User Data. Как следствие, твоя WndProc не будет вызвана. Решить эту проблему можно, передав в CreateWindow указатель на this в качестве последнего параметра и корректно обработав эту ситуацию внутри GlobalWndProc.

По поводу WS_VISIBLE. Если ты установишь этот стиль, то помимо сообщения WM_CREATE ты пропустишь ещё массу сообщений: WM_SIZE, WM_SHOWWINDOW, WM_PAINT и т.д., которые будут сгенерированы операционной системой в момент показа окна.

Re: Определить адресс функции

Добавлено: 25 сен 2009, 20:11
l.rod
снято с обсуждения :)