Sync to trunk HEAD (r43416)
[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
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
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 (ISITHOOKED(WH_CBT))
760 {
761 LRESULT lResult;
762 NtUserMessageCall( hWnd, WM_SYSCOMMAND, wParam, lParam, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, FALSE);
763 if (lResult) return 0;
764 }
765
766 switch (wParam & 0xfff0)
767 {
768 case SC_MOVE:
769 case SC_SIZE:
770 DefWndDoSizeMove(hWnd, wParam);
771 break;
772 case SC_MINIMIZE:
773 wp.length = sizeof(WINDOWPLACEMENT);
774 if(GetWindowPlacement(hWnd, &wp))
775 {
776 wp.showCmd = SW_MINIMIZE;
777 SetWindowPlacement(hWnd, &wp);
778 }
779 break;
780 case SC_MAXIMIZE:
781 wp.length = sizeof(WINDOWPLACEMENT);
782 if(GetWindowPlacement(hWnd, &wp))
783 {
784 wp.showCmd = SW_MAXIMIZE;
785 SetWindowPlacement(hWnd, &wp);
786 }
787 break;
788 case SC_RESTORE:
789 wp.length = sizeof(WINDOWPLACEMENT);
790 if(GetWindowPlacement(hWnd, &wp))
791 {
792 wp.showCmd = SW_RESTORE;
793 SetWindowPlacement(hWnd, &wp);
794 }
795 break;
796 case SC_CLOSE:
797 return SendMessageW(hWnd, WM_CLOSE, 0, 0);
798
799 case SC_MOUSEMENU:
800 {
801 Pt.x = (short)LOWORD(lParam);
802 Pt.y = (short)HIWORD(lParam);
803 MenuTrackMouseMenuBar(hWnd, wParam & 0x000f, Pt);
804 }
805 break;
806 case SC_KEYMENU:
807 MenuTrackKbdMenuBar(hWnd, wParam, (WCHAR)lParam);
808 break;
809 case SC_VSCROLL:
810 case SC_HSCROLL:
811 {
812 Pt.x = (short)LOWORD(lParam);
813 Pt.y = (short)HIWORD(lParam);
814 DefWndTrackScrollBar(hWnd, wParam, Pt);
815 }
816 break;
817
818 default:
819 /* FIXME: Implement */
820 UNIMPLEMENTED;
821 break;
822 }
823
824 return(0);
825 }
826
827 LRESULT
828 DefWndHandleWindowPosChanging(HWND hWnd, WINDOWPOS* Pos)
829 {
830 POINT maxTrack, minTrack;
831 LONG style = GetWindowLongPtrA(hWnd, GWL_STYLE);
832
833 if (Pos->flags & SWP_NOSIZE) return 0;
834 if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
835 {
836 WinPosGetMinMaxInfo(hWnd, NULL, NULL, &minTrack, &maxTrack);
837 Pos->cx = min(Pos->cx, maxTrack.x);
838 Pos->cy = min(Pos->cy, maxTrack.y);
839 if (!(style & WS_MINIMIZE))
840 {
841 if (Pos->cx < minTrack.x) Pos->cx = minTrack.x;
842 if (Pos->cy < minTrack.y) Pos->cy = minTrack.y;
843 }
844 }
845 else
846 {
847 Pos->cx = max(Pos->cx, 0);
848 Pos->cy = max(Pos->cy, 0);
849 }
850 return 0;
851 }
852
853 /* Undocumented flags. */
854 #define SWP_NOCLIENTMOVE 0x0800
855 #define SWP_NOCLIENTSIZE 0x1000
856
857 LRESULT
858 DefWndHandleWindowPosChanged(HWND hWnd, WINDOWPOS* Pos)
859 {
860 RECT Rect;
861
862 GetClientRect(hWnd, &Rect);
863 MapWindowPoints(hWnd, (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CHILD ?
864 GetParent(hWnd) : NULL), (LPPOINT) &Rect, 2);
865
866 if (! (Pos->flags & SWP_NOCLIENTMOVE))
867 {
868 SendMessageW(hWnd, WM_MOVE, 0, MAKELONG(Rect.left, Rect.top));
869 }
870
871 if (! (Pos->flags & SWP_NOCLIENTSIZE))
872 {
873 WPARAM wp = SIZE_RESTORED;
874 if (IsZoomed(hWnd))
875 {
876 wp = SIZE_MAXIMIZED;
877 }
878 else if (IsIconic(hWnd))
879 {
880 wp = SIZE_MINIMIZED;
881 }
882 SendMessageW(hWnd, WM_SIZE, wp,
883 MAKELONG(Rect.right - Rect.left, Rect.bottom - Rect.top));
884 }
885
886 return 0;
887 }
888
889 /***********************************************************************
890 * DefWndControlColor
891 *
892 * Default colors for control painting.
893 */
894 HBRUSH
895 DefWndControlColor(HDC hDC, UINT ctlType)
896 {
897 if (CTLCOLOR_SCROLLBAR == ctlType)
898 {
899 HBRUSH hb = GetSysColorBrush(COLOR_SCROLLBAR);
900 COLORREF bk = GetSysColor(COLOR_3DHILIGHT);
901 SetTextColor(hDC, GetSysColor(COLOR_3DFACE));
902 SetBkColor(hDC, bk);
903
904 /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
905 * we better use 0x55aa bitmap brush to make scrollbar's background
906 * look different from the window background.
907 */
908 if (bk == GetSysColor(COLOR_WINDOW))
909 {
910 static const WORD wPattern55AA[] =
911 {
912 0x5555, 0xaaaa, 0x5555, 0xaaaa,
913 0x5555, 0xaaaa, 0x5555, 0xaaaa
914 };
915 static HBITMAP hPattern55AABitmap = NULL;
916 static HBRUSH hPattern55AABrush = NULL;
917 if (hPattern55AABrush == NULL)
918 {
919 hPattern55AABitmap = CreateBitmap(8, 8, 1, 1, wPattern55AA);
920 hPattern55AABrush = CreatePatternBrush(hPattern55AABitmap);
921 }
922 return hPattern55AABrush;
923 }
924 UnrealizeObject(hb);
925 return hb;
926 }
927
928 SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
929
930 if ((CTLCOLOR_EDIT == ctlType) || (CTLCOLOR_LISTBOX == ctlType))
931 {
932 SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
933 }
934 else
935 {
936 SetBkColor(hDC, GetSysColor(COLOR_3DFACE));
937 return GetSysColorBrush(COLOR_3DFACE);
938 }
939
940 return GetSysColorBrush(COLOR_WINDOW);
941 }
942
943 static void DefWndPrint( HWND hwnd, HDC hdc, ULONG uFlags)
944 {
945 /*
946 * Visibility flag.
947 */
948 if ( (uFlags & PRF_CHECKVISIBLE) &&
949 !IsWindowVisible(hwnd) )
950 return;
951
952 /*
953 * Unimplemented flags.
954 */
955 if ( (uFlags & PRF_CHILDREN) ||
956 (uFlags & PRF_OWNED) ||
957 (uFlags & PRF_NONCLIENT) )
958 {
959 FIXME("WM_PRINT message with unsupported flags\n");
960 }
961
962 /*
963 * Background
964 */
965 if ( uFlags & PRF_ERASEBKGND)
966 SendMessageW(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
967
968 /*
969 * Client area
970 */
971 if ( uFlags & PRF_CLIENT)
972 SendMessageW(hwnd, WM_PRINTCLIENT, (WPARAM)hdc, uFlags);
973 }
974
975 static BOOL CALLBACK
976 UserSendUiUpdateMsg(HWND hwnd, LPARAM lParam)
977 {
978 SendMessageW(hwnd, WM_UPDATEUISTATE, (WPARAM)lParam, 0);
979 return TRUE;
980 }
981
982
983 VOID FASTCALL
984 DefWndScreenshot(HWND hWnd)
985 {
986 RECT rect;
987 HDC hdc;
988 INT w;
989 INT h;
990 HBITMAP hbitmap;
991 HDC hdc2;
992
993 OpenClipboard(hWnd);
994 EmptyClipboard();
995
996 hdc = GetWindowDC(hWnd);
997 GetWindowRect(hWnd, &rect);
998 w = rect.right - rect.left;
999 h = rect.bottom - rect.top;
1000
1001 hbitmap = CreateCompatibleBitmap(hdc, w, h);
1002 hdc2 = CreateCompatibleDC(hdc);
1003 SelectObject(hdc2, hbitmap);
1004
1005 BitBlt(hdc2, 0, 0, w, h,
1006 hdc, 0, 0,
1007 SRCCOPY);
1008
1009 SetClipboardData(CF_BITMAP, hbitmap);
1010
1011 ReleaseDC(hWnd, hdc);
1012 ReleaseDC(hWnd, hdc2);
1013
1014 CloseClipboard();
1015
1016 }
1017
1018
1019
1020 LRESULT WINAPI
1021 User32DefWindowProc(HWND hWnd,
1022 UINT Msg,
1023 WPARAM wParam,
1024 LPARAM lParam,
1025 BOOL bUnicode)
1026 {
1027 switch (Msg)
1028 {
1029 case WM_NCPAINT:
1030 {
1031 return DefWndNCPaint(hWnd, (HRGN)wParam, -1);
1032 }
1033
1034 case WM_NCCALCSIZE:
1035 {
1036 return DefWndNCCalcSize(hWnd, (BOOL)wParam, (RECT*)lParam);
1037 }
1038
1039 case WM_POPUPSYSTEMMENU:
1040 {
1041 /* This is an undocumented message used by the windows taskbar to
1042 display the system menu of windows that belong to other processes. */
1043 HMENU menu = GetSystemMenu(hWnd, FALSE);
1044
1045 if (menu)
1046 TrackPopupMenu(menu, TPM_LEFTBUTTON|TPM_RIGHTBUTTON,
1047 LOWORD(lParam), HIWORD(lParam), 0, hWnd, NULL);
1048 return 0;
1049 }
1050
1051 case WM_NCACTIVATE:
1052 {
1053 return DefWndNCActivate(hWnd, wParam);
1054 }
1055
1056 case WM_NCHITTEST:
1057 {
1058 POINT Point;
1059 Point.x = GET_X_LPARAM(lParam);
1060 Point.y = GET_Y_LPARAM(lParam);
1061 return (DefWndNCHitTest(hWnd, Point));
1062 }
1063
1064 case WM_LBUTTONDOWN:
1065 case WM_RBUTTONDOWN:
1066 case WM_MBUTTONDOWN:
1067 iF10Key = iMenuSysKey = 0;
1068 break;
1069
1070 case WM_NCLBUTTONDOWN:
1071 {
1072 return (DefWndNCLButtonDown(hWnd, wParam, lParam));
1073 }
1074
1075 case WM_LBUTTONDBLCLK:
1076 return (DefWndNCLButtonDblClk(hWnd, HTCLIENT, lParam));
1077
1078 case WM_NCLBUTTONDBLCLK:
1079 {
1080 return (DefWndNCLButtonDblClk(hWnd, wParam, lParam));
1081 }
1082
1083 case WM_WINDOWPOSCHANGING:
1084 {
1085 return (DefWndHandleWindowPosChanging(hWnd, (WINDOWPOS*)lParam));
1086 }
1087
1088 case WM_WINDOWPOSCHANGED:
1089 {
1090 return (DefWndHandleWindowPosChanged(hWnd, (WINDOWPOS*)lParam));
1091 }
1092
1093 case WM_NCRBUTTONDOWN:
1094 {
1095 /* in Windows, capture is taken when right-clicking on the caption bar */
1096 if (wParam == HTCAPTION)
1097 {
1098 SetCapture(hWnd);
1099 }
1100 break;
1101 }
1102
1103 case WM_RBUTTONUP:
1104 {
1105 POINT Pt;
1106 if (hWnd == GetCapture())
1107 {
1108 ReleaseCapture();
1109 }
1110 Pt.x = GET_X_LPARAM(lParam);
1111 Pt.y = GET_Y_LPARAM(lParam);
1112 ClientToScreen(hWnd, &Pt);
1113 lParam = MAKELPARAM(Pt.x, Pt.y);
1114 if (bUnicode)
1115 {
1116 SendMessageW(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
1117 }
1118 else
1119 {
1120 SendMessageA(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
1121 }
1122 break;
1123 }
1124
1125 case WM_NCRBUTTONUP:
1126 /*
1127 * FIXME : we must NOT send WM_CONTEXTMENU on a WM_NCRBUTTONUP (checked
1128 * in Windows), but what _should_ we do? According to MSDN :
1129 * "If it is appropriate to do so, the system sends the WM_SYSCOMMAND
1130 * message to the window". When is it appropriate?
1131 */
1132 break;
1133
1134 case WM_CONTEXTMENU:
1135 {
1136 if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CHILD)
1137 {
1138 if (bUnicode)
1139 {
1140 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1141 }
1142 else
1143 {
1144 SendMessageA(GetParent(hWnd), WM_CONTEXTMENU, wParam, lParam);
1145 }
1146 }
1147 else
1148 {
1149 POINT Pt;
1150 LONG_PTR Style;
1151 LONG HitCode;
1152
1153 Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
1154
1155 Pt.x = GET_X_LPARAM(lParam);
1156 Pt.y = GET_Y_LPARAM(lParam);
1157 if (Style & WS_CHILD)
1158 {
1159 ScreenToClient(GetParent(hWnd), &Pt);
1160 }
1161
1162 HitCode = DefWndNCHitTest(hWnd, Pt);
1163
1164 if (HitCode == HTCAPTION || HitCode == HTSYSMENU)
1165 {
1166 HMENU SystemMenu;
1167 UINT Flags;
1168
1169 if((SystemMenu = GetSystemMenu(hWnd, FALSE)))
1170 {
1171 MenuInitSysMenuPopup(SystemMenu, GetWindowLongPtrW(hWnd, GWL_STYLE),
1172 GetClassLongPtrW(hWnd, GCL_STYLE), HitCode);
1173
1174 if(HitCode == HTCAPTION)
1175 Flags = TPM_LEFTBUTTON | TPM_RIGHTBUTTON;
1176 else
1177 Flags = TPM_LEFTBUTTON;
1178
1179 TrackPopupMenu(SystemMenu, Flags,
1180 Pt.x, Pt.y, 0, hWnd, NULL);
1181 }
1182 }
1183 }
1184 break;
1185 }
1186
1187 case WM_PRINT:
1188 {
1189 DefWndPrint(hWnd, (HDC)wParam, lParam);
1190 return (0);
1191 }
1192
1193 case WM_SYSCOLORCHANGE:
1194 {
1195 /* force to redraw non-client area */
1196 DefWndNCPaint(hWnd, (HRGN)1, -1);
1197 /* Use InvalidateRect to redraw client area, enable
1198 * erase to redraw all subcontrols otherwise send the
1199 * WM_SYSCOLORCHANGE to child windows/controls is required
1200 */
1201 InvalidateRect(hWnd,NULL,TRUE);
1202 return (0);
1203 }
1204
1205 case WM_PAINTICON:
1206 case WM_PAINT:
1207 {
1208 PAINTSTRUCT Ps;
1209 HDC hDC = BeginPaint(hWnd, &Ps);
1210 if (hDC)
1211 {
1212 HICON hIcon;
1213
1214 if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_MINIMIZE &&
1215 (hIcon = (HICON)GetClassLongPtrW(hWnd, GCL_HICON)) != NULL)
1216 {
1217 RECT ClientRect;
1218 INT x, y;
1219 GetClientRect(hWnd, &ClientRect);
1220 x = (ClientRect.right - ClientRect.left -
1221 GetSystemMetrics(SM_CXICON)) / 2;
1222 y = (ClientRect.bottom - ClientRect.top -
1223 GetSystemMetrics(SM_CYICON)) / 2;
1224 DrawIcon(hDC, x, y, hIcon);
1225 }
1226 EndPaint(hWnd, &Ps);
1227 }
1228 return (0);
1229 }
1230
1231 case WM_SYNCPAINT:
1232 {
1233 HRGN hRgn;
1234 hRgn = CreateRectRgn(0, 0, 0, 0);
1235 if (GetUpdateRgn(hWnd, hRgn, FALSE) != NULLREGION)
1236 {
1237 RedrawWindow(hWnd, NULL, hRgn,
1238 RDW_ERASENOW | RDW_ERASE | RDW_FRAME |
1239 RDW_ALLCHILDREN);
1240 }
1241 DeleteObject(hRgn);
1242 return (0);
1243 }
1244
1245 case WM_SETREDRAW:
1246 {
1247 LONG_PTR Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
1248 if (wParam) SetWindowLongPtr(hWnd, GWL_STYLE, Style | WS_VISIBLE);
1249 else
1250 {
1251 RedrawWindow(hWnd, NULL, 0, RDW_ALLCHILDREN | RDW_VALIDATE);
1252 Style &= ~WS_VISIBLE;
1253 SetWindowLongPtr(hWnd, GWL_STYLE, Style);
1254 }
1255 return (0);
1256 }
1257
1258 case WM_CLOSE:
1259 {
1260 DestroyWindow(hWnd);
1261 return (0);
1262 }
1263
1264 case WM_MOUSEACTIVATE:
1265 {
1266 if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CHILD)
1267 {
1268 LONG Ret;
1269 if (bUnicode)
1270 {
1271 Ret = SendMessageW(GetParent(hWnd), WM_MOUSEACTIVATE,
1272 wParam, lParam);
1273 }
1274 else
1275 {
1276 Ret = SendMessageA(GetParent(hWnd), WM_MOUSEACTIVATE,
1277 wParam, lParam);
1278 }
1279 if (Ret)
1280 {
1281 return (Ret);
1282 }
1283 }
1284 return ((LOWORD(lParam) >= HTCLIENT) ? MA_ACTIVATE : MA_NOACTIVATE);
1285 }
1286
1287 case WM_ACTIVATE:
1288 {
1289 /* Check if the window is minimized. */
1290 if (LOWORD(wParam) != WA_INACTIVE &&
1291 !(GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_MINIMIZE))
1292 {
1293 SetFocus(hWnd);
1294 }
1295 break;
1296 }
1297
1298 case WM_MOUSEWHEEL:
1299 {
1300 if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CHILD)
1301 {
1302 if (bUnicode)
1303 {
1304 return (SendMessageW(GetParent(hWnd), WM_MOUSEWHEEL,
1305 wParam, lParam));
1306 }
1307 else
1308 {
1309 return (SendMessageA(GetParent(hWnd), WM_MOUSEWHEEL,
1310 wParam, lParam));
1311 }
1312 }
1313 break;
1314 }
1315
1316 case WM_ERASEBKGND:
1317 case WM_ICONERASEBKGND:
1318 {
1319 RECT Rect;
1320 HBRUSH hBrush = (HBRUSH)GetClassLongPtrW(hWnd, GCL_HBRBACKGROUND);
1321
1322 if (NULL == hBrush)
1323 {
1324 return 0;
1325 }
1326 if (GetClassLongPtrW(hWnd, GCL_STYLE) & CS_PARENTDC)
1327 {
1328 /* can't use GetClipBox with a parent DC or we fill the whole parent */
1329 GetClientRect(hWnd, &Rect);
1330 DPtoLP((HDC)wParam, (LPPOINT)&Rect, 2);
1331 }
1332 else
1333 {
1334 GetClipBox((HDC)wParam, &Rect);
1335 }
1336 FillRect((HDC)wParam, &Rect, hBrush);
1337 return (1);
1338 }
1339
1340 case WM_CTLCOLORMSGBOX:
1341 case WM_CTLCOLOREDIT:
1342 case WM_CTLCOLORLISTBOX:
1343 case WM_CTLCOLORBTN:
1344 case WM_CTLCOLORDLG:
1345 case WM_CTLCOLORSTATIC:
1346 case WM_CTLCOLORSCROLLBAR:
1347 return (LRESULT) DefWndControlColor((HDC)wParam, Msg - WM_CTLCOLORMSGBOX);
1348
1349 case WM_CTLCOLOR:
1350 return (LRESULT) DefWndControlColor((HDC)wParam, HIWORD(lParam));
1351
1352 case WM_SETCURSOR:
1353 {
1354 LONG_PTR Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
1355
1356 if (Style & WS_CHILD)
1357 {
1358 if (LOWORD(lParam) < HTLEFT || LOWORD(lParam) > HTBOTTOMRIGHT)
1359 {
1360 BOOL bResult;
1361 if (bUnicode)
1362 {
1363 bResult = SendMessageW(GetParent(hWnd), WM_SETCURSOR,
1364 wParam, lParam);
1365 }
1366 else
1367 {
1368 bResult = SendMessageA(GetParent(hWnd), WM_SETCURSOR,
1369 wParam, lParam);
1370 }
1371 if (bResult)
1372 {
1373 return(TRUE);
1374 }
1375 }
1376 }
1377 return (DefWndHandleSetCursor(hWnd, wParam, lParam, Style));
1378 }
1379
1380 case WM_SYSCOMMAND:
1381 return (DefWndHandleSysCommand(hWnd, wParam, lParam));
1382
1383 case WM_KEYDOWN:
1384 if(wParam == VK_F10) iF10Key = VK_F10;
1385 break;
1386
1387 /* FIXME: This is also incomplete. */
1388 case WM_SYSKEYDOWN:
1389 {
1390 if (HIWORD(lParam) & KEYDATA_ALT)
1391 {
1392 HWND top = GetAncestor(hWnd, GA_ROOT);
1393 /* if( HIWORD(lParam) & ~KEYDATA_PREVSTATE ) */
1394 if ( (wParam == VK_MENU || wParam == VK_LMENU
1395 || wParam == VK_RMENU) && !iMenuSysKey )
1396 {
1397 iMenuSysKey = 1;
1398 /* mimic behaviour of XP, sending a WM_SYSCOMMAND when pressing <alt> */
1399 SendMessageW( top, WM_SYSCOMMAND, SC_KEYMENU, 0L );
1400 }
1401 else
1402 iMenuSysKey = 0;
1403
1404 iF10Key = 0;
1405
1406 if (wParam == VK_F4) /* Try to close the window */
1407 {
1408 if (!(GetClassLongPtrW(top, GCL_STYLE) & CS_NOCLOSE))
1409 {
1410 if (bUnicode)
1411 PostMessageW(top, WM_SYSCOMMAND, SC_CLOSE, 0);
1412 else
1413 PostMessageA(top, WM_SYSCOMMAND, SC_CLOSE, 0);
1414 }
1415 }
1416 else if (wParam == VK_SNAPSHOT)
1417 {
1418 HWND hwnd = hWnd;
1419 while (GetParent(hwnd) != NULL)
1420 {
1421 hwnd = GetParent(hwnd);
1422 }
1423 DefWndScreenshot(hwnd);
1424 }
1425 }
1426 else if( wParam == VK_F10 )
1427 iF10Key = 1;
1428 else if( wParam == VK_ESCAPE && (GetKeyState(VK_SHIFT) & 0x8000))
1429 SendMessageW( hWnd, WM_SYSCOMMAND, SC_KEYMENU, ' ' );
1430 break;
1431 }
1432
1433 case WM_KEYUP:
1434 case WM_SYSKEYUP:
1435 {
1436 /* Press and release F10 or ALT */
1437 if (((wParam == VK_MENU || wParam == VK_LMENU || wParam == VK_RMENU)
1438 && iMenuSysKey) || ((wParam == VK_F10) && iF10Key))
1439 SendMessageW( GetAncestor( hWnd, GA_ROOT ), WM_SYSCOMMAND, SC_KEYMENU, 0L );
1440 iMenuSysKey = iF10Key = 0;
1441 break;
1442 }
1443
1444 case WM_SYSCHAR:
1445 {
1446 iMenuSysKey = 0;
1447 if (wParam == '\r' && IsIconic(hWnd))
1448 {
1449 PostMessageW( hWnd, WM_SYSCOMMAND, SC_RESTORE, 0L );
1450 break;
1451 }
1452 if ((HIWORD(lParam) & KEYDATA_ALT) && wParam)
1453 {
1454 if (wParam == '\t' || wParam == '\x1b') break;
1455 if (wParam == ' ' && (GetWindowLongPtrW( hWnd, GWL_STYLE ) & WS_CHILD))
1456 SendMessageW( GetParent(hWnd), Msg, wParam, lParam );
1457 else
1458 SendMessageW( hWnd, WM_SYSCOMMAND, SC_KEYMENU, wParam );
1459 }
1460 else /* check for Ctrl-Esc */
1461 if (wParam != '\x1b') MessageBeep(0);
1462 break;
1463 }
1464
1465 case WM_SHOWWINDOW:
1466 {
1467 if (lParam) // Call when it is necessary.
1468 NtUserMessageCall( hWnd, Msg, wParam, lParam, 0, FNID_DEFWINDOWPROC, FALSE);
1469 break;
1470 }
1471
1472 case WM_CLIENTSHUTDOWN:
1473 {
1474 LRESULT lResult;
1475 NtUserMessageCall( hWnd, Msg, wParam, lParam, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, FALSE);
1476 return lResult;
1477 }
1478
1479 case WM_CANCELMODE:
1480 {
1481 iMenuSysKey = 0;
1482 /* FIXME: Check for a desktop. */
1483 if (!(GetWindowLongPtrW( hWnd, GWL_STYLE ) & WS_CHILD)) EndMenu();
1484 if (GetCapture() == hWnd)
1485 {
1486 ReleaseCapture();
1487 }
1488 break;
1489 }
1490
1491 case WM_VKEYTOITEM:
1492 case WM_CHARTOITEM:
1493 return (-1);
1494 /*
1495 case WM_DROPOBJECT:
1496 return DRAG_FILE;
1497 */
1498 case WM_QUERYDROPOBJECT:
1499 {
1500 if (GetWindowLongPtrW(hWnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES)
1501 {
1502 return(1);
1503 }
1504 break;
1505 }
1506
1507 case WM_QUERYDRAGICON:
1508 {
1509 UINT Len;
1510 HICON hIcon;
1511
1512 hIcon = (HICON)GetClassLongPtrW(hWnd, GCL_HICON);
1513 if (hIcon)
1514 {
1515 return ((LRESULT)hIcon);
1516 }
1517 for (Len = 1; Len < 64; Len++)
1518 {
1519 if ((hIcon = LoadIconW(NULL, MAKEINTRESOURCEW(Len))) != NULL)
1520 {
1521 return((LRESULT)hIcon);
1522 }
1523 }
1524 return ((LRESULT)LoadIconW(0, IDI_APPLICATION));
1525 }
1526
1527 case WM_ISACTIVEICON:
1528 {
1529 PWND pWnd;
1530 BOOL isai;
1531 pWnd = ValidateHwnd(hWnd);
1532 if (!pWnd) return 0;
1533 isai = (pWnd->state & WNDS_ACTIVEFRAME) != 0;
1534 return isai;
1535 }
1536
1537 case WM_NOTIFYFORMAT:
1538 {
1539 if (lParam == NF_QUERY)
1540 return IsWindowUnicode(hWnd) ? NFR_UNICODE : NFR_ANSI;
1541 break;
1542 }
1543
1544 case WM_SETICON:
1545 {
1546 INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
1547 HICON hOldIcon = (HICON)GetClassLongPtrW(hWnd, Index);
1548 SetClassLongPtrW(hWnd, Index, lParam);
1549 SetWindowPos(hWnd, 0, 0, 0, 0, 0,
1550 SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
1551 SWP_NOACTIVATE | SWP_NOZORDER);
1552 return ((LRESULT)hOldIcon);
1553 }
1554
1555 case WM_GETICON:
1556 {
1557 INT Index = (wParam == ICON_BIG) ? GCL_HICON : GCL_HICONSM;
1558 return (GetClassLongPtrW(hWnd, Index));
1559 }
1560
1561 case WM_HELP:
1562 {
1563 if (bUnicode)
1564 {
1565 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1566 }
1567 else
1568 {
1569 SendMessageA(GetParent(hWnd), Msg, wParam, lParam);
1570 }
1571 break;
1572 }
1573
1574 case WM_SYSTIMER:
1575 {
1576 THRDCARETINFO CaretInfo;
1577 switch(wParam)
1578 {
1579 case 0xffff: /* Caret timer */
1580 /* switch showing byte in win32k and get information about the caret */
1581 if(NtUserSwitchCaretShowing(&CaretInfo) && (CaretInfo.hWnd == hWnd))
1582 {
1583 DrawCaret(hWnd, &CaretInfo);
1584 }
1585 break;
1586 }
1587 break;
1588 }
1589
1590 case WM_QUERYOPEN:
1591 case WM_QUERYENDSESSION:
1592 {
1593 return (1);
1594 }
1595
1596 case WM_INPUTLANGCHANGEREQUEST:
1597 {
1598 HKL NewHkl;
1599
1600 if(wParam & INPUTLANGCHANGE_BACKWARD
1601 && wParam & INPUTLANGCHANGE_FORWARD)
1602 {
1603 return FALSE;
1604 }
1605
1606 //FIXME: What to do with INPUTLANGCHANGE_SYSCHARSET ?
1607
1608 if(wParam & INPUTLANGCHANGE_BACKWARD) NewHkl = (HKL) HKL_PREV;
1609 else if(wParam & INPUTLANGCHANGE_FORWARD) NewHkl = (HKL) HKL_NEXT;
1610 else NewHkl = (HKL) lParam;
1611
1612 NtUserActivateKeyboardLayout(NewHkl, 0);
1613
1614 return TRUE;
1615 }
1616
1617 case WM_INPUTLANGCHANGE:
1618 {
1619 int count = 0;
1620 HWND *win_array = WIN_ListChildren( hWnd );
1621
1622 if (!win_array)
1623 break;
1624 while (win_array[count])
1625 SendMessageW( win_array[count++], WM_INPUTLANGCHANGE, wParam, lParam);
1626 HeapFree(GetProcessHeap(),0,win_array);
1627 break;
1628 }
1629
1630 case WM_QUERYUISTATE:
1631 {
1632 LRESULT Ret = 0;
1633 PWND Wnd = ValidateHwnd(hWnd);
1634 if (Wnd != NULL)
1635 {
1636 if (Wnd->HideFocus)
1637 Ret |= UISF_HIDEFOCUS;
1638 if (Wnd->HideAccel)
1639 Ret |= UISF_HIDEACCEL;
1640 }
1641 return Ret;
1642 }
1643
1644 case WM_CHANGEUISTATE:
1645 {
1646 BOOL AlwaysShowCues = FALSE;
1647 WORD Action = LOWORD(wParam);
1648 WORD Flags = HIWORD(wParam);
1649 PWND Wnd;
1650
1651 SystemParametersInfoW(SPI_GETKEYBOARDCUES, 0, &AlwaysShowCues, 0);
1652 if (AlwaysShowCues)
1653 break;
1654
1655 Wnd= ValidateHwnd(hWnd);
1656 if (!Wnd || lParam != 0)
1657 break;
1658
1659 if (Flags & ~(UISF_HIDEFOCUS | UISF_HIDEACCEL | UISF_ACTIVE))
1660 break;
1661
1662 if (Flags & UISF_ACTIVE)
1663 {
1664 WARN("WM_CHANGEUISTATE does not yet support UISF_ACTIVE!\n");
1665 }
1666
1667 if (Action == UIS_INITIALIZE)
1668 {
1669 PDESKTOPINFO Desk = GetThreadDesktopInfo();
1670 if (Desk == NULL)
1671 break;
1672
1673 Action = Desk->LastInputWasKbd ? UIS_CLEAR : UIS_SET;
1674 Flags = UISF_HIDEFOCUS | UISF_HIDEACCEL;
1675
1676 /* We need to update wParam in case we need to send out messages */
1677 wParam = MAKEWPARAM(Action, Flags);
1678 }
1679
1680 switch (Action)
1681 {
1682 case UIS_SET:
1683 /* See if we actually need to change something */
1684 if ((Flags & UISF_HIDEFOCUS) && !Wnd->HideFocus)
1685 break;
1686 if ((Flags & UISF_HIDEACCEL) && !Wnd->HideAccel)
1687 break;
1688
1689 /* Don't need to do anything... */
1690 return 0;
1691
1692 case UIS_CLEAR:
1693 /* See if we actually need to change something */
1694 if ((Flags & UISF_HIDEFOCUS) && Wnd->HideFocus)
1695 break;
1696 if ((Flags & UISF_HIDEACCEL) && Wnd->HideAccel)
1697 break;
1698
1699 /* Don't need to do anything... */
1700 return 0;
1701
1702 default:
1703 WARN("WM_CHANGEUISTATE: Unsupported Action 0x%x\n", Action);
1704 break;
1705 }
1706
1707 if ((Wnd->style & WS_CHILD) && Wnd->spwndParent != NULL)
1708 {
1709 /* We're a child window and we need to pass this message down until
1710 we reach the root */
1711 hWnd = UserHMGetHandle((PWND)DesktopPtrToUser(Wnd->spwndParent));
1712 }
1713 else
1714 {
1715 /* We're a top level window, we need to change the UI state */
1716 Msg = WM_UPDATEUISTATE;
1717 }
1718
1719 if (bUnicode)
1720 return SendMessageW(hWnd, Msg, wParam, lParam);
1721 else
1722 return SendMessageA(hWnd, Msg, wParam, lParam);
1723 }
1724
1725 case WM_UPDATEUISTATE:
1726 {
1727 BOOL Change = TRUE;
1728 BOOL AlwaysShowCues = FALSE;
1729 WORD Action = LOWORD(wParam);
1730 WORD Flags = HIWORD(wParam);
1731 PWND Wnd;
1732
1733 SystemParametersInfoW(SPI_GETKEYBOARDCUES, 0, &AlwaysShowCues, 0);
1734 if (AlwaysShowCues)
1735 break;
1736
1737 Wnd = ValidateHwnd(hWnd);
1738 if (!Wnd || lParam != 0)
1739 break;
1740
1741 if (Flags & ~(UISF_HIDEFOCUS | UISF_HIDEACCEL | UISF_ACTIVE))
1742 break;
1743
1744 if (Flags & UISF_ACTIVE)
1745 {
1746 WARN("WM_UPDATEUISTATE does not yet support UISF_ACTIVE!\n");
1747 }
1748
1749 if (Action == UIS_INITIALIZE)
1750 {
1751 PDESKTOPINFO Desk = GetThreadDesktopInfo();
1752 if (Desk == NULL)
1753 break;
1754
1755 Action = Desk->LastInputWasKbd ? UIS_CLEAR : UIS_SET;
1756 Flags = UISF_HIDEFOCUS | UISF_HIDEACCEL;
1757
1758 /* We need to update wParam for broadcasting the update */
1759 wParam = MAKEWPARAM(Action, Flags);
1760 }
1761
1762 switch (Action)
1763 {
1764 case UIS_SET:
1765 /* See if we actually need to change something */
1766 if ((Flags & UISF_HIDEFOCUS) && !Wnd->HideFocus)
1767 break;
1768 if ((Flags & UISF_HIDEACCEL) && !Wnd->HideAccel)
1769 break;
1770
1771 /* Don't need to do anything... */
1772 Change = FALSE;
1773 break;
1774
1775 case UIS_CLEAR:
1776 /* See if we actually need to change something */
1777 if ((Flags & UISF_HIDEFOCUS) && Wnd->HideFocus)
1778 break;
1779 if ((Flags & UISF_HIDEACCEL) && Wnd->HideAccel)
1780 break;
1781
1782 /* Don't need to do anything... */
1783 Change = FALSE;
1784 break;
1785
1786 default:
1787 WARN("WM_UPDATEUISTATE: Unsupported Action 0x%x\n", Action);
1788 return 0;
1789 }
1790
1791 /* Pack the information and call win32k */
1792 if (Change)
1793 {
1794 if (!NtUserCallTwoParam((DWORD_PTR)hWnd, (DWORD_PTR)Flags | ((DWORD_PTR)Action << 3), TWOPARAM_ROUTINE_ROS_UPDATEUISTATE))
1795 break;
1796 }
1797
1798 /* Always broadcast the update to all children */
1799 EnumChildWindows(hWnd,
1800 UserSendUiUpdateMsg,
1801 (LPARAM)wParam);
1802
1803 break;
1804 }
1805
1806 }
1807 return 0;
1808 }
1809
1810
1811 /*
1812 * helpers for calling IMM32 (from Wine 10/22/2008)
1813 *
1814 * WM_IME_* messages are generated only by IMM32,
1815 * so I assume imm32 is already LoadLibrary-ed.
1816 */
1817 static HWND
1818 DefWndImmGetDefaultIMEWnd(HWND hwnd)
1819 {
1820 HINSTANCE hInstIMM = GetModuleHandleW(L"imm32\0");
1821 HWND (WINAPI *pFunc)(HWND);
1822 HWND hwndRet = 0;
1823
1824 if (!hInstIMM)
1825 {
1826 ERR("cannot get IMM32 handle\n");
1827 return 0;
1828 }
1829
1830 pFunc = (void*) GetProcAddress(hInstIMM, "ImmGetDefaultIMEWnd");
1831 if (pFunc != NULL)
1832 hwndRet = (*pFunc)(hwnd);
1833
1834 return hwndRet;
1835 }
1836
1837
1838 static BOOL
1839 DefWndImmIsUIMessageA(HWND hwndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1840 {
1841 HINSTANCE hInstIMM = GetModuleHandleW(L"imm32\0");
1842 BOOL (WINAPI *pFunc)(HWND,UINT,WPARAM,LPARAM);
1843 BOOL fRet = FALSE;
1844
1845 if (!hInstIMM)
1846 {
1847 ERR("cannot get IMM32 handle\n");
1848 return FALSE;
1849 }
1850
1851 pFunc = (void*) GetProcAddress(hInstIMM, "ImmIsUIMessageA");
1852 if (pFunc != NULL)
1853 fRet = (*pFunc)(hwndIME, msg, wParam, lParam);
1854
1855 return fRet;
1856 }
1857
1858
1859 static BOOL
1860 DefWndImmIsUIMessageW(HWND hwndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1861 {
1862 HINSTANCE hInstIMM = GetModuleHandleW(L"imm32\0");
1863 BOOL (WINAPI *pFunc)(HWND,UINT,WPARAM,LPARAM);
1864 BOOL fRet = FALSE;
1865
1866 if (!hInstIMM)
1867 {
1868 ERR("cannot get IMM32 handle\n");
1869 return FALSE;
1870 }
1871
1872 pFunc = (void*) GetProcAddress(hInstIMM, "ImmIsUIMessageW");
1873 if (pFunc != NULL)
1874 fRet = (*pFunc)(hwndIME, msg, wParam, lParam);
1875
1876 return fRet;
1877 }
1878
1879
1880 LRESULT WINAPI
1881 RealDefWindowProcA(HWND hWnd,
1882 UINT Msg,
1883 WPARAM wParam,
1884 LPARAM lParam)
1885 {
1886 LRESULT Result = 0;
1887 PWND Wnd;
1888
1889 SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam);
1890 switch (Msg)
1891 {
1892 case WM_NCCREATE:
1893 {
1894 if (lParam)
1895 {
1896 LPCREATESTRUCTA cs = (LPCREATESTRUCTA)lParam;
1897 /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
1898 * may have child window IDs instead of window name */
1899 if (HIWORD(cs->lpszName))
1900 {
1901 DefSetText(hWnd, (PCWSTR)cs->lpszName, TRUE);
1902 }
1903 Result = 1;
1904 }
1905 break;
1906 }
1907
1908 case WM_GETTEXTLENGTH:
1909 {
1910 PWSTR buf;
1911 ULONG len;
1912
1913 Wnd = ValidateHwnd(hWnd);
1914 if (Wnd != NULL && Wnd->strName.Length != 0)
1915 {
1916 buf = DesktopPtrToUser(Wnd->strName.Buffer);
1917 if (buf != NULL &&
1918 NT_SUCCESS(RtlUnicodeToMultiByteSize(&len,
1919 buf,
1920 Wnd->strName.Length)))
1921 {
1922 Result = (LRESULT) len;
1923 }
1924 }
1925 else Result = 0L;
1926
1927 break;
1928 }
1929
1930 case WM_GETTEXT:
1931 {
1932 PWSTR buf = NULL;
1933 PSTR outbuf = (PSTR)lParam;
1934 UINT copy;
1935
1936 Wnd = ValidateHwnd(hWnd);
1937 if (Wnd != NULL && wParam != 0)
1938 {
1939 if (Wnd->strName.Buffer != NULL)
1940 buf = DesktopPtrToUser(Wnd->strName.Buffer);
1941 else
1942 outbuf[0] = L'\0';
1943
1944 if (buf != NULL)
1945 {
1946 if (Wnd->strName.Length != 0)
1947 {
1948 copy = min(Wnd->strName.Length / sizeof(WCHAR), wParam - 1);
1949 Result = WideCharToMultiByte(CP_ACP,
1950 0,
1951 buf,
1952 copy,
1953 outbuf,
1954 wParam,
1955 NULL,
1956 NULL);
1957 outbuf[Result] = '\0';
1958 }
1959 else
1960 outbuf[0] = '\0';
1961 }
1962 }
1963 break;
1964 }
1965
1966 case WM_SETTEXT:
1967 {
1968 DefSetText(hWnd, (PCWSTR)lParam, TRUE);
1969
1970 if ((GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
1971 {
1972 DefWndNCPaint(hWnd, (HRGN)1, -1);
1973 }
1974
1975 Result = 1;
1976 break;
1977 }
1978
1979 case WM_IME_KEYDOWN:
1980 {
1981 Result = PostMessageA(hWnd, WM_KEYDOWN, wParam, lParam);
1982 break;
1983 }
1984
1985 case WM_IME_KEYUP:
1986 {
1987 Result = PostMessageA(hWnd, WM_KEYUP, wParam, lParam);
1988 break;
1989 }
1990
1991 case WM_IME_CHAR:
1992 {
1993 if (HIBYTE(wParam))
1994 PostMessageA(hWnd, WM_CHAR, HIBYTE(wParam), lParam);
1995 PostMessageA(hWnd, WM_CHAR, LOBYTE(wParam), lParam);
1996 break;
1997 }
1998
1999 case WM_IME_STARTCOMPOSITION:
2000 case WM_IME_COMPOSITION:
2001 case WM_IME_ENDCOMPOSITION:
2002 case WM_IME_SELECT:
2003 case WM_IME_NOTIFY:
2004 {
2005 HWND hwndIME;
2006
2007 hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
2008 if (hwndIME)
2009 Result = SendMessageA(hwndIME, Msg, wParam, lParam);
2010 break;
2011 }
2012
2013 case WM_IME_SETCONTEXT:
2014 {
2015 HWND hwndIME;
2016
2017 hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
2018 if (hwndIME)
2019 Result = DefWndImmIsUIMessageA(hwndIME, Msg, wParam, lParam);
2020 break;
2021 }
2022
2023 /* fall through */
2024 default:
2025 Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, FALSE);
2026 }
2027
2028 SPY_ExitMessage(SPY_RESULT_DEFWND, hWnd, Msg, Result, wParam, lParam);
2029 return Result;
2030 }
2031
2032
2033 LRESULT WINAPI
2034 RealDefWindowProcW(HWND hWnd,
2035 UINT Msg,
2036 WPARAM wParam,
2037 LPARAM lParam)
2038 {
2039 LRESULT Result = 0;
2040 PWND Wnd;
2041
2042 SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam);
2043 switch (Msg)
2044 {
2045 case WM_NCCREATE:
2046 {
2047 if (lParam)
2048 {
2049 LPCREATESTRUCTW cs = (LPCREATESTRUCTW)lParam;
2050 /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
2051 * may have child window IDs instead of window name */
2052
2053 if (HIWORD(cs->lpszName))
2054 {
2055 DefSetText(hWnd, cs->lpszName, FALSE);
2056 }
2057 Result = 1;
2058 }
2059 break;
2060 }
2061
2062 case WM_GETTEXTLENGTH:
2063 {
2064 PWSTR buf;
2065 ULONG len;
2066
2067 Wnd = ValidateHwnd(hWnd);
2068 if (Wnd != NULL && Wnd->strName.Length != 0)
2069 {
2070 buf = DesktopPtrToUser(Wnd->strName.Buffer);
2071 if (buf != NULL &&
2072 NT_SUCCESS(RtlUnicodeToMultiByteSize(&len,
2073 buf,
2074 Wnd->strName.Length)))
2075 {
2076 Result = (LRESULT) (Wnd->strName.Length / sizeof(WCHAR));
2077 }
2078 }
2079 else Result = 0L;
2080
2081 break;
2082 }
2083
2084 case WM_GETTEXT:
2085 {
2086 PWSTR buf = NULL;
2087 PWSTR outbuf = (PWSTR)lParam;
2088
2089 Wnd = ValidateHwnd(hWnd);
2090 if (Wnd != NULL && wParam != 0)
2091 {
2092 if (Wnd->strName.Buffer != NULL)
2093 buf = DesktopPtrToUser(Wnd->strName.Buffer);
2094 else
2095 outbuf[0] = L'\0';
2096
2097 if (buf != NULL)
2098 {
2099 if (Wnd->strName.Length != 0)
2100 {
2101 Result = min(Wnd->strName.Length / sizeof(WCHAR), wParam - 1);
2102 RtlCopyMemory(outbuf,
2103 buf,
2104 Result * sizeof(WCHAR));
2105 outbuf[Result] = L'\0';
2106 }
2107 else
2108 outbuf[0] = L'\0';
2109 }
2110 }
2111 break;
2112 }
2113
2114 case WM_SETTEXT:
2115 {
2116 DefSetText(hWnd, (PCWSTR)lParam, FALSE);
2117
2118 if ((GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
2119 {
2120 DefWndNCPaint(hWnd, (HRGN)1, -1);
2121 }
2122 Result = 1;
2123 break;
2124 }
2125
2126 case WM_IME_CHAR:
2127 {
2128 PostMessageW(hWnd, WM_CHAR, wParam, lParam);
2129 Result = 0;
2130 break;
2131 }
2132
2133 case WM_IME_KEYDOWN:
2134 {
2135 Result = PostMessageW(hWnd, WM_KEYDOWN, wParam, lParam);
2136 break;
2137 }
2138
2139 case WM_IME_KEYUP:
2140 {
2141 Result = PostMessageW(hWnd, WM_KEYUP, wParam, lParam);
2142 break;
2143 }
2144
2145 case WM_IME_STARTCOMPOSITION:
2146 case WM_IME_COMPOSITION:
2147 case WM_IME_ENDCOMPOSITION:
2148 case WM_IME_SELECT:
2149 case WM_IME_NOTIFY:
2150 {
2151 HWND hwndIME;
2152
2153 hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
2154 if (hwndIME)
2155 Result = SendMessageW(hwndIME, Msg, wParam, lParam);
2156 break;
2157 }
2158
2159 case WM_IME_SETCONTEXT:
2160 {
2161 HWND hwndIME;
2162
2163 hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
2164 if (hwndIME)
2165 Result = DefWndImmIsUIMessageW(hwndIME, Msg, wParam, lParam);
2166 break;
2167 }
2168
2169 default:
2170 Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, TRUE);
2171 }
2172 SPY_ExitMessage(SPY_RESULT_DEFWND, hWnd, Msg, Result, wParam, lParam);
2173
2174 return Result;
2175 }
2176
2177 LRESULT WINAPI
2178 DefWindowProcA(HWND hWnd,
2179 UINT Msg,
2180 WPARAM wParam,
2181 LPARAM lParam)
2182 {
2183 BOOL Hook, msgOverride = FALSE;
2184 LRESULT Result = 0;
2185
2186 LOADUSERAPIHOOK
2187
2188 Hook = BeginIfHookedUserApiHook();
2189 if (Hook)
2190 msgOverride = IsMsgOverride(Msg, &guah.DefWndProcArray);
2191
2192 /* Bypass SEH and go direct. */
2193 if (!Hook || !msgOverride)
2194 return RealDefWindowProcA(hWnd, Msg, wParam, lParam);
2195
2196 _SEH2_TRY
2197 {
2198 Result = guah.DefWindowProcA(hWnd, Msg, wParam, lParam);
2199 }
2200 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2201 {
2202 }
2203 _SEH2_END;
2204
2205 EndUserApiHook();
2206
2207 return Result;
2208 }
2209
2210 LRESULT WINAPI
2211 DefWindowProcW(HWND hWnd,
2212 UINT Msg,
2213 WPARAM wParam,
2214 LPARAM lParam)
2215 {
2216 BOOL Hook, msgOverride = FALSE;
2217 LRESULT Result = 0;
2218
2219 LOADUSERAPIHOOK
2220
2221 Hook = BeginIfHookedUserApiHook();
2222 if (Hook)
2223 msgOverride = IsMsgOverride(Msg, &guah.DefWndProcArray);
2224
2225 /* Bypass SEH and go direct. */
2226 if (!Hook || !msgOverride)
2227 return RealDefWindowProcW(hWnd, Msg, wParam, lParam);
2228
2229 _SEH2_TRY
2230 {
2231 Result = guah.DefWindowProcW(hWnd, Msg, wParam, lParam);
2232 }
2233 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2234 {
2235 }
2236 _SEH2_END;
2237
2238 EndUserApiHook();
2239
2240 return Result;
2241 }