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