tags:

views:

120

answers:

4

I'm trying to determine the working area of the desktop even when the taskbar is hidden.

I have two Rectangles, the screen's bounds and the taskbar's bounds. I need to subtract the taskbar's bounds Rectangle from the screen Rectangle to determine the available working area of the desktop. Basically, I want to come up with Screen.WorkingArea except when the taskbar is hidden.

Say the screen rectangle X,Y,W,H = 0,0,1680,1050 and the taskbar X,Y,W,H is 0,1010,1680,40. I need to subtract the second from the first to determine that the working area is 0,0,1680,1010.

The taskbar can be on either of the four sides of the screen and I know there's got to be a better method than determining where the taskbar is and then having a separate line of code to generate a new Rectangle for each of the four possible positions.

A: 

Unless 3 sides of the rectangles are coincident, subtracting one rectangle from another will end up with a shape that is not a rectangle, so a general solution to 'subtract rectangles' doesn't really make much sense.

Solution for 3 sides coincident:

Given rectangles (Ax, Ay, Aw, Ah) and (Bx, By, Bw, Bh):

(max(Ax, Bx), max(Ay, By), min(Ax + Aw, Bx + Bw) - max(Ax, Bx), min(Ay + Ah, By + Bh) - max(Ay, By)

Edited.

Forrest
Grah, this has a problem, it's the intersection not the difference.
Forrest
A: 

I'm not sure there's a better method than the one you mentioned. The problem is that in the general case, subtracting a rectangular region from another is going to leave a hole somewhere in between, so the result isn't really a rectangle. In your case, you know that the taskbar fits exactly on one of the sides of the screen rectangle, so the "best" way is indeed figuring out which side it is and subtracting the width/height from that side.

casablanca
I've settled on having to do it that way. I was hoping for a more elegant mathematical approach, but this method works just fine.
Chris Thompson
A: 

I guess I'm confused as to what you're attempting to derive. .NET reports the current working area of the desktop as the resolution of the monitor minus the space consumed by the Taskbar.

  • If the Taskbar is not hidden, the desktop's working area is the entire resolution of the monitor minus the size of the Taskbar.
  • If the Taskbar is set to hidden, the desktop's working area is the entire resolution of the monitor.
  • If the Taskbar is docked to the top or left, the desktop's working area is the entire resolution of the monitor minus the size of the taskbar and then shifted in the X/Y direction as appropriate.

Determining the working area of the screen is exposed in .NET already (including the shifting X/Y coordinates when the Taskbar is docked to the top or left.

     // set the coordinate to the upper-left of the screen
     Rectangle r = Screen.GetWorkingArea(new Point(0, 0));

     // the resulting rectangle will show the deviation in X/Y
     // and also the dimensions of the desktop (minus the Taskbar)
     MessageBox.Show
     (
        r.ToString()
     );
Michael
Yes, I know that. I need to know the visible desktop area when the taskbar is showing even when auto-hide is enabled. If auto-hide is enabled, and the taskbar is showing, the WorkingArea is still the entire desktop, and my popup gets covered up by the taskbar. I need to move my popup to be above the taskbar when it's showing either with auto-hide on or off.
Chris Thompson
Okay, I'm not going to ask why you would want that behavior. But your reply **is** more clear that regardless of the Taskbar's position (even during auto-hide) - you want to be in the EFFECTIVE working area if the Taskbar was shown.I suggest a Win32 call (via P/Invoke) to toggle the auto-hide of the taskbar TWICE (thus reverting it to the original setting), taking the smaller of the two rectangles.
Michael
A: 

This matrix shows what happens in each case:

in all cases: sX = 0; sY = 0; sW = width; sH = height; 
north: tX = 0;          tY = 0;          tW = sW;    tH = sizeH;   wX = 0;     wY = tH; wW = sW;         wH = sH - sizeH;   sizeW=0,    sizeH=size
south: tX = 0;          tY = sH - sizeH; tW = sW;    tH = sizeH;   wX = 0;     wY = 0;  wW = sW;         wH = sH - sizeH;   sizeW=0,    sizeH=size
east : tX = 0;          tY = 0;          tW = sizeW; tH = sH;      wX = sizeW; wY = 0;  wW = sW - sizeW; wH = sH        ;   sizeW=size, sizeH=0
west : tX = sW - sizeW; tY = 0;          tW = sizeW; tH = sH;      wX = 0;     wY = 0;  wW = sW - sizeW; wH = sH        ;   sizeW=size, sizeH=0

which we can generalize into:

in all cases: sX = 0; sY = 0; sW = width; sH = height; 
north: tX = 0;          tY = 0;          tW = sW;    tH = sizeH;   wX = 0;  wY = tH; wW = sW - sizeW; wH = sH - sizeH;   sizeW=0,     sizeH=value
south: tX = 0;          tY = sH - sizeH; tW = sW;    tH = sizeH;   wX = 0;  wY = 0;  wW = sW - sizeW; wH = sH - sizeH;   sizeW=0,     sizeH=value
east : tX = 0;          tY = 0;          tW = sizeW; tH = sH;      wX = tW; wY = 0;  wW = sW - sizeW; wH = sH - sizeH;   sizeW=value, sizeH=0
west : tX = sW - sizeW; tY = 0;          tW = sizeW; tH = sH;      wX = 0;  wY = 0;  wW = sW - sizeW; wH = sH - sizeH;   sizeW=value, sizeH=0

the matrix revealed this algorithm:

if (east/west)   sizeW = tW;  else   sizeW = 0; 
if (north/south) sizeH = tH;  else   sizeH = 0;
wX = 0; wY = 0; wW = sW - sizeW; wH = sH - sizeH;
if (east)  wX = sizeW;
if (north) wY = sizeH;

which in C/C++/Java and other similar languages can be written as:

sizeW = (tH == sH) ? tW : 0; 
sizeH = (tW == sW) ? tH : 0;
wX = (sizeH == 0 && tX == 0) ? sizeW : 0; 
wY = (sizeW == 0 && tY == 0) ? sizeH : 0; 
wW = sW - sizeW; 
wH = sH - sizeH;

This seems to be correct for the case you've given. I haven't re-checked for the other cases though, so I may have made a mistake.

EDIT:

after a bit more thinking, I think I found the optimum selection:

wW = sW - ((tH == sH) ? tW : 0); 
wH = sH - ((tW == sW) ? tH : 0);
wX = (wH == sH && tX == 0) ? tW : 0; 
wY = (wW == sW && tY == 0) ? tH : 0; 
Lie Ryan
I'll give it a shot, though I don't think it saves me any lines of code =)
Chris Thompson
@Chris Thompson: you can collade sizeW and sizeH calculation into wX,wY,wW, and wH; however that means you will be calculating each of them 3 times instead of once. PS: don't put this into production code; you'll regret it later.
Lie Ryan
@Chris Thompson: does my latest update save you more code now (4-lines and no repeated subexpressions)? I believe this could be the most optimal code, though don't quote me on that.
Lie Ryan