Get precise location and size of TaskBar
This is how:
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left; // x position of upper-left corner
public int Top; // y position of upper-left corner
public int Right; // x position of lower-right corner
public int Bottom; // y position of lower-right corner
}
How to get the location and size of taskbar
:
//Get the handle of the task bar
IntPtr TaskBarHandle;
TaskBarHandle = FindWindow("Shell_traywnd", "");
RECT rct;
//Get the taskbar window rect in screen coordinates
GetWindowRect(TaskBarHandle, out rct);
UWP: How to get the TaskBar Height
Well!! So after a lot of searching on internet, seeing similar answers on stackoverflow and suggestions, It seems that calculating the TaskBar height in UWP application is not so straight or simple task. However for my situation I ended up with this work around which works fine. But I will continue to find a proper approach. Assuming my screen resolution is 1600x900 ,So here is what I did:
private void GetScreenDimension()
{
//To get Screen Measurements e.g. height, width, X,Y...
ApplicationView view = ApplicationView.GetForCurrentView();
//Getting the Window Title Bar height(In my case I get :Top=32,Bottom=860)
double titleBarHeight = view.VisibleBounds.Top;
//Getting the TaskBar Height
double taskBarHeight = view.VisibleBounds.Top + (view.VisibleBounds.Top / 4);
//Getting the workable Height of the screen ( excluding Task Bar Height)
double availableheight = GridTimelineContent.ActualHeight - taskBarHeight;
double availablewidth = GridTimelineContent.ActualWidth;
if (_viewModel != null)
{
_viewModel.AvailableHeight = availableheight;
_viewModel.AvailableWidth = availablewidth;
//Getting the actual Physical height (i.e including TitleBar Height and Task Bar Height, gives 900 in my case which is what I wanted)
_viewModel.ActualScreenHeight = view.VisibleBounds.Height + titleBarHeight + taskBarHeight;
_viewModel.PageWidth = (this as Page).ActualWidth;
}
}
Please Note:
1) When I run the application with TaskBar Locked(visible), I get view.VisibleBounds.Height as 828.
2) When I run the application with TaskBar AutoHidden(Invisible), I get view.VisibleBounds.Height as 868.
Which gave me an idea that 900-868=32 could be Tittle Bar Height, and as I jumped from 828 to 868 after hiding the Task Bar means 868-828=40 could be the Task Bar Height.
Conclusion:
Title Bar Height = view.VisibleBounds.Top (Which is 32)
Task Bar Height = view.VisibleBounds.Top (Which is 32) + (view.VisibleBounds.Top / 4)(Which is 8);(32+8 = Total 40)
Remainning Height = view.VisibleBounds.Height (Which is 828)
If I combine the above three, I get 900 (Required Height) using this line of code:
_viewModel.ActualScreenHeight = view.VisibleBounds.Height + titleBarHeight + taskBarHeight;
I hope it's useful for others too.
Thanks!!
Taskbar width, height and position
Well, since this question is composed on how to get the task bar coordinates I've decided to post another version of how to achieve this by using SHAppBarMessage function with ABM_GETTASKBARPOS message parameter.
I've posted two versions; one with and one without given task bar handle. Note that if you are sending ABM_GETTASKBARPOS message you should specify the hWnd member in the APPBARDATA structure as it's mentioned in the ABM_GETTASKBARPOS description. So the first version is safe for this case. The second one works though but it's formally wrong.
uses ShellAPI;
procedure TForm1.Button1Click(Sender: TObject);
var
Data: TAppBarData;
begin
Data.hWnd := FindWindow('Shell_TrayWnd', nil);
Data.cbSize := SizeOf(TAppBarData);
if Data.hWnd <> 0 then
if SHAppBarMessage(ABM_GETTASKBARPOS, Data) = 1 then
ShowMessage(
'Left: ' + IntToStr(Data.rc.Left) + 'px ; ' +
'Top: ' + IntToStr(Data.rc.Top) + 'px ; ' +
'Width: ' + IntToStr(Data.rc.Right - Data.rc.Left) + 'px ; ' +
'Height: ' + IntToStr(Data.rc.Bottom - Data.rc.Top) + 'px'
);
end;
Note that this version (where the TAppBarData.hWnd member is not specified) works though but it's wrong according to the MSDN.
procedure TForm1.Button2Click(Sender: TObject);
var
Data: TAppBarData;
begin
Data.cbSize := SizeOf(TAppBarData);
if SHAppBarMessage(ABM_GETTASKBARPOS, Data) = 1 then
ShowMessage(
'Left: ' + IntToStr(Data.rc.Left) + 'px ; ' +
'Top: ' + IntToStr(Data.rc.Top) + 'px ; ' +
'Width: ' + IntToStr(Data.rc.Right - Data.rc.Left) + 'px ; ' +
'Height: ' + IntToStr(Data.rc.Bottom - Data.rc.Top) + 'px'
);
end;
Windows 10 task bar location
You can obtain the screen insets for a given screen device using java.awt.Toolkit
.
For the primary screen:
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice defaultScreenDevice = ge.getDefaultScreenDevice();
GraphicsConfiguration defaultConfiguration = defaultScreenDevice.getDefaultConfiguration();
Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(defaultConfiguration);
Insets for my primary screen (using Windows 10):
java.awt.Insets[top=0,left=0,bottom=40,right=0]
Therefore, the task bar is 40 pixels height, and at the bottom of the screen.
Get Taskbar Position?
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;
How would I find the height of the task bar?
You get it from GetMonitorInfo()
, MONITORINFOEX.rcWork member.
Get the HMONITOR that you need to call this function from, say, MonitorFromRect(), passing your window rectangle. Or MonitorFromPoint() or EnumDisplayMonitors(), depends where you want to display your window. (0,0) is always the upper left corner of the primary monitor.
Related Topics
Minimal and Correct Way to Map One-To-Many with Nhibernate
Filter SQL Based on C# List Instead of a Filter Table
Two Dimensional Array Slice in C#
.Net and Bitmap Not Automatically Disposed by Gc When There Is No Memory Left
.Net Regex Matching $ with the End of the String and Not of Line, Even with Multiline Enabled
Center Multiple Rows of Controls in a Flowlayoutpanel
Unrolled Loop Works, for Loop Does Not Work
Get Text/Value from Textbox After Value/Text Changed Server Side
Newtonsoft JSON.Net Deserialization Error Where Fields in JSON Change Order
Set Cultureinfo in ASP.NET Core to Have a . as Currencydecimalseparator Instead of ,
How to Use a Controller in Another Assembly in ASP.NET Core MVC 2.0
Simulate Steady CPU Load and Spikes
Possible to Use Automapper to Map One Object to List of Objects
Entity Framework Code First Lazy Loading