Changing an Access Bar's Size or Position

The size or position of an access bar can change, usually as a result of the user resizing or moving it. In SHELLFUN, the user can change the position of the bar by clicking the Right, Left, Top, or Bottom button to align the access bar with the specified edge of the screen. The application must then determine whether that position is available. If another access bar is already anchored to the specified edge, you must recalculate the position of the new access bar so that it will appear next to the bar already occupying that edge.

In SHELLFUN, I had to consider the vertical or horizontal orientation of the access bar and then remember to reset the positions of the child buttons accordingly. (The buttons are placed crosswise on a horizontal bar, or up and down on a vertical bar.) When the user clicks a button on the SHELLFUN access bar, the message is sent to a function that filters out information about which button was clicked:

void AppBarClicked (UINT msg, APPBARDATA *pabd)
{
switch (msg)
{
case IDM_LEFT:
AppBarPosChanged (ABE_LEFT, pabd);
break;

case IDM_RIGHT:
AppBarPosChanged (ABE_RIGHT, pabd);
break;

case IDM_TOP:
AppBarPosChanged (ABE_TOP, pabd);
break;

case IDM_BOTTOM:
AppBarPosChanged (ABE_BOTTOM, pabd);
break;
}
}

Once you have determined the new specified edge, you can do the real positioning:

void PASCAL AppBarPosChanged (UINT uEdge, APPBARDATA *abd)
{
RECT rcl;

// Get the screen coordinates.
rcl.left = rcl.top = 0;
rcl.right = GetSystemMetrics (SM_CXSCREEN);
rcl.bottom = GetSystemMetrics (SM_CYSCREEN);

switch (uEdge)
{
case ABE_TOP:
abd->rc.left = abd->rc.top = 0;
abd->rc.right = rcl.right;
abd->rc.bottom = DEF_APPBAR_HEIGHT;
break;

case ABE_BOTTOM:
abd->rc.left = 0;
abd->rc.top = rcl.bottom - DEF_APPBAR_HEIGHT;
abd->rc.right = rcl.right;
abd->rc.bottom = rcl.bottom;
break;

case ABE_LEFT:
abd->rc.left = abd->rc.top = 0;
abd->rc.right = DEF_APPBAR_WIDTH;
abd->rc.bottom = rcl.bottom;
break;

case ABE_RIGHT:
abd->rc.top = 0;
abd->rc.left = rcl.right - DEF_APPBAR_WIDTH;
abd->rc.right = rcl.right;
abd->rc.bottom = rcl.bottom;
break;
}

// Check to see whether this position is OK.
SHAppBarMessage (ABM_QUERYPOS, abd);

switch (uEdge)
{
case ABE_LEFT:
abd->rc.right = abd->rc.left + DEF_APPBAR_WIDTH;
break;

case ABE_RIGHT:
abd->rc.left = abd->rc.right - DEF_APPBAR_WIDTH;
break;

case ABE_TOP:
abd->rc.bottom = abd->rc.top + DEF_APPBAR_HEIGHT;
break;

case ABE_BOTTOM:
abd->rc.top = abd->rc.bottom - DEF_APPBAR_HEIGHT;
break;
}

// Set the access bar position.
SHAppBarMessage (ABM_SETPOS, abd);

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

if ((uEdge == ABE_TOP) || (uEdge == ABE_BOTTOM))
{
MoveWindow (g_hwndBtn1, 5, 0, BUTTON_WIDTH, BUTTON_HEIGHT, TRUE);
MoveWindow (g_hwndBtn2, BUTTON_WIDTH * 2, 0, BUTTON_WIDTH,
BUTTON_HEIGHT, TRUE);
MoveWindow (g_hwndBtn3, BUTTON_WIDTH * 4, 0, BUTTON_WIDTH,
BUTTON_HEIGHT, TRUE);
MoveWindow (g_hwndBtn4, BUTTON_WIDTH * 6, 0, BUTTON_WIDTH,
BUTTON_HEIGHT, TRUE);
}
else
{
MoveWindow (g_hwndBtn1, 2, 5, BUTTON_WIDTH, BUTTON_HEIGHT, TRUE);
MoveWindow (g_hwndBtn2, 2, BUTTON_HEIGHT * 2, BUTTON_WIDTH,
BUTTON_HEIGHT, TRUE);
MoveWindow (g_hwndBtn3, 2, BUTTON_HEIGHT * 4, BUTTON_WIDTH,
BUTTON_HEIGHT, TRUE);
MoveWindow (g_hwndBtn4, 2, BUTTON_HEIGHT * 6, BUTTON_WIDTH,
BUTTON_HEIGHT, TRUE);
}
}