nonclient.c 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672
  1. /*
  2. * Non-client area window functions
  3. *
  4. * Copyright 1994 Alexandre Julliard
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. */
  20. #include "config.h"
  21. #include <stdarg.h>
  22. #include "windef.h"
  23. #include "winbase.h"
  24. #include "wingdi.h"
  25. #include "wine/winuser16.h"
  26. #include "wownt32.h"
  27. #include "win.h"
  28. #include "user_private.h"
  29. #include "dce.h"
  30. #include "controls.h"
  31. #include "cursoricon.h"
  32. #include "winpos.h"
  33. #include "shellapi.h"
  34. #include "wine/debug.h"
  35. WINE_DEFAULT_DEBUG_CHANNEL(nonclient);
  36. WINE_DECLARE_DEBUG_CHANNEL(shell);
  37. BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
  38. static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
  39. 0x55, 0x50,
  40. 0xAA, 0xA0,
  41. 0x55, 0x50,
  42. 0xAA, 0xA0,
  43. 0x55, 0x50,
  44. 0xAA, 0xA0,
  45. 0x55, 0x50,
  46. 0xAA, 0xA0,
  47. 0x55, 0x50};
  48. #define SC_ABOUTWINE (SC_SCREENSAVE+1)
  49. #define SC_PUTMARK (SC_SCREENSAVE+2)
  50. /* Some useful macros */
  51. #define HAS_DLGFRAME(style,exStyle) \
  52. (((exStyle) & WS_EX_DLGMODALFRAME) || \
  53. (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
  54. #define HAS_THICKFRAME(style,exStyle) \
  55. (((style) & WS_THICKFRAME) && \
  56. !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
  57. #define HAS_THINFRAME(style) \
  58. (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
  59. #define HAS_BIGFRAME(style,exStyle) \
  60. (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
  61. ((exStyle) & WS_EX_DLGMODALFRAME))
  62. #define HAS_STATICOUTERFRAME(style,exStyle) \
  63. (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
  64. WS_EX_STATICEDGE)
  65. #define HAS_ANYFRAME(style,exStyle) \
  66. (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
  67. ((exStyle) & WS_EX_DLGMODALFRAME) || \
  68. !((style) & (WS_CHILD | WS_POPUP)))
  69. #define HAS_MENU(w) (!((w)->dwStyle & WS_CHILD) && ((w)->wIDmenu != 0))
  70. /******************************************************************************
  71. * NC_AdjustRectOuter
  72. *
  73. * Computes the size of the "outside" parts of the window based on the
  74. * parameters of the client area.
  75. *
  76. + PARAMS
  77. * LPRECT16 rect
  78. * DWORD style
  79. * BOOL menu
  80. * DWORD exStyle
  81. *
  82. * NOTES
  83. * "Outer" parts of a window means the whole window frame, caption and
  84. * menu bar. It does not include "inner" parts of the frame like client
  85. * edge, static edge or scroll bars.
  86. *
  87. *****************************************************************************/
  88. static void
  89. NC_AdjustRectOuter (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
  90. {
  91. int adjust;
  92. if(style & WS_ICONIC) return;
  93. if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
  94. WS_EX_STATICEDGE)
  95. {
  96. adjust = 1; /* for the outer frame always present */
  97. }
  98. else
  99. {
  100. adjust = 0;
  101. if ((exStyle & WS_EX_DLGMODALFRAME) ||
  102. (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
  103. }
  104. if (style & WS_THICKFRAME)
  105. adjust += ( GetSystemMetrics (SM_CXFRAME)
  106. - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
  107. if ((style & (WS_BORDER|WS_DLGFRAME)) ||
  108. (exStyle & WS_EX_DLGMODALFRAME))
  109. adjust++; /* The other border */
  110. InflateRect (rect, adjust, adjust);
  111. if ((style & WS_CAPTION) == WS_CAPTION)
  112. {
  113. if (exStyle & WS_EX_TOOLWINDOW)
  114. rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
  115. else
  116. rect->top -= GetSystemMetrics(SM_CYCAPTION);
  117. }
  118. if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
  119. }
  120. /******************************************************************************
  121. * NC_AdjustRectInner
  122. *
  123. * Computes the size of the "inside" part of the window based on the
  124. * parameters of the client area.
  125. *
  126. + PARAMS
  127. * LPRECT16 rect
  128. * DWORD style
  129. * DWORD exStyle
  130. *
  131. * NOTES
  132. * "Inner" part of a window means the window frame inside of the flat
  133. * window frame. It includes the client edge, the static edge and the
  134. * scroll bars.
  135. *
  136. *****************************************************************************/
  137. static void
  138. NC_AdjustRectInner (LPRECT rect, DWORD style, DWORD exStyle)
  139. {
  140. if(style & WS_ICONIC) return;
  141. if (exStyle & WS_EX_CLIENTEDGE)
  142. InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
  143. if (style & WS_VSCROLL)
  144. {
  145. if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
  146. rect->left -= GetSystemMetrics(SM_CXVSCROLL);
  147. else
  148. rect->right += GetSystemMetrics(SM_CXVSCROLL);
  149. }
  150. if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
  151. }
  152. static HICON NC_IconForWindow( HWND hwnd )
  153. {
  154. HICON hIcon = 0;
  155. WND *wndPtr = WIN_GetPtr( hwnd );
  156. if (wndPtr && wndPtr != WND_OTHER_PROCESS)
  157. {
  158. hIcon = wndPtr->hIconSmall;
  159. if (!hIcon) hIcon = wndPtr->hIcon;
  160. WIN_ReleasePtr( wndPtr );
  161. }
  162. if (!hIcon) hIcon = (HICON) GetClassLongA( hwnd, GCL_HICONSM );
  163. if (!hIcon) hIcon = (HICON) GetClassLongA( hwnd, GCL_HICON );
  164. /* If there is no hIcon specified and this is a modal dialog,
  165. * get the default one.
  166. */
  167. if (!hIcon && (GetWindowLongA( hwnd, GWL_STYLE ) & DS_MODALFRAME))
  168. hIcon = LoadImageA(0, (LPSTR)IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
  169. return hIcon;
  170. }
  171. /***********************************************************************
  172. * DrawCaption (USER32.@) Draws a caption bar
  173. *
  174. * PARAMS
  175. * hwnd [I]
  176. * hdc [I]
  177. * lpRect [I]
  178. * uFlags [I]
  179. *
  180. * RETURNS
  181. * Success:
  182. * Failure:
  183. */
  184. BOOL WINAPI
  185. DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
  186. {
  187. return DrawCaptionTempA (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x1F);
  188. }
  189. /***********************************************************************
  190. * DrawCaptionTempA (USER32.@)
  191. */
  192. BOOL WINAPI DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
  193. HICON hIcon, LPCSTR str, UINT uFlags)
  194. {
  195. LPWSTR strW;
  196. INT len;
  197. BOOL ret = FALSE;
  198. if (!(uFlags & DC_TEXT) || !str)
  199. return DrawCaptionTempW( hwnd, hdc, rect, hFont, hIcon, NULL, uFlags );
  200. len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
  201. if ((strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
  202. {
  203. MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
  204. ret = DrawCaptionTempW (hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
  205. HeapFree( GetProcessHeap (), 0, strW );
  206. }
  207. return ret;
  208. }
  209. /***********************************************************************
  210. * DrawCaptionTempW (USER32.@)
  211. */
  212. BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
  213. HICON hIcon, LPCWSTR str, UINT uFlags)
  214. {
  215. RECT rc = *rect;
  216. TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
  217. hwnd, hdc, rect, hFont, hIcon, debugstr_w(str), uFlags);
  218. /* drawing background */
  219. if (uFlags & DC_INBUTTON) {
  220. FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
  221. if (uFlags & DC_ACTIVE) {
  222. HBRUSH hbr = SelectObject (hdc, UITOOLS_GetPattern55AABrush ());
  223. PatBlt (hdc, rc.left, rc.top,
  224. rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
  225. SelectObject (hdc, hbr);
  226. }
  227. }
  228. else {
  229. FillRect (hdc, &rc, GetSysColorBrush ((uFlags & DC_ACTIVE) ?
  230. COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
  231. }
  232. /* drawing icon */
  233. if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
  234. POINT pt;
  235. pt.x = rc.left + 2;
  236. pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
  237. if (!hIcon) hIcon = NC_IconForWindow(hwnd);
  238. DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
  239. GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
  240. rc.left += (rc.bottom - rc.top);
  241. }
  242. /* drawing text */
  243. if (uFlags & DC_TEXT) {
  244. HFONT hOldFont;
  245. if (uFlags & DC_INBUTTON)
  246. SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
  247. else if (uFlags & DC_ACTIVE)
  248. SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
  249. else
  250. SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
  251. SetBkMode (hdc, TRANSPARENT);
  252. if (hFont)
  253. hOldFont = SelectObject (hdc, hFont);
  254. else {
  255. NONCLIENTMETRICSW nclm;
  256. HFONT hNewFont;
  257. nclm.cbSize = sizeof(NONCLIENTMETRICSW);
  258. SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
  259. hNewFont = CreateFontIndirectW ((uFlags & DC_SMALLCAP) ?
  260. &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
  261. hOldFont = SelectObject (hdc, hNewFont);
  262. }
  263. if (str)
  264. DrawTextW (hdc, str, -1, &rc,
  265. DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
  266. else {
  267. WCHAR szText[128];
  268. INT nLen;
  269. nLen = GetWindowTextW (hwnd, szText, 128);
  270. DrawTextW (hdc, szText, nLen, &rc,
  271. DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
  272. }
  273. if (hFont)
  274. SelectObject (hdc, hOldFont);
  275. else
  276. DeleteObject (SelectObject (hdc, hOldFont));
  277. }
  278. /* drawing focus ??? */
  279. if (uFlags & 0x2000)
  280. FIXME("undocumented flag (0x2000)!\n");
  281. return 0;
  282. }
  283. /***********************************************************************
  284. * AdjustWindowRect (USER32.@)
  285. */
  286. BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
  287. {
  288. return AdjustWindowRectEx( rect, style, menu, 0 );
  289. }
  290. /***********************************************************************
  291. * AdjustWindowRectEx (USER32.@)
  292. */
  293. BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
  294. {
  295. /* Correct the window style */
  296. style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
  297. exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
  298. WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
  299. if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
  300. TRACE("(%ld,%ld)-(%ld,%ld) %08lx %d %08lx\n",
  301. rect->left, rect->top, rect->right, rect->bottom,
  302. style, menu, exStyle );
  303. NC_AdjustRectOuter( rect, style, menu, exStyle );
  304. NC_AdjustRectInner( rect, style, exStyle );
  305. return TRUE;
  306. }
  307. /***********************************************************************
  308. * NC_HandleNCCalcSize
  309. *
  310. * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
  311. */
  312. LONG NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
  313. {
  314. RECT tmpRect = { 0, 0, 0, 0 };
  315. LONG result = 0;
  316. LONG cls_style = GetClassLongA(hwnd, GCL_STYLE);
  317. LONG style = GetWindowLongA( hwnd, GWL_STYLE );
  318. LONG exStyle = GetWindowLongA( hwnd, GWL_EXSTYLE );
  319. if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
  320. if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
  321. if (!IsIconic(hwnd))
  322. {
  323. NC_AdjustRectOuter( &tmpRect, style, FALSE, exStyle );
  324. winRect->left -= tmpRect.left;
  325. winRect->top -= tmpRect.top;
  326. winRect->right -= tmpRect.right;
  327. winRect->bottom -= tmpRect.bottom;
  328. if (!(style & WS_CHILD) && GetMenu(hwnd))
  329. {
  330. TRACE("Calling GetMenuBarHeight with hwnd %p, width %ld, at (%ld, %ld).\n",
  331. hwnd, winRect->right - winRect->left, -tmpRect.left, -tmpRect.top );
  332. winRect->top +=
  333. MENU_GetMenuBarHeight( hwnd,
  334. winRect->right - winRect->left,
  335. -tmpRect.left, -tmpRect.top ) + 1;
  336. }
  337. SetRect(&tmpRect, 0, 0, 0, 0);
  338. NC_AdjustRectInner (&tmpRect, style, exStyle);
  339. winRect->left -= tmpRect.left;
  340. winRect->top -= tmpRect.top;
  341. winRect->right -= tmpRect.right;
  342. winRect->bottom -= tmpRect.bottom;
  343. if (winRect->top > winRect->bottom)
  344. winRect->bottom = winRect->top;
  345. if (winRect->left > winRect->right)
  346. winRect->right = winRect->left;
  347. }
  348. return result;
  349. }
  350. /***********************************************************************
  351. * NC_GetInsideRect
  352. *
  353. * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
  354. * but without the borders (if any).
  355. * The rectangle is in window coordinates (for drawing with GetWindowDC()).
  356. */
  357. static void NC_GetInsideRect( HWND hwnd, RECT *rect )
  358. {
  359. WND *wndPtr = WIN_GetPtr( hwnd );
  360. if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return;
  361. rect->top = rect->left = 0;
  362. rect->right = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
  363. rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
  364. if (wndPtr->dwStyle & WS_ICONIC) goto END;
  365. /* Remove frame from rectangle */
  366. if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
  367. {
  368. InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
  369. }
  370. else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
  371. {
  372. InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
  373. }
  374. else if (HAS_THINFRAME( wndPtr->dwStyle ))
  375. {
  376. InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
  377. }
  378. /* We have additional border information if the window
  379. * is a child (but not an MDI child) */
  380. if ( (wndPtr->dwStyle & WS_CHILD) &&
  381. ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
  382. {
  383. if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
  384. InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
  385. if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
  386. InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
  387. }
  388. END:
  389. WIN_ReleasePtr( wndPtr );
  390. }
  391. /***********************************************************************
  392. * NC_DoNCHitTest
  393. *
  394. * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
  395. *
  396. * FIXME: Just a modified copy of the Win 3.1 version.
  397. */
  398. static LONG NC_DoNCHitTest (WND *wndPtr, POINT pt )
  399. {
  400. RECT rect, rcClient;
  401. POINT ptClient;
  402. TRACE("hwnd=%p pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
  403. GetWindowRect(wndPtr->hwndSelf, &rect );
  404. if (!PtInRect( &rect, pt )) return HTNOWHERE;
  405. if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
  406. /* Check client area */
  407. ptClient = pt;
  408. ScreenToClient( wndPtr->hwndSelf, &ptClient );
  409. GetClientRect( wndPtr->hwndSelf, &rcClient );
  410. if (PtInRect( &rcClient, ptClient )) return HTCLIENT;
  411. /* Check borders */
  412. if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
  413. {
  414. InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
  415. if (!PtInRect( &rect, pt ))
  416. {
  417. /* Check top sizing border */
  418. if (pt.y < rect.top)
  419. {
  420. if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
  421. if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
  422. return HTTOP;
  423. }
  424. /* Check bottom sizing border */
  425. if (pt.y >= rect.bottom)
  426. {
  427. if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
  428. if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
  429. return HTBOTTOM;
  430. }
  431. /* Check left sizing border */
  432. if (pt.x < rect.left)
  433. {
  434. if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
  435. if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
  436. return HTLEFT;
  437. }
  438. /* Check right sizing border */
  439. if (pt.x >= rect.right)
  440. {
  441. if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
  442. if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
  443. return HTRIGHT;
  444. }
  445. }
  446. }
  447. else /* No thick frame */
  448. {
  449. if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
  450. InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
  451. else if (HAS_THINFRAME( wndPtr->dwStyle ))
  452. InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
  453. if (!PtInRect( &rect, pt )) return HTBORDER;
  454. }
  455. /* Check caption */
  456. if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
  457. {
  458. if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
  459. rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
  460. else
  461. rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
  462. if (!PtInRect( &rect, pt ))
  463. {
  464. BOOL min_or_max_box = (wndPtr->dwStyle & WS_MAXIMIZEBOX) ||
  465. (wndPtr->dwStyle & WS_MINIMIZEBOX);
  466. /* Check system menu */
  467. if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
  468. {
  469. if (NC_IconForWindow(wndPtr->hwndSelf))
  470. rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
  471. }
  472. if (pt.x < rect.left) return HTSYSMENU;
  473. /* Check close button */
  474. if (wndPtr->dwStyle & WS_SYSMENU)
  475. rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
  476. if (pt.x > rect.right) return HTCLOSE;
  477. /* Check maximize box */
  478. /* In win95 there is automatically a Maximize button when there is a minimize one*/
  479. if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
  480. rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
  481. if (pt.x > rect.right) return HTMAXBUTTON;
  482. /* Check minimize box */
  483. /* In win95 there is automatically a Maximize button when there is a Maximize one*/
  484. if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
  485. rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
  486. if (pt.x > rect.right) return HTMINBUTTON;
  487. return HTCAPTION;
  488. }
  489. }
  490. /* Check vertical scroll bar */
  491. if (wndPtr->dwStyle & WS_VSCROLL)
  492. {
  493. if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
  494. rcClient.left -= GetSystemMetrics(SM_CXVSCROLL);
  495. else
  496. rcClient.right += GetSystemMetrics(SM_CXVSCROLL);
  497. if (PtInRect( &rcClient, ptClient )) return HTVSCROLL;
  498. }
  499. /* Check horizontal scroll bar */
  500. if (wndPtr->dwStyle & WS_HSCROLL)
  501. {
  502. rcClient.bottom += GetSystemMetrics(SM_CYHSCROLL);
  503. if (PtInRect( &rcClient, ptClient ))
  504. {
  505. /* Check size box */
  506. if ((wndPtr->dwStyle & WS_VSCROLL) &&
  507. ((((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (ptClient.x <= rcClient.left + GetSystemMetrics(SM_CXVSCROLL))) ||
  508. (((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (ptClient.x >= rcClient.right - GetSystemMetrics(SM_CXVSCROLL)))))
  509. return HTSIZE;
  510. return HTHSCROLL;
  511. }
  512. }
  513. /* Check menu bar */
  514. if (HAS_MENU(wndPtr))
  515. {
  516. if ((ptClient.y < 0) && (ptClient.x >= 0) && (ptClient.x < rcClient.right))
  517. return HTMENU;
  518. }
  519. /* Has to return HTNOWHERE if nothing was found
  520. Could happen when a window has a customized non client area */
  521. return HTNOWHERE;
  522. }
  523. /***********************************************************************
  524. * NC_HandleNCHitTest
  525. *
  526. * Handle a WM_NCHITTEST message. Called from DefWindowProc().
  527. */
  528. LONG NC_HandleNCHitTest (HWND hwnd , POINT pt)
  529. {
  530. LONG retvalue;
  531. WND *wndPtr = WIN_GetPtr( hwnd );
  532. if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return HTERROR;
  533. retvalue = NC_DoNCHitTest (wndPtr, pt);
  534. WIN_ReleasePtr( wndPtr );
  535. return retvalue;
  536. }
  537. /******************************************************************************
  538. *
  539. * NC_DrawSysButton
  540. *
  541. * Draws the system icon.
  542. *
  543. *****************************************************************************/
  544. BOOL NC_DrawSysButton (HWND hwnd, HDC hdc, BOOL down)
  545. {
  546. HICON hIcon = NC_IconForWindow( hwnd );
  547. if (hIcon)
  548. {
  549. RECT rect;
  550. NC_GetInsideRect( hwnd, &rect );
  551. DrawIconEx (hdc, rect.left + 2, rect.top + 1, hIcon,
  552. GetSystemMetrics(SM_CXSMICON),
  553. GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
  554. }
  555. return (hIcon != 0);
  556. }
  557. /******************************************************************************
  558. *
  559. * NC_DrawCloseButton
  560. *
  561. * Draws the close button.
  562. *
  563. * If bGrayed is true, then draw a disabled Close button
  564. *
  565. *****************************************************************************/
  566. static void NC_DrawCloseButton (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
  567. {
  568. RECT rect;
  569. NC_GetInsideRect( hwnd, &rect );
  570. /* A tool window has a smaller Close button */
  571. if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
  572. {
  573. INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
  574. INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
  575. INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
  576. rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
  577. rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
  578. rect.bottom = rect.top + iBmpHeight;
  579. rect.right = rect.left + iBmpWidth;
  580. }
  581. else
  582. {
  583. rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
  584. rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
  585. rect.top += 2;
  586. rect.right -= 2;
  587. }
  588. DrawFrameControl( hdc, &rect, DFC_CAPTION,
  589. (DFCS_CAPTIONCLOSE |
  590. (down ? DFCS_PUSHED : 0) |
  591. (bGrayed ? DFCS_INACTIVE : 0)) );
  592. }
  593. /******************************************************************************
  594. * NC_DrawMaxButton
  595. *
  596. * Draws the maximize button for windows.
  597. * If bGrayed is true, then draw a disabled Maximize button
  598. */
  599. static void NC_DrawMaxButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
  600. {
  601. RECT rect;
  602. UINT flags;
  603. /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
  604. if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
  605. return;
  606. flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
  607. NC_GetInsideRect( hwnd, &rect );
  608. if (GetWindowLongA( hwnd, GWL_STYLE) & WS_SYSMENU)
  609. rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
  610. rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
  611. rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
  612. rect.top += 2;
  613. rect.right -= 2;
  614. if (down) flags |= DFCS_PUSHED;
  615. if (bGrayed) flags |= DFCS_INACTIVE;
  616. DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
  617. }
  618. /******************************************************************************
  619. * NC_DrawMinButton
  620. *
  621. * Draws the minimize button for windows.
  622. * If bGrayed is true, then draw a disabled Minimize button
  623. */
  624. static void NC_DrawMinButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
  625. {
  626. RECT rect;
  627. UINT flags = DFCS_CAPTIONMIN;
  628. DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
  629. /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
  630. if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
  631. return;
  632. NC_GetInsideRect( hwnd, &rect );
  633. if (style & WS_SYSMENU)
  634. rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
  635. if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
  636. rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
  637. rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
  638. rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
  639. rect.top += 2;
  640. rect.right -= 2;
  641. if (down) flags |= DFCS_PUSHED;
  642. if (bGrayed) flags |= DFCS_INACTIVE;
  643. DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
  644. }
  645. /******************************************************************************
  646. *
  647. * NC_DrawFrame
  648. *
  649. * Draw a window frame inside the given rectangle, and update the rectangle.
  650. *
  651. * Bugs
  652. * Many. First, just what IS a frame in Win95? Note that the 3D look
  653. * on the outer edge is handled by NC_DoNCPaint. As is the inner
  654. * edge. The inner rectangle just inside the frame is handled by the
  655. * Caption code.
  656. *
  657. * In short, for most people, this function should be a nop (unless
  658. * you LIKE thick borders in Win95/NT4.0 -- I've been working with
  659. * them lately, but just to get this code right). Even so, it doesn't
  660. * appear to be so. It's being worked on...
  661. *
  662. *****************************************************************************/
  663. static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL active, DWORD style, DWORD exStyle)
  664. {
  665. INT width, height;
  666. /* Firstly the "thick" frame */
  667. if (style & WS_THICKFRAME)
  668. {
  669. width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
  670. height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
  671. SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
  672. COLOR_INACTIVEBORDER) );
  673. /* Draw frame */
  674. PatBlt( hdc, rect->left, rect->top,
  675. rect->right - rect->left, height, PATCOPY );
  676. PatBlt( hdc, rect->left, rect->top,
  677. width, rect->bottom - rect->top, PATCOPY );
  678. PatBlt( hdc, rect->left, rect->bottom - 1,
  679. rect->right - rect->left, -height, PATCOPY );
  680. PatBlt( hdc, rect->right - 1, rect->top,
  681. -width, rect->bottom - rect->top, PATCOPY );
  682. InflateRect( rect, -width, -height );
  683. }
  684. /* Now the other bit of the frame */
  685. if ((style & (WS_BORDER|WS_DLGFRAME)) ||
  686. (exStyle & WS_EX_DLGMODALFRAME))
  687. {
  688. width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
  689. height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
  690. /* This should give a value of 1 that should also work for a border */
  691. SelectObject( hdc, GetSysColorBrush(
  692. (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
  693. COLOR_3DFACE :
  694. (exStyle & WS_EX_STATICEDGE) ?
  695. COLOR_WINDOWFRAME :
  696. (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
  697. COLOR_3DFACE :
  698. /* else */
  699. COLOR_WINDOWFRAME));
  700. /* Draw frame */
  701. PatBlt( hdc, rect->left, rect->top,
  702. rect->right - rect->left, height, PATCOPY );
  703. PatBlt( hdc, rect->left, rect->top,
  704. width, rect->bottom - rect->top, PATCOPY );
  705. PatBlt( hdc, rect->left, rect->bottom - 1,
  706. rect->right - rect->left, -height, PATCOPY );
  707. PatBlt( hdc, rect->right - 1, rect->top,
  708. -width, rect->bottom - rect->top, PATCOPY );
  709. InflateRect( rect, -width, -height );
  710. }
  711. }
  712. /******************************************************************************
  713. *
  714. * NC_DrawCaption
  715. *
  716. * Draw the window caption for windows.
  717. * The correct pen for the window frame must be selected in the DC.
  718. *
  719. *****************************************************************************/
  720. static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style,
  721. DWORD exStyle, BOOL active )
  722. {
  723. RECT r = *rect;
  724. WCHAR buffer[256];
  725. HPEN hPrevPen;
  726. HMENU hSysMenu;
  727. hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
  728. ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
  729. WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
  730. COLOR_WINDOWFRAME : COLOR_3DFACE) );
  731. MoveToEx( hdc, r.left, r.bottom - 1, NULL );
  732. LineTo( hdc, r.right, r.bottom - 1 );
  733. SelectObject( hdc, hPrevPen );
  734. r.bottom--;
  735. FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
  736. COLOR_INACTIVECAPTION) );
  737. if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
  738. if (NC_DrawSysButton (hwnd, hdc, FALSE))
  739. r.left += GetSystemMetrics(SM_CXSMICON) + 2;
  740. }
  741. if (style & WS_SYSMENU)
  742. {
  743. UINT state;
  744. /* Go get the sysmenu */
  745. hSysMenu = GetSystemMenu(hwnd, FALSE);
  746. state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
  747. /* Draw a grayed close button if disabled and a normal one if SC_CLOSE is not there */
  748. NC_DrawCloseButton (hwnd, hdc, FALSE,
  749. ((((state & MF_DISABLED) || (state & MF_GRAYED))) && (state != 0xFFFFFFFF)));
  750. r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
  751. if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
  752. {
  753. /* In win95 the two buttons are always there */
  754. /* But if the menu item is not in the menu they're disabled*/
  755. NC_DrawMaxButton( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
  756. r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
  757. NC_DrawMinButton( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
  758. r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
  759. }
  760. }
  761. if (InternalGetWindowText( hwnd, buffer, sizeof(buffer)/sizeof(WCHAR) ))
  762. {
  763. NONCLIENTMETRICSW nclm;
  764. HFONT hFont, hOldFont;
  765. nclm.cbSize = sizeof(nclm);
  766. SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
  767. if (exStyle & WS_EX_TOOLWINDOW)
  768. hFont = CreateFontIndirectW (&nclm.lfSmCaptionFont);
  769. else
  770. hFont = CreateFontIndirectW (&nclm.lfCaptionFont);
  771. hOldFont = SelectObject (hdc, hFont);
  772. if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
  773. else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
  774. SetBkMode( hdc, TRANSPARENT );
  775. r.left += 2;
  776. DrawTextW( hdc, buffer, -1, &r,
  777. DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
  778. DeleteObject (SelectObject (hdc, hOldFont));
  779. }
  780. }
  781. /******************************************************************************
  782. *
  783. * NC_DoNCPaint
  784. *
  785. * Paint the non-client area for windows. The clip region is
  786. * currently ignored.
  787. *
  788. * Bugs
  789. * grep -E -A10 -B5 \(95\)\|\(Bugs\)\|\(FIXME\) windows/nonclient.c \
  790. * misc/tweak.c controls/menu.c # :-)
  791. *
  792. *****************************************************************************/
  793. static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
  794. {
  795. HDC hdc;
  796. RECT rfuzz, rect, rectClip;
  797. BOOL active;
  798. WND *wndPtr;
  799. DWORD dwStyle, dwExStyle;
  800. WORD flags;
  801. HRGN hrgn;
  802. RECT rectClient, rectWindow;
  803. int has_menu;
  804. if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
  805. has_menu = HAS_MENU(wndPtr);
  806. dwStyle = wndPtr->dwStyle;
  807. dwExStyle = wndPtr->dwExStyle;
  808. flags = wndPtr->flags;
  809. rectClient = wndPtr->rectClient;
  810. rectWindow = wndPtr->rectWindow;
  811. WIN_ReleasePtr( wndPtr );
  812. if ( dwStyle & WS_MINIMIZE ||
  813. !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
  814. active = flags & WIN_NCACTIVATED;
  815. TRACE("%p %d\n", hwnd, active );
  816. /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
  817. the call to GetDCEx implying that it is allowed not to use it either.
  818. However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
  819. will cause clipRgn to be deleted after ReleaseDC().
  820. Now, how is the "system" supposed to tell what happened?
  821. */
  822. hrgn = CreateRectRgn( rectClient.left - rectWindow.left,
  823. rectClient.top - rectWindow.top,
  824. rectClient.right - rectWindow.left,
  825. rectClient.bottom - rectWindow.top );
  826. if (clip > (HRGN)1)
  827. {
  828. CombineRgn( hrgn, clip, hrgn, RGN_DIFF );
  829. hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_INTERSECTRGN );
  830. }
  831. else
  832. {
  833. hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_EXCLUDERGN );
  834. }
  835. if (!hdc) return;
  836. rect.top = rect.left = 0;
  837. rect.right = rectWindow.right - rectWindow.left;
  838. rect.bottom = rectWindow.bottom - rectWindow.top;
  839. if( clip > (HRGN)1 )
  840. GetRgnBox( clip, &rectClip );
  841. else
  842. {
  843. clip = 0;
  844. rectClip = rect;
  845. }
  846. SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
  847. if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
  848. DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
  849. }
  850. else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
  851. DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
  852. }
  853. NC_DrawFrame(hdc, &rect, active, dwStyle, dwExStyle );
  854. if ((dwStyle & WS_CAPTION) == WS_CAPTION)
  855. {
  856. RECT r = rect;
  857. if (dwExStyle & WS_EX_TOOLWINDOW) {
  858. r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
  859. rect.top += GetSystemMetrics(SM_CYSMCAPTION);
  860. }
  861. else {
  862. r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
  863. rect.top += GetSystemMetrics(SM_CYCAPTION);
  864. }
  865. if( !clip || IntersectRect( &rfuzz, &r, &rectClip ) )
  866. NC_DrawCaption(hdc, &r, hwnd, dwStyle, dwExStyle, active);
  867. }
  868. if (has_menu)
  869. {
  870. RECT r = rect;
  871. r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
  872. TRACE("Calling DrawMenuBar with rect (%ld, %ld)-(%ld, %ld)\n",
  873. r.left, r.top, r.right, r.bottom);
  874. rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
  875. }
  876. TRACE("After MenuBar, rect is (%ld, %ld)-(%ld, %ld).\n",
  877. rect.left, rect.top, rect.right, rect.bottom );
  878. if (dwExStyle & WS_EX_CLIENTEDGE)
  879. DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
  880. /* Draw the scroll-bars */
  881. if (dwStyle & WS_VSCROLL)
  882. SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
  883. if (dwStyle & WS_HSCROLL)
  884. SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
  885. /* Draw the "size-box" */
  886. if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
  887. {
  888. RECT r = rect;
  889. if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
  890. r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
  891. else
  892. r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
  893. r.top = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
  894. FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
  895. }
  896. ReleaseDC( hwnd, hdc );
  897. }
  898. /***********************************************************************
  899. * NC_HandleNCPaint
  900. *
  901. * Handle a WM_NCPAINT message. Called from DefWindowProc().
  902. */
  903. LONG NC_HandleNCPaint( HWND hwnd , HRGN clip)
  904. {
  905. DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
  906. if( dwStyle & WS_VISIBLE )
  907. {
  908. if( dwStyle & WS_MINIMIZE )
  909. WINPOS_RedrawIconTitle( hwnd );
  910. else
  911. NC_DoNCPaint( hwnd, clip, FALSE );
  912. }
  913. return 0;
  914. }
  915. /***********************************************************************
  916. * NC_HandleNCActivate
  917. *
  918. * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
  919. */
  920. LONG NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
  921. {
  922. WND* wndPtr = WIN_GetPtr( hwnd );
  923. if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
  924. /* Lotus Notes draws menu descriptions in the caption of its main
  925. * window. When it wants to restore original "system" view, it just
  926. * sends WM_NCACTIVATE message to itself. Any optimizations here in
  927. * attempt to minimize redrawings lead to a not restored caption.
  928. */
  929. if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
  930. else wndPtr->flags &= ~WIN_NCACTIVATED;
  931. WIN_ReleasePtr( wndPtr );
  932. if (IsIconic(hwnd))
  933. WINPOS_RedrawIconTitle( hwnd );
  934. else
  935. NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
  936. return TRUE;
  937. }
  938. /***********************************************************************
  939. * NC_HandleSetCursor
  940. *
  941. * Handle a WM_SETCURSOR message. Called from DefWindowProc().
  942. */
  943. LONG NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
  944. {
  945. hwnd = WIN_GetFullHandle( (HWND)wParam );
  946. switch((short)LOWORD(lParam))
  947. {
  948. case HTERROR:
  949. {
  950. WORD msg = HIWORD( lParam );
  951. if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
  952. (msg == WM_RBUTTONDOWN))
  953. MessageBeep(0);
  954. }
  955. break;
  956. case HTCLIENT:
  957. {
  958. HCURSOR hCursor = (HCURSOR)GetClassLongA(hwnd, GCL_HCURSOR);
  959. if(hCursor) {
  960. SetCursor(hCursor);
  961. return TRUE;
  962. }
  963. return FALSE;
  964. }
  965. case HTLEFT:
  966. case HTRIGHT:
  967. return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZEWE ) );
  968. case HTTOP:
  969. case HTBOTTOM:
  970. return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENS ) );
  971. case HTTOPLEFT:
  972. case HTBOTTOMRIGHT:
  973. return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENWSE ) );
  974. case HTTOPRIGHT:
  975. case HTBOTTOMLEFT:
  976. return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENESW ) );
  977. }
  978. /* Default cursor: arrow */
  979. return (LONG)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
  980. }
  981. /***********************************************************************
  982. * NC_GetSysPopupPos
  983. */
  984. void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
  985. {
  986. if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
  987. else
  988. {
  989. WND *wndPtr = WIN_GetPtr( hwnd );
  990. if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return;
  991. NC_GetInsideRect( hwnd, rect );
  992. OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
  993. if (wndPtr->dwStyle & WS_CHILD)
  994. ClientToScreen( GetParent(hwnd), (POINT *)rect );
  995. rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
  996. rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
  997. WIN_ReleasePtr( wndPtr );
  998. }
  999. }
  1000. /***********************************************************************
  1001. * NC_TrackMinMaxBox
  1002. *
  1003. * Track a mouse button press on the minimize or maximize box.
  1004. *
  1005. * The big difference between 3.1 and 95 is the disabled button state.
  1006. * In win95 the system button can be disabled, so it can ignore the mouse
  1007. * event.
  1008. *
  1009. */
  1010. static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
  1011. {
  1012. MSG msg;
  1013. HDC hdc = GetWindowDC( hwnd );
  1014. BOOL pressed = TRUE;
  1015. UINT state;
  1016. DWORD wndStyle = GetWindowLongA( hwnd, GWL_STYLE);
  1017. HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
  1018. void (*paintButton)(HWND, HDC, BOOL, BOOL);
  1019. if (wParam == HTMINBUTTON)
  1020. {
  1021. /* If the style is not present, do nothing */
  1022. if (!(wndStyle & WS_MINIMIZEBOX))
  1023. return;
  1024. /* Check if the sysmenu item for minimize is there */
  1025. state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
  1026. paintButton = &NC_DrawMinButton;
  1027. }
  1028. else
  1029. {
  1030. /* If the style is not present, do nothing */
  1031. if (!(wndStyle & WS_MAXIMIZEBOX))
  1032. return;
  1033. /* Check if the sysmenu item for maximize is there */
  1034. state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
  1035. paintButton = &NC_DrawMaxButton;
  1036. }
  1037. SetCapture( hwnd );
  1038. (*paintButton)( hwnd, hdc, TRUE, FALSE);
  1039. while(1)
  1040. {
  1041. BOOL oldstate = pressed;
  1042. if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
  1043. if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
  1044. if(msg.message == WM_LBUTTONUP)
  1045. break;
  1046. if(msg.message != WM_MOUSEMOVE)
  1047. continue;
  1048. pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
  1049. if (pressed != oldstate)
  1050. (*paintButton)( hwnd, hdc, pressed, FALSE);
  1051. }
  1052. if(pressed)
  1053. (*paintButton)(hwnd, hdc, FALSE, FALSE);
  1054. ReleaseCapture();
  1055. ReleaseDC( hwnd, hdc );
  1056. /* If the item minimize or maximize of the sysmenu are not there */
  1057. /* or if the style is not present, do nothing */
  1058. if ((!pressed) || (state == 0xFFFFFFFF))
  1059. return;
  1060. if (wParam == HTMINBUTTON)
  1061. SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
  1062. else
  1063. SendMessageA( hwnd, WM_SYSCOMMAND,
  1064. IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
  1065. }
  1066. /***********************************************************************
  1067. * NC_TrackCloseButton
  1068. *
  1069. * Track a mouse button press on the Win95 close button.
  1070. */
  1071. static void NC_TrackCloseButton (HWND hwnd, WORD wParam)
  1072. {
  1073. MSG msg;
  1074. HDC hdc;
  1075. BOOL pressed = TRUE;
  1076. HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
  1077. UINT state;
  1078. if(hSysMenu == 0)
  1079. return;
  1080. state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
  1081. /* If the item close of the sysmenu is disabled or not there do nothing */
  1082. if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
  1083. return;
  1084. hdc = GetWindowDC( hwnd );
  1085. SetCapture( hwnd );
  1086. NC_DrawCloseButton (hwnd, hdc, TRUE, FALSE);
  1087. while(1)
  1088. {
  1089. BOOL oldstate = pressed;
  1090. if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
  1091. if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
  1092. if(msg.message == WM_LBUTTONUP)
  1093. break;
  1094. if(msg.message != WM_MOUSEMOVE)
  1095. continue;
  1096. pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
  1097. if (pressed != oldstate)
  1098. NC_DrawCloseButton (hwnd, hdc, pressed, FALSE);
  1099. }
  1100. if(pressed)
  1101. NC_DrawCloseButton (hwnd, hdc, FALSE, FALSE);
  1102. ReleaseCapture();
  1103. ReleaseDC( hwnd, hdc );
  1104. if (!pressed) return;
  1105. SendMessageA( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
  1106. }
  1107. /***********************************************************************
  1108. * NC_TrackScrollBar
  1109. *
  1110. * Track a mouse button press on the horizontal or vertical scroll-bar.
  1111. */
  1112. static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
  1113. {
  1114. INT scrollbar;
  1115. if ((wParam & 0xfff0) == SC_HSCROLL)
  1116. {
  1117. if ((wParam & 0x0f) != HTHSCROLL) return;
  1118. scrollbar = SB_HORZ;
  1119. }
  1120. else /* SC_VSCROLL */
  1121. {
  1122. if ((wParam & 0x0f) != HTVSCROLL) return;
  1123. scrollbar = SB_VERT;
  1124. }
  1125. SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
  1126. }
  1127. /***********************************************************************
  1128. * NC_HandleNCLButtonDown
  1129. *
  1130. * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
  1131. */
  1132. LONG NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
  1133. {
  1134. LONG style = GetWindowLongA( hwnd, GWL_STYLE );
  1135. switch(wParam) /* Hit test */
  1136. {
  1137. case HTCAPTION:
  1138. {
  1139. HWND top = GetAncestor( hwnd, GA_ROOT );
  1140. if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
  1141. SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
  1142. break;
  1143. }
  1144. case HTSYSMENU:
  1145. if( style & WS_SYSMENU )
  1146. {
  1147. if( !(style & WS_MINIMIZE) )
  1148. {
  1149. HDC hDC = GetWindowDC(hwnd);
  1150. NC_DrawSysButton( hwnd, hDC, TRUE );
  1151. ReleaseDC( hwnd, hDC );
  1152. }
  1153. SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
  1154. }
  1155. break;
  1156. case HTMENU:
  1157. SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
  1158. break;
  1159. case HTHSCROLL:
  1160. SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
  1161. break;
  1162. case HTVSCROLL:
  1163. SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
  1164. break;
  1165. case HTMINBUTTON:
  1166. case HTMAXBUTTON:
  1167. NC_TrackMinMaxBox( hwnd, wParam );
  1168. break;
  1169. case HTCLOSE:
  1170. NC_TrackCloseButton (hwnd, wParam);
  1171. break;
  1172. case HTLEFT:
  1173. case HTRIGHT:
  1174. case HTTOP:
  1175. case HTTOPLEFT:
  1176. case HTTOPRIGHT:
  1177. case HTBOTTOM:
  1178. case HTBOTTOMLEFT:
  1179. case HTBOTTOMRIGHT:
  1180. /* Old comment:
  1181. * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
  1182. * This was previously done by setting wParam=SC_SIZE + wParam - 2
  1183. */
  1184. /* But that is not what WinNT does. Instead it sends this. This
  1185. * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
  1186. * SC_MOUSEMENU into wParam.
  1187. */
  1188. SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
  1189. break;
  1190. case HTBORDER:
  1191. break;
  1192. }
  1193. return 0;
  1194. }
  1195. /***********************************************************************
  1196. * NC_HandleNCLButtonDblClk
  1197. *
  1198. * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
  1199. */
  1200. LONG NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
  1201. {
  1202. /*
  1203. * if this is an icon, send a restore since we are handling
  1204. * a double click
  1205. */
  1206. if (IsIconic(hwnd))
  1207. {
  1208. SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
  1209. return 0;
  1210. }
  1211. switch(wParam) /* Hit test */
  1212. {
  1213. case HTCAPTION:
  1214. /* stop processing if WS_MAXIMIZEBOX is missing */
  1215. if (GetWindowLongA( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
  1216. SendMessageW( hwnd, WM_SYSCOMMAND,
  1217. IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
  1218. break;
  1219. case HTSYSMENU:
  1220. if (!(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE))
  1221. SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
  1222. break;
  1223. case HTHSCROLL:
  1224. SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
  1225. break;
  1226. case HTVSCROLL:
  1227. SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
  1228. break;
  1229. }
  1230. return 0;
  1231. }
  1232. /***********************************************************************
  1233. * NC_HandleSysCommand
  1234. *
  1235. * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
  1236. */
  1237. LONG NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
  1238. {
  1239. TRACE("Handling WM_SYSCOMMAND %x %lx\n", wParam, lParam );
  1240. if (HOOK_CallHooks( WH_CBT, HCBT_SYSCOMMAND, wParam, lParam, TRUE ))
  1241. return 0;
  1242. switch (wParam & 0xfff0)
  1243. {
  1244. case SC_SIZE:
  1245. case SC_MOVE:
  1246. if (USER_Driver.pSysCommandSizeMove)
  1247. USER_Driver.pSysCommandSizeMove( hwnd, wParam );
  1248. break;
  1249. case SC_MINIMIZE:
  1250. if (hwnd == GetForegroundWindow())
  1251. ShowOwnedPopups(hwnd,FALSE);
  1252. ShowWindow( hwnd, SW_MINIMIZE );
  1253. break;
  1254. case SC_MAXIMIZE:
  1255. if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
  1256. ShowOwnedPopups(hwnd,TRUE);
  1257. ShowWindow( hwnd, SW_MAXIMIZE );
  1258. break;
  1259. case SC_RESTORE:
  1260. if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
  1261. ShowOwnedPopups(hwnd,TRUE);
  1262. ShowWindow( hwnd, SW_RESTORE );
  1263. break;
  1264. case SC_CLOSE:
  1265. return SendMessageA( hwnd, WM_CLOSE, 0, 0 );
  1266. case SC_VSCROLL:
  1267. case SC_HSCROLL:
  1268. {
  1269. POINT pt;
  1270. pt.x = (short)LOWORD(lParam);
  1271. pt.y = (short)HIWORD(lParam);
  1272. NC_TrackScrollBar( hwnd, wParam, pt );
  1273. }
  1274. break;
  1275. case SC_MOUSEMENU:
  1276. {
  1277. POINT pt;
  1278. pt.x = (short)LOWORD(lParam);
  1279. pt.y = (short)HIWORD(lParam);
  1280. MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
  1281. }
  1282. break;
  1283. case SC_KEYMENU:
  1284. MENU_TrackKbdMenuBar( hwnd, wParam, (WCHAR)lParam );
  1285. break;
  1286. case SC_TASKLIST:
  1287. WinExec( "taskman.exe", SW_SHOWNORMAL );
  1288. break;
  1289. case SC_SCREENSAVE:
  1290. if (wParam == SC_ABOUTWINE)
  1291. {
  1292. HMODULE hmodule = LoadLibraryA( "shell32.dll" );
  1293. if (hmodule)
  1294. {
  1295. FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
  1296. if (aboutproc) aboutproc( hwnd, PACKAGE_NAME, PACKAGE_STRING, 0 );
  1297. FreeLibrary( hmodule );
  1298. }
  1299. }
  1300. else
  1301. if (wParam == SC_PUTMARK)
  1302. DPRINTF("Debug mark requested by user\n");
  1303. break;
  1304. case SC_HOTKEY:
  1305. case SC_ARRANGE:
  1306. case SC_NEXTWINDOW:
  1307. case SC_PREVWINDOW:
  1308. FIXME("unimplemented WM_SYSCOMMAND %04x!\n", wParam);
  1309. break;
  1310. }
  1311. return 0;
  1312. }
  1313. /*************************************************************
  1314. * NC_DrawGrayButton
  1315. *
  1316. * Stub for the grayed button of the caption
  1317. *
  1318. *************************************************************/
  1319. BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
  1320. {
  1321. HBITMAP hMaskBmp;
  1322. HDC hdcMask;
  1323. HBRUSH hOldBrush;
  1324. hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
  1325. if(hMaskBmp == 0)
  1326. return FALSE;
  1327. hdcMask = CreateCompatibleDC (0);
  1328. SelectObject (hdcMask, hMaskBmp);
  1329. /* Draw the grayed bitmap using the mask */
  1330. hOldBrush = SelectObject (hdc, (HGDIOBJ)RGB(128, 128, 128));
  1331. BitBlt (hdc, x, y, 12, 10,
  1332. hdcMask, 0, 0, 0xB8074A);
  1333. /* Clean up */
  1334. SelectObject (hdc, hOldBrush);
  1335. DeleteObject(hMaskBmp);
  1336. DeleteDC (hdcMask);
  1337. return TRUE;
  1338. }
  1339. /***********************************************************************
  1340. * GetTitleBarInfo (USER32.@)
  1341. * TODO: Handle STATE_SYSTEM_PRESSED
  1342. */
  1343. BOOL WINAPI GetTitleBarInfo(HWND hwnd, PTITLEBARINFO tbi) {
  1344. DWORD dwStyle;
  1345. DWORD dwExStyle;
  1346. RECT wndRect;
  1347. TRACE("(%p %p)\n", hwnd, tbi);
  1348. if(tbi->cbSize != sizeof(TITLEBARINFO)) {
  1349. TRACE("Invalid TITLEBARINFO size: %ld\n", tbi->cbSize);
  1350. SetLastError(ERROR_INVALID_PARAMETER);
  1351. return FALSE;
  1352. }
  1353. dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
  1354. dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
  1355. NC_GetInsideRect(hwnd, &tbi->rcTitleBar);
  1356. GetWindowRect(hwnd, &wndRect);
  1357. tbi->rcTitleBar.top += wndRect.top;
  1358. tbi->rcTitleBar.left += wndRect.left;
  1359. tbi->rcTitleBar.right += wndRect.left;
  1360. tbi->rcTitleBar.bottom = tbi->rcTitleBar.top;
  1361. if(dwExStyle & WS_EX_TOOLWINDOW)
  1362. tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYSMCAPTION);
  1363. else {
  1364. tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYCAPTION);
  1365. tbi->rcTitleBar.left += GetSystemMetrics(SM_CXSIZE);
  1366. }
  1367. ZeroMemory(&tbi->rgstate, sizeof(tbi->rgstate));
  1368. /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
  1369. * Under XP it seems to
  1370. */
  1371. tbi->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
  1372. if(dwStyle & WS_CAPTION) {
  1373. tbi->rgstate[1] = STATE_SYSTEM_INVISIBLE;
  1374. if(dwStyle & WS_SYSMENU) {
  1375. if(!(dwStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX))) {
  1376. tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
  1377. tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
  1378. }
  1379. else {
  1380. if(!(dwStyle & WS_MINIMIZEBOX))
  1381. tbi->rgstate[2] = STATE_SYSTEM_UNAVAILABLE;
  1382. if(!(dwStyle & WS_MAXIMIZEBOX))
  1383. tbi->rgstate[3] = STATE_SYSTEM_UNAVAILABLE;
  1384. }
  1385. if(!(dwExStyle & WS_EX_CONTEXTHELP))
  1386. tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
  1387. if(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
  1388. tbi->rgstate[5] = STATE_SYSTEM_UNAVAILABLE;
  1389. }
  1390. else {
  1391. tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
  1392. tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
  1393. tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
  1394. tbi->rgstate[5] = STATE_SYSTEM_INVISIBLE;
  1395. }
  1396. }
  1397. else
  1398. tbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE;
  1399. return TRUE;
  1400. }