Optimize GetWindowText(Length)A/W and WM_GETTEXT(LENGTH)
[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 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 COLORREF SysColors[NUM_SYSCOLORS] = {0};
37 HPEN SysPens[NUM_SYSCOLORS] = {0};
38 HBRUSH SysBrushes[NUM_SYSCOLORS] = {0};
39
40 /* Bits in the dwKeyData */
41 #define KEYDATA_ALT 0x2000
42 #define KEYDATA_PREVSTATE 0x4000
43
44 static short iF10Key = 0;
45 static short iMenuSysKey = 0;
46
47 /* FUNCTIONS *****************************************************************/
48
49 void
50 InitStockObjects(void)
51 {
52 /* FIXME - Instead of copying the stuff to usermode we should map the tables to
53 userland. The current implementation has one big flaw: the system color
54 table doesn't get updated when another process changes them. That's why
55 we should rather map the table into usermode. But it only affects the
56 SysColors table - the pens, brushes and stock objects are not affected
57 as their handles never change. But it'd be faster to map them, too. */
58 if(SysBrushes[0] == NULL)
59 {
60 /* only initialize once */
61 (void)NtUserGetSysColors(SysColors, NUM_SYSCOLORS);
62 (void)NtUserGetSysColorPens(SysPens, NUM_SYSCOLORS);
63 (void)NtUserGetSysColorBrushes(SysBrushes, NUM_SYSCOLORS);
64 }
65 }
66
67 /*
68 * @implemented
69 */
70 DWORD STDCALL
71 GetSysColor(int nIndex)
72 {
73 if(nIndex >= 0 && nIndex <= NUM_SYSCOLORS)
74 {
75 return SysColors[nIndex];
76 }
77
78 SetLastError(ERROR_INVALID_PARAMETER);
79 return 0;
80 }
81
82 /*
83 * @implemented
84 */
85 HPEN STDCALL
86 GetSysColorPen(int nIndex)
87 {
88 if(nIndex >= 0 && nIndex <= NUM_SYSCOLORS)
89 {
90 return SysPens[nIndex];
91 }
92
93 SetLastError(ERROR_INVALID_PARAMETER);
94 return NULL;
95 }
96
97 /*
98 * @implemented
99 */
100 HBRUSH STDCALL
101 GetSysColorBrush(int nIndex)
102 {
103 if(nIndex >= 0 && nIndex <= NUM_SYSCOLORS)
104 {
105 return SysBrushes[nIndex];
106 }
107
108 SetLastError(ERROR_INVALID_PARAMETER);
109 return NULL;
110 }
111
112 /*
113 * @implemented
114 */
115 BOOL
116 STDCALL
117 SetSysColors(
118 int cElements,
119 CONST INT *lpaElements,
120 CONST COLORREF *lpaRgbValues)
121 {
122 BOOL Ret;
123 struct
124 {
125 INT *Elements;
126 COLORREF *Colors;
127 } ChangeSysColors;
128
129 ChangeSysColors.Elements = (INT*)lpaElements;
130 ChangeSysColors.Colors = (COLORREF*)lpaRgbValues;
131
132 if(cElements > 0)
133 {
134 Ret = NtUserSetSysColors(&ChangeSysColors, cElements);
135 if(Ret)
136 {
137 /* FIXME - just change it in the usermode structure, too, instead of asking win32k again */
138 (void)NtUserGetSysColors(SysColors, NUM_SYSCOLORS);
139 }
140 }
141 else
142 {
143 SetLastError(ERROR_INVALID_PARAMETER);
144 Ret = FALSE;
145 }
146
147 return Ret;
148 }
149
150 void
151 UserGetInsideRectNC(PWINDOW Wnd, RECT *rect)
152 {
153 ULONG Style;
154 ULONG ExStyle;
155
156 Style = Wnd->Style;
157 ExStyle = Wnd->ExStyle;
158
159 rect->top = rect->left = 0;
160 rect->right = Wnd->WindowRect.right - Wnd->WindowRect.left;
161 rect->bottom = Wnd->WindowRect.bottom - Wnd->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, PWINDOW Wnd, WPARAM wParam, POINT *capturePoint)
299 {
300 LONG hittest = 0;
301 POINT pt;
302 MSG msg;
303 RECT rectWindow;
304 ULONG Style = Wnd->Style;
305
306 rectWindow = Wnd->WindowRect;
307
308 if ((wParam & 0xfff0) == SC_MOVE)
309 {
310 /* Move pointer at the center of the caption */
311 RECT rect;
312 UserGetInsideRectNC(Wnd, &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, ExStyle;
439 BOOL thickframe;
440 BOOL iconic;
441 BOOL moved = FALSE;
442 DWORD dwPoint = GetMessagePos();
443 BOOL DragFullWindows = FALSE;
444 HWND hWndParent = NULL;
445 PWINDOW Wnd;
446
447 Wnd = ValidateHwnd(hwnd);
448 if (!Wnd)
449 return;
450
451 Style = Wnd->Style;
452 ExStyle = Wnd->ExStyle;
453 iconic = (Style & WS_MINIMIZE) != 0;
454
455 SystemParametersInfoA(SPI_GETDRAGFULLWINDOWS, 0, &DragFullWindows, 0);
456
457 pt.x = GET_X_LPARAM(dwPoint);
458 pt.y = GET_Y_LPARAM(dwPoint);
459 capturePoint = pt;
460
461 if ((Style & WS_MAXIMIZE) || !IsWindowVisible(hwnd))
462 {
463 return;
464 }
465
466 thickframe = UserHasThickFrameStyle(Style, ExStyle) && !(Style & WS_MINIMIZE);
467 if ((wParam & 0xfff0) == SC_MOVE)
468 {
469 if (!hittest)
470 {
471 hittest = DefWndStartSizeMove(hwnd, Wnd, wParam, &capturePoint);
472 }
473 if (!hittest)
474 {
475 return;
476 }
477 }
478 else /* SC_SIZE */
479 {
480 if (!thickframe)
481 {
482 return;
483 }
484 if (hittest && ((wParam & 0xfff0) != SC_MOUSEMENU))
485 {
486 hittest += (HTLEFT - WMSZ_LEFT);
487 }
488 else
489 {
490 SetCapture(hwnd);
491 hittest = DefWndStartSizeMove(hwnd, Wnd, wParam, &capturePoint);
492 if (!hittest)
493 {
494 ReleaseCapture();
495 return;
496 }
497 }
498 }
499
500 /* Get min/max info */
501
502 WinPosGetMinMaxInfo(hwnd, NULL, NULL, &minTrack, &maxTrack);
503 sizingRect = Wnd->WindowRect;
504 if (Style & WS_CHILD)
505 {
506 hWndParent = GetParent(hwnd);
507 MapWindowPoints( 0, hWndParent, (LPPOINT)&sizingRect, 2 );
508 unmodRect = sizingRect;
509 GetClientRect(hWndParent, &mouseRect );
510 clipRect = mouseRect;
511 MapWindowPoints(hWndParent, HWND_DESKTOP, (LPPOINT)&clipRect, 2);
512 }
513 else
514 {
515 if(!(ExStyle & WS_EX_TOPMOST))
516 {
517 SystemParametersInfoW(SPI_GETWORKAREA, 0, &clipRect, 0);
518 mouseRect = clipRect;
519 }
520 else
521 {
522 SetRect(&mouseRect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
523 clipRect = mouseRect;
524 }
525 unmodRect = sizingRect;
526 }
527 ClipCursor(&clipRect);
528
529 origRect = sizingRect;
530 if (ON_LEFT_BORDER(hittest))
531 {
532 mouseRect.left = max( mouseRect.left, sizingRect.right-maxTrack.x );
533 mouseRect.right = min( mouseRect.right, sizingRect.right-minTrack.x );
534 }
535 else if (ON_RIGHT_BORDER(hittest))
536 {
537 mouseRect.left = max( mouseRect.left, sizingRect.left+minTrack.x );
538 mouseRect.right = min( mouseRect.right, sizingRect.left+maxTrack.x );
539 }
540 if (ON_TOP_BORDER(hittest))
541 {
542 mouseRect.top = max( mouseRect.top, sizingRect.bottom-maxTrack.y );
543 mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minTrack.y);
544 }
545 else if (ON_BOTTOM_BORDER(hittest))
546 {
547 mouseRect.top = max( mouseRect.top, sizingRect.top+minTrack.y );
548 mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+maxTrack.y );
549 }
550 if (Style & WS_CHILD)
551 {
552 MapWindowPoints( hWndParent, 0, (LPPOINT)&mouseRect, 2 );
553 }
554
555 SendMessageA( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
556 (void)NtUserSetGUIThreadHandle(MSQ_STATE_MOVESIZE, hwnd);
557 if (GetCapture() != hwnd) SetCapture( hwnd );
558
559 if (Style & WS_CHILD)
560 {
561 /* Retrieve a default cache DC (without using the window style) */
562 hdc = GetDCEx(hWndParent, 0, DCX_CACHE);
563 DesktopRgn = NULL;
564 }
565 else
566 {
567 hdc = GetDC( 0 );
568 DesktopRgn = CreateRectRgnIndirect(&clipRect);
569 }
570
571 SelectObject(hdc, DesktopRgn);
572
573 if( iconic ) /* create a cursor for dragging */
574 {
575 HICON hIcon = (HICON)GetClassLongW(hwnd, GCL_HICON);
576 if(!hIcon) hIcon = (HICON)SendMessageW( hwnd, WM_QUERYDRAGICON, 0, 0L);
577 if( hIcon ) hDragCursor = CursorIconToCursor( hIcon, TRUE );
578 if( !hDragCursor ) iconic = FALSE;
579 }
580
581 /* invert frame if WIN31_LOOK to indicate mouse click on caption */
582 if( !iconic && !DragFullWindows)
583 {
584 UserDrawMovingFrame( hdc, &sizingRect, thickframe);
585 }
586
587 for(;;)
588 {
589 int dx = 0, dy = 0;
590
591 if (GetMessageW(&msg, 0, 0, 0) <= 0)
592 break;
593
594 /* Exit on button-up, Return, or Esc */
595 if ((msg.message == WM_LBUTTONUP) ||
596 ((msg.message == WM_KEYDOWN) &&
597 ((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
598
599 if (msg.message == WM_PAINT)
600 {
601 if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
602 UpdateWindow( msg.hwnd );
603 if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
604 continue;
605 }
606
607 if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
608 continue; /* We are not interested in other messages */
609
610 pt = msg.pt;
611
612 if (msg.message == WM_KEYDOWN) switch(msg.wParam)
613 {
614 case VK_UP: pt.y -= 8; break;
615 case VK_DOWN: pt.y += 8; break;
616 case VK_LEFT: pt.x -= 8; break;
617 case VK_RIGHT: pt.x += 8; break;
618 }
619
620 pt.x = max( pt.x, mouseRect.left );
621 pt.x = min( pt.x, mouseRect.right );
622 pt.y = max( pt.y, mouseRect.top );
623 pt.y = min( pt.y, mouseRect.bottom );
624
625 dx = pt.x - capturePoint.x;
626 dy = pt.y - capturePoint.y;
627
628 if (dx || dy)
629 {
630 if( !moved )
631 {
632 moved = TRUE;
633
634 if( iconic ) /* ok, no system popup tracking */
635 {
636 hOldCursor = SetCursor(hDragCursor);
637 ShowCursor( TRUE );
638 }
639 }
640
641 if (msg.message == WM_KEYDOWN) SetCursorPos( pt.x, pt.y );
642 else
643 {
644 RECT newRect = unmodRect;
645 WPARAM wpSizingHit = 0;
646
647 if (hittest == HTCAPTION) OffsetRect( &newRect, dx, dy );
648 if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
649 else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
650 if (ON_TOP_BORDER(hittest)) newRect.top += dy;
651 else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
652 if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
653 capturePoint = pt;
654
655 /* determine the hit location */
656 if (hittest >= HTLEFT && hittest <= HTBOTTOMRIGHT)
657 wpSizingHit = WMSZ_LEFT + (hittest - HTLEFT);
658 unmodRect = newRect;
659 SendMessageA( hwnd, WM_SIZING, wpSizingHit, (LPARAM)&newRect );
660
661 if (!iconic)
662 {
663 if(!DragFullWindows)
664 UserDrawMovingFrame( hdc, &newRect, thickframe );
665 else {
666 /* To avoid any deadlocks, all the locks on the windows
667 structures must be suspended before the SetWindowPos */
668 SetWindowPos( hwnd, 0, newRect.left, newRect.top,
669 newRect.right - newRect.left,
670 newRect.bottom - newRect.top,
671 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
672 }
673 }
674 sizingRect = newRect;
675 }
676 }
677 }
678
679 ReleaseCapture();
680 ClipCursor(NULL);
681 if( iconic )
682 {
683 if( moved ) /* restore cursors, show icon title later on */
684 {
685 ShowCursor( FALSE );
686 SetCursor( hOldCursor );
687 }
688 DestroyCursor( hDragCursor );
689 }
690 else if(!DragFullWindows)
691 UserDrawMovingFrame( hdc, &sizingRect, thickframe );
692
693 if (Style & WS_CHILD)
694 ReleaseDC( hWndParent, hdc );
695 else
696 {
697 ReleaseDC( 0, hdc );
698 if(DesktopRgn)
699 {
700 DeleteObject(DesktopRgn);
701 }
702 }
703 (void)NtUserSetGUIThreadHandle(MSQ_STATE_MOVESIZE, NULL);
704 SendMessageA( hwnd, WM_EXITSIZEMOVE, 0, 0 );
705 SendMessageA( hwnd, WM_SETVISIBLE, !IsIconic(hwnd), 0L);
706
707 /* window moved or resized */
708 if (moved)
709 {
710 /* if the moving/resizing isn't canceled call SetWindowPos
711 * with the new position or the new size of the window
712 */
713 if (!((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) )
714 {
715 /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
716 if(!DragFullWindows)
717 SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
718 sizingRect.right - sizingRect.left,
719 sizingRect.bottom - sizingRect.top,
720 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
721 }
722 else { /* restore previous size/position */
723 if(DragFullWindows)
724 SetWindowPos( hwnd, 0, origRect.left, origRect.top,
725 origRect.right - origRect.left,
726 origRect.bottom - origRect.top,
727 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
728 }
729 }
730
731 if( IsWindow(hwnd) )
732 if( Style & WS_MINIMIZE )
733 {
734 /* Single click brings up the system menu when iconized */
735
736 if( !moved )
737 {
738 if( Style & WS_SYSMENU )
739 SendMessageA( hwnd, WM_SYSCOMMAND,
740 SC_MOUSEMENU + HTSYSMENU, MAKELONG(pt.x,pt.y));
741 }
742 }
743 }
744
745
746 /***********************************************************************
747 * DefWndTrackScrollBar
748 *
749 * Track a mouse button press on the horizontal or vertical scroll-bar.
750 */
751 static VOID
752 DefWndTrackScrollBar(HWND Wnd, WPARAM wParam, POINT Pt)
753 {
754 INT ScrollBar;
755
756 if (SC_HSCROLL == (wParam & 0xfff0))
757 {
758 if (HTHSCROLL != (wParam & 0x0f))
759 {
760 return;
761 }
762 ScrollBar = SB_HORZ;
763 }
764 else /* SC_VSCROLL */
765 {
766 if (HTVSCROLL != (wParam & 0x0f))
767 {
768 return;
769 }
770 ScrollBar = SB_VERT;
771 }
772 ScrollTrackScrollBar(Wnd, ScrollBar, Pt );
773 }
774
775
776 LRESULT
777 DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
778 {
779 WINDOWPLACEMENT wp;
780 POINT Pt;
781
782 switch (wParam & 0xfff0)
783 {
784 case SC_MOVE:
785 case SC_SIZE:
786 DefWndDoSizeMove(hWnd, wParam);
787 break;
788 case SC_MINIMIZE:
789 wp.length = sizeof(WINDOWPLACEMENT);
790 if(GetWindowPlacement(hWnd, &wp))
791 {
792 wp.showCmd = SW_MINIMIZE;
793 SetWindowPlacement(hWnd, &wp);
794 }
795 break;
796 case SC_MAXIMIZE:
797 wp.length = sizeof(WINDOWPLACEMENT);
798 if(GetWindowPlacement(hWnd, &wp))
799 {
800 wp.showCmd = SW_MAXIMIZE;
801 SetWindowPlacement(hWnd, &wp);
802 }
803 break;
804 case SC_RESTORE:
805 wp.length = sizeof(WINDOWPLACEMENT);
806 if(GetWindowPlacement(hWnd, &wp))
807 {
808 wp.showCmd = SW_RESTORE;
809 SetWindowPlacement(hWnd, &wp);
810 }
811 break;
812 case SC_CLOSE:
813 SendMessageA(hWnd, WM_CLOSE, 0, 0);
814 break;
815 case SC_MOUSEMENU:
816 {
817 Pt.x = (short)LOWORD(lParam);
818 Pt.y = (short)HIWORD(lParam);
819 MenuTrackMouseMenuBar(hWnd, wParam & 0x000f, Pt);
820 }
821 break;
822 case SC_KEYMENU:
823 MenuTrackKbdMenuBar(hWnd, wParam, (WCHAR)lParam);
824 break;
825 case SC_VSCROLL:
826 case SC_HSCROLL:
827 {
828 Pt.x = (short)LOWORD(lParam);
829 Pt.y = (short)HIWORD(lParam);
830 DefWndTrackScrollBar(hWnd, wParam, Pt);
831 }
832 break;
833
834 default:
835 /* FIXME: Implement */
836 UNIMPLEMENTED;
837 break;
838 }
839
840 return(0);
841 }
842
843 LRESULT
844 DefWndHandleWindowPosChanging(HWND hWnd, WINDOWPOS* Pos)
845 {
846 POINT maxTrack, minTrack;
847 LONG style = GetWindowLongA(hWnd, GWL_STYLE);
848
849 if (Pos->flags & SWP_NOSIZE) return 0;
850 if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
851 {
852 WinPosGetMinMaxInfo(hWnd, NULL, NULL, &minTrack, &maxTrack);
853 Pos->cx = min(Pos->cx, maxTrack.x);
854 Pos->cy = min(Pos->cy, maxTrack.y);
855 if (!(style & WS_MINIMIZE))
856 {
857 if (Pos->cx < minTrack.x) Pos->cx = minTrack.x;
858 if (Pos->cy < minTrack.y) Pos->cy = minTrack.y;
859 }
860 }
861 else
862 {
863 Pos->cx = max(Pos->cx, 0);
864 Pos->cy = max(Pos->cy, 0);
865 }
866 return 0;
867 }
868
869 /* Undocumented flags. */
870 #define SWP_NOCLIENTMOVE 0x0800
871 #define SWP_NOCLIENTSIZE 0x1000
872
873 LRESULT
874 DefWndHandleWindowPosChanged(HWND hWnd, WINDOWPOS* Pos)
875 {
876 RECT Rect;
877
878 GetClientRect(hWnd, &Rect);
879 MapWindowPoints(hWnd, (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD ?
880 GetParent(hWnd) : NULL), (LPPOINT) &Rect, 2);
881
882 if (! (Pos->flags & SWP_NOCLIENTMOVE))
883 {
884 SendMessageW(hWnd, WM_MOVE, 0, MAKELONG(Rect.left, Rect.top));
885 }
886
887 if (! (Pos->flags & SWP_NOCLIENTSIZE))
888 {
889 WPARAM wp = SIZE_RESTORED;
890 if (IsZoomed(hWnd))
891 {
892 wp = SIZE_MAXIMIZED;
893 }
894 else if (IsIconic(hWnd))
895 {
896 wp = SIZE_MINIMIZED;
897 }
898 SendMessageW(hWnd, WM_SIZE, wp,
899 MAKELONG(Rect.right - Rect.left, Rect.bottom - Rect.top));
900 }
901
902 return 0;
903 }
904
905 /***********************************************************************
906 * DefWndControlColor
907 *
908 * Default colors for control painting.
909 */
910 HBRUSH
911 DefWndControlColor(HDC hDC, UINT ctlType)
912 {
913 if (CTLCOLOR_SCROLLBAR == ctlType)
914 {
915 HBRUSH hb = GetSysColorBrush(COLOR_SCROLLBAR);
916 COLORREF bk = GetSysColor(COLOR_3DHILIGHT);
917 SetTextColor(hDC, GetSysColor(COLOR_3DFACE));
918 SetBkColor(hDC, bk);
919
920 /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
921 * we better use 0x55aa bitmap brush to make scrollbar's background
922 * look different from the window background.
923 */
924 if (bk == GetSysColor(COLOR_WINDOW))
925 {
926 static const WORD wPattern55AA[] =
927 {
928 0x5555, 0xaaaa, 0x5555, 0xaaaa,
929 0x5555, 0xaaaa, 0x5555, 0xaaaa
930 };
931 static HBITMAP hPattern55AABitmap = NULL;
932 static HBRUSH hPattern55AABrush = NULL;
933 if (hPattern55AABrush == NULL)
934 {
935 hPattern55AABitmap = CreateBitmap(8, 8, 1, 1, wPattern55AA);
936 hPattern55AABrush = CreatePatternBrush(hPattern55AABitmap);
937 }
938 return hPattern55AABrush;
939 }
940 UnrealizeObject(hb);
941 return hb;
942 }
943
944 SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
945
946 if ((CTLCOLOR_EDIT == ctlType) || (CTLCOLOR_LISTBOX == ctlType))
947 {
948 SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
949 }
950 else
951 {
952 SetBkColor(hDC, GetSysColor(COLOR_3DFACE));
953 return GetSysColorBrush(COLOR_3DFACE);
954 }
955
956 return GetSysColorBrush(COLOR_WINDOW);
957 }
958
959 static void DefWndPrint( HWND hwnd, HDC hdc, ULONG uFlags)
960 {
961 /*
962 * Visibility flag.
963 */
964 if ( (uFlags & PRF_CHECKVISIBLE) &&
965 !IsWindowVisible(hwnd) )
966 return;
967
968 /*
969 * Unimplemented flags.
970 */
971 if ( (uFlags & PRF_CHILDREN) ||
972 (uFlags & PRF_OWNED) ||
973 (uFlags & PRF_NONCLIENT) )
974 {
975 FIXME("WM_PRINT message with unsupported flags\n");
976 }
977
978 /*
979 * Background
980 */
981 if ( uFlags & PRF_ERASEBKGND)
982 SendMessageW(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
983
984 /*
985 * Client area
986 */
987 if ( uFlags & PRF_CLIENT)
988 SendMessageW(hwnd, WM_PRINTCLIENT, (WPARAM)hdc, PRF_CLIENT);
989 }
990
991
992 VOID FASTCALL
993 DefWndScreenshot(HWND hWnd)
994 {
995 RECT rect;
996
997 OpenClipboard(hWnd);
998 EmptyClipboard();
999
1000 HDC hdc = GetWindowDC(hWnd);
1001 GetWindowRect(hWnd, &rect);
1002 INT w = rect.right - rect.left;
1003 INT h = rect.bottom - rect.top;
1004
1005 HBITMAP hbitmap = CreateCompatibleBitmap(hdc, w, h);
1006 HDC hdc2 = CreateCompatibleDC(hdc);
1007 SelectObject(hdc2, hbitmap);
1008
1009 BitBlt(hdc2, 0, 0, w, h,
1010 hdc, 0, 0,
1011 SRCCOPY);
1012
1013 SetClipboardData(CF_BITMAP, hbitmap);
1014
1015 ReleaseDC(hWnd, hdc);
1016 ReleaseDC(hWnd, hdc2);
1017
1018 CloseClipboard();
1019
1020 }
1021
1022
1023
1024 LRESULT STDCALL
1025 User32DefWindowProc(HWND hWnd,
1026 UINT Msg,
1027 WPARAM wParam,
1028 LPARAM lParam,
1029 BOOL bUnicode)
1030 {
1031 switch (Msg)
1032 {
1033 case WM_NCPAINT:
1034 {
1035 return DefWndNCPaint(hWnd, (HRGN)wParam, -1);
1036 }
1037
1038 case WM_NCCALCSIZE:
1039 {
1040 return DefWndNCCalcSize(hWnd, (BOOL)wParam, (RECT*)lParam);
1041 }
1042
1043 case WM_NCACTIVATE:
1044 {
1045 return DefWndNCActivate(hWnd, wParam);
1046 }
1047
1048 case WM_NCHITTEST:
1049 {
1050 POINT Point;
1051 Point.x = GET_X_LPARAM(lParam);
1052 Point.y = GET_Y_LPARAM(lParam);
1053 return (DefWndNCHitTest(hWnd, Point));
1054 }
1055
1056 case WM_LBUTTONDOWN:
1057 case WM_RBUTTONDOWN:
1058 case WM_MBUTTONDOWN:
1059 iF10Key = iMenuSysKey = 0;
1060 break;
1061
1062 case WM_NCLBUTTONDOWN:
1063 {
1064 return (DefWndNCLButtonDown(hWnd, wParam, lParam));
1065 }
1066
1067 case WM_LBUTTONDBLCLK:
1068 return (DefWndNCLButtonDblClk(hWnd, HTCLIENT, lParam));
1069
1070 case WM_NCLBUTTONDBLCLK:
1071 {
1072 return (DefWndNCLButtonDblClk(hWnd, wParam, lParam));
1073 }
1074
1075 case WM_WINDOWPOSCHANGING:
1076 {
1077 return (DefWndHandleWindowPosChanging(hWnd, (WINDOWPOS*)lParam));
1078 }
1079
1080 case WM_WINDOWPOSCHANGED:
1081 {
1082 return (DefWndHandleWindowPosChanged(hWnd, (WINDOWPOS*)lParam));
1083 }
1084
1085 case WM_NCRBUTTONDOWN:
1086 {
1087 /* in Windows, capture is taken when right-clicking on the caption bar */
1088 if (wParam == HTCAPTION)
1089 {
1090 SetCapture(hWnd);
1091 }
1092 break;
1093 }
1094
1095 case WM_RBUTTONUP:
1096 {
1097 POINT Pt;
1098 if (hWnd == GetCapture())
1099 {
1100 ReleaseCapture();
1101 }
1102 Pt.x = GET_X_LPARAM(lParam);
1103 Pt.y = GET_Y_LPARAM(lParam);
1104 ClientToScreen(hWnd, &Pt);
1105 lParam = MAKELPARAM(Pt.x, Pt.y);
1106 if (bUnicode)
1107 {
1108 SendMessageW(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
1109 }
1110 else
1111 {
1112 SendMessageA(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
1113 }
1114 break;
1115 }
1116
1117 case WM_NCRBUTTONUP:
1118 /*
1119 * FIXME : we must NOT send WM_CONTEXTMENU on a WM_NCRBUTTONUP (checked
1120 * in Windows), but what _should_ we do? According to MSDN :
1121 * "If it is appropriate to do so, the system sends the WM_SYSCOMMAND
1122 * message to the window". When is it appropriate?
1123 */
1124 break;
1125
1126 case WM_CONTEXTMENU:
1127 {
1128 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1129 {
1130 if (bUnicode)
1131 {
1132 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1133 }
1134 else
1135 {
1136 SendMessageA(GetParent(hWnd), WM_CONTEXTMENU, wParam, lParam);
1137 }
1138 }
1139 else
1140 {
1141 POINT Pt;
1142 DWORD Style;
1143 LONG HitCode;
1144
1145 Style = GetWindowLongW(hWnd, GWL_STYLE);
1146
1147 Pt.x = GET_X_LPARAM(lParam);
1148 Pt.y = GET_Y_LPARAM(lParam);
1149 if (Style & WS_CHILD)
1150 {
1151 ScreenToClient(GetParent(hWnd), &Pt);
1152 }
1153
1154 HitCode = DefWndNCHitTest(hWnd, Pt);
1155
1156 if (HitCode == HTCAPTION || HitCode == HTSYSMENU)
1157 {
1158 HMENU SystemMenu;
1159 UINT Flags;
1160
1161 if((SystemMenu = GetSystemMenu(hWnd, FALSE)))
1162 {
1163 MenuInitSysMenuPopup(SystemMenu, GetWindowLongW(hWnd, GWL_STYLE),
1164 GetClassLongW(hWnd, GCL_STYLE), HitCode);
1165
1166 if(HitCode == HTCAPTION)
1167 Flags = TPM_LEFTBUTTON | TPM_RIGHTBUTTON;
1168 else
1169 Flags = TPM_LEFTBUTTON;
1170
1171 TrackPopupMenu(SystemMenu, Flags,
1172 Pt.x, Pt.y, 0, hWnd, NULL);
1173 }
1174 }
1175 }
1176 break;
1177 }
1178
1179 case WM_PRINT:
1180 {
1181 DefWndPrint(hWnd, (HDC)wParam, lParam);
1182 return (0);
1183 }
1184
1185 case WM_PAINTICON:
1186 case WM_PAINT:
1187 {
1188 PAINTSTRUCT Ps;
1189 HDC hDC = BeginPaint(hWnd, &Ps);
1190 if (hDC)
1191 {
1192 HICON hIcon;
1193 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE &&
1194 (hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON)) != NULL)
1195 {
1196 RECT ClientRect;
1197 INT x, y;
1198 GetClientRect(hWnd, &ClientRect);
1199 x = (ClientRect.right - ClientRect.left -
1200 GetSystemMetrics(SM_CXICON)) / 2;
1201 y = (ClientRect.bottom - ClientRect.top -
1202 GetSystemMetrics(SM_CYICON)) / 2;
1203 DrawIcon(hDC, x, y, hIcon);
1204 }
1205 EndPaint(hWnd, &Ps);
1206 }
1207 return (0);
1208 }
1209
1210 case WM_SYNCPAINT:
1211 {
1212 HRGN hRgn;
1213 hRgn = CreateRectRgn(0, 0, 0, 0);
1214 if (GetUpdateRgn(hWnd, hRgn, FALSE) != NULLREGION)
1215 {
1216 RedrawWindow(hWnd, NULL, hRgn,
1217 RDW_ERASENOW | RDW_ERASE | RDW_FRAME |
1218 RDW_ALLCHILDREN);
1219 }
1220 DeleteObject(hRgn);
1221 return (0);
1222 }
1223
1224 case WM_SETREDRAW:
1225 {
1226 DefWndSetRedraw(hWnd, wParam);
1227 return (0);
1228 }
1229
1230 case WM_CLOSE:
1231 {
1232 DestroyWindow(hWnd);
1233 return (0);
1234 }
1235
1236 case WM_MOUSEACTIVATE:
1237 {
1238 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1239 {
1240 LONG Ret;
1241 if (bUnicode)
1242 {
1243 Ret = SendMessageW(GetParent(hWnd), WM_MOUSEACTIVATE,
1244 wParam, lParam);
1245 }
1246 else
1247 {
1248 Ret = SendMessageA(GetParent(hWnd), WM_MOUSEACTIVATE,
1249 wParam, lParam);
1250 }
1251 if (Ret)
1252 {
1253 return (Ret);
1254 }
1255 }
1256 return ((LOWORD(lParam) >= HTCLIENT) ? MA_ACTIVATE : MA_NOACTIVATE);
1257 }
1258
1259 case WM_ACTIVATE:
1260 {
1261 /* Check if the window is minimized. */
1262 if (LOWORD(wParam) != WA_INACTIVE &&
1263 !(GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE))
1264 {
1265 SetFocus(hWnd);
1266 }
1267 break;
1268 }
1269
1270 case WM_MOUSEWHEEL:
1271 {
1272 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1273 {
1274 if (bUnicode)
1275 {
1276 return (SendMessageW(GetParent(hWnd), WM_MOUSEWHEEL,
1277 wParam, lParam));
1278 }
1279 else
1280 {
1281 return (SendMessageA(GetParent(hWnd), WM_MOUSEWHEEL,
1282 wParam, lParam));
1283 }
1284 }
1285 break;
1286 }
1287
1288 case WM_ERASEBKGND:
1289 case WM_ICONERASEBKGND:
1290 {
1291 RECT Rect;
1292 HBRUSH hBrush = (HBRUSH)GetClassLongW(hWnd, GCL_HBRBACKGROUND);
1293
1294 if (NULL == hBrush)
1295 {
1296 return 0;
1297 }
1298 if (GetClassLongW(hWnd, GCL_STYLE) & CS_PARENTDC)
1299 {
1300 /* can't use GetClipBox with a parent DC or we fill the whole parent */
1301 GetClientRect(hWnd, &Rect);
1302 DPtoLP((HDC)wParam, (LPPOINT)&Rect, 2);
1303 }
1304 else
1305 {
1306 GetClipBox((HDC)wParam, &Rect);
1307 }
1308 FillRect((HDC)wParam, &Rect, hBrush);
1309 return (1);
1310 }
1311
1312 case WM_CTLCOLORMSGBOX:
1313 case WM_CTLCOLOREDIT:
1314 case WM_CTLCOLORLISTBOX:
1315 case WM_CTLCOLORBTN:
1316 case WM_CTLCOLORDLG:
1317 case WM_CTLCOLORSTATIC:
1318 case WM_CTLCOLORSCROLLBAR:
1319 return (LRESULT) DefWndControlColor((HDC)wParam, Msg - WM_CTLCOLORMSGBOX);
1320
1321 case WM_CTLCOLOR:
1322 return (LRESULT) DefWndControlColor((HDC)wParam, HIWORD(lParam));
1323
1324 case WM_SETCURSOR:
1325 {
1326 ULONG Style = GetWindowLongW(hWnd, GWL_STYLE);
1327
1328 if (Style & WS_CHILD)
1329 {
1330 if (LOWORD(lParam) < HTLEFT || LOWORD(lParam) > HTBOTTOMRIGHT)
1331 {
1332 BOOL bResult;
1333 if (bUnicode)
1334 {
1335 bResult = SendMessageW(GetParent(hWnd), WM_SETCURSOR,
1336 wParam, lParam);
1337 }
1338 else
1339 {
1340 bResult = SendMessageA(GetParent(hWnd), WM_SETCURSOR,
1341 wParam, lParam);
1342 }
1343 if (bResult)
1344 {
1345 return(TRUE);
1346 }
1347 }
1348 }
1349 return (DefWndHandleSetCursor(hWnd, wParam, lParam, Style));
1350 }
1351
1352 case WM_SYSCOMMAND:
1353 return (DefWndHandleSysCommand(hWnd, wParam, lParam));
1354
1355 case WM_KEYDOWN:
1356 if(wParam == VK_F10) iF10Key = VK_F10;
1357 break;
1358
1359 /* FIXME: This is also incomplete. */
1360 case WM_SYSKEYDOWN:
1361 {
1362 if (HIWORD(lParam) & KEYDATA_ALT)
1363 {
1364 /* if( HIWORD(lParam) & ~KEYDATA_PREVSTATE ) */
1365 if ( (wParam == VK_MENU || wParam == VK_LMENU
1366 || wParam == VK_RMENU) && !iMenuSysKey )
1367 iMenuSysKey = 1;
1368 else
1369 iMenuSysKey = 0;
1370
1371 iF10Key = 0;
1372
1373 if (wParam == VK_F4) /* Try to close the window */
1374 {
1375 HWND top = GetAncestor(hWnd, GA_ROOT);
1376 if (!(GetClassLongW(top, GCL_STYLE) & CS_NOCLOSE))
1377 {
1378 if (bUnicode)
1379 PostMessageW(top, WM_SYSCOMMAND, SC_CLOSE, 0);
1380 else
1381 PostMessageA(top, WM_SYSCOMMAND, SC_CLOSE, 0);
1382 }
1383 }
1384 else if (wParam == VK_SNAPSHOT)
1385 {
1386 HWND hwnd = hWnd;
1387 while (GetParent(hwnd) != NULL)
1388 {
1389 hwnd = GetParent(hwnd);
1390 }
1391 DefWndScreenshot(hwnd);
1392 }
1393 }
1394 else if( wParam == VK_F10 )
1395 iF10Key = 1;
1396 else if( wParam == VK_ESCAPE && (GetKeyState(VK_SHIFT) & 0x8000))
1397 SendMessageW( hWnd, WM_SYSCOMMAND, SC_KEYMENU, ' ' );
1398 break;
1399 }
1400
1401 case WM_KEYUP:
1402 case WM_SYSKEYUP:
1403 {
1404 /* Press and release F10 or ALT */
1405 if (((wParam == VK_MENU || wParam == VK_LMENU || wParam == VK_RMENU)
1406 && iMenuSysKey) || ((wParam == VK_F10) && iF10Key))
1407 SendMessageW( GetAncestor( hWnd, GA_ROOT ), WM_SYSCOMMAND, SC_KEYMENU, 0L );
1408 iMenuSysKey = iF10Key = 0;
1409 break;
1410 }
1411
1412 case WM_SYSCHAR:
1413 {
1414 iMenuSysKey = 0;
1415 if (wParam == '\r' && IsIconic(hWnd))
1416 {
1417 PostMessageW( hWnd, WM_SYSCOMMAND, SC_RESTORE, 0L );
1418 break;
1419 }
1420 if ((HIWORD(lParam) & KEYDATA_ALT) && wParam)
1421 {
1422 if (wParam == '\t' || wParam == '\x1b') break;
1423 if (wParam == ' ' && (GetWindowLongW( hWnd, GWL_STYLE ) & WS_CHILD))
1424 SendMessageW( GetParent(hWnd), Msg, wParam, lParam );
1425 else
1426 SendMessageW( hWnd, WM_SYSCOMMAND, SC_KEYMENU, wParam );
1427 }
1428 else /* check for Ctrl-Esc */
1429 if (wParam != '\x1b') MessageBeep(0);
1430 break;
1431 }
1432
1433 case WM_SHOWWINDOW:
1434 {
1435 LONG Style;
1436 INT Ret = 0;
1437
1438 if (!lParam) return 0;
1439 Style = GetWindowLongW(hWnd, GWL_STYLE);
1440 if ((Style & WS_VISIBLE) && wParam) return 0;
1441 if (!(Style & WS_VISIBLE) && !wParam) return 0;
1442 if (!GetWindow(hWnd, GW_OWNER)) return 0;
1443 Ret = NtUserCallTwoParam((DWORD) hWnd, (DWORD) wParam, TWOPARAM_ROUTINE_ROS_SHOWWINDOW);
1444 if(Ret)
1445 {
1446 if( Ret == -1) return 0;
1447 return Ret;
1448 }
1449 ShowWindow(hWnd, wParam ? SW_SHOWNOACTIVATE : SW_HIDE);
1450 break;
1451 }
1452
1453 case WM_CANCELMODE:
1454 {
1455 iMenuSysKey = 0;
1456 /* FIXME: Check for a desktop. */
1457 if (!(GetWindowLongW( hWnd, GWL_STYLE ) & WS_CHILD)) EndMenu();
1458 if (GetCapture() == hWnd)
1459 {
1460 ReleaseCapture();
1461 }
1462 break;
1463 }
1464
1465 case WM_VKEYTOITEM:
1466 case WM_CHARTOITEM:
1467 return (-1);
1468 /*
1469 case WM_DROPOBJECT:
1470 return DRAG_FILE;
1471 */
1472 case WM_QUERYDROPOBJECT:
1473 {
1474 if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES)
1475 {
1476 return(1);
1477 }
1478 break;
1479 }
1480
1481 case WM_QUERYDRAGICON:
1482 {
1483 UINT Len;
1484 HICON hIcon;
1485
1486 hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON);
1487 if (hIcon)
1488 {
1489 return ((LRESULT)hIcon);
1490 }
1491 for (Len = 1; Len < 64; Len++)
1492 {
1493 if ((hIcon = LoadIconW(NULL, MAKEINTRESOURCEW(Len))) != NULL)
1494 {
1495 return((LRESULT)hIcon);
1496 }
1497 }
1498 return ((LRESULT)LoadIconW(0, IDI_APPLICATION));
1499 }
1500
1501 /* FIXME: WM_ISACTIVEICON */
1502
1503 case WM_NOTIFYFORMAT:
1504 {
1505 if (lParam == NF_QUERY)
1506 return IsWindowUnicode(hWnd) ? NFR_UNICODE : NFR_ANSI;
1507 break;
1508 }
1509
1510 case WM_SETICON:
1511 {
1512 INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
1513 HICON hOldIcon = (HICON)GetClassLongW(hWnd, Index);
1514 SetClassLongW(hWnd, Index, lParam);
1515 SetWindowPos(hWnd, 0, 0, 0, 0, 0,
1516 SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
1517 SWP_NOACTIVATE | SWP_NOZORDER);
1518 return ((LRESULT)hOldIcon);
1519 }
1520
1521 case WM_GETICON:
1522 {
1523 INT Index = (wParam == ICON_BIG) ? GCL_HICON : GCL_HICONSM;
1524 return (GetClassLongW(hWnd, Index));
1525 }
1526
1527 case WM_HELP:
1528 {
1529 if (bUnicode)
1530 {
1531 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1532 }
1533 else
1534 {
1535 SendMessageA(GetParent(hWnd), Msg, wParam, lParam);
1536 }
1537 break;
1538 }
1539
1540 case WM_SYSTIMER:
1541 {
1542 THRDCARETINFO CaretInfo;
1543 switch(wParam)
1544 {
1545 case 0xffff: /* Caret timer */
1546 /* switch showing byte in win32k and get information about the caret */
1547 if(NtUserSwitchCaretShowing(&CaretInfo) && (CaretInfo.hWnd == hWnd))
1548 {
1549 DrawCaret(hWnd, &CaretInfo);
1550 }
1551 break;
1552 }
1553 break;
1554 }
1555
1556 case WM_QUERYOPEN:
1557 case WM_QUERYENDSESSION:
1558 {
1559 return (1);
1560 }
1561
1562 case WM_INPUTLANGCHANGEREQUEST:
1563 {
1564 HKL NewHkl;
1565
1566 if(wParam & INPUTLANGCHANGE_BACKWARD
1567 && wParam & INPUTLANGCHANGE_FORWARD)
1568 {
1569 return FALSE;
1570 }
1571
1572 //FIXME: What to do with INPUTLANGCHANGE_SYSCHARSET ?
1573
1574 if(wParam & INPUTLANGCHANGE_BACKWARD) NewHkl = (HKL) HKL_PREV;
1575 else if(wParam & INPUTLANGCHANGE_FORWARD) NewHkl = (HKL) HKL_NEXT;
1576 else NewHkl = (HKL) lParam;
1577
1578 NtUserActivateKeyboardLayout(NewHkl, 0);
1579
1580 return TRUE;
1581 }
1582
1583 case WM_INPUTLANGCHANGE:
1584 {
1585 //FIXME: What to do?
1586 return TRUE;
1587 }
1588
1589 case WM_ENDSESSION:
1590 if (wParam) PostQuitMessage(0);
1591 return 0;
1592
1593 }
1594 return 0;
1595 }
1596
1597
1598 LRESULT STDCALL
1599 DefWindowProcA(HWND hWnd,
1600 UINT Msg,
1601 WPARAM wParam,
1602 LPARAM lParam)
1603 {
1604 LRESULT Result = 0;
1605 PWINDOW Wnd;
1606
1607 SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam);
1608 switch (Msg)
1609 {
1610 case WM_NCCREATE:
1611 {
1612 ANSI_STRING AnsiString;
1613 UNICODE_STRING UnicodeString;
1614 LPCREATESTRUCTA cs = (LPCREATESTRUCTA)lParam;
1615 /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
1616 * may have child window IDs instead of window name */
1617
1618 if(cs->lpszName)
1619 {
1620 RtlInitAnsiString(&AnsiString, (LPSTR)cs->lpszName);
1621 RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
1622 NtUserDefSetText(hWnd, &UnicodeString);
1623 RtlFreeUnicodeString(&UnicodeString);
1624 }
1625 else
1626 NtUserDefSetText(hWnd, NULL);
1627
1628 Result = 1;
1629 break;
1630 }
1631
1632 case WM_GETTEXTLENGTH:
1633 {
1634 PWSTR buf;
1635 ULONG len;
1636
1637 Wnd = ValidateHwnd(hWnd);
1638 if (Wnd != NULL && Wnd->WindowName.Length != 0)
1639 {
1640 buf = DesktopPtrToUser(Wnd->WindowName.Buffer);
1641 if (buf != NULL &&
1642 NT_SUCCESS(RtlUnicodeToMultiByteSize(&len,
1643 buf,
1644 Wnd->WindowName.Length)))
1645 {
1646 Result = (LRESULT)len;
1647 }
1648 }
1649 break;
1650 }
1651
1652 case WM_GETTEXT:
1653 {
1654 PWSTR buf = NULL;
1655 PSTR outbuf = (PSTR)lParam;
1656 UINT copy;
1657
1658 Wnd = ValidateHwnd(hWnd);
1659 if (Wnd != NULL && wParam != 0)
1660 {
1661 if (Wnd->WindowName.Buffer != NULL)
1662 buf = DesktopPtrToUser(Wnd->WindowName.Buffer);
1663 else
1664 outbuf[0] = L'\0';
1665
1666 if (buf != NULL)
1667 {
1668 if (Wnd->WindowName.Length != 0)
1669 {
1670 copy = min(Wnd->WindowName.Length / sizeof(WCHAR), wParam - 1);
1671 Result = WideCharToMultiByte(CP_ACP,
1672 0,
1673 buf,
1674 copy,
1675 outbuf,
1676 wParam,
1677 NULL,
1678 NULL);
1679 outbuf[Result] = '\0';
1680 }
1681 else
1682 outbuf[0] = '\0';
1683 }
1684 }
1685 break;
1686 }
1687
1688 case WM_SETTEXT:
1689 {
1690 ANSI_STRING AnsiString;
1691 UNICODE_STRING UnicodeString;
1692
1693 if(lParam)
1694 {
1695 RtlInitAnsiString(&AnsiString, (LPSTR)lParam);
1696 RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
1697 NtUserDefSetText(hWnd, &UnicodeString);
1698 RtlFreeUnicodeString(&UnicodeString);
1699 }
1700 else
1701 NtUserDefSetText(hWnd, NULL);
1702
1703 if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
1704 {
1705 DefWndNCPaint(hWnd, (HRGN)1, -1);
1706 }
1707
1708 Result = 1;
1709 break;
1710 }
1711
1712 /* FIXME: Implement these. */
1713 case WM_IME_CHAR:
1714 case WM_IME_KEYDOWN:
1715 case WM_IME_KEYUP:
1716 case WM_IME_STARTCOMPOSITION:
1717 case WM_IME_COMPOSITION:
1718 case WM_IME_ENDCOMPOSITION:
1719 case WM_IME_SELECT:
1720 case WM_IME_SETCONTEXT:
1721 FIXME("FIXME: WM_IME_* conversion isn't implemented yet!");
1722 /* fall through */
1723 default:
1724 Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, FALSE);
1725 }
1726
1727 SPY_ExitMessage(SPY_RESULT_DEFWND, hWnd, Msg, Result, wParam, lParam);
1728 return Result;
1729 }
1730
1731
1732 LRESULT STDCALL
1733 DefWindowProcW(HWND hWnd,
1734 UINT Msg,
1735 WPARAM wParam,
1736 LPARAM lParam)
1737 {
1738 LRESULT Result = 0;
1739 PWINDOW Wnd;
1740
1741 SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam);
1742 switch (Msg)
1743 {
1744 case WM_NCCREATE:
1745 {
1746 UNICODE_STRING UnicodeString;
1747 LPCREATESTRUCTW cs = (LPCREATESTRUCTW)lParam;
1748 /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
1749 * may have child window IDs instead of window name */
1750
1751 if(cs->lpszName)
1752 RtlInitUnicodeString(&UnicodeString, (LPWSTR)cs->lpszName);
1753
1754 NtUserDefSetText( hWnd, (cs->lpszName ? &UnicodeString : NULL));
1755 Result = 1;
1756 break;
1757 }
1758
1759 case WM_GETTEXTLENGTH:
1760 {
1761 PWSTR buf;
1762 ULONG len;
1763
1764 Wnd = ValidateHwnd(hWnd);
1765 if (Wnd != NULL && Wnd->WindowName.Length != 0)
1766 {
1767 buf = DesktopPtrToUser(Wnd->WindowName.Buffer);
1768 if (buf != NULL &&
1769 NT_SUCCESS(RtlUnicodeToMultiByteSize(&len,
1770 buf,
1771 Wnd->WindowName.Length)))
1772 {
1773 Result = (LRESULT)len;
1774 }
1775 }
1776 break;
1777 }
1778
1779 case WM_GETTEXT:
1780 {
1781 PWSTR buf = NULL;
1782 PWSTR outbuf = (PWSTR)lParam;
1783
1784 Wnd = ValidateHwnd(hWnd);
1785 if (Wnd != NULL && wParam != 0)
1786 {
1787 if (Wnd->WindowName.Buffer != NULL)
1788 buf = DesktopPtrToUser(Wnd->WindowName.Buffer);
1789 else
1790 outbuf[0] = L'\0';
1791
1792 if (buf != NULL)
1793 {
1794 if (Wnd->WindowName.Length != 0)
1795 {
1796 Result = min(Wnd->WindowName.Length / sizeof(WCHAR), wParam - 1);
1797 RtlCopyMemory(outbuf,
1798 buf,
1799 Result * sizeof(WCHAR));
1800 outbuf[Result] = L'\0';
1801 }
1802 else
1803 outbuf[0] = L'\0';
1804 }
1805 }
1806 break;
1807 }
1808
1809 case WM_SETTEXT:
1810 {
1811 UNICODE_STRING UnicodeString;
1812
1813 if(lParam)
1814 RtlInitUnicodeString(&UnicodeString, (LPWSTR)lParam);
1815
1816 NtUserDefSetText(hWnd, (lParam ? &UnicodeString : NULL));
1817
1818 if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
1819 {
1820 DefWndNCPaint(hWnd, (HRGN)1, -1);
1821 }
1822 Result = 1;
1823 break;
1824 }
1825
1826 case WM_IME_CHAR:
1827 {
1828 SendMessageW(hWnd, WM_CHAR, wParam, lParam);
1829 Result = 0;
1830 break;
1831 }
1832
1833 case WM_IME_SETCONTEXT:
1834 {
1835 /* FIXME */
1836 FIXME("FIXME: WM_IME_SETCONTEXT is not implemented!");
1837 Result = 0;
1838 break;
1839 }
1840
1841 default:
1842 Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, TRUE);
1843 }
1844 SPY_ExitMessage(SPY_RESULT_DEFWND, hWnd, Msg, Result, wParam, lParam);
1845
1846 return Result;
1847 }
1848