使用應用程式桌面工具列
應用程式 桌面工具列 (也稱為 appbar)是類似于 Windows 工作列的視窗。 它錨定在畫面邊緣,而且通常包含按鈕,讓使用者快速存取其他應用程式和視窗。 系統可防止其他應用程式使用 appbar 所使用的桌面區域。 任何指定的時間,桌面上都可以有任意數目的 appbar。
本主題包含下列各節。
關於應用程式桌面工具列
Windows 提供 API,可讓您利用系統所提供的 appbar 服務。 這些服務可協助確保應用程式定義的應用程式行彼此運作順暢,以及使用工作列。 系統會維護每個 appbar 的相關資訊,並傳送 appbars 訊息,以通知它們可能會影響其大小、位置和外觀的事件。
傳送訊息
應用程式會使用一組特殊的訊息,稱為 appbar 訊息來新增或移除 appbar、設定 appbar 的大小和位置,以及擷取工作列的大小、位置和狀態的相關資訊。 若要傳送 appbar 訊息,應用程式必須使用 SHAppBarMessage 函式。 函式的參數包括訊息識別碼,例如 ABM_NEW ,以及 APPBARDATA 結構的位址。 結構成員包含系統需要處理指定訊息的資訊。
針對任何指定的 appbar 訊息,系統會使用 APPBARDATA 結構的一些成員,並忽略其他成員 。 不過,系統一律會使用 cbSize 和 hWnd 成員,因此應用程式必須針對每個 appbar 訊息填入這些成員。 cbSize 成員會指定結構的大小,而 hWnd 成員是 appbar 視窗的控制碼。
某些 appbar 訊息會向系統要求資訊。 處理這些訊息時,系統會將要求的資訊 複製到 APPBARDATA 結構。
註冊
系統會保留應用程式行的內部清單,並維護清單中每個列的相關資訊。 系統會使用資訊來管理應用列、為其執行服務,以及傳送通知訊息。
應用程式必須先註冊 appbar(也就是將其新增至內部清單),才能從系統接收 appbar 服務。 若要註冊 appbar,應用程式會傳送 ABM_NEW 訊息。 隨附 的 APPBARDATA 結構包含 appbar 視窗的控制碼和應用程式定義的訊息識別碼。 系統會使用訊息識別碼,將通知訊息傳送至 appbar 視窗的視窗程式。 如需詳細資訊,請參閱 Appbar 通知訊息。
應用程式會藉由傳送 ABM_REMOVE 訊息來取消註冊 appbar。 取消註冊 appbar 會將它從系統的內部 appbar 清單中移除。 系統不再將通知訊息傳送至 appbar,或防止其他應用程式使用 appbar 所使用的螢幕區域。 在終結 appbar 之前,應用程式應該一律傳送 ABM_REMOVE 。
Appbar 大小和位置
應用程式應該設定 appbar 的大小和位置,使其不會干擾任何其他應用列或工作列。 每個 appbar 都必須錨定到畫面的特定邊緣,而且多個 appbar 可以錨定到邊緣。 不過,如果 appbar 錨定在與工作列相同的邊緣,系統可確保工作列一律位於最外邊緣。
若要設定 appbar 的大小和位置,應用程式會先藉由傳送 ABM_QUERYPOS 訊息來建議 appbar 的螢幕邊緣和周框。 系統會判斷工作列或其他應用列是否使用建議矩形內的任何畫面區域部分、調整矩形(如有必要),並將調整後的矩形傳回給應用程式。
接下來,應用程式會 傳送ABM_SETPOS 訊息,以設定應用程式行的新周框。 同樣地,系統可能會先調整矩形,再將矩形傳回應用程式。 基於這個理由,應用程式應該使用ABM_SETPOS 傳回的 調整矩形來設定最終的大小和位置。 應用程式可以使用 MoveWindow 函式將 appbar 移至位置。
藉由使用雙步驟程式來設定大小和位置,系統可讓應用程式在移動作業期間提供中繼意見反應給使用者。 例如,如果使用者拖曳 appbar,應用程式可能會顯示陰影矩形,指出 appbar 實際移動之前的新位置。
應用程式應該在註冊應用程式欄之後,以及每當 appbar 收到 ABN_POSCHANGED 通知訊息時,設定其 appbar 的大小和位置。 每當工作列的大小、位置或可見度狀態發生變更,以及每當畫面同一端的另一個 appbar 調整大小、新增或移除時,Appbar 就會收到此通知訊息。
每當 appbar 收到WM_ACTI加值稅E訊息時,應該傳送 ABM_ACTI加值稅E 訊息。 同樣地,當 appbar 收到WM_WINDOWPOSCHANGED訊息時,它必須呼叫 ABM_WINDOWPOSCHANGED 。 傳送這些訊息可確保系統正確地設定相同邊緣上任何自動隱藏 appbar 的 z 順序。
自動隱藏應用程式桌面工具列
自動隱藏 appbar 是通常隱藏但當使用者將滑鼠游標移至與 appbar 相關聯的螢幕邊緣時,就會變成可見的 appbar。 當使用者將滑鼠游標移出橫條周框時,appbar 會再次隱藏本身。
雖然系統在任何指定時間允許數個不同的 appbar,但它一次只允許一個自動隱藏 appbar,每個螢幕邊緣在第一個先到的第一個服務基礎。 系統會自動維護自動隱藏 appbar 的 z 順序(僅限其迭置順序群組內)。
應用程式會 使用ABM_SETAUTOHIDEBAR 訊息來註冊或取消註冊自動隱藏應用程式行。 訊息會指定 appbar 的邊緣,以及指定要註冊或取消註冊 appbar 的旗標。 如果已註冊自動隱藏 appbar,但其中一個已與指定的邊緣相關聯,訊息就會失敗。 應用程式可以藉由傳送 ABM_GETAUTOHIDEBAR 訊息,擷取與邊緣相關聯的自動隱藏應用程式行控制碼。
自動隱藏 appbar 不需要註冊為一般應用列;也就是說,它不需要藉由傳送 ABM_NEW 訊息來註冊。 ABM_NEW未註冊 的 appbar 會重迭錨定在相同畫面邊緣的任何 appbar。
Appbar 通知訊息
系統會傳送訊息,以通知 appbar 可能會影響其位置和外觀的事件。 訊息會在應用程式定義的訊息內容中傳送。 當應用程式傳送 ABM_NEW 訊息來註冊 appbar 時,應用程式會指定訊息的識別碼。 通知程式碼位於 應用程式定義訊息的 wParam 參數中。
當工作列的大小、位置或可見度狀態變更、將另一個 appbar 新增至畫面的相同邊緣,或當相同畫面邊緣上的另一個應用列調整大小或移除時,appbar 會收到ABN_POSCHANGED 通知訊息。 appbar 應該藉由傳送 ABM_QUERYPOS 和 ABM_SETPOS 訊息來回應此通知訊息。 如果 appbar 的位置已變更,它應該呼叫 MoveWindow 函式,將自己移至新位置。
每當工作列的自動隱藏或永遠開啟狀態變更時,系統會傳送 ABN_STATECHANGE 通知訊息,也就是說,當使用者選取或清除 工作列屬性工作表上的 [永遠 開啟] 或 [自動隱藏 ] 核取方塊時。 如有需要,appbar 可以使用此通知訊息來設定其狀態以符合工作列的狀態。
當全螢幕應用程式啟動或最後一個全螢幕應用程式關閉時,appbar 會收到 ABN_FULLSCREENAPP 通知訊息。 lParam 參數會指出全螢幕應用程式是否正在開啟或關閉。 如果開啟,appbar 必須卸載至迭置順序的底部。 當最後一個全螢幕應用程式關閉時,appbar 應該會還原其迭置順序位置。
當使用者從工作列的快顯功能表選取 [串聯]、[水準磚] 或 [垂直磚] 命令時,appbar 會收到 ABN_WINDOWARRANGE 通知訊息。 系統會傳送訊息兩次,再重新排列視窗( lParam 為 TRUE )和排列視窗之後( lParam 為 FALSE )。
appbar 可以使用 ABN_WINDOWARRANGE 訊息,將本身從串聯或磚作業中排除。 若要排除本身,當 lParam 為 TRUE 時 ,appbar 應該隱藏本身,並在 lParam 為 FALSE 時 顯示本身。 如果 appbar 隱藏本身以回應此訊息,則不需要傳送 ABM_QUERYPOS 和 ABM_SETPOS 訊息,以回應串聯或磚作業。
註冊應用程式桌面工具列
應用程式必須藉由傳送 ABM_NEW 訊息來註冊 appbar。 註冊 appbar 會將它新增至系統的內部清單,並提供系統用來將通知訊息傳送至 appbar 的訊息識別碼。 在結束之前,應用程式必須藉由傳送 ABM_REMOVE 訊息來取消註冊 appbar。 取消註冊會從系統的內部清單移除 appbar,並防止列接收 appbar 通知訊息。
下列範例中的 函式會根據布林旗標參數的值來註冊或取消註冊 appbar。
// 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;
}
設定 Appbar 大小和位置
應用程式應該在註冊 appbar 之後、在使用者移動或調整 appbar 的大小之後,以及每當 appbar 收到 ABN_POSCHANGED 通知訊息時,設定 appbar 的大小和位置。 在設定 appbar 的大小和位置之前,應用程式會藉由傳送 ABM_QUERYPOS 訊息,查詢系統是否有已核准的周框。 系統會傳回周框,不會干擾工作列或任何其他應用列。 系統只會透過矩形減法調整矩形;它不費力地保留矩形的初始大小。 基於這個理由,appbar 在傳送 ABM_QUERYPOS 之後,應該視需要重新調整矩形。
接下來,應用程式會使用 ABM_SETPOS 訊息,將周框傳回系統。 然後它會呼叫 MoveWindow 函式,將 appbar 移至位置。
下列範例示範如何設定 appbar 的大小和位置。
// 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);
}
處理 Appbar 通知訊息
當工作列的狀態變更、當全螢幕應用程式啟動時(或最後一個關閉),或事件發生可能會影響 appbar 的大小和位置時,appbar 會收到通知訊息。 下列範例示範如何處理各種通知訊息。
// 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;
}
}
下列函式會調整 appbar 的周框,然後呼叫應用程式定義的 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);
}