some work on menus
[reactos.git] / reactos / lib / user32 / windows / defwnd.c
1 /* $Id: defwnd.c,v 1.62 2003/08/06 18:43:57 weiden Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS user32.dll
5 * FILE: lib/user32/windows/window.c
6 * PURPOSE: Window management
7 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * UPDATE HISTORY:
9 * 06-06-2001 CSH Created
10 */
11
12 /* INCLUDES ******************************************************************/
13
14 #include <windows.h>
15 #include <user32.h>
16 #include <window.h>
17 #include <user32/wininternal.h>
18 #include <string.h>
19 #include <menu.h>
20 #include <cursor.h>
21 #include <winpos.h>
22
23 #define NDEBUG
24 #include <debug.h>
25
26 /* GLOBALS *******************************************************************/
27
28 static HBITMAP hbSysMenu;
29 /* TODO: widgets will be cached here.
30 static HBITMAP hbClose;
31 static HBITMAP hbCloseD;
32 static HBITMAP hbMinimize;
33 static HBITMAP hbMinimizeD;
34 static HBITMAP hbRestore;
35 static HBITMAP hbRestoreD;
36 static HBITMAP hbMaximize;
37 static HBITMAP hbScrUp;
38 static HBITMAP hbScrDwn;
39 static HBITMAP hbScrLeft;
40 static HBITMAP hbScrRight;
41 */
42 static COLORREF SysColours[] =
43 {
44 RGB(224, 224, 224) /* COLOR_SCROLLBAR */,
45 RGB(58, 110, 165) /* COLOR_BACKGROUND */,
46 RGB(0, 0, 128) /* COLOR_ACTIVECAPTION */,
47 RGB(128, 128, 128) /* COLOR_INACTIVECAPTION */,
48 RGB(192, 192, 192) /* COLOR_MENU */,
49 RGB(192, 192, 192) /* COLOR_WINDOW */,
50 RGB(192, 192, 192) /* COLOR_WINDOWFRAME */,
51 RGB(0, 0, 0) /* COLOR_MENUTEXT */,
52 RGB(0, 0, 0) /* COLOR_WINDOWTEXT */,
53 RGB(255, 255, 255) /* COLOR_CAPTIONTEXT */,
54 RGB(128, 128, 128) /* COLOR_ACTIVEBORDER */,
55 RGB(255, 255, 255) /* COLOR_INACTIVEBORDER */,
56 RGB(255, 255, 232) /* COLOR_APPWORKSPACE */,
57 RGB(224, 224, 224) /* COLOR_HILIGHT */,
58 RGB(0, 0, 128) /* COLOR_HILIGHTTEXT */,
59 RGB(192, 192, 192) /* COLOR_BTNFACE */,
60 RGB(128, 128, 128) /* COLOR_BTNSHADOW */,
61 RGB(192, 192, 192) /* COLOR_GRAYTEXT */,
62 RGB(0, 0, 0) /* COLOR_BTNTEXT */,
63 RGB(192, 192, 192) /* COLOR_INACTIVECAPTIONTEXT */,
64 RGB(255, 255, 255) /* COLOR_BTNHILIGHT */,
65 RGB(32, 32, 32) /* COLOR_3DDKSHADOW */,
66 RGB(192, 192, 192) /* COLOR_3DLIGHT */,
67 RGB(0, 0, 0) /* COLOR_INFOTEXT */,
68 RGB(255, 255, 192) /* COLOR_INFOBK */,
69 RGB(184, 180, 184) /* COLOR_ALTERNATEBTNFACE */,
70 RGB(0, 0, 255) /* COLOR_HOTLIGHT */,
71 RGB(16, 132, 208) /* COLOR_GRADIENTACTIVECAPTION */,
72 RGB(181, 181, 181) /* COLOR_GRADIENTINACTIVECAPTION */,
73 };
74
75 static ATOM AtomInternalPos;
76
77 /* Bits in the dwKeyData */
78 #define KEYDATA_ALT 0x2000
79
80 /* FUNCTIONS *****************************************************************/
81
82 BOOL IsMaxBoxActive(HWND hWnd)
83 {
84 ULONG uStyle = GetWindowLong( hWnd, GWL_STYLE );
85 return (uStyle & WS_MAXIMIZEBOX);
86 }
87
88 BOOL IsCloseBoxActive( HWND hWnd )
89 {
90 ULONG uStyle = GetWindowLong(hWnd, GWL_STYLE );
91 return ( uStyle & WS_SYSMENU );
92 }
93
94 BOOL IsMinBoxActive( HWND hWnd )
95 {
96 ULONG uStyle = GetWindowLong( hWnd, GWL_STYLE );
97 return (uStyle & WS_MINIMIZEBOX);
98 }
99
100 INT UIGetFrameSizeX( HWND hWnd )
101 {
102 ULONG uStyle = GetWindowLong( hWnd, GWL_STYLE );
103
104 if ( uStyle & WS_THICKFRAME )
105 return GetSystemMetrics( SM_CXSIZEFRAME );
106 else
107 return GetSystemMetrics( SM_CXFRAME );
108 }
109
110 INT UIGetFrameSizeY( HWND hWnd )
111 {
112 ULONG uStyle = GetWindowLong( hWnd, GWL_STYLE );
113
114 if ( uStyle & WS_THICKFRAME )
115 return GetSystemMetrics( SM_CYSIZEFRAME );
116 else
117 return GetSystemMetrics( SM_CYFRAME );
118 }
119
120 VOID
121 UserSetupInternalPos( VOID )
122 {
123 LPSTR Str = "SysIP";
124 AtomInternalPos = GlobalAddAtomA(Str);
125 }
126
127
128 /*
129 * @implemented
130 */
131 DWORD STDCALL
132 GetSysColor(int nIndex)
133 {
134 return SysColours[nIndex];
135 }
136
137
138 HPEN STDCALL
139 GetSysColorPen( int nIndex )
140 {
141 return(CreatePen(PS_SOLID, 1, SysColours[nIndex]));
142 }
143
144
145 /*
146 * @implemented
147 */
148 HBRUSH STDCALL
149 GetSysColorBrush( int nIndex )
150 {
151 return(CreateSolidBrush(SysColours[nIndex]));
152 }
153
154
155 /*
156 * @unimplemented
157 */
158 LRESULT STDCALL
159 DefFrameProcA( HWND hWnd,
160 HWND hWndMDIClient,
161 UINT uMsg,
162 WPARAM wParam,
163 LPARAM lParam )
164 {
165 UNIMPLEMENTED;
166 return((LRESULT)0);
167 }
168
169 /*
170 * @unimplemented
171 */
172 LRESULT STDCALL
173 DefFrameProcW(HWND hWnd,
174 HWND hWndMDIClient,
175 UINT uMsg,
176 WPARAM wParam,
177 LPARAM lParam)
178 {
179 UNIMPLEMENTED;
180 return((LRESULT)0);
181 }
182
183 PINTERNALPOS
184 UserGetInternalPos(HWND hWnd)
185 {
186 PINTERNALPOS lpPos;
187 lpPos = (PINTERNALPOS)GetPropA(hWnd, (LPSTR)(DWORD)AtomInternalPos);
188 return(lpPos);
189 }
190
191 BOOL
192 DefWndRedrawIconTitle(HWND hWnd)
193 {
194 PINTERNALPOS lpPos = (PINTERNALPOS)GetPropA(hWnd,
195 (LPSTR)(DWORD)AtomInternalPos);
196 if (lpPos != NULL)
197 {
198 if (lpPos->IconTitle != NULL)
199 {
200 SendMessageA(lpPos->IconTitle, WM_SHOWWINDOW, TRUE, 0);
201 InvalidateRect(lpPos->IconTitle, NULL, TRUE);
202 return(TRUE);
203 }
204 }
205 return(FALSE);
206 }
207
208
209 BOOL
210 UserHasMenu(HWND hWnd, ULONG Style)
211 {
212 return(!(Style & WS_CHILD) && GetMenu(hWnd) != 0);
213 }
214
215
216 ULONG
217 UserHasAnyFrameStyle(ULONG Style, ULONG ExStyle)
218 {
219 return((Style & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) ||
220 (ExStyle & WS_EX_DLGMODALFRAME) ||
221 (!(Style & (WS_CHILD | WS_POPUP))));
222 }
223
224
225 ULONG
226 UserHasDlgFrameStyle(ULONG Style, ULONG ExStyle)
227 {
228 return((ExStyle & WS_EX_DLGMODALFRAME) ||
229 ((Style & WS_DLGFRAME) && (!(Style & WS_THICKFRAME))));
230 }
231
232
233 ULONG
234 UserHasThickFrameStyle(ULONG Style, ULONG ExStyle)
235 {
236 return((Style & WS_THICKFRAME) &&
237 (!((Style & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)));
238 }
239
240
241 ULONG
242 UserHasThinFrameStyle(ULONG Style, ULONG ExStyle)
243 {
244 return((Style & WS_BORDER) ||
245 (!(Style & (WS_CHILD | WS_POPUP))));
246 }
247
248
249 ULONG
250 UserHasBigFrameStyle(ULONG Style, ULONG ExStyle)
251 {
252 return((Style & (WS_THICKFRAME | WS_DLGFRAME)) ||
253 (ExStyle & WS_EX_DLGMODALFRAME));
254 }
255
256 void UserGetInsideRectNC( HWND hWnd, RECT *rect )
257 {
258 RECT WindowRect;
259 ULONG Style;
260 ULONG ExStyle;
261
262 Style = GetWindowLong(hWnd, GWL_STYLE);
263 ExStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
264 GetWindowRect(hWnd, &WindowRect);
265 rect->top = rect->left = 0;
266 rect->right = WindowRect.right - WindowRect.left;
267 rect->bottom = WindowRect.bottom - WindowRect.top;
268
269 if (Style & WS_ICONIC)
270 {
271 return;
272 }
273
274 /* Remove frame from rectangle */
275 if (UserHasThickFrameStyle(Style, ExStyle ))
276 {
277 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME),
278 -GetSystemMetrics(SM_CYFRAME) );
279 }
280 else
281 {
282 if (UserHasDlgFrameStyle(Style, ExStyle ))
283 {
284 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME),
285 -GetSystemMetrics(SM_CYDLGFRAME));
286 /* FIXME: this isn't in NC_AdjustRect? why not? */
287 if (ExStyle & WS_EX_DLGMODALFRAME)
288 InflateRect( rect, -1, 0 );
289 }
290 else
291 {
292 if (UserHasThinFrameStyle(Style, ExStyle))
293 {
294 InflateRect(rect, -GetSystemMetrics(SM_CXBORDER),
295 -GetSystemMetrics(SM_CYBORDER));
296 }
297 }
298 }
299 }
300
301 VOID UserDrawSysMenuButton( HWND hWnd, HDC hDC, BOOL down )
302 {
303 RECT Rect;
304 HDC hDcMem;
305 HBITMAP hSavedBitmap;
306
307 hbSysMenu = LoadBitmap(0, MAKEINTRESOURCE(OBM_CLOSE));
308 UserGetInsideRectNC(hWnd, &Rect);
309 hDcMem = CreateCompatibleDC(hDC);
310 hSavedBitmap = SelectObject(hDcMem, hbSysMenu);
311 BitBlt(hDC, Rect.left + 2, Rect.top +
312 2, 16, 16, hDcMem,
313 (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD) ?
314 GetSystemMetrics(SM_CXSIZE): 0, 0, SRCCOPY);
315 SelectObject(hDcMem, hSavedBitmap);
316 DeleteDC(hDcMem);
317 }
318
319 /* FIXME: Cache bitmaps, then just bitblt instead of calling DFC() (and
320 wasting precious CPU cycles) every time */
321
322 static void UserDrawCaptionButton( HWND hWnd, HDC hDC, BOOL bDown, ULONG Type )
323 {
324
325 RECT rect;
326 INT iBmpWidth = GetSystemMetrics(SM_CXSIZE) - 2;
327 INT iBmpHeight = GetSystemMetrics(SM_CYSIZE) - 4;
328
329 INT OffsetX = UIGetFrameSizeX( hWnd );
330 INT OffsetY = UIGetFrameSizeY( hWnd );
331
332 if(!(GetWindowLong( hWnd, GWL_STYLE ) & WS_SYSMENU))
333 {
334 return;
335 }
336
337 GetWindowRect( hWnd, &rect );
338
339 rect.right = rect.right - rect.left;
340 rect.bottom = rect.bottom - rect.top;
341 rect.left = rect.top = 0;
342
343 switch(Type)
344 {
345 case DFCS_CAPTIONMIN:
346 {
347 if ((GetWindowLong( hWnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW) == TRUE)
348 return; /* ToolWindows don't have min/max buttons */
349
350 SetRect(&rect,
351 rect.right - OffsetX - (iBmpWidth*3) - 5,
352 OffsetY + 2,
353 rect.right - (iBmpWidth * 2) - OffsetX - 5,
354 rect.top + iBmpHeight + OffsetY + 2 );
355 DrawFrameControl( hDC, &rect, DFC_CAPTION,
356 DFCS_CAPTIONMIN | (bDown ? DFCS_PUSHED : 0) |
357 (IsMinBoxActive(hWnd) ? 0 : DFCS_INACTIVE) );
358 break;
359 }
360 case DFCS_CAPTIONMAX:
361 {
362 if ((GetWindowLong( hWnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW) == TRUE)
363 return; /* ToolWindows don't have min/max buttons */
364 SetRect(&rect,
365 rect.right - OffsetX - (iBmpWidth*2) - 5,
366 OffsetY + 2,
367 rect.right - iBmpWidth - OffsetX - 5,
368 rect.top + iBmpHeight + OffsetY + 2 );
369
370 DrawFrameControl( hDC, &rect, DFC_CAPTION,
371 (IsZoomed(hWnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX) |
372 (bDown ? DFCS_PUSHED : 0) |
373 (IsMaxBoxActive(hWnd) ? 0 : DFCS_INACTIVE) );
374 break;
375 }
376 case DFCS_CAPTIONCLOSE:
377 {
378 SetRect(&rect,
379 rect.right - OffsetX - iBmpWidth - 3,
380 OffsetY + 2,
381 rect.right - OffsetX - 3,
382 rect.top + iBmpHeight + OffsetY + 2 );
383
384 DrawFrameControl( hDC, &rect, DFC_CAPTION,
385 (DFCS_CAPTIONCLOSE |
386 (bDown ? DFCS_PUSHED : 0) |
387 (IsCloseBoxActive(hWnd) ? 0 : DFCS_INACTIVE)) );
388 }
389 }
390 }
391
392 static void UserDrawCaptionNC( HDC hDC, RECT *rect, HWND hWnd,
393 DWORD style, BOOL active )
394 {
395 RECT r = *rect;
396 WCHAR buffer[256];
397 /* FIXME: Implement and Use DrawCaption() */
398 SelectObject( hDC, GetSysColorBrush(active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION) );
399
400 PatBlt(hDC,rect->left + GetSystemMetrics(SM_CXFRAME), rect->top +
401 GetSystemMetrics(SM_CYFRAME), rect->right - (GetSystemMetrics(SM_CXFRAME) * 2), (rect->top +
402 GetSystemMetrics(SM_CYCAPTION)) - 1, PATCOPY );
403
404 if (style & WS_SYSMENU)
405 {
406 UserDrawSysMenuButton( hWnd, hDC, FALSE);
407 r.left += GetSystemMetrics(SM_CXSIZE) + 1;
408 UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONCLOSE);
409 r.right -= GetSystemMetrics(SM_CXSMSIZE) + 1;
410 UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONMIN);
411 UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONMAX);
412 }
413 if (GetWindowTextW( hWnd, buffer, sizeof(buffer)/sizeof(buffer[0]) ))
414 {
415 NONCLIENTMETRICSW nclm;
416 HFONT hFont, hOldFont;
417
418 nclm.cbSize = sizeof(nclm);
419 SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
420 SetTextColor(hDC, SysColours[ active ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT]);
421 SetBkMode( hDC, TRANSPARENT );
422 if (style & WS_EX_TOOLWINDOW)
423 hFont = CreateFontIndirectW(&nclm.lfSmCaptionFont);
424 else
425 hFont = CreateFontIndirectW(&nclm.lfCaptionFont);
426 hOldFont = SelectObject(hDC, hFont);
427 TextOutW(hDC, r.left + (GetSystemMetrics(SM_CXDLGFRAME) * 2), rect->top + (nclm.lfCaptionFont.lfHeight / 2), buffer, wcslen(buffer));
428 DeleteObject (SelectObject (hDC, hOldFont));
429 }
430 }
431
432
433 VOID
434 UserDrawFrameNC(HWND hWnd, RECT* rect, BOOL dlgFrame, BOOL active)
435 {
436 HDC hDC = GetWindowDC(hWnd);
437 SelectObject( hDC, GetSysColorBrush(COLOR_WINDOW) );
438 DrawEdge(hDC, rect,EDGE_RAISED, BF_RECT | BF_MIDDLE);
439 }
440
441
442 void SCROLL_DrawScrollBar (HWND hWnd, HDC hDC, INT nBar, BOOL arrows, BOOL interior);
443
444 VOID
445 DefWndDoPaintNC(HWND hWnd, HRGN clip)
446 {
447 ULONG Active;
448 HDC hDC;
449 RECT rect;
450 ULONG Style;
451 ULONG ExStyle;
452 int wFrame = 0;
453
454 Active = GetWindowLongW(hWnd, GWL_STYLE) & WIN_NCACTIVATED;
455 Style = GetWindowLong(hWnd, GWL_STYLE);
456 ExStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
457
458 hDC = GetDCEx(hWnd, (clip > (HRGN)1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
459 ((clip > (HRGN)1) ? (DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0));
460 if (hDC == 0)
461 {
462 return;
463 }
464
465 /* FIXME: Test whether we need to draw anything at all. */
466
467 GetWindowRect(hWnd, &rect);
468 rect.right = rect.right - rect.left;
469 rect.bottom = rect.bottom - rect.top;
470 rect.top = rect.left = 0;
471 SelectObject(hDC, GetSysColorPen(COLOR_WINDOWFRAME));
472 if (UserHasThickFrameStyle(Style, ExStyle))
473 {
474 UserDrawFrameNC(hWnd, &rect, FALSE, Active);
475 wFrame = GetSystemMetrics(SM_CXSIZEFRAME);
476 }
477 else if (UserHasDlgFrameStyle(Style, ExStyle))
478 {
479 UserDrawFrameNC(hWnd, &rect, TRUE, Active);
480 wFrame = GetSystemMetrics(SM_CXDLGFRAME);
481 }
482 if (Style & WS_CAPTION)
483 {
484 RECT r = rect;
485 r.bottom = rect.top + GetSystemMetrics(SM_CYSIZE);
486 rect.top += GetSystemMetrics(SM_CYSIZE) +
487 GetSystemMetrics(SM_CYBORDER);
488 UserDrawCaptionNC(hDC, &r, hWnd, Style, Active);
489 }
490
491 /* Draw menu bar. */
492 if (UserHasMenu(hWnd, Style))
493 {
494 RECT r = rect;
495 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
496 r.left += wFrame;
497 r.right -= wFrame;
498 rect.top += MenuDrawMenuBar(hDC, &r, hWnd, FALSE);
499 }
500
501 /* Draw scrollbars */
502 if (Style & WS_VSCROLL)
503 SCROLL_DrawScrollBar(hWnd, hDC, SB_VERT, TRUE, TRUE);
504 if (Style & WS_HSCROLL)
505 SCROLL_DrawScrollBar(hWnd, hDC, SB_HORZ, TRUE, TRUE);
506
507 /* FIXME: Draw size box.*/
508
509 ReleaseDC(hWnd, hDC);
510 }
511
512
513 LRESULT
514 DefWndPaintNC(HWND hWnd, HRGN clip)
515 {
516 if (IsWindowVisible(hWnd))
517 {
518 if (IsIconic(hWnd))
519 {
520 DefWndRedrawIconTitle(hWnd);
521 }
522 else
523 {
524 DefWndDoPaintNC(hWnd, clip);
525 }
526 }
527 return(0);
528 }
529
530
531 LRESULT
532 DefWndHitTestNC(HWND hWnd, POINT Point)
533 {
534 RECT WindowRect;
535 ULONG Style = GetWindowLong(hWnd, GWL_STYLE);
536 ULONG ExStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
537
538 GetWindowRect(hWnd, &WindowRect);
539 if (!PtInRect(&WindowRect, Point))
540 {
541 return(HTNOWHERE);
542 }
543 if (Style & WS_MINIMIZE)
544 {
545 return(HTCAPTION);
546 }
547 if (UserHasThickFrameStyle(Style, ExStyle))
548 {
549 InflateRect(&WindowRect, -GetSystemMetrics(SM_CXFRAME),
550 -GetSystemMetrics(SM_CYFRAME));
551 if (!PtInRect(&WindowRect, Point))
552 {
553 if (Point.y < WindowRect.top)
554 {
555 if (Point.x < (WindowRect.left + GetSystemMetrics(SM_CXSIZE)))
556 {
557 return(HTTOPLEFT);
558 }
559 if (Point.x >= (WindowRect.right - GetSystemMetrics(SM_CXSIZE)))
560 {
561 return(HTTOPRIGHT);
562 }
563 return(HTTOP);
564 }
565 if (Point.y >= WindowRect.bottom)
566 {
567 if (Point.x < (WindowRect.left + GetSystemMetrics(SM_CXSIZE)))
568 {
569 return(HTBOTTOMLEFT);
570 }
571 if (Point.x >= (WindowRect.right - GetSystemMetrics(SM_CXSIZE)))
572 {
573 return(HTBOTTOMRIGHT);
574 }
575 return(HTBOTTOM);
576 }
577 if (Point.x < WindowRect.left)
578 {
579 if (Point.y < (WindowRect.top + GetSystemMetrics(SM_CYSIZE)))
580 {
581 return(HTTOPLEFT);
582 }
583 if (Point.y >= (WindowRect.bottom - GetSystemMetrics(SM_CYSIZE)))
584 {
585 return(HTBOTTOMLEFT);
586 }
587 return(HTLEFT);
588 }
589 if (Point.x >= WindowRect.right)
590 {
591 if (Point.y < (WindowRect.top + GetSystemMetrics(SM_CYSIZE)))
592 {
593 return(HTTOPRIGHT);
594 }
595 if (Point.y >= (WindowRect.bottom - GetSystemMetrics(SM_CYSIZE)))
596 {
597 return(HTBOTTOMRIGHT);
598 }
599 return(HTRIGHT);
600 }
601 }
602 }
603 else
604 {
605 if (UserHasDlgFrameStyle(Style, ExStyle))
606 {
607 InflateRect(&WindowRect, -GetSystemMetrics(SM_CXDLGFRAME),
608 -GetSystemMetrics(SM_CYDLGFRAME));
609 }
610 else if (UserHasThinFrameStyle(Style, ExStyle))
611 {
612 InflateRect(&WindowRect, -GetSystemMetrics(SM_CXBORDER),
613 -GetSystemMetrics(SM_CYBORDER));
614 }
615 if (!PtInRect(&WindowRect, Point))
616 {
617 return(HTBORDER);
618 }
619 }
620
621 if ((Style & WS_CAPTION) == WS_CAPTION)
622 {
623 WindowRect.top += (GetSystemMetrics(SM_CYCAPTION) -
624 GetSystemMetrics(SM_CYBORDER));
625 if (!PtInRect(&WindowRect, Point))
626 {
627 if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW))
628 {
629 WindowRect.left += GetSystemMetrics(SM_CXSIZE);
630 WindowRect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
631 }
632 if (Point.x <= WindowRect.left)
633 {
634 return(HTSYSMENU);
635 }
636 if (WindowRect.right <= Point.x)
637 {
638 return(HTCLOSE);
639 }
640
641 if (Style & WS_MAXIMIZEBOX || Style & WS_MINIMIZEBOX)
642 {
643 WindowRect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
644 }
645 if (Point.x >= WindowRect.right)
646 {
647 return(HTMAXBUTTON);
648 }
649
650 if (Style & WS_MINIMIZEBOX)
651 {
652 WindowRect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
653 }
654 if (Point.x >= WindowRect.right)
655 {
656 return(HTMINBUTTON);
657 }
658 return(HTCAPTION);
659 }
660 }
661
662 ScreenToClient(hWnd, &Point);
663 GetClientRect(hWnd, &WindowRect);
664
665 if (PtInRect(&WindowRect, Point))
666 {
667 return(HTCLIENT);
668 }
669
670 if (Style & WS_VSCROLL)
671 {
672 WindowRect.right += GetSystemMetrics(SM_CXVSCROLL);
673 if (PtInRect(&WindowRect, Point))
674 {
675 return(HTVSCROLL);
676 }
677 }
678
679 if (Style & WS_HSCROLL)
680 {
681 WindowRect.bottom += GetSystemMetrics(SM_CYHSCROLL);
682 if (PtInRect(&WindowRect, Point))
683 {
684 if ((Style & WS_VSCROLL) &&
685 (Point.x >= (WindowRect.right - GetSystemMetrics(SM_CXVSCROLL))))
686 {
687 return(HTSIZE);
688 }
689 return(HTHSCROLL);
690 }
691 }
692
693 if (UserHasMenu(hWnd, Style))
694 {
695 if (Point.y < 0 && Point.x >= 0 && Point.x <= WindowRect.right)
696 {
697 return(HTMENU);
698 }
699 }
700
701 return(HTNOWHERE);
702 }
703
704 LRESULT
705 DefWndHandleLButtonDownNC(HWND hWnd, WPARAM wParam, LPARAM lParam)
706 {
707 switch (wParam)
708 {
709 case HTCAPTION:
710 {
711 HWND hTopWnd = GetAncestor(hWnd, GA_ROOT);
712 if (SetActiveWindow(hTopWnd) || GetActiveWindow() == hTopWnd)
713 {
714 SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam);
715 }
716 break;
717 }
718 case HTSYSMENU:
719 {
720 if (GetWindowLong(hWnd, GWL_STYLE) & WS_SYSMENU)
721 {
722 if (!(GetWindowLong(hWnd, GWL_STYLE) & WS_MINIMIZE))
723 {
724 HDC hDC = GetWindowDC(hWnd);
725 UserDrawSysMenuButton(hWnd, hDC, TRUE);
726 ReleaseDC(hWnd, hDC);
727 }
728 SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU,
729 lParam);
730 }
731 break;
732 }
733 case HTMENU:
734 {
735 SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam);
736 break;
737 }
738 case HTHSCROLL:
739 {
740 SendMessageA(hWnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam);
741 break;
742 }
743 case HTVSCROLL:
744 {
745 SendMessageA(hWnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam);
746 break;
747 }
748 case HTMINBUTTON:
749 {
750 UserDrawCaptionButton( hWnd, GetWindowDC(hWnd), IsMinBoxActive(hWnd), DFCS_CAPTIONMIN);
751 break;
752 }
753 case HTMAXBUTTON:
754 {
755 UserDrawCaptionButton( hWnd, GetWindowDC(hWnd), IsMaxBoxActive(hWnd), DFCS_CAPTIONMAX);
756 break;
757 }
758 case HTCLOSE:
759 {
760 UserDrawCaptionButton( hWnd, GetWindowDC(hWnd), TRUE, DFCS_CAPTIONCLOSE);
761 break;
762 }
763 case HTLEFT:
764 case HTRIGHT:
765 case HTTOP:
766 case HTBOTTOM:
767 case HTTOPLEFT:
768 case HTTOPRIGHT:
769 case HTBOTTOMLEFT:
770 case HTBOTTOMRIGHT:
771 {
772 SendMessageA(hWnd, WM_SYSCOMMAND, SC_SIZE + wParam - 2, lParam);
773 break;
774 }
775 }
776 return(0);
777 }
778
779
780 LRESULT
781 DefWndHandleLButtonDblClkNC(HWND hWnd, WPARAM wParam, LPARAM lParam)
782 {
783 UNIMPLEMENTED;
784 return(0);
785 }
786
787
788 LRESULT
789 DefWndHandleLButtonUpNC(HWND hWnd, WPARAM wParam, LPARAM lParam)
790 {
791 UserDrawCaptionButton( hWnd, GetWindowDC(hWnd), FALSE, DFCS_CAPTIONMIN);
792 UserDrawCaptionButton( hWnd, GetWindowDC(hWnd), FALSE, DFCS_CAPTIONMAX);
793 UserDrawCaptionButton( hWnd, GetWindowDC(hWnd), FALSE, DFCS_CAPTIONCLOSE);
794 switch (wParam)
795 {
796 case HTMINBUTTON:
797 {
798 SendMessageA(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
799 break;
800 }
801 case HTMAXBUTTON:
802 {
803 SendMessageA(hWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
804 break;
805 }
806 case HTCLOSE:
807 {
808 SendMessageA(hWnd, WM_SYSCOMMAND, SC_CLOSE, 0);
809 break;
810 }
811 }
812 return(0);
813 }
814
815
816 LRESULT
817 DefWndHandleActiveNC(HWND hWnd, WPARAM wParam)
818 {
819 UNIMPLEMENTED;
820 return(0);
821 }
822
823
824 VOID
825 DefWndSetRedraw(HWND hWnd, WPARAM wParam)
826 {
827 UNIMPLEMENTED;
828 }
829
830
831 LRESULT
832 DefWndHandleSetCursor(HWND hWnd, WPARAM wParam, LPARAM lParam)
833 {
834 /* Not for child windows. */
835 if (hWnd != (HWND)wParam)
836 {
837 return(0);
838 }
839
840 switch(LOWORD(lParam))
841 {
842 case HTERROR:
843 {
844 WORD Msg = HIWORD(lParam);
845 if (Msg == WM_LBUTTONDOWN || Msg == WM_MBUTTONDOWN ||
846 Msg == WM_RBUTTONDOWN)
847 {
848 MessageBeep(0);
849 }
850 break;
851 }
852
853 case HTCLIENT:
854 {
855 HICON hCursor = (HICON)GetClassLong(hWnd, GCL_HCURSOR);
856 if (hCursor)
857 {
858 SetCursor(hCursor);
859 return(TRUE);
860 }
861 return(FALSE);
862 }
863
864 case HTLEFT:
865 case HTRIGHT:
866 {
867 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZEWE)));
868 }
869
870 case HTTOP:
871 case HTBOTTOM:
872 {
873 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENS)));
874 }
875
876 case HTTOPLEFT:
877 case HTBOTTOMRIGHT:
878 {
879 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENWSE)));
880 }
881
882 case HTBOTTOMLEFT:
883 case HTTOPRIGHT:
884 {
885 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENESW)));
886 }
887 }
888 return((LRESULT)SetCursor(LoadCursorW(0, IDC_ARROW)));
889 }
890
891 static LONG
892 DefWndStartSizeMove(HWND hWnd, WPARAM wParam, POINT *capturePoint)
893 {
894 LONG hittest = 0;
895 POINT pt;
896 MSG msg;
897 RECT rectWindow;
898 ULONG Style = GetWindowLong(hWnd, GWL_STYLE);
899
900 GetWindowRect(hWnd, &rectWindow);
901
902 if ((wParam & 0xfff0) == SC_MOVE)
903 {
904 /* Move pointer at the center of the caption */
905 RECT rect;
906 UserGetInsideRectNC(hWnd, &rect);
907 if (Style & WS_SYSMENU)
908 rect.left += GetSystemMetrics(SM_CXSIZE) + 1;
909 if (Style & WS_MINIMIZEBOX)
910 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
911 if (Style & WS_MAXIMIZEBOX)
912 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
913 pt.x = rectWindow.left + (rect.right - rect.left) / 2;
914 pt.y = rectWindow.top + rect.top + GetSystemMetrics(SM_CYSIZE)/2;
915 hittest = HTCAPTION;
916 *capturePoint = pt;
917 }
918 else /* SC_SIZE */
919 {
920 while(!hittest)
921 {
922 GetMessage(&msg, NULL, 0, 0);
923 switch(msg.message)
924 {
925 case WM_MOUSEMOVE:
926 hittest = DefWndHitTestNC(hWnd, msg.pt);
927 if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT))
928 hittest = 0;
929 break;
930
931 case WM_LBUTTONUP:
932 return 0;
933
934 case WM_KEYDOWN:
935 switch(msg.wParam)
936 {
937 case VK_UP:
938 hittest = HTTOP;
939 pt.x =(rectWindow.left+rectWindow.right)/2;
940 pt.y = rectWindow.top + GetSystemMetrics(SM_CYFRAME) / 2;
941 break;
942 case VK_DOWN:
943 hittest = HTBOTTOM;
944 pt.x =(rectWindow.left+rectWindow.right)/2;
945 pt.y = rectWindow.bottom - GetSystemMetrics(SM_CYFRAME) / 2;
946 break;
947 case VK_LEFT:
948 hittest = HTLEFT;
949 pt.x = rectWindow.left + GetSystemMetrics(SM_CXFRAME) / 2;
950 pt.y =(rectWindow.top+rectWindow.bottom)/2;
951 break;
952 case VK_RIGHT:
953 hittest = HTRIGHT;
954 pt.x = rectWindow.right - GetSystemMetrics(SM_CXFRAME) / 2;
955 pt.y =(rectWindow.top+rectWindow.bottom)/2;
956 break;
957 case VK_RETURN:
958 case VK_ESCAPE: return 0;
959 }
960 }
961 }
962 *capturePoint = pt;
963 }
964 SetCursorPos( pt.x, pt.y );
965 DefWndHandleSetCursor(hWnd, (WPARAM)hWnd, MAKELONG(hittest, WM_MOUSEMOVE));
966 return hittest;
967 }
968
969 #define ON_LEFT_BORDER(hit) \
970 (((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
971 #define ON_RIGHT_BORDER(hit) \
972 (((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
973 #define ON_TOP_BORDER(hit) \
974 (((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
975 #define ON_BOTTOM_BORDER(hit) \
976 (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
977
978 VOID STATIC
979 UserDrawWindowFrame(HDC hdc, const RECT *rect,
980 ULONG width, ULONG height, DWORD rop )
981 {
982 HBRUSH hbrush = SelectObject( hdc, GetStockObject( GRAY_BRUSH ) );
983 PatBlt( hdc, rect->left, rect->top,
984 rect->right - rect->left - width, height, rop );
985 PatBlt( hdc, rect->left, rect->top + height, width,
986 rect->bottom - rect->top - height, rop );
987 PatBlt( hdc, rect->left + width, rect->bottom - 1,
988 rect->right - rect->left - width, -height, rop );
989 PatBlt( hdc, rect->right - 1, rect->top, -width,
990 rect->bottom - rect->top - height, rop );
991 SelectObject( hdc, hbrush );
992 }
993
994 VOID STATIC
995 UserDrawMovingFrame(HDC hdc, RECT *rect, BOOL thickframe)
996 {
997 if (thickframe)
998 {
999 UserDrawWindowFrame(hdc, rect, GetSystemMetrics(SM_CXFRAME),
1000 GetSystemMetrics(SM_CYFRAME), PATINVERT );
1001 }
1002 else DrawFocusRect( hdc, rect );
1003 }
1004
1005 VOID STATIC
1006 DefWndDoSizeMove(HWND hwnd, WORD wParam)
1007 {
1008 MSG msg;
1009 RECT sizingRect, mouseRect, origRect;
1010 HDC hdc;
1011 LONG hittest = (LONG)(wParam & 0x0f);
1012 HCURSOR hDragCursor = 0, hOldCursor = 0;
1013 POINT minTrack, maxTrack;
1014 POINT capturePoint, pt;
1015 ULONG Style = GetWindowLong(hwnd, GWL_STYLE);
1016 ULONG ExStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
1017 BOOL thickframe = UserHasThickFrameStyle(Style, ExStyle);
1018 BOOL iconic = Style & WS_MINIMIZE;
1019 BOOL moved = FALSE;
1020 DWORD dwPoint = GetMessagePos();
1021 BOOL DragFullWindows = FALSE;
1022 HWND hWndParent;
1023
1024 SystemParametersInfoA(SPI_GETDRAGFULLWINDOWS, 0, &DragFullWindows, 0);
1025
1026 pt.x = SLOWORD(dwPoint);
1027 pt.y = SHIWORD(dwPoint);
1028 capturePoint = pt;
1029
1030 if (IsZoomed(hwnd) || !IsWindowVisible(hwnd))
1031 {
1032 return;
1033 }
1034
1035 if ((wParam & 0xfff0) == SC_MOVE)
1036 {
1037 if (!hittest)
1038 {
1039 hittest = DefWndStartSizeMove(hwnd, wParam, &capturePoint);
1040 }
1041 if (!hittest)
1042 {
1043 return;
1044 }
1045 }
1046 else /* SC_SIZE */
1047 {
1048 if (!thickframe)
1049 {
1050 return;
1051 }
1052 if (hittest && hittest != HTSYSMENU)
1053 {
1054 hittest += 2;
1055 }
1056 else
1057 {
1058 SetCapture(hwnd);
1059 hittest = DefWndStartSizeMove(hwnd, wParam, &capturePoint);
1060 if (!hittest)
1061 {
1062 ReleaseCapture();
1063 return;
1064 }
1065 }
1066 }
1067
1068 if (Style & WS_CHILD)
1069 {
1070 hWndParent = GetParent(hwnd);
1071 }
1072
1073 /* Get min/max info */
1074
1075 WinPosGetMinMaxInfo(hwnd, NULL, NULL, &minTrack, &maxTrack);
1076 GetWindowRect(hwnd, &sizingRect);
1077 origRect = sizingRect;
1078 if (Style & WS_CHILD)
1079 {
1080 GetClientRect(hWndParent, &mouseRect );
1081 }
1082 else
1083 {
1084 SetRect(&mouseRect, 0, 0, GetSystemMetrics(SM_CXSCREEN),
1085 GetSystemMetrics(SM_CYSCREEN));
1086 }
1087 if (ON_LEFT_BORDER(hittest))
1088 {
1089 mouseRect.left = max( mouseRect.left, sizingRect.right-maxTrack.x );
1090 mouseRect.right = min( mouseRect.right, sizingRect.right-minTrack.x );
1091 }
1092 else if (ON_RIGHT_BORDER(hittest))
1093 {
1094 mouseRect.left = max( mouseRect.left, sizingRect.left+minTrack.x );
1095 mouseRect.right = min( mouseRect.right, sizingRect.left+maxTrack.x );
1096 }
1097 if (ON_TOP_BORDER(hittest))
1098 {
1099 mouseRect.top = max( mouseRect.top, sizingRect.bottom-maxTrack.y );
1100 mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minTrack.y);
1101 }
1102 else if (ON_BOTTOM_BORDER(hittest))
1103 {
1104 mouseRect.top = max( mouseRect.top, sizingRect.top+minTrack.y );
1105 mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+maxTrack.y );
1106 }
1107 if (Style & WS_CHILD)
1108 {
1109 MapWindowPoints( hWndParent, 0, (LPPOINT)&mouseRect, 2 );
1110 }
1111 SendMessageA( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
1112
1113 if (GetCapture() != hwnd) SetCapture( hwnd );
1114
1115 if (Style & WS_CHILD)
1116 {
1117 /* Retrieve a default cache DC (without using the window style) */
1118 hdc = GetDCEx(hWndParent, 0, DCX_CACHE);
1119 }
1120 else
1121 {
1122 hdc = GetDC( 0 );
1123 }
1124
1125 if( iconic ) /* create a cursor for dragging */
1126 {
1127 HICON hIcon = (HICON)GetClassLong(hwnd, GCL_HICON);
1128 if(!hIcon) hIcon = (HICON)SendMessage( hwnd, WM_QUERYDRAGICON, 0, 0L);
1129 if( hIcon ) hDragCursor = CursorIconToCursor( hIcon, TRUE );
1130 if( !hDragCursor ) iconic = FALSE;
1131 }
1132
1133 /* invert frame if WIN31_LOOK to indicate mouse click on caption */
1134 if( !iconic && !DragFullWindows)
1135 {
1136 UserDrawMovingFrame( hdc, &sizingRect, thickframe );
1137 }
1138
1139 while(1)
1140 {
1141 int dx = 0, dy = 0;
1142
1143 GetMessage(&msg, 0, 0, 0);
1144
1145 /* Exit on button-up, Return, or Esc */
1146 if ((msg.message == WM_LBUTTONUP) ||
1147 ((msg.message == WM_KEYDOWN) &&
1148 ((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
1149
1150 if (msg.message == WM_PAINT)
1151 {
1152 if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
1153 UpdateWindow( msg.hwnd );
1154 if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
1155 continue;
1156 }
1157
1158 if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
1159 continue; /* We are not interested in other messages */
1160
1161 pt = msg.pt;
1162
1163 if (msg.message == WM_KEYDOWN) switch(msg.wParam)
1164 {
1165 case VK_UP: pt.y -= 8; break;
1166 case VK_DOWN: pt.y += 8; break;
1167 case VK_LEFT: pt.x -= 8; break;
1168 case VK_RIGHT: pt.x += 8; break;
1169 }
1170
1171 pt.x = max( pt.x, mouseRect.left );
1172 pt.x = min( pt.x, mouseRect.right );
1173 pt.y = max( pt.y, mouseRect.top );
1174 pt.y = min( pt.y, mouseRect.bottom );
1175
1176 dx = pt.x - capturePoint.x;
1177 dy = pt.y - capturePoint.y;
1178
1179 if (dx || dy)
1180 {
1181 if( !moved )
1182 {
1183 moved = TRUE;
1184
1185 if( iconic ) /* ok, no system popup tracking */
1186 {
1187 hOldCursor = SetCursor(hDragCursor);
1188 ShowCursor( TRUE );
1189 WinPosShowIconTitle( hwnd, FALSE );
1190 }
1191 }
1192
1193 if (msg.message == WM_KEYDOWN) SetCursorPos( pt.x, pt.y );
1194 else
1195 {
1196 RECT newRect = sizingRect;
1197 WPARAM wpSizingHit = 0;
1198
1199 if (hittest == HTCAPTION) OffsetRect( &newRect, dx, dy );
1200 if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
1201 else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
1202 if (ON_TOP_BORDER(hittest)) newRect.top += dy;
1203 else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
1204 if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
1205 capturePoint = pt;
1206
1207 /* determine the hit location */
1208 if (hittest >= HTLEFT && hittest <= HTBOTTOMRIGHT)
1209 wpSizingHit = WMSZ_LEFT + (hittest - HTLEFT);
1210 SendMessageA( hwnd, WM_SIZING, wpSizingHit, (LPARAM)&newRect );
1211
1212 if (!iconic)
1213 {
1214 if(!DragFullWindows)
1215 UserDrawMovingFrame( hdc, &newRect, thickframe );
1216 else {
1217 /* To avoid any deadlocks, all the locks on the windows
1218 structures must be suspended before the SetWindowPos */
1219 SetWindowPos( hwnd, 0, newRect.left, newRect.top,
1220 newRect.right - newRect.left,
1221 newRect.bottom - newRect.top,
1222 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
1223 }
1224 }
1225 sizingRect = newRect;
1226 }
1227 }
1228 }
1229
1230 ReleaseCapture();
1231 if( iconic )
1232 {
1233 if( moved ) /* restore cursors, show icon title later on */
1234 {
1235 ShowCursor( FALSE );
1236 SetCursor( hOldCursor );
1237 }
1238 DestroyCursor( hDragCursor );
1239 }
1240 else if(!DragFullWindows)
1241 UserDrawMovingFrame( hdc, &sizingRect, thickframe );
1242
1243 if (Style & WS_CHILD)
1244 ReleaseDC( hWndParent, hdc );
1245 else
1246 ReleaseDC( 0, hdc );
1247
1248 SendMessageA( hwnd, WM_EXITSIZEMOVE, 0, 0 );
1249 SendMessageA( hwnd, WM_SETVISIBLE, !IsIconic(hwnd), 0L);
1250
1251 /* window moved or resized */
1252 if (moved)
1253 {
1254 /* if the moving/resizing isn't canceled call SetWindowPos
1255 * with the new position or the new size of the window
1256 */
1257 if (!((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) )
1258 {
1259 /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
1260 if(!DragFullWindows)
1261 SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
1262 sizingRect.right - sizingRect.left,
1263 sizingRect.bottom - sizingRect.top,
1264 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
1265 }
1266 else { /* restore previous size/position */
1267 if(DragFullWindows)
1268 SetWindowPos( hwnd, 0, origRect.left, origRect.top,
1269 origRect.right - origRect.left,
1270 origRect.bottom - origRect.top,
1271 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
1272 }
1273 }
1274
1275 if( IsWindow(hwnd) )
1276 if( Style & WS_MINIMIZE )
1277 {
1278 /* Single click brings up the system menu when iconized */
1279
1280 if( !moved )
1281 {
1282 if( Style & WS_SYSMENU )
1283 SendMessageA( hwnd, WM_SYSCOMMAND,
1284 SC_MOUSEMENU + HTSYSMENU, MAKELONG(pt.x,pt.y));
1285 }
1286 else WinPosShowIconTitle( hwnd, TRUE );
1287 }
1288 }
1289
1290
1291 LRESULT
1292 DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, POINT Pt)
1293 {
1294 switch (wParam & 0xfff0)
1295 {
1296 case SC_MOVE:
1297 case SC_SIZE:
1298 DefWndDoSizeMove(hWnd, wParam);
1299 break;
1300 case SC_CLOSE:
1301 SendMessageA(hWnd, WM_CLOSE, 0, 0);
1302 break;
1303 case SC_MOUSEMENU:
1304 MenuTrackMouseMenuBar(hWnd, wParam, Pt);
1305 break;
1306 case SC_KEYMENU:
1307 MenuTrackKbdMenuBar(hWnd, wParam, Pt.x);
1308 break;
1309 default:
1310 /* FIXME: Implement */
1311 UNIMPLEMENTED;
1312 break;
1313 }
1314
1315 return(0);
1316 }
1317
1318
1319 VOID
1320 DefWndAdjustRect(RECT* Rect, ULONG Style, BOOL Menu, ULONG ExStyle)
1321 {
1322 if (Style & WS_ICONIC)
1323 {
1324 return;
1325 }
1326
1327 if (UserHasThickFrameStyle(Style, ExStyle))
1328 {
1329 InflateRect(Rect, GetSystemMetrics(SM_CXFRAME),
1330 GetSystemMetrics(SM_CYFRAME));
1331 }
1332 else if (UserHasDlgFrameStyle(Style, ExStyle))
1333 {
1334 InflateRect(Rect, GetSystemMetrics(SM_CXDLGFRAME),
1335 GetSystemMetrics(SM_CYDLGFRAME));
1336 }
1337 else if (UserHasThinFrameStyle(Style, ExStyle))
1338 {
1339 InflateRect(Rect, GetSystemMetrics(SM_CXBORDER),
1340 GetSystemMetrics(SM_CYBORDER));
1341 }
1342 if (Style & WS_CAPTION)
1343 {
1344 Rect->top -= (GetSystemMetrics(SM_CYCAPTION) -
1345 GetSystemMetrics(SM_CYBORDER)) + 1;
1346 }
1347 if (Menu)
1348 {
1349 Rect->top -= GetSystemMetrics(SM_CYMENU) + GetSystemMetrics(SM_CYBORDER);
1350 }
1351 if (Style & WS_VSCROLL)
1352 {
1353 Rect->right += GetSystemMetrics(SM_CXVSCROLL) - 1;
1354 if (UserHasAnyFrameStyle(Style, ExStyle))
1355 {
1356 Rect->right++;
1357 }
1358 }
1359 if (Style & WS_HSCROLL)
1360 {
1361 Rect->bottom += GetSystemMetrics(SM_CYHSCROLL) - 1;
1362 if (UserHasAnyFrameStyle(Style, ExStyle))
1363 {
1364 Rect->bottom++;
1365 }
1366 }
1367 }
1368
1369
1370 LRESULT STDCALL
1371 DefWndNCCalcSize(HWND hWnd, RECT* Rect)
1372 {
1373 LRESULT Result = 0;
1374 LONG Style = GetClassLongW(hWnd, GCL_STYLE);
1375 RECT TmpRect = {0, 0, 0, 0};
1376
1377 if (Style & CS_VREDRAW)
1378 {
1379 Result |= WVR_VREDRAW;
1380 }
1381 if (Style & CS_HREDRAW)
1382 {
1383 Result |= WVR_HREDRAW;
1384 }
1385
1386 if (!(GetWindowLong(hWnd, GWL_STYLE) & WS_MINIMIZE))
1387 {
1388 DefWndAdjustRect(&TmpRect, GetWindowLong(hWnd, GWL_STYLE),
1389 FALSE, GetWindowLong(hWnd, GWL_EXSTYLE));
1390 Rect->left -= TmpRect.left;
1391 Rect->top -= TmpRect.top;
1392 Rect->right -= TmpRect.right;
1393 Rect->bottom -= TmpRect.bottom;
1394 if (UserHasMenu(hWnd, GetWindowLong(hWnd, GWL_EXSTYLE)))
1395 {
1396 Rect->top += MenuGetMenuBarHeight(hWnd,
1397 Rect->right - Rect->left,
1398 -TmpRect.left,
1399 -TmpRect.top) + 1;
1400 }
1401 Rect->bottom = max(Rect->top, Rect->bottom);
1402 Rect->right = max(Rect->left, Rect->right);
1403 }
1404 return(Result);
1405 }
1406
1407
1408 LRESULT
1409 DefWndHandleWindowPosChanging(HWND hWnd, WINDOWPOS* Pos)
1410 {
1411 UNIMPLEMENTED;
1412 return 0;
1413 }
1414
1415
1416 LRESULT STDCALL
1417 User32DefWindowProc(HWND hWnd,
1418 UINT Msg,
1419 WPARAM wParam,
1420 LPARAM lParam,
1421 BOOL bUnicode)
1422 {
1423 switch (Msg)
1424 {
1425 case WM_NCPAINT:
1426 {
1427 return(DefWndPaintNC(hWnd, (HRGN)wParam));
1428 }
1429 case WM_WINDOWPOSCHANGING:
1430 {
1431 DbgPrint("WM_WINDOWPOSCHANGING\n\n");
1432 break;
1433 }
1434 case WM_NCHITTEST:
1435 {
1436 POINT Point;
1437 Point.x = SLOWORD(lParam);
1438 Point.y = SHIWORD(lParam);
1439 return(DefWndHitTestNC(hWnd, Point));
1440 }
1441
1442 case WM_NCLBUTTONDOWN:
1443 {
1444 return(DefWndHandleLButtonDownNC(hWnd, wParam, lParam));
1445 }
1446
1447 case WM_NCLBUTTONUP:
1448 {
1449 return(DefWndHandleLButtonUpNC(hWnd, wParam, lParam));
1450 }
1451
1452 case WM_LBUTTONDBLCLK:
1453 case WM_NCLBUTTONDBLCLK:
1454 {
1455 return(DefWndHandleLButtonDblClkNC(hWnd, wParam, lParam));
1456 }
1457
1458 case WM_NCRBUTTONDOWN:
1459 {
1460 if (wParam == HTCAPTION)
1461 {
1462 SetCapture(hWnd);
1463 }
1464 break;
1465 }
1466 case WM_LBUTTONUP:
1467 {
1468 break;
1469 }
1470 case WM_RBUTTONUP:
1471 {
1472 POINT Pt;
1473 if (hWnd == GetCapture())
1474 {
1475 ReleaseCapture();
1476 }
1477 Pt.x = SLOWORD(lParam);
1478 Pt.y = SHIWORD(lParam);
1479 ClientToScreen(hWnd, &Pt);
1480 lParam = MAKELPARAM(Pt.x, Pt.y);
1481 if (bUnicode)
1482 {
1483 SendMessageW(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
1484 }
1485 else
1486 {
1487 SendMessageA (hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
1488 }
1489 break;
1490 }
1491
1492 case WM_NCRBUTTONUP:
1493 {
1494 /* Wine does nothing here. */
1495 break;
1496 }
1497
1498 case WM_CONTEXTMENU:
1499 {
1500 if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)
1501 {
1502 if (bUnicode)
1503 {
1504 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1505 }
1506 else
1507 {
1508 SendMessageA(hWnd, WM_CONTEXTMENU, wParam, lParam);
1509 }
1510 }
1511 else
1512 {
1513 LONG HitCode;
1514 POINT Pt;
1515
1516 Pt.x = SLOWORD(lParam);
1517 Pt.y = SHIWORD(lParam);
1518
1519 if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)
1520 {
1521 ScreenToClient(GetParent(hWnd), &Pt);
1522 }
1523
1524 HitCode = DefWndHitTestNC(hWnd, Pt);
1525
1526 if (HitCode == HTCAPTION || HitCode == HTSYSMENU)
1527 {
1528 TrackPopupMenu(GetSystemMenu(hWnd, FALSE),
1529 TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
1530 Pt.x, Pt.y, 0, hWnd, NULL);
1531 }
1532 }
1533 break;
1534 }
1535
1536 case WM_NCACTIVATE:
1537 {
1538 return(DefWndHandleActiveNC(hWnd, wParam));
1539 }
1540
1541 case WM_NCDESTROY:
1542 {
1543 return(0);
1544 }
1545
1546 case WM_PRINT:
1547 {
1548 return(0);
1549 }
1550
1551 case WM_PAINTICON:
1552 case WM_PAINT:
1553 {
1554 PAINTSTRUCT Ps;
1555 HDC hDC = BeginPaint(hWnd, &Ps);
1556 if (hDC)
1557 {
1558 HICON hIcon;
1559 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE &&
1560 (hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON)) != NULL)
1561 {
1562 RECT WindowRect;
1563 INT x, y;
1564 GetWindowRect(hWnd, &WindowRect);
1565 x = (WindowRect.right - WindowRect.left -
1566 GetSystemMetrics(SM_CXICON)) / 2;
1567 y = (WindowRect.bottom - WindowRect.top -
1568 GetSystemMetrics(SM_CYICON)) / 2;
1569 DrawIcon(hDC, x, y, hIcon);
1570 }
1571 if (GetWindowLong(hWnd, GWL_EXSTYLE) & WS_EX_CLIENTEDGE)
1572 {
1573 RECT WindowRect;
1574 GetClientRect(hWnd, &WindowRect);
1575 DrawEdge(hDC, &WindowRect, EDGE_SUNKEN, BF_RECT);
1576 }
1577 EndPaint(hWnd, &Ps);
1578 }
1579 return(0);
1580 }
1581
1582 case WM_SYNCPAINT:
1583 {
1584 HRGN hRgn;
1585 hRgn = CreateRectRgn(0, 0, 0, 0);
1586 if (GetUpdateRgn(hWnd, hRgn, FALSE) != NULLREGION)
1587 {
1588 RedrawWindow(hWnd, NULL, hRgn,
1589 RDW_ERASENOW | RDW_ERASE | RDW_FRAME |
1590 RDW_ALLCHILDREN);
1591 }
1592 DeleteObject(hRgn);
1593 return(0);
1594 }
1595
1596 case WM_SETREDRAW:
1597 {
1598 DefWndSetRedraw(hWnd, wParam);
1599 return(0);
1600 }
1601
1602 case WM_CLOSE:
1603 {
1604 DestroyWindow(hWnd);
1605 return(0);
1606 }
1607
1608 case WM_MOUSEACTIVATE:
1609 {
1610 if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)
1611 {
1612 LONG Ret;
1613 if (bUnicode)
1614 {
1615 Ret = SendMessageW(GetParent(hWnd), WM_MOUSEACTIVATE,
1616 wParam, lParam);
1617 }
1618 else
1619 {
1620 Ret = SendMessageA(GetParent(hWnd), WM_MOUSEACTIVATE,
1621 wParam, lParam);
1622 }
1623 if (Ret)
1624 {
1625 return(Ret);
1626 }
1627 }
1628 return((LOWORD(lParam) >= HTCLIENT) ? MA_ACTIVATE : MA_NOACTIVATE);
1629 }
1630
1631 case WM_ACTIVATE:
1632 {
1633 /* Check if the window is minimized. */
1634 if (LOWORD(lParam) != WA_INACTIVE &&
1635 !(GetWindowLong(hWnd, GWL_STYLE) & WS_MINIMIZE))
1636 {
1637 SetFocus(hWnd);
1638 }
1639 break;
1640 }
1641
1642 case WM_MOUSEWHEEL:
1643 {
1644 if (GetWindowLong(hWnd, GWL_STYLE & WS_CHILD))
1645 {
1646 if (bUnicode)
1647 {
1648 return(SendMessageW(GetParent(hWnd), WM_MOUSEWHEEL,
1649 wParam, lParam));
1650 }
1651 else
1652 {
1653 return(SendMessageA(GetParent(hWnd), WM_MOUSEWHEEL,
1654 wParam, lParam));
1655 }
1656 }
1657 break;
1658 }
1659
1660 case WM_ERASEBKGND:
1661 case WM_ICONERASEBKGND:
1662 {
1663
1664 RECT Rect;
1665 HBRUSH hBrush = (HBRUSH)GetClassLongW(hWnd, GCL_HBRBACKGROUND);
1666 GetClipBox((HDC)wParam, &Rect);
1667 FillRect((HDC)wParam, &Rect, hBrush);
1668 return(1);
1669 }
1670
1671 case WM_GETDLGCODE:
1672 {
1673 return(0);
1674 }
1675
1676 /* FIXME: Implement colour controls. */
1677
1678 case WM_SETCURSOR:
1679 {
1680 if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)
1681 {
1682 if (LOWORD(lParam) < HTLEFT || LOWORD(lParam) > HTBOTTOMRIGHT)
1683 {
1684 BOOL bResult;
1685 if (bUnicode)
1686 {
1687 bResult = SendMessageW(GetParent(hWnd), WM_SETCURSOR,
1688 wParam, lParam);
1689 }
1690 else
1691 {
1692 bResult = SendMessageA(GetParent(hWnd), WM_SETCURSOR,
1693 wParam, lParam);
1694 }
1695 if (bResult)
1696 {
1697 return(TRUE);
1698 }
1699 }
1700 }
1701 return(DefWndHandleSetCursor(hWnd, wParam, lParam));
1702 }
1703
1704 case WM_SYSCOMMAND:
1705 {
1706 POINT Pt;
1707 Pt.x = SLOWORD(lParam);
1708 Pt.y = SHIWORD(lParam);
1709 return(DefWndHandleSysCommand(hWnd, wParam, Pt));
1710 }
1711
1712 /* FIXME: Handle key messages. */
1713
1714 case WM_SHOWWINDOW:
1715 {
1716 if (lParam)
1717 {
1718 return(0);
1719 }
1720 /* FIXME: Not done correctly */
1721 if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_VISIBLE && !wParam) ||
1722 (!(GetWindowLongW(hWnd, GWL_STYLE) & WS_VISIBLE) && wParam))
1723 {
1724 return(0);
1725 }
1726 ShowWindow(hWnd, wParam ? SW_SHOWNA : SW_HIDE);
1727 break;
1728 }
1729
1730 case WM_CANCELMODE:
1731 {
1732 /* FIXME: Check for a desktop. */
1733 if (GetCapture() == hWnd)
1734 {
1735 ReleaseCapture();
1736 }
1737 break;
1738 }
1739
1740 case WM_VKEYTOITEM:
1741 case WM_CHARTOITEM:
1742 return(-1);
1743
1744 case WM_DROPOBJECT:
1745 /* FIXME: Implement this. */
1746 break;
1747
1748 case WM_QUERYDROPOBJECT:
1749 {
1750 if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES)
1751 {
1752 return(1);
1753 }
1754 break;
1755 }
1756
1757 case WM_QUERYDRAGICON:
1758 {
1759 UINT Len;
1760 HICON hIcon;
1761
1762 hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON);
1763 if (hIcon)
1764 {
1765 return((LRESULT)hIcon);
1766 }
1767 for (Len = 1; Len < 64; Len++)
1768 {
1769 if ((hIcon = LoadIconW(NULL, MAKEINTRESOURCE(Len))) != NULL)
1770 {
1771 return((LRESULT)hIcon);
1772 }
1773 }
1774 return((LRESULT)LoadIconW(0, IDI_APPLICATION));
1775 }
1776
1777 /* FIXME: WM_ISACTIVEICON */
1778
1779 case WM_NOTIFYFORMAT:
1780 {
1781 if (IsWindowUnicode(hWnd))
1782 {
1783 return(NFR_UNICODE);
1784 }
1785 else
1786 {
1787 return(NFR_ANSI);
1788 }
1789 }
1790
1791 case WM_SETICON:
1792 {
1793 INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
1794 HICON hOldIcon = (HICON)GetClassLongW(hWnd, Index);
1795 SetClassLongW(hWnd, Index, lParam);
1796 SetWindowPos(hWnd, 0, 0, 0, 0, 0,
1797 SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
1798 SWP_NOACTIVATE | SWP_NOZORDER);
1799 return((LRESULT)hOldIcon);
1800 }
1801
1802 case WM_GETICON:
1803 {
1804 INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
1805 return(GetClassLongW(hWnd, Index));
1806 }
1807
1808 case WM_HELP:
1809 {
1810 if (bUnicode)
1811 {
1812 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1813 }
1814 else
1815 {
1816 SendMessageA(GetParent(hWnd), Msg, wParam, lParam);
1817 }
1818 break;
1819 }
1820
1821 case WM_SYSKEYDOWN:
1822 if (HIWORD(lParam) & KEYDATA_ALT)
1823 {
1824 if (wParam == VK_F4) /* Try to close the window */
1825 {
1826 //HWND hTopWnd = GetAncestor(hWnd, GA_ROOT);
1827 HWND hTopWnd = hWnd;
1828 if (!(GetClassLongW(hTopWnd, GCL_STYLE) & CS_NOCLOSE))
1829 {
1830 if (bUnicode)
1831 {
1832 PostMessageW(hTopWnd, WM_SYSCOMMAND, SC_CLOSE, 0);
1833 }
1834 else
1835 {
1836 PostMessageA(hTopWnd, WM_SYSCOMMAND, SC_CLOSE, 0);
1837 }
1838 }
1839 }
1840 }
1841 break;
1842 }
1843 return 0;
1844 }
1845
1846
1847 LRESULT STDCALL
1848 DefWindowProcA(HWND hWnd,
1849 UINT Msg,
1850 WPARAM wParam,
1851 LPARAM lParam)
1852 {
1853 LRESULT Result;
1854 static LPSTR WindowTextAtom = 0;
1855 PSTR WindowText;
1856
1857 switch (Msg)
1858 {
1859 case WM_NCCREATE:
1860 {
1861 CREATESTRUCTA* Cs = (CREATESTRUCTA*)lParam;
1862 if (HIWORD(Cs->lpszName))
1863 {
1864 if (0 == WindowTextAtom)
1865 {
1866 WindowTextAtom =
1867 (LPSTR)(ULONG)GlobalAddAtomA("USER32!WindowTextAtomA");
1868 }
1869 WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
1870 strlen(Cs->lpszName) * sizeof(CHAR));
1871 strcpy(WindowText, Cs->lpszName);
1872 SetPropA(hWnd, WindowTextAtom, WindowText);
1873 }
1874 return(1);
1875 }
1876
1877 case WM_NCCALCSIZE:
1878 {
1879 return(DefWndNCCalcSize(hWnd, (RECT*)lParam));
1880 }
1881
1882 case WM_WINDOWPOSCHANGING:
1883 {
1884 return(DefWndHandleWindowPosChanging(hWnd, (WINDOWPOS*)lParam));
1885 }
1886
1887 case WM_GETTEXTLENGTH:
1888 {
1889 if (WindowTextAtom == 0 ||
1890 (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
1891 {
1892 return(0);
1893 }
1894 return(strlen(WindowText));
1895 }
1896
1897 case WM_GETTEXT:
1898 {
1899 if (WindowTextAtom == 0 ||
1900 (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
1901 {
1902 if (wParam > 1)
1903 {
1904 *((PSTR)lParam) = '\0';
1905 }
1906 return(0);
1907 }
1908 strncpy((LPSTR)lParam, WindowText, wParam);
1909 return(min(wParam, strlen(WindowText)));
1910 }
1911
1912 case WM_SETTEXT:
1913 {
1914 if (0 == WindowTextAtom)
1915 {
1916 WindowTextAtom =
1917 (LPSTR)(DWORD)GlobalAddAtomA("USER32!WindowTextAtomW");
1918 }
1919 if (WindowTextAtom != 0 &&
1920 (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
1921 {
1922 RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
1923 }
1924 WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
1925 strlen((PSTR)lParam) * sizeof(CHAR));
1926 strcpy(WindowText, (PSTR)lParam);
1927 SetPropA(hWnd, WindowTextAtom, WindowText);
1928 if (0 != (GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION))
1929 {
1930 DefWndPaintNC(hWnd, (HRGN) 1);
1931 }
1932 Result = (LPARAM) TRUE;
1933 break;
1934 }
1935
1936 case WM_NCDESTROY:
1937 {
1938 if (WindowTextAtom != 0 &&
1939 (WindowText = RemovePropA(hWnd, WindowTextAtom)) == NULL)
1940 {
1941 RtlFreeHeap(GetProcessHeap(), 0, WindowText);
1942 }
1943 return(0);
1944 }
1945
1946 default:
1947 Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, FALSE);
1948 break;
1949 }
1950
1951 return(Result);
1952 }
1953
1954
1955 LRESULT STDCALL
1956 DefWindowProcW(HWND hWnd,
1957 UINT Msg,
1958 WPARAM wParam,
1959 LPARAM lParam)
1960 {
1961 LRESULT Result;
1962 static LPWSTR WindowTextAtom = 0;
1963 PWSTR WindowText;
1964
1965 switch (Msg)
1966 {
1967 case WM_NCCREATE:
1968 {
1969 CREATESTRUCTW* Cs = (CREATESTRUCTW*)lParam;
1970 if (HIWORD(Cs->lpszName))
1971 {
1972 if (0 == WindowTextAtom)
1973 {
1974 WindowTextAtom =
1975 (LPWSTR)(DWORD)GlobalAddAtomW(L"USER32!WindowTextAtomW");
1976 }
1977 WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
1978 wcslen(Cs->lpszName) * sizeof(WCHAR));
1979 wcscpy(WindowText, Cs->lpszName);
1980 SetPropW(hWnd, WindowTextAtom, WindowText);
1981 }
1982 return(1);
1983 }
1984
1985 case WM_NCCALCSIZE:
1986 {
1987 return(DefWndNCCalcSize(hWnd, (RECT*)lParam));
1988 }
1989
1990 case WM_WINDOWPOSCHANGING:
1991 {
1992 return(DefWndHandleWindowPosChanging(hWnd, (WINDOWPOS*)lParam));
1993 }
1994
1995 case WM_GETTEXTLENGTH:
1996 {
1997 if (WindowTextAtom == 0 ||
1998 (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
1999 {
2000 return(0);
2001 }
2002 return(wcslen(WindowText));
2003 }
2004
2005 case WM_GETTEXT:
2006 {
2007 if (WindowTextAtom == 0 ||
2008 (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
2009 {
2010 if (wParam > 1)
2011 {
2012 ((PWSTR)lParam) = '\0';
2013 }
2014 return(0);
2015 }
2016 wcsncpy((PWSTR)lParam, WindowText, wParam);
2017 return(min(wParam, wcslen(WindowText)));
2018 }
2019
2020 case WM_SETTEXT:
2021 {
2022 if (WindowTextAtom != 0)
2023 {
2024 WindowTextAtom =
2025 (LPWSTR)(DWORD)GlobalAddAtom(L"USER32!WindowTextAtomW");
2026 }
2027 if (WindowTextAtom != 0 &&
2028 (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
2029 {
2030 RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
2031 }
2032 WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
2033 wcslen((PWSTR)lParam) * sizeof(WCHAR));
2034 wcscpy(WindowText, (PWSTR)lParam);
2035 SetPropW(hWnd, WindowTextAtom, WindowText);
2036 if (0 != (GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION))
2037 {
2038 DefWndPaintNC(hWnd, (HRGN) 1);
2039 }
2040 Result = (LPARAM) TRUE;
2041 break;
2042 }
2043
2044 case WM_NCDESTROY:
2045 {
2046 if (WindowTextAtom != 0 &&
2047 (WindowText = RemovePropW(hWnd, WindowTextAtom)) == NULL)
2048 {
2049 RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
2050 }
2051 return(0);
2052 }
2053
2054 default:
2055 Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, TRUE);
2056 break;
2057 }
2058
2059 return(Result);
2060 }