views:

1369

answers:

4

Is there an API call to determine the size and position of window caption buttons? I'm trying to draw vista-style caption buttons onto an owner drawn window. I'm dealing with c/c++/mfc.

Edit: Does anyone have a code example to draw the close button?

+2  A: 

GetSystemMetrics gives all these informations. To draw within the window decoration, use GetWindowDC.

fbonnet
What about the position?
Mark Ingram
If you're drawing your own controls, shouldn't you choose these values yourself according to your needs?
fbonnet
Well, I'm drawing my own backgrounds etc, and on XP we draw our own min/restore/close buttons - however on Vista we want to draw the proper vista buttons in the correct place.
Mark Ingram
A: 

GetSystemMetrics function should help you with a size (SM_CYSIZE and SM_CXSIZE parameters).

EDIT

I'm not sure you can find positions with this function but you might take a look at emule source code, they've managed to add a button to a window caption.

Serge
What about the position?
Mark Ingram
+2  A: 

I've found the function required to get the position of the buttons in vista:

http://msdn.microsoft.com/en-us/library/aa969436.aspx (WM_GETTITLEBARINFOEX)

This link also shows the system metrics required to get all the spacing correct (shame it's not a full dialog picture though). This works perfectly in Vista, and mostly in XP (in XP there is slightly too much of a gap between the buttons).

http://shellrevealed.com/photos/blog_images/images/4538/original.aspx

Mark Ingram
Sadly, the shellrevealed link is now broken - if you have this information anywhere else could you add it directly into the answer? Thanks.
Will Dean
+1  A: 

The following code is adapted from the "Global Titlebar Hook" example I found at http://www.catch22.net/content/snippets. I modified the example to make it MFC-friendly. It returns the X-coordinate of the leftmost titlebar button but it could easily be modified to find the position of any of the buttons.

#define B_EDGE 2

int CMyWindow::CalcRightEdge()
{
 if(GetStyle() & WS_THICKFRAME)
  return GetSystemMetrics(SM_CXSIZEFRAME);
 else
  return GetSystemMetrics(SM_CXFIXEDFRAME);
}


int CMyWindow::findNewButtonPosition()
{
 int   nButSize  = 0;
 DWORD dwStyle   = GetStyle();
 DWORD dwExStyle = GetExStyle();

 if(dwExStyle & WS_EX_TOOLWINDOW)
 {
  int nSysButSize = GetSystemMetrics(SM_CXSMSIZE) - B_EDGE;

  if(GetStyle() & WS_SYSMENU) 
   nButSize += nSysButSize + B_EDGE;

  return nButSize + CalcRightEdge();
 }
 else
 {
  int nSysButSize = GetSystemMetrics(SM_CXSIZE) - B_EDGE;

 // Window has Close [X] button. This button has a 2-pixel
 // border on either size
  if(dwStyle & WS_SYSMENU) 
   nButSize += nSysButSize + B_EDGE;

 // If either of the minimize or maximize buttons are shown,
 // Then both will appear (but may be disabled)
 // This button pair has a 2 pixel border on the left
  if(dwStyle & (WS_MINIMIZEBOX | WS_MAXIMIZEBOX) )
   nButSize += B_EDGE + nSysButSize * 2;

 // A window can have a question-mark button, but only
 // if it doesn't have any min/max buttons
  else if(dwExStyle & WS_EX_CONTEXTHELP)
   nButSize += B_EDGE + nSysButSize;

 // Now calculate the size of the border...aggghh!
  return nButSize + CalcRightEdge();
 }
}
Adam Pierce