Jenter Алекс
Шрифт:
Другими словами, за размер буфера принимается размер переменной var, которая связывается с контролом. Отсюда следует два вывода. Во-первых, переменная var может быть только статическим массивом, а динамическим – нет. Во-вторых, в программе, использующей набор символов Unicode, этот размер будет всегда определяться неправильно. Выход в том и в другом случае – отказаться от макроса DDX_TEXT и обратиться к функции DDX_Text напрямую, передав ей правильный размер. Замечу также, что при передаче строки из переменной в контрол размер буфера значения не имеет, так что если вы передаёте данные только в этом направлении, DDX_TEXT использовать можно.
С набором символов Unicode связана ещё одна интересная проблема. Посмотрим на следующую карту DDX:
Если попытаться откомпилировать этот код, задав макрос UNICODE, компилятор выдаст следующую ошибку: 'DDX_Text' : ambiguous call to overloaded function (неоднозначность при обращении к перегруженной функции). Дело в том, что в классе CWinDataExchange<> существует несколько перегруженных версий DDX_Text. Вот две из них:
Если макрос UNICODE определён, LPTSTR превращается в wchar_t*, а BSTR&– в wchar_t*&. Получается неоднозначность. Чтобы решить эту проблему, можно переписать карту DDX так:
Поскольку в C++ константный указатель можно передать по значению, но не по ссылке, неоднозначность тем самым удаётся разрешить. В любом случае, если вы собираетесь компилировать программу с поддержкой Unicode, я советую вам использовать для обмена текстом переменные типа CString. Это избавит вас от многих проблем, подобных рассмотренным выше.
Макрос DDX_CONTROL связывает контрол с объектом класса, порождённого от CWindowImplBaseT<>. Если вы знакомы с mfc, вы знаете, что там обычной практикой является связывание объекта класса CWnd (или его потомка) с контролом, даже если вам не нужно подключать его к карте сообщений, а просто вызвать несколько обёрток типа CWnd::GetWindowText или CListCtrl::GetItem. Это создаёт значительный, причём совершенно ненужный, перерасход ресурсов. Не используйте макрос DDX_CONTROL из wtl подобным образом. Он используется, если вам действительно необходимо заменить оконную процедуру контрола и обрабатывать его сообщения через карту сообщений.
Если же вам нужно просто использовать функции-обёртки из класса CWindow для работы с контролом, достаточно получить хэндл этого контрола с помощью GetDlgItem, а затем присвоить его объекту класса. Удобно делать это в обработчике WM_INITDIALOG. Например:
Ниже в этой статье мы увидим, что кроме CWindow в WTL существует целый набор классов для работы с контролами – CStatic, CButton, CEdit и т. д. Их можно использовать так же, как и CWindow в приведённом выше примере.