overrun of static array
[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_NCACTIVATE:
1036 {
1037 return DefWndNCActivate(hWnd, wParam);
1038 }
1039
1040 case WM_NCHITTEST:
1041 {
1042 POINT Point;
1043 Point.x = GET_X_LPARAM(lParam);
1044 Point.y = GET_Y_LPARAM(lParam);
1045 return (DefWndNCHitTest(hWnd, Point));
1046 }
1047
1048 case WM_LBUTTONDOWN:
1049 case WM_RBUTTONDOWN:
1050 case WM_MBUTTONDOWN:
1051 iF10Key = iMenuSysKey = 0;
1052 break;
1053
1054 case WM_NCLBUTTONDOWN:
1055 {
1056 return (DefWndNCLButtonDown(hWnd, wParam, lParam));
1057 }
1058
1059 case WM_LBUTTONDBLCLK:
1060 return (DefWndNCLButtonDblClk(hWnd, HTCLIENT, lParam));
1061
1062 case WM_NCLBUTTONDBLCLK:
1063 {
1064 return (DefWndNCLButtonDblClk(hWnd, wParam, lParam));
1065 }
1066
1067 case WM_WINDOWPOSCHANGING:
1068 {
1069 return (DefWndHandleWindowPosChanging(hWnd, (WINDOWPOS*)lParam));
1070 }
1071
1072 case WM_WINDOWPOSCHANGED:
1073 {
1074 return (DefWndHandleWindowPosChanged(hWnd, (WINDOWPOS*)lParam));
1075 }
1076
1077 case WM_NCRBUTTONDOWN:
1078 {
1079 /* in Windows, capture is taken when right-clicking on the caption bar */
1080 if (wParam == HTCAPTION)
1081 {
1082 SetCapture(hWnd);
1083 }
1084 break;
1085 }
1086
1087 case WM_RBUTTONUP:
1088 {
1089 POINT Pt;
1090 if (hWnd == GetCapture())
1091 {
1092 ReleaseCapture();
1093 }
1094 Pt.x = GET_X_LPARAM(lParam);
1095 Pt.y = GET_Y_LPARAM(lParam);
1096 ClientToScreen(hWnd, &Pt);
1097 lParam = MAKELPARAM(Pt.x, Pt.y);
1098 if (bUnicode)
1099 {
1100 SendMessageW(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
1101 }
1102 else
1103 {
1104 SendMessageA(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
1105 }
1106 break;
1107 }
1108
1109 case WM_NCRBUTTONUP:
1110 /*
1111 * FIXME : we must NOT send WM_CONTEXTMENU on a WM_NCRBUTTONUP (checked
1112 * in Windows), but what _should_ we do? According to MSDN :
1113 * "If it is appropriate to do so, the system sends the WM_SYSCOMMAND
1114 * message to the window". When is it appropriate?
1115 */
1116 break;
1117
1118 case WM_CONTEXTMENU:
1119 {
1120 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1121 {
1122 if (bUnicode)
1123 {
1124 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1125 }
1126 else
1127 {
1128 SendMessageA(GetParent(hWnd), WM_CONTEXTMENU, wParam, lParam);
1129 }
1130 }
1131 else
1132 {
1133 POINT Pt;
1134 DWORD Style;
1135 LONG HitCode;
1136
1137 Style = GetWindowLongW(hWnd, GWL_STYLE);
1138
1139 Pt.x = GET_X_LPARAM(lParam);
1140 Pt.y = GET_Y_LPARAM(lParam);
1141 if (Style & WS_CHILD)
1142 {
1143 ScreenToClient(GetParent(hWnd), &Pt);
1144 }
1145
1146 HitCode = DefWndNCHitTest(hWnd, Pt);
1147
1148 if (HitCode == HTCAPTION || HitCode == HTSYSMENU)
1149 {
1150 HMENU SystemMenu;
1151 UINT Flags;
1152
1153 if((SystemMenu = GetSystemMenu(hWnd, FALSE)))
1154 {
1155 MenuInitSysMenuPopup(SystemMenu, GetWindowLongW(hWnd, GWL_STYLE),
1156 GetClassLongW(hWnd, GCL_STYLE), HitCode);
1157
1158 if(HitCode == HTCAPTION)
1159 Flags = TPM_LEFTBUTTON | TPM_RIGHTBUTTON;
1160 else
1161 Flags = TPM_LEFTBUTTON;
1162
1163 TrackPopupMenu(SystemMenu, Flags,
1164 Pt.x, Pt.y, 0, hWnd, NULL);
1165 }
1166 }
1167 }
1168 break;
1169 }
1170
1171 case WM_PRINT:
1172 {
1173 DefWndPrint(hWnd, (HDC)wParam, lParam);
1174 return (0);
1175 }
1176
1177 case WM_PAINTICON:
1178 case WM_PAINT:
1179 {
1180 PAINTSTRUCT Ps;
1181 HDC hDC = BeginPaint(hWnd, &Ps);
1182 if (hDC)
1183 {
1184 HICON hIcon;
1185 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE &&
1186 (hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON)) != NULL)
1187 {
1188 RECT ClientRect;
1189 INT x, y;
1190 GetClientRect(hWnd, &ClientRect);
1191 x = (ClientRect.right - ClientRect.left -
1192 GetSystemMetrics(SM_CXICON)) / 2;
1193 y = (ClientRect.bottom - ClientRect.top -
1194 GetSystemMetrics(SM_CYICON)) / 2;
1195 DrawIcon(hDC, x, y, hIcon);
1196 }
1197 EndPaint(hWnd, &Ps);
1198 }
1199 return (0);
1200 }
1201
1202 case WM_SYNCPAINT:
1203 {
1204 HRGN hRgn;
1205 hRgn = CreateRectRgn(0, 0, 0, 0);
1206 if (GetUpdateRgn(hWnd, hRgn, FALSE) != NULLREGION)
1207 {
1208 RedrawWindow(hWnd, NULL, hRgn,
1209 RDW_ERASENOW | RDW_ERASE | RDW_FRAME |
1210 RDW_ALLCHILDREN);
1211 }
1212 DeleteObject(hRgn);
1213 return (0);
1214 }
1215
1216 case WM_SETREDRAW:
1217 {
1218 DefWndSetRedraw(hWnd, wParam);
1219 return (0);
1220 }
1221
1222 case WM_CLOSE:
1223 {
1224 DestroyWindow(hWnd);
1225 return (0);
1226 }
1227
1228 case WM_MOUSEACTIVATE:
1229 {
1230 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1231 {
1232 LONG Ret;
1233 if (bUnicode)
1234 {
1235 Ret = SendMessageW(GetParent(hWnd), WM_MOUSEACTIVATE,
1236 wParam, lParam);
1237 }
1238 else
1239 {
1240 Ret = SendMessageA(GetParent(hWnd), WM_MOUSEACTIVATE,
1241 wParam, lParam);
1242 }
1243 if (Ret)
1244 {
1245 return (Ret);
1246 }
1247 }
1248 return ((LOWORD(lParam) >= HTCLIENT) ? MA_ACTIVATE : MA_NOACTIVATE);
1249 }
1250
1251 case WM_ACTIVATE:
1252 {
1253 /* Check if the window is minimized. */
1254 if (LOWORD(wParam) != WA_INACTIVE &&
1255 !(GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE))
1256 {
1257 SetFocus(hWnd);
1258 }
1259 break;
1260 }
1261
1262 case WM_MOUSEWHEEL:
1263 {
1264 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1265 {
1266 if (bUnicode)
1267 {
1268 return (SendMessageW(GetParent(hWnd), WM_MOUSEWHEEL,
1269 wParam, lParam));
1270 }
1271 else
1272 {
1273 return (SendMessageA(GetParent(hWnd), WM_MOUSEWHEEL,
1274 wParam, lParam));
1275 }
1276 }
1277 break;
1278 }
1279
1280 case WM_ERASEBKGND:
1281 case WM_ICONERASEBKGND:
1282 {
1283 RECT Rect;
1284 HBRUSH hBrush = (HBRUSH)GetClassLongW(hWnd, GCL_HBRBACKGROUND);
1285
1286 if (NULL == hBrush)
1287 {
1288 return 0;
1289 }
1290 if (GetClassLongW(hWnd, GCL_STYLE) & CS_PARENTDC)
1291 {
1292 /* can't use GetClipBox with a parent DC or we fill the whole parent */
1293 GetClientRect(hWnd, &Rect);
1294 DPtoLP((HDC)wParam, (LPPOINT)&Rect, 2);
1295 }
1296 else
1297 {
1298 GetClipBox((HDC)wParam, &Rect);
1299 }
1300 FillRect((HDC)wParam, &Rect, hBrush);
1301 return (1);
1302 }
1303
1304 case WM_CTLCOLORMSGBOX:
1305 case WM_CTLCOLOREDIT:
1306 case WM_CTLCOLORLISTBOX:
1307 case WM_CTLCOLORBTN:
1308 case WM_CTLCOLORDLG:
1309 case WM_CTLCOLORSTATIC:
1310 case WM_CTLCOLORSCROLLBAR:
1311 return (LRESULT) DefWndControlColor((HDC)wParam, Msg - WM_CTLCOLORMSGBOX);
1312
1313 case WM_CTLCOLOR:
1314 return (LRESULT) DefWndControlColor((HDC)wParam, HIWORD(lParam));
1315
1316 case WM_SETCURSOR:
1317 {
1318 ULONG Style = GetWindowLongW(hWnd, GWL_STYLE);
1319
1320 if (Style & WS_CHILD)
1321 {
1322 if (LOWORD(lParam) < HTLEFT || LOWORD(lParam) > HTBOTTOMRIGHT)
1323 {
1324 BOOL bResult;
1325 if (bUnicode)
1326 {
1327 bResult = SendMessageW(GetParent(hWnd), WM_SETCURSOR,
1328 wParam, lParam);
1329 }
1330 else
1331 {
1332 bResult = SendMessageA(GetParent(hWnd), WM_SETCURSOR,
1333 wParam, lParam);
1334 }
1335 if (bResult)
1336 {
1337 return(TRUE);
1338 }
1339 }
1340 }
1341 return (DefWndHandleSetCursor(hWnd, wParam, lParam, Style));
1342 }
1343
1344 case WM_SYSCOMMAND:
1345 return (DefWndHandleSysCommand(hWnd, wParam, lParam));
1346
1347 case WM_KEYDOWN:
1348 if(wParam == VK_F10) iF10Key = VK_F10;
1349 break;
1350
1351 /* FIXME: This is also incomplete. */
1352 case WM_SYSKEYDOWN:
1353 {
1354 if (HIWORD(lParam) & KEYDATA_ALT)
1355 {
1356 /* if( HIWORD(lParam) & ~KEYDATA_PREVSTATE ) */
1357 if ( (wParam == VK_MENU || wParam == VK_LMENU
1358 || wParam == VK_RMENU) && !iMenuSysKey )
1359 iMenuSysKey = 1;
1360 else
1361 iMenuSysKey = 0;
1362
1363 iF10Key = 0;
1364
1365 if (wParam == VK_F4) /* Try to close the window */
1366 {
1367 HWND top = GetAncestor(hWnd, GA_ROOT);
1368 if (!(GetClassLongW(top, GCL_STYLE) & CS_NOCLOSE))
1369 {
1370 if (bUnicode)
1371 PostMessageW(top, WM_SYSCOMMAND, SC_CLOSE, 0);
1372 else
1373 PostMessageA(top, WM_SYSCOMMAND, SC_CLOSE, 0);
1374 }
1375 }
1376 else if (wParam == VK_SNAPSHOT)
1377 {
1378 HWND hwnd = hWnd;
1379 while (GetParent(hwnd) != NULL)
1380 {
1381 hwnd = GetParent(hwnd);
1382 }
1383 DefWndScreenshot(hwnd);
1384 }
1385 }
1386 else if( wParam == VK_F10 )
1387 iF10Key = 1;
1388 else if( wParam == VK_ESCAPE && (GetKeyState(VK_SHIFT) & 0x8000))
1389 SendMessageW( hWnd, WM_SYSCOMMAND, SC_KEYMENU, ' ' );
1390 break;
1391 }
1392
1393 case WM_KEYUP:
1394 case WM_SYSKEYUP:
1395 {
1396 /* Press and release F10 or ALT */
1397 if (((wParam == VK_MENU || wParam == VK_LMENU || wParam == VK_RMENU)
1398 && iMenuSysKey) || ((wParam == VK_F10) && iF10Key))
1399 SendMessageW( GetAncestor( hWnd, GA_ROOT ), WM_SYSCOMMAND, SC_KEYMENU, 0L );
1400 iMenuSysKey = iF10Key = 0;
1401 break;
1402 }
1403
1404 case WM_SYSCHAR:
1405 {
1406 iMenuSysKey = 0;
1407 if (wParam == '\r' && IsIconic(hWnd))
1408 {
1409 PostMessageW( hWnd, WM_SYSCOMMAND, SC_RESTORE, 0L );
1410 break;
1411 }
1412 if ((HIWORD(lParam) & KEYDATA_ALT) && wParam)
1413 {
1414 if (wParam == '\t' || wParam == '\x1b') break;
1415 if (wParam == ' ' && (GetWindowLongW( hWnd, GWL_STYLE ) & WS_CHILD))
1416 SendMessageW( GetParent(hWnd), Msg, wParam, lParam );
1417 else
1418 SendMessageW( hWnd, WM_SYSCOMMAND, SC_KEYMENU, wParam );
1419 }
1420 else /* check for Ctrl-Esc */
1421 if (wParam != '\x1b') MessageBeep(0);
1422 break;
1423 }
1424
1425 case WM_SHOWWINDOW:
1426 {
1427 if (lParam) // Call when it is necessary.
1428 NtUserMessageCall( hWnd, Msg, wParam, lParam, 0, FNID_DEFWINDOWPROC, FALSE);
1429 break;
1430 }
1431
1432 case WM_CANCELMODE:
1433 {
1434 iMenuSysKey = 0;
1435 /* FIXME: Check for a desktop. */
1436 if (!(GetWindowLongW( hWnd, GWL_STYLE ) & WS_CHILD)) EndMenu();
1437 if (GetCapture() == hWnd)
1438 {
1439 ReleaseCapture();
1440 }
1441 break;
1442 }
1443
1444 case WM_VKEYTOITEM:
1445 case WM_CHARTOITEM:
1446 return (-1);
1447 /*
1448 case WM_DROPOBJECT:
1449 return DRAG_FILE;
1450 */
1451 case WM_QUERYDROPOBJECT:
1452 {
1453 if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES)
1454 {
1455 return(1);
1456 }
1457 break;
1458 }
1459
1460 case WM_QUERYDRAGICON:
1461 {
1462 UINT Len;
1463 HICON hIcon;
1464
1465 hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON);
1466 if (hIcon)
1467 {
1468 return ((LRESULT)hIcon);
1469 }
1470 for (Len = 1; Len < 64; Len++)
1471 {
1472 if ((hIcon = LoadIconW(NULL, MAKEINTRESOURCEW(Len))) != NULL)
1473 {
1474 return((LRESULT)hIcon);
1475 }
1476 }
1477 return ((LRESULT)LoadIconW(0, IDI_APPLICATION));
1478 }
1479
1480 /* FIXME: WM_ISACTIVEICON */
1481
1482 case WM_NOTIFYFORMAT:
1483 {
1484 if (lParam == NF_QUERY)
1485 return IsWindowUnicode(hWnd) ? NFR_UNICODE : NFR_ANSI;
1486 break;
1487 }
1488
1489 case WM_SETICON:
1490 {
1491 INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
1492 HICON hOldIcon = (HICON)GetClassLongW(hWnd, Index);
1493 SetClassLongW(hWnd, Index, lParam);
1494 SetWindowPos(hWnd, 0, 0, 0, 0, 0,
1495 SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
1496 SWP_NOACTIVATE | SWP_NOZORDER);
1497 return ((LRESULT)hOldIcon);
1498 }
1499
1500 case WM_GETICON:
1501 {
1502 INT Index = (wParam == ICON_BIG) ? GCL_HICON : GCL_HICONSM;
1503 return (GetClassLongW(hWnd, Index));
1504 }
1505
1506 case WM_HELP:
1507 {
1508 if (bUnicode)
1509 {
1510 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1511 }
1512 else
1513 {
1514 SendMessageA(GetParent(hWnd), Msg, wParam, lParam);
1515 }
1516 break;
1517 }
1518
1519 case WM_SYSTIMER:
1520 {
1521 THRDCARETINFO CaretInfo;
1522 switch(wParam)
1523 {
1524 case 0xffff: /* Caret timer */
1525 /* switch showing byte in win32k and get information about the caret */
1526 if(NtUserSwitchCaretShowing(&CaretInfo) && (CaretInfo.hWnd == hWnd))
1527 {
1528 DrawCaret(hWnd, &CaretInfo);
1529 }
1530 break;
1531 }
1532 break;
1533 }
1534
1535 case WM_QUERYOPEN:
1536 case WM_QUERYENDSESSION:
1537 {
1538 return (1);
1539 }
1540
1541 case WM_INPUTLANGCHANGEREQUEST:
1542 {
1543 HKL NewHkl;
1544
1545 if(wParam & INPUTLANGCHANGE_BACKWARD
1546 && wParam & INPUTLANGCHANGE_FORWARD)
1547 {
1548 return FALSE;
1549 }
1550
1551 //FIXME: What to do with INPUTLANGCHANGE_SYSCHARSET ?
1552
1553 if(wParam & INPUTLANGCHANGE_BACKWARD) NewHkl = (HKL) HKL_PREV;
1554 else if(wParam & INPUTLANGCHANGE_FORWARD) NewHkl = (HKL) HKL_NEXT;
1555 else NewHkl = (HKL) lParam;
1556
1557 NtUserActivateKeyboardLayout(NewHkl, 0);
1558
1559 return TRUE;
1560 }
1561
1562 case WM_INPUTLANGCHANGE:
1563 {
1564 //FIXME: What to do?
1565 return TRUE;
1566 }
1567
1568 case WM_ENDSESSION:
1569 if (wParam) PostQuitMessage(0);
1570 return 0;
1571
1572 case WM_QUERYUISTATE:
1573 {
1574 LRESULT Ret = 0;
1575 PWINDOW Wnd = ValidateHwnd(hWnd);
1576 if (Wnd != NULL)
1577 {
1578 if (Wnd->HideFocus)
1579 Ret |= UISF_HIDEFOCUS;
1580 if (Wnd->HideAccel)
1581 Ret |= UISF_HIDEACCEL;
1582 }
1583 return Ret;
1584 }
1585
1586 case WM_CHANGEUISTATE:
1587 {
1588 BOOL AlwaysShowCues = TRUE;
1589 WORD Action = LOWORD(wParam);
1590 WORD Flags = HIWORD(wParam);
1591 PWINDOW Wnd;
1592
1593 SystemParametersInfoW(SPI_GETKEYBOARDCUES, 0, &AlwaysShowCues, 0);
1594 if (AlwaysShowCues)
1595 break;
1596
1597 Wnd= ValidateHwnd(hWnd);
1598 if (!Wnd || lParam != 0)
1599 break;
1600
1601 if (Flags & ~(UISF_HIDEFOCUS | UISF_HIDEACCEL | UISF_ACTIVE))
1602 break;
1603
1604 if (Flags & UISF_ACTIVE)
1605 {
1606 WARN("WM_CHANGEUISTATE does not yet support UISF_ACTIVE!\n");
1607 }
1608
1609 if (Action == UIS_INITIALIZE)
1610 {
1611 PDESKTOP Desk = GetThreadDesktopInfo();
1612 if (Desk == NULL)
1613 break;
1614
1615 Action = Desk->LastInputWasKbd ? UIS_CLEAR : UIS_SET;
1616 Flags = UISF_HIDEFOCUS | UISF_HIDEACCEL;
1617
1618 /* We need to update wParam in case we need to send out messages */
1619 wParam = MAKEWPARAM(Action, Flags);
1620 }
1621
1622 switch (Action)
1623 {
1624 case UIS_SET:
1625 /* See if we actually need to change something */
1626 if ((Flags & UISF_HIDEFOCUS) && !Wnd->HideFocus)
1627 break;
1628 if ((Flags & UISF_HIDEACCEL) && !Wnd->HideAccel)
1629 break;
1630
1631 /* Don't need to do anything... */
1632 return 0;
1633
1634 case UIS_CLEAR:
1635 /* See if we actually need to change something */
1636 if ((Flags & UISF_HIDEFOCUS) && Wnd->HideFocus)
1637 break;
1638 if ((Flags & UISF_HIDEACCEL) && Wnd->HideAccel)
1639 break;
1640
1641 /* Don't need to do anything... */
1642 return 0;
1643
1644 default:
1645 WARN("WM_CHANGEUISTATE: Unsupported Action 0x%x\n", Action);
1646 break;
1647 }
1648
1649 if ((Wnd->Style & WS_CHILD) && Wnd->Parent != NULL)
1650 {
1651 /* We're a child window and we need to pass this message down until
1652 we reach the root */
1653 hWnd = UserHMGetHandle((PWINDOW)DesktopPtrToUser(Wnd->Parent));
1654 }
1655 else
1656 {
1657 /* We're a top level window, we need to change the UI state */
1658 Msg = WM_UPDATEUISTATE;
1659 }
1660
1661 if (bUnicode)
1662 return SendMessageW(hWnd, Msg, wParam, lParam);
1663 else
1664 return SendMessageA(hWnd, Msg, wParam, lParam);
1665 }
1666
1667 case WM_UPDATEUISTATE:
1668 {
1669 BOOL Change = TRUE;
1670 BOOL AlwaysShowCues = TRUE;
1671 WORD Action = LOWORD(wParam);
1672 WORD Flags = HIWORD(wParam);
1673 PWINDOW Wnd;
1674
1675 SystemParametersInfoW(SPI_GETKEYBOARDCUES, 0, &AlwaysShowCues, 0);
1676 if (AlwaysShowCues)
1677 break;
1678
1679 Wnd = ValidateHwnd(hWnd);
1680 if (!Wnd || lParam != 0)
1681 break;
1682
1683 if (Flags & ~(UISF_HIDEFOCUS | UISF_HIDEACCEL | UISF_ACTIVE))
1684 break;
1685
1686 if (Flags & UISF_ACTIVE)
1687 {
1688 WARN("WM_UPDATEUISTATE does not yet support UISF_ACTIVE!\n");
1689 }
1690
1691 if (Action == UIS_INITIALIZE)
1692 {
1693 PDESKTOP Desk = GetThreadDesktopInfo();
1694 if (Desk == NULL)
1695 break;
1696
1697 Action = Desk->LastInputWasKbd ? UIS_CLEAR : UIS_SET;
1698 Flags = UISF_HIDEFOCUS | UISF_HIDEACCEL;
1699
1700 /* We need to update wParam for broadcasting the update */
1701 wParam = MAKEWPARAM(Action, Flags);
1702 }
1703
1704 switch (Action)
1705 {
1706 case UIS_SET:
1707 /* See if we actually need to change something */
1708 if ((Flags & UISF_HIDEFOCUS) && !Wnd->HideFocus)
1709 break;
1710 if ((Flags & UISF_HIDEACCEL) && !Wnd->HideAccel)
1711 break;
1712
1713 /* Don't need to do anything... */
1714 Change = FALSE;
1715 break;
1716
1717 case UIS_CLEAR:
1718 /* See if we actually need to change something */
1719 if ((Flags & UISF_HIDEFOCUS) && Wnd->HideFocus)
1720 break;
1721 if ((Flags & UISF_HIDEACCEL) && Wnd->HideAccel)
1722 break;
1723
1724 /* Don't need to do anything... */
1725 Change = FALSE;
1726 break;
1727
1728 default:
1729 WARN("WM_UPDATEUISTATE: Unsupported Action 0x%x\n", Action);
1730 return 0;
1731 }
1732
1733 /* Pack the information and call win32k */
1734 if (Change)
1735 {
1736 if (!NtUserCallTwoParam((DWORD)hWnd, (DWORD)Flags | ((DWORD)Action << 3), TWOPARAM_ROUTINE_ROS_UPDATEUISTATE))
1737 break;
1738 }
1739
1740 /* Always broadcast the update to all children */
1741 EnumChildWindows(hWnd,
1742 UserSendUiUpdateMsg,
1743 (LPARAM)wParam);
1744
1745 break;
1746 }
1747
1748 }
1749 return 0;
1750 }
1751
1752
1753 LRESULT STDCALL
1754 DefWindowProcA(HWND hWnd,
1755 UINT Msg,
1756 WPARAM wParam,
1757 LPARAM lParam)
1758 {
1759 LRESULT Result = 0;
1760 PWINDOW Wnd;
1761
1762 SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam);
1763 switch (Msg)
1764 {
1765 case WM_NCCREATE:
1766 {
1767 ANSI_STRING AnsiString;
1768 UNICODE_STRING UnicodeString;
1769 LPCREATESTRUCTA cs = (LPCREATESTRUCTA)lParam;
1770 /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
1771 * may have child window IDs instead of window name */
1772
1773 if(cs->lpszName)
1774 {
1775 RtlInitAnsiString(&AnsiString, (LPSTR)cs->lpszName);
1776 RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
1777 NtUserDefSetText(hWnd, &UnicodeString);
1778 RtlFreeUnicodeString(&UnicodeString);
1779 }
1780 else
1781 NtUserDefSetText(hWnd, NULL);
1782
1783 Result = 1;
1784 break;
1785 }
1786
1787 case WM_GETTEXTLENGTH:
1788 {
1789 PWSTR buf;
1790 ULONG len;
1791
1792 Wnd = ValidateHwnd(hWnd);
1793 if (Wnd != NULL && Wnd->WindowName.Length != 0)
1794 {
1795 buf = DesktopPtrToUser(Wnd->WindowName.Buffer);
1796 if (buf != NULL &&
1797 NT_SUCCESS(RtlUnicodeToMultiByteSize(&len,
1798 buf,
1799 Wnd->WindowName.Length)))
1800 {
1801 Result = (LRESULT)len;
1802 }
1803 }
1804 break;
1805 }
1806
1807 case WM_GETTEXT:
1808 {
1809 PWSTR buf = NULL;
1810 PSTR outbuf = (PSTR)lParam;
1811 UINT copy;
1812
1813 Wnd = ValidateHwnd(hWnd);
1814 if (Wnd != NULL && wParam != 0)
1815 {
1816 if (Wnd->WindowName.Buffer != NULL)
1817 buf = DesktopPtrToUser(Wnd->WindowName.Buffer);
1818 else
1819 outbuf[0] = L'\0';
1820
1821 if (buf != NULL)
1822 {
1823 if (Wnd->WindowName.Length != 0)
1824 {
1825 copy = min(Wnd->WindowName.Length / sizeof(WCHAR), wParam - 1);
1826 Result = WideCharToMultiByte(CP_ACP,
1827 0,
1828 buf,
1829 copy,
1830 outbuf,
1831 wParam,
1832 NULL,
1833 NULL);
1834 outbuf[Result] = '\0';
1835 }
1836 else
1837 outbuf[0] = '\0';
1838 }
1839 }
1840 break;
1841 }
1842
1843 case WM_SETTEXT:
1844 {
1845 ANSI_STRING AnsiString;
1846 UNICODE_STRING UnicodeString;
1847
1848 if(lParam)
1849 {
1850 RtlInitAnsiString(&AnsiString, (LPSTR)lParam);
1851 RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
1852 NtUserDefSetText(hWnd, &UnicodeString);
1853 RtlFreeUnicodeString(&UnicodeString);
1854 }
1855 else
1856 NtUserDefSetText(hWnd, NULL);
1857
1858 if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
1859 {
1860 DefWndNCPaint(hWnd, (HRGN)1, -1);
1861 }
1862
1863 Result = 1;
1864 break;
1865 }
1866
1867 /* FIXME: Implement these. */
1868 case WM_IME_CHAR:
1869 case WM_IME_KEYDOWN:
1870 case WM_IME_KEYUP:
1871 case WM_IME_STARTCOMPOSITION:
1872 case WM_IME_COMPOSITION:
1873 case WM_IME_ENDCOMPOSITION:
1874 case WM_IME_SELECT:
1875 case WM_IME_SETCONTEXT:
1876 FIXME("FIXME: WM_IME_* conversion isn't implemented yet!");
1877 /* fall through */
1878 default:
1879 Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, FALSE);
1880 }
1881
1882 SPY_ExitMessage(SPY_RESULT_DEFWND, hWnd, Msg, Result, wParam, lParam);
1883 return Result;
1884 }
1885
1886
1887 LRESULT STDCALL
1888 DefWindowProcW(HWND hWnd,
1889 UINT Msg,
1890 WPARAM wParam,
1891 LPARAM lParam)
1892 {
1893 LRESULT Result = 0;
1894 PWINDOW Wnd;
1895
1896 SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam);
1897 switch (Msg)
1898 {
1899 case WM_NCCREATE:
1900 {
1901 UNICODE_STRING UnicodeString;
1902 LPCREATESTRUCTW cs = (LPCREATESTRUCTW)lParam;
1903 /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
1904 * may have child window IDs instead of window name */
1905
1906 if(cs->lpszName)
1907 RtlInitUnicodeString(&UnicodeString, (LPWSTR)cs->lpszName);
1908
1909 NtUserDefSetText( hWnd, (cs->lpszName ? &UnicodeString : NULL));
1910 Result = 1;
1911 break;
1912 }
1913
1914 case WM_GETTEXTLENGTH:
1915 {
1916 PWSTR buf;
1917 ULONG len;
1918
1919 Wnd = ValidateHwnd(hWnd);
1920 if (Wnd != NULL && Wnd->WindowName.Length != 0)
1921 {
1922 buf = DesktopPtrToUser(Wnd->WindowName.Buffer);
1923 if (buf != NULL &&
1924 NT_SUCCESS(RtlUnicodeToMultiByteSize(&len,
1925 buf,
1926 Wnd->WindowName.Length)))
1927 {
1928 Result = (LRESULT)len;
1929 }
1930 }
1931 break;
1932 }
1933
1934 case WM_GETTEXT:
1935 {
1936 PWSTR buf = NULL;
1937 PWSTR outbuf = (PWSTR)lParam;
1938
1939 Wnd = ValidateHwnd(hWnd);
1940 if (Wnd != NULL && wParam != 0)
1941 {
1942 if (Wnd->WindowName.Buffer != NULL)
1943 buf = DesktopPtrToUser(Wnd->WindowName.Buffer);
1944 else
1945 outbuf[0] = L'\0';
1946
1947 if (buf != NULL)
1948 {
1949 if (Wnd->WindowName.Length != 0)
1950 {
1951 Result = min(Wnd->WindowName.Length / sizeof(WCHAR), wParam - 1);
1952 RtlCopyMemory(outbuf,
1953 buf,
1954 Result * sizeof(WCHAR));
1955 outbuf[Result] = L'\0';
1956 }
1957 else
1958 outbuf[0] = L'\0';
1959 }
1960 }
1961 break;
1962 }
1963
1964 case WM_SETTEXT:
1965 {
1966 UNICODE_STRING UnicodeString;
1967
1968 if(lParam)
1969 RtlInitUnicodeString(&UnicodeString, (LPWSTR)lParam);
1970
1971 NtUserDefSetText(hWnd, (lParam ? &UnicodeString : NULL));
1972
1973 if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
1974 {
1975 DefWndNCPaint(hWnd, (HRGN)1, -1);
1976 }
1977 Result = 1;
1978 break;
1979 }
1980
1981 case WM_IME_CHAR:
1982 {
1983 SendMessageW(hWnd, WM_CHAR, wParam, lParam);
1984 Result = 0;
1985 break;
1986 }
1987
1988 case WM_IME_SETCONTEXT:
1989 {
1990 /* FIXME */
1991 FIXME("FIXME: WM_IME_SETCONTEXT is not implemented!");
1992 Result = 0;
1993 break;
1994 }
1995
1996 default:
1997 Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, TRUE);
1998 }
1999 SPY_ExitMessage(SPY_RESULT_DEFWND, hWnd, Msg, Result, wParam, lParam);
2000
2001 return Result;
2002 }
2003