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