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