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