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