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