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