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