Поделиться через


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

Панель инструментов на рабочем столе приложения (также называемая панелью приложений) — это окно, аналогичное панели задач Windows. Он привязан к краю экрана, и обычно он содержит кнопки, которые предоставляют пользователю быстрый доступ к другим приложениям и окнам. Система запрещает другим приложениям использовать область рабочего стола, используемую панелью приложений. Любое количество панелей приложений могут существовать на рабочем столе в любой момент времени.

В этом разделе содержатся следующие разделы.

Сведения о панели инструментов для настольных приложений

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

Отправка сообщений

Приложение использует специальный набор сообщений, называемых сообщениями appbar, для добавления или удаления панели приложений, задания размера и положения панели приложений, а также получения сведений о размере, положении и состоянии панели задач. Чтобы отправить сообщение панели приложений, приложение должно использовать функцию SHAppBarMessage. Параметры функции включают идентификатор сообщения, например ABM_NEW, и адрес структуры APPBARDATA. Члены структуры содержат сведения, необходимые системе для обработки данного сообщения.

Для любого заданного сообщения панели приложений система использует некоторые члены структуры APPBARDATA и игнорирует другие. Однако система всегда использует члены cbSize и hWnd, поэтому приложение должно заполнять эти члены для каждого сообщения appbar. Элемент cbSize указывает размер структуры, а элемент hWnd — это дескриптор окна панели приложений.

Некоторые сообщения на панели приложений запрашивают информацию из системы. При обработке этих сообщений система копирует запрошенные сведения в структуру APPBARDATA.

Регистрация

Система сохраняет внутренний список панелей приложений и поддерживает сведения о каждой панели в списке. Система использует сведения для управления панели приложений, выполнения служб и отправки уведомлений.

Приложение должно зарегистрировать панель приложений (то есть добавить ее в внутренний список), прежде чем она сможет получать службы панели приложений из системы. Чтобы зарегистрировать панель приложений, приложение отправляет сообщение ABM_NEW. Сопровождающая структура APPBARDATA включает дескриптор окна панели приложения и определяемый приложением идентификатор сообщения. Система использует идентификатор сообщения для отправки уведомлений в процедуру окна панели задач. Для получения дополнительной информации см. раздел «Сообщения уведомления панели приложений (Appbar)».

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

Размер и положение панели приложений

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

Чтобы задать размер и положение панели приложений, приложение сначала предлагает край экрана и ограничивающий прямоугольник для панели приложения, отправив сообщение ABM_QUERYPOS. Система определяет, используется ли любая часть области экрана в предлагаемом прямоугольнике панели задач или другой панели приложений, настраивает прямоугольник (при необходимости) и возвращает настроенный прямоугольник в приложение.

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

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

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

Когда панель приложений получает сообщение WM_ACTIVATE, она должна отправить сообщение ABM_ACTIVATE. Аналогичным образом, когда панель приложений получает сообщение WM_WINDOWPOSCHANGED, она должна вызывать ABM_WINDOWPOSCHANGED. Отправка этих сообщений гарантирует, что система правильно устанавливает порядок по оси Z любых панелей автоскрытия приложений на одном и том же краю.

Панели инструментов рабочего стола приложения с автоскрытием

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

Хотя система разрешает использовать несколько различных панелей приложений в любой момент времени, она позволяет одновременно использовать только одну автоматически скрываемую панель приложений для каждого края экрана по принципу "первый пришел – первый обслужен". Система автоматически поддерживает z-последовательность скрываемой панели задач, но только внутри ее группы z-последовательности.

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

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

Сообщения уведомлений на панели приложений

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

Панель приложений получает сообщение уведомления ABN_POSCHANGED, когда изменяются размер, положение или видимость панели задач, когда другая панель добавляется на тот же край экрана, или когда другая панель на том же краю экрана изменяется или удаляется. Панель приложений должна отвечать на это уведомление, отправляя ABM_QUERYPOS и ABM_SETPOS сообщения. Если позиция панели приложений изменилась, она должна вызвать функцию MoveWindow, чтобы перейти к новой позиции.

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

При запуске полноэкранного приложения или при закрытии последнего полноэкранного приложения панель приложений получает уведомление ABN_FULLSCREENAPP. Параметр lParam указывает на то, открывается или закрывается полноэкранное приложение. Если она открывается, панель приложений должна переместиться на нижнюю позицию в z-порядке. Панель приложений должна восстановить положение z-порядка при закрытии последнего полноэкранного приложения.

Панель приложений получает уведомление ABN_WINDOWARRANGE, когда пользователь выбирает команду "Каскадом", "Расположение по горизонтали" или "Расположение по вертикали" из контекстного меню панели задач. Система отправляет сообщение два раза: перед переупорядочением окон (lParamTRUE) и после упорядочения окон (lParamFALSE).

Панель приложений может использовать сообщения ABN_WINDOWARRANGE для исключения из операции каскада или укладки. Чтобы исключить себя, панель приложений должна скрыть себя, если lParamTRUE и показать себя, когда lParamFALSE. Если панель приложений скрывает себя в ответ на это сообщение, не нужно отправлять ABM_QUERYPOS и ABM_SETPOS сообщения в ответ на операцию каскада или плитки.

Регистрация панели инструментов для настольного приложения

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

Функция в следующем примере регистрирует или отменяет регистрацию панели приложений в зависимости от значения логического параметра флага.

// RegisterAccessBar - registers or unregisters an appbar. 
// Returns TRUE if successful, or FALSE otherwise. 

// hwndAccessBar - handle to the appbar 
// fRegister - register and unregister flag 

// Global variables 
//     g_uSide - screen edge (defaults to ABE_TOP) 
//     g_fAppRegistered - flag indicating whether the bar is registered 

BOOL RegisterAccessBar(HWND hwndAccessBar, BOOL fRegister) 
{ 
    APPBARDATA abd; 
    
    // An application-defined message identifier
    APPBAR_CALLBACK = (WM_USER + 0x01);
    
    // Specify the structure size and handle to the appbar. 
    abd.cbSize = sizeof(APPBARDATA); 
    abd.hWnd = hwndAccessBar; 

    if (fRegister) 
    { 
        // Provide an identifier for notification messages. 
        abd.uCallbackMessage = APPBAR_CALLBACK; 

        // Register the appbar. 
        if (!SHAppBarMessage(ABM_NEW, &abd)) 
            return FALSE; 

        g_uSide = ABE_TOP;       // default edge 
        g_fAppRegistered = TRUE; 

    } 
    else 
    { 
        // Unregister the appbar. 
        SHAppBarMessage(ABM_REMOVE, &abd); 
        g_fAppRegistered = FALSE; 
    } 

    return TRUE; 
}

Настройка размера и положения панели приложений

Приложение должно задать размер и позицию панели приложений после регистрации панели приложений, после того как панель приложений переместили или изменили её размер, а также при получении сообщения уведомления ABN_POSCHANGED. Прежде чем задать размер и позицию панели приложений, приложение запрашивает у системы подтверждение ограничивающего прямоугольника, отправив сообщение ABM_QUERYPOS. Система возвращает ограничивающий прямоугольник, который не вмешивается в панель задач или любую другую панель приложений. Система настраивает прямоугольник исключительно вычитая из него другой прямоугольник, не пытаясь сохранить его начальный размер. По этой причине панель приложений должна подкорректировать прямоугольник по мере необходимости после отправки ABM_QUERYPOS.

Затем приложение передает ограничивающий прямоугольник обратно в систему с помощью сообщения ABM_SETPOS. Затем он вызывает функцию MoveWindow для перемещения панели приложений в положение.

В следующем примере показано, как задать размер и положение панели приложений.

// AppBarQuerySetPos - sets the size and position of an appbar. 

// uEdge - screen edge to which the appbar is to be anchored 
// lprc - current bounding rectangle of the appbar 
// pabd - address of the APPBARDATA structure with the hWnd and cbSize members filled

void PASCAL AppBarQuerySetPos(UINT uEdge, LPRECT lprc, PAPPBARDATA pabd) 
{ 
    int iHeight = 0; 
    int iWidth = 0; 

    pabd->rc = *lprc; 
    pabd->uEdge = uEdge; 

    // Copy the screen coordinates of the appbar's bounding 
    // rectangle into the APPBARDATA structure. 
    if ((uEdge == ABE_LEFT) || (uEdge == ABE_RIGHT)) 
    { 
        iWidth = pabd->rc.right - pabd->rc.left; 
        pabd->rc.top = 0; 
        pabd->rc.bottom = GetSystemMetrics(SM_CYSCREEN); 
    } 
    else 
    { 
        iHeight = pabd->rc.bottom - pabd->rc.top; 
        pabd->rc.left = 0; 
        pabd->rc.right = GetSystemMetrics(SM_CXSCREEN); 
    } 

    // Query the system for an approved size and position. 
    SHAppBarMessage(ABM_QUERYPOS, pabd); 

    // Adjust the rectangle, depending on the edge to which the appbar is anchored.
    switch (uEdge) 
    { 
        case ABE_LEFT: 
            pabd->rc.right = pabd->rc.left + iWidth; 
            break; 

        case ABE_RIGHT: 
            pabd->rc.left = pabd->rc.right - iWidth; 
            break; 

        case ABE_TOP: 
            pabd->rc.bottom = pabd->rc.top + iHeight; 
            break; 

        case ABE_BOTTOM: 
            pabd->rc.top = pabd->rc.bottom - iHeight; 
            break; 
    } 

    // Pass the final bounding rectangle to the system. 
    SHAppBarMessage(ABM_SETPOS, pabd); 

    // Move and size the appbar so that it conforms to the 
    // bounding rectangle passed to the system. 
    MoveWindow(pabd->hWnd, 
               pabd->rc.left, 
               pabd->rc.top, 
               pabd->rc.right - pabd->rc.left, 
               pabd->rc.bottom - pabd->rc.top, 
               TRUE); 

}

Обработка сообщений уведомлений на панели приложений

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

// AppBarCallback - processes notification messages sent by the system. 

// hwndAccessBar - handle to the appbar 
// uNotifyMsg - identifier of the notification message 
// lParam - message parameter 

void AppBarCallback(HWND hwndAccessBar, UINT uNotifyMsg, 
    LPARAM lParam) 
{ 
    APPBARDATA abd; 
    UINT uState; 

    abd.cbSize = sizeof(abd); 
    abd.hWnd = hwndAccessBar; 

    switch (uNotifyMsg) 
    { 
        case ABN_STATECHANGE: 

            // Check to see if the taskbar's always-on-top state has changed
            // and, if it has, change the appbar's state accordingly.
            uState = SHAppBarMessage(ABM_GETSTATE, &abd); 

            SetWindowPos(hwndAccessBar, 
                         (ABS_ALWAYSONTOP & uState) ? HWND_TOPMOST : HWND_BOTTOM, 
                         0, 0, 0, 0, 
                         SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); 

            break; 

        case ABN_FULLSCREENAPP: 

            // A full-screen application has started, or the last full-screen
            // application has closed. Set the appbar's z-order appropriately.
            if (lParam) 
            { 
                SetWindowPos(hwndAccessBar, 
                             (ABS_ALWAYSONTOP & uState) ? HWND_TOPMOST : HWND_BOTTOM, 
                             0, 0, 0, 0, 
                             SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); 
            } 
            else 
            { 
                uState = SHAppBarMessage(ABM_GETSTATE, &abd); 

                if (uState & ABS_ALWAYSONTOP) 
                    SetWindowPos(hwndAccessBar, 
                                 HWND_TOPMOST, 
                                 0, 0, 0, 0, 
                                 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); 
            } 

        case ABN_POSCHANGED: 

            // The taskbar or another appbar has changed its size or position.
            AppBarPosChanged(&abd); 
            break; 
    } 
}

Следующая функция настраивает ограничивающий прямоугольник панели приложения, а затем вызывает определяемую приложением функцию AppBarQuerySetPos (включенную в предыдущий раздел), чтобы задать размер и положение панели соответствующим образом.

// AppBarPosChanged - adjusts the appbar's size and position. 

// pabd - address of an APPBARDATA structure that contains information 
//        used to adjust the size and position. 

void PASCAL AppBarPosChanged(PAPPBARDATA pabd) 
{ 
    RECT rc; 
    RECT rcWindow; 
    int iHeight; 
    int iWidth; 

    rc.top = 0; 
    rc.left = 0; 
    rc.right = GetSystemMetrics(SM_CXSCREEN); 
    rc.bottom = GetSystemMetrics(SM_CYSCREEN); 

    GetWindowRect(pabd->hWnd, &rcWindow); 

    iHeight = rcWindow.bottom - rcWindow.top; 
    iWidth = rcWindow.right - rcWindow.left; 

    switch (g_uSide) 
    { 
        case ABE_TOP: 
            rc.bottom = rc.top + iHeight; 
            break; 

        case ABE_BOTTOM: 
            rc.top = rc.bottom - iHeight; 
            break; 

        case ABE_LEFT: 
            rc.right = rc.left + iWidth; 
            break; 

        case ABE_RIGHT: 
            rc.left = rc.right - iWidth; 
            break; 
    } 

    AppBarQuerySetPos(g_uSide, &rc, pabd); 
}