Merge 13511:13830 from trunk
[reactos.git] / reactos / lib / user32 / windows / defwnd.c
1 /* $Id$
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 #include <windowsx.h>
16 #include <window.h>
17 #include <user32/wininternal.h>
18 #include <string.h>
19 #include <cursor.h>
20 #include <menu.h>
21 #include <scroll.h>
22 #include <winpos.h>
23
24 #define NDEBUG
25 #include <debug.h>
26
27 #ifndef WM_SETVISIBLE
28 #define WM_SETVISIBLE 9
29 #endif
30 #ifndef WM_QUERYDROPOBJECT
31 #define WM_QUERYDROPOBJECT 0x022B
32 #endif
33
34 LRESULT DefWndNCPaint(HWND hWnd, HRGN hRgn);
35 LRESULT DefWndNCCalcSize(HWND hWnd, BOOL CalcSizeStruct, RECT *Rect);
36 LRESULT DefWndNCActivate(HWND hWnd, WPARAM wParam);
37 LRESULT DefWndNCHitTest(HWND hWnd, POINT Point);
38 LRESULT DefWndNCLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam);
39 LRESULT DefWndNCLButtonDblClk(HWND hWnd, WPARAM wParam, LPARAM lParam);
40 void FASTCALL MenuInitSysMenuPopup(HMENU Menu, DWORD Style, DWORD ClsStyle, LONG HitTest );
41
42 /* GLOBALS *******************************************************************/
43
44 COLORREF SysColors[NUM_SYSCOLORS] = {0};
45 HPEN SysPens[NUM_SYSCOLORS] = {0};
46 HBRUSH SysBrushes[NUM_SYSCOLORS] = {0};
47
48 /* Bits in the dwKeyData */
49 #define KEYDATA_ALT 0x2000
50
51 /* FUNCTIONS *****************************************************************/
52
53 void
54 InitStockObjects(void)
55 {
56 /* FIXME - Instead of copying the stuff to usermode we should map the tables to
57 userland. The current implementation has one big flaw: the system color
58 table doesn't get updated when another process changes them. That's why
59 we should rather map the table into usermode. But it only affects the
60 SysColors table - the pens, brushes and stock objects are not affected
61 as their handles never change. But it'd be faster to map them, too. */
62 if(SysBrushes[0] == NULL)
63 {
64 /* only initialize once */
65 NtUserGetSysColors(SysColors, NUM_SYSCOLORS);
66 NtUserGetSysColorPens(SysPens, NUM_SYSCOLORS);
67 NtUserGetSysColorBrushes(SysBrushes, NUM_SYSCOLORS);
68 }
69 }
70
71 /*
72 * @implemented
73 */
74 DWORD STDCALL
75 GetSysColor(int nIndex)
76 {
77 if(nIndex >= 0 && nIndex <= NUM_SYSCOLORS)
78 {
79 return SysColors[nIndex];
80 }
81
82 SetLastError(ERROR_INVALID_PARAMETER);
83 return 0;
84 }
85
86 /*
87 * @implemented
88 */
89 HPEN STDCALL
90 GetSysColorPen(int nIndex)
91 {
92 if(nIndex >= 0 && nIndex <= NUM_SYSCOLORS)
93 {
94 return SysPens[nIndex];
95 }
96
97 SetLastError(ERROR_INVALID_PARAMETER);
98 return NULL;
99 }
100
101 /*
102 * @implemented
103 */
104 HBRUSH STDCALL
105 GetSysColorBrush(int nIndex)
106 {
107 if(nIndex >= 0 && nIndex <= NUM_SYSCOLORS)
108 {
109 return SysBrushes[nIndex];
110 }
111
112 SetLastError(ERROR_INVALID_PARAMETER);
113 return NULL;
114 }
115
116 /*
117 * @implemented
118 */
119 BOOL
120 STDCALL
121 SetSysColors(
122 int cElements,
123 CONST INT *lpaElements,
124 CONST COLORREF *lpaRgbValues)
125 {
126 BOOL Ret;
127 struct
128 {
129 INT *Elements;
130 COLORREF *Colors;
131 } ChangeSysColors;
132
133 ChangeSysColors.Elements = (INT*)lpaElements;
134 ChangeSysColors.Colors = (COLORREF*)lpaRgbValues;
135
136 if(cElements > 0)
137 {
138 Ret = NtUserSetSysColors(&ChangeSysColors, cElements);
139 if(Ret)
140 {
141 /* FIXME - just change it in the usermode structure, too, instead of asking win32k again */
142 NtUserGetSysColors(SysColors, NUM_SYSCOLORS);
143 }
144 }
145 else
146 {
147 SetLastError(ERROR_INVALID_PARAMETER);
148 Ret = FALSE;
149 }
150
151 return Ret;
152 }
153
154 void
155 UserGetInsideRectNC(HWND hWnd, RECT *rect)
156 {
157 RECT WindowRect;
158 ULONG Style;
159 ULONG ExStyle;
160
161 Style = GetWindowLongW(hWnd, GWL_STYLE);
162 ExStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
163 GetWindowRect(hWnd, &WindowRect);
164 rect->top = rect->left = 0;
165 rect->right = WindowRect.right - WindowRect.left;
166 rect->bottom = WindowRect.bottom - WindowRect.top;
167
168 if (Style & WS_ICONIC)
169 {
170 return;
171 }
172
173 /* Remove frame from rectangle */
174 if (UserHasThickFrameStyle(Style, ExStyle ))
175 {
176 InflateRect(rect, -GetSystemMetrics(SM_CXFRAME),
177 -GetSystemMetrics(SM_CYFRAME));
178 }
179 else
180 {
181 if (UserHasDlgFrameStyle(Style, ExStyle ))
182 {
183 InflateRect(rect, -GetSystemMetrics(SM_CXDLGFRAME),
184 -GetSystemMetrics(SM_CYDLGFRAME));
185 /* FIXME: this isn't in NC_AdjustRect? why not? */
186 if (ExStyle & WS_EX_DLGMODALFRAME)
187 InflateRect( rect, -1, 0 );
188 }
189 else
190 {
191 if (UserHasThinFrameStyle(Style, ExStyle))
192 {
193 InflateRect(rect, -GetSystemMetrics(SM_CXBORDER),
194 -GetSystemMetrics(SM_CYBORDER));
195 }
196 }
197 }
198 }
199
200
201 VOID
202 DefWndSetRedraw(HWND hWnd, WPARAM wParam)
203 {
204 if ((BOOL) wParam && 0 == (GetWindowLong(hWnd, GWL_STYLE) & WS_VISIBLE))
205 {
206 ShowWindow(hWnd, SW_NORMAL);
207 }
208
209 UNIMPLEMENTED;
210 }
211
212
213 LRESULT
214 DefWndHandleSetCursor(HWND hWnd, WPARAM wParam, LPARAM lParam, ULONG Style)
215 {
216 /* Not for child windows. */
217 if (hWnd != (HWND)wParam)
218 {
219 return(0);
220 }
221
222 switch((INT_PTR) LOWORD(lParam))
223 {
224 case HTERROR:
225 {
226 WORD Msg = HIWORD(lParam);
227 if (Msg == WM_LBUTTONDOWN || Msg == WM_MBUTTONDOWN ||
228 Msg == WM_RBUTTONDOWN || Msg == WM_XBUTTONDOWN)
229 {
230 MessageBeep(0);
231 }
232 break;
233 }
234
235 case HTCLIENT:
236 {
237 HICON hCursor = (HICON)GetClassLongW(hWnd, GCL_HCURSOR);
238 if (hCursor)
239 {
240 SetCursor(hCursor);
241 return(TRUE);
242 }
243 return(FALSE);
244 }
245
246 case HTLEFT:
247 case HTRIGHT:
248 {
249 if (Style & WS_MAXIMIZE)
250 {
251 break;
252 }
253 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZEWE)));
254 }
255
256 case HTTOP:
257 case HTBOTTOM:
258 {
259 if (Style & WS_MAXIMIZE)
260 {
261 break;
262 }
263 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENS)));
264 }
265
266 case HTTOPLEFT:
267 case HTBOTTOMRIGHT:
268 {
269 if (Style & WS_MAXIMIZE)
270 {
271 break;
272 }
273 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENWSE)));
274 }
275
276 case HTBOTTOMLEFT:
277 case HTTOPRIGHT:
278 {
279 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_MAXIMIZE)
280 {
281 break;
282 }
283 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENESW)));
284 }
285 }
286 return((LRESULT)SetCursor(LoadCursorW(0, IDC_ARROW)));
287 }
288
289 static LONG
290 DefWndStartSizeMove(HWND hWnd, WPARAM wParam, POINT *capturePoint)
291 {
292 LONG hittest = 0;
293 POINT pt;
294 MSG msg;
295 RECT rectWindow;
296 ULONG Style = GetWindowLongW(hWnd, GWL_STYLE);
297
298 GetWindowRect(hWnd, &rectWindow);
299
300 if ((wParam & 0xfff0) == SC_MOVE)
301 {
302 /* Move pointer at the center of the caption */
303 RECT rect;
304 UserGetInsideRectNC(hWnd, &rect);
305 if (Style & WS_SYSMENU)
306 rect.left += GetSystemMetrics(SM_CXSIZE) + 1;
307 if (Style & WS_MINIMIZEBOX)
308 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
309 if (Style & WS_MAXIMIZEBOX)
310 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
311 pt.x = rectWindow.left + (rect.right - rect.left) / 2;
312 pt.y = rectWindow.top + rect.top + GetSystemMetrics(SM_CYSIZE)/2;
313 hittest = HTCAPTION;
314 *capturePoint = pt;
315 }
316 else /* SC_SIZE */
317 {
318 while(!hittest)
319 {
320 GetMessageW(&msg, NULL, 0, 0);
321 switch(msg.message)
322 {
323 case WM_MOUSEMOVE:
324 hittest = DefWndNCHitTest(hWnd, msg.pt);
325 if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT))
326 hittest = 0;
327 break;
328
329 case WM_LBUTTONUP:
330 return 0;
331
332 case WM_KEYDOWN:
333 switch(msg.wParam)
334 {
335 case VK_UP:
336 hittest = HTTOP;
337 pt.x =(rectWindow.left+rectWindow.right)/2;
338 pt.y = rectWindow.top + GetSystemMetrics(SM_CYFRAME) / 2;
339 break;
340 case VK_DOWN:
341 hittest = HTBOTTOM;
342 pt.x =(rectWindow.left+rectWindow.right)/2;
343 pt.y = rectWindow.bottom - GetSystemMetrics(SM_CYFRAME) / 2;
344 break;
345 case VK_LEFT:
346 hittest = HTLEFT;
347 pt.x = rectWindow.left + GetSystemMetrics(SM_CXFRAME) / 2;
348 pt.y =(rectWindow.top+rectWindow.bottom)/2;
349 break;
350 case VK_RIGHT:
351 hittest = HTRIGHT;
352 pt.x = rectWindow.right - GetSystemMetrics(SM_CXFRAME) / 2;
353 pt.y =(rectWindow.top+rectWindow.bottom)/2;
354 break;
355 case VK_RETURN:
356 case VK_ESCAPE: return 0;
357 }
358 }
359 }
360 *capturePoint = pt;
361 }
362 SetCursorPos( pt.x, pt.y );
363 DefWndHandleSetCursor(hWnd, (WPARAM)hWnd, MAKELONG(hittest, WM_MOUSEMOVE), Style);
364 return hittest;
365 }
366
367 #define ON_LEFT_BORDER(hit) \
368 (((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
369 #define ON_RIGHT_BORDER(hit) \
370 (((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
371 #define ON_TOP_BORDER(hit) \
372 (((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
373 #define ON_BOTTOM_BORDER(hit) \
374 (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
375
376 VOID STATIC
377 UserDrawWindowFrame(HDC hdc, const RECT *rect,
378 ULONG width, ULONG height)
379 {
380 static HBRUSH hDraggingRectBrush = NULL;
381
382 if(!hDraggingRectBrush)
383 {
384 static HBITMAP hDraggingPattern = NULL;
385 const DWORD Pattern[4] = {0x5555AAAA, 0x5555AAAA, 0x5555AAAA, 0x5555AAAA};
386
387 hDraggingPattern = CreateBitmap(8, 8, 1, 1, Pattern);
388 hDraggingRectBrush = CreatePatternBrush(hDraggingPattern);
389 }
390
391 HBRUSH hbrush = SelectObject( hdc, hDraggingRectBrush );
392 PatBlt( hdc, rect->left, rect->top,
393 rect->right - rect->left - width, height, PATINVERT );
394 PatBlt( hdc, rect->left, rect->top + height, width,
395 rect->bottom - rect->top - height, PATINVERT );
396 PatBlt( hdc, rect->left + width, rect->bottom - 1,
397 rect->right - rect->left - width, -height, PATINVERT );
398 PatBlt( hdc, rect->right - 1, rect->top, -width,
399 rect->bottom - rect->top - height, PATINVERT );
400 SelectObject( hdc, hbrush );
401 }
402
403 VOID STATIC
404 UserDrawMovingFrame(HDC hdc, RECT *rect, BOOL thickframe)
405 {
406 if(thickframe)
407 {
408 UserDrawWindowFrame(hdc, rect, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME));
409 }
410 else
411 {
412 UserDrawWindowFrame(hdc, rect, 1, 1);
413 }
414 }
415
416 VOID STATIC
417 DefWndDoSizeMove(HWND hwnd, WORD wParam)
418 {
419 HRGN DesktopRgn;
420 MSG msg;
421 RECT sizingRect, mouseRect, origRect, clipRect, unmodRect;
422 HDC hdc;
423 LONG hittest = (LONG)(wParam & 0x0f);
424 HCURSOR hDragCursor = 0, hOldCursor = 0;
425 POINT minTrack, maxTrack;
426 POINT capturePoint, pt;
427 ULONG Style = GetWindowLongW(hwnd, GWL_STYLE);
428 ULONG ExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
429 BOOL thickframe;
430 BOOL iconic = Style & WS_MINIMIZE;
431 BOOL moved = FALSE;
432 DWORD dwPoint = GetMessagePos();
433 BOOL DragFullWindows = FALSE;
434 HWND hWndParent = NULL;
435
436 SystemParametersInfoA(SPI_GETDRAGFULLWINDOWS, 0, &DragFullWindows, 0);
437
438 pt.x = GET_X_LPARAM(dwPoint);
439 pt.y = GET_Y_LPARAM(dwPoint);
440 capturePoint = pt;
441
442 if (IsZoomed(hwnd) || !IsWindowVisible(hwnd))
443 {
444 return;
445 }
446
447 thickframe = UserHasThickFrameStyle(Style, ExStyle) && !(Style & WS_MINIMIZE);
448 if ((wParam & 0xfff0) == SC_MOVE)
449 {
450 if (!hittest)
451 {
452 hittest = DefWndStartSizeMove(hwnd, wParam, &capturePoint);
453 }
454 if (!hittest)
455 {
456 return;
457 }
458 }
459 else /* SC_SIZE */
460 {
461 if (!thickframe)
462 {
463 return;
464 }
465 if (hittest && ((wParam & 0xfff0) != SC_MOUSEMENU))
466 {
467 hittest += (HTLEFT - WMSZ_LEFT);
468 }
469 else
470 {
471 SetCapture(hwnd);
472 hittest = DefWndStartSizeMove(hwnd, wParam, &capturePoint);
473 if (!hittest)
474 {
475 ReleaseCapture();
476 return;
477 }
478 }
479 }
480
481 if (Style & WS_CHILD)
482 {
483 hWndParent = GetParent(hwnd);
484 }
485
486 /* Get min/max info */
487
488 WinPosGetMinMaxInfo(hwnd, NULL, NULL, &minTrack, &maxTrack);
489 GetWindowRect(hwnd, &sizingRect);
490 unmodRect = sizingRect;
491 if (Style & WS_CHILD)
492 {
493 MapWindowPoints( 0, hWndParent, (LPPOINT)&sizingRect, 2 );
494 GetClientRect(hWndParent, &mouseRect );
495 clipRect = mouseRect;
496 MapWindowPoints(hWndParent, HWND_DESKTOP, (LPPOINT)&clipRect, 2);
497 }
498 else
499 {
500 if(!(ExStyle & WS_EX_TOPMOST))
501 {
502 SystemParametersInfoW(SPI_GETWORKAREA, 0, &clipRect, 0);
503 mouseRect = clipRect;
504 }
505 else
506 {
507 SetRect(&mouseRect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
508 clipRect = mouseRect;
509 }
510 }
511 ClipCursor(&clipRect);
512
513 origRect = sizingRect;
514 if (ON_LEFT_BORDER(hittest))
515 {
516 mouseRect.left = max( mouseRect.left, sizingRect.right-maxTrack.x );
517 mouseRect.right = min( mouseRect.right, sizingRect.right-minTrack.x );
518 }
519 else if (ON_RIGHT_BORDER(hittest))
520 {
521 mouseRect.left = max( mouseRect.left, sizingRect.left+minTrack.x );
522 mouseRect.right = min( mouseRect.right, sizingRect.left+maxTrack.x );
523 }
524 if (ON_TOP_BORDER(hittest))
525 {
526 mouseRect.top = max( mouseRect.top, sizingRect.bottom-maxTrack.y );
527 mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minTrack.y);
528 }
529 else if (ON_BOTTOM_BORDER(hittest))
530 {
531 mouseRect.top = max( mouseRect.top, sizingRect.top+minTrack.y );
532 mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+maxTrack.y );
533 }
534 if (Style & WS_CHILD)
535 {
536 MapWindowPoints( hWndParent, 0, (LPPOINT)&mouseRect, 2 );
537 }
538
539 SendMessageA( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
540 NtUserSetGUIThreadHandle(MSQ_STATE_MOVESIZE, hwnd);
541 if (GetCapture() != hwnd) SetCapture( hwnd );
542
543 if (Style & WS_CHILD)
544 {
545 /* Retrieve a default cache DC (without using the window style) */
546 hdc = GetDCEx(hWndParent, 0, DCX_CACHE);
547 DesktopRgn = NULL;
548 }
549 else
550 {
551 hdc = GetDC( 0 );
552 DesktopRgn = CreateRectRgnIndirect(&clipRect);
553 }
554
555 SelectObject(hdc, DesktopRgn);
556
557 if( iconic ) /* create a cursor for dragging */
558 {
559 HICON hIcon = (HICON)GetClassLongW(hwnd, GCL_HICON);
560 if(!hIcon) hIcon = (HICON)SendMessageW( hwnd, WM_QUERYDRAGICON, 0, 0L);
561 if( hIcon ) hDragCursor = CursorIconToCursor( hIcon, TRUE );
562 if( !hDragCursor ) iconic = FALSE;
563 }
564
565 /* invert frame if WIN31_LOOK to indicate mouse click on caption */
566 if( !iconic && !DragFullWindows)
567 {
568 UserDrawMovingFrame( hdc, &sizingRect, thickframe);
569 }
570
571 for(;;)
572 {
573 int dx = 0, dy = 0;
574
575 GetMessageW(&msg, 0, 0, 0);
576
577 /* Exit on button-up, Return, or Esc */
578 if ((msg.message == WM_LBUTTONUP) ||
579 ((msg.message == WM_KEYDOWN) &&
580 ((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
581
582 if (msg.message == WM_PAINT)
583 {
584 if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
585 UpdateWindow( msg.hwnd );
586 if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
587 continue;
588 }
589
590 if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
591 continue; /* We are not interested in other messages */
592
593 pt = msg.pt;
594
595 if (msg.message == WM_KEYDOWN) switch(msg.wParam)
596 {
597 case VK_UP: pt.y -= 8; break;
598 case VK_DOWN: pt.y += 8; break;
599 case VK_LEFT: pt.x -= 8; break;
600 case VK_RIGHT: pt.x += 8; break;
601 }
602
603 pt.x = max( pt.x, mouseRect.left );
604 pt.x = min( pt.x, mouseRect.right );
605 pt.y = max( pt.y, mouseRect.top );
606 pt.y = min( pt.y, mouseRect.bottom );
607
608 dx = pt.x - capturePoint.x;
609 dy = pt.y - capturePoint.y;
610
611 if (dx || dy)
612 {
613 if( !moved )
614 {
615 moved = TRUE;
616
617 if( iconic ) /* ok, no system popup tracking */
618 {
619 hOldCursor = SetCursor(hDragCursor);
620 ShowCursor( TRUE );
621 }
622 }
623
624 if (msg.message == WM_KEYDOWN) SetCursorPos( pt.x, pt.y );
625 else
626 {
627 RECT newRect = unmodRect;
628 WPARAM wpSizingHit = 0;
629
630 if (hittest == HTCAPTION) OffsetRect( &newRect, dx, dy );
631 if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
632 else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
633 if (ON_TOP_BORDER(hittest)) newRect.top += dy;
634 else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
635 if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
636 capturePoint = pt;
637
638 /* determine the hit location */
639 if (hittest >= HTLEFT && hittest <= HTBOTTOMRIGHT)
640 wpSizingHit = WMSZ_LEFT + (hittest - HTLEFT);
641 unmodRect = newRect;
642 SendMessageA( hwnd, WM_SIZING, wpSizingHit, (LPARAM)&newRect );
643
644 if (!iconic)
645 {
646 if(!DragFullWindows)
647 UserDrawMovingFrame( hdc, &newRect, thickframe );
648 else {
649 /* To avoid any deadlocks, all the locks on the windows
650 structures must be suspended before the SetWindowPos */
651 SetWindowPos( hwnd, 0, newRect.left, newRect.top,
652 newRect.right - newRect.left,
653 newRect.bottom - newRect.top,
654 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
655 }
656 }
657 sizingRect = newRect;
658 }
659 }
660 }
661
662 ReleaseCapture();
663 ClipCursor(NULL);
664 if( iconic )
665 {
666 if( moved ) /* restore cursors, show icon title later on */
667 {
668 ShowCursor( FALSE );
669 SetCursor( hOldCursor );
670 }
671 DestroyCursor( hDragCursor );
672 }
673 else if(!DragFullWindows)
674 UserDrawMovingFrame( hdc, &sizingRect, thickframe );
675
676 if (Style & WS_CHILD)
677 ReleaseDC( hWndParent, hdc );
678 else
679 {
680 ReleaseDC( 0, hdc );
681 if(DesktopRgn)
682 {
683 DeleteObject(DesktopRgn);
684 }
685 }
686 NtUserSetGUIThreadHandle(MSQ_STATE_MOVESIZE, NULL);
687 SendMessageA( hwnd, WM_EXITSIZEMOVE, 0, 0 );
688 SendMessageA( hwnd, WM_SETVISIBLE, !IsIconic(hwnd), 0L);
689
690 /* window moved or resized */
691 if (moved)
692 {
693 /* if the moving/resizing isn't canceled call SetWindowPos
694 * with the new position or the new size of the window
695 */
696 if (!((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) )
697 {
698 /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
699 if(!DragFullWindows)
700 SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
701 sizingRect.right - sizingRect.left,
702 sizingRect.bottom - sizingRect.top,
703 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
704 }
705 else { /* restore previous size/position */
706 if(DragFullWindows)
707 SetWindowPos( hwnd, 0, origRect.left, origRect.top,
708 origRect.right - origRect.left,
709 origRect.bottom - origRect.top,
710 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
711 }
712 }
713
714 if( IsWindow(hwnd) )
715 if( Style & WS_MINIMIZE )
716 {
717 /* Single click brings up the system menu when iconized */
718
719 if( !moved )
720 {
721 if( Style & WS_SYSMENU )
722 SendMessageA( hwnd, WM_SYSCOMMAND,
723 SC_MOUSEMENU + HTSYSMENU, MAKELONG(pt.x,pt.y));
724 }
725 }
726 }
727
728
729 /***********************************************************************
730 * DefWndTrackScrollBar
731 *
732 * Track a mouse button press on the horizontal or vertical scroll-bar.
733 */
734 STATIC VOID
735 DefWndTrackScrollBar(HWND Wnd, WPARAM wParam, POINT Pt)
736 {
737 INT ScrollBar;
738
739 if (SC_HSCROLL == (wParam & 0xfff0))
740 {
741 if (HTHSCROLL != (wParam & 0x0f))
742 {
743 return;
744 }
745 ScrollBar = SB_HORZ;
746 }
747 else /* SC_VSCROLL */
748 {
749 if (HTVSCROLL != (wParam & 0x0f))
750 {
751 return;
752 }
753 ScrollBar = SB_VERT;
754 }
755 ScrollTrackScrollBar(Wnd, ScrollBar, Pt );
756 }
757
758
759 LRESULT
760 DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, POINT Pt)
761 {
762 WINDOWPLACEMENT wp;
763
764 switch (wParam & 0xfff0)
765 {
766 case SC_MOVE:
767 case SC_SIZE:
768 DefWndDoSizeMove(hWnd, wParam);
769 break;
770 case SC_MINIMIZE:
771 wp.length = sizeof(WINDOWPLACEMENT);
772 if(GetWindowPlacement(hWnd, &wp))
773 {
774 wp.showCmd = SW_MINIMIZE;
775 SetWindowPlacement(hWnd, &wp);
776 }
777 break;
778 case SC_MAXIMIZE:
779 wp.length = sizeof(WINDOWPLACEMENT);
780 if(GetWindowPlacement(hWnd, &wp))
781 {
782 wp.showCmd = SW_MAXIMIZE;
783 SetWindowPlacement(hWnd, &wp);
784 }
785 break;
786 case SC_RESTORE:
787 wp.length = sizeof(WINDOWPLACEMENT);
788 if(GetWindowPlacement(hWnd, &wp))
789 {
790 wp.showCmd = SW_RESTORE;
791 SetWindowPlacement(hWnd, &wp);
792 }
793 break;
794 case SC_CLOSE:
795 SendMessageA(hWnd, WM_CLOSE, 0, 0);
796 break;
797 case SC_MOUSEMENU:
798 MenuTrackMouseMenuBar(hWnd, wParam & 0x000f, Pt);
799 break;
800 case SC_KEYMENU:
801 MenuTrackKbdMenuBar(hWnd, wParam, Pt.x);
802 break;
803 case SC_VSCROLL:
804 case SC_HSCROLL:
805 DefWndTrackScrollBar(hWnd, wParam, Pt);
806 break;
807
808 default:
809 /* FIXME: Implement */
810 UNIMPLEMENTED;
811 break;
812 }
813
814 return(0);
815 }
816
817 LRESULT
818 DefWndHandleWindowPosChanging(HWND hWnd, WINDOWPOS* Pos)
819 {
820 POINT maxSize, minTrack;
821 LONG style = GetWindowLongA(hWnd, GWL_STYLE);
822
823 if (Pos->flags & SWP_NOSIZE) return 0;
824 if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
825 {
826 WinPosGetMinMaxInfo(hWnd, &maxSize, NULL, &minTrack, NULL);
827 Pos->cx = min(Pos->cx, maxSize.x);
828 Pos->cy = min(Pos->cy, maxSize.y);
829 if (!(style & WS_MINIMIZE))
830 {
831 if (Pos->cx < minTrack.x) Pos->cx = minTrack.x;
832 if (Pos->cy < minTrack.y) Pos->cy = minTrack.y;
833 }
834 }
835 else
836 {
837 Pos->cx = max(Pos->cx, 0);
838 Pos->cy = max(Pos->cy, 0);
839 }
840 return 0;
841 }
842
843 /* Undocumented flags. */
844 #define SWP_NOCLIENTMOVE 0x0800
845 #define SWP_NOCLIENTSIZE 0x1000
846
847 LRESULT
848 DefWndHandleWindowPosChanged(HWND hWnd, WINDOWPOS* Pos)
849 {
850 RECT Rect;
851
852 GetClientRect(hWnd, &Rect);
853 MapWindowPoints(hWnd, (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD ?
854 GetParent(hWnd) : NULL), (LPPOINT) &Rect, 2);
855
856 if (! (Pos->flags & SWP_NOCLIENTMOVE))
857 {
858 SendMessageW(hWnd, WM_MOVE, 0, MAKELONG(Rect.left, Rect.top));
859 }
860
861 if (! (Pos->flags & SWP_NOCLIENTSIZE))
862 {
863 WPARAM wp = SIZE_RESTORED;
864 if (IsZoomed(hWnd))
865 {
866 wp = SIZE_MAXIMIZED;
867 }
868 else if (IsIconic(hWnd))
869 {
870 wp = SIZE_MINIMIZED;
871 }
872 SendMessageW(hWnd, WM_SIZE, wp,
873 MAKELONG(Rect.right - Rect.left, Rect.bottom - Rect.top));
874 }
875
876 return 0;
877 }
878
879 /***********************************************************************
880 * DefWndControlColor
881 *
882 * Default colors for control painting.
883 */
884 HBRUSH
885 DefWndControlColor(HDC hDC, UINT ctlType)
886 {
887 if (CTLCOLOR_SCROLLBAR == ctlType)
888 {
889 HBRUSH hb = GetSysColorBrush(COLOR_SCROLLBAR);
890 COLORREF bk = GetSysColor(COLOR_3DHILIGHT);
891 SetTextColor(hDC, GetSysColor(COLOR_3DFACE));
892 SetBkColor(hDC, bk);
893
894 /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
895 * we better use 0x55aa bitmap brush to make scrollbar's background
896 * look different from the window background.
897 */
898 if (bk == GetSysColor(COLOR_WINDOW))
899 {
900 static const WORD wPattern55AA[] =
901 {
902 0x5555, 0xaaaa, 0x5555, 0xaaaa,
903 0x5555, 0xaaaa, 0x5555, 0xaaaa
904 };
905 static HBITMAP hPattern55AABitmap = NULL;
906 static HBRUSH hPattern55AABrush = NULL;
907 if (hPattern55AABrush == NULL)
908 {
909 hPattern55AABitmap = CreateBitmap(8, 8, 1, 1, wPattern55AA);
910 hPattern55AABrush = CreatePatternBrush(hPattern55AABitmap);
911 }
912 return hPattern55AABrush;
913 }
914 UnrealizeObject(hb);
915 return hb;
916 }
917
918 SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
919
920 if ((CTLCOLOR_EDIT == ctlType) || (CTLCOLOR_LISTBOX == ctlType))
921 {
922 SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
923 }
924 else
925 {
926 SetBkColor(hDC, GetSysColor(COLOR_3DFACE));
927 return GetSysColorBrush(COLOR_3DFACE);
928 }
929
930 return GetSysColorBrush(COLOR_WINDOW);
931 }
932
933 VOID FASTCALL
934 DefWndScreenshot(HWND hWnd)
935 {
936
937 }
938
939 LRESULT STDCALL
940 User32DefWindowProc(HWND hWnd,
941 UINT Msg,
942 WPARAM wParam,
943 LPARAM lParam,
944 BOOL bUnicode)
945 {
946 switch (Msg)
947 {
948 case WM_NCPAINT:
949 {
950 return DefWndNCPaint(hWnd, (HRGN)wParam);
951 }
952
953 case WM_NCCALCSIZE:
954 {
955 return DefWndNCCalcSize(hWnd, (BOOL)wParam, (RECT*)lParam);
956 }
957
958 case WM_NCACTIVATE:
959 {
960 return DefWndNCActivate(hWnd, wParam);
961 }
962
963 case WM_NCHITTEST:
964 {
965 POINT Point;
966 Point.x = GET_X_LPARAM(lParam);
967 Point.y = GET_Y_LPARAM(lParam);
968 return (DefWndNCHitTest(hWnd, Point));
969 }
970
971 case WM_NCLBUTTONDOWN:
972 {
973 return (DefWndNCLButtonDown(hWnd, wParam, lParam));
974 }
975
976 case WM_NCLBUTTONDBLCLK:
977 {
978 return (DefWndNCLButtonDblClk(hWnd, wParam, lParam));
979 }
980
981 case WM_WINDOWPOSCHANGING:
982 {
983 return (DefWndHandleWindowPosChanging(hWnd, (WINDOWPOS*)lParam));
984 }
985
986 case WM_WINDOWPOSCHANGED:
987 {
988 return (DefWndHandleWindowPosChanged(hWnd, (WINDOWPOS*)lParam));
989 }
990
991 case WM_RBUTTONUP:
992 {
993 POINT Pt;
994 if (hWnd == GetCapture())
995 {
996 ReleaseCapture();
997 }
998 Pt.x = GET_X_LPARAM(lParam);
999 Pt.y = GET_Y_LPARAM(lParam);
1000 ClientToScreen(hWnd, &Pt);
1001 lParam = MAKELPARAM(Pt.x, Pt.y);
1002 if (bUnicode)
1003 {
1004 SendMessageW(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
1005 }
1006 else
1007 {
1008 SendMessageA(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
1009 }
1010 break;
1011 }
1012
1013 case WM_CONTEXTMENU:
1014 {
1015 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1016 {
1017 if (bUnicode)
1018 {
1019 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1020 }
1021 else
1022 {
1023 SendMessageA(GetParent(hWnd), WM_CONTEXTMENU, wParam, lParam);
1024 }
1025 }
1026 else
1027 {
1028 POINT Pt;
1029 DWORD Style;
1030 LONG HitCode;
1031
1032 Style = GetWindowLongW(hWnd, GWL_STYLE);
1033
1034 Pt.x = GET_X_LPARAM(lParam);
1035 Pt.y = GET_Y_LPARAM(lParam);
1036 if (Style & WS_CHILD)
1037 {
1038 ScreenToClient(GetParent(hWnd), &Pt);
1039 }
1040
1041 HitCode = DefWndNCHitTest(hWnd, Pt);
1042
1043 if (HitCode == HTCAPTION || HitCode == HTSYSMENU)
1044 {
1045 HMENU SystemMenu;
1046 UINT Flags;
1047
1048 if((SystemMenu = GetSystemMenu(hWnd, FALSE)))
1049 {
1050 MenuInitSysMenuPopup(SystemMenu, GetWindowLongW(hWnd, GWL_STYLE),
1051 GetClassLongW(hWnd, GCL_STYLE), HitCode);
1052
1053 if(HitCode == HTCAPTION)
1054 Flags = TPM_LEFTBUTTON | TPM_RIGHTBUTTON;
1055 else
1056 Flags = TPM_LEFTBUTTON;
1057
1058 TrackPopupMenu(SystemMenu, Flags,
1059 Pt.x, Pt.y, 0, hWnd, NULL);
1060 }
1061 }
1062 }
1063 break;
1064 }
1065
1066 case WM_PRINT:
1067 {
1068 /* FIXME: Implement. */
1069 return (0);
1070 }
1071
1072 case WM_PAINTICON:
1073 case WM_PAINT:
1074 {
1075 PAINTSTRUCT Ps;
1076 HDC hDC = BeginPaint(hWnd, &Ps);
1077 if (hDC)
1078 {
1079 HICON hIcon;
1080 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE &&
1081 (hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON)) != NULL)
1082 {
1083 RECT ClientRect;
1084 INT x, y;
1085 GetClientRect(hWnd, &ClientRect);
1086 x = (ClientRect.right - ClientRect.left -
1087 GetSystemMetrics(SM_CXICON)) / 2;
1088 y = (ClientRect.bottom - ClientRect.top -
1089 GetSystemMetrics(SM_CYICON)) / 2;
1090 DrawIcon(hDC, x, y, hIcon);
1091 }
1092 EndPaint(hWnd, &Ps);
1093 }
1094 return (0);
1095 }
1096
1097 case WM_SYNCPAINT:
1098 {
1099 HRGN hRgn;
1100 hRgn = CreateRectRgn(0, 0, 0, 0);
1101 if (GetUpdateRgn(hWnd, hRgn, FALSE) != NULLREGION)
1102 {
1103 RedrawWindow(hWnd, NULL, hRgn,
1104 RDW_ERASENOW | RDW_ERASE | RDW_FRAME |
1105 RDW_ALLCHILDREN);
1106 }
1107 DeleteObject(hRgn);
1108 return (0);
1109 }
1110
1111 case WM_SETREDRAW:
1112 {
1113 DefWndSetRedraw(hWnd, wParam);
1114 return (0);
1115 }
1116
1117 case WM_CLOSE:
1118 {
1119 DestroyWindow(hWnd);
1120 return (0);
1121 }
1122
1123 case WM_MOUSEACTIVATE:
1124 {
1125 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1126 {
1127 LONG Ret;
1128 if (bUnicode)
1129 {
1130 Ret = SendMessageW(GetParent(hWnd), WM_MOUSEACTIVATE,
1131 wParam, lParam);
1132 }
1133 else
1134 {
1135 Ret = SendMessageA(GetParent(hWnd), WM_MOUSEACTIVATE,
1136 wParam, lParam);
1137 }
1138 if (Ret)
1139 {
1140 return (Ret);
1141 }
1142 }
1143 return ((LOWORD(lParam) >= HTCLIENT) ? MA_ACTIVATE : MA_NOACTIVATE);
1144 }
1145
1146 case WM_ACTIVATE:
1147 {
1148 /* Check if the window is minimized. */
1149 if (LOWORD(wParam) != WA_INACTIVE &&
1150 !(GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE))
1151 {
1152 SetFocus(hWnd);
1153 }
1154 break;
1155 }
1156
1157 case WM_MOUSEWHEEL:
1158 {
1159 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1160 {
1161 if (bUnicode)
1162 {
1163 return (SendMessageW(GetParent(hWnd), WM_MOUSEWHEEL,
1164 wParam, lParam));
1165 }
1166 else
1167 {
1168 return (SendMessageA(GetParent(hWnd), WM_MOUSEWHEEL,
1169 wParam, lParam));
1170 }
1171 }
1172 break;
1173 }
1174
1175 case WM_ERASEBKGND:
1176 case WM_ICONERASEBKGND:
1177 {
1178 RECT Rect;
1179 HBRUSH hBrush = (HBRUSH)GetClassLongW(hWnd, GCL_HBRBACKGROUND);
1180
1181 if (NULL == hBrush)
1182 {
1183 return 0;
1184 }
1185 if (GetClassLongW(hWnd, GCL_STYLE) & CS_PARENTDC)
1186 {
1187 /* can't use GetClipBox with a parent DC or we fill the whole parent */
1188 GetClientRect(hWnd, &Rect);
1189 DPtoLP((HDC)wParam, (LPPOINT)&Rect, 2);
1190 }
1191 else
1192 {
1193 GetClipBox((HDC)wParam, &Rect);
1194 }
1195 FillRect((HDC)wParam, &Rect, hBrush);
1196 return (1);
1197 }
1198
1199 case WM_CTLCOLORMSGBOX:
1200 case WM_CTLCOLOREDIT:
1201 case WM_CTLCOLORLISTBOX:
1202 case WM_CTLCOLORBTN:
1203 case WM_CTLCOLORDLG:
1204 case WM_CTLCOLORSTATIC:
1205 case WM_CTLCOLORSCROLLBAR:
1206 return (LRESULT) DefWndControlColor((HDC)wParam, Msg - WM_CTLCOLORMSGBOX);
1207
1208 case WM_SETCURSOR:
1209 {
1210 ULONG Style = GetWindowLongW(hWnd, GWL_STYLE);
1211
1212 if (Style & WS_CHILD)
1213 {
1214 if (LOWORD(lParam) < HTLEFT || LOWORD(lParam) > HTBOTTOMRIGHT)
1215 {
1216 BOOL bResult;
1217 if (bUnicode)
1218 {
1219 bResult = SendMessageW(GetParent(hWnd), WM_SETCURSOR,
1220 wParam, lParam);
1221 }
1222 else
1223 {
1224 bResult = SendMessageA(GetParent(hWnd), WM_SETCURSOR,
1225 wParam, lParam);
1226 }
1227 if (bResult)
1228 {
1229 return(TRUE);
1230 }
1231 }
1232 }
1233 return (DefWndHandleSetCursor(hWnd, wParam, lParam, Style));
1234 }
1235
1236 case WM_SYSCOMMAND:
1237 {
1238 POINT Pt;
1239 Pt.x = GET_X_LPARAM(lParam);
1240 Pt.y = GET_Y_LPARAM(lParam);
1241 return (DefWndHandleSysCommand(hWnd, wParam, Pt));
1242 }
1243
1244 /* FIXME: Handle key messages. */
1245 /*
1246 case WM_KEYDOWN:
1247 case WM_KEYUP:
1248 case WM_SYSKEYUP:
1249 case WM_SYSCHAR:
1250 */
1251
1252 /* FIXME: This is also incomplete. */
1253 case WM_SYSKEYDOWN:
1254 {
1255 if (HIWORD(lParam) & KEYDATA_ALT)
1256 {
1257 if (wParam == VK_F4) /* Try to close the window */
1258 {
1259 HWND top = GetAncestor(hWnd, GA_ROOT);
1260 if (!(GetClassLongW(top, GCL_STYLE) & CS_NOCLOSE))
1261 {
1262 if (bUnicode)
1263 PostMessageW(top, WM_SYSCOMMAND, SC_CLOSE, 0);
1264 else
1265 PostMessageA(top, WM_SYSCOMMAND, SC_CLOSE, 0);
1266 }
1267 }
1268 else if (wParam == VK_SNAPSHOT)
1269 {
1270 DefWndScreenshot(hWnd);
1271 }
1272 }
1273 break;
1274 }
1275
1276 case WM_SHOWWINDOW:
1277 {
1278 LONG Style;
1279
1280 if (!lParam)
1281 return 0;
1282 Style = GetWindowLongW(hWnd, GWL_STYLE);
1283 if (!(Style & WS_POPUP))
1284 return 0;
1285 if ((Style & WS_VISIBLE) && wParam)
1286 return 0;
1287 if (!(Style & WS_VISIBLE) && !wParam)
1288 return 0;
1289 if (!GetWindow(hWnd, GW_OWNER))
1290 return 0;
1291 ShowWindow(hWnd, wParam ? SW_SHOWNA : SW_HIDE);
1292 break;
1293 }
1294
1295 case WM_CANCELMODE:
1296 {
1297 /* FIXME: Check for a desktop. */
1298 if (GetCapture() == hWnd)
1299 {
1300 ReleaseCapture();
1301 }
1302 break;
1303 }
1304
1305 case WM_VKEYTOITEM:
1306 case WM_CHARTOITEM:
1307 return (-1);
1308 /*
1309 case WM_DROPOBJECT:
1310
1311 break;
1312 */
1313 case WM_QUERYDROPOBJECT:
1314 {
1315 if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES)
1316 {
1317 return(1);
1318 }
1319 break;
1320 }
1321
1322 case WM_QUERYDRAGICON:
1323 {
1324 UINT Len;
1325 HICON hIcon;
1326
1327 hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON);
1328 if (hIcon)
1329 {
1330 return ((LRESULT)hIcon);
1331 }
1332 for (Len = 1; Len < 64; Len++)
1333 {
1334 if ((hIcon = LoadIconW(NULL, MAKEINTRESOURCEW(Len))) != NULL)
1335 {
1336 return((LRESULT)hIcon);
1337 }
1338 }
1339 return ((LRESULT)LoadIconW(0, IDI_APPLICATION));
1340 }
1341
1342 /* FIXME: WM_ISACTIVEICON */
1343
1344 case WM_NOTIFYFORMAT:
1345 {
1346 if (IsWindowUnicode(hWnd))
1347 {
1348 return(NFR_UNICODE);
1349 }
1350 else
1351 {
1352 return(NFR_ANSI);
1353 }
1354 }
1355
1356 case WM_SETICON:
1357 {
1358 INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
1359 HICON hOldIcon = (HICON)GetClassLongW(hWnd, Index);
1360 SetClassLongW(hWnd, Index, lParam);
1361 SetWindowPos(hWnd, 0, 0, 0, 0, 0,
1362 SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
1363 SWP_NOACTIVATE | SWP_NOZORDER);
1364 return ((LRESULT)hOldIcon);
1365 }
1366
1367 case WM_GETICON:
1368 {
1369 INT Index = (wParam == ICON_BIG) ? GCL_HICON : GCL_HICONSM;
1370 return (GetClassLongW(hWnd, Index));
1371 }
1372
1373 case WM_HELP:
1374 {
1375 if (bUnicode)
1376 {
1377 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1378 }
1379 else
1380 {
1381 SendMessageA(GetParent(hWnd), Msg, wParam, lParam);
1382 }
1383 break;
1384 }
1385
1386 case WM_SYSTIMER:
1387 {
1388 THRDCARETINFO CaretInfo;
1389 switch(wParam)
1390 {
1391 case 0xffff: /* Caret timer */
1392 /* switch showing byte in win32k and get information about the caret */
1393 if(NtUserSwitchCaretShowing(&CaretInfo) && (CaretInfo.hWnd == hWnd))
1394 {
1395 DrawCaret(hWnd, &CaretInfo);
1396 }
1397 break;
1398 }
1399 break;
1400 }
1401
1402 case WM_QUERYOPEN:
1403 case WM_QUERYENDSESSION:
1404 {
1405 return (1);
1406 }
1407 }
1408 return 0;
1409 }
1410
1411
1412 LRESULT STDCALL
1413 DefWindowProcA(HWND hWnd,
1414 UINT Msg,
1415 WPARAM wParam,
1416 LPARAM lParam)
1417 {
1418 switch (Msg)
1419 {
1420 case WM_NCCREATE:
1421 {
1422 return TRUE;
1423 }
1424
1425 case WM_GETTEXTLENGTH:
1426 {
1427 return (LRESULT)NtUserInternalGetWindowText(hWnd, NULL, 0);
1428 }
1429
1430 case WM_GETTEXT:
1431 {
1432 LPWSTR Buffer;
1433 LPSTR AnsiBuffer = (LPSTR)lParam;
1434 INT Length;
1435
1436 if (wParam > 1)
1437 {
1438 *((PWSTR)lParam) = '\0';
1439 }
1440 Buffer = HeapAlloc(GetProcessHeap(), 0, wParam * sizeof(WCHAR));
1441 if (!Buffer)
1442 return FALSE;
1443 Length = NtUserInternalGetWindowText(hWnd, Buffer, wParam);
1444 if (Length > 0 && wParam > 0 &&
1445 !WideCharToMultiByte(CP_ACP, 0, Buffer, -1,
1446 AnsiBuffer, wParam, NULL, NULL))
1447 {
1448 AnsiBuffer[0] = '\0';
1449 }
1450
1451 HeapFree(GetProcessHeap(), 0, Buffer);
1452
1453 return (LRESULT)Length;
1454 }
1455
1456 case WM_SETTEXT:
1457 {
1458 ANSI_STRING AnsiString;
1459 UNICODE_STRING UnicodeString;
1460
1461 if(lParam)
1462 {
1463 RtlInitAnsiString(&AnsiString, (LPSTR)lParam);
1464 RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
1465 NtUserDefSetText(hWnd, &UnicodeString);
1466 RtlFreeUnicodeString(&UnicodeString);
1467 }
1468 else
1469 NtUserDefSetText(hWnd, NULL);
1470
1471 if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
1472 {
1473 DefWndNCPaint(hWnd, (HRGN)1);
1474 }
1475 return TRUE;
1476 }
1477
1478 /*
1479 FIXME: Implement these.
1480 case WM_IME_CHAR:
1481 case WM_IME_KEYDOWN:
1482 case WM_IME_KEYUP:
1483 case WM_IME_STARTCOMPOSITION:
1484 case WM_IME_COMPOSITION:
1485 case WM_IME_ENDCOMPOSITION:
1486 case WM_IME_SELECT:
1487 case WM_IME_SETCONTEXT:
1488 */
1489 }
1490
1491 return User32DefWindowProc(hWnd, Msg, wParam, lParam, FALSE);
1492 }
1493
1494
1495 LRESULT STDCALL
1496 DefWindowProcW(HWND hWnd,
1497 UINT Msg,
1498 WPARAM wParam,
1499 LPARAM lParam)
1500 {
1501 switch (Msg)
1502 {
1503 case WM_NCCREATE:
1504 {
1505 return TRUE;
1506 }
1507
1508 case WM_GETTEXTLENGTH:
1509 {
1510 return (LRESULT)NtUserInternalGetWindowText(hWnd, NULL, 0);
1511 }
1512
1513 case WM_GETTEXT:
1514 {
1515 if (wParam > 1)
1516 {
1517 *((PWSTR)lParam) = L'\0';
1518 }
1519 return (LRESULT)NtUserInternalGetWindowText(hWnd, (PWSTR)lParam, wParam);
1520 }
1521
1522 case WM_SETTEXT:
1523 {
1524 UNICODE_STRING UnicodeString;
1525
1526 if(lParam)
1527 RtlInitUnicodeString(&UnicodeString, (LPWSTR)lParam);
1528
1529 NtUserDefSetText(hWnd, (lParam ? &UnicodeString : NULL));
1530
1531 if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
1532 {
1533 DefWndNCPaint(hWnd, (HRGN)1);
1534 }
1535 return (1);
1536 }
1537
1538 case WM_IME_CHAR:
1539 {
1540 SendMessageW(hWnd, WM_CHAR, wParam, lParam);
1541 return (0);
1542 }
1543
1544 case WM_IME_SETCONTEXT:
1545 {
1546 /* FIXME */
1547 return (0);
1548 }
1549 }
1550
1551 return User32DefWindowProc(hWnd, Msg, wParam, lParam, TRUE);
1552 }
1553