Index: dll/win32/user32/windows/window.c =================================================================== --- dll/win32/user32/windows/window.c (revision 33630) +++ dll/win32/user32/windows/window.c (working copy) @@ -21,6 +21,18 @@ #define CW_USEDEFAULT16 0x00008000 + /* Some useful macros */ +#define HAS_DLGFRAME(style,exStyle) \ + (((exStyle) & WS_EX_DLGMODALFRAME) || \ + (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME))) + +#define HAS_THICKFRAME(style,exStyle) \ + (((style) & WS_THICKFRAME) && \ + !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME)) + +#define HAS_THINFRAME(style) \ + (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP))) + /* FUNCTIONS *****************************************************************/ @@ -977,15 +989,120 @@ } +/*********************************************************************** + * NC_GetInsideRect + * + * Get the 'inside' rectangle of a window, i.e. the whole window rectangle + * but without the borders (if any). + * The rectangle is in window coordinates (for drawing with GetWindowDC()). + */ +static void NC_GetInsideRect( HWND hwnd, RECT *rect ) +{ + PWINDOW Wnd = ValidateHwnd(hwnd); + + if (!Wnd) return; + + rect->top = rect->left = 0; + rect->right = Wnd->ClientRect.right - Wnd->ClientRect.left; + rect->bottom = Wnd->ClientRect.bottom - Wnd->ClientRect.top; + + if (Wnd->Style & WS_ICONIC) return; + + /* Remove frame from rectangle */ + if (HAS_THICKFRAME( Wnd->Style, Wnd->ExStyle )) + { + InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) ); + } + else if (HAS_DLGFRAME( Wnd->Style, Wnd->ExStyle )) + { + InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME)); + } + else if (HAS_THINFRAME( Wnd->Style )) + { + InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) ); + } + + /* We have additional border information if the window + * is a child (but not an MDI child) */ + if ( (Wnd->Style & WS_CHILD) && + ( (Wnd->ExStyle & WS_EX_MDICHILD) == 0 ) ) + { + if (Wnd->ExStyle & WS_EX_CLIENTEDGE) + InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE)); + if (Wnd->ExStyle & WS_EX_STATICEDGE) + InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER)); + } +} + /* - * @unimplemented + * @implemented */ BOOL STDCALL GetTitleBarInfo(HWND hwnd, - PTITLEBARINFO pti) + PTITLEBARINFO tbi) { - UNIMPLEMENTED; - return FALSE; + DWORD dwStyle; + DWORD dwExStyle; + RECT wndRect; + + TRACE("(%p %p)\n", hwnd, tbi); + + if(tbi->cbSize != sizeof(TITLEBARINFO)) { + TRACE("Invalid TITLEBARINFO size: %d\n", tbi->cbSize); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + dwStyle = GetWindowLongW(hwnd, GWL_STYLE); + dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE); + NC_GetInsideRect(hwnd, &tbi->rcTitleBar); + + GetWindowRect(hwnd, &wndRect); + + tbi->rcTitleBar.top += wndRect.top; + tbi->rcTitleBar.left += wndRect.left; + tbi->rcTitleBar.right += wndRect.left; + + tbi->rcTitleBar.bottom = tbi->rcTitleBar.top; + if(dwExStyle & WS_EX_TOOLWINDOW) + tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYSMCAPTION); + else { + tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYCAPTION); + tbi->rcTitleBar.left += GetSystemMetrics(SM_CXSIZE); + } + + ZeroMemory(&tbi->rgstate, sizeof(tbi->rgstate)); + /* Does the title bar always have STATE_SYSTEM_FOCUSABLE? + * Under XP it seems to + */ + tbi->rgstate[0] = STATE_SYSTEM_FOCUSABLE; + if(dwStyle & WS_CAPTION) { + tbi->rgstate[1] = STATE_SYSTEM_INVISIBLE; + if(dwStyle & WS_SYSMENU) { + if(!(dwStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX))) { + tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE; + tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE; + } + else { + if(!(dwStyle & WS_MINIMIZEBOX)) + tbi->rgstate[2] = STATE_SYSTEM_UNAVAILABLE; + if(!(dwStyle & WS_MAXIMIZEBOX)) + tbi->rgstate[3] = STATE_SYSTEM_UNAVAILABLE; + } + if(!(dwExStyle & WS_EX_CONTEXTHELP)) + tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE; + if(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE) + tbi->rgstate[5] = STATE_SYSTEM_UNAVAILABLE; + } + else { + tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE; + tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE; + tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE; + tbi->rgstate[5] = STATE_SYSTEM_INVISIBLE; + } + } + else + tbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE; + return TRUE; }