Во первых, враппер - это только обертка объекта, поэтому влезать в этот объект с целью понавешать на него максимально много функций и свойств, предполагающих буквально автономную его работу во всех возможных ситуациях не надо, пусть этим занимается кто-то еще, кому интересен сам процесс, а не результат.
class CWindowWrapper{ protected: HWND hwnd; public: operator HWND( void )const{ return hwnd; } CWindowWrapper( HWND hwnd = HWND_DESKTOP ): hwnd( hwnd ){ } LRESULT SendMessage( UINT uMsg, WPARAM wParam, LPARAM lParam )const{ return ::SendMessage( hwnd, uMsg, wParam, lParam ); } };Пара строк - и враппер готов.
Теперь им можно свободно пользоваться в любой ситуации, когда требуется HWND, причем без особых затрат на внедрение:
... LRESULT OnCommand( WORD ID, WORD Notify, const CWindowWrapper& Ctrl ){ switch( Notify ){ case EN_CHANGE: Ctrl.SendMessage( ... ) break; } } ... switch( uMsg ){ ... case WM_COMMAND: return OnCommand( LOWORD( wParam ), HIWORD( wParam ), (HWND)lParam ); ... } return ::DefWindowProc( hwnd, uMsg, wParam, lParam );
Конечно, пока этот объект только копирует функционал своего подопытного, пользы от него мало. Вот здесь-то и выплывает второе свойство врапперов - адаптация к среде разработки, т.е. враппер - это такой объект, который позволяет избавиться от рутинных дел, а не просто перевести API через ООП.
class CWindowWrapper{ ... INT GetWindowTextLength( void )const{ return ::GetWindowTextLength( hwnd ); } INT GetWindowText( LPTSTR lpString, INT nMaxCount )const{ return ::GetWindowText( hwnd, lpString, nMaxCount ); } std::W( string ) GetWindowText( void )const{ std::W( string )Buffer; INT Length; // if( Length = GetWindowTextLength() ){ Buffer.resize( Length ); GetWindowText( &*Buffer.begin() , Length ); } return Buffer; } ... };GetWindowText с использованием STL-контейнера - полезный метод? Несомненно.
Последнее свойство - враппер не должен быть один. То есть, конечно, он может быть и один, но он не должен один решать слишком много задач, иначе враппер из маленькой шестеренки большого механизма превратится в неповоротливый коленвал, которому возможно и достанется в нем своя роль, но только один раз, и только до первой же поломки, после которой, взвесив затраты на переборку, умные авторы все же предпочтут от него просто отказаться.
class CEditWrapper : public CWindowWrapper{ public: CEditWrapper( HWND hwnd = HWND_DESKTOP ): CWindowWrapper( hwnd ){ } ... BOOL CanUndo( void )const{ return SendMessage( EM_CANUNDO, 0, 0 ) ? TRUE : FALSE; } ... };Удобно, не правда ли? Когда потребуется к примеру RichEdit, наследовать его от Edit уже не составит труда.
А если понадобится совершить какое-то специфическое действие, например: добавить в список Combo значение из поля ввода Combo?
Да просто создаем враппер под эту задачу:
class CMyComboWrapper : public CComboBoxWrapper{ public: CMyComboWrapper( HWND hwnd = HWND_DESKTOP ): CComboBoxWrapper( hwnd ){ } ... CEditWrapper MyComboEdit( void )const{ COMBOBOXINFO ComboBoxInfo; // ComboBoxInfo.cbSize = sizeof( ComboBoxInfo ); GetComboBoxInfo( &ComboBoxInfo ); return ComboBoxInfo.hwndItem; } LRESULT MyAdd( void )const{ return AddString( MyComboEdit().GetWindowText().c_str() ); } ... };Несложные манипуляции и предельно прозрачный код: не задача нас решает, а мы её :)
Вобщем, не забываем что на самом деле должны уметь делать эти маленькие помошники, как с их помощью решаются задачи и сколько реально должно стоить их внедрение.
Удачи!
Комментариев нет:
Отправить комментарий