Merge from amd64-branch:
[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_SYSCOLORCHANGE:
1206 {
1207 /* force to redraw non-client area */
1208 DefWndNCPaint(hWnd, (HRGN)1, -1);
1209 /* Use InvalidateRect to redraw client area, enable
1210 * erase to redraw all subcontrols otherwise send the
1211 * WM_SYSCOLORCHANGE to child windows/controls is required
1212 */
1213 InvalidateRect(hWnd,NULL,TRUE);
1214 return (0);
1215 }
1216
1217 case WM_PAINTICON:
1218 case WM_PAINT:
1219 {
1220 PAINTSTRUCT Ps;
1221 HDC hDC = BeginPaint(hWnd, &Ps);
1222 if (hDC)
1223 {
1224 HICON hIcon;
1225
1226 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE &&
1227 (hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON)) != NULL)
1228 {
1229 RECT ClientRect;
1230 INT x, y;
1231 GetClientRect(hWnd, &ClientRect);
1232 x = (ClientRect.right - ClientRect.left -
1233 GetSystemMetrics(SM_CXICON)) / 2;
1234 y = (ClientRect.bottom - ClientRect.top -
1235 GetSystemMetrics(SM_CYICON)) / 2;
1236 DrawIcon(hDC, x, y, hIcon);
1237 }
1238 EndPaint(hWnd, &Ps);
1239 }
1240 return (0);
1241 }
1242
1243 case WM_SYNCPAINT:
1244 {
1245 HRGN hRgn;
1246 hRgn = CreateRectRgn(0, 0, 0, 0);
1247 if (GetUpdateRgn(hWnd, hRgn, FALSE) != NULLREGION)
1248 {
1249 RedrawWindow(hWnd, NULL, hRgn,
1250 RDW_ERASENOW | RDW_ERASE | RDW_FRAME |
1251 RDW_ALLCHILDREN);
1252 }
1253 DeleteObject(hRgn);
1254 return (0);
1255 }
1256
1257 case WM_SETREDRAW:
1258 {
1259 DefWndSetRedraw(hWnd, wParam);
1260 return (0);
1261 }
1262
1263 case WM_CLOSE:
1264 {
1265 DestroyWindow(hWnd);
1266 return (0);
1267 }
1268
1269 case WM_MOUSEACTIVATE:
1270 {
1271 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1272 {
1273 LONG Ret;
1274 if (bUnicode)
1275 {
1276 Ret = SendMessageW(GetParent(hWnd), WM_MOUSEACTIVATE,
1277 wParam, lParam);
1278 }
1279 else
1280 {
1281 Ret = SendMessageA(GetParent(hWnd), WM_MOUSEACTIVATE,
1282 wParam, lParam);
1283 }
1284 if (Ret)
1285 {
1286 return (Ret);
1287 }
1288 }
1289 return ((LOWORD(lParam) >= HTCLIENT) ? MA_ACTIVATE : MA_NOACTIVATE);
1290 }
1291
1292 case WM_ACTIVATE:
1293 {
1294 /* Check if the window is minimized. */
1295 if (LOWORD(wParam) != WA_INACTIVE &&
1296 !(GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE))
1297 {
1298 SetFocus(hWnd);
1299 }
1300 break;
1301 }
1302
1303 case WM_MOUSEWHEEL:
1304 {
1305 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1306 {
1307 if (bUnicode)
1308 {
1309 return (SendMessageW(GetParent(hWnd), WM_MOUSEWHEEL,
1310 wParam, lParam));
1311 }
1312 else
1313 {
1314 return (SendMessageA(GetParent(hWnd), WM_MOUSEWHEEL,
1315 wParam, lParam));
1316 }
1317 }
1318 break;
1319 }
1320
1321 case WM_ERASEBKGND:
1322 case WM_ICONERASEBKGND:
1323 {
1324 RECT Rect;
1325 HBRUSH hBrush = (HBRUSH)GetClassLongW(hWnd, GCL_HBRBACKGROUND);
1326
1327 if (NULL == hBrush)
1328 {
1329 return 0;
1330 }
1331 if (GetClassLongW(hWnd, GCL_STYLE) & CS_PARENTDC)
1332 {
1333 /* can't use GetClipBox with a parent DC or we fill the whole parent */
1334 GetClientRect(hWnd, &Rect);
1335 DPtoLP((HDC)wParam, (LPPOINT)&Rect, 2);
1336 }
1337 else
1338 {
1339 GetClipBox((HDC)wParam, &Rect);
1340 }
1341 FillRect((HDC)wParam, &Rect, hBrush);
1342 return (1);
1343 }
1344
1345 case WM_CTLCOLORMSGBOX:
1346 case WM_CTLCOLOREDIT:
1347 case WM_CTLCOLORLISTBOX:
1348 case WM_CTLCOLORBTN:
1349 case WM_CTLCOLORDLG:
1350 case WM_CTLCOLORSTATIC:
1351 case WM_CTLCOLORSCROLLBAR:
1352 return (LRESULT) DefWndControlColor((HDC)wParam, Msg - WM_CTLCOLORMSGBOX);
1353
1354 case WM_CTLCOLOR:
1355 return (LRESULT) DefWndControlColor((HDC)wParam, HIWORD(lParam));
1356
1357 case WM_SETCURSOR:
1358 {
1359 ULONG Style = GetWindowLongW(hWnd, GWL_STYLE);
1360
1361 if (Style & WS_CHILD)
1362 {
1363 if (LOWORD(lParam) < HTLEFT || LOWORD(lParam) > HTBOTTOMRIGHT)
1364 {
1365 BOOL bResult;
1366 if (bUnicode)
1367 {
1368 bResult = SendMessageW(GetParent(hWnd), WM_SETCURSOR,
1369 wParam, lParam);
1370 }
1371 else
1372 {
1373 bResult = SendMessageA(GetParent(hWnd), WM_SETCURSOR,
1374 wParam, lParam);
1375 }
1376 if (bResult)
1377 {
1378 return(TRUE);
1379 }
1380 }
1381 }
1382 return (DefWndHandleSetCursor(hWnd, wParam, lParam, Style));
1383 }
1384
1385 case WM_SYSCOMMAND:
1386 return (DefWndHandleSysCommand(hWnd, wParam, lParam));
1387
1388 case WM_KEYDOWN:
1389 if(wParam == VK_F10) iF10Key = VK_F10;
1390 break;
1391
1392 /* FIXME: This is also incomplete. */
1393 case WM_SYSKEYDOWN:
1394 {
1395 if (HIWORD(lParam) & KEYDATA_ALT)
1396 {
1397 HWND top = GetAncestor(hWnd, GA_ROOT);
1398 /* if( HIWORD(lParam) & ~KEYDATA_PREVSTATE ) */
1399 if ( (wParam == VK_MENU || wParam == VK_LMENU
1400 || wParam == VK_RMENU) && !iMenuSysKey )
1401 {
1402 iMenuSysKey = 1;
1403 /* mimic behaviour of XP, sending a WM_SYSCOMMAND when pressing <alt> */
1404 SendMessageW( top, WM_SYSCOMMAND, SC_KEYMENU, 0L );
1405 }
1406 else
1407 iMenuSysKey = 0;
1408
1409 iF10Key = 0;
1410
1411 if (wParam == VK_F4) /* Try to close the window */
1412 {
1413 if (!(GetClassLongW(top, GCL_STYLE) & CS_NOCLOSE))
1414 {
1415 if (bUnicode)
1416 PostMessageW(top, WM_SYSCOMMAND, SC_CLOSE, 0);
1417 else
1418 PostMessageA(top, WM_SYSCOMMAND, SC_CLOSE, 0);
1419 }
1420 }
1421 else if (wParam == VK_SNAPSHOT)
1422 {
1423 HWND hwnd = hWnd;
1424 while (GetParent(hwnd) != NULL)
1425 {
1426 hwnd = GetParent(hwnd);
1427 }
1428 DefWndScreenshot(hwnd);
1429 }
1430 }
1431 else if( wParam == VK_F10 )
1432 iF10Key = 1;
1433 else if( wParam == VK_ESCAPE && (GetKeyState(VK_SHIFT) & 0x8000))
1434 SendMessageW( hWnd, WM_SYSCOMMAND, SC_KEYMENU, ' ' );
1435 break;
1436 }
1437
1438 case WM_KEYUP:
1439 case WM_SYSKEYUP:
1440 {
1441 /* Press and release F10 or ALT */
1442 if (((wParam == VK_MENU || wParam == VK_LMENU || wParam == VK_RMENU)
1443 && iMenuSysKey) || ((wParam == VK_F10) && iF10Key))
1444 SendMessageW( GetAncestor( hWnd, GA_ROOT ), WM_SYSCOMMAND, SC_KEYMENU, 0L );
1445 iMenuSysKey = iF10Key = 0;
1446 break;
1447 }
1448
1449 case WM_SYSCHAR:
1450 {
1451 iMenuSysKey = 0;
1452 if (wParam == '\r' && IsIconic(hWnd))
1453 {
1454 PostMessageW( hWnd, WM_SYSCOMMAND, SC_RESTORE, 0L );
1455 break;
1456 }
1457 if ((HIWORD(lParam) & KEYDATA_ALT) && wParam)
1458 {
1459 if (wParam == '\t' || wParam == '\x1b') break;
1460 if (wParam == ' ' && (GetWindowLongW( hWnd, GWL_STYLE ) & WS_CHILD))
1461 SendMessageW( GetParent(hWnd), Msg, wParam, lParam );
1462 else
1463 SendMessageW( hWnd, WM_SYSCOMMAND, SC_KEYMENU, wParam );
1464 }
1465 else /* check for Ctrl-Esc */
1466 if (wParam != '\x1b') MessageBeep(0);
1467 break;
1468 }
1469
1470 case WM_SHOWWINDOW:
1471 {
1472 if (lParam) // Call when it is necessary.
1473 NtUserMessageCall( hWnd, Msg, wParam, lParam, 0, FNID_DEFWINDOWPROC, FALSE);
1474 break;
1475 }
1476
1477 case WM_CANCELMODE:
1478 {
1479 iMenuSysKey = 0;
1480 /* FIXME: Check for a desktop. */
1481 if (!(GetWindowLongW( hWnd, GWL_STYLE ) & WS_CHILD)) EndMenu();
1482 if (GetCapture() == hWnd)
1483 {
1484 ReleaseCapture();
1485 }
1486 break;
1487 }
1488
1489 case WM_VKEYTOITEM:
1490 case WM_CHARTOITEM:
1491 return (-1);
1492 /*
1493 case WM_DROPOBJECT:
1494 return DRAG_FILE;
1495 */
1496 case WM_QUERYDROPOBJECT:
1497 {
1498 if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES)
1499 {
1500 return(1);
1501 }
1502 break;
1503 }
1504
1505 case WM_QUERYDRAGICON:
1506 {
1507 UINT Len;
1508 HICON hIcon;
1509
1510 hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON);
1511 if (hIcon)
1512 {
1513 return ((LRESULT)hIcon);
1514 }
1515 for (Len = 1; Len < 64; Len++)
1516 {
1517 if ((hIcon = LoadIconW(NULL, MAKEINTRESOURCEW(Len))) != NULL)
1518 {
1519 return((LRESULT)hIcon);
1520 }
1521 }
1522 return ((LRESULT)LoadIconW(0, IDI_APPLICATION));
1523 }
1524
1525 /* FIXME: WM_ISACTIVEICON */
1526
1527 case WM_NOTIFYFORMAT:
1528 {
1529 if (lParam == NF_QUERY)
1530 return IsWindowUnicode(hWnd) ? NFR_UNICODE : NFR_ANSI;
1531 break;
1532 }
1533
1534 case WM_SETICON:
1535 {
1536 INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
1537 HICON hOldIcon = (HICON)GetClassLongW(hWnd, Index);
1538 SetClassLongW(hWnd, Index, lParam);
1539 SetWindowPos(hWnd, 0, 0, 0, 0, 0,
1540 SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
1541 SWP_NOACTIVATE | SWP_NOZORDER);
1542 return ((LRESULT)hOldIcon);
1543 }
1544
1545 case WM_GETICON:
1546 {
1547 INT Index = (wParam == ICON_BIG) ? GCL_HICON : GCL_HICONSM;
1548 return (GetClassLongW(hWnd, Index));
1549 }
1550
1551 case WM_HELP:
1552 {
1553 if (bUnicode)
1554 {
1555 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1556 }
1557 else
1558 {
1559 SendMessageA(GetParent(hWnd), Msg, wParam, lParam);
1560 }
1561 break;
1562 }
1563
1564 case WM_SYSTIMER:
1565 {
1566 THRDCARETINFO CaretInfo;
1567 switch(wParam)
1568 {
1569 case 0xffff: /* Caret timer */
1570 /* switch showing byte in win32k and get information about the caret */
1571 if(NtUserSwitchCaretShowing(&CaretInfo) && (CaretInfo.hWnd == hWnd))
1572 {
1573 DrawCaret(hWnd, &CaretInfo);
1574 }
1575 break;
1576 }
1577 break;
1578 }
1579
1580 case WM_QUERYOPEN:
1581 case WM_QUERYENDSESSION:
1582 {
1583 return (1);
1584 }
1585
1586 case WM_INPUTLANGCHANGEREQUEST:
1587 {
1588 HKL NewHkl;
1589
1590 if(wParam & INPUTLANGCHANGE_BACKWARD
1591 && wParam & INPUTLANGCHANGE_FORWARD)
1592 {
1593 return FALSE;
1594 }
1595
1596 //FIXME: What to do with INPUTLANGCHANGE_SYSCHARSET ?
1597
1598 if(wParam & INPUTLANGCHANGE_BACKWARD) NewHkl = (HKL) HKL_PREV;
1599 else if(wParam & INPUTLANGCHANGE_FORWARD) NewHkl = (HKL) HKL_NEXT;
1600 else NewHkl = (HKL) lParam;
1601
1602 NtUserActivateKeyboardLayout(NewHkl, 0);
1603
1604 return TRUE;
1605 }
1606
1607 case WM_INPUTLANGCHANGE:
1608 {
1609 int count = 0;
1610 HWND *win_array = WIN_ListChildren( hWnd );
1611
1612 if (!win_array)
1613 break;
1614 while (win_array[count])
1615 SendMessageW( win_array[count++], WM_INPUTLANGCHANGE, wParam, lParam);
1616 HeapFree(GetProcessHeap(),0,win_array);
1617 break;
1618 }
1619
1620 case WM_QUERYUISTATE:
1621 {
1622 LRESULT Ret = 0;
1623 PWINDOW Wnd = ValidateHwnd(hWnd);
1624 if (Wnd != NULL)
1625 {
1626 if (Wnd->HideFocus)
1627 Ret |= UISF_HIDEFOCUS;
1628 if (Wnd->HideAccel)
1629 Ret |= UISF_HIDEACCEL;
1630 }
1631 return Ret;
1632 }
1633
1634 case WM_CHANGEUISTATE:
1635 {
1636 BOOL AlwaysShowCues = FALSE;
1637 WORD Action = LOWORD(wParam);
1638 WORD Flags = HIWORD(wParam);
1639 PWINDOW Wnd;
1640
1641 SystemParametersInfoW(SPI_GETKEYBOARDCUES, 0, &AlwaysShowCues, 0);
1642 if (AlwaysShowCues)
1643 break;
1644
1645 Wnd= ValidateHwnd(hWnd);
1646 if (!Wnd || lParam != 0)
1647 break;
1648
1649 if (Flags & ~(UISF_HIDEFOCUS | UISF_HIDEACCEL | UISF_ACTIVE))
1650 break;
1651
1652 if (Flags & UISF_ACTIVE)
1653 {
1654 WARN("WM_CHANGEUISTATE does not yet support UISF_ACTIVE!\n");
1655 }
1656
1657 if (Action == UIS_INITIALIZE)
1658 {
1659 PDESKTOPINFO Desk = GetThreadDesktopInfo();
1660 if (Desk == NULL)
1661 break;
1662
1663 Action = Desk->LastInputWasKbd ? UIS_CLEAR : UIS_SET;
1664 Flags = UISF_HIDEFOCUS | UISF_HIDEACCEL;
1665
1666 /* We need to update wParam in case we need to send out messages */
1667 wParam = MAKEWPARAM(Action, Flags);
1668 }
1669
1670 switch (Action)
1671 {
1672 case UIS_SET:
1673 /* See if we actually need to change something */
1674 if ((Flags & UISF_HIDEFOCUS) && !Wnd->HideFocus)
1675 break;
1676 if ((Flags & UISF_HIDEACCEL) && !Wnd->HideAccel)
1677 break;
1678
1679 /* Don't need to do anything... */
1680 return 0;
1681
1682 case UIS_CLEAR:
1683 /* See if we actually need to change something */
1684 if ((Flags & UISF_HIDEFOCUS) && Wnd->HideFocus)
1685 break;
1686 if ((Flags & UISF_HIDEACCEL) && Wnd->HideAccel)
1687 break;
1688
1689 /* Don't need to do anything... */
1690 return 0;
1691
1692 default:
1693 WARN("WM_CHANGEUISTATE: Unsupported Action 0x%x\n", Action);
1694 break;
1695 }
1696
1697 if ((Wnd->Style & WS_CHILD) && Wnd->Parent != NULL)
1698 {
1699 /* We're a child window and we need to pass this message down until
1700 we reach the root */
1701 hWnd = UserHMGetHandle((PWINDOW)DesktopPtrToUser(Wnd->Parent));
1702 }
1703 else
1704 {
1705 /* We're a top level window, we need to change the UI state */
1706 Msg = WM_UPDATEUISTATE;
1707 }
1708
1709 if (bUnicode)
1710 return SendMessageW(hWnd, Msg, wParam, lParam);
1711 else
1712 return SendMessageA(hWnd, Msg, wParam, lParam);
1713 }
1714
1715 case WM_UPDATEUISTATE:
1716 {
1717 BOOL Change = TRUE;
1718 BOOL AlwaysShowCues = FALSE;
1719 WORD Action = LOWORD(wParam);
1720 WORD Flags = HIWORD(wParam);
1721 PWINDOW Wnd;
1722
1723 SystemParametersInfoW(SPI_GETKEYBOARDCUES, 0, &AlwaysShowCues, 0);
1724 if (AlwaysShowCues)
1725 break;
1726
1727 Wnd = ValidateHwnd(hWnd);
1728 if (!Wnd || lParam != 0)
1729 break;
1730
1731 if (Flags & ~(UISF_HIDEFOCUS | UISF_HIDEACCEL | UISF_ACTIVE))
1732 break;
1733
1734 if (Flags & UISF_ACTIVE)
1735 {
1736 WARN("WM_UPDATEUISTATE does not yet support UISF_ACTIVE!\n");
1737 }
1738
1739 if (Action == UIS_INITIALIZE)
1740 {
1741 PDESKTOPINFO Desk = GetThreadDesktopInfo();
1742 if (Desk == NULL)
1743 break;
1744
1745 Action = Desk->LastInputWasKbd ? UIS_CLEAR : UIS_SET;
1746 Flags = UISF_HIDEFOCUS | UISF_HIDEACCEL;
1747
1748 /* We need to update wParam for broadcasting the update */
1749 wParam = MAKEWPARAM(Action, Flags);
1750 }
1751
1752 switch (Action)
1753 {
1754 case UIS_SET:
1755 /* See if we actually need to change something */
1756 if ((Flags & UISF_HIDEFOCUS) && !Wnd->HideFocus)
1757 break;
1758 if ((Flags & UISF_HIDEACCEL) && !Wnd->HideAccel)
1759 break;
1760
1761 /* Don't need to do anything... */
1762 Change = FALSE;
1763 break;
1764
1765 case UIS_CLEAR:
1766 /* See if we actually need to change something */
1767 if ((Flags & UISF_HIDEFOCUS) && Wnd->HideFocus)
1768 break;
1769 if ((Flags & UISF_HIDEACCEL) && Wnd->HideAccel)
1770 break;
1771
1772 /* Don't need to do anything... */
1773 Change = FALSE;
1774 break;
1775
1776 default:
1777 WARN("WM_UPDATEUISTATE: Unsupported Action 0x%x\n", Action);
1778 return 0;
1779 }
1780
1781 /* Pack the information and call win32k */
1782 if (Change)
1783 {
1784 if (!NtUserCallTwoParam((DWORD)hWnd, (DWORD)Flags | ((DWORD)Action << 3), TWOPARAM_ROUTINE_ROS_UPDATEUISTATE))
1785 break;
1786 }
1787
1788 /* Always broadcast the update to all children */
1789 EnumChildWindows(hWnd,
1790 UserSendUiUpdateMsg,
1791 (LPARAM)wParam);
1792
1793 break;
1794 }
1795
1796 }
1797 return 0;
1798 }
1799
1800
1801 /*
1802 * helpers for calling IMM32 (from Wine 10/22/2008)
1803 *
1804 * WM_IME_* messages are generated only by IMM32,
1805 * so I assume imm32 is already LoadLibrary-ed.
1806 */
1807 static HWND
1808 DefWndImmGetDefaultIMEWnd(HWND hwnd)
1809 {
1810 HINSTANCE hInstIMM = GetModuleHandleW(L"imm32\0");
1811 HWND (WINAPI *pFunc)(HWND);
1812 HWND hwndRet = 0;
1813
1814 if (!hInstIMM)
1815 {
1816 ERR("cannot get IMM32 handle\n");
1817 return 0;
1818 }
1819
1820 pFunc = (void*) GetProcAddress(hInstIMM, "ImmGetDefaultIMEWnd");
1821 if (pFunc != NULL)
1822 hwndRet = (*pFunc)(hwnd);
1823
1824 return hwndRet;
1825 }
1826
1827
1828 static BOOL
1829 DefWndImmIsUIMessageA(HWND hwndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1830 {
1831 HINSTANCE hInstIMM = GetModuleHandleW(L"imm32\0");
1832 BOOL (WINAPI *pFunc)(HWND,UINT,WPARAM,LPARAM);
1833 BOOL fRet = FALSE;
1834
1835 if (!hInstIMM)
1836 {
1837 ERR("cannot get IMM32 handle\n");
1838 return FALSE;
1839 }
1840
1841 pFunc = (void*) GetProcAddress(hInstIMM, "ImmIsUIMessageA");
1842 if (pFunc != NULL)
1843 fRet = (*pFunc)(hwndIME, msg, wParam, lParam);
1844
1845 return fRet;
1846 }
1847
1848
1849 static BOOL
1850 DefWndImmIsUIMessageW(HWND hwndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1851 {
1852 HINSTANCE hInstIMM = GetModuleHandleW(L"imm32\0");
1853 BOOL (WINAPI *pFunc)(HWND,UINT,WPARAM,LPARAM);
1854 BOOL fRet = FALSE;
1855
1856 if (!hInstIMM)
1857 {
1858 ERR("cannot get IMM32 handle\n");
1859 return FALSE;
1860 }
1861
1862 pFunc = (void*) GetProcAddress(hInstIMM, "ImmIsUIMessageW");
1863 if (pFunc != NULL)
1864 fRet = (*pFunc)(hwndIME, msg, wParam, lParam);
1865
1866 return fRet;
1867 }
1868
1869
1870 LRESULT WINAPI
1871 DefWindowProcA(HWND hWnd,
1872 UINT Msg,
1873 WPARAM wParam,
1874 LPARAM lParam)
1875 {
1876 LRESULT Result = 0;
1877 PWINDOW Wnd;
1878
1879 SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam);
1880 switch (Msg)
1881 {
1882 case WM_NCCREATE:
1883 {
1884 LPCREATESTRUCTA cs = (LPCREATESTRUCTA)lParam;
1885 /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
1886 * may have child window IDs instead of window name */
1887
1888 DefSetText(hWnd, (PCWSTR)cs->lpszName, TRUE);
1889
1890 Result = 1;
1891 break;
1892 }
1893
1894 case WM_GETTEXTLENGTH:
1895 {
1896 PWSTR buf;
1897 ULONG len;
1898
1899 Wnd = ValidateHwnd(hWnd);
1900 if (Wnd != NULL && Wnd->WindowName.Length != 0)
1901 {
1902 buf = DesktopPtrToUser(Wnd->WindowName.Buffer);
1903 if (buf != NULL &&
1904 NT_SUCCESS(RtlUnicodeToMultiByteSize(&len,
1905 buf,
1906 Wnd->WindowName.Length)))
1907 {
1908 Result = (LRESULT) len;
1909 }
1910 }
1911 else Result = 0L;
1912
1913 break;
1914 }
1915
1916 case WM_GETTEXT:
1917 {
1918 PWSTR buf = NULL;
1919 PSTR outbuf = (PSTR)lParam;
1920 UINT copy;
1921
1922 Wnd = ValidateHwnd(hWnd);
1923 if (Wnd != NULL && wParam != 0)
1924 {
1925 if (Wnd->WindowName.Buffer != NULL)
1926 buf = DesktopPtrToUser(Wnd->WindowName.Buffer);
1927 else
1928 outbuf[0] = L'\0';
1929
1930 if (buf != NULL)
1931 {
1932 if (Wnd->WindowName.Length != 0)
1933 {
1934 copy = min(Wnd->WindowName.Length / sizeof(WCHAR), wParam - 1);
1935 Result = WideCharToMultiByte(CP_ACP,
1936 0,
1937 buf,
1938 copy,
1939 outbuf,
1940 wParam,
1941 NULL,
1942 NULL);
1943 outbuf[Result] = '\0';
1944 }
1945 else
1946 outbuf[0] = '\0';
1947 }
1948 }
1949 break;
1950 }
1951
1952 case WM_SETTEXT:
1953 {
1954 DefSetText(hWnd, (PCWSTR)lParam, TRUE);
1955
1956 if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
1957 {
1958 DefWndNCPaint(hWnd, (HRGN)1, -1);
1959 }
1960
1961 Result = 1;
1962 break;
1963 }
1964
1965 case WM_IME_KEYDOWN:
1966 {
1967 Result = PostMessageA(hWnd, WM_KEYDOWN, wParam, lParam);
1968 break;
1969 }
1970
1971 case WM_IME_KEYUP:
1972 {
1973 Result = PostMessageA(hWnd, WM_KEYUP, wParam, lParam);
1974 break;
1975 }
1976
1977 case WM_IME_CHAR:
1978 {
1979 if (HIBYTE(wParam))
1980 PostMessageA(hWnd, WM_CHAR, HIBYTE(wParam), lParam);
1981 PostMessageA(hWnd, WM_CHAR, LOBYTE(wParam), lParam);
1982 break;
1983 }
1984
1985 case WM_IME_STARTCOMPOSITION:
1986 case WM_IME_COMPOSITION:
1987 case WM_IME_ENDCOMPOSITION:
1988 case WM_IME_SELECT:
1989 case WM_IME_NOTIFY:
1990 {
1991 HWND hwndIME;
1992
1993 hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
1994 if (hwndIME)
1995 Result = SendMessageA(hwndIME, Msg, wParam, lParam);
1996 break;
1997 }
1998
1999 case WM_IME_SETCONTEXT:
2000 {
2001 HWND hwndIME;
2002
2003 hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
2004 if (hwndIME)
2005 Result = DefWndImmIsUIMessageA(hwndIME, Msg, wParam, lParam);
2006 break;
2007 }
2008
2009 /* fall through */
2010 default:
2011 Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, FALSE);
2012 }
2013
2014 SPY_ExitMessage(SPY_RESULT_DEFWND, hWnd, Msg, Result, wParam, lParam);
2015 return Result;
2016 }
2017
2018
2019 LRESULT WINAPI
2020 DefWindowProcW(HWND hWnd,
2021 UINT Msg,
2022 WPARAM wParam,
2023 LPARAM lParam)
2024 {
2025 LRESULT Result = 0;
2026 PWINDOW Wnd;
2027
2028 SPY_EnterMessage(SPY_DEFWNDPROC, hWnd, Msg, wParam, lParam);
2029 switch (Msg)
2030 {
2031 case WM_NCCREATE:
2032 {
2033 LPCREATESTRUCTW cs = (LPCREATESTRUCTW)lParam;
2034 /* check for string, as static icons, bitmaps (SS_ICON, SS_BITMAP)
2035 * may have child window IDs instead of window name */
2036
2037 DefSetText(hWnd, cs->lpszName, FALSE);
2038 Result = 1;
2039 break;
2040 }
2041
2042 case WM_GETTEXTLENGTH:
2043 {
2044 PWSTR buf;
2045 ULONG len;
2046
2047 Wnd = ValidateHwnd(hWnd);
2048 if (Wnd != NULL && Wnd->WindowName.Length != 0)
2049 {
2050 buf = DesktopPtrToUser(Wnd->WindowName.Buffer);
2051 if (buf != NULL &&
2052 NT_SUCCESS(RtlUnicodeToMultiByteSize(&len,
2053 buf,
2054 Wnd->WindowName.Length)))
2055 {
2056 Result = (LRESULT) (Wnd->WindowName.Length / sizeof(WCHAR));
2057 }
2058 }
2059 else Result = 0L;
2060
2061 break;
2062 }
2063
2064 case WM_GETTEXT:
2065 {
2066 PWSTR buf = NULL;
2067 PWSTR outbuf = (PWSTR)lParam;
2068
2069 Wnd = ValidateHwnd(hWnd);
2070 if (Wnd != NULL && wParam != 0)
2071 {
2072 if (Wnd->WindowName.Buffer != NULL)
2073 buf = DesktopPtrToUser(Wnd->WindowName.Buffer);
2074 else
2075 outbuf[0] = L'\0';
2076
2077 if (buf != NULL)
2078 {
2079 if (Wnd->WindowName.Length != 0)
2080 {
2081 Result = min(Wnd->WindowName.Length / sizeof(WCHAR), wParam - 1);
2082 RtlCopyMemory(outbuf,
2083 buf,
2084 Result * sizeof(WCHAR));
2085 outbuf[Result] = L'\0';
2086 }
2087 else
2088 outbuf[0] = L'\0';
2089 }
2090 }
2091 break;
2092 }
2093
2094 case WM_SETTEXT:
2095 {
2096 DefSetText(hWnd, (PCWSTR)lParam, FALSE);
2097
2098 if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
2099 {
2100 DefWndNCPaint(hWnd, (HRGN)1, -1);
2101 }
2102 Result = 1;
2103 break;
2104 }
2105
2106 case WM_IME_CHAR:
2107 {
2108 PostMessageW(hWnd, WM_CHAR, wParam, lParam);
2109 Result = 0;
2110 break;
2111 }
2112
2113 case WM_IME_KEYDOWN:
2114 {
2115 Result = PostMessageW(hWnd, WM_KEYDOWN, wParam, lParam);
2116 break;
2117 }
2118
2119 case WM_IME_KEYUP:
2120 {
2121 Result = PostMessageW(hWnd, WM_KEYUP, wParam, lParam);
2122 break;
2123 }
2124
2125 case WM_IME_STARTCOMPOSITION:
2126 case WM_IME_COMPOSITION:
2127 case WM_IME_ENDCOMPOSITION:
2128 case WM_IME_SELECT:
2129 case WM_IME_NOTIFY:
2130 {
2131 HWND hwndIME;
2132
2133 hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
2134 if (hwndIME)
2135 Result = SendMessageW(hwndIME, Msg, wParam, lParam);
2136 break;
2137 }
2138
2139 case WM_IME_SETCONTEXT:
2140 {
2141 HWND hwndIME;
2142
2143 hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
2144 if (hwndIME)
2145 Result = DefWndImmIsUIMessageW(hwndIME, Msg, wParam, lParam);
2146 break;
2147 }
2148
2149 default:
2150 Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, TRUE);
2151 }
2152 SPY_ExitMessage(SPY_RESULT_DEFWND, hWnd, Msg, Result, wParam, lParam);
2153
2154 return Result;
2155 }
2156