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