make does like tabs, right? Fix build.
[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 (void)NtUserSetGUIThreadHandle(MSQ_STATE_MOVESIZE, NULL);
670 SendMessageA( hwnd, WM_EXITSIZEMOVE, 0, 0 );
671 SendMessageA( hwnd, WM_SETVISIBLE, !IsIconic(hwnd), 0L);
672
673 /* window moved or resized */
674 if (moved)
675 {
676 /* if the moving/resizing isn't canceled call SetWindowPos
677 * with the new position or the new size of the window
678 */
679 if (!((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) )
680 {
681 /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
682 if(!DragFullWindows)
683 SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
684 sizingRect.right - sizingRect.left,
685 sizingRect.bottom - sizingRect.top,
686 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
687 }
688 else { /* restore previous size/position */
689 if(DragFullWindows)
690 SetWindowPos( hwnd, 0, origRect.left, origRect.top,
691 origRect.right - origRect.left,
692 origRect.bottom - origRect.top,
693 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
694 }
695 }
696
697 if( IsWindow(hwnd) )
698 if( Style & WS_MINIMIZE )
699 {
700 /* Single click brings up the system menu when iconized */
701
702 if( !moved )
703 {
704 if( Style & WS_SYSMENU )
705 SendMessageA( hwnd, WM_SYSCOMMAND,
706 SC_MOUSEMENU + HTSYSMENU, MAKELONG(pt.x,pt.y));
707 }
708 }
709 }
710
711
712 /***********************************************************************
713 * DefWndTrackScrollBar
714 *
715 * Track a mouse button press on the horizontal or vertical scroll-bar.
716 */
717 static VOID
718 DefWndTrackScrollBar(HWND Wnd, WPARAM wParam, POINT Pt)
719 {
720 INT ScrollBar;
721
722 if (SC_HSCROLL == (wParam & 0xfff0))
723 {
724 if (HTHSCROLL != (wParam & 0x0f))
725 {
726 return;
727 }
728 ScrollBar = SB_HORZ;
729 }
730 else /* SC_VSCROLL */
731 {
732 if (HTVSCROLL != (wParam & 0x0f))
733 {
734 return;
735 }
736 ScrollBar = SB_VERT;
737 }
738 ScrollTrackScrollBar(Wnd, ScrollBar, Pt );
739 }
740
741
742 LRESULT
743 DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
744 {
745 // WINDOWPLACEMENT wp;
746 POINT Pt;
747
748 // ATM, This is for Hook call.
749 if (NtUserMessageCall( hWnd, WM_SYSCOMMAND, wParam, lParam, 0, NUMC_DEFWINDOWPROC, FALSE))
750 return 0;
751
752 switch (wParam & 0xfff0)
753 {
754 case SC_MOVE:
755 case SC_SIZE:
756 DefWndDoSizeMove(hWnd, wParam);
757 break;
758 case SC_MINIMIZE:
759 FIXME("SysCommand SC_MINIMIZE\n");
760 /* wp.length = sizeof(WINDOWPLACEMENT);
761 if(GetWindowPlacement(hWnd, &wp))
762 {
763 wp.showCmd = SW_MINIMIZE;
764 SetWindowPlacement(hWnd, &wp);
765 }*/
766 if (hWnd == GetForegroundWindow())
767 ShowOwnedPopups(hWnd,FALSE);
768 ShowWindow( hWnd, SW_MINIMIZE );
769 break;
770 case SC_MAXIMIZE:
771 FIXME("SysCommand SC_MAXIMIZE\n");
772 /* wp.length = sizeof(WINDOWPLACEMENT);
773 if(GetWindowPlacement(hWnd, &wp))
774 {
775 wp.showCmd = SW_MAXIMIZE;
776 SetWindowPlacement(hWnd, &wp);
777 }*/
778 if (IsIconic(hWnd) && hWnd == GetForegroundWindow())
779 ShowOwnedPopups(hWnd,TRUE);
780 ShowWindow( hWnd, SW_MAXIMIZE );
781 break;
782 case SC_RESTORE:
783 FIXME("SysCommand SC_RESTORE\n");
784 /* wp.length = sizeof(WINDOWPLACEMENT);
785 if(GetWindowPlacement(hWnd, &wp))
786 {
787 wp.showCmd = SW_RESTORE;
788 SetWindowPlacement(hWnd, &wp);
789 }*/
790 if (IsIconic(hWnd) && hWnd == GetForegroundWindow())
791 ShowOwnedPopups(hWnd,TRUE);
792 ShowWindow( hWnd, SW_RESTORE );
793 break;
794 case SC_CLOSE:
795 SendMessageA(hWnd, WM_CLOSE, 0, 0);
796 break;
797 case SC_MOUSEMENU:
798 {
799 Pt.x = (short)LOWORD(lParam);
800 Pt.y = (short)HIWORD(lParam);
801 MenuTrackMouseMenuBar(hWnd, wParam & 0x000f, Pt);
802 }
803 break;
804 case SC_KEYMENU:
805 MenuTrackKbdMenuBar(hWnd, wParam, (WCHAR)lParam);
806 break;
807 case SC_VSCROLL:
808 case SC_HSCROLL:
809 {
810 Pt.x = (short)LOWORD(lParam);
811 Pt.y = (short)HIWORD(lParam);
812 DefWndTrackScrollBar(hWnd, wParam, Pt);
813 }
814 break;
815
816 default:
817 /* FIXME: Implement */
818 UNIMPLEMENTED;
819 break;
820 }
821
822 return(0);
823 }
824
825 LRESULT
826 DefWndHandleWindowPosChanging(HWND hWnd, WINDOWPOS* Pos)
827 {
828 POINT maxTrack, minTrack;
829 LONG style = GetWindowLongA(hWnd, GWL_STYLE);
830
831 if (Pos->flags & SWP_NOSIZE) return 0;
832 if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
833 {
834 WinPosGetMinMaxInfo(hWnd, NULL, NULL, &minTrack, &maxTrack);
835 Pos->cx = min(Pos->cx, maxTrack.x);
836 Pos->cy = min(Pos->cy, maxTrack.y);
837 if (!(style & WS_MINIMIZE))
838 {
839 if (Pos->cx < minTrack.x) Pos->cx = minTrack.x;
840 if (Pos->cy < minTrack.y) Pos->cy = minTrack.y;
841 }
842 }
843 else
844 {
845 Pos->cx = max(Pos->cx, 0);
846 Pos->cy = max(Pos->cy, 0);
847 }
848 return 0;
849 }
850
851 /* Undocumented flags. */
852 #define SWP_NOCLIENTMOVE 0x0800
853 #define SWP_NOCLIENTSIZE 0x1000
854
855 LRESULT
856 DefWndHandleWindowPosChanged(HWND hWnd, WINDOWPOS* Pos)
857 {
858 RECT Rect;
859
860 GetClientRect(hWnd, &Rect);
861 MapWindowPoints(hWnd, (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD ?
862 GetParent(hWnd) : NULL), (LPPOINT) &Rect, 2);
863
864 if (! (Pos->flags & SWP_NOCLIENTMOVE))
865 {
866 SendMessageW(hWnd, WM_MOVE, 0, MAKELONG(Rect.left, Rect.top));
867 }
868
869 if (! (Pos->flags & SWP_NOCLIENTSIZE))
870 {
871 WPARAM wp = SIZE_RESTORED;
872 if (IsZoomed(hWnd))
873 {
874 wp = SIZE_MAXIMIZED;
875 }
876 else if (IsIconic(hWnd))
877 {
878 wp = SIZE_MINIMIZED;
879 }
880 SendMessageW(hWnd, WM_SIZE, wp,
881 MAKELONG(Rect.right - Rect.left, Rect.bottom - Rect.top));
882 }
883
884 return 0;
885 }
886
887 /***********************************************************************
888 * DefWndControlColor
889 *
890 * Default colors for control painting.
891 */
892 HBRUSH
893 DefWndControlColor(HDC hDC, UINT ctlType)
894 {
895 if (CTLCOLOR_SCROLLBAR == ctlType)
896 {
897 HBRUSH hb = GetSysColorBrush(COLOR_SCROLLBAR);
898 COLORREF bk = GetSysColor(COLOR_3DHILIGHT);
899 SetTextColor(hDC, GetSysColor(COLOR_3DFACE));
900 SetBkColor(hDC, bk);
901
902 /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
903 * we better use 0x55aa bitmap brush to make scrollbar's background
904 * look different from the window background.
905 */
906 if (bk == GetSysColor(COLOR_WINDOW))
907 {
908 static const WORD wPattern55AA[] =
909 {
910 0x5555, 0xaaaa, 0x5555, 0xaaaa,
911 0x5555, 0xaaaa, 0x5555, 0xaaaa
912 };
913 static HBITMAP hPattern55AABitmap = NULL;
914 static HBRUSH hPattern55AABrush = NULL;
915 if (hPattern55AABrush == NULL)
916 {
917 hPattern55AABitmap = CreateBitmap(8, 8, 1, 1, wPattern55AA);
918 hPattern55AABrush = CreatePatternBrush(hPattern55AABitmap);
919 }
920 return hPattern55AABrush;
921 }
922 UnrealizeObject(hb);
923 return hb;
924 }
925
926 SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
927
928 if ((CTLCOLOR_EDIT == ctlType) || (CTLCOLOR_LISTBOX == ctlType))
929 {
930 SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
931 }
932 else
933 {
934 SetBkColor(hDC, GetSysColor(COLOR_3DFACE));
935 return GetSysColorBrush(COLOR_3DFACE);
936 }
937
938 return GetSysColorBrush(COLOR_WINDOW);
939 }
940
941 static void DefWndPrint( HWND hwnd, HDC hdc, ULONG uFlags)
942 {
943 /*
944 * Visibility flag.
945 */
946 if ( (uFlags & PRF_CHECKVISIBLE) &&
947 !IsWindowVisible(hwnd) )
948 return;
949
950 /*
951 * Unimplemented flags.
952 */
953 if ( (uFlags & PRF_CHILDREN) ||
954 (uFlags & PRF_OWNED) ||
955 (uFlags & PRF_NONCLIENT) )
956 {
957 FIXME("WM_PRINT message with unsupported flags\n");
958 }
959
960 /*
961 * Background
962 */
963 if ( uFlags & PRF_ERASEBKGND)
964 SendMessageW(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
965
966 /*
967 * Client area
968 */
969 if ( uFlags & PRF_CLIENT)
970 SendMessageW(hwnd, WM_PRINTCLIENT, (WPARAM)hdc, PRF_CLIENT);
971 }
972
973 static BOOL CALLBACK
974 UserSendUiUpdateMsg(HWND hwnd, LPARAM lParam)
975 {
976 SendMessageW(hwnd, WM_UPDATEUISTATE, (WPARAM)lParam, 0);
977 return TRUE;
978 }
979
980
981 VOID FASTCALL
982 DefWndScreenshot(HWND hWnd)
983 {
984 RECT rect;
985 HDC hdc;
986 INT w;
987 INT h;
988 HBITMAP hbitmap;
989 HDC hdc2;
990
991 OpenClipboard(hWnd);
992 EmptyClipboard();
993
994 hdc = GetWindowDC(hWnd);
995 GetWindowRect(hWnd, &rect);
996 w = rect.right - rect.left;
997 h = rect.bottom - rect.top;
998
999 hbitmap = CreateCompatibleBitmap(hdc, w, h);
1000 hdc2 = CreateCompatibleDC(hdc);
1001 SelectObject(hdc2, hbitmap);
1002
1003 BitBlt(hdc2, 0, 0, w, h,
1004 hdc, 0, 0,
1005 SRCCOPY);
1006
1007 SetClipboardData(CF_BITMAP, hbitmap);
1008
1009 ReleaseDC(hWnd, hdc);
1010 ReleaseDC(hWnd, hdc2);
1011
1012 CloseClipboard();
1013
1014 }
1015
1016
1017
1018 LRESULT STDCALL
1019 User32DefWindowProc(HWND hWnd,
1020 UINT Msg,
1021 WPARAM wParam,
1022 LPARAM lParam,
1023 BOOL bUnicode)
1024 {
1025 switch (Msg)
1026 {
1027 case WM_NCPAINT:
1028 {
1029 return DefWndNCPaint(hWnd, (HRGN)wParam, -1);
1030 }
1031
1032 case WM_NCCALCSIZE:
1033 {
1034 return DefWndNCCalcSize(hWnd, (BOOL)wParam, (RECT*)lParam);
1035 }
1036
1037 case WM_NCACTIVATE:
1038 {
1039 return DefWndNCActivate(hWnd, wParam);
1040 }
1041
1042 case WM_NCHITTEST:
1043 {
1044 POINT Point;
1045 Point.x = GET_X_LPARAM(lParam);
1046 Point.y = GET_Y_LPARAM(lParam);
1047 return (DefWndNCHitTest(hWnd, Point));
1048 }
1049
1050 case WM_LBUTTONDOWN:
1051 case WM_RBUTTONDOWN:
1052 case WM_MBUTTONDOWN:
1053 iF10Key = iMenuSysKey = 0;
1054 break;
1055
1056 case WM_NCLBUTTONDOWN:
1057 {
1058 return (DefWndNCLButtonDown(hWnd, wParam, lParam));
1059 }
1060
1061 case WM_LBUTTONDBLCLK:
1062 return (DefWndNCLButtonDblClk(hWnd, HTCLIENT, lParam));
1063
1064 case WM_NCLBUTTONDBLCLK:
1065 {
1066 return (DefWndNCLButtonDblClk(hWnd, wParam, lParam));
1067 }
1068
1069 case WM_WINDOWPOSCHANGING:
1070 {
1071 return (DefWndHandleWindowPosChanging(hWnd, (WINDOWPOS*)lParam));
1072 }
1073
1074 case WM_WINDOWPOSCHANGED:
1075 {
1076 return (DefWndHandleWindowPosChanged(hWnd, (WINDOWPOS*)lParam));
1077 }
1078
1079 case WM_NCRBUTTONDOWN:
1080 {
1081 /* in Windows, capture is taken when right-clicking on the caption bar */
1082 if (wParam == HTCAPTION)
1083 {
1084 SetCapture(hWnd);
1085 }
1086 break;
1087 }
1088
1089 case WM_RBUTTONUP:
1090 {
1091 POINT Pt;
1092 if (hWnd == GetCapture())
1093 {
1094 ReleaseCapture();
1095 }
1096 Pt.x = GET_X_LPARAM(lParam);
1097 Pt.y = GET_Y_LPARAM(lParam);
1098 ClientToScreen(hWnd, &Pt);
1099 lParam = MAKELPARAM(Pt.x, Pt.y);
1100 if (bUnicode)
1101 {
1102 SendMessageW(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
1103 }
1104 else
1105 {
1106 SendMessageA(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
1107 }
1108 break;
1109 }
1110
1111 case WM_NCRBUTTONUP:
1112 /*
1113 * FIXME : we must NOT send WM_CONTEXTMENU on a WM_NCRBUTTONUP (checked
1114 * in Windows), but what _should_ we do? According to MSDN :
1115 * "If it is appropriate to do so, the system sends the WM_SYSCOMMAND
1116 * message to the window". When is it appropriate?
1117 */
1118 break;
1119
1120 case WM_CONTEXTMENU:
1121 {
1122 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1123 {
1124 if (bUnicode)
1125 {
1126 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1127 }
1128 else
1129 {
1130 SendMessageA(GetParent(hWnd), WM_CONTEXTMENU, wParam, lParam);
1131 }
1132 }
1133 else
1134 {
1135 POINT Pt;
1136 DWORD Style;
1137 LONG HitCode;
1138
1139 Style = GetWindowLongW(hWnd, GWL_STYLE);
1140
1141 Pt.x = GET_X_LPARAM(lParam);
1142 Pt.y = GET_Y_LPARAM(lParam);
1143 if (Style & WS_CHILD)
1144 {
1145 ScreenToClient(GetParent(hWnd), &Pt);
1146 }
1147
1148 HitCode = DefWndNCHitTest(hWnd, Pt);
1149
1150 if (HitCode == HTCAPTION || HitCode == HTSYSMENU)
1151 {
1152 HMENU SystemMenu;
1153 UINT Flags;
1154
1155 if((SystemMenu = GetSystemMenu(hWnd, FALSE)))
1156 {
1157 MenuInitSysMenuPopup(SystemMenu, GetWindowLongW(hWnd, GWL_STYLE),
1158 GetClassLongW(hWnd, GCL_STYLE), HitCode);
1159
1160 if(HitCode == HTCAPTION)
1161 Flags = TPM_LEFTBUTTON | TPM_RIGHTBUTTON;
1162 else
1163 Flags = TPM_LEFTBUTTON;
1164
1165 TrackPopupMenu(SystemMenu, Flags,
1166 Pt.x, Pt.y, 0, hWnd, NULL);
1167 }
1168 }
1169 }
1170 break;
1171 }
1172
1173 case WM_PRINT:
1174 {
1175 DefWndPrint(hWnd, (HDC)wParam, lParam);
1176 return (0);
1177 }
1178
1179 case WM_PAINTICON:
1180 case WM_PAINT:
1181 {
1182 PAINTSTRUCT Ps;
1183 HDC hDC = BeginPaint(hWnd, &Ps);
1184 if (hDC)
1185 {
1186 HICON hIcon;
1187 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE &&
1188 (hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON)) != NULL)
1189 {
1190 RECT ClientRect;
1191 INT x, y;
1192 GetClientRect(hWnd, &ClientRect);
1193 x = (ClientRect.right - ClientRect.left -
1194 GetSystemMetrics(SM_CXICON)) / 2;
1195 y = (ClientRect.bottom - ClientRect.top -
1196 GetSystemMetrics(SM_CYICON)) / 2;
1197 DrawIcon(hDC, x, y, hIcon);
1198 }
1199 EndPaint(hWnd, &Ps);
1200 }
1201 return (0);
1202 }
1203
1204 case WM_SYNCPAINT:
1205 {
1206 HRGN hRgn;
1207 hRgn = CreateRectRgn(0, 0, 0, 0);
1208 if (GetUpdateRgn(hWnd, hRgn, FALSE) != NULLREGION)
1209 {
1210 RedrawWindow(hWnd, NULL, hRgn,
1211 RDW_ERASENOW | RDW_ERASE | RDW_FRAME |
1212 RDW_ALLCHILDREN);
1213 }
1214 DeleteObject(hRgn);
1215 return (0);
1216 }
1217
1218 case WM_SETREDRAW:
1219 {
1220 DefWndSetRedraw(hWnd, wParam);
1221 return (0);
1222 }
1223
1224 case WM_CLOSE:
1225 {
1226 DestroyWindow(hWnd);
1227 return (0);
1228 }
1229
1230 case WM_MOUSEACTIVATE:
1231 {
1232 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1233 {
1234 LONG Ret;
1235 if (bUnicode)
1236 {
1237 Ret = SendMessageW(GetParent(hWnd), WM_MOUSEACTIVATE,
1238 wParam, lParam);
1239 }
1240 else
1241 {
1242 Ret = SendMessageA(GetParent(hWnd), WM_MOUSEACTIVATE,
1243 wParam, lParam);
1244 }
1245 if (Ret)
1246 {
1247 return (Ret);
1248 }
1249 }
1250 return ((LOWORD(lParam) >= HTCLIENT) ? MA_ACTIVATE : MA_NOACTIVATE);
1251 }
1252
1253 case WM_ACTIVATE:
1254 {
1255 /* Check if the window is minimized. */
1256 if (LOWORD(wParam) != WA_INACTIVE &&
1257 !(GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE))
1258 {
1259 SetFocus(hWnd);
1260 }
1261 break;
1262 }
1263
1264 case WM_MOUSEWHEEL:
1265 {
1266 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1267 {
1268 if (bUnicode)
1269 {
1270 return (SendMessageW(GetParent(hWnd), WM_MOUSEWHEEL,
1271 wParam, lParam));
1272 }
1273 else
1274 {
1275 return (SendMessageA(GetParent(hWnd), WM_MOUSEWHEEL,
1276 wParam, lParam));
1277 }
1278 }
1279 break;
1280 }
1281
1282 case WM_ERASEBKGND:
1283 case WM_ICONERASEBKGND:
1284 {
1285 RECT Rect;
1286 HBRUSH hBrush = (HBRUSH)GetClassLongW(hWnd, GCL_HBRBACKGROUND);
1287
1288 if (NULL == hBrush)
1289 {
1290 return 0;
1291 }
1292 if (GetClassLongW(hWnd, GCL_STYLE) & CS_PARENTDC)
1293 {
1294 /* can't use GetClipBox with a parent DC or we fill the whole parent */
1295 GetClientRect(hWnd, &Rect);
1296 DPtoLP((HDC)wParam, (LPPOINT)&Rect, 2);
1297 }
1298 else
1299 {
1300 GetClipBox((HDC)wParam, &Rect);
1301 }
1302 FillRect((HDC)wParam, &Rect, hBrush);
1303 return (1);
1304 }
1305
1306 case WM_CTLCOLORMSGBOX:
1307 case WM_CTLCOLOREDIT:
1308 case WM_CTLCOLORLISTBOX:
1309 case WM_CTLCOLORBTN:
1310 case WM_CTLCOLORDLG:
1311 case WM_CTLCOLORSTATIC:
1312 case WM_CTLCOLORSCROLLBAR:
1313 return (LRESULT) DefWndControlColor((HDC)wParam, Msg - WM_CTLCOLORMSGBOX);
1314
1315 case WM_CTLCOLOR:
1316 return (LRESULT) DefWndControlColor((HDC)wParam, HIWORD(lParam));
1317
1318 case WM_SETCURSOR:
1319 {
1320 ULONG Style = GetWindowLongW(hWnd, GWL_STYLE);
1321
1322 if (Style & WS_CHILD)
1323 {
1324 if (LOWORD(lParam) < HTLEFT || LOWORD(lParam) > HTBOTTOMRIGHT)
1325 {
1326 BOOL bResult;
1327 if (bUnicode)
1328 {
1329 bResult = SendMessageW(GetParent(hWnd), WM_SETCURSOR,
1330 wParam, lParam);
1331 }
1332 else
1333 {
1334 bResult = SendMessageA(GetParent(hWnd), WM_SETCURSOR,
1335 wParam, lParam);
1336 }
1337 if (bResult)
1338 {
1339 return(TRUE);
1340 }
1341 }
1342 }
1343 return (DefWndHandleSetCursor(hWnd, wParam, lParam, Style));
1344 }
1345
1346 case WM_SYSCOMMAND:
1347 return (DefWndHandleSysCommand(hWnd, wParam, lParam));
1348
1349 case WM_KEYDOWN:
1350 if(wParam == VK_F10) iF10Key = VK_F10;
1351 break;
1352
1353 /* FIXME: This is also incomplete. */
1354 case WM_SYSKEYDOWN:
1355 {
1356 if (HIWORD(lParam) & KEYDATA_ALT)
1357 {
1358 /* if( HIWORD(lParam) & ~KEYDATA_PREVSTATE ) */
1359 if ( (wParam == VK_MENU || wParam == VK_LMENU
1360 || wParam == VK_RMENU) && !iMenuSysKey )
1361 iMenuSysKey = 1;
1362 else
1363 iMenuSysKey = 0;
1364
1365 iF10Key = 0;
1366
1367 if (wParam == VK_F4) /* Try to close the window */
1368 {
1369 HWND top = GetAncestor(hWnd, GA_ROOT);
1370 if (!(GetClassLongW(top, GCL_STYLE) & CS_NOCLOSE))
1371 {
1372 if (bUnicode)
1373 PostMessageW(top, WM_SYSCOMMAND, SC_CLOSE, 0);
1374 else
1375 PostMessageA(top, WM_SYSCOMMAND, SC_CLOSE, 0);
1376 }
1377 }
1378 else if (wParam == VK_SNAPSHOT)
1379 {
1380 HWND hwnd = hWnd;
1381 while (GetParent(hwnd) != NULL)
1382 {
1383 hwnd = GetParent(hwnd);
1384 }
1385 DefWndScreenshot(hwnd);
1386 }
1387 }
1388 else if( wParam == VK_F10 )
1389 iF10Key = 1;
1390 else if( wParam == VK_ESCAPE && (GetKeyState(VK_SHIFT) & 0x8000))
1391 SendMessageW( hWnd, WM_SYSCOMMAND, SC_KEYMENU, ' ' );
1392 break;
1393 }
1394
1395 case WM_KEYUP:
1396 case WM_SYSKEYUP:
1397 {
1398 /* Press and release F10 or ALT */
1399 if (((wParam == VK_MENU || wParam == VK_LMENU || wParam == VK_RMENU)
1400 && iMenuSysKey) || ((wParam == VK_F10) && iF10Key))
1401 SendMessageW( GetAncestor( hWnd, GA_ROOT ), WM_SYSCOMMAND, SC_KEYMENU, 0L );
1402 iMenuSysKey = iF10Key = 0;
1403 break;
1404 }
1405
1406 case WM_SYSCHAR:
1407 {
1408 iMenuSysKey = 0;
1409 if (wParam == '\r' && IsIconic(hWnd))
1410 {
1411 PostMessageW( hWnd, WM_SYSCOMMAND, SC_RESTORE, 0L );
1412 break;
1413 }
1414 if ((HIWORD(lParam) & KEYDATA_ALT) && wParam)
1415 {
1416 if (wParam == '\t' || wParam == '\x1b') break;
1417 if (wParam == ' ' && (GetWindowLongW( hWnd, GWL_STYLE ) & WS_CHILD))
1418 SendMessageW( GetParent(hWnd), Msg, wParam, lParam );
1419 else
1420 SendMessageW( hWnd, WM_SYSCOMMAND, SC_KEYMENU, wParam );
1421 }
1422 else /* check for Ctrl-Esc */
1423 if (wParam != '\x1b') MessageBeep(0);
1424 break;
1425 }
1426
1427 case WM_SHOWWINDOW:
1428 {
1429 if (lParam) // Call when it is necessary.
1430 NtUserMessageCall( hWnd, Msg, wParam, lParam, 0, NUMC_DEFWINDOWPROC, FALSE);
1431 break;
1432 }
1433
1434 case WM_CANCELMODE:
1435 {
1436 iMenuSysKey = 0;
1437 /* FIXME: Check for a desktop. */
1438 if (!(GetWindowLongW( hWnd, GWL_STYLE ) & WS_CHILD)) EndMenu();
1439 if (GetCapture() == hWnd)
1440 {
1441 ReleaseCapture();
1442 }
1443 break;
1444 }
1445
1446 case WM_VKEYTOITEM:
1447 case WM_CHARTOITEM:
1448 return (-1);
1449 /*
1450 case WM_DROPOBJECT:
1451 return DRAG_FILE;
1452 */
1453 case WM_QUERYDROPOBJECT:
1454 {
1455 if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES)
1456 {
1457 return(1);
1458 }
1459 break;
1460 }
1461
1462 case WM_QUERYDRAGICON:
1463 {
1464 UINT Len;
1465 HICON hIcon;
1466
1467 hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON);
1468 if (hIcon)
1469 {
1470 return ((LRESULT)hIcon);
1471 }
1472 for (Len = 1; Len < 64; Len++)
1473 {
1474 if ((hIcon = LoadIconW(NULL, MAKEINTRESOURCEW(Len))) != NULL)
1475 {
1476 return((LRESULT)hIcon);
1477 }
1478 }
1479 return ((LRESULT)LoadIconW(0, IDI_APPLICATION));
1480 }
1481
1482 /* FIXME: WM_ISACTIVEICON */
1483
1484 case WM_NOTIFYFORMAT:
1485 {
1486 if (lParam == NF_QUERY)
1487 return IsWindowUnicode(hWnd) ? NFR_UNICODE : NFR_ANSI;
1488 break;
1489 }
1490
1491 case WM_SETICON:
1492 {
1493 INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
1494 HICON hOldIcon = (HICON)GetClassLongW(hWnd, Index);
1495 SetClassLongW(hWnd, Index, lParam);
1496 SetWindowPos(hWnd, 0, 0, 0, 0, 0,
1497 SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
1498 SWP_NOACTIVATE | SWP_NOZORDER);
1499 return ((LRESULT)hOldIcon);
1500 }
1501
1502 case WM_GETICON:
1503 {
1504 INT Index = (wParam == ICON_BIG) ? GCL_HICON : GCL_HICONSM;
1505 return (GetClassLongW(hWnd, Index));
1506 }
1507
1508 case WM_HELP:
1509 {
1510 if (bUnicode)
1511 {
1512 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1513 }
1514 else
1515 {
1516 SendMessageA(GetParent(hWnd), Msg, wParam, lParam);
1517 }
1518 break;
1519 }
1520
1521 case WM_SYSTIMER:
1522 {
1523 THRDCARETINFO CaretInfo;
1524 switch(wParam)
1525 {
1526 case 0xffff: /* Caret timer */
1527 /* switch showing byte in win32k and get information about the caret */
1528 if(NtUserSwitchCaretShowing(&CaretInfo) && (CaretInfo.hWnd == hWnd))
1529 {
1530 DrawCaret(hWnd, &CaretInfo);
1531 }
1532 break;
1533 }
1534 break;
1535 }
1536
1537 case WM_QUERYOPEN:
1538 case WM_QUERYENDSESSION:
1539 {
1540 return (1);
1541 }
1542
1543 case WM_INPUTLANGCHANGEREQUEST:
1544 {
1545 HKL NewHkl;
1546
1547 if(wParam & INPUTLANGCHANGE_BACKWARD
1548 && wParam & INPUTLANGCHANGE_FORWARD)
1549 {
1550 return FALSE;
1551 }
1552
1553 //FIXME: What to do with INPUTLANGCHANGE_SYSCHARSET ?
1554
1555 if(wParam & INPUTLANGCHANGE_BACKWARD) NewHkl = (HKL) HKL_PREV;
1556 else if(wParam & INPUTLANGCHANGE_FORWARD) NewHkl = (HKL) HKL_NEXT;
1557 else NewHkl = (HKL) lParam;
1558
1559 NtUserActivateKeyboardLayout(NewHkl, 0);
1560
1561 return TRUE;
1562 }
1563
1564 case WM_INPUTLANGCHANGE:
1565 {
1566 //FIXME: What to do?
1567 return TRUE;
1568 }
1569
1570 case WM_ENDSESSION:
1571 if (wParam) PostQuitMessage(0);
1572 return 0;
1573
1574 case WM_QUERYUISTATE:
1575 {
1576 LRESULT Ret = 0;
1577 PWINDOW Wnd = ValidateHwnd(hWnd);
1578 if (Wnd != NULL)
1579 {
1580 if (Wnd->HideFocus)
1581 Ret |= UISF_HIDEFOCUS;
1582 if (Wnd->HideAccel)
1583 Ret |= UISF_HIDEACCEL;
1584 }
1585 return Ret;
1586 }
1587
1588 case WM_CHANGEUISTATE:
1589 {
1590 BOOL AlwaysShowCues = TRUE;
1591 WORD Action = LOWORD(wParam);
1592 WORD Flags = HIWORD(wParam);
1593 PWINDOW Wnd;
1594
1595 SystemParametersInfoW(SPI_GETKEYBOARDCUES, 0, &AlwaysShowCues, 0);
1596 if (AlwaysShowCues)
1597 break;
1598
1599 Wnd= ValidateHwnd(hWnd);
1600 if (!Wnd || lParam != 0)
1601 break;
1602
1603 if (Flags & ~(UISF_HIDEFOCUS | UISF_HIDEACCEL | UISF_ACTIVE))
1604 break;
1605
1606 if (Flags & UISF_ACTIVE)
1607 {
1608 WARN("WM_CHANGEUISTATE does not yet support UISF_ACTIVE!\n");
1609 }
1610
1611 if (Action == UIS_INITIALIZE)
1612 {
1613 PDESKTOP Desk = GetThreadDesktopInfo();
1614 if (Desk == NULL)
1615 break;
1616
1617 Action = Desk->LastInputWasKbd ? UIS_CLEAR : UIS_SET;
1618 Flags = UISF_HIDEFOCUS | UISF_HIDEACCEL;
1619
1620 /* We need to update wParam in case we need to send out messages */
1621 wParam = MAKEWPARAM(Action, Flags);
1622 }
1623
1624 switch (Action)
1625 {
1626 case UIS_SET:
1627 /* See if we actually need to change something */
1628 if ((Flags & UISF_HIDEFOCUS) && !Wnd->HideFocus)
1629 break;
1630 if ((Flags & UISF_HIDEACCEL) && !Wnd->HideAccel)
1631 break;
1632
1633 /* Don't need to do anything... */
1634 return 0;
1635
1636 case UIS_CLEAR:
1637 /* See if we actually need to change something */
1638 if ((Flags & UISF_HIDEFOCUS) && Wnd->HideFocus)
1639 break;
1640 if ((Flags & UISF_HIDEACCEL) && Wnd->HideAccel)
1641 break;
1642
1643 /* Don't need to do anything... */
1644 return 0;
1645
1646 default:
1647 WARN("WM_CHANGEUISTATE: Unsupported Action 0x%x\n", Action);
1648 break;
1649 }
1650
1651 if ((Wnd->Style & WS_CHILD) && Wnd->Parent != NULL)
1652 {
1653 /* We're a child window and we need to pass this message down until
1654 we reach the root */
1655 hWnd = UserHMGetHandle((PWINDOW)DesktopPtrToUser(Wnd->Parent));
1656 }
1657 else
1658 {
1659 /* We're a top level window, we need to change the UI state */
1660 Msg = WM_UPDATEUISTATE;
1661 }
1662
1663 if (bUnicode)
1664 return SendMessageW(hWnd, Msg, wParam, lParam);
1665 else
1666 return SendMessageA(hWnd, Msg, wParam, lParam);
1667 }
1668
1669 case WM_UPDATEUISTATE:
1670 {
1671 BOOL Change = TRUE;
1672 BOOL AlwaysShowCues = TRUE;
1673 WORD Action = LOWORD(wParam);
1674 WORD Flags = HIWORD(wParam);
1675 PWINDOW Wnd;
1676
1677 SystemParametersInfoW(SPI_GETKEYBOARDCUES, 0, &AlwaysShowCues, 0);
1678 if (AlwaysShowCues)
1679 break;
1680
1681 Wnd = ValidateHwnd(hWnd);
1682 if (!Wnd || lParam != 0)
1683 break;
1684
1685 if (Flags & ~(UISF_HIDEFOCUS | UISF_HIDEACCEL | UISF_ACTIVE))
1686 break;
1687
1688 if (Flags & UISF_ACTIVE)
1689 {
1690 WARN("WM_UPDATEUISTATE does not yet support UISF_ACTIVE!\n");
1691 }
1692
1693 if (Action == UIS_INITIALIZE)
1694 {
1695 PDESKTOP Desk = GetThreadDesktopInfo();
1696 if (Desk == NULL)
1697 break;
1698
1699 Action = Desk->LastInputWasKbd ? UIS_CLEAR : UIS_SET;
1700 Flags = UISF_HIDEFOCUS | UISF_HIDEACCEL;
1701
1702 /* We need to update wParam for broadcasting the update */
1703 wParam = MAKEWPARAM(Action, Flags);
1704 }
1705
1706 switch (Action)
1707 {
1708 case UIS_SET:
1709 /* See if we actually need to change something */
1710 if ((Flags & UISF_HIDEFOCUS) && !Wnd->HideFocus)
1711 break;
1712 if ((Flags & UISF_HIDEACCEL) && !Wnd->HideAccel)
1713 break;
1714
1715 /* Don't need to do anything... */
1716 Change = FALSE;
1717 break;
1718
1719 case UIS_CLEAR:
1720 /* See if we actually need to change something */
1721 if ((Flags & UISF_HIDEFOCUS) && Wnd->HideFocus)
1722 break;
1723 if ((Flags & UISF_HIDEACCEL) && Wnd->HideAccel)
1724 break;
1725
1726 /* Don't need to do anything... */
1727 Change = FALSE;
1728 break;
1729
1730 default:
1731 WARN("WM_UPDATEUISTATE: Unsupported Action 0x%x\n", Action);
1732 return 0;
1733 }
1734
1735 /* Pack the information and call win32k */
1736 if (Change)
1737 {
1738 if (!NtUserCallTwoParam((DWORD)hWnd, (DWORD)Flags | ((DWORD)Action << 3), TWOPARAM_ROUTINE_ROS_UPDATEUISTATE))
1739 break;
1740 }
1741
1742 /* Always broadcast the update to all children */
1743 EnumChildWindows(hWnd,
1744 UserSendUiUpdateMsg,
1745 (LPARAM)wParam);
1746
1747 break;
1748 }
1749
1750 }
1751 return 0;
1752 }
1753
1754
1755 LRESULT STDCALL
1756 DefWindowProcA(HWND hWnd,
1757 UINT Msg,
1758 WPARAM wParam,
1759 LPARAM lParam)
1760 {
1761 LRESULT Result = 0;
1762 PWINDOW Wnd;
1763
1764 SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam);
1765 switch (Msg)
1766 {
1767 case WM_NCCREATE:
1768 {
1769 ANSI_STRING AnsiString;
1770 UNICODE_STRING UnicodeString;
1771 LPCREATESTRUCTA cs = (LPCREATESTRUCTA)lParam;
1772 /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
1773 * may have child window IDs instead of window name */
1774
1775 if(cs->lpszName)
1776 {
1777 RtlInitAnsiString(&AnsiString, (LPSTR)cs->lpszName);
1778 RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
1779 NtUserDefSetText(hWnd, &UnicodeString);
1780 RtlFreeUnicodeString(&UnicodeString);
1781 }
1782 else
1783 NtUserDefSetText(hWnd, NULL);
1784
1785 Result = 1;
1786 break;
1787 }
1788
1789 case WM_GETTEXTLENGTH:
1790 {
1791 PWSTR buf;
1792 ULONG len;
1793
1794 Wnd = ValidateHwnd(hWnd);
1795 if (Wnd != NULL && Wnd->WindowName.Length != 0)
1796 {
1797 buf = DesktopPtrToUser(Wnd->WindowName.Buffer);
1798 if (buf != NULL &&
1799 NT_SUCCESS(RtlUnicodeToMultiByteSize(&len,
1800 buf,
1801 Wnd->WindowName.Length)))
1802 {
1803 Result = (LRESULT)len;
1804 }
1805 }
1806 break;
1807 }
1808
1809 case WM_GETTEXT:
1810 {
1811 PWSTR buf = NULL;
1812 PSTR outbuf = (PSTR)lParam;
1813 UINT copy;
1814
1815 Wnd = ValidateHwnd(hWnd);
1816 if (Wnd != NULL && wParam != 0)
1817 {
1818 if (Wnd->WindowName.Buffer != NULL)
1819 buf = DesktopPtrToUser(Wnd->WindowName.Buffer);
1820 else
1821 outbuf[0] = L'\0';
1822
1823 if (buf != NULL)
1824 {
1825 if (Wnd->WindowName.Length != 0)
1826 {
1827 copy = min(Wnd->WindowName.Length / sizeof(WCHAR), wParam - 1);
1828 Result = WideCharToMultiByte(CP_ACP,
1829 0,
1830 buf,
1831 copy,
1832 outbuf,
1833 wParam,
1834 NULL,
1835 NULL);
1836 outbuf[Result] = '\0';
1837 }
1838 else
1839 outbuf[0] = '\0';
1840 }
1841 }
1842 break;
1843 }
1844
1845 case WM_SETTEXT:
1846 {
1847 ANSI_STRING AnsiString;
1848 UNICODE_STRING UnicodeString;
1849
1850 if(lParam)
1851 {
1852 RtlInitAnsiString(&AnsiString, (LPSTR)lParam);
1853 RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
1854 NtUserDefSetText(hWnd, &UnicodeString);
1855 RtlFreeUnicodeString(&UnicodeString);
1856 }
1857 else
1858 NtUserDefSetText(hWnd, NULL);
1859
1860 if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
1861 {
1862 DefWndNCPaint(hWnd, (HRGN)1, -1);
1863 }
1864
1865 Result = 1;
1866 break;
1867 }
1868
1869 /* FIXME: Implement these. */
1870 case WM_IME_CHAR:
1871 case WM_IME_KEYDOWN:
1872 case WM_IME_KEYUP:
1873 case WM_IME_STARTCOMPOSITION:
1874 case WM_IME_COMPOSITION:
1875 case WM_IME_ENDCOMPOSITION:
1876 case WM_IME_SELECT:
1877 case WM_IME_SETCONTEXT:
1878 FIXME("FIXME: WM_IME_* conversion isn't implemented yet!");
1879 /* fall through */
1880 default:
1881 Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, FALSE);
1882 }
1883
1884 SPY_ExitMessage(SPY_RESULT_DEFWND, hWnd, Msg, Result, wParam, lParam);
1885 return Result;
1886 }
1887
1888
1889 LRESULT STDCALL
1890 DefWindowProcW(HWND hWnd,
1891 UINT Msg,
1892 WPARAM wParam,
1893 LPARAM lParam)
1894 {
1895 LRESULT Result = 0;
1896 PWINDOW Wnd;
1897
1898 SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam);
1899 switch (Msg)
1900 {
1901 case WM_NCCREATE:
1902 {
1903 UNICODE_STRING UnicodeString;
1904 LPCREATESTRUCTW cs = (LPCREATESTRUCTW)lParam;
1905 /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
1906 * may have child window IDs instead of window name */
1907
1908 if(cs->lpszName)
1909 RtlInitUnicodeString(&UnicodeString, (LPWSTR)cs->lpszName);
1910
1911 NtUserDefSetText( hWnd, (cs->lpszName ? &UnicodeString : NULL));
1912 Result = 1;
1913 break;
1914 }
1915
1916 case WM_GETTEXTLENGTH:
1917 {
1918 PWSTR buf;
1919 ULONG len;
1920
1921 Wnd = ValidateHwnd(hWnd);
1922 if (Wnd != NULL && Wnd->WindowName.Length != 0)
1923 {
1924 buf = DesktopPtrToUser(Wnd->WindowName.Buffer);
1925 if (buf != NULL &&
1926 NT_SUCCESS(RtlUnicodeToMultiByteSize(&len,
1927 buf,
1928 Wnd->WindowName.Length)))
1929 {
1930 Result = (LRESULT)len;
1931 }
1932 }
1933 break;
1934 }
1935
1936 case WM_GETTEXT:
1937 {
1938 PWSTR buf = NULL;
1939 PWSTR outbuf = (PWSTR)lParam;
1940
1941 Wnd = ValidateHwnd(hWnd);
1942 if (Wnd != NULL && wParam != 0)
1943 {
1944 if (Wnd->WindowName.Buffer != NULL)
1945 buf = DesktopPtrToUser(Wnd->WindowName.Buffer);
1946 else
1947 outbuf[0] = L'\0';
1948
1949 if (buf != NULL)
1950 {
1951 if (Wnd->WindowName.Length != 0)
1952 {
1953 Result = min(Wnd->WindowName.Length / sizeof(WCHAR), wParam - 1);
1954 RtlCopyMemory(outbuf,
1955 buf,
1956 Result * sizeof(WCHAR));
1957 outbuf[Result] = L'\0';
1958 }
1959 else
1960 outbuf[0] = L'\0';
1961 }
1962 }
1963 break;
1964 }
1965
1966 case WM_SETTEXT:
1967 {
1968 UNICODE_STRING UnicodeString;
1969
1970 if(lParam)
1971 RtlInitUnicodeString(&UnicodeString, (LPWSTR)lParam);
1972
1973 NtUserDefSetText(hWnd, (lParam ? &UnicodeString : NULL));
1974
1975 if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
1976 {
1977 DefWndNCPaint(hWnd, (HRGN)1, -1);
1978 }
1979 Result = 1;
1980 break;
1981 }
1982
1983 case WM_IME_CHAR:
1984 {
1985 SendMessageW(hWnd, WM_CHAR, wParam, lParam);
1986 Result = 0;
1987 break;
1988 }
1989
1990 case WM_IME_SETCONTEXT:
1991 {
1992 /* FIXME */
1993 FIXME("FIXME: WM_IME_SETCONTEXT is not implemented!");
1994 Result = 0;
1995 break;
1996 }
1997
1998 default:
1999 Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, TRUE);
2000 }
2001 SPY_ExitMessage(SPY_RESULT_DEFWND, hWnd, Msg, Result, wParam, lParam);
2002
2003 return Result;
2004 }
2005