Пользовательские элементы управления

В этом разделе содержатся сведения о определяемых приложением или пользовательских элементах управления.

Рассматриваются следующие разделы.

Создание элементов управления нарисованным владельцем

Кнопки, меню, статические текстовые элементы управления, поля списка и поля со списком можно создать с помощью флага стиля, нарисованного владельцем. Если элемент управления имеет стиль, нарисованный владельцем, система обрабатывает взаимодействие пользователя с элементом управления как обычно, выполняя такие задачи, как обнаружение того, когда пользователь выбрал кнопку и уведомляет владельца кнопки о событии. Однако, поскольку элемент управления нарисован владельцем, родительское окно элемента управления отвечает за внешний вид элемента управления. Родительское окно получает сообщение всякий раз, когда элемент управления должен быть нарисован.

Для кнопок и статических элементов управления текстом стиль, нарисованный владельцем, влияет на то, как система рисует весь элемент управления. Для полей списка и полей со списком родительское окно рисует элементы в элементе управления, а элемент управления рисует свой собственный контур. Например, приложение может настроить поле списка таким образом, чтобы оно отображалось небольшое растровое изображение рядом с каждым элементом в списке.

В следующем примере кода показано, как создать статическое текстовое элемент управления, нарисованное владельцем. Предположим, что Юникод определен.

// g_myStatic is a global HWND variable.
g_myStatic = CreateWindowEx(0, L"STATIC", L"Some static text", 
            WS_CHILD | WS_VISIBLE | SS_OWNERDRAW, 
            25, 125, 150, 20, hDlg, 0, 0, 0);

В следующем примере из процедуры окна диалогового окна, содержащего элемент управления, созданный в предыдущем примере, сообщение WM_DRAWITEM обрабатывается путем отображения текста в пользовательском цвете с помощью шрифта по умолчанию. Обратите внимание, что при обработке WM_DRAWITEM не требуется вызывать BeginPaint и EndPaint.

case WM_DRAWITEM:
{
    LPDRAWITEMSTRUCT pDIS = (LPDRAWITEMSTRUCT)lParam;
    if (pDIS->hwndItem == g_myStatic)
    {
        SetTextColor(pDIS->hDC, RGB(100, 0, 100));
        WCHAR staticText[99];
        int len = SendMessage(myStatic, WM_GETTEXT, 
            ARRAYSIZE(staticText), (LPARAM)staticText);
        TextOut(pDIS->hDC, pDIS->rcItem.left, pDIS->rcItem.top, staticText, len);
    }
    return TRUE;
}

Дополнительные сведения о элементах управления, нарисованных владельцем, см. в разделе "Создание прямоугольника со списком", нарисованного владельцем, и поля со списком владельцев.

Подкласс класса Window существующего элемента управления

Подклассы существующего элемента управления — это другой способ создания пользовательского элемента управления. Процедура подкласса может изменить выбранное поведение элемента управления, обрабатывая эти сообщения, влияющие на выбранное поведение. Все остальные сообщения передаются в исходную процедуру окна для элемента управления. Например, приложение может отображать небольшую растровую карту рядом с текстом в элементе управления редактирования только для чтения, подклассив элемент управления и обработать сообщение WM_PAINT . Дополнительные сведения см. в разделе "О процедурах окна" и элементах управления подклассами.

Реализация класса окна, определяемого приложением

Чтобы создать элемент управления, не основанный на существующем элементе управления, приложение должно создать и зарегистрировать класс окна. Процесс регистрации определенного приложением класса окна для пользовательского элемента управления совпадает с регистрацией класса для обычного окна. Чтобы создать пользовательский элемент управления, укажите имя класса окна в функции CreateWindowEx или в шаблоне диалогового окна. Каждый класс должен иметь уникальное имя, соответствующую процедуру окна и другую информацию.

По крайней мере процедура окна рисует элемент управления. Если приложение использует элемент управления для передачи информации о типе пользователя, процедура окна также обрабатывает входные сообщения с клавиатуры и мыши и отправляет уведомления в родительское окно. Кроме того, если элемент управления поддерживает контрольные сообщения, процедура окна обрабатывает сообщения, отправленные в него родительским окном или другими окнами. Например, элементы управления часто обрабатывают сообщение WM_GETDLGCODE , отправляемое диалоговым окном, чтобы направить диалоговое окно для обработки ввода клавиатуры таким образом.

Процедура окна для определяемого приложением элемента управления должна обрабатывать любое предопределенное сообщение элемента управления в следующей таблице, если сообщение влияет на операцию элемента управления.

Message Рекомендация
WM_GETDLGCODE Обработка, если элемент управления использует клавиши ВВОД, ESC, TAB или стрелки. Функция IsDialogMessage отправляет это сообщение элементам управления в диалоговом окне, чтобы определить, следует ли обрабатывать ключи или передавать их в элемент управления.
WM_GETFONT Обработка, если также обрабатывается сообщение WM_SETFONT.
WM_GETTEXT Обработка, если текст элемента управления не совпадает с заголовком, указанным функцией CreateWindowEx.
WM_GETTEXTLENGTH Обработка, если текст элемента управления не совпадает с заголовком, указанным функцией CreateWindowEx.
WM_KILLFOCUS Процесс, если элемент управления отображает курсор, прямоугольник фокуса или другой элемент, указывающий, что он имеет фокус ввода.
WM_SETFOCUS Процесс, если элемент управления отображает курсор, прямоугольник фокуса или другой элемент, указывающий, что он имеет фокус ввода.
WM_SETTEXT Обработка, если текст элемента управления не совпадает с заголовком, указанным функцией CreateWindowEx.
WM_SETFONT Обработка, если элемент управления отображает текст. Система отправляет это сообщение при создании диалогового окна с DS_SETFONT стилем.

 

Определяемые приложением сообщения управления относятся к заданному элементу управления и должны быть явно отправлены в элемент управления с помощью функции SendMessage или SendDlgItemMessage. Числовое значение для каждого сообщения должно быть уникальным и не должно конфликтовировать со значениями других сообщений окна. Чтобы гарантировать, что определяемые приложением значения сообщений не конфликтуют, приложение должно создать каждое значение, добавив уникальное число в значение WM_USER.

Отправка уведомлений из элемента управления

Пользовательские элементы управления могут потребоваться для отправки уведомлений о событиях в родительское окно, чтобы хост-приложение могло реагировать на эти события. Например, пользовательское представление списка может отправлять уведомление, когда пользователь выбирает элемент, и другое уведомление при двойном щелчке элемента.

Уведомления отправляются как WM_COMMAND или WM_NOTIFY сообщения. WM_NOTIFY сообщения содержат больше информации, чем WM_COMMAND сообщения.

Идентификатор элемента управления — это уникальное число, которое приложение использует для идентификации элемента управления, отправляя сообщение. Приложение задает идентификатор элемента управления при создании элемента управления. Приложение задает идентификатор в параметре hMenu функции CreateWindowEx или в элементе идентификатора структуры DLGITEMTEMPLATEEX.

Так как сам элемент управления не задает идентификатор элемента управления, элемент управления должен получить идентификатор, прежде чем он сможет отправлять сообщения уведомлений. Элемент управления должен использовать функцию GetDlgCtrlID для получения собственного идентификатора элемента управления. Хотя идентификатор элемента управления указывается в качестве дескриптора меню при создании элемента управления, функция GetMenu не может использоваться для получения идентификатора. Кроме того, элемент управления может получить идентификатор из элемента hMenu в структуре CREATESTRUCT при обработке сообщения WM_CREATE.

В следующих примерах, где hwndControl является дескриптором окна управления и CN_VALUECHANGED является пользовательским определением уведомлений, показаны два способа отправки уведомления для конкретного элемента управления.

 // Send as WM_COMMAND.
SendMessage(GetParent(hwndControl), 
    WM_COMMAND,
    MAKEWPARAM(GetDlgCtrlID(hwndControl), CN_VALUECHANGED),
    (LPARAM)hwndControl);

// Send as WM_NOTIFY.           
NMHDR nmh;
nmh.code = CN_VALUECHANGED;
nmh.idFrom = GetDlgCtrlID(hwndControl);
nmh.hwndFrom = hwndControl;
SendMessage(GetParent(hwndControl), 
    WM_NOTIFY, 
    (WPARAM)hwndControl, 
    (LPARAM)&nmh);

Обратите внимание, что структура NMHDR может быть частью более крупной управляемой структуры, содержащей дополнительные сведения. В этом примере старые и новые значения элемента управления могут содержаться в этой структуре. (Такие расширенные структуры используются со многими стандартными уведомлениями; например, см. раздел .LVN_INSERTITEM, использующего структуру NMLISTVIEW .)

Специальные возможности

Все распространенные элементы управления поддерживают microsoft Active Accessibility (MSAA), что обеспечивает программный доступ к приложениям со специальными возможностями, такими как средства чтения с экрана. MSAA также позволяет модель автоматизации пользовательского интерфейса, более новой технологии для взаимодействия с элементами управления.

Пользовательские элементы управления должны реализовать интерфейс IAccessible (для поддержки MSAA) или интерфейсов модель автоматизации пользовательского интерфейса или обоих. В противном случае продукты со специальными возможностями смогут получать только очень ограниченные сведения о окне управления, не будут иметь доступа к свойствам элемента управления и не смогут активировать события в элементе управления.

Дополнительные сведения о том, как сделать элемент управления доступным, см. в разделе API автоматизации Windows.

Концептуальной

Общие справочники по элементу управления

Настройка внешнего вида элемента управления с помощью пользовательского рисования

Управление сообщениями

Использование визуальных стилей с элементами управления нарисованным владельцем