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