Как DialogProc объявить методом класса?
От: Maxud  
Дата: 14.10.02 14:51
Оценка:
Помогите!
Есть класс. В нем создается диалог, через DialogBox. В параметрах указывается процедура обработки сообщений, которая должна быть методом класса. Я ее объявил как static — она работает, но в самой процедуре использовать другие методы (не статические нельзя, т.е. можно, но для этого нужно объявить переменную класса и с ней работать).
Как можно объявить данную процедуру методом класса, чтобы можно было в ней работать как в нормальном методе?
Re: Как DialogProc объявить методом класса?
От: jazzer Россия Skype: enerjazzer
Дата: 14.10.02 15:01
Оценка: 13 (1)
Здравствуйте Maxud, Вы писали:

M>Помогите!

M>Есть класс. В нем создается диалог, через DialogBox. В параметрах указывается процедура обработки сообщений, которая должна быть методом класса. Я ее объявил как static — она работает, но в самой процедуре использовать другие методы (не статические нельзя, т.е. можно, но для этого нужно объявить переменную класса и с ней работать).
M>Как можно объявить данную процедуру методом класса, чтобы можно было в ней работать как в нормальном методе? :???:

Процедуру — никак, она обязана быть обычной статической функцией.
Но Вам никто не запретит из этой статической функции вызывать метод Вашего класса, только для этого Вам необходимо иметь указатель на экземпляр этого класса (а хранить его можно, например, в области данных самого окна диалога, тогда прямо в это статической функции его можно будет оттуда вытаскивать и вызывать по нему необходимый метод).
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: Как DialogProc объявить методом класса?
От: Ed.ward Россия  
Дата: 14.10.02 15:04
Оценка: 12 (2)
Здравствуйте Maxud, Вы писали:

M>Помогите!

M>Есть класс. В нем создается диалог, через DialogBox. В параметрах указывается процедура обработки сообщений, которая должна быть методом класса. Я ее объявил как static — она работает, но в самой процедуре использовать другие методы (не статические нельзя, т.е. можно, но для этого нужно объявить переменную класса и с ней работать).
M>Как можно объявить данную процедуру методом класса, чтобы можно было в ней работать как в нормальном методе?


template < class T >
class CStdThunk{
  BYTE    m_mov;          // mov ecx, %pThis
  DWORD   m_this;         //
  BYTE    m_jmp;          // jmp func
  DWORD   m_relproc;      // relative jmp

public:
    typedef void ( T:: *TMFP )(  );
    /// -----------------------------------
    void InitThunk( TMFP method, const T *pThis )
    {
        union { DWORD func; TMFP method; } addr;
        addr.method = ( TMFP )method;
        m_mov       = 0xB9;
        m_this      = ( DWORD )pThis;
        m_jmp       = 0xE9;
        m_relproc   = addr.func - ( DWORD )( this + 1 );
        FlushInstructionCache( GetCurrentProcess(  ), this, sizeof( *this ) );
    }

    /// -----------------------------------
    FARPROC GetThunk(  ) const 
    {
        _ASSERT(m_mov == 0xB9);
        return ( FARPROC )this; 
    }

};

class Dialog : public CStdThunk< Dialog >
{
public:
  Dialog( )
  {
    InitThunk( ( TMFP )DlgProc, this );  
  }

  BOOL /*CALLBACK*/ DlgProc( HWND hwnd, UINT uMsg, WPARAM wp, LPARAM lp )
  {
    //обработка сообщений
  }

  void Create( HINSTANCE hInst, HWND hwndParent, LPCTSTR template )
  {
    m_hwnd = CreateDialog( hInst, MAKEINTRESOURCE( template ), hwndParent, GetThunk() );
  }
private:
  HWND m_hwnd;
}


примерно так

Ed.ward
Re[2]: Как DialogProc объявить методом класса?
От: McSeem2 США http://www.antigrain.com
Дата: 14.10.02 20:17
Оценка:
Здравствуйте Ed.ward, Вы писали:

[. . .]

EW>примерно так


Интересное решение. Я обычно использую SetWindowLong()/GetWindowLong(). Но при этом приходится объявлять процедуру как friend, что не всегда возможно. У тебя же в этом плане все честно — то есть, процедура окна является настоящим мембером. Проблема в другом. Насколько это переносимо и компиляторно-зависимо? Будет ли работать с Intel C++ и с g++ под cygwin (я тут случайно обнаружил, что cygwin имеет windows.h и прочие API файлы и виндовые приложения собираются g++ на ура).
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[3]: Как DialogProc объявить методом класса?
От: Ed.ward Россия  
Дата: 15.10.02 06:21
Оценка:
Здравствуйте McSeem2, Вы писали:

MS>Здравствуйте Ed.ward, Вы писали:


MS>[. . .]


EW>>примерно так


MS>Интересное решение. Я обычно использую SetWindowLong()/GetWindowLong(). Но при этом приходится объявлять процедуру как friend, что не всегда возможно. У тебя же в этом плане все честно — то есть, процедура окна является настоящим мембером. Проблема в другом. Насколько это переносимо и компиляторно-зависимо? Будет ли работать с Intel C++ и с g++ под cygwin (я тут случайно обнаружил, что cygwin имеет windows.h и прочие API файлы и виндовые приложения собираются g++ на ура).


По идее это не должно зависить от компилятора, потому как код там на ассемблере
BYTE    m_mov;          // mov ecx, %pThis
DWORD   m_this;         //
BYTE    m_jmp;          // jmp func
DWORD   m_relproc;      // relative jmp

вроде как от стандарта ассемблера ни один компилятор не отклоняется

Ed.ward
Re[2]: Хак - он и есть хак
От: jazzer Россия Skype: enerjazzer
Дата: 15.10.02 07:26
Оценка:
Здравствуйте Ed.ward, Вы писали:

Все это работает только пока вызов функции-члена оформляется так, как это у тебя записано:

EW> addr.method = ( TMFP )method;

EW> m_mov = 0xB9;
EW> m_this = ( DWORD )pThis;
EW> m_jmp = 0xE9;
EW> m_relproc = addr.func — ( DWORD )( this + 1 );

Тем не менее в Стандарте ничего такого нет, и нигде не сказано, что this должен неявно идти первым параметром функции. И компилятор может оформлять функции-члены так, как ему заблагорассудится. А твое решение целиком на этом покоится.

Так что если человек сидит под одним компилятором (и под одной его версией) и не собирается никогда компилировать свою программу на других компиляторах/платформах (т.е. сидит дома и пишет для себя и своих друзей), тогда это — приемлемое решение.

Если же ты должен отдать заказчику программу в исходниках — тогда то, что ты автоматически вылетаешь за рамки языка, используя асм, ни к чему хорошему не приведет.
Что еще хуже, такой код не портируем без аналогичного хака.

Кому охота извращаться — кто ж ему запретит?

Я лично предпочту независимое от компилера/платформы решение.

P.S. 2 Ed.ward: Можешь мне за это соoбщение еще один ноль вкатить ;)
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[3]: Хак - он и есть хак
От: Андрей Россия  
Дата: 15.10.02 07:39
Оценка: 1 (1)
Здравствуйте jazzer, Вы писали:

skip

Это вообще-то код из ATL — так что в M$ крутые хакеры сидят
Re[4]: MS только на своем компилере сидит
От: jazzer Россия Skype: enerjazzer
Дата: 15.10.02 07:55
Оценка:
Или я не прав?

Я в курсе, что это из ATL — я сам на ней писал в свое время, к тому же этот хак уже обсуждался в этом форуме.

А в квалификации мелкософтовских программеров я не сомневаюсь — только я не думаю, что они хоть сколько-нибудь озабочены переносимостью, другими компилерами, Стандартом С++ и прочими не относящимися к win32 и .NET вещами.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[3]: Хак - он и есть хак
От: Ed.ward Россия  
Дата: 15.10.02 08:03
Оценка:
Здравствуйте jazzer, Вы писали:

J>Здравствуйте Ed.ward, Вы писали:


J>Тем не менее в Стандарте ничего такого нет, и нигде не сказано, что this должен неявно идти первым параметром функции. И компилятор может оформлять функции-члены так, как ему заблагорассудится. А твое решение целиком на этом покоится.


облажался, каюсь, про this, то я позабыл


J>P.S. 2 Ed.ward: Можешь мне за это соoбщение еще один ноль вкатить

ноль я поставил за категоричность "Процедуру — никак, она обязана быть обычной статической функцией."
Человек же не спрашивал про переносимость и совместимость, а ты ему в лоб "никак". Может он пишет исключительно на M$ VC++ и просто мечтал а таком хаке.

а за это сообщение ноль нельзя ставить, это впору мне ноль ставить за предыдущее, потому как неправ.

Ed.ward
Re[4]: Категоричность
От: jazzer Россия Skype: enerjazzer
Дата: 15.10.02 08:07
Оценка:
Здравствуйте Ed.ward, Вы писали:

EW>ноль я поставил за категоричность "Процедуру — никак, она обязана быть обычной статической функцией."

EW>Человек же не спрашивал про переносимость и совместимость, а ты ему в лоб "никак". Может он пишет исключительно на M$ VC++ и просто мечтал а таком хаке.

согласен, нужно было написать "никак, если пользоваться только средствами стандартного С++". Потому как бинарная совместимость — за пределами Стандарта.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.