Во первых, враппер - это только обертка объекта, поэтому влезать в этот объект с целью понавешать на него максимально много функций и свойств, предполагающих буквально автономную его работу во всех возможных ситуациях не надо, пусть этим занимается кто-то еще, кому интересен сам процесс, а не результат.
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() );
}
...
};Несложные манипуляции и предельно прозрачный код: не задача нас решает, а мы её :)Вобщем, не забываем что на самом деле должны уметь делать эти маленькие помошники, как с их помощью решаются задачи и сколько реально должно стоить их внедрение.
Удачи!
Комментариев нет:
Отправить комментарий