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