[user32]
[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 LRESULT NC_HandleNCRButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam );
26 void FASTCALL MenuInitSysMenuPopup(HMENU Menu, DWORD Style, DWORD ClsStyle, LONG HitTest );
27 void MENU_EndMenu( HWND );
28
29 /* GLOBALS *******************************************************************/
30
31 static short iF10Key = 0;
32 static short iMenuSysKey = 0;
33
34 /* FUNCTIONS *****************************************************************/
35
36 /*
37 * @implemented
38 */
39 DWORD
40 WINAPI
41 DECLSPEC_HOTPATCH
42 GetSysColor(int nIndex)
43 {
44 if(nIndex >= 0 && nIndex < NUM_SYSCOLORS)
45 {
46 return gpsi->argbSystem[nIndex];
47 }
48
49 SetLastError(ERROR_INVALID_PARAMETER);
50 return 0;
51 }
52
53 /*
54 * @implemented
55 */
56 HBRUSH
57 WINAPI
58 DECLSPEC_HOTPATCH
59 GetSysColorBrush(int nIndex)
60 {
61 if(nIndex >= 0 && nIndex < NUM_SYSCOLORS)
62 {
63 return gpsi->ahbrSystem[nIndex];
64 }
65
66 SetLastError(ERROR_INVALID_PARAMETER);
67 return NULL;
68 }
69
70 /*
71 * @implemented
72 */
73 BOOL
74 WINAPI
75 SetSysColors(
76 int cElements,
77 CONST INT *lpaElements,
78 CONST COLORREF *lpaRgbValues)
79 {
80 return NtUserSetSysColors(cElements, lpaElements, lpaRgbValues, 0);
81 }
82
83 BOOL
84 FASTCALL
85 DefSetText(HWND hWnd, PCWSTR String, BOOL Ansi)
86 {
87 BOOL Ret;
88 LARGE_STRING lsString;
89
90 if ( String )
91 {
92 if ( Ansi )
93 RtlInitLargeAnsiString((PLARGE_ANSI_STRING)&lsString, (PCSZ)String, 0);
94 else
95 RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&lsString, String, 0);
96 }
97 Ret = NtUserDefSetText(hWnd, (String ? &lsString : NULL));
98
99 if (Ret)
100 IntNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hWnd, OBJID_WINDOW, CHILDID_SELF, 0);
101
102 return Ret;
103 }
104
105 void
106 UserGetInsideRectNC(PWND Wnd, RECT *rect)
107 {
108 ULONG Style;
109 ULONG ExStyle;
110
111 Style = Wnd->style;
112 ExStyle = Wnd->ExStyle;
113
114 rect->top = rect->left = 0;
115 rect->right = Wnd->rcWindow.right - Wnd->rcWindow.left;
116 rect->bottom = Wnd->rcWindow.bottom - Wnd->rcWindow.top;
117
118 if (Style & WS_ICONIC)
119 {
120 return;
121 }
122
123 /* Remove frame from rectangle */
124 if (UserHasThickFrameStyle(Style, ExStyle ))
125 {
126 InflateRect(rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME));
127 }
128 else
129 {
130 if (UserHasDlgFrameStyle(Style, ExStyle ))
131 {
132 InflateRect(rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
133 /* FIXME: this isn't in NC_AdjustRect? why not? */
134 if (ExStyle & WS_EX_DLGMODALFRAME)
135 InflateRect( rect, -1, 0 );
136 }
137 else
138 {
139 if (UserHasThinFrameStyle(Style, ExStyle))
140 {
141 InflateRect(rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
142 }
143 }
144 }
145 /* We have additional border information if the window
146 * is a child (but not an MDI child) */
147 if ((Style & WS_CHILD) && !(ExStyle & WS_EX_MDICHILD))
148 {
149 if (ExStyle & WS_EX_CLIENTEDGE)
150 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
151 if (ExStyle & WS_EX_STATICEDGE)
152 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
153 }
154 }
155
156 LRESULT
157 DefWndHandleSetCursor(HWND hWnd, WPARAM wParam, LPARAM lParam, ULONG Style)
158 {
159 /* Not for child windows. */
160 if (hWnd != (HWND)wParam)
161 {
162 return(0);
163 }
164
165 switch((INT_PTR) LOWORD(lParam))
166 {
167 case HTERROR:
168 {
169 WORD Msg = HIWORD(lParam);
170 if (Msg == WM_LBUTTONDOWN || Msg == WM_MBUTTONDOWN ||
171 Msg == WM_RBUTTONDOWN || Msg == WM_XBUTTONDOWN)
172 {
173 MessageBeep(0);
174 }
175 break;
176 }
177
178 case HTCLIENT:
179 {
180 HICON hCursor = (HICON)GetClassLongPtrW(hWnd, GCL_HCURSOR);
181 if (hCursor)
182 {
183 SetCursor(hCursor);
184 return(TRUE);
185 }
186 return(FALSE);
187 }
188
189 case HTLEFT:
190 case HTRIGHT:
191 {
192 if (Style & WS_MAXIMIZE)
193 {
194 break;
195 }
196 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZEWE)));
197 }
198
199 case HTTOP:
200 case HTBOTTOM:
201 {
202 if (Style & WS_MAXIMIZE)
203 {
204 break;
205 }
206 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENS)));
207 }
208
209 case HTTOPLEFT:
210 case HTBOTTOMRIGHT:
211 {
212 if (Style & WS_MAXIMIZE)
213 {
214 break;
215 }
216 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENWSE)));
217 }
218
219 case HTBOTTOMLEFT:
220 case HTTOPRIGHT:
221 {
222 if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_MAXIMIZE)
223 {
224 break;
225 }
226 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENESW)));
227 }
228 }
229 return((LRESULT)SetCursor(LoadCursorW(0, IDC_ARROW)));
230 }
231
232 /***********************************************************************
233 * DefWndTrackScrollBar
234 *
235 * Track a mouse button press on the horizontal or vertical scroll-bar.
236 */
237 static VOID
238 DefWndTrackScrollBar(HWND Wnd, WPARAM wParam, POINT Pt)
239 {
240 INT ScrollBar;
241
242 if (SC_HSCROLL == (wParam & 0xfff0))
243 {
244 if (HTHSCROLL != (wParam & 0x0f))
245 {
246 return;
247 }
248 ScrollBar = SB_HORZ;
249 }
250 else /* SC_VSCROLL */
251 {
252 if (HTVSCROLL != (wParam & 0x0f))
253 {
254 return;
255 }
256 ScrollBar = SB_VERT;
257 }
258 ScrollTrackScrollBar(Wnd, ScrollBar, Pt );
259 }
260
261 LRESULT WINAPI DoAppSwitch( WPARAM wParam, LPARAM lParam);
262
263 LRESULT
264 DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
265 {
266 POINT Pt;
267 LRESULT lResult;
268
269 if (!IsWindowEnabled( hWnd )) return 0;
270
271 if (ISITHOOKED(WH_CBT))
272 {
273 NtUserMessageCall( hWnd, WM_SYSCOMMAND, wParam, lParam, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, FALSE);
274 if (lResult) return 0;
275 }
276
277 switch (wParam & 0xfff0)
278 {
279 case SC_MOVE:
280 case SC_SIZE:
281 NtUserMessageCall( hWnd, WM_SYSCOMMAND, wParam, lParam, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, FALSE);
282 break;
283
284 case SC_MINIMIZE:
285 if (hWnd == GetActiveWindow())
286 ShowOwnedPopups(hWnd,FALSE);
287 ShowWindow( hWnd, SW_MINIMIZE );
288 break;
289
290 case SC_MAXIMIZE:
291 if (IsIconic(hWnd) && hWnd == GetActiveWindow())
292 ShowOwnedPopups(hWnd,TRUE);
293 ShowWindow( hWnd, SW_MAXIMIZE );
294 break;
295
296 case SC_RESTORE:
297 if (IsIconic(hWnd) && hWnd == GetActiveWindow())
298 ShowOwnedPopups(hWnd,TRUE);
299 ShowWindow( hWnd, SW_RESTORE );
300 break;
301
302 case SC_CLOSE:
303 return SendMessageW(hWnd, WM_CLOSE, 0, 0);
304
305 // case SC_DEFAULT:
306 case SC_MOUSEMENU:
307 {
308 Pt.x = (short)LOWORD(lParam);
309 Pt.y = (short)HIWORD(lParam);
310 MenuTrackMouseMenuBar(hWnd, wParam & 0x000f, Pt);
311 }
312 break;
313 case SC_KEYMENU:
314 MenuTrackKbdMenuBar(hWnd, wParam, (WCHAR)lParam);
315 break;
316 case SC_VSCROLL:
317 case SC_HSCROLL:
318 {
319 Pt.x = (short)LOWORD(lParam);
320 Pt.y = (short)HIWORD(lParam);
321 DefWndTrackScrollBar(hWnd, wParam, Pt);
322 }
323 break;
324
325 case SC_TASKLIST:
326 WinExec( "taskman.exe", SW_SHOWNORMAL );
327 break;
328
329 case SC_SCREENSAVE:
330 NtUserMessageCall( hWnd, WM_SYSCOMMAND, wParam, lParam, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, FALSE);
331 break;
332
333 case SC_NEXTWINDOW:
334 case SC_PREVWINDOW:
335 DoAppSwitch( wParam, lParam);
336 break;
337
338 case SC_HOTKEY:
339 {
340 HWND hwnd, hWndLastActive;
341 PWND pWnd;
342
343 hwnd = (HWND)lParam;
344 pWnd = ValidateHwnd(hwnd);
345 if (pWnd)
346 {
347 hWndLastActive = GetLastActivePopup(hwnd);
348 if (hWndLastActive)
349 {
350 hwnd = hWndLastActive;
351 pWnd = ValidateHwnd(hwnd);
352 }
353 SetForegroundWindow(hwnd);
354 if (pWnd->style & WS_MINIMIZE)
355 {
356 PostMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
357 }
358 }
359 }
360 break;
361
362 default:
363 FIXME("Unimplemented DefWndHandleSysCommand wParam 0x%x\n",wParam);
364 break;
365 }
366
367 return(0);
368 }
369
370 /***********************************************************************
371 * DefWndControlColor
372 *
373 * Default colors for control painting.
374 */
375 HBRUSH
376 DefWndControlColor(HDC hDC, UINT ctlType)
377 {
378 if (ctlType == CTLCOLOR_SCROLLBAR)
379 {
380 HBRUSH hb = GetSysColorBrush(COLOR_SCROLLBAR);
381 COLORREF bk = GetSysColor(COLOR_3DHILIGHT);
382 SetTextColor(hDC, GetSysColor(COLOR_3DFACE));
383 SetBkColor(hDC, bk);
384
385 /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
386 * we better use 0x55aa bitmap brush to make scrollbar's background
387 * look different from the window background.
388 */
389 if ( bk == GetSysColor(COLOR_WINDOW))
390 return gpsi->hbrGray;
391
392 UnrealizeObject( hb );
393 return hb;
394 }
395
396 SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
397
398 if ((ctlType == CTLCOLOR_EDIT) || (ctlType == CTLCOLOR_LISTBOX))
399 {
400 SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
401 }
402 else
403 {
404 SetBkColor(hDC, GetSysColor(COLOR_3DFACE));
405 return GetSysColorBrush(COLOR_3DFACE);
406 }
407
408 return GetSysColorBrush(COLOR_WINDOW);
409 }
410
411 static void DefWndPrint( HWND hwnd, HDC hdc, ULONG uFlags)
412 {
413 /*
414 * Visibility flag.
415 */
416 if ( (uFlags & PRF_CHECKVISIBLE) &&
417 !IsWindowVisible(hwnd) )
418 return;
419
420 /*
421 * Unimplemented flags.
422 */
423 if ( (uFlags & PRF_CHILDREN) ||
424 (uFlags & PRF_OWNED) ||
425 (uFlags & PRF_NONCLIENT) )
426 {
427 FIXME("WM_PRINT message with unsupported flags\n");
428 }
429
430 /*
431 * Background
432 */
433 if ( uFlags & PRF_ERASEBKGND)
434 SendMessageW(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
435
436 /*
437 * Client area
438 */
439 if ( uFlags & PRF_CLIENT)
440 SendMessageW(hwnd, WM_PRINTCLIENT, (WPARAM)hdc, uFlags);
441 }
442
443 static BOOL CALLBACK
444 UserSendUiUpdateMsg(HWND hwnd, LPARAM lParam)
445 {
446 SendMessageW(hwnd, WM_UPDATEUISTATE, (WPARAM)lParam, 0);
447 return TRUE;
448 }
449
450 static void
451 UserPaintCaption(HWND hwnd)
452 {
453 /* FIXME: this is not 100% correct */
454
455 /*
456 * When themes are not enabled we can go on and paint the non client area.
457 * However if we do that with themes enabled we will draw a classic frame.
458 * This is sovled by sending a themes specific message to notify the themes
459 * engine that the caption needs to be redrawn
460 */
461 if(gpsi->dwSRVIFlags & SRVINFO_APIHOOK)
462 {
463 SendMessage(hwnd, WM_NCUAHDRAWCAPTION,0,0);
464 }
465 else
466 {
467 DefWndNCPaint(hwnd, HRGN_WINDOW, -1);
468 }
469 }
470
471 // WM_SETICON
472 LRESULT FASTCALL
473 DefWndSetIcon(PWND pWnd, WPARAM wParam, LPARAM lParam)
474 {
475 HICON hIcon, hIconSmall, hIconOld;
476
477 if ( wParam > ICON_SMALL2 )
478 {
479 SetLastError(ERROR_INVALID_PARAMETER);
480 return 0;
481 }
482 hIconSmall = UserGetProp(UserHMGetHandle(pWnd), gpsi->atomIconSmProp);
483 hIcon = UserGetProp(UserHMGetHandle(pWnd), gpsi->atomIconProp);
484
485 hIconOld = wParam == ICON_BIG ? hIcon : hIconSmall;
486
487 switch(wParam)
488 {
489 case ICON_BIG:
490 hIcon = (HICON)lParam;
491 break;
492 case ICON_SMALL:
493 hIconSmall = (HICON)lParam;
494 break;
495 case ICON_SMALL2:
496 ERR("FIXME: Set ICON_SMALL2 support!\n");
497 default:
498 break;
499 }
500
501 NtUserSetProp(UserHMGetHandle(pWnd), gpsi->atomIconProp, hIcon);
502 NtUserSetProp(UserHMGetHandle(pWnd), gpsi->atomIconSmProp, hIconSmall);
503
504 if ((pWnd->style & WS_CAPTION ) == WS_CAPTION)
505 UserPaintCaption(UserHMGetHandle(pWnd)); /* Repaint caption */
506
507 return (LRESULT)hIconOld;
508 }
509
510 LRESULT FASTCALL
511 DefWndGetIcon(PWND pWnd, WPARAM wParam, LPARAM lParam)
512 {
513 HICON hIconRet;
514 if ( wParam > ICON_SMALL2 )
515 {
516 SetLastError(ERROR_INVALID_PARAMETER);
517 return 0;
518 }
519 switch(wParam)
520 {
521 case ICON_BIG:
522 hIconRet = UserGetProp(UserHMGetHandle(pWnd), gpsi->atomIconProp);
523 break;
524 case ICON_SMALL:
525 case ICON_SMALL2:
526 hIconRet = UserGetProp(UserHMGetHandle(pWnd), gpsi->atomIconSmProp);
527 break;
528 default:
529 break;
530 }
531 return (LRESULT)hIconRet;
532 }
533
534 VOID FASTCALL
535 DefWndScreenshot(HWND hWnd)
536 {
537 RECT rect;
538 HDC hdc;
539 INT w;
540 INT h;
541 HBITMAP hbitmap;
542 HDC hdc2;
543
544 OpenClipboard(hWnd);
545 EmptyClipboard();
546
547 hdc = GetWindowDC(hWnd);
548 GetWindowRect(hWnd, &rect);
549 w = rect.right - rect.left;
550 h = rect.bottom - rect.top;
551
552 hbitmap = CreateCompatibleBitmap(hdc, w, h);
553 hdc2 = CreateCompatibleDC(hdc);
554 SelectObject(hdc2, hbitmap);
555
556 BitBlt(hdc2, 0, 0, w, h,
557 hdc, 0, 0,
558 SRCCOPY);
559
560 SetClipboardData(CF_BITMAP, hbitmap);
561
562 ReleaseDC(hWnd, hdc);
563 ReleaseDC(hWnd, hdc2);
564
565 CloseClipboard();
566 }
567
568
569
570 LRESULT WINAPI
571 User32DefWindowProc(HWND hWnd,
572 UINT Msg,
573 WPARAM wParam,
574 LPARAM lParam,
575 BOOL bUnicode)
576 {
577 PWND pWnd = NULL;
578 if (hWnd)
579 {
580 pWnd = ValidateHwnd(hWnd);
581 if (!pWnd) return 0;
582 }
583
584 switch (Msg)
585 {
586 case WM_NCPAINT:
587 {
588 return DefWndNCPaint(hWnd, (HRGN)wParam, -1);
589 }
590
591 case WM_NCCALCSIZE:
592 {
593 return DefWndNCCalcSize(hWnd, (BOOL)wParam, (RECT*)lParam);
594 }
595
596 case WM_POPUPSYSTEMMENU:
597 {
598 /* This is an undocumented message used by the windows taskbar to
599 display the system menu of windows that belong to other processes. */
600 HMENU menu = GetSystemMenu(hWnd, FALSE);
601
602 if (menu)
603 TrackPopupMenu(menu, TPM_LEFTBUTTON|TPM_RIGHTBUTTON,
604 LOWORD(lParam), HIWORD(lParam), 0, hWnd, NULL);
605 return 0;
606 }
607
608 case WM_NCACTIVATE:
609 {
610 return DefWndNCActivate(hWnd, wParam, lParam);
611 }
612
613 case WM_NCHITTEST:
614 {
615 POINT Point;
616 Point.x = GET_X_LPARAM(lParam);
617 Point.y = GET_Y_LPARAM(lParam);
618 return (DefWndNCHitTest(hWnd, Point));
619 }
620
621 case WM_LBUTTONDOWN:
622 case WM_RBUTTONDOWN:
623 case WM_MBUTTONDOWN:
624 iF10Key = iMenuSysKey = 0;
625 break;
626
627 case WM_NCLBUTTONDOWN:
628 {
629 return (DefWndNCLButtonDown(hWnd, wParam, lParam));
630 }
631
632 case WM_LBUTTONDBLCLK:
633 return (DefWndNCLButtonDblClk(hWnd, HTCLIENT, lParam));
634
635 case WM_NCLBUTTONDBLCLK:
636 {
637 return (DefWndNCLButtonDblClk(hWnd, wParam, lParam));
638 }
639
640 case WM_NCRBUTTONDOWN:
641 return NC_HandleNCRButtonDown( hWnd, wParam, lParam );
642
643 case WM_RBUTTONUP:
644 {
645 POINT Pt;
646
647 Pt.x = GET_X_LPARAM(lParam);
648 Pt.y = GET_Y_LPARAM(lParam);
649 ClientToScreen(hWnd, &Pt);
650 lParam = MAKELPARAM(Pt.x, Pt.y);
651 if (bUnicode)
652 {
653 SendMessageW(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
654 }
655 else
656 {
657 SendMessageA(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
658 }
659 break;
660 }
661
662 case WM_NCRBUTTONUP:
663 /*
664 * FIXME : we must NOT send WM_CONTEXTMENU on a WM_NCRBUTTONUP (checked
665 * in Windows), but what _should_ we do? According to MSDN :
666 * "If it is appropriate to do so, the system sends the WM_SYSCOMMAND
667 * message to the window". When is it appropriate?
668 */
669 break;
670
671 case WM_CONTEXTMENU:
672 {
673 if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CHILD)
674 {
675 if (bUnicode)
676 {
677 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
678 }
679 else
680 {
681 SendMessageA(GetParent(hWnd), WM_CONTEXTMENU, wParam, lParam);
682 }
683 }
684 else
685 {
686 POINT Pt;
687 LONG_PTR Style;
688 LONG HitCode;
689
690 Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
691
692 Pt.x = GET_X_LPARAM(lParam);
693 Pt.y = GET_Y_LPARAM(lParam);
694 if (Style & WS_CHILD)
695 {
696 ScreenToClient(GetParent(hWnd), &Pt);
697 }
698
699 HitCode = DefWndNCHitTest(hWnd, Pt);
700
701 if (HitCode == HTCAPTION || HitCode == HTSYSMENU)
702 {
703 HMENU SystemMenu;
704 UINT Flags;
705
706 if((SystemMenu = GetSystemMenu(hWnd, FALSE)))
707 {
708 MenuInitSysMenuPopup(SystemMenu, GetWindowLongPtrW(hWnd, GWL_STYLE),
709 GetClassLongPtrW(hWnd, GCL_STYLE), HitCode);
710
711 if(HitCode == HTCAPTION)
712 Flags = TPM_LEFTBUTTON | TPM_RIGHTBUTTON;
713 else
714 Flags = TPM_LEFTBUTTON;
715
716 TrackPopupMenu(SystemMenu, Flags,
717 Pt.x, Pt.y, 0, hWnd, NULL);
718 }
719 }
720 }
721 break;
722 }
723
724 case WM_PRINT:
725 {
726 DefWndPrint(hWnd, (HDC)wParam, lParam);
727 return (0);
728 }
729
730 case WM_SYSCOLORCHANGE:
731 {
732 /* force to redraw non-client area */
733 DefWndNCPaint(hWnd, HRGN_WINDOW, -1);
734 /* Use InvalidateRect to redraw client area, enable
735 * erase to redraw all subcontrols otherwise send the
736 * WM_SYSCOLORCHANGE to child windows/controls is required
737 */
738 InvalidateRect(hWnd,NULL,TRUE);
739 return (0);
740 }
741
742 case WM_PAINTICON:
743 case WM_PAINT:
744 {
745 PAINTSTRUCT Ps;
746 HDC hDC;
747
748 /* If already in Paint and Client area is not empty just return. */
749 if (pWnd->state2 & WNDS2_STARTPAINT && !IsRectEmpty(&pWnd->rcClient))
750 {
751 ERR("In Paint and Client area is not empty!\n");
752 return 0;
753 }
754
755 hDC = BeginPaint(hWnd, &Ps);
756 if (hDC)
757 {
758 HICON hIcon;
759
760 if (IsIconic(hWnd) && ((hIcon = (HICON)GetClassLongPtrW( hWnd, GCLP_HICON))))
761 {
762 RECT ClientRect;
763 INT x, y;
764 GetClientRect(hWnd, &ClientRect);
765 x = (ClientRect.right - ClientRect.left -
766 GetSystemMetrics(SM_CXICON)) / 2;
767 y = (ClientRect.bottom - ClientRect.top -
768 GetSystemMetrics(SM_CYICON)) / 2;
769 DrawIcon(hDC, x, y, hIcon);
770 }
771 EndPaint(hWnd, &Ps);
772 }
773 return (0);
774 }
775
776 case WM_CLOSE:
777 DestroyWindow(hWnd);
778 return (0);
779
780 case WM_MOUSEACTIVATE:
781 if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CHILD)
782 {
783 LONG Ret = SendMessageW(GetParent(hWnd), WM_MOUSEACTIVATE, wParam, lParam);
784 if (Ret) return (Ret);
785 }
786 return ( (HIWORD(lParam) == WM_LBUTTONDOWN && LOWORD(lParam) == HTCAPTION) ? MA_NOACTIVATE : MA_ACTIVATE );
787
788 case WM_ACTIVATE:
789 /* The default action in Windows is to set the keyboard focus to
790 * the window, if it's being activated and not minimized */
791 if (LOWORD(wParam) != WA_INACTIVE &&
792 !(GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_MINIMIZE))
793 {
794 //ERR("WM_ACTIVATE %p\n",hWnd);
795 SetFocus(hWnd);
796 }
797 break;
798
799 case WM_MOUSEWHEEL:
800 if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CHILD)
801 return SendMessageW( GetParent(hWnd), WM_MOUSEWHEEL, wParam, lParam);
802 break;
803
804 case WM_ERASEBKGND:
805 case WM_ICONERASEBKGND:
806 {
807 RECT Rect;
808 HBRUSH hBrush = (HBRUSH)GetClassLongPtrW(hWnd, GCL_HBRBACKGROUND);
809
810 if (NULL == hBrush)
811 {
812 return 0;
813 }
814 if (GetClassLongPtrW(hWnd, GCL_STYLE) & CS_PARENTDC)
815 {
816 /* can't use GetClipBox with a parent DC or we fill the whole parent */
817 GetClientRect(hWnd, &Rect);
818 DPtoLP((HDC)wParam, (LPPOINT)&Rect, 2);
819 }
820 else
821 {
822 GetClipBox((HDC)wParam, &Rect);
823 }
824 FillRect((HDC)wParam, &Rect, hBrush);
825 return (1);
826 }
827
828 case WM_CTLCOLORMSGBOX:
829 case WM_CTLCOLOREDIT:
830 case WM_CTLCOLORLISTBOX:
831 case WM_CTLCOLORBTN:
832 case WM_CTLCOLORDLG:
833 case WM_CTLCOLORSTATIC:
834 case WM_CTLCOLORSCROLLBAR:
835 return (LRESULT) DefWndControlColor((HDC)wParam, Msg - WM_CTLCOLORMSGBOX);
836
837 case WM_CTLCOLOR:
838 return (LRESULT) DefWndControlColor((HDC)wParam, HIWORD(lParam));
839
840 case WM_SETCURSOR:
841 {
842 LONG_PTR Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
843
844 if (Style & WS_CHILD)
845 {
846 /* with the exception of the border around a resizable wnd,
847 * give the parent first chance to set the cursor */
848 if (LOWORD(lParam) < HTLEFT || LOWORD(lParam) > HTBOTTOMRIGHT)
849 {
850 HWND parent = GetParent( hWnd );
851 if (bUnicode)
852 {
853 if (parent != GetDesktopWindow() &&
854 SendMessageW( parent, WM_SETCURSOR, wParam, lParam))
855 return TRUE;
856 }
857 else
858 {
859 if (parent != GetDesktopWindow() &&
860 SendMessageA( parent, WM_SETCURSOR, wParam, lParam))
861 return TRUE;
862 }
863 }
864 }
865 return (DefWndHandleSetCursor(hWnd, wParam, lParam, Style));
866 }
867
868 case WM_SYSCOMMAND:
869 return (DefWndHandleSysCommand(hWnd, wParam, lParam));
870
871 case WM_KEYDOWN:
872 if(wParam == VK_F10) iF10Key = VK_F10;
873 break;
874
875 case WM_SYSKEYDOWN:
876 {
877 if (HIWORD(lParam) & KF_ALTDOWN)
878 { /* Previous state, if the key was down before this message,
879 this is a cheap way to ignore autorepeat keys. */
880 if ( !(HIWORD(lParam) & KF_REPEAT) )
881 {
882 if ( ( wParam == VK_MENU ||
883 wParam == VK_LMENU ||
884 wParam == VK_RMENU ) && !iMenuSysKey )
885 iMenuSysKey = 1;
886 else
887 iMenuSysKey = 0;
888 }
889
890 iF10Key = 0;
891
892 if (wParam == VK_F4) /* Try to close the window */
893 {
894 HWND top = GetAncestor(hWnd, GA_ROOT);
895 if (!(GetClassLongPtrW(top, GCL_STYLE) & CS_NOCLOSE))
896 PostMessageW(top, WM_SYSCOMMAND, SC_CLOSE, 0);
897 }
898 else if (wParam == VK_SNAPSHOT) // Alt-VK_SNAPSHOT?
899 {
900 HWND hwnd = hWnd;
901 while (GetParent(hwnd) != NULL)
902 {
903 hwnd = GetParent(hwnd);
904 }
905 DefWndScreenshot(hwnd);
906 }
907 else if ( wParam == VK_ESCAPE || wParam == VK_TAB ) // Alt-Tab/ESC Alt-Shift-Tab/ESC
908 {
909 WPARAM wParamTmp;
910 HWND Active = GetActiveWindow(); // Noticed MDI problem.
911 if (!Active)
912 {
913 FIXME("WM_SYSKEYDOWN VK_ESCAPE no active\n");
914 break;
915 }
916 wParamTmp = GetKeyState(VK_SHIFT) & 0x8000 ? SC_PREVWINDOW : SC_NEXTWINDOW;
917 SendMessageW( Active, WM_SYSCOMMAND, wParamTmp, wParam );
918 }
919 }
920 else if( wParam == VK_F10 )
921 {
922 if (GetKeyState(VK_SHIFT) & 0x8000)
923 SendMessageW( hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, MAKELPARAM(-1, -1) );
924 iF10Key = 1;
925 }
926 break;
927 }
928
929 case WM_KEYUP:
930 case WM_SYSKEYUP:
931 {
932 /* Press and release F10 or ALT */
933 if (((wParam == VK_MENU || wParam == VK_LMENU || wParam == VK_RMENU)
934 && iMenuSysKey) || ((wParam == VK_F10) && iF10Key))
935 SendMessageW( GetAncestor( hWnd, GA_ROOT ), WM_SYSCOMMAND, SC_KEYMENU, 0L );
936 iMenuSysKey = iF10Key = 0;
937 break;
938 }
939
940 case WM_SYSCHAR:
941 {
942 iMenuSysKey = 0;
943 if (wParam == VK_RETURN && IsIconic(hWnd))
944 {
945 PostMessageW( hWnd, WM_SYSCOMMAND, SC_RESTORE, 0L );
946 break;
947 }
948 if ((HIWORD(lParam) & KF_ALTDOWN) && wParam)
949 {
950 if (wParam == VK_TAB || wParam == VK_ESCAPE) break;
951 if (wParam == VK_SPACE && (GetWindowLongPtrW( hWnd, GWL_STYLE ) & WS_CHILD))
952 SendMessageW( GetParent(hWnd), Msg, wParam, lParam );
953 else
954 SendMessageW( hWnd, WM_SYSCOMMAND, SC_KEYMENU, wParam );
955 }
956 else /* check for Ctrl-Esc */
957 if (wParam != VK_ESCAPE) MessageBeep(0);
958 break;
959 }
960
961 case WM_CANCELMODE:
962 {
963 iMenuSysKey = 0;
964 /* FIXME: Check for a desktop. */
965 //if (!(GetWindowLongPtrW( hWnd, GWL_STYLE ) & WS_CHILD)) EndMenu();
966 MENU_EndMenu( hWnd );
967 if (GetCapture() == hWnd)
968 {
969 ReleaseCapture();
970 }
971 break;
972 }
973
974 case WM_VKEYTOITEM:
975 case WM_CHARTOITEM:
976 return (-1);
977 /*
978 case WM_DROPOBJECT:
979 return DRAG_FILE;
980 */
981 case WM_QUERYDROPOBJECT:
982 {
983 if (GetWindowLongPtrW(hWnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES)
984 {
985 return(1);
986 }
987 break;
988 }
989
990 case WM_QUERYDRAGICON:
991 {
992 UINT Len;
993 HICON hIcon;
994
995 hIcon = (HICON)GetClassLongPtrW(hWnd, GCL_HICON);
996 if (hIcon)
997 {
998 return ((LRESULT)hIcon);
999 }
1000 for (Len = 1; Len < 64; Len++)
1001 {
1002 if ((hIcon = LoadIconW(NULL, MAKEINTRESOURCEW(Len))) != NULL)
1003 {
1004 return((LRESULT)hIcon);
1005 }
1006 }
1007 return ((LRESULT)LoadIconW(0, IDI_APPLICATION));
1008 }
1009
1010 case WM_ISACTIVEICON:
1011 {
1012 BOOL isai;
1013 isai = (pWnd->state & WNDS_ACTIVEFRAME) != 0;
1014 return isai;
1015 }
1016
1017 case WM_NOTIFYFORMAT:
1018 {
1019 if (lParam == NF_QUERY)
1020 return IsWindowUnicode(hWnd) ? NFR_UNICODE : NFR_ANSI;
1021 break;
1022 }
1023
1024 case WM_SETICON:
1025 {
1026 return DefWndSetIcon(pWnd, wParam, lParam);
1027 }
1028
1029 case WM_GETICON:
1030 {
1031 return DefWndGetIcon(pWnd, wParam, lParam);
1032 }
1033
1034 case WM_HELP:
1035 {
1036 if (bUnicode)
1037 {
1038 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1039 }
1040 else
1041 {
1042 SendMessageA(GetParent(hWnd), Msg, wParam, lParam);
1043 }
1044 break;
1045 }
1046
1047 case WM_SYSTIMER:
1048 {
1049 THRDCARETINFO CaretInfo;
1050 switch(wParam)
1051 {
1052 case 0xffff: /* Caret timer */
1053 /* switch showing byte in win32k and get information about the caret */
1054 if(NtUserxSwitchCaretShowing(&CaretInfo) && (CaretInfo.hWnd == hWnd))
1055 {
1056 DrawCaret(hWnd, &CaretInfo);
1057 }
1058 break;
1059 }
1060 break;
1061 }
1062
1063 case WM_QUERYOPEN:
1064 case WM_QUERYENDSESSION:
1065 {
1066 return (1);
1067 }
1068
1069 case WM_INPUTLANGCHANGEREQUEST:
1070 {
1071 HKL NewHkl;
1072
1073 if(wParam & INPUTLANGCHANGE_BACKWARD
1074 && wParam & INPUTLANGCHANGE_FORWARD)
1075 {
1076 return FALSE;
1077 }
1078
1079 //FIXME: What to do with INPUTLANGCHANGE_SYSCHARSET ?
1080
1081 if(wParam & INPUTLANGCHANGE_BACKWARD) NewHkl = (HKL) HKL_PREV;
1082 else if(wParam & INPUTLANGCHANGE_FORWARD) NewHkl = (HKL) HKL_NEXT;
1083 else NewHkl = (HKL) lParam;
1084
1085 NtUserActivateKeyboardLayout(NewHkl, 0);
1086
1087 return TRUE;
1088 }
1089
1090 case WM_INPUTLANGCHANGE:
1091 {
1092 int count = 0;
1093 HWND *win_array = WIN_ListChildren( hWnd );
1094
1095 if (!win_array)
1096 break;
1097 while (win_array[count])
1098 SendMessageW( win_array[count++], WM_INPUTLANGCHANGE, wParam, lParam);
1099 HeapFree(GetProcessHeap(),0,win_array);
1100 break;
1101 }
1102
1103 case WM_QUERYUISTATE:
1104 {
1105 LRESULT Ret = 0;
1106 PWND Wnd = ValidateHwnd(hWnd);
1107 if (Wnd != NULL)
1108 {
1109 if (Wnd->HideFocus)
1110 Ret |= UISF_HIDEFOCUS;
1111 if (Wnd->HideAccel)
1112 Ret |= UISF_HIDEACCEL;
1113 }
1114 return Ret;
1115 }
1116
1117 case WM_CHANGEUISTATE:
1118 {
1119 BOOL AlwaysShowCues = FALSE;
1120 WORD Action = LOWORD(wParam);
1121 WORD Flags = HIWORD(wParam);
1122 PWND Wnd;
1123
1124 SystemParametersInfoW(SPI_GETKEYBOARDCUES, 0, &AlwaysShowCues, 0);
1125 if (AlwaysShowCues)
1126 break;
1127
1128 Wnd= ValidateHwnd(hWnd);
1129 if (!Wnd || lParam != 0)
1130 break;
1131
1132 if (Flags & ~(UISF_HIDEFOCUS | UISF_HIDEACCEL | UISF_ACTIVE))
1133 break;
1134
1135 if (Flags & UISF_ACTIVE)
1136 {
1137 WARN("WM_CHANGEUISTATE does not yet support UISF_ACTIVE!\n");
1138 }
1139
1140 if (Action == UIS_INITIALIZE)
1141 {
1142 PDESKTOPINFO Desk = GetThreadDesktopInfo();
1143 if (Desk == NULL)
1144 break;
1145
1146 Action = Desk->LastInputWasKbd ? UIS_CLEAR : UIS_SET;
1147 Flags = UISF_HIDEFOCUS | UISF_HIDEACCEL;
1148
1149 /* We need to update wParam in case we need to send out messages */
1150 wParam = MAKEWPARAM(Action, Flags);
1151 }
1152
1153 switch (Action)
1154 {
1155 case UIS_SET:
1156 /* See if we actually need to change something */
1157 if ((Flags & UISF_HIDEFOCUS) && !Wnd->HideFocus)
1158 break;
1159 if ((Flags & UISF_HIDEACCEL) && !Wnd->HideAccel)
1160 break;
1161
1162 /* Don't need to do anything... */
1163 return 0;
1164
1165 case UIS_CLEAR:
1166 /* See if we actually need to change something */
1167 if ((Flags & UISF_HIDEFOCUS) && Wnd->HideFocus)
1168 break;
1169 if ((Flags & UISF_HIDEACCEL) && Wnd->HideAccel)
1170 break;
1171
1172 /* Don't need to do anything... */
1173 return 0;
1174
1175 default:
1176 WARN("WM_CHANGEUISTATE: Unsupported Action 0x%x\n", Action);
1177 break;
1178 }
1179
1180 if ((Wnd->style & WS_CHILD) && Wnd->spwndParent != NULL)
1181 {
1182 /* We're a child window and we need to pass this message down until
1183 we reach the root */
1184 hWnd = UserHMGetHandle((PWND)DesktopPtrToUser(Wnd->spwndParent));
1185 }
1186 else
1187 {
1188 /* We're a top level window, we need to change the UI state */
1189 Msg = WM_UPDATEUISTATE;
1190 }
1191
1192 if (bUnicode)
1193 return SendMessageW(hWnd, Msg, wParam, lParam);
1194 else
1195 return SendMessageA(hWnd, Msg, wParam, lParam);
1196 }
1197
1198 case WM_UPDATEUISTATE:
1199 {
1200 BOOL Change = TRUE;
1201 BOOL AlwaysShowCues = FALSE;
1202 WORD Action = LOWORD(wParam);
1203 WORD Flags = HIWORD(wParam);
1204 PWND Wnd;
1205
1206 SystemParametersInfoW(SPI_GETKEYBOARDCUES, 0, &AlwaysShowCues, 0);
1207 if (AlwaysShowCues)
1208 break;
1209
1210 Wnd = ValidateHwnd(hWnd);
1211 if (!Wnd || lParam != 0)
1212 break;
1213
1214 if (Flags & ~(UISF_HIDEFOCUS | UISF_HIDEACCEL | UISF_ACTIVE))
1215 break;
1216
1217 if (Flags & UISF_ACTIVE)
1218 {
1219 WARN("WM_UPDATEUISTATE does not yet support UISF_ACTIVE!\n");
1220 }
1221
1222 if (Action == UIS_INITIALIZE)
1223 {
1224 PDESKTOPINFO Desk = GetThreadDesktopInfo();
1225 if (Desk == NULL)
1226 break;
1227
1228 Action = Desk->LastInputWasKbd ? UIS_CLEAR : UIS_SET;
1229 Flags = UISF_HIDEFOCUS | UISF_HIDEACCEL;
1230
1231 /* We need to update wParam for broadcasting the update */
1232 wParam = MAKEWPARAM(Action, Flags);
1233 }
1234
1235 switch (Action)
1236 {
1237 case UIS_SET:
1238 /* See if we actually need to change something */
1239 if ((Flags & UISF_HIDEFOCUS) && !Wnd->HideFocus)
1240 break;
1241 if ((Flags & UISF_HIDEACCEL) && !Wnd->HideAccel)
1242 break;
1243
1244 /* Don't need to do anything... */
1245 Change = FALSE;
1246 break;
1247
1248 case UIS_CLEAR:
1249 /* See if we actually need to change something */
1250 if ((Flags & UISF_HIDEFOCUS) && Wnd->HideFocus)
1251 break;
1252 if ((Flags & UISF_HIDEACCEL) && Wnd->HideAccel)
1253 break;
1254
1255 /* Don't need to do anything... */
1256 Change = FALSE;
1257 break;
1258
1259 default:
1260 WARN("WM_UPDATEUISTATE: Unsupported Action 0x%x\n", Action);
1261 return 0;
1262 }
1263
1264 /* Pack the information and call win32k */
1265 if (Change)
1266 {
1267 if (!NtUserxUpdateUiState(hWnd, Flags | ((DWORD)Action << 3)))
1268 break;
1269 }
1270
1271 /* Always broadcast the update to all children */
1272 EnumChildWindows(hWnd,
1273 UserSendUiUpdateMsg,
1274 (LPARAM)wParam);
1275
1276 break;
1277 }
1278
1279 /* Move to Win32k !*/
1280 case WM_SHOWWINDOW:
1281 if (!lParam) break; // Call when it is necessary.
1282 case WM_SYNCPAINT:
1283 case WM_SETREDRAW:
1284 case WM_CLIENTSHUTDOWN:
1285 case WM_GETHOTKEY:
1286 case WM_SETHOTKEY:
1287 case WM_WINDOWPOSCHANGING:
1288 case WM_WINDOWPOSCHANGED:
1289 case WM_APPCOMMAND:
1290 {
1291 LRESULT lResult;
1292 NtUserMessageCall( hWnd, Msg, wParam, lParam, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, !bUnicode);
1293 return lResult;
1294 }
1295 }
1296 return 0;
1297 }
1298
1299
1300 /*
1301 * helpers for calling IMM32 (from Wine 10/22/2008)
1302 *
1303 * WM_IME_* messages are generated only by IMM32,
1304 * so I assume imm32 is already LoadLibrary-ed.
1305 */
1306 static HWND
1307 DefWndImmGetDefaultIMEWnd(HWND hwnd)
1308 {
1309 HINSTANCE hInstIMM = GetModuleHandleW(L"imm32\0");
1310 HWND (WINAPI *pFunc)(HWND);
1311 HWND hwndRet = 0;
1312
1313 if (!hInstIMM)
1314 {
1315 ERR("cannot get IMM32 handle\n");
1316 return 0;
1317 }
1318
1319 pFunc = (void*) GetProcAddress(hInstIMM, "ImmGetDefaultIMEWnd");
1320 if (pFunc != NULL)
1321 hwndRet = (*pFunc)(hwnd);
1322
1323 return hwndRet;
1324 }
1325
1326
1327 static BOOL
1328 DefWndImmIsUIMessageA(HWND hwndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1329 {
1330 HINSTANCE hInstIMM = GetModuleHandleW(L"imm32\0");
1331 BOOL (WINAPI *pFunc)(HWND,UINT,WPARAM,LPARAM);
1332 BOOL fRet = FALSE;
1333
1334 if (!hInstIMM)
1335 {
1336 ERR("cannot get IMM32 handle\n");
1337 return FALSE;
1338 }
1339
1340 pFunc = (void*) GetProcAddress(hInstIMM, "ImmIsUIMessageA");
1341 if (pFunc != NULL)
1342 fRet = (*pFunc)(hwndIME, msg, wParam, lParam);
1343
1344 return fRet;
1345 }
1346
1347
1348 static BOOL
1349 DefWndImmIsUIMessageW(HWND hwndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1350 {
1351 HINSTANCE hInstIMM = GetModuleHandleW(L"imm32\0");
1352 BOOL (WINAPI *pFunc)(HWND,UINT,WPARAM,LPARAM);
1353 BOOL fRet = FALSE;
1354
1355 if (!hInstIMM)
1356 {
1357 ERR("cannot get IMM32 handle\n");
1358 return FALSE;
1359 }
1360
1361 pFunc = (void*) GetProcAddress(hInstIMM, "ImmIsUIMessageW");
1362 if (pFunc != NULL)
1363 fRet = (*pFunc)(hwndIME, msg, wParam, lParam);
1364
1365 return fRet;
1366 }
1367
1368
1369 LRESULT WINAPI
1370 RealDefWindowProcA(HWND hWnd,
1371 UINT Msg,
1372 WPARAM wParam,
1373 LPARAM lParam)
1374 {
1375 LRESULT Result = 0;
1376 PWND Wnd;
1377
1378 Wnd = ValidateHwnd(hWnd);
1379
1380 if ( !Wnd &&
1381 Msg != WM_CTLCOLORMSGBOX &&
1382 Msg != WM_CTLCOLORBTN &&
1383 Msg != WM_CTLCOLORDLG &&
1384 Msg != WM_CTLCOLORSTATIC )
1385 return 0;
1386
1387 SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam);
1388 switch (Msg)
1389 {
1390 case WM_NCCREATE:
1391 {
1392 if ( Wnd &&
1393 Wnd->style & (WS_HSCROLL | WS_VSCROLL) )
1394 {
1395 if (!Wnd->pSBInfo)
1396 {
1397 SCROLLINFO si = {sizeof si, SIF_ALL, 0, 100, 0, 0, 0};
1398 SetScrollInfo( hWnd, SB_HORZ, &si, FALSE );
1399 SetScrollInfo( hWnd, SB_VERT, &si, FALSE );
1400 }
1401 }
1402
1403 if (lParam)
1404 {
1405 LPCREATESTRUCTA cs = (LPCREATESTRUCTA)lParam;
1406 /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
1407 * may have child window IDs instead of window name */
1408 if (HIWORD(cs->lpszName))
1409 {
1410 DefSetText(hWnd, (PCWSTR)cs->lpszName, TRUE);
1411 }
1412 Result = 1;
1413 }
1414 break;
1415 }
1416
1417 case WM_GETTEXTLENGTH:
1418 {
1419 PWSTR buf;
1420 ULONG len;
1421
1422 if (Wnd != NULL && Wnd->strName.Length != 0)
1423 {
1424 buf = DesktopPtrToUser(Wnd->strName.Buffer);
1425 if (buf != NULL &&
1426 NT_SUCCESS(RtlUnicodeToMultiByteSize(&len,
1427 buf,
1428 Wnd->strName.Length)))
1429 {
1430 Result = (LRESULT) len;
1431 }
1432 }
1433 else Result = 0L;
1434
1435 break;
1436 }
1437
1438 case WM_GETTEXT:
1439 {
1440 PWSTR buf = NULL;
1441 PSTR outbuf = (PSTR)lParam;
1442 UINT copy;
1443
1444 if (Wnd != NULL && wParam != 0)
1445 {
1446 if (Wnd->strName.Buffer != NULL)
1447 buf = DesktopPtrToUser(Wnd->strName.Buffer);
1448 else
1449 outbuf[0] = L'\0';
1450
1451 if (buf != NULL)
1452 {
1453 if (Wnd->strName.Length != 0)
1454 {
1455 copy = min(Wnd->strName.Length / sizeof(WCHAR), wParam - 1);
1456 Result = WideCharToMultiByte(CP_ACP,
1457 0,
1458 buf,
1459 copy,
1460 outbuf,
1461 wParam,
1462 NULL,
1463 NULL);
1464 outbuf[Result] = '\0';
1465 }
1466 else
1467 outbuf[0] = '\0';
1468 }
1469 }
1470 break;
1471 }
1472
1473 case WM_SETTEXT:
1474 {
1475 DefSetText(hWnd, (PCWSTR)lParam, TRUE);
1476
1477 if ((GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
1478 UserPaintCaption(hWnd);
1479 Result = 1;
1480 break;
1481 }
1482
1483 case WM_IME_KEYDOWN:
1484 {
1485 Result = PostMessageA(hWnd, WM_KEYDOWN, wParam, lParam);
1486 break;
1487 }
1488
1489 case WM_IME_KEYUP:
1490 {
1491 Result = PostMessageA(hWnd, WM_KEYUP, wParam, lParam);
1492 break;
1493 }
1494
1495 case WM_IME_CHAR:
1496 {
1497 if (HIBYTE(wParam))
1498 PostMessageA(hWnd, WM_CHAR, HIBYTE(wParam), lParam);
1499 PostMessageA(hWnd, WM_CHAR, LOBYTE(wParam), lParam);
1500 break;
1501 }
1502
1503 case WM_IME_STARTCOMPOSITION:
1504 case WM_IME_COMPOSITION:
1505 case WM_IME_ENDCOMPOSITION:
1506 case WM_IME_SELECT:
1507 case WM_IME_NOTIFY:
1508 {
1509 HWND hwndIME;
1510
1511 hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
1512 if (hwndIME)
1513 Result = SendMessageA(hwndIME, Msg, wParam, lParam);
1514 break;
1515 }
1516
1517 case WM_IME_SETCONTEXT:
1518 {
1519 HWND hwndIME;
1520
1521 hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
1522 if (hwndIME)
1523 Result = DefWndImmIsUIMessageA(hwndIME, Msg, wParam, lParam);
1524 break;
1525 }
1526
1527 /* fall through */
1528 default:
1529 Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, FALSE);
1530 }
1531
1532 SPY_ExitMessage(SPY_RESULT_DEFWND, hWnd, Msg, Result, wParam, lParam);
1533 return Result;
1534 }
1535
1536
1537 LRESULT WINAPI
1538 RealDefWindowProcW(HWND hWnd,
1539 UINT Msg,
1540 WPARAM wParam,
1541 LPARAM lParam)
1542 {
1543 LRESULT Result = 0;
1544 PWND Wnd;
1545
1546 Wnd = ValidateHwnd(hWnd);
1547
1548 if ( !Wnd &&
1549 Msg != WM_CTLCOLORMSGBOX &&
1550 Msg != WM_CTLCOLORBTN &&
1551 Msg != WM_CTLCOLORDLG &&
1552 Msg != WM_CTLCOLORSTATIC )
1553 return 0;
1554
1555 SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam);
1556 switch (Msg)
1557 {
1558 case WM_NCCREATE:
1559 {
1560 if ( Wnd &&
1561 Wnd->style & (WS_HSCROLL | WS_VSCROLL) )
1562 {
1563 if (!Wnd->pSBInfo)
1564 {
1565 SCROLLINFO si = {sizeof si, SIF_ALL, 0, 100, 0, 0, 0};
1566 SetScrollInfo( hWnd, SB_HORZ, &si, FALSE );
1567 SetScrollInfo( hWnd, SB_VERT, &si, FALSE );
1568 }
1569 }
1570
1571 if (lParam)
1572 {
1573 LPCREATESTRUCTW cs = (LPCREATESTRUCTW)lParam;
1574 /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
1575 * may have child window IDs instead of window name */
1576 if (HIWORD(cs->lpszName))
1577 {
1578 DefSetText(hWnd, cs->lpszName, FALSE);
1579 }
1580 Result = 1;
1581 }
1582 break;
1583 }
1584
1585 case WM_GETTEXTLENGTH:
1586 {
1587 PWSTR buf;
1588 ULONG len;
1589
1590 if (Wnd != NULL && Wnd->strName.Length != 0)
1591 {
1592 buf = DesktopPtrToUser(Wnd->strName.Buffer);
1593 if (buf != NULL &&
1594 NT_SUCCESS(RtlUnicodeToMultiByteSize(&len,
1595 buf,
1596 Wnd->strName.Length)))
1597 {
1598 Result = (LRESULT) (Wnd->strName.Length / sizeof(WCHAR));
1599 }
1600 }
1601 else Result = 0L;
1602
1603 break;
1604 }
1605
1606 case WM_GETTEXT:
1607 {
1608 PWSTR buf = NULL;
1609 PWSTR outbuf = (PWSTR)lParam;
1610
1611 if (Wnd != NULL && wParam != 0)
1612 {
1613 if (Wnd->strName.Buffer != NULL)
1614 buf = DesktopPtrToUser(Wnd->strName.Buffer);
1615 else
1616 outbuf[0] = L'\0';
1617
1618 if (buf != NULL)
1619 {
1620 if (Wnd->strName.Length != 0)
1621 {
1622 Result = min(Wnd->strName.Length / sizeof(WCHAR), wParam - 1);
1623 RtlCopyMemory(outbuf,
1624 buf,
1625 Result * sizeof(WCHAR));
1626 outbuf[Result] = L'\0';
1627 }
1628 else
1629 outbuf[0] = L'\0';
1630 }
1631 }
1632 break;
1633 }
1634
1635 case WM_SETTEXT:
1636 {
1637 DefSetText(hWnd, (PCWSTR)lParam, FALSE);
1638
1639 if ((GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
1640 UserPaintCaption(hWnd);
1641 Result = 1;
1642 break;
1643 }
1644
1645 case WM_IME_CHAR:
1646 {
1647 PostMessageW(hWnd, WM_CHAR, wParam, lParam);
1648 Result = 0;
1649 break;
1650 }
1651
1652 case WM_IME_KEYDOWN:
1653 {
1654 Result = PostMessageW(hWnd, WM_KEYDOWN, wParam, lParam);
1655 break;
1656 }
1657
1658 case WM_IME_KEYUP:
1659 {
1660 Result = PostMessageW(hWnd, WM_KEYUP, wParam, lParam);
1661 break;
1662 }
1663
1664 case WM_IME_STARTCOMPOSITION:
1665 case WM_IME_COMPOSITION:
1666 case WM_IME_ENDCOMPOSITION:
1667 case WM_IME_SELECT:
1668 case WM_IME_NOTIFY:
1669 {
1670 HWND hwndIME;
1671
1672 hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
1673 if (hwndIME)
1674 Result = SendMessageW(hwndIME, Msg, wParam, lParam);
1675 break;
1676 }
1677
1678 case WM_IME_SETCONTEXT:
1679 {
1680 HWND hwndIME;
1681
1682 hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
1683 if (hwndIME)
1684 Result = DefWndImmIsUIMessageW(hwndIME, Msg, wParam, lParam);
1685 break;
1686 }
1687
1688 default:
1689 Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, TRUE);
1690 }
1691 SPY_ExitMessage(SPY_RESULT_DEFWND, hWnd, Msg, Result, wParam, lParam);
1692
1693 return Result;
1694 }
1695
1696 LRESULT WINAPI
1697 DefWindowProcA(HWND hWnd,
1698 UINT Msg,
1699 WPARAM wParam,
1700 LPARAM lParam)
1701 {
1702 BOOL Hook, msgOverride = FALSE;
1703 LRESULT Result = 0;
1704
1705 LoadUserApiHook();
1706
1707 Hook = BeginIfHookedUserApiHook();
1708 if (Hook)
1709 {
1710 msgOverride = IsMsgOverride(Msg, &guah.DefWndProcArray);
1711 if(msgOverride == FALSE)
1712 {
1713 EndUserApiHook();
1714 }
1715 }
1716
1717 /* Bypass SEH and go direct. */
1718 if (!Hook || !msgOverride)
1719 return RealDefWindowProcA(hWnd, Msg, wParam, lParam);
1720
1721 _SEH2_TRY
1722 {
1723 Result = guah.DefWindowProcA(hWnd, Msg, wParam, lParam);
1724 }
1725 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1726 {
1727 }
1728 _SEH2_END;
1729
1730 EndUserApiHook();
1731
1732 return Result;
1733 }
1734
1735 LRESULT WINAPI
1736 DefWindowProcW(HWND hWnd,
1737 UINT Msg,
1738 WPARAM wParam,
1739 LPARAM lParam)
1740 {
1741 BOOL Hook, msgOverride = FALSE;
1742 LRESULT Result = 0;
1743
1744 LoadUserApiHook();
1745
1746 Hook = BeginIfHookedUserApiHook();
1747 if (Hook)
1748 {
1749 msgOverride = IsMsgOverride(Msg, &guah.DefWndProcArray);
1750 if(msgOverride == FALSE)
1751 {
1752 EndUserApiHook();
1753 }
1754 }
1755
1756 /* Bypass SEH and go direct. */
1757 if (!Hook || !msgOverride)
1758 return RealDefWindowProcW(hWnd, Msg, wParam, lParam);
1759
1760 _SEH2_TRY
1761 {
1762 Result = guah.DefWindowProcW(hWnd, Msg, wParam, lParam);
1763 }
1764 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1765 {
1766 }
1767 _SEH2_END;
1768
1769 EndUserApiHook();
1770
1771 return Result;
1772 }