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