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