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