7

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?

Mark Ingram
  • 71,849
  • 51
  • 176
  • 230

4 Answers4

12

I've found the function required to get the position of the buttons in vista: 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).

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

Axalo
  • 2,953
  • 4
  • 25
  • 39
Mark Ingram
  • 71,849
  • 51
  • 176
  • 230
4

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

fbonnet
  • 2,325
  • 14
  • 23
  • If you're drawing your own controls, shouldn't you choose these values yourself according to your needs? – fbonnet Jan 26 '09 at 11:04
  • 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 Jan 26 '09 at 11:25
3

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
  • 33,531
  • 22
  • 69
  • 89
  • I appreciate this answer, but it's unbelievably disappointing to see that they didn't include the code to draw the buttons. – Skewjo Dec 09 '20 at 03:58
-1

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
  • 7,706
  • 5
  • 40
  • 46