Sync with trunk head (part 1 of x)
[reactos.git] / dll / win32 / user32 / windows / defwnd.c
1 /*
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS user32.dll
5 * FILE: dll/win32/user32/windows/defwnd.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 void MENU_EndMenu( HWND );
34
35 /* GLOBALS *******************************************************************/
36
37 /* Bits in the dwKeyData */
38 #define KEYDATA_ALT 0x2000
39 #define KEYDATA_PREVSTATE 0x4000
40
41 static short iF10Key = 0;
42 static short iMenuSysKey = 0;
43
44 /* FUNCTIONS *****************************************************************/
45
46 void
47 InitStockObjects(void)
48 {
49 /* FIXME - Instead of copying the stuff to usermode we should map the tables to
50 userland. The current implementation has one big flaw: the system color
51 table doesn't get updated when another process changes them. That's why
52 we should rather map the table into usermode. But it only affects the
53 SysColors table - the pens, brushes and stock objects are not affected
54 as their handles never change. But it'd be faster to map them, too. */
55
56 // Done! gpsi!
57 }
58
59 /*
60 * @implemented
61 */
62 DWORD WINAPI
63 GetSysColor(int nIndex)
64 {
65 if(nIndex >= 0 && nIndex < NUM_SYSCOLORS)
66 {
67 return gpsi->argbSystem[nIndex];
68 }
69
70 SetLastError(ERROR_INVALID_PARAMETER);
71 return 0;
72 }
73
74 /*
75 * @implemented
76 */
77 HBRUSH WINAPI
78 GetSysColorBrush(int nIndex)
79 {
80 if(nIndex >= 0 && nIndex < NUM_SYSCOLORS)
81 {
82 return gpsi->ahbrSystem[nIndex];
83 }
84
85 SetLastError(ERROR_INVALID_PARAMETER);
86 return NULL;
87 }
88
89 /*
90 * @implemented
91 */
92 BOOL
93 WINAPI
94 SetSysColors(
95 int cElements,
96 CONST INT *lpaElements,
97 CONST COLORREF *lpaRgbValues)
98 {
99 return NtUserSetSysColors(cElements, lpaElements, lpaRgbValues, 0);
100 }
101
102 BOOL
103 FASTCALL
104 DefSetText(HWND hWnd, PCWSTR String, BOOL Ansi)
105 {
106 LARGE_STRING lsString;
107
108 if ( String )
109 {
110 if ( Ansi )
111 RtlInitLargeAnsiString((PLARGE_ANSI_STRING)&lsString, (PCSZ)String, 0);
112 else
113 RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&lsString, String, 0);
114 }
115 return NtUserDefSetText(hWnd, (String ? &lsString : NULL));
116 }
117
118 void
119 UserGetInsideRectNC(PWND Wnd, RECT *rect)
120 {
121 ULONG Style;
122 ULONG ExStyle;
123
124 Style = Wnd->style;
125 ExStyle = Wnd->ExStyle;
126
127 rect->top = rect->left = 0;
128 rect->right = Wnd->rcWindow.right - Wnd->rcWindow.left;
129 rect->bottom = Wnd->rcWindow.bottom - Wnd->rcWindow.top;
130
131 if (Style & WS_ICONIC)
132 {
133 return;
134 }
135
136 /* Remove frame from rectangle */
137 if (UserHasThickFrameStyle(Style, ExStyle ))
138 {
139 InflateRect(rect, -GetSystemMetrics(SM_CXFRAME),
140 -GetSystemMetrics(SM_CYFRAME));
141 }
142 else
143 {
144 if (UserHasDlgFrameStyle(Style, ExStyle ))
145 {
146 InflateRect(rect, -GetSystemMetrics(SM_CXDLGFRAME),
147 -GetSystemMetrics(SM_CYDLGFRAME));
148 /* FIXME: this isn't in NC_AdjustRect? why not? */
149 if (ExStyle & WS_EX_DLGMODALFRAME)
150 InflateRect( rect, -1, 0 );
151 }
152 else
153 {
154 if (UserHasThinFrameStyle(Style, ExStyle))
155 {
156 InflateRect(rect, -GetSystemMetrics(SM_CXBORDER),
157 -GetSystemMetrics(SM_CYBORDER));
158 }
159 }
160 }
161 }
162
163
164 VOID
165 DefWndSetRedraw(HWND hWnd, WPARAM wParam)
166 {
167 LONG Style = GetWindowLongPtr(hWnd, GWL_STYLE);
168 /* Content can be redrawn after a change. */
169 if (wParam)
170 {
171 if (!(Style & WS_VISIBLE)) /* Not Visible */
172 {
173 SetWindowLongPtr(hWnd, GWL_STYLE, WS_VISIBLE);
174 }
175 }
176 else /* Content cannot be redrawn after a change. */
177 {
178 if (Style & WS_VISIBLE) /* Visible */
179 {
180 RedrawWindow( hWnd, NULL, 0, RDW_ALLCHILDREN | RDW_VALIDATE );
181 Style &= ~WS_VISIBLE;
182 SetWindowLongPtr(hWnd, GWL_STYLE, Style); /* clear bits */
183 }
184 }
185 return;
186 }
187
188
189 LRESULT
190 DefWndHandleSetCursor(HWND hWnd, WPARAM wParam, LPARAM lParam, ULONG Style)
191 {
192 /* Not for child windows. */
193 if (hWnd != (HWND)wParam)
194 {
195 return(0);
196 }
197
198 switch((INT_PTR) LOWORD(lParam))
199 {
200 case HTERROR:
201 {
202 WORD Msg = HIWORD(lParam);
203 if (Msg == WM_LBUTTONDOWN || Msg == WM_MBUTTONDOWN ||
204 Msg == WM_RBUTTONDOWN || Msg == WM_XBUTTONDOWN)
205 {
206 MessageBeep(0);
207 }
208 break;
209 }
210
211 case HTCLIENT:
212 {
213 HICON hCursor = (HICON)GetClassLongPtrW(hWnd, GCL_HCURSOR);
214 if (hCursor)
215 {
216 SetCursor(hCursor);
217 return(TRUE);
218 }
219 return(FALSE);
220 }
221
222 case HTLEFT:
223 case HTRIGHT:
224 {
225 if (Style & WS_MAXIMIZE)
226 {
227 break;
228 }
229 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZEWE)));
230 }
231
232 case HTTOP:
233 case HTBOTTOM:
234 {
235 if (Style & WS_MAXIMIZE)
236 {
237 break;
238 }
239 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENS)));
240 }
241
242 case HTTOPLEFT:
243 case HTBOTTOMRIGHT:
244 {
245 if (Style & WS_MAXIMIZE)
246 {
247 break;
248 }
249 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENWSE)));
250 }
251
252 case HTBOTTOMLEFT:
253 case HTTOPRIGHT:
254 {
255 if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_MAXIMIZE)
256 {
257 break;
258 }
259 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENESW)));
260 }
261 }
262 return((LRESULT)SetCursor(LoadCursorW(0, IDC_ARROW)));
263 }
264
265 static LONG
266 DefWndStartSizeMove(HWND hWnd, PWND Wnd, WPARAM wParam, POINT *capturePoint)
267 {
268 LONG hittest = 0;
269 POINT pt;
270 MSG msg;
271 RECT rectWindow;
272 ULONG Style = Wnd->style;
273
274 rectWindow = Wnd->rcWindow;
275
276 if ((wParam & 0xfff0) == SC_MOVE)
277 {
278 /* Move pointer at the center of the caption */
279 RECT rect;
280 UserGetInsideRectNC(Wnd, &rect);
281 if (Style & WS_SYSMENU)
282 rect.left += GetSystemMetrics(SM_CXSIZE) + 1;
283 if (Style & WS_MINIMIZEBOX)
284 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
285 if (Style & WS_MAXIMIZEBOX)
286 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
287 pt.x = rectWindow.left + (rect.right - rect.left) / 2;
288 pt.y = rectWindow.top + rect.top + GetSystemMetrics(SM_CYSIZE)/2;
289 hittest = HTCAPTION;
290 *capturePoint = pt;
291 }
292 else /* SC_SIZE */
293 {
294 pt.x = pt.y = 0;
295 while(!hittest)
296 {
297 if (GetMessageW(&msg, NULL, 0, 0) <= 0)
298 break;
299 switch(msg.message)
300 {
301 case WM_MOUSEMOVE:
302 hittest = DefWndNCHitTest(hWnd, msg.pt);
303 if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT))
304 hittest = 0;
305 break;
306
307 case WM_LBUTTONUP:
308 return 0;
309
310 case WM_KEYDOWN:
311 switch(msg.wParam)
312 {
313 case VK_UP:
314 hittest = HTTOP;
315 pt.x =(rectWindow.left+rectWindow.right)/2;
316 pt.y = rectWindow.top + GetSystemMetrics(SM_CYFRAME) / 2;
317 break;
318 case VK_DOWN:
319 hittest = HTBOTTOM;
320 pt.x =(rectWindow.left+rectWindow.right)/2;
321 pt.y = rectWindow.bottom - GetSystemMetrics(SM_CYFRAME) / 2;
322 break;
323 case VK_LEFT:
324 hittest = HTLEFT;
325 pt.x = rectWindow.left + GetSystemMetrics(SM_CXFRAME) / 2;
326 pt.y =(rectWindow.top+rectWindow.bottom)/2;
327 break;
328 case VK_RIGHT:
329 hittest = HTRIGHT;
330 pt.x = rectWindow.right - GetSystemMetrics(SM_CXFRAME) / 2;
331 pt.y =(rectWindow.top+rectWindow.bottom)/2;
332 break;
333 case VK_RETURN:
334 case VK_ESCAPE: return 0;
335 }
336 }
337 }
338 *capturePoint = pt;
339 }
340 SetCursorPos( pt.x, pt.y );
341 DefWndHandleSetCursor(hWnd, (WPARAM)hWnd, MAKELONG(hittest, WM_MOUSEMOVE), Style);
342 return hittest;
343 }
344
345 #define ON_LEFT_BORDER(hit) \
346 (((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
347 #define ON_RIGHT_BORDER(hit) \
348 (((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
349 #define ON_TOP_BORDER(hit) \
350 (((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
351 #define ON_BOTTOM_BORDER(hit) \
352 (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
353
354 static VOID
355 UserDrawWindowFrame(HDC hdc, const RECT *rect,
356 ULONG width, ULONG height)
357 {
358 static HBRUSH hDraggingRectBrush = NULL;
359 HBRUSH hbrush;
360
361 if(!hDraggingRectBrush)
362 {
363 static HBITMAP hDraggingPattern = NULL;
364 const DWORD Pattern[4] = {0x5555AAAA, 0x5555AAAA, 0x5555AAAA, 0x5555AAAA};
365
366 hDraggingPattern = CreateBitmap(8, 8, 1, 1, Pattern);
367 hDraggingRectBrush = CreatePatternBrush(hDraggingPattern);
368 }
369
370 hbrush = SelectObject( hdc, hDraggingRectBrush );
371 PatBlt( hdc, rect->left, rect->top,
372 rect->right - rect->left - width, height, PATINVERT );
373 PatBlt( hdc, rect->left, rect->top + height, width,
374 rect->bottom - rect->top - height, PATINVERT );
375 PatBlt( hdc, rect->left + width, rect->bottom - 1,
376 rect->right - rect->left - width, -height, PATINVERT );
377 PatBlt( hdc, rect->right - 1, rect->top, -width,
378 rect->bottom - rect->top - height, PATINVERT );
379 SelectObject( hdc, hbrush );
380 }
381
382 static VOID
383 UserDrawMovingFrame(HDC hdc, RECT *rect, BOOL thickframe)
384 {
385 if(thickframe)
386 {
387 UserDrawWindowFrame(hdc, rect, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME));
388 }
389 else
390 {
391 UserDrawWindowFrame(hdc, rect, 1, 1);
392 }
393 }
394
395 static VOID
396 DefWndDoSizeMove(HWND hwnd, WORD wParam)
397 {
398 HRGN DesktopRgn;
399 MSG msg;
400 RECT sizingRect, mouseRect, origRect, clipRect, unmodRect;
401 HDC hdc;
402 LONG hittest = (LONG)(wParam & 0x0f);
403 HCURSOR hDragCursor = 0, hOldCursor = 0;
404 POINT minTrack, maxTrack;
405 POINT capturePoint, pt;
406 ULONG Style, ExStyle;
407 BOOL thickframe;
408 BOOL iconic;
409 BOOL moved = FALSE;
410 DWORD dwPoint = GetMessagePos();
411 BOOL DragFullWindows = FALSE;
412 HWND hWndParent = NULL;
413 PWND Wnd;
414
415 Wnd = ValidateHwnd(hwnd);
416 if (!Wnd)
417 return;
418
419 Style = Wnd->style;
420 ExStyle = Wnd->ExStyle;
421 iconic = (Style & WS_MINIMIZE) != 0;
422
423 SystemParametersInfoA(SPI_GETDRAGFULLWINDOWS, 0, &DragFullWindows, 0);
424
425 pt.x = GET_X_LPARAM(dwPoint);
426 pt.y = GET_Y_LPARAM(dwPoint);
427 capturePoint = pt;
428
429 if ((Style & WS_MAXIMIZE) || !IsWindowVisible(hwnd))
430 {
431 return;
432 }
433
434 thickframe = UserHasThickFrameStyle(Style, ExStyle) && !(Style & WS_MINIMIZE);
435 if ((wParam & 0xfff0) == SC_MOVE)
436 {
437 if (!hittest)
438 {
439 hittest = DefWndStartSizeMove(hwnd, Wnd, wParam, &capturePoint);
440 }
441 if (!hittest)
442 {
443 return;
444 }
445 }
446 else /* SC_SIZE */
447 {
448 if (!thickframe)
449 {
450 return;
451 }
452 if (hittest && ((wParam & 0xfff0) != SC_MOUSEMENU))
453 {
454 hittest += (HTLEFT - WMSZ_LEFT);
455 }
456 else
457 {
458 SetCapture(hwnd);
459 hittest = DefWndStartSizeMove(hwnd, Wnd, wParam, &capturePoint);
460 if (!hittest)
461 {
462 ReleaseCapture();
463 return;
464 }
465 }
466 }
467
468 /* Get min/max info */
469
470 WinPosGetMinMaxInfo(hwnd, NULL, NULL, &minTrack, &maxTrack);
471 sizingRect = Wnd->rcWindow;
472 if (Style & WS_CHILD)
473 {
474 hWndParent = GetParent(hwnd);
475 MapWindowPoints( 0, hWndParent, (LPPOINT)&sizingRect, 2 );
476 unmodRect = sizingRect;
477 GetClientRect(hWndParent, &mouseRect );
478 clipRect = mouseRect;
479 MapWindowPoints(hWndParent, HWND_DESKTOP, (LPPOINT)&clipRect, 2);
480 }
481 else
482 {
483 if(!(ExStyle & WS_EX_TOPMOST))
484 {
485 SystemParametersInfoW(SPI_GETWORKAREA, 0, &clipRect, 0);
486 mouseRect = clipRect;
487 }
488 else
489 {
490 SetRect(&mouseRect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
491 clipRect = mouseRect;
492 }
493 unmodRect = sizingRect;
494 }
495 ClipCursor(&clipRect);
496
497 origRect = sizingRect;
498 if (ON_LEFT_BORDER(hittest))
499 {
500 mouseRect.left = max( mouseRect.left, sizingRect.right-maxTrack.x );
501 mouseRect.right = min( mouseRect.right, sizingRect.right-minTrack.x );
502 }
503 else if (ON_RIGHT_BORDER(hittest))
504 {
505 mouseRect.left = max( mouseRect.left, sizingRect.left+minTrack.x );
506 mouseRect.right = min( mouseRect.right, sizingRect.left+maxTrack.x );
507 }
508 if (ON_TOP_BORDER(hittest))
509 {
510 mouseRect.top = max( mouseRect.top, sizingRect.bottom-maxTrack.y );
511 mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minTrack.y);
512 }
513 else if (ON_BOTTOM_BORDER(hittest))
514 {
515 mouseRect.top = max( mouseRect.top, sizingRect.top+minTrack.y );
516 mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+maxTrack.y );
517 }
518 if (Style & WS_CHILD)
519 {
520 MapWindowPoints( hWndParent, 0, (LPPOINT)&mouseRect, 2 );
521 }
522
523 SendMessageA( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
524 (void)NtUserSetGUIThreadHandle(MSQ_STATE_MOVESIZE, hwnd);
525 if (GetCapture() != hwnd) SetCapture( hwnd );
526
527 if (Style & WS_CHILD)
528 {
529 /* Retrieve a default cache DC (without using the window style) */
530 hdc = GetDCEx(hWndParent, 0, DCX_CACHE);
531 DesktopRgn = NULL;
532 }
533 else
534 {
535 hdc = GetDC( 0 );
536 DesktopRgn = CreateRectRgnIndirect(&clipRect);
537 }
538
539 SelectObject(hdc, DesktopRgn);
540
541 if( iconic ) /* create a cursor for dragging */
542 {
543 HICON hIcon = (HICON)GetClassLongPtrW(hwnd, GCL_HICON);
544 if(!hIcon) hIcon = (HICON)SendMessageW( hwnd, WM_QUERYDRAGICON, 0, 0L);
545 if( hIcon ) hDragCursor = CursorIconToCursor( hIcon, TRUE );
546 if( !hDragCursor ) iconic = FALSE;
547 }
548
549 /* invert frame if WIN31_LOOK to indicate mouse click on caption */
550 if( !iconic && !DragFullWindows)
551 {
552 UserDrawMovingFrame( hdc, &sizingRect, thickframe);
553 }
554
555 for(;;)
556 {
557 int dx = 0, dy = 0;
558
559 if (GetMessageW(&msg, 0, 0, 0) <= 0)
560 break;
561
562 /* Exit on button-up, Return, or Esc */
563 if ((msg.message == WM_LBUTTONUP) ||
564 ((msg.message == WM_KEYDOWN) &&
565 ((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
566
567 if (msg.message == WM_PAINT)
568 {
569 if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
570 UpdateWindow( msg.hwnd );
571 if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
572 continue;
573 }
574
575 if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
576 continue; /* We are not interested in other messages */
577
578 pt = msg.pt;
579
580 if (msg.message == WM_KEYDOWN) switch(msg.wParam)
581 {
582 case VK_UP: pt.y -= 8; break;
583 case VK_DOWN: pt.y += 8; break;
584 case VK_LEFT: pt.x -= 8; break;
585 case VK_RIGHT: pt.x += 8; break;
586 }
587
588 pt.x = max( pt.x, mouseRect.left );
589 pt.x = min( pt.x, mouseRect.right );
590 pt.y = max( pt.y, mouseRect.top );
591 pt.y = min( pt.y, mouseRect.bottom );
592
593 dx = pt.x - capturePoint.x;
594 dy = pt.y - capturePoint.y;
595
596 if (dx || dy)
597 {
598 if( !moved )
599 {
600 moved = TRUE;
601
602 if( iconic ) /* ok, no system popup tracking */
603 {
604 hOldCursor = SetCursor(hDragCursor);
605 ShowCursor( TRUE );
606 }
607 }
608
609 if (msg.message == WM_KEYDOWN) SetCursorPos( pt.x, pt.y );
610 else
611 {
612 RECT newRect = unmodRect;
613 WPARAM wpSizingHit = 0;
614
615 if (hittest == HTCAPTION) OffsetRect( &newRect, dx, dy );
616 if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
617 else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
618 if (ON_TOP_BORDER(hittest)) newRect.top += dy;
619 else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
620 if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
621 capturePoint = pt;
622
623 /* determine the hit location */
624 if (hittest >= HTLEFT && hittest <= HTBOTTOMRIGHT)
625 wpSizingHit = WMSZ_LEFT + (hittest - HTLEFT);
626 unmodRect = newRect;
627 SendMessageA( hwnd, WM_SIZING, wpSizingHit, (LPARAM)&newRect );
628
629 if (!iconic)
630 {
631 if(!DragFullWindows)
632 UserDrawMovingFrame( hdc, &newRect, thickframe );
633 else {
634 /* To avoid any deadlocks, all the locks on the windows
635 structures must be suspended before the SetWindowPos */
636 SetWindowPos( hwnd, 0, newRect.left, newRect.top,
637 newRect.right - newRect.left,
638 newRect.bottom - newRect.top,
639 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
640 }
641 }
642 sizingRect = newRect;
643 }
644 }
645 }
646
647 ReleaseCapture();
648 ClipCursor(NULL);
649 if( iconic )
650 {
651 if( moved ) /* restore cursors, show icon title later on */
652 {
653 ShowCursor( FALSE );
654 SetCursor( hOldCursor );
655 }
656 DestroyCursor( hDragCursor );
657 }
658 else if(!DragFullWindows)
659 UserDrawMovingFrame( hdc, &sizingRect, thickframe );
660
661 if (Style & WS_CHILD)
662 ReleaseDC( hWndParent, hdc );
663 else
664 {
665 ReleaseDC( 0, hdc );
666 if(DesktopRgn)
667 {
668 DeleteObject(DesktopRgn);
669 }
670 }
671
672 if (ISITHOOKED(WH_CBT))
673 {
674 LRESULT lResult;
675 NtUserMessageCall( hwnd, WM_CBT, HCBT_MOVESIZE, (LPARAM)&sizingRect, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, FALSE);
676 if (lResult) moved = FALSE;
677 }
678
679 (void)NtUserSetGUIThreadHandle(MSQ_STATE_MOVESIZE, NULL);
680 SendMessageA( hwnd, WM_EXITSIZEMOVE, 0, 0 );
681 SendMessageA( hwnd, WM_SETVISIBLE, !IsIconic(hwnd), 0L);
682
683 /* window moved or resized */
684 if (moved)
685 {
686 /* if the moving/resizing isn't canceled call SetWindowPos
687 * with the new position or the new size of the window
688 */
689 if (!((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) )
690 {
691 /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
692 if(!DragFullWindows)
693 SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
694 sizingRect.right - sizingRect.left,
695 sizingRect.bottom - sizingRect.top,
696 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
697 }
698 else { /* restore previous size/position */
699 if(DragFullWindows)
700 SetWindowPos( hwnd, 0, origRect.left, origRect.top,
701 origRect.right - origRect.left,
702 origRect.bottom - origRect.top,
703 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
704 }
705 }
706
707 if( IsWindow(hwnd) )
708 if( Style & WS_MINIMIZE )
709 {
710 /* Single click brings up the system menu when iconized */
711
712 if( !moved )
713 {
714 if( Style & WS_SYSMENU )
715 SendMessageA( hwnd, WM_SYSCOMMAND,
716 SC_MOUSEMENU + HTSYSMENU, MAKELONG(pt.x,pt.y));
717 }
718 }
719 }
720
721
722 /***********************************************************************
723 * DefWndTrackScrollBar
724 *
725 * Track a mouse button press on the horizontal or vertical scroll-bar.
726 */
727 static VOID
728 DefWndTrackScrollBar(HWND Wnd, WPARAM wParam, POINT Pt)
729 {
730 INT ScrollBar;
731
732 if (SC_HSCROLL == (wParam & 0xfff0))
733 {
734 if (HTHSCROLL != (wParam & 0x0f))
735 {
736 return;
737 }
738 ScrollBar = SB_HORZ;
739 }
740 else /* SC_VSCROLL */
741 {
742 if (HTVSCROLL != (wParam & 0x0f))
743 {
744 return;
745 }
746 ScrollBar = SB_VERT;
747 }
748 ScrollTrackScrollBar(Wnd, ScrollBar, Pt );
749 }
750
751
752 LRESULT
753 DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
754 {
755 WINDOWPLACEMENT wp;
756 POINT Pt;
757
758 if (!IsWindowEnabled( hWnd )) return 0;
759
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
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 /* with the exception of the border around a resizable wnd,
1360 * give the parent first chance to set the cursor */
1361 if (LOWORD(lParam) < HTLEFT || LOWORD(lParam) > HTBOTTOMRIGHT)
1362 {
1363 HWND parent = GetParent( hWnd );
1364 if (bUnicode)
1365 {
1366 if (parent != GetDesktopWindow() &&
1367 SendMessageW( parent, WM_SETCURSOR, wParam, lParam))
1368 return TRUE;
1369 }
1370 else
1371 {
1372 if (parent != GetDesktopWindow() &&
1373 SendMessageA( parent, WM_SETCURSOR, wParam, lParam))
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 iMenuSysKey = 1;
1398 else
1399 iMenuSysKey = 0;
1400
1401 iF10Key = 0;
1402
1403 if (wParam == VK_F4) /* Try to close the window */
1404 {
1405 if (!(GetClassLongPtrW(top, GCL_STYLE) & CS_NOCLOSE))
1406 {
1407 if (bUnicode)
1408 PostMessageW(top, WM_SYSCOMMAND, SC_CLOSE, 0);
1409 else
1410 PostMessageA(top, WM_SYSCOMMAND, SC_CLOSE, 0);
1411 }
1412 }
1413 else if (wParam == VK_SNAPSHOT)
1414 {
1415 HWND hwnd = hWnd;
1416 while (GetParent(hwnd) != NULL)
1417 {
1418 hwnd = GetParent(hwnd);
1419 }
1420 DefWndScreenshot(hwnd);
1421 }
1422 }
1423 else if( wParam == VK_F10 )
1424 {
1425 if (GetKeyState(VK_SHIFT) & 0x8000)
1426 SendMessageW( hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, MAKELPARAM(-1, -1) );
1427 iF10Key = 1;
1428 }
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 MENU_EndMenu( hWnd );
1486 if (GetCapture() == hWnd)
1487 {
1488 ReleaseCapture();
1489 }
1490 break;
1491 }
1492
1493 case WM_VKEYTOITEM:
1494 case WM_CHARTOITEM:
1495 return (-1);
1496 /*
1497 case WM_DROPOBJECT:
1498 return DRAG_FILE;
1499 */
1500 case WM_QUERYDROPOBJECT:
1501 {
1502 if (GetWindowLongPtrW(hWnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES)
1503 {
1504 return(1);
1505 }
1506 break;
1507 }
1508
1509 case WM_QUERYDRAGICON:
1510 {
1511 UINT Len;
1512 HICON hIcon;
1513
1514 hIcon = (HICON)GetClassLongPtrW(hWnd, GCL_HICON);
1515 if (hIcon)
1516 {
1517 return ((LRESULT)hIcon);
1518 }
1519 for (Len = 1; Len < 64; Len++)
1520 {
1521 if ((hIcon = LoadIconW(NULL, MAKEINTRESOURCEW(Len))) != NULL)
1522 {
1523 return((LRESULT)hIcon);
1524 }
1525 }
1526 return ((LRESULT)LoadIconW(0, IDI_APPLICATION));
1527 }
1528
1529 case WM_ISACTIVEICON:
1530 {
1531 PWND pWnd;
1532 BOOL isai;
1533 pWnd = ValidateHwnd(hWnd);
1534 if (!pWnd) return 0;
1535 isai = (pWnd->state & WNDS_ACTIVEFRAME) != 0;
1536 return isai;
1537 }
1538
1539 case WM_NOTIFYFORMAT:
1540 {
1541 if (lParam == NF_QUERY)
1542 return IsWindowUnicode(hWnd) ? NFR_UNICODE : NFR_ANSI;
1543 break;
1544 }
1545
1546 case WM_SETICON:
1547 {
1548 INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
1549 HICON hOldIcon = (HICON)GetClassLongPtrW(hWnd, Index);
1550 SetClassLongPtrW(hWnd, Index, lParam);
1551 SetWindowPos(hWnd, 0, 0, 0, 0, 0,
1552 SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
1553 SWP_NOACTIVATE | SWP_NOZORDER);
1554 return ((LRESULT)hOldIcon);
1555 }
1556
1557 case WM_GETICON:
1558 {
1559 INT Index = (wParam == ICON_BIG) ? GCL_HICON : GCL_HICONSM;
1560 return (GetClassLongPtrW(hWnd, Index));
1561 }
1562
1563 case WM_HELP:
1564 {
1565 if (bUnicode)
1566 {
1567 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1568 }
1569 else
1570 {
1571 SendMessageA(GetParent(hWnd), Msg, wParam, lParam);
1572 }
1573 break;
1574 }
1575
1576 case WM_SYSTIMER:
1577 {
1578 THRDCARETINFO CaretInfo;
1579 switch(wParam)
1580 {
1581 case 0xffff: /* Caret timer */
1582 /* switch showing byte in win32k and get information about the caret */
1583 if(NtUserSwitchCaretShowing(&CaretInfo) && (CaretInfo.hWnd == hWnd))
1584 {
1585 DrawCaret(hWnd, &CaretInfo);
1586 }
1587 break;
1588 }
1589 break;
1590 }
1591
1592 case WM_QUERYOPEN:
1593 case WM_QUERYENDSESSION:
1594 {
1595 return (1);
1596 }
1597
1598 case WM_INPUTLANGCHANGEREQUEST:
1599 {
1600 HKL NewHkl;
1601
1602 if(wParam & INPUTLANGCHANGE_BACKWARD
1603 && wParam & INPUTLANGCHANGE_FORWARD)
1604 {
1605 return FALSE;
1606 }
1607
1608 //FIXME: What to do with INPUTLANGCHANGE_SYSCHARSET ?
1609
1610 if(wParam & INPUTLANGCHANGE_BACKWARD) NewHkl = (HKL) HKL_PREV;
1611 else if(wParam & INPUTLANGCHANGE_FORWARD) NewHkl = (HKL) HKL_NEXT;
1612 else NewHkl = (HKL) lParam;
1613
1614 NtUserActivateKeyboardLayout(NewHkl, 0);
1615
1616 return TRUE;
1617 }
1618
1619 case WM_INPUTLANGCHANGE:
1620 {
1621 int count = 0;
1622 HWND *win_array = WIN_ListChildren( hWnd );
1623
1624 if (!win_array)
1625 break;
1626 while (win_array[count])
1627 SendMessageW( win_array[count++], WM_INPUTLANGCHANGE, wParam, lParam);
1628 HeapFree(GetProcessHeap(),0,win_array);
1629 break;
1630 }
1631
1632 case WM_QUERYUISTATE:
1633 {
1634 LRESULT Ret = 0;
1635 PWND Wnd = ValidateHwnd(hWnd);
1636 if (Wnd != NULL)
1637 {
1638 if (Wnd->HideFocus)
1639 Ret |= UISF_HIDEFOCUS;
1640 if (Wnd->HideAccel)
1641 Ret |= UISF_HIDEACCEL;
1642 }
1643 return Ret;
1644 }
1645
1646 case WM_CHANGEUISTATE:
1647 {
1648 BOOL AlwaysShowCues = FALSE;
1649 WORD Action = LOWORD(wParam);
1650 WORD Flags = HIWORD(wParam);
1651 PWND Wnd;
1652
1653 SystemParametersInfoW(SPI_GETKEYBOARDCUES, 0, &AlwaysShowCues, 0);
1654 if (AlwaysShowCues)
1655 break;
1656
1657 Wnd= ValidateHwnd(hWnd);
1658 if (!Wnd || lParam != 0)
1659 break;
1660
1661 if (Flags & ~(UISF_HIDEFOCUS | UISF_HIDEACCEL | UISF_ACTIVE))
1662 break;
1663
1664 if (Flags & UISF_ACTIVE)
1665 {
1666 WARN("WM_CHANGEUISTATE does not yet support UISF_ACTIVE!\n");
1667 }
1668
1669 if (Action == UIS_INITIALIZE)
1670 {
1671 PDESKTOPINFO Desk = GetThreadDesktopInfo();
1672 if (Desk == NULL)
1673 break;
1674
1675 Action = Desk->LastInputWasKbd ? UIS_CLEAR : UIS_SET;
1676 Flags = UISF_HIDEFOCUS | UISF_HIDEACCEL;
1677
1678 /* We need to update wParam in case we need to send out messages */
1679 wParam = MAKEWPARAM(Action, Flags);
1680 }
1681
1682 switch (Action)
1683 {
1684 case UIS_SET:
1685 /* See if we actually need to change something */
1686 if ((Flags & UISF_HIDEFOCUS) && !Wnd->HideFocus)
1687 break;
1688 if ((Flags & UISF_HIDEACCEL) && !Wnd->HideAccel)
1689 break;
1690
1691 /* Don't need to do anything... */
1692 return 0;
1693
1694 case UIS_CLEAR:
1695 /* See if we actually need to change something */
1696 if ((Flags & UISF_HIDEFOCUS) && Wnd->HideFocus)
1697 break;
1698 if ((Flags & UISF_HIDEACCEL) && Wnd->HideAccel)
1699 break;
1700
1701 /* Don't need to do anything... */
1702 return 0;
1703
1704 default:
1705 WARN("WM_CHANGEUISTATE: Unsupported Action 0x%x\n", Action);
1706 break;
1707 }
1708
1709 if ((Wnd->style & WS_CHILD) && Wnd->spwndParent != NULL)
1710 {
1711 /* We're a child window and we need to pass this message down until
1712 we reach the root */
1713 hWnd = UserHMGetHandle((PWND)DesktopPtrToUser(Wnd->spwndParent));
1714 }
1715 else
1716 {
1717 /* We're a top level window, we need to change the UI state */
1718 Msg = WM_UPDATEUISTATE;
1719 }
1720
1721 if (bUnicode)
1722 return SendMessageW(hWnd, Msg, wParam, lParam);
1723 else
1724 return SendMessageA(hWnd, Msg, wParam, lParam);
1725 }
1726
1727 case WM_UPDATEUISTATE:
1728 {
1729 BOOL Change = TRUE;
1730 BOOL AlwaysShowCues = FALSE;
1731 WORD Action = LOWORD(wParam);
1732 WORD Flags = HIWORD(wParam);
1733 PWND Wnd;
1734
1735 SystemParametersInfoW(SPI_GETKEYBOARDCUES, 0, &AlwaysShowCues, 0);
1736 if (AlwaysShowCues)
1737 break;
1738
1739 Wnd = ValidateHwnd(hWnd);
1740 if (!Wnd || lParam != 0)
1741 break;
1742
1743 if (Flags & ~(UISF_HIDEFOCUS | UISF_HIDEACCEL | UISF_ACTIVE))
1744 break;
1745
1746 if (Flags & UISF_ACTIVE)
1747 {
1748 WARN("WM_UPDATEUISTATE does not yet support UISF_ACTIVE!\n");
1749 }
1750
1751 if (Action == UIS_INITIALIZE)
1752 {
1753 PDESKTOPINFO Desk = GetThreadDesktopInfo();
1754 if (Desk == NULL)
1755 break;
1756
1757 Action = Desk->LastInputWasKbd ? UIS_CLEAR : UIS_SET;
1758 Flags = UISF_HIDEFOCUS | UISF_HIDEACCEL;
1759
1760 /* We need to update wParam for broadcasting the update */
1761 wParam = MAKEWPARAM(Action, Flags);
1762 }
1763
1764 switch (Action)
1765 {
1766 case UIS_SET:
1767 /* See if we actually need to change something */
1768 if ((Flags & UISF_HIDEFOCUS) && !Wnd->HideFocus)
1769 break;
1770 if ((Flags & UISF_HIDEACCEL) && !Wnd->HideAccel)
1771 break;
1772
1773 /* Don't need to do anything... */
1774 Change = FALSE;
1775 break;
1776
1777 case UIS_CLEAR:
1778 /* See if we actually need to change something */
1779 if ((Flags & UISF_HIDEFOCUS) && Wnd->HideFocus)
1780 break;
1781 if ((Flags & UISF_HIDEACCEL) && Wnd->HideAccel)
1782 break;
1783
1784 /* Don't need to do anything... */
1785 Change = FALSE;
1786 break;
1787
1788 default:
1789 WARN("WM_UPDATEUISTATE: Unsupported Action 0x%x\n", Action);
1790 return 0;
1791 }
1792
1793 /* Pack the information and call win32k */
1794 if (Change)
1795 {
1796 if (!NtUserCallTwoParam((DWORD_PTR)hWnd, (DWORD_PTR)Flags | ((DWORD_PTR)Action << 3), TWOPARAM_ROUTINE_ROS_UPDATEUISTATE))
1797 break;
1798 }
1799
1800 /* Always broadcast the update to all children */
1801 EnumChildWindows(hWnd,
1802 UserSendUiUpdateMsg,
1803 (LPARAM)wParam);
1804
1805 break;
1806 }
1807
1808 }
1809 return 0;
1810 }
1811
1812
1813 /*
1814 * helpers for calling IMM32 (from Wine 10/22/2008)
1815 *
1816 * WM_IME_* messages are generated only by IMM32,
1817 * so I assume imm32 is already LoadLibrary-ed.
1818 */
1819 static HWND
1820 DefWndImmGetDefaultIMEWnd(HWND hwnd)
1821 {
1822 HINSTANCE hInstIMM = GetModuleHandleW(L"imm32\0");
1823 HWND (WINAPI *pFunc)(HWND);
1824 HWND hwndRet = 0;
1825
1826 if (!hInstIMM)
1827 {
1828 ERR("cannot get IMM32 handle\n");
1829 return 0;
1830 }
1831
1832 pFunc = (void*) GetProcAddress(hInstIMM, "ImmGetDefaultIMEWnd");
1833 if (pFunc != NULL)
1834 hwndRet = (*pFunc)(hwnd);
1835
1836 return hwndRet;
1837 }
1838
1839
1840 static BOOL
1841 DefWndImmIsUIMessageA(HWND hwndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1842 {
1843 HINSTANCE hInstIMM = GetModuleHandleW(L"imm32\0");
1844 BOOL (WINAPI *pFunc)(HWND,UINT,WPARAM,LPARAM);
1845 BOOL fRet = FALSE;
1846
1847 if (!hInstIMM)
1848 {
1849 ERR("cannot get IMM32 handle\n");
1850 return FALSE;
1851 }
1852
1853 pFunc = (void*) GetProcAddress(hInstIMM, "ImmIsUIMessageA");
1854 if (pFunc != NULL)
1855 fRet = (*pFunc)(hwndIME, msg, wParam, lParam);
1856
1857 return fRet;
1858 }
1859
1860
1861 static BOOL
1862 DefWndImmIsUIMessageW(HWND hwndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1863 {
1864 HINSTANCE hInstIMM = GetModuleHandleW(L"imm32\0");
1865 BOOL (WINAPI *pFunc)(HWND,UINT,WPARAM,LPARAM);
1866 BOOL fRet = FALSE;
1867
1868 if (!hInstIMM)
1869 {
1870 ERR("cannot get IMM32 handle\n");
1871 return FALSE;
1872 }
1873
1874 pFunc = (void*) GetProcAddress(hInstIMM, "ImmIsUIMessageW");
1875 if (pFunc != NULL)
1876 fRet = (*pFunc)(hwndIME, msg, wParam, lParam);
1877
1878 return fRet;
1879 }
1880
1881
1882 LRESULT WINAPI
1883 RealDefWindowProcA(HWND hWnd,
1884 UINT Msg,
1885 WPARAM wParam,
1886 LPARAM lParam)
1887 {
1888 LRESULT Result = 0;
1889 PWND Wnd;
1890
1891 SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam);
1892 switch (Msg)
1893 {
1894 case WM_NCCREATE:
1895 {
1896 if (lParam)
1897 {
1898 LPCREATESTRUCTA cs = (LPCREATESTRUCTA)lParam;
1899 /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
1900 * may have child window IDs instead of window name */
1901 if (HIWORD(cs->lpszName))
1902 {
1903 DefSetText(hWnd, (PCWSTR)cs->lpszName, TRUE);
1904 }
1905 Result = 1;
1906 }
1907 break;
1908 }
1909
1910 case WM_GETTEXTLENGTH:
1911 {
1912 PWSTR buf;
1913 ULONG len;
1914
1915 Wnd = ValidateHwnd(hWnd);
1916 if (Wnd != NULL && Wnd->strName.Length != 0)
1917 {
1918 buf = DesktopPtrToUser(Wnd->strName.Buffer);
1919 if (buf != NULL &&
1920 NT_SUCCESS(RtlUnicodeToMultiByteSize(&len,
1921 buf,
1922 Wnd->strName.Length)))
1923 {
1924 Result = (LRESULT) len;
1925 }
1926 }
1927 else Result = 0L;
1928
1929 break;
1930 }
1931
1932 case WM_GETTEXT:
1933 {
1934 PWSTR buf = NULL;
1935 PSTR outbuf = (PSTR)lParam;
1936 UINT copy;
1937
1938 Wnd = ValidateHwnd(hWnd);
1939 if (Wnd != NULL && wParam != 0)
1940 {
1941 if (Wnd->strName.Buffer != NULL)
1942 buf = DesktopPtrToUser(Wnd->strName.Buffer);
1943 else
1944 outbuf[0] = L'\0';
1945
1946 if (buf != NULL)
1947 {
1948 if (Wnd->strName.Length != 0)
1949 {
1950 copy = min(Wnd->strName.Length / sizeof(WCHAR), wParam - 1);
1951 Result = WideCharToMultiByte(CP_ACP,
1952 0,
1953 buf,
1954 copy,
1955 outbuf,
1956 wParam,
1957 NULL,
1958 NULL);
1959 outbuf[Result] = '\0';
1960 }
1961 else
1962 outbuf[0] = '\0';
1963 }
1964 }
1965 break;
1966 }
1967
1968 case WM_SETTEXT:
1969 {
1970 DefSetText(hWnd, (PCWSTR)lParam, TRUE);
1971
1972 if ((GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
1973 {
1974 DefWndNCPaint(hWnd, (HRGN)1, -1);
1975 }
1976
1977 Result = 1;
1978 break;
1979 }
1980
1981 case WM_IME_KEYDOWN:
1982 {
1983 Result = PostMessageA(hWnd, WM_KEYDOWN, wParam, lParam);
1984 break;
1985 }
1986
1987 case WM_IME_KEYUP:
1988 {
1989 Result = PostMessageA(hWnd, WM_KEYUP, wParam, lParam);
1990 break;
1991 }
1992
1993 case WM_IME_CHAR:
1994 {
1995 if (HIBYTE(wParam))
1996 PostMessageA(hWnd, WM_CHAR, HIBYTE(wParam), lParam);
1997 PostMessageA(hWnd, WM_CHAR, LOBYTE(wParam), lParam);
1998 break;
1999 }
2000
2001 case WM_IME_STARTCOMPOSITION:
2002 case WM_IME_COMPOSITION:
2003 case WM_IME_ENDCOMPOSITION:
2004 case WM_IME_SELECT:
2005 case WM_IME_NOTIFY:
2006 {
2007 HWND hwndIME;
2008
2009 hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
2010 if (hwndIME)
2011 Result = SendMessageA(hwndIME, Msg, wParam, lParam);
2012 break;
2013 }
2014
2015 case WM_IME_SETCONTEXT:
2016 {
2017 HWND hwndIME;
2018
2019 hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
2020 if (hwndIME)
2021 Result = DefWndImmIsUIMessageA(hwndIME, Msg, wParam, lParam);
2022 break;
2023 }
2024
2025 /* fall through */
2026 default:
2027 Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, FALSE);
2028 }
2029
2030 SPY_ExitMessage(SPY_RESULT_DEFWND, hWnd, Msg, Result, wParam, lParam);
2031 return Result;
2032 }
2033
2034
2035 LRESULT WINAPI
2036 RealDefWindowProcW(HWND hWnd,
2037 UINT Msg,
2038 WPARAM wParam,
2039 LPARAM lParam)
2040 {
2041 LRESULT Result = 0;
2042 PWND Wnd;
2043
2044 SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam);
2045 switch (Msg)
2046 {
2047 case WM_NCCREATE:
2048 {
2049 if (lParam)
2050 {
2051 LPCREATESTRUCTW cs = (LPCREATESTRUCTW)lParam;
2052 /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
2053 * may have child window IDs instead of window name */
2054 if (HIWORD(cs->lpszName))
2055 {
2056 DefSetText(hWnd, cs->lpszName, FALSE);
2057 }
2058 Result = 1;
2059 }
2060 break;
2061 }
2062
2063 case WM_GETTEXTLENGTH:
2064 {
2065 PWSTR buf;
2066 ULONG len;
2067
2068 Wnd = ValidateHwnd(hWnd);
2069 if (Wnd != NULL && Wnd->strName.Length != 0)
2070 {
2071 buf = DesktopPtrToUser(Wnd->strName.Buffer);
2072 if (buf != NULL &&
2073 NT_SUCCESS(RtlUnicodeToMultiByteSize(&len,
2074 buf,
2075 Wnd->strName.Length)))
2076 {
2077 Result = (LRESULT) (Wnd->strName.Length / sizeof(WCHAR));
2078 }
2079 }
2080 else Result = 0L;
2081
2082 break;
2083 }
2084
2085 case WM_GETTEXT:
2086 {
2087 PWSTR buf = NULL;
2088 PWSTR outbuf = (PWSTR)lParam;
2089
2090 Wnd = ValidateHwnd(hWnd);
2091 if (Wnd != NULL && wParam != 0)
2092 {
2093 if (Wnd->strName.Buffer != NULL)
2094 buf = DesktopPtrToUser(Wnd->strName.Buffer);
2095 else
2096 outbuf[0] = L'\0';
2097
2098 if (buf != NULL)
2099 {
2100 if (Wnd->strName.Length != 0)
2101 {
2102 Result = min(Wnd->strName.Length / sizeof(WCHAR), wParam - 1);
2103 RtlCopyMemory(outbuf,
2104 buf,
2105 Result * sizeof(WCHAR));
2106 outbuf[Result] = L'\0';
2107 }
2108 else
2109 outbuf[0] = L'\0';
2110 }
2111 }
2112 break;
2113 }
2114
2115 case WM_SETTEXT:
2116 {
2117 DefSetText(hWnd, (PCWSTR)lParam, FALSE);
2118
2119 if ((GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
2120 {
2121 DefWndNCPaint(hWnd, (HRGN)1, -1);
2122 }
2123 Result = 1;
2124 break;
2125 }
2126
2127 case WM_IME_CHAR:
2128 {
2129 PostMessageW(hWnd, WM_CHAR, wParam, lParam);
2130 Result = 0;
2131 break;
2132 }
2133
2134 case WM_IME_KEYDOWN:
2135 {
2136 Result = PostMessageW(hWnd, WM_KEYDOWN, wParam, lParam);
2137 break;
2138 }
2139
2140 case WM_IME_KEYUP:
2141 {
2142 Result = PostMessageW(hWnd, WM_KEYUP, wParam, lParam);
2143 break;
2144 }
2145
2146 case WM_IME_STARTCOMPOSITION:
2147 case WM_IME_COMPOSITION:
2148 case WM_IME_ENDCOMPOSITION:
2149 case WM_IME_SELECT:
2150 case WM_IME_NOTIFY:
2151 {
2152 HWND hwndIME;
2153
2154 hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
2155 if (hwndIME)
2156 Result = SendMessageW(hwndIME, Msg, wParam, lParam);
2157 break;
2158 }
2159
2160 case WM_IME_SETCONTEXT:
2161 {
2162 HWND hwndIME;
2163
2164 hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
2165 if (hwndIME)
2166 Result = DefWndImmIsUIMessageW(hwndIME, Msg, wParam, lParam);
2167 break;
2168 }
2169
2170 default:
2171 Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, TRUE);
2172 }
2173 SPY_ExitMessage(SPY_RESULT_DEFWND, hWnd, Msg, Result, wParam, lParam);
2174
2175 return Result;
2176 }
2177
2178 LRESULT WINAPI
2179 DefWindowProcA(HWND hWnd,
2180 UINT Msg,
2181 WPARAM wParam,
2182 LPARAM lParam)
2183 {
2184 BOOL Hook, msgOverride = FALSE;
2185 LRESULT Result = 0;
2186
2187 LOADUSERAPIHOOK
2188
2189 Hook = BeginIfHookedUserApiHook();
2190 if (Hook)
2191 msgOverride = IsMsgOverride(Msg, &guah.DefWndProcArray);
2192
2193 /* Bypass SEH and go direct. */
2194 if (!Hook || !msgOverride)
2195 return RealDefWindowProcA(hWnd, Msg, wParam, lParam);
2196
2197 _SEH2_TRY
2198 {
2199 Result = guah.DefWindowProcA(hWnd, Msg, wParam, lParam);
2200 }
2201 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2202 {
2203 }
2204 _SEH2_END;
2205
2206 EndUserApiHook();
2207
2208 return Result;
2209 }
2210
2211 LRESULT WINAPI
2212 DefWindowProcW(HWND hWnd,
2213 UINT Msg,
2214 WPARAM wParam,
2215 LPARAM lParam)
2216 {
2217 BOOL Hook, msgOverride = FALSE;
2218 LRESULT Result = 0;
2219
2220 LOADUSERAPIHOOK
2221
2222 Hook = BeginIfHookedUserApiHook();
2223 if (Hook)
2224 msgOverride = IsMsgOverride(Msg, &guah.DefWndProcArray);
2225
2226 /* Bypass SEH and go direct. */
2227 if (!Hook || !msgOverride)
2228 return RealDefWindowProcW(hWnd, Msg, wParam, lParam);
2229
2230 _SEH2_TRY
2231 {
2232 Result = guah.DefWindowProcW(hWnd, Msg, wParam, lParam);
2233 }
2234 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2235 {
2236 }
2237 _SEH2_END;
2238
2239 EndUserApiHook();
2240
2241 return Result;
2242 }