Search code examples
delphitaskbarsystem-tray

Get Taskbar Position?


I have my main Application hidden using:

Application.ShowMainForm:= False;

The Application uses a TTrayIcon which I have assigned a Popup menu to.

By using and selecting one of the Popup menus in the Tray Icon I want to make my Application visible again, but I want the position of the Application to popup above the Taskbar.

By default the Windows Taskbar is at the bottom, so in this case my Application would appear in the bottom right just above the clock - of course the Taskbar can be moved and sized by the user so I need a way of knowing definitively these metrics.

Simply put, I want my Application to appear in the corner of the Taskbar above (or next) to the System clock.

Thanks in advance.


Solution

  • Use SHAppBarMessage to get the location of the taskbar:

    SHAppBarMessage(ABM_GETTASKBARPOS, appBarData);
    

    That, along with the size of the "primary" monitor:

    nScreenWidth := GetSystemMetrics(SM_CXSCREEN);
    nScreenHeight := GetSystemMetrics(SM_CYSCREEN);
    

    and you can work out if the Taskbar is located at the

    • top
    • left
    • bottom
    • right

    of the screen, and its size.

    {Calculate taskbar position from its window rect. However,
     on XP it may be that the taskbar is slightly larger or smaller than the
     screen size. Therefore we allow some tolerance here.
    }
    if NearlyEqual(rcTaskbar.Left, 0, TASKBAR_X_TOLERANCE) and
            NearlyEqual(rcTaskbar.Right, nScreenWidth, TASKBAR_X_TOLERANCE) then
    begin
        // Taskbar is on top or on bottom
        if NearlyEqual(rcTaskbar.Top, 0, TASKBAR_Y_TOLERANCE) then
            FTaskbarPlacement := ABE_TOP
        else
            FTaskbarPlacement := ABE_BOTTOM;
    end
    else
    begin
        // Taskbar is on left or on right
        if NearlyEqual(rcTaskbar.Left, 0, TASKBAR_X_TOLERANCE) then
            FTaskbarPlacement := ABE_LEFT
        else
            FTaskbarPlacement := ABE_RIGHT;
    end;
    

    With that you can pop up your toast:

    case FTaskbarPlacement of
    ABE_RIGHT:
       begin
          Self.Left := rcTaskbar.Left-Self.Width;
          Self.Top := rcTaskbar.Bottom - Self.Height;
       end;
    ABE_LEFT:
       begin
          Self.Left := rcTaskbar.Right;
          Self.Top := rcTaskbar.Bottom - Self.Height;
       end;
     ABE_TOP:
        begin
           Self.Left := rcTaskbar.Right - Self.Height;
           Self.Top := rcTaskbar.Bottom;
        end;
     else //ABE_BOTTOM
        // Taskbar is on the bottom or Invisible
        Self.Left := rcTaskbar.Right - Self.Width;
        Self.Top := rcTaskbar.Top - Self.Height;
     end;
    

    enter image description here