Merge from branch ReactX to Trunk,
[reactos.git] / reactos / dll / win32 / user32 / windows / defwnd.c
1 /* $Id$
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 <user32.h>
15
16 #include <wine/debug.h>
17 WINE_DEFAULT_DEBUG_CHANNEL(user32);
18
19 #ifndef WM_SETVISIBLE
20 #define WM_SETVISIBLE 9
21 #endif
22 #ifndef WM_QUERYDROPOBJECT
23 #define WM_QUERYDROPOBJECT 0x022B
24 #endif
25
26 LRESULT DefWndNCPaint(HWND hWnd, HRGN hRgn, BOOL Active);
27 LRESULT DefWndNCCalcSize(HWND hWnd, BOOL CalcSizeStruct, RECT *Rect);
28 LRESULT DefWndNCActivate(HWND hWnd, WPARAM wParam);
29 LRESULT DefWndNCHitTest(HWND hWnd, POINT Point);
30 LRESULT DefWndNCLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam);
31 LRESULT DefWndNCLButtonDblClk(HWND hWnd, WPARAM wParam, LPARAM lParam);
32 void FASTCALL MenuInitSysMenuPopup(HMENU Menu, DWORD Style, DWORD ClsStyle, LONG HitTest );
33
34 /* GLOBALS *******************************************************************/
35
36 COLORREF SysColors[NUM_SYSCOLORS] = {0};
37 HPEN SysPens[NUM_SYSCOLORS] = {0};
38 HBRUSH SysBrushes[NUM_SYSCOLORS] = {0};
39
40 /* Bits in the dwKeyData */
41 #define KEYDATA_ALT 0x2000
42 #define KEYDATA_PREVSTATE 0x4000
43
44 static short iF10Key = 0;
45 static short iMenuSysKey = 0;
46
47 /* FUNCTIONS *****************************************************************/
48
49 void
50 InitStockObjects(void)
51 {
52 /* FIXME - Instead of copying the stuff to usermode we should map the tables to
53 userland. The current implementation has one big flaw: the system color
54 table doesn't get updated when another process changes them. That's why
55 we should rather map the table into usermode. But it only affects the
56 SysColors table - the pens, brushes and stock objects are not affected
57 as their handles never change. But it'd be faster to map them, too. */
58 if(SysBrushes[0] == NULL)
59 {
60 /* only initialize once */
61 (void)NtUserGetSysColors(SysColors, NUM_SYSCOLORS);
62 (void)NtUserGetSysColorPens(SysPens, NUM_SYSCOLORS);
63 (void)NtUserGetSysColorBrushes(SysBrushes, NUM_SYSCOLORS);
64 }
65 }
66
67 /*
68 * @implemented
69 */
70 DWORD STDCALL
71 GetSysColor(int nIndex)
72 {
73 if(nIndex >= 0 && nIndex <= NUM_SYSCOLORS)
74 {
75 return SysColors[nIndex];
76 }
77
78 SetLastError(ERROR_INVALID_PARAMETER);
79 return 0;
80 }
81
82 /*
83 * @implemented
84 */
85 HPEN STDCALL
86 GetSysColorPen(int nIndex)
87 {
88 if(nIndex >= 0 && nIndex <= NUM_SYSCOLORS)
89 {
90 return SysPens[nIndex];
91 }
92
93 SetLastError(ERROR_INVALID_PARAMETER);
94 return NULL;
95 }
96
97 /*
98 * @implemented
99 */
100 HBRUSH STDCALL
101 GetSysColorBrush(int nIndex)
102 {
103 if(nIndex >= 0 && nIndex <= NUM_SYSCOLORS)
104 {
105 return SysBrushes[nIndex];
106 }
107
108 SetLastError(ERROR_INVALID_PARAMETER);
109 return NULL;
110 }
111
112 /*
113 * @implemented
114 */
115 BOOL
116 STDCALL
117 SetSysColors(
118 int cElements,
119 CONST INT *lpaElements,
120 CONST COLORREF *lpaRgbValues)
121 {
122 BOOL Ret;
123 struct
124 {
125 INT *Elements;
126 COLORREF *Colors;
127 } ChangeSysColors;
128
129 ChangeSysColors.Elements = (INT*)lpaElements;
130 ChangeSysColors.Colors = (COLORREF*)lpaRgbValues;
131
132 if(cElements > 0)
133 {
134 Ret = NtUserSetSysColors(&ChangeSysColors, cElements);
135 if(Ret)
136 {
137 /* FIXME - just change it in the usermode structure, too, instead of asking win32k again */
138 (void)NtUserGetSysColors(SysColors, NUM_SYSCOLORS);
139 }
140 }
141 else
142 {
143 SetLastError(ERROR_INVALID_PARAMETER);
144 Ret = FALSE;
145 }
146
147 return Ret;
148 }
149
150 void
151 UserGetInsideRectNC(HWND hWnd, RECT *rect)
152 {
153 RECT WindowRect;
154 ULONG Style;
155 ULONG ExStyle;
156
157 Style = GetWindowLongW(hWnd, GWL_STYLE);
158 ExStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
159 GetWindowRect(hWnd, &WindowRect);
160 rect->top = rect->left = 0;
161 rect->right = WindowRect.right - WindowRect.left;
162 rect->bottom = WindowRect.bottom - WindowRect.top;
163
164 if (Style & WS_ICONIC)
165 {
166 return;
167 }
168
169 /* Remove frame from rectangle */
170 if (UserHasThickFrameStyle(Style, ExStyle ))
171 {
172 InflateRect(rect, -GetSystemMetrics(SM_CXFRAME),
173 -GetSystemMetrics(SM_CYFRAME));
174 }
175 else
176 {
177 if (UserHasDlgFrameStyle(Style, ExStyle ))
178 {
179 InflateRect(rect, -GetSystemMetrics(SM_CXDLGFRAME),
180 -GetSystemMetrics(SM_CYDLGFRAME));
181 /* FIXME: this isn't in NC_AdjustRect? why not? */
182 if (ExStyle & WS_EX_DLGMODALFRAME)
183 InflateRect( rect, -1, 0 );
184 }
185 else
186 {
187 if (UserHasThinFrameStyle(Style, ExStyle))
188 {
189 InflateRect(rect, -GetSystemMetrics(SM_CXBORDER),
190 -GetSystemMetrics(SM_CYBORDER));
191 }
192 }
193 }
194 }
195
196
197 VOID
198 DefWndSetRedraw(HWND hWnd, WPARAM wParam)
199 {
200 LONG Style = GetWindowLong(hWnd, GWL_STYLE);
201 /* Content can be redrawn after a change. */
202 if (wParam)
203 {
204 if (!(Style & WS_VISIBLE)) /* Not Visible */
205 {
206 SetWindowLong(hWnd, GWL_STYLE, WS_VISIBLE);
207 }
208 }
209 else /* Content cannot be redrawn after a change. */
210 {
211 if (Style & WS_VISIBLE) /* Visible */
212 {
213 RedrawWindow( hWnd, NULL, 0, RDW_ALLCHILDREN | RDW_VALIDATE );
214 Style &= ~WS_VISIBLE;
215 SetWindowLong(hWnd, GWL_STYLE, Style); /* clear bits */
216 }
217 }
218 return;
219 }
220
221
222 LRESULT
223 DefWndHandleSetCursor(HWND hWnd, WPARAM wParam, LPARAM lParam, ULONG Style)
224 {
225 /* Not for child windows. */
226 if (hWnd != (HWND)wParam)
227 {
228 return(0);
229 }
230
231 switch((INT_PTR) LOWORD(lParam))
232 {
233 case HTERROR:
234 {
235 WORD Msg = HIWORD(lParam);
236 if (Msg == WM_LBUTTONDOWN || Msg == WM_MBUTTONDOWN ||
237 Msg == WM_RBUTTONDOWN || Msg == WM_XBUTTONDOWN)
238 {
239 MessageBeep(0);
240 }
241 break;
242 }
243
244 case HTCLIENT:
245 {
246 HICON hCursor = (HICON)GetClassLongW(hWnd, GCL_HCURSOR);
247 if (hCursor)
248 {
249 SetCursor(hCursor);
250 return(TRUE);
251 }
252 return(FALSE);
253 }
254
255 case HTLEFT:
256 case HTRIGHT:
257 {
258 if (Style & WS_MAXIMIZE)
259 {
260 break;
261 }
262 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZEWE)));
263 }
264
265 case HTTOP:
266 case HTBOTTOM:
267 {
268 if (Style & WS_MAXIMIZE)
269 {
270 break;
271 }
272 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENS)));
273 }
274
275 case HTTOPLEFT:
276 case HTBOTTOMRIGHT:
277 {
278 if (Style & WS_MAXIMIZE)
279 {
280 break;
281 }
282 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENWSE)));
283 }
284
285 case HTBOTTOMLEFT:
286 case HTTOPRIGHT:
287 {
288 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_MAXIMIZE)
289 {
290 break;
291 }
292 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENESW)));
293 }
294 }
295 return((LRESULT)SetCursor(LoadCursorW(0, IDC_ARROW)));
296 }
297
298 static LONG
299 DefWndStartSizeMove(HWND hWnd, WPARAM wParam, POINT *capturePoint)
300 {
301 LONG hittest = 0;
302 POINT pt;
303 MSG msg;
304 RECT rectWindow;
305 ULONG Style = GetWindowLongW(hWnd, GWL_STYLE);
306
307 GetWindowRect(hWnd, &rectWindow);
308
309 if ((wParam & 0xfff0) == SC_MOVE)
310 {
311 /* Move pointer at the center of the caption */
312 RECT rect;
313 UserGetInsideRectNC(hWnd, &rect);
314 if (Style & WS_SYSMENU)
315 rect.left += GetSystemMetrics(SM_CXSIZE) + 1;
316 if (Style & WS_MINIMIZEBOX)
317 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
318 if (Style & WS_MAXIMIZEBOX)
319 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
320 pt.x = rectWindow.left + (rect.right - rect.left) / 2;
321 pt.y = rectWindow.top + rect.top + GetSystemMetrics(SM_CYSIZE)/2;
322 hittest = HTCAPTION;
323 *capturePoint = pt;
324 }
325 else /* SC_SIZE */
326 {
327 pt.x = pt.y = 0;
328 while(!hittest)
329 {
330 if (GetMessageW(&msg, NULL, 0, 0) <= 0)
331 break;
332 switch(msg.message)
333 {
334 case WM_MOUSEMOVE:
335 hittest = DefWndNCHitTest(hWnd, msg.pt);
336 if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT))
337 hittest = 0;
338 break;
339
340 case WM_LBUTTONUP:
341 return 0;
342
343 case WM_KEYDOWN:
344 switch(msg.wParam)
345 {
346 case VK_UP:
347 hittest = HTTOP;
348 pt.x =(rectWindow.left+rectWindow.right)/2;
349 pt.y = rectWindow.top + GetSystemMetrics(SM_CYFRAME) / 2;
350 break;
351 case VK_DOWN:
352 hittest = HTBOTTOM;
353 pt.x =(rectWindow.left+rectWindow.right)/2;
354 pt.y = rectWindow.bottom - GetSystemMetrics(SM_CYFRAME) / 2;
355 break;
356 case VK_LEFT:
357 hittest = HTLEFT;
358 pt.x = rectWindow.left + GetSystemMetrics(SM_CXFRAME) / 2;
359 pt.y =(rectWindow.top+rectWindow.bottom)/2;
360 break;
361 case VK_RIGHT:
362 hittest = HTRIGHT;
363 pt.x = rectWindow.right - GetSystemMetrics(SM_CXFRAME) / 2;
364 pt.y =(rectWindow.top+rectWindow.bottom)/2;
365 break;
366 case VK_RETURN:
367 case VK_ESCAPE: return 0;
368 }
369 }
370 }
371 *capturePoint = pt;
372 }
373 SetCursorPos( pt.x, pt.y );
374 DefWndHandleSetCursor(hWnd, (WPARAM)hWnd, MAKELONG(hittest, WM_MOUSEMOVE), Style);
375 return hittest;
376 }
377
378 #define ON_LEFT_BORDER(hit) \
379 (((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
380 #define ON_RIGHT_BORDER(hit) \
381 (((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
382 #define ON_TOP_BORDER(hit) \
383 (((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
384 #define ON_BOTTOM_BORDER(hit) \
385 (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
386
387 static VOID
388 UserDrawWindowFrame(HDC hdc, const RECT *rect,
389 ULONG width, ULONG height)
390 {
391 static HBRUSH hDraggingRectBrush = NULL;
392 HBRUSH hbrush;
393
394 if(!hDraggingRectBrush)
395 {
396 static HBITMAP hDraggingPattern = NULL;
397 const DWORD Pattern[4] = {0x5555AAAA, 0x5555AAAA, 0x5555AAAA, 0x5555AAAA};
398
399 hDraggingPattern = CreateBitmap(8, 8, 1, 1, Pattern);
400 hDraggingRectBrush = CreatePatternBrush(hDraggingPattern);
401 }
402
403 hbrush = SelectObject( hdc, hDraggingRectBrush );
404 PatBlt( hdc, rect->left, rect->top,
405 rect->right - rect->left - width, height, PATINVERT );
406 PatBlt( hdc, rect->left, rect->top + height, width,
407 rect->bottom - rect->top - height, PATINVERT );
408 PatBlt( hdc, rect->left + width, rect->bottom - 1,
409 rect->right - rect->left - width, -height, PATINVERT );
410 PatBlt( hdc, rect->right - 1, rect->top, -width,
411 rect->bottom - rect->top - height, PATINVERT );
412 SelectObject( hdc, hbrush );
413 }
414
415 static VOID
416 UserDrawMovingFrame(HDC hdc, RECT *rect, BOOL thickframe)
417 {
418 if(thickframe)
419 {
420 UserDrawWindowFrame(hdc, rect, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME));
421 }
422 else
423 {
424 UserDrawWindowFrame(hdc, rect, 1, 1);
425 }
426 }
427
428 static VOID
429 DefWndDoSizeMove(HWND hwnd, WORD wParam)
430 {
431 HRGN DesktopRgn;
432 MSG msg;
433 RECT sizingRect, mouseRect, origRect, clipRect, unmodRect;
434 HDC hdc;
435 LONG hittest = (LONG)(wParam & 0x0f);
436 HCURSOR hDragCursor = 0, hOldCursor = 0;
437 POINT minTrack, maxTrack;
438 POINT capturePoint, pt;
439 ULONG Style = GetWindowLongW(hwnd, GWL_STYLE);
440 ULONG ExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
441 BOOL thickframe;
442 BOOL iconic = Style & WS_MINIMIZE;
443 BOOL moved = FALSE;
444 DWORD dwPoint = GetMessagePos();
445 BOOL DragFullWindows = FALSE;
446 HWND hWndParent = NULL;
447
448 SystemParametersInfoA(SPI_GETDRAGFULLWINDOWS, 0, &DragFullWindows, 0);
449
450 pt.x = GET_X_LPARAM(dwPoint);
451 pt.y = GET_Y_LPARAM(dwPoint);
452 capturePoint = pt;
453
454 if (IsZoomed(hwnd) || !IsWindowVisible(hwnd))
455 {
456 return;
457 }
458
459 thickframe = UserHasThickFrameStyle(Style, ExStyle) && !(Style & WS_MINIMIZE);
460 if ((wParam & 0xfff0) == SC_MOVE)
461 {
462 if (!hittest)
463 {
464 hittest = DefWndStartSizeMove(hwnd, wParam, &capturePoint);
465 }
466 if (!hittest)
467 {
468 return;
469 }
470 }
471 else /* SC_SIZE */
472 {
473 if (!thickframe)
474 {
475 return;
476 }
477 if (hittest && ((wParam & 0xfff0) != SC_MOUSEMENU))
478 {
479 hittest += (HTLEFT - WMSZ_LEFT);
480 }
481 else
482 {
483 SetCapture(hwnd);
484 hittest = DefWndStartSizeMove(hwnd, wParam, &capturePoint);
485 if (!hittest)
486 {
487 ReleaseCapture();
488 return;
489 }
490 }
491 }
492
493 /* Get min/max info */
494
495 WinPosGetMinMaxInfo(hwnd, NULL, NULL, &minTrack, &maxTrack);
496 GetWindowRect(hwnd, &sizingRect);
497 if (Style & WS_CHILD)
498 {
499 hWndParent = GetParent(hwnd);
500 MapWindowPoints( 0, hWndParent, (LPPOINT)&sizingRect, 2 );
501 unmodRect = sizingRect;
502 GetClientRect(hWndParent, &mouseRect );
503 clipRect = mouseRect;
504 MapWindowPoints(hWndParent, HWND_DESKTOP, (LPPOINT)&clipRect, 2);
505 }
506 else
507 {
508 if(!(ExStyle & WS_EX_TOPMOST))
509 {
510 SystemParametersInfoW(SPI_GETWORKAREA, 0, &clipRect, 0);
511 mouseRect = clipRect;
512 }
513 else
514 {
515 SetRect(&mouseRect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
516 clipRect = mouseRect;
517 }
518 unmodRect = sizingRect;
519 }
520 ClipCursor(&clipRect);
521
522 origRect = sizingRect;
523 if (ON_LEFT_BORDER(hittest))
524 {
525 mouseRect.left = max( mouseRect.left, sizingRect.right-maxTrack.x );
526 mouseRect.right = min( mouseRect.right, sizingRect.right-minTrack.x );
527 }
528 else if (ON_RIGHT_BORDER(hittest))
529 {
530 mouseRect.left = max( mouseRect.left, sizingRect.left+minTrack.x );
531 mouseRect.right = min( mouseRect.right, sizingRect.left+maxTrack.x );
532 }
533 if (ON_TOP_BORDER(hittest))
534 {
535 mouseRect.top = max( mouseRect.top, sizingRect.bottom-maxTrack.y );
536 mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minTrack.y);
537 }
538 else if (ON_BOTTOM_BORDER(hittest))
539 {
540 mouseRect.top = max( mouseRect.top, sizingRect.top+minTrack.y );
541 mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+maxTrack.y );
542 }
543 if (Style & WS_CHILD)
544 {
545 MapWindowPoints( hWndParent, 0, (LPPOINT)&mouseRect, 2 );
546 }
547
548 SendMessageA( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
549 (void)NtUserSetGUIThreadHandle(MSQ_STATE_MOVESIZE, hwnd);
550 if (GetCapture() != hwnd) SetCapture( hwnd );
551
552 if (Style & WS_CHILD)
553 {
554 /* Retrieve a default cache DC (without using the window style) */
555 hdc = GetDCEx(hWndParent, 0, DCX_CACHE);
556 DesktopRgn = NULL;
557 }
558 else
559 {
560 hdc = GetDC( 0 );
561 DesktopRgn = CreateRectRgnIndirect(&clipRect);
562 }
563
564 SelectObject(hdc, DesktopRgn);
565
566 if( iconic ) /* create a cursor for dragging */
567 {
568 HICON hIcon = (HICON)GetClassLongW(hwnd, GCL_HICON);
569 if(!hIcon) hIcon = (HICON)SendMessageW( hwnd, WM_QUERYDRAGICON, 0, 0L);
570 if( hIcon ) hDragCursor = CursorIconToCursor( hIcon, TRUE );
571 if( !hDragCursor ) iconic = FALSE;
572 }
573
574 /* invert frame if WIN31_LOOK to indicate mouse click on caption */
575 if( !iconic && !DragFullWindows)
576 {
577 UserDrawMovingFrame( hdc, &sizingRect, thickframe);
578 }
579
580 for(;;)
581 {
582 int dx = 0, dy = 0;
583
584 if (GetMessageW(&msg, 0, 0, 0) <= 0)
585 break;
586
587 /* Exit on button-up, Return, or Esc */
588 if ((msg.message == WM_LBUTTONUP) ||
589 ((msg.message == WM_KEYDOWN) &&
590 ((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
591
592 if (msg.message == WM_PAINT)
593 {
594 if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
595 UpdateWindow( msg.hwnd );
596 if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
597 continue;
598 }
599
600 if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
601 continue; /* We are not interested in other messages */
602
603 pt = msg.pt;
604
605 if (msg.message == WM_KEYDOWN) switch(msg.wParam)
606 {
607 case VK_UP: pt.y -= 8; break;
608 case VK_DOWN: pt.y += 8; break;
609 case VK_LEFT: pt.x -= 8; break;
610 case VK_RIGHT: pt.x += 8; break;
611 }
612
613 pt.x = max( pt.x, mouseRect.left );
614 pt.x = min( pt.x, mouseRect.right );
615 pt.y = max( pt.y, mouseRect.top );
616 pt.y = min( pt.y, mouseRect.bottom );
617
618 dx = pt.x - capturePoint.x;
619 dy = pt.y - capturePoint.y;
620
621 if (dx || dy)
622 {
623 if( !moved )
624 {
625 moved = TRUE;
626
627 if( iconic ) /* ok, no system popup tracking */
628 {
629 hOldCursor = SetCursor(hDragCursor);
630 ShowCursor( TRUE );
631 }
632 }
633
634 if (msg.message == WM_KEYDOWN) SetCursorPos( pt.x, pt.y );
635 else
636 {
637 RECT newRect = unmodRect;
638 WPARAM wpSizingHit = 0;
639
640 if (hittest == HTCAPTION) OffsetRect( &newRect, dx, dy );
641 if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
642 else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
643 if (ON_TOP_BORDER(hittest)) newRect.top += dy;
644 else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
645 if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
646 capturePoint = pt;
647
648 /* determine the hit location */
649 if (hittest >= HTLEFT && hittest <= HTBOTTOMRIGHT)
650 wpSizingHit = WMSZ_LEFT + (hittest - HTLEFT);
651 unmodRect = newRect;
652 SendMessageA( hwnd, WM_SIZING, wpSizingHit, (LPARAM)&newRect );
653
654 if (!iconic)
655 {
656 if(!DragFullWindows)
657 UserDrawMovingFrame( hdc, &newRect, thickframe );
658 else {
659 /* To avoid any deadlocks, all the locks on the windows
660 structures must be suspended before the SetWindowPos */
661 SetWindowPos( hwnd, 0, newRect.left, newRect.top,
662 newRect.right - newRect.left,
663 newRect.bottom - newRect.top,
664 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
665 }
666 }
667 sizingRect = newRect;
668 }
669 }
670 }
671
672 ReleaseCapture();
673 ClipCursor(NULL);
674 if( iconic )
675 {
676 if( moved ) /* restore cursors, show icon title later on */
677 {
678 ShowCursor( FALSE );
679 SetCursor( hOldCursor );
680 }
681 DestroyCursor( hDragCursor );
682 }
683 else if(!DragFullWindows)
684 UserDrawMovingFrame( hdc, &sizingRect, thickframe );
685
686 if (Style & WS_CHILD)
687 ReleaseDC( hWndParent, hdc );
688 else
689 {
690 ReleaseDC( 0, hdc );
691 if(DesktopRgn)
692 {
693 DeleteObject(DesktopRgn);
694 }
695 }
696 (void)NtUserSetGUIThreadHandle(MSQ_STATE_MOVESIZE, NULL);
697 SendMessageA( hwnd, WM_EXITSIZEMOVE, 0, 0 );
698 SendMessageA( hwnd, WM_SETVISIBLE, !IsIconic(hwnd), 0L);
699
700 /* window moved or resized */
701 if (moved)
702 {
703 /* if the moving/resizing isn't canceled call SetWindowPos
704 * with the new position or the new size of the window
705 */
706 if (!((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) )
707 {
708 /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
709 if(!DragFullWindows)
710 SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
711 sizingRect.right - sizingRect.left,
712 sizingRect.bottom - sizingRect.top,
713 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
714 }
715 else { /* restore previous size/position */
716 if(DragFullWindows)
717 SetWindowPos( hwnd, 0, origRect.left, origRect.top,
718 origRect.right - origRect.left,
719 origRect.bottom - origRect.top,
720 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
721 }
722 }
723
724 if( IsWindow(hwnd) )
725 if( Style & WS_MINIMIZE )
726 {
727 /* Single click brings up the system menu when iconized */
728
729 if( !moved )
730 {
731 if( Style & WS_SYSMENU )
732 SendMessageA( hwnd, WM_SYSCOMMAND,
733 SC_MOUSEMENU + HTSYSMENU, MAKELONG(pt.x,pt.y));
734 }
735 }
736 }
737
738
739 /***********************************************************************
740 * DefWndTrackScrollBar
741 *
742 * Track a mouse button press on the horizontal or vertical scroll-bar.
743 */
744 static VOID
745 DefWndTrackScrollBar(HWND Wnd, WPARAM wParam, POINT Pt)
746 {
747 INT ScrollBar;
748
749 if (SC_HSCROLL == (wParam & 0xfff0))
750 {
751 if (HTHSCROLL != (wParam & 0x0f))
752 {
753 return;
754 }
755 ScrollBar = SB_HORZ;
756 }
757 else /* SC_VSCROLL */
758 {
759 if (HTVSCROLL != (wParam & 0x0f))
760 {
761 return;
762 }
763 ScrollBar = SB_VERT;
764 }
765 ScrollTrackScrollBar(Wnd, ScrollBar, Pt );
766 }
767
768
769 LRESULT
770 DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
771 {
772 WINDOWPLACEMENT wp;
773 POINT Pt;
774
775 switch (wParam & 0xfff0)
776 {
777 case SC_MOVE:
778 case SC_SIZE:
779 DefWndDoSizeMove(hWnd, wParam);
780 break;
781 case SC_MINIMIZE:
782 wp.length = sizeof(WINDOWPLACEMENT);
783 if(GetWindowPlacement(hWnd, &wp))
784 {
785 wp.showCmd = SW_MINIMIZE;
786 SetWindowPlacement(hWnd, &wp);
787 }
788 break;
789 case SC_MAXIMIZE:
790 wp.length = sizeof(WINDOWPLACEMENT);
791 if(GetWindowPlacement(hWnd, &wp))
792 {
793 wp.showCmd = SW_MAXIMIZE;
794 SetWindowPlacement(hWnd, &wp);
795 }
796 break;
797 case SC_RESTORE:
798 wp.length = sizeof(WINDOWPLACEMENT);
799 if(GetWindowPlacement(hWnd, &wp))
800 {
801 wp.showCmd = SW_RESTORE;
802 SetWindowPlacement(hWnd, &wp);
803 }
804 break;
805 case SC_CLOSE:
806 SendMessageA(hWnd, WM_CLOSE, 0, 0);
807 break;
808 case SC_MOUSEMENU:
809 {
810 Pt.x = (short)LOWORD(lParam);
811 Pt.y = (short)HIWORD(lParam);
812 MenuTrackMouseMenuBar(hWnd, wParam & 0x000f, Pt);
813 }
814 break;
815 case SC_KEYMENU:
816 MenuTrackKbdMenuBar(hWnd, wParam, (WCHAR)lParam);
817 break;
818 case SC_VSCROLL:
819 case SC_HSCROLL:
820 {
821 Pt.x = (short)LOWORD(lParam);
822 Pt.y = (short)HIWORD(lParam);
823 DefWndTrackScrollBar(hWnd, wParam, Pt);
824 }
825 break;
826
827 default:
828 /* FIXME: Implement */
829 UNIMPLEMENTED;
830 break;
831 }
832
833 return(0);
834 }
835
836 LRESULT
837 DefWndHandleWindowPosChanging(HWND hWnd, WINDOWPOS* Pos)
838 {
839 POINT maxTrack, minTrack;
840 LONG style = GetWindowLongA(hWnd, GWL_STYLE);
841
842 if (Pos->flags & SWP_NOSIZE) return 0;
843 if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
844 {
845 WinPosGetMinMaxInfo(hWnd, NULL, NULL, &minTrack, &maxTrack);
846 Pos->cx = min(Pos->cx, maxTrack.x);
847 Pos->cy = min(Pos->cy, maxTrack.y);
848 if (!(style & WS_MINIMIZE))
849 {
850 if (Pos->cx < minTrack.x) Pos->cx = minTrack.x;
851 if (Pos->cy < minTrack.y) Pos->cy = minTrack.y;
852 }
853 }
854 else
855 {
856 Pos->cx = max(Pos->cx, 0);
857 Pos->cy = max(Pos->cy, 0);
858 }
859 return 0;
860 }
861
862 /* Undocumented flags. */
863 #define SWP_NOCLIENTMOVE 0x0800
864 #define SWP_NOCLIENTSIZE 0x1000
865
866 LRESULT
867 DefWndHandleWindowPosChanged(HWND hWnd, WINDOWPOS* Pos)
868 {
869 RECT Rect;
870
871 GetClientRect(hWnd, &Rect);
872 MapWindowPoints(hWnd, (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD ?
873 GetParent(hWnd) : NULL), (LPPOINT) &Rect, 2);
874
875 if (! (Pos->flags & SWP_NOCLIENTMOVE))
876 {
877 SendMessageW(hWnd, WM_MOVE, 0, MAKELONG(Rect.left, Rect.top));
878 }
879
880 if (! (Pos->flags & SWP_NOCLIENTSIZE))
881 {
882 WPARAM wp = SIZE_RESTORED;
883 if (IsZoomed(hWnd))
884 {
885 wp = SIZE_MAXIMIZED;
886 }
887 else if (IsIconic(hWnd))
888 {
889 wp = SIZE_MINIMIZED;
890 }
891 SendMessageW(hWnd, WM_SIZE, wp,
892 MAKELONG(Rect.right - Rect.left, Rect.bottom - Rect.top));
893 }
894
895 return 0;
896 }
897
898 /***********************************************************************
899 * DefWndControlColor
900 *
901 * Default colors for control painting.
902 */
903 HBRUSH
904 DefWndControlColor(HDC hDC, UINT ctlType)
905 {
906 if (CTLCOLOR_SCROLLBAR == ctlType)
907 {
908 HBRUSH hb = GetSysColorBrush(COLOR_SCROLLBAR);
909 COLORREF bk = GetSysColor(COLOR_3DHILIGHT);
910 SetTextColor(hDC, GetSysColor(COLOR_3DFACE));
911 SetBkColor(hDC, bk);
912
913 /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
914 * we better use 0x55aa bitmap brush to make scrollbar's background
915 * look different from the window background.
916 */
917 if (bk == GetSysColor(COLOR_WINDOW))
918 {
919 static const WORD wPattern55AA[] =
920 {
921 0x5555, 0xaaaa, 0x5555, 0xaaaa,
922 0x5555, 0xaaaa, 0x5555, 0xaaaa
923 };
924 static HBITMAP hPattern55AABitmap = NULL;
925 static HBRUSH hPattern55AABrush = NULL;
926 if (hPattern55AABrush == NULL)
927 {
928 hPattern55AABitmap = CreateBitmap(8, 8, 1, 1, wPattern55AA);
929 hPattern55AABrush = CreatePatternBrush(hPattern55AABitmap);
930 }
931 return hPattern55AABrush;
932 }
933 UnrealizeObject(hb);
934 return hb;
935 }
936
937 SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
938
939 if ((CTLCOLOR_EDIT == ctlType) || (CTLCOLOR_LISTBOX == ctlType))
940 {
941 SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
942 }
943 else
944 {
945 SetBkColor(hDC, GetSysColor(COLOR_3DFACE));
946 return GetSysColorBrush(COLOR_3DFACE);
947 }
948
949 return GetSysColorBrush(COLOR_WINDOW);
950 }
951
952 static void DefWndPrint( HWND hwnd, HDC hdc, ULONG uFlags)
953 {
954 /*
955 * Visibility flag.
956 */
957 if ( (uFlags & PRF_CHECKVISIBLE) &&
958 !IsWindowVisible(hwnd) )
959 return;
960
961 /*
962 * Unimplemented flags.
963 */
964 if ( (uFlags & PRF_CHILDREN) ||
965 (uFlags & PRF_OWNED) ||
966 (uFlags & PRF_NONCLIENT) )
967 {
968 FIXME("WM_PRINT message with unsupported flags\n");
969 }
970
971 /*
972 * Background
973 */
974 if ( uFlags & PRF_ERASEBKGND)
975 SendMessageW(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
976
977 /*
978 * Client area
979 */
980 if ( uFlags & PRF_CLIENT)
981 SendMessageW(hwnd, WM_PRINTCLIENT, (WPARAM)hdc, PRF_CLIENT);
982 }
983
984
985 VOID FASTCALL
986 DefWndScreenshot(HWND hWnd)
987 {
988 RECT rect;
989
990 OpenClipboard(hWnd);
991 EmptyClipboard();
992
993 HDC hdc = GetWindowDC(hWnd);
994 GetWindowRect(hWnd, &rect);
995 INT w = rect.right - rect.left;
996 INT h = rect.bottom - rect.top;
997
998 HBITMAP hbitmap = CreateCompatibleBitmap(hdc, w, h);
999 HDC hdc2 = CreateCompatibleDC(hdc);
1000 SelectObject(hdc2, hbitmap);
1001
1002 BitBlt(hdc2, 0, 0, w, h,
1003 hdc, 0, 0,
1004 SRCCOPY);
1005
1006 SetClipboardData(CF_BITMAP, hbitmap);
1007
1008 ReleaseDC(hWnd, hdc);
1009 ReleaseDC(hWnd, hdc2);
1010
1011 CloseClipboard();
1012
1013 }
1014
1015
1016
1017 LRESULT STDCALL
1018 User32DefWindowProc(HWND hWnd,
1019 UINT Msg,
1020 WPARAM wParam,
1021 LPARAM lParam,
1022 BOOL bUnicode)
1023 {
1024 switch (Msg)
1025 {
1026 case WM_NCPAINT:
1027 {
1028 return DefWndNCPaint(hWnd, (HRGN)wParam, -1);
1029 }
1030
1031 case WM_NCCALCSIZE:
1032 {
1033 return DefWndNCCalcSize(hWnd, (BOOL)wParam, (RECT*)lParam);
1034 }
1035
1036 case WM_NCACTIVATE:
1037 {
1038 return DefWndNCActivate(hWnd, wParam);
1039 }
1040
1041 case WM_NCHITTEST:
1042 {
1043 POINT Point;
1044 Point.x = GET_X_LPARAM(lParam);
1045 Point.y = GET_Y_LPARAM(lParam);
1046 return (DefWndNCHitTest(hWnd, Point));
1047 }
1048
1049 case WM_LBUTTONDOWN:
1050 case WM_RBUTTONDOWN:
1051 case WM_MBUTTONDOWN:
1052 iF10Key = iMenuSysKey = 0;
1053 break;
1054
1055 case WM_NCLBUTTONDOWN:
1056 {
1057 return (DefWndNCLButtonDown(hWnd, wParam, lParam));
1058 }
1059
1060 case WM_LBUTTONDBLCLK:
1061 return (DefWndNCLButtonDblClk(hWnd, HTCLIENT, lParam));
1062
1063 case WM_NCLBUTTONDBLCLK:
1064 {
1065 return (DefWndNCLButtonDblClk(hWnd, wParam, lParam));
1066 }
1067
1068 case WM_WINDOWPOSCHANGING:
1069 {
1070 return (DefWndHandleWindowPosChanging(hWnd, (WINDOWPOS*)lParam));
1071 }
1072
1073 case WM_WINDOWPOSCHANGED:
1074 {
1075 return (DefWndHandleWindowPosChanged(hWnd, (WINDOWPOS*)lParam));
1076 }
1077
1078 case WM_NCRBUTTONDOWN:
1079 {
1080 /* in Windows, capture is taken when right-clicking on the caption bar */
1081 if (wParam == HTCAPTION)
1082 {
1083 SetCapture(hWnd);
1084 }
1085 break;
1086 }
1087
1088 case WM_RBUTTONUP:
1089 {
1090 POINT Pt;
1091 if (hWnd == GetCapture())
1092 {
1093 ReleaseCapture();
1094 }
1095 Pt.x = GET_X_LPARAM(lParam);
1096 Pt.y = GET_Y_LPARAM(lParam);
1097 ClientToScreen(hWnd, &Pt);
1098 lParam = MAKELPARAM(Pt.x, Pt.y);
1099 if (bUnicode)
1100 {
1101 SendMessageW(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
1102 }
1103 else
1104 {
1105 SendMessageA(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
1106 }
1107 break;
1108 }
1109
1110 case WM_NCRBUTTONUP:
1111 /*
1112 * FIXME : we must NOT send WM_CONTEXTMENU on a WM_NCRBUTTONUP (checked
1113 * in Windows), but what _should_ we do? According to MSDN :
1114 * "If it is appropriate to do so, the system sends the WM_SYSCOMMAND
1115 * message to the window". When is it appropriate?
1116 */
1117 break;
1118
1119 case WM_CONTEXTMENU:
1120 {
1121 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1122 {
1123 if (bUnicode)
1124 {
1125 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1126 }
1127 else
1128 {
1129 SendMessageA(GetParent(hWnd), WM_CONTEXTMENU, wParam, lParam);
1130 }
1131 }
1132 else
1133 {
1134 POINT Pt;
1135 DWORD Style;
1136 LONG HitCode;
1137
1138 Style = GetWindowLongW(hWnd, GWL_STYLE);
1139
1140 Pt.x = GET_X_LPARAM(lParam);
1141 Pt.y = GET_Y_LPARAM(lParam);
1142 if (Style & WS_CHILD)
1143 {
1144 ScreenToClient(GetParent(hWnd), &Pt);
1145 }
1146
1147 HitCode = DefWndNCHitTest(hWnd, Pt);
1148
1149 if (HitCode == HTCAPTION || HitCode == HTSYSMENU)
1150 {
1151 HMENU SystemMenu;
1152 UINT Flags;
1153
1154 if((SystemMenu = GetSystemMenu(hWnd, FALSE)))
1155 {
1156 MenuInitSysMenuPopup(SystemMenu, GetWindowLongW(hWnd, GWL_STYLE),
1157 GetClassLongW(hWnd, GCL_STYLE), HitCode);
1158
1159 if(HitCode == HTCAPTION)
1160 Flags = TPM_LEFTBUTTON | TPM_RIGHTBUTTON;
1161 else
1162 Flags = TPM_LEFTBUTTON;
1163
1164 TrackPopupMenu(SystemMenu, Flags,
1165 Pt.x, Pt.y, 0, hWnd, NULL);
1166 }
1167 }
1168 }
1169 break;
1170 }
1171
1172 case WM_PRINT:
1173 {
1174 DefWndPrint(hWnd, (HDC)wParam, lParam);
1175 return (0);
1176 }
1177
1178 case WM_PAINTICON:
1179 case WM_PAINT:
1180 {
1181 PAINTSTRUCT Ps;
1182 HDC hDC = BeginPaint(hWnd, &Ps);
1183 if (hDC)
1184 {
1185 HICON hIcon;
1186 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE &&
1187 (hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON)) != NULL)
1188 {
1189 RECT ClientRect;
1190 INT x, y;
1191 GetClientRect(hWnd, &ClientRect);
1192 x = (ClientRect.right - ClientRect.left -
1193 GetSystemMetrics(SM_CXICON)) / 2;
1194 y = (ClientRect.bottom - ClientRect.top -
1195 GetSystemMetrics(SM_CYICON)) / 2;
1196 DrawIcon(hDC, x, y, hIcon);
1197 }
1198 EndPaint(hWnd, &Ps);
1199 }
1200 return (0);
1201 }
1202
1203 case WM_SYNCPAINT:
1204 {
1205 HRGN hRgn;
1206 hRgn = CreateRectRgn(0, 0, 0, 0);
1207 if (GetUpdateRgn(hWnd, hRgn, FALSE) != NULLREGION)
1208 {
1209 RedrawWindow(hWnd, NULL, hRgn,
1210 RDW_ERASENOW | RDW_ERASE | RDW_FRAME |
1211 RDW_ALLCHILDREN);
1212 }
1213 DeleteObject(hRgn);
1214 return (0);
1215 }
1216
1217 case WM_SETREDRAW:
1218 {
1219 DefWndSetRedraw(hWnd, wParam);
1220 return (0);
1221 }
1222
1223 case WM_CLOSE:
1224 {
1225 DestroyWindow(hWnd);
1226 return (0);
1227 }
1228
1229 case WM_MOUSEACTIVATE:
1230 {
1231 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1232 {
1233 LONG Ret;
1234 if (bUnicode)
1235 {
1236 Ret = SendMessageW(GetParent(hWnd), WM_MOUSEACTIVATE,
1237 wParam, lParam);
1238 }
1239 else
1240 {
1241 Ret = SendMessageA(GetParent(hWnd), WM_MOUSEACTIVATE,
1242 wParam, lParam);
1243 }
1244 if (Ret)
1245 {
1246 return (Ret);
1247 }
1248 }
1249 return ((LOWORD(lParam) >= HTCLIENT) ? MA_ACTIVATE : MA_NOACTIVATE);
1250 }
1251
1252 case WM_ACTIVATE:
1253 {
1254 /* Check if the window is minimized. */
1255 if (LOWORD(wParam) != WA_INACTIVE &&
1256 !(GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE))
1257 {
1258 SetFocus(hWnd);
1259 }
1260 break;
1261 }
1262
1263 case WM_MOUSEWHEEL:
1264 {
1265 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1266 {
1267 if (bUnicode)
1268 {
1269 return (SendMessageW(GetParent(hWnd), WM_MOUSEWHEEL,
1270 wParam, lParam));
1271 }
1272 else
1273 {
1274 return (SendMessageA(GetParent(hWnd), WM_MOUSEWHEEL,
1275 wParam, lParam));
1276 }
1277 }
1278 break;
1279 }
1280
1281 case WM_ERASEBKGND:
1282 case WM_ICONERASEBKGND:
1283 {
1284 RECT Rect;
1285 HBRUSH hBrush = (HBRUSH)GetClassLongW(hWnd, GCL_HBRBACKGROUND);
1286
1287 if (NULL == hBrush)
1288 {
1289 return 0;
1290 }
1291 if (GetClassLongW(hWnd, GCL_STYLE) & CS_PARENTDC)
1292 {
1293 /* can't use GetClipBox with a parent DC or we fill the whole parent */
1294 GetClientRect(hWnd, &Rect);
1295 DPtoLP((HDC)wParam, (LPPOINT)&Rect, 2);
1296 }
1297 else
1298 {
1299 GetClipBox((HDC)wParam, &Rect);
1300 }
1301 FillRect((HDC)wParam, &Rect, hBrush);
1302 return (1);
1303 }
1304
1305 case WM_CTLCOLORMSGBOX:
1306 case WM_CTLCOLOREDIT:
1307 case WM_CTLCOLORLISTBOX:
1308 case WM_CTLCOLORBTN:
1309 case WM_CTLCOLORDLG:
1310 case WM_CTLCOLORSTATIC:
1311 case WM_CTLCOLORSCROLLBAR:
1312 return (LRESULT) DefWndControlColor((HDC)wParam, Msg - WM_CTLCOLORMSGBOX);
1313
1314 case WM_CTLCOLOR:
1315 return (LRESULT) DefWndControlColor((HDC)wParam, HIWORD(lParam));
1316
1317 case WM_SETCURSOR:
1318 {
1319 ULONG Style = GetWindowLongW(hWnd, GWL_STYLE);
1320
1321 if (Style & WS_CHILD)
1322 {
1323 if (LOWORD(lParam) < HTLEFT || LOWORD(lParam) > HTBOTTOMRIGHT)
1324 {
1325 BOOL bResult;
1326 if (bUnicode)
1327 {
1328 bResult = SendMessageW(GetParent(hWnd), WM_SETCURSOR,
1329 wParam, lParam);
1330 }
1331 else
1332 {
1333 bResult = SendMessageA(GetParent(hWnd), WM_SETCURSOR,
1334 wParam, lParam);
1335 }
1336 if (bResult)
1337 {
1338 return(TRUE);
1339 }
1340 }
1341 }
1342 return (DefWndHandleSetCursor(hWnd, wParam, lParam, Style));
1343 }
1344
1345 case WM_SYSCOMMAND:
1346 return (DefWndHandleSysCommand(hWnd, wParam, lParam));
1347
1348 case WM_KEYDOWN:
1349 if(wParam == VK_F10) iF10Key = VK_F10;
1350 break;
1351
1352 /* FIXME: This is also incomplete. */
1353 case WM_SYSKEYDOWN:
1354 {
1355 if (HIWORD(lParam) & KEYDATA_ALT)
1356 {
1357 /* if( HIWORD(lParam) & ~KEYDATA_PREVSTATE ) */
1358 if ( (wParam == VK_MENU || wParam == VK_LMENU
1359 || wParam == VK_RMENU) && !iMenuSysKey )
1360 iMenuSysKey = 1;
1361 else
1362 iMenuSysKey = 0;
1363
1364 iF10Key = 0;
1365
1366 if (wParam == VK_F4) /* Try to close the window */
1367 {
1368 HWND top = GetAncestor(hWnd, GA_ROOT);
1369 if (!(GetClassLongW(top, GCL_STYLE) & CS_NOCLOSE))
1370 {
1371 if (bUnicode)
1372 PostMessageW(top, WM_SYSCOMMAND, SC_CLOSE, 0);
1373 else
1374 PostMessageA(top, WM_SYSCOMMAND, SC_CLOSE, 0);
1375 }
1376 }
1377 else if (wParam == VK_SNAPSHOT)
1378 {
1379 HWND hwnd = hWnd;
1380 while (GetParent(hwnd) != NULL)
1381 {
1382 hwnd = GetParent(hwnd);
1383 }
1384 DefWndScreenshot(hwnd);
1385 }
1386 }
1387 else if( wParam == VK_F10 )
1388 iF10Key = 1;
1389 else if( wParam == VK_ESCAPE && (GetKeyState(VK_SHIFT) & 0x8000))
1390 SendMessageW( hWnd, WM_SYSCOMMAND, SC_KEYMENU, ' ' );
1391 break;
1392 }
1393
1394 case WM_KEYUP:
1395 case WM_SYSKEYUP:
1396 {
1397 /* Press and release F10 or ALT */
1398 if (((wParam == VK_MENU || wParam == VK_LMENU || wParam == VK_RMENU)
1399 && iMenuSysKey) || ((wParam == VK_F10) && iF10Key))
1400 SendMessageW( GetAncestor( hWnd, GA_ROOT ), WM_SYSCOMMAND, SC_KEYMENU, 0L );
1401 iMenuSysKey = iF10Key = 0;
1402 break;
1403 }
1404
1405 case WM_SYSCHAR:
1406 {
1407 iMenuSysKey = 0;
1408 if (wParam == '\r' && IsIconic(hWnd))
1409 {
1410 PostMessageW( hWnd, WM_SYSCOMMAND, SC_RESTORE, 0L );
1411 break;
1412 }
1413 if ((HIWORD(lParam) & KEYDATA_ALT) && wParam)
1414 {
1415 if (wParam == '\t' || wParam == '\x1b') break;
1416 if (wParam == ' ' && (GetWindowLongW( hWnd, GWL_STYLE ) & WS_CHILD))
1417 SendMessageW( GetParent(hWnd), Msg, wParam, lParam );
1418 else
1419 SendMessageW( hWnd, WM_SYSCOMMAND, SC_KEYMENU, wParam );
1420 }
1421 else /* check for Ctrl-Esc */
1422 if (wParam != '\x1b') MessageBeep(0);
1423 break;
1424 }
1425
1426 case WM_SHOWWINDOW:
1427 {
1428 LONG Style;
1429 INT Ret = 0;
1430
1431 if (!lParam) return 0;
1432 Style = GetWindowLongW(hWnd, GWL_STYLE);
1433 if ((Style & WS_VISIBLE) && wParam) return 0;
1434 if (!(Style & WS_VISIBLE) && !wParam) return 0;
1435 if (!GetWindow(hWnd, GW_OWNER)) return 0;
1436 Ret = NtUserCallTwoParam((DWORD) hWnd, (DWORD) wParam, TWOPARAM_ROUTINE_ROS_SHOWWINDOW);
1437 if(Ret)
1438 {
1439 if( Ret == -1) return 0;
1440 return Ret;
1441 }
1442 ShowWindow(hWnd, wParam ? SW_SHOWNOACTIVATE : SW_HIDE);
1443 break;
1444 }
1445
1446 case WM_CANCELMODE:
1447 {
1448 iMenuSysKey = 0;
1449 /* FIXME: Check for a desktop. */
1450 if (!(GetWindowLongW( hWnd, GWL_STYLE ) & WS_CHILD)) EndMenu();
1451 if (GetCapture() == hWnd)
1452 {
1453 ReleaseCapture();
1454 }
1455 break;
1456 }
1457
1458 case WM_VKEYTOITEM:
1459 case WM_CHARTOITEM:
1460 return (-1);
1461 /*
1462 case WM_DROPOBJECT:
1463 return DRAG_FILE;
1464 */
1465 case WM_QUERYDROPOBJECT:
1466 {
1467 if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES)
1468 {
1469 return(1);
1470 }
1471 break;
1472 }
1473
1474 case WM_QUERYDRAGICON:
1475 {
1476 UINT Len;
1477 HICON hIcon;
1478
1479 hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON);
1480 if (hIcon)
1481 {
1482 return ((LRESULT)hIcon);
1483 }
1484 for (Len = 1; Len < 64; Len++)
1485 {
1486 if ((hIcon = LoadIconW(NULL, MAKEINTRESOURCEW(Len))) != NULL)
1487 {
1488 return((LRESULT)hIcon);
1489 }
1490 }
1491 return ((LRESULT)LoadIconW(0, IDI_APPLICATION));
1492 }
1493
1494 /* FIXME: WM_ISACTIVEICON */
1495
1496 case WM_NOTIFYFORMAT:
1497 {
1498 if (lParam == NF_QUERY)
1499 return IsWindowUnicode(hWnd) ? NFR_UNICODE : NFR_ANSI;
1500 break;
1501 }
1502
1503 case WM_SETICON:
1504 {
1505 INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
1506 HICON hOldIcon = (HICON)GetClassLongW(hWnd, Index);
1507 SetClassLongW(hWnd, Index, lParam);
1508 SetWindowPos(hWnd, 0, 0, 0, 0, 0,
1509 SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
1510 SWP_NOACTIVATE | SWP_NOZORDER);
1511 return ((LRESULT)hOldIcon);
1512 }
1513
1514 case WM_GETICON:
1515 {
1516 INT Index = (wParam == ICON_BIG) ? GCL_HICON : GCL_HICONSM;
1517 return (GetClassLongW(hWnd, Index));
1518 }
1519
1520 case WM_HELP:
1521 {
1522 if (bUnicode)
1523 {
1524 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1525 }
1526 else
1527 {
1528 SendMessageA(GetParent(hWnd), Msg, wParam, lParam);
1529 }
1530 break;
1531 }
1532
1533 case WM_SYSTIMER:
1534 {
1535 THRDCARETINFO CaretInfo;
1536 switch(wParam)
1537 {
1538 case 0xffff: /* Caret timer */
1539 /* switch showing byte in win32k and get information about the caret */
1540 if(NtUserSwitchCaretShowing(&CaretInfo) && (CaretInfo.hWnd == hWnd))
1541 {
1542 DrawCaret(hWnd, &CaretInfo);
1543 }
1544 break;
1545 }
1546 break;
1547 }
1548
1549 case WM_QUERYOPEN:
1550 case WM_QUERYENDSESSION:
1551 {
1552 return (1);
1553 }
1554
1555 case WM_INPUTLANGCHANGEREQUEST:
1556 {
1557 HKL NewHkl;
1558
1559 if(wParam & INPUTLANGCHANGE_BACKWARD
1560 && wParam & INPUTLANGCHANGE_FORWARD)
1561 {
1562 return FALSE;
1563 }
1564
1565 //FIXME: What to do with INPUTLANGCHANGE_SYSCHARSET ?
1566
1567 if(wParam & INPUTLANGCHANGE_BACKWARD) NewHkl = (HKL) HKL_PREV;
1568 else if(wParam & INPUTLANGCHANGE_FORWARD) NewHkl = (HKL) HKL_NEXT;
1569 else NewHkl = (HKL) lParam;
1570
1571 NtUserActivateKeyboardLayout(NewHkl, 0);
1572
1573 return TRUE;
1574 }
1575
1576 case WM_INPUTLANGCHANGE:
1577 {
1578 //FIXME: What to do?
1579 return TRUE;
1580 }
1581
1582 case WM_ENDSESSION:
1583 if (wParam) PostQuitMessage(0);
1584 return 0;
1585
1586 }
1587 return 0;
1588 }
1589
1590
1591 LRESULT STDCALL
1592 DefWindowProcA(HWND hWnd,
1593 UINT Msg,
1594 WPARAM wParam,
1595 LPARAM lParam)
1596 {
1597 LRESULT Result = 0;
1598
1599 SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam);
1600 switch (Msg)
1601 {
1602 case WM_NCCREATE:
1603 {
1604 ANSI_STRING AnsiString;
1605 UNICODE_STRING UnicodeString;
1606 LPCREATESTRUCTA cs = (LPCREATESTRUCTA)lParam;
1607 /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
1608 * may have child window IDs instead of window name */
1609
1610 if(cs->lpszName)
1611 {
1612 RtlInitAnsiString(&AnsiString, (LPSTR)cs->lpszName);
1613 RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
1614 NtUserDefSetText(hWnd, &UnicodeString);
1615 RtlFreeUnicodeString(&UnicodeString);
1616 }
1617 else
1618 NtUserDefSetText(hWnd, NULL);
1619
1620 Result = 1;
1621 break;
1622 }
1623
1624 case WM_GETTEXTLENGTH:
1625 {
1626 Result = (LRESULT)NtUserInternalGetWindowText(hWnd, NULL, 0);
1627 break;
1628 }
1629
1630 case WM_GETTEXT:
1631 {
1632 LPWSTR Buffer;
1633 LPSTR AnsiBuffer = (LPSTR)lParam;
1634 INT Length;
1635
1636 Buffer = HeapAlloc(GetProcessHeap(), 0, wParam * sizeof(WCHAR));
1637 if (!Buffer)
1638 {
1639 Result = 0;
1640 break;
1641 }
1642 Length = NtUserInternalGetWindowText(hWnd, Buffer, wParam);
1643 if (Length > 0 && wParam > 0 &&
1644 !WideCharToMultiByte(CP_ACP, 0, Buffer, -1,
1645 AnsiBuffer, wParam, NULL, NULL))
1646 {
1647 AnsiBuffer[0] = '\0';
1648 }
1649
1650 HeapFree(GetProcessHeap(), 0, Buffer);
1651
1652 Result = (LRESULT)Length;
1653 break;
1654 }
1655
1656 case WM_SETTEXT:
1657 {
1658 ANSI_STRING AnsiString;
1659 UNICODE_STRING UnicodeString;
1660
1661 if(lParam)
1662 {
1663 RtlInitAnsiString(&AnsiString, (LPSTR)lParam);
1664 RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
1665 NtUserDefSetText(hWnd, &UnicodeString);
1666 RtlFreeUnicodeString(&UnicodeString);
1667 }
1668 else
1669 NtUserDefSetText(hWnd, NULL);
1670
1671 if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
1672 {
1673 DefWndNCPaint(hWnd, (HRGN)1, -1);
1674 }
1675
1676 Result = 1;
1677 break;
1678 }
1679
1680 /* FIXME: Implement these. */
1681 case WM_IME_CHAR:
1682 case WM_IME_KEYDOWN:
1683 case WM_IME_KEYUP:
1684 case WM_IME_STARTCOMPOSITION:
1685 case WM_IME_COMPOSITION:
1686 case WM_IME_ENDCOMPOSITION:
1687 case WM_IME_SELECT:
1688 case WM_IME_SETCONTEXT:
1689 FIXME("FIXME: WM_IME_* conversion isn't implemented yet!");
1690 /* fall through */
1691 default:
1692 Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, FALSE);
1693 }
1694
1695 SPY_ExitMessage(SPY_RESULT_DEFWND, hWnd, Msg, Result, wParam, lParam);
1696 return Result;
1697 }
1698
1699
1700 LRESULT STDCALL
1701 DefWindowProcW(HWND hWnd,
1702 UINT Msg,
1703 WPARAM wParam,
1704 LPARAM lParam)
1705 {
1706 LRESULT Result = 0;
1707
1708 SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam);
1709 switch (Msg)
1710 {
1711 case WM_NCCREATE:
1712 {
1713 UNICODE_STRING UnicodeString;
1714 LPCREATESTRUCTW cs = (LPCREATESTRUCTW)lParam;
1715 /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
1716 * may have child window IDs instead of window name */
1717
1718 if(cs->lpszName)
1719 RtlInitUnicodeString(&UnicodeString, (LPWSTR)cs->lpszName);
1720
1721 NtUserDefSetText( hWnd, (cs->lpszName ? &UnicodeString : NULL));
1722 Result = 1;
1723 break;
1724 }
1725
1726 case WM_GETTEXTLENGTH:
1727 {
1728 Result = (LRESULT)NtUserInternalGetWindowText(hWnd, NULL, 0);
1729 break;
1730 }
1731
1732 case WM_GETTEXT:
1733 {
1734 Result = (LRESULT)NtUserInternalGetWindowText(hWnd, (PWSTR)lParam, wParam);
1735 break;
1736 }
1737
1738 case WM_SETTEXT:
1739 {
1740 UNICODE_STRING UnicodeString;
1741
1742 if(lParam)
1743 RtlInitUnicodeString(&UnicodeString, (LPWSTR)lParam);
1744
1745 NtUserDefSetText(hWnd, (lParam ? &UnicodeString : NULL));
1746
1747 if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
1748 {
1749 DefWndNCPaint(hWnd, (HRGN)1, -1);
1750 }
1751 Result = 1;
1752 break;
1753 }
1754
1755 case WM_IME_CHAR:
1756 {
1757 SendMessageW(hWnd, WM_CHAR, wParam, lParam);
1758 Result = 0;
1759 break;
1760 }
1761
1762 case WM_IME_SETCONTEXT:
1763 {
1764 /* FIXME */
1765 FIXME("FIXME: WM_IME_SETCONTEXT is not implemented!");
1766 Result = 0;
1767 break;
1768 }
1769
1770 default:
1771 Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, TRUE);
1772 }
1773 SPY_ExitMessage(SPY_RESULT_DEFWND, hWnd, Msg, Result, wParam, lParam);
1774
1775 return Result;
1776 }
1777