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