0326b7452b5e84a4bf5b01994477e680bb1ffd40
[reactos.git] / reactos / lib / user32 / windows / defwnd.c
1 /* $Id: defwnd.c,v 1.149 2004/12/13 15:39:52 navaraf Exp $
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;
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 if (Style & WS_CHILD)
491 {
492 MapWindowPoints( 0, hWndParent, (LPPOINT)&sizingRect, 2 );
493 GetClientRect(hWndParent, &mouseRect );
494 clipRect = mouseRect;
495 MapWindowPoints(hWndParent, HWND_DESKTOP, (LPPOINT)&clipRect, 2);
496 }
497 else
498 {
499 if(!(ExStyle & WS_EX_TOPMOST))
500 {
501 SystemParametersInfoW(SPI_GETWORKAREA, 0, &clipRect, 0);
502 mouseRect = clipRect;
503 }
504 else
505 {
506 SetRect(&mouseRect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
507 clipRect = mouseRect;
508 }
509 }
510 ClipCursor(&clipRect);
511
512 origRect = sizingRect;
513 if (ON_LEFT_BORDER(hittest))
514 {
515 mouseRect.left = max( mouseRect.left, sizingRect.right-maxTrack.x );
516 mouseRect.right = min( mouseRect.right, sizingRect.right-minTrack.x );
517 }
518 else if (ON_RIGHT_BORDER(hittest))
519 {
520 mouseRect.left = max( mouseRect.left, sizingRect.left+minTrack.x );
521 mouseRect.right = min( mouseRect.right, sizingRect.left+maxTrack.x );
522 }
523 if (ON_TOP_BORDER(hittest))
524 {
525 mouseRect.top = max( mouseRect.top, sizingRect.bottom-maxTrack.y );
526 mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minTrack.y);
527 }
528 else if (ON_BOTTOM_BORDER(hittest))
529 {
530 mouseRect.top = max( mouseRect.top, sizingRect.top+minTrack.y );
531 mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+maxTrack.y );
532 }
533 if (Style & WS_CHILD)
534 {
535 MapWindowPoints( hWndParent, 0, (LPPOINT)&mouseRect, 2 );
536 }
537
538 SendMessageA( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
539 NtUserSetGUIThreadHandle(MSQ_STATE_MOVESIZE, hwnd);
540 if (GetCapture() != hwnd) SetCapture( hwnd );
541
542 if (Style & WS_CHILD)
543 {
544 /* Retrieve a default cache DC (without using the window style) */
545 hdc = GetDCEx(hWndParent, 0, DCX_CACHE);
546 DesktopRgn = NULL;
547 }
548 else
549 {
550 hdc = GetDC( 0 );
551 DesktopRgn = CreateRectRgnIndirect(&clipRect);
552 }
553
554 SelectObject(hdc, DesktopRgn);
555
556 if( iconic ) /* create a cursor for dragging */
557 {
558 HICON hIcon = (HICON)GetClassLongW(hwnd, GCL_HICON);
559 if(!hIcon) hIcon = (HICON)SendMessageW( hwnd, WM_QUERYDRAGICON, 0, 0L);
560 if( hIcon ) hDragCursor = CursorIconToCursor( hIcon, TRUE );
561 if( !hDragCursor ) iconic = FALSE;
562 }
563
564 /* invert frame if WIN31_LOOK to indicate mouse click on caption */
565 if( !iconic && !DragFullWindows)
566 {
567 UserDrawMovingFrame( hdc, &sizingRect, thickframe);
568 }
569
570 for(;;)
571 {
572 int dx = 0, dy = 0;
573
574 GetMessageW(&msg, 0, 0, 0);
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 = sizingRect;
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 SendMessageA( hwnd, WM_SIZING, wpSizingHit, (LPARAM)&newRect );
641
642 if (!iconic)
643 {
644 if(!DragFullWindows)
645 UserDrawMovingFrame( hdc, &newRect, thickframe );
646 else {
647 /* To avoid any deadlocks, all the locks on the windows
648 structures must be suspended before the SetWindowPos */
649 SetWindowPos( hwnd, 0, newRect.left, newRect.top,
650 newRect.right - newRect.left,
651 newRect.bottom - newRect.top,
652 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
653 }
654 }
655 sizingRect = newRect;
656 }
657 }
658 }
659
660 ReleaseCapture();
661 ClipCursor(NULL);
662 if( iconic )
663 {
664 if( moved ) /* restore cursors, show icon title later on */
665 {
666 ShowCursor( FALSE );
667 SetCursor( hOldCursor );
668 }
669 DestroyCursor( hDragCursor );
670 }
671 else if(!DragFullWindows)
672 UserDrawMovingFrame( hdc, &sizingRect, thickframe );
673
674 if (Style & WS_CHILD)
675 ReleaseDC( hWndParent, hdc );
676 else
677 {
678 ReleaseDC( 0, hdc );
679 if(DesktopRgn)
680 {
681 DeleteObject(DesktopRgn);
682 }
683 }
684 NtUserSetGUIThreadHandle(MSQ_STATE_MOVESIZE, NULL);
685 SendMessageA( hwnd, WM_EXITSIZEMOVE, 0, 0 );
686 SendMessageA( hwnd, WM_SETVISIBLE, !IsIconic(hwnd), 0L);
687
688 /* window moved or resized */
689 if (moved)
690 {
691 /* if the moving/resizing isn't canceled call SetWindowPos
692 * with the new position or the new size of the window
693 */
694 if (!((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) )
695 {
696 /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
697 if(!DragFullWindows)
698 SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
699 sizingRect.right - sizingRect.left,
700 sizingRect.bottom - sizingRect.top,
701 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
702 }
703 else { /* restore previous size/position */
704 if(DragFullWindows)
705 SetWindowPos( hwnd, 0, origRect.left, origRect.top,
706 origRect.right - origRect.left,
707 origRect.bottom - origRect.top,
708 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
709 }
710 }
711
712 if( IsWindow(hwnd) )
713 if( Style & WS_MINIMIZE )
714 {
715 /* Single click brings up the system menu when iconized */
716
717 if( !moved )
718 {
719 if( Style & WS_SYSMENU )
720 SendMessageA( hwnd, WM_SYSCOMMAND,
721 SC_MOUSEMENU + HTSYSMENU, MAKELONG(pt.x,pt.y));
722 }
723 }
724 }
725
726
727 /***********************************************************************
728 * DefWndTrackScrollBar
729 *
730 * Track a mouse button press on the horizontal or vertical scroll-bar.
731 */
732 STATIC VOID
733 DefWndTrackScrollBar(HWND Wnd, WPARAM wParam, POINT Pt)
734 {
735 INT ScrollBar;
736
737 if (SC_HSCROLL == (wParam & 0xfff0))
738 {
739 if (HTHSCROLL != (wParam & 0x0f))
740 {
741 return;
742 }
743 ScrollBar = SB_HORZ;
744 }
745 else /* SC_VSCROLL */
746 {
747 if (HTVSCROLL != (wParam & 0x0f))
748 {
749 return;
750 }
751 ScrollBar = SB_VERT;
752 }
753 ScrollTrackScrollBar(Wnd, ScrollBar, Pt );
754 }
755
756
757 LRESULT
758 DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, POINT Pt)
759 {
760 WINDOWPLACEMENT wp;
761
762 switch (wParam & 0xfff0)
763 {
764 case SC_MOVE:
765 case SC_SIZE:
766 DefWndDoSizeMove(hWnd, wParam);
767 break;
768 case SC_MINIMIZE:
769 wp.length = sizeof(WINDOWPLACEMENT);
770 if(GetWindowPlacement(hWnd, &wp))
771 {
772 wp.showCmd = SW_MINIMIZE;
773 SetWindowPlacement(hWnd, &wp);
774 }
775 break;
776 case SC_MAXIMIZE:
777 wp.length = sizeof(WINDOWPLACEMENT);
778 if(GetWindowPlacement(hWnd, &wp))
779 {
780 wp.showCmd = SW_MAXIMIZE;
781 SetWindowPlacement(hWnd, &wp);
782 }
783 break;
784 case SC_RESTORE:
785 wp.length = sizeof(WINDOWPLACEMENT);
786 if(GetWindowPlacement(hWnd, &wp))
787 {
788 wp.showCmd = SW_RESTORE;
789 SetWindowPlacement(hWnd, &wp);
790 }
791 break;
792 case SC_CLOSE:
793 SendMessageA(hWnd, WM_CLOSE, 0, 0);
794 break;
795 case SC_MOUSEMENU:
796 MenuTrackMouseMenuBar(hWnd, wParam & 0x000f, Pt);
797 break;
798 case SC_KEYMENU:
799 MenuTrackKbdMenuBar(hWnd, wParam, Pt.x);
800 break;
801 case SC_VSCROLL:
802 case SC_HSCROLL:
803 DefWndTrackScrollBar(hWnd, wParam, Pt);
804 break;
805
806 default:
807 /* FIXME: Implement */
808 UNIMPLEMENTED;
809 break;
810 }
811
812 return(0);
813 }
814
815 LRESULT
816 DefWndHandleWindowPosChanging(HWND hWnd, WINDOWPOS* Pos)
817 {
818 POINT maxSize, minTrack;
819 LONG style = GetWindowLongA(hWnd, GWL_STYLE);
820
821 if (Pos->flags & SWP_NOSIZE) return 0;
822 if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
823 {
824 WinPosGetMinMaxInfo(hWnd, &maxSize, NULL, &minTrack, NULL);
825 Pos->cx = min(Pos->cx, maxSize.x);
826 Pos->cy = min(Pos->cy, maxSize.y);
827 if (!(style & WS_MINIMIZE))
828 {
829 if (Pos->cx < minTrack.x) Pos->cx = minTrack.x;
830 if (Pos->cy < minTrack.y) Pos->cy = minTrack.y;
831 }
832 }
833 else
834 {
835 Pos->cx = max(Pos->cx, 0);
836 Pos->cy = max(Pos->cy, 0);
837 }
838 return 0;
839 }
840
841 /* Undocumented flags. */
842 #define SWP_NOCLIENTMOVE 0x0800
843 #define SWP_NOCLIENTSIZE 0x1000
844
845 LRESULT
846 DefWndHandleWindowPosChanged(HWND hWnd, WINDOWPOS* Pos)
847 {
848 RECT Rect;
849
850 GetClientRect(hWnd, &Rect);
851 MapWindowPoints(hWnd, (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD ?
852 GetParent(hWnd) : NULL), (LPPOINT) &Rect, 2);
853
854 if (! (Pos->flags & SWP_NOCLIENTMOVE))
855 {
856 SendMessageW(hWnd, WM_MOVE, 0, MAKELONG(Rect.left, Rect.top));
857 }
858
859 if (! (Pos->flags & SWP_NOCLIENTSIZE))
860 {
861 WPARAM wp = SIZE_RESTORED;
862 if (IsZoomed(hWnd))
863 {
864 wp = SIZE_MAXIMIZED;
865 }
866 else if (IsIconic(hWnd))
867 {
868 wp = SIZE_MINIMIZED;
869 }
870 SendMessageW(hWnd, WM_SIZE, wp,
871 MAKELONG(Rect.right - Rect.left, Rect.bottom - Rect.top));
872 }
873
874 return 0;
875 }
876
877 /***********************************************************************
878 * DefWndControlColor
879 *
880 * Default colors for control painting.
881 */
882 HBRUSH
883 DefWndControlColor(HDC hDC, UINT ctlType)
884 {
885 if (CTLCOLOR_SCROLLBAR == ctlType)
886 {
887 HBRUSH hb = GetSysColorBrush(COLOR_SCROLLBAR);
888 COLORREF bk = GetSysColor(COLOR_3DHILIGHT);
889 SetTextColor(hDC, GetSysColor(COLOR_3DFACE));
890 SetBkColor(hDC, bk);
891
892 /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
893 * we better use 0x55aa bitmap brush to make scrollbar's background
894 * look different from the window background.
895 */
896 if (bk == GetSysColor(COLOR_WINDOW))
897 {
898 static const WORD wPattern55AA[] =
899 {
900 0x5555, 0xaaaa, 0x5555, 0xaaaa,
901 0x5555, 0xaaaa, 0x5555, 0xaaaa
902 };
903 static HBITMAP hPattern55AABitmap = NULL;
904 static HBRUSH hPattern55AABrush = NULL;
905 if (hPattern55AABrush == NULL)
906 {
907 hPattern55AABitmap = CreateBitmap(8, 8, 1, 1, wPattern55AA);
908 hPattern55AABrush = CreatePatternBrush(hPattern55AABitmap);
909 }
910 return hPattern55AABrush;
911 }
912 UnrealizeObject(hb);
913 return hb;
914 }
915
916 SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
917
918 if ((CTLCOLOR_EDIT == ctlType) || (CTLCOLOR_LISTBOX == ctlType))
919 {
920 SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
921 }
922 else
923 {
924 SetBkColor(hDC, GetSysColor(COLOR_3DFACE));
925 return GetSysColorBrush(COLOR_3DFACE);
926 }
927
928 return GetSysColorBrush(COLOR_WINDOW);
929 }
930
931 VOID FASTCALL
932 DefWndScreenshot(HWND hWnd)
933 {
934
935 }
936
937 LRESULT STDCALL
938 User32DefWindowProc(HWND hWnd,
939 UINT Msg,
940 WPARAM wParam,
941 LPARAM lParam,
942 BOOL bUnicode)
943 {
944 switch (Msg)
945 {
946 case WM_NCPAINT:
947 {
948 return DefWndNCPaint(hWnd, (HRGN)wParam);
949 }
950
951 case WM_NCCALCSIZE:
952 {
953 return DefWndNCCalcSize(hWnd, (BOOL)wParam, (RECT*)lParam);
954 }
955
956 case WM_NCACTIVATE:
957 {
958 return DefWndNCActivate(hWnd, wParam);
959 }
960
961 case WM_NCHITTEST:
962 {
963 POINT Point;
964 Point.x = GET_X_LPARAM(lParam);
965 Point.y = GET_Y_LPARAM(lParam);
966 return (DefWndNCHitTest(hWnd, Point));
967 }
968
969 case WM_NCLBUTTONDOWN:
970 {
971 return (DefWndNCLButtonDown(hWnd, wParam, lParam));
972 }
973
974 case WM_NCLBUTTONDBLCLK:
975 {
976 return (DefWndNCLButtonDblClk(hWnd, wParam, lParam));
977 }
978
979 case WM_WINDOWPOSCHANGING:
980 {
981 return (DefWndHandleWindowPosChanging(hWnd, (WINDOWPOS*)lParam));
982 }
983
984 case WM_WINDOWPOSCHANGED:
985 {
986 return (DefWndHandleWindowPosChanged(hWnd, (WINDOWPOS*)lParam));
987 }
988
989 case WM_RBUTTONUP:
990 {
991 POINT Pt;
992 if (hWnd == GetCapture())
993 {
994 ReleaseCapture();
995 }
996 Pt.x = GET_X_LPARAM(lParam);
997 Pt.y = GET_Y_LPARAM(lParam);
998 ClientToScreen(hWnd, &Pt);
999 lParam = MAKELPARAM(Pt.x, Pt.y);
1000 if (bUnicode)
1001 {
1002 SendMessageW(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
1003 }
1004 else
1005 {
1006 SendMessageA(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
1007 }
1008 break;
1009 }
1010
1011 case WM_CONTEXTMENU:
1012 {
1013 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1014 {
1015 if (bUnicode)
1016 {
1017 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1018 }
1019 else
1020 {
1021 SendMessageA(GetParent(hWnd), WM_CONTEXTMENU, wParam, lParam);
1022 }
1023 }
1024 else
1025 {
1026 POINT Pt;
1027 DWORD Style;
1028 LONG HitCode;
1029
1030 Style = GetWindowLongW(hWnd, GWL_STYLE);
1031
1032 Pt.x = GET_X_LPARAM(lParam);
1033 Pt.y = GET_Y_LPARAM(lParam);
1034 if (Style & WS_CHILD)
1035 {
1036 ScreenToClient(GetParent(hWnd), &Pt);
1037 }
1038
1039 HitCode = DefWndNCHitTest(hWnd, Pt);
1040
1041 if (HitCode == HTCAPTION || HitCode == HTSYSMENU)
1042 {
1043 HMENU SystemMenu;
1044 UINT Flags;
1045
1046 if((SystemMenu = GetSystemMenu(hWnd, FALSE)))
1047 {
1048 MenuInitSysMenuPopup(SystemMenu, GetWindowLongW(hWnd, GWL_STYLE),
1049 GetClassLongW(hWnd, GCL_STYLE), HitCode);
1050
1051 if(HitCode == HTCAPTION)
1052 Flags = TPM_LEFTBUTTON | TPM_RIGHTBUTTON;
1053 else
1054 Flags = TPM_LEFTBUTTON;
1055
1056 TrackPopupMenu(SystemMenu, Flags,
1057 Pt.x, Pt.y, 0, hWnd, NULL);
1058 }
1059 }
1060 }
1061 break;
1062 }
1063
1064 case WM_PRINT:
1065 {
1066 /* FIXME: Implement. */
1067 return (0);
1068 }
1069
1070 case WM_PAINTICON:
1071 case WM_PAINT:
1072 {
1073 PAINTSTRUCT Ps;
1074 HDC hDC = BeginPaint(hWnd, &Ps);
1075 if (hDC)
1076 {
1077 HICON hIcon;
1078 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE &&
1079 (hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON)) != NULL)
1080 {
1081 RECT ClientRect;
1082 INT x, y;
1083 GetClientRect(hWnd, &ClientRect);
1084 x = (ClientRect.right - ClientRect.left -
1085 GetSystemMetrics(SM_CXICON)) / 2;
1086 y = (ClientRect.bottom - ClientRect.top -
1087 GetSystemMetrics(SM_CYICON)) / 2;
1088 DrawIcon(hDC, x, y, hIcon);
1089 }
1090 EndPaint(hWnd, &Ps);
1091 }
1092 return (0);
1093 }
1094
1095 case WM_SYNCPAINT:
1096 {
1097 HRGN hRgn;
1098 hRgn = CreateRectRgn(0, 0, 0, 0);
1099 if (GetUpdateRgn(hWnd, hRgn, FALSE) != NULLREGION)
1100 {
1101 RedrawWindow(hWnd, NULL, hRgn,
1102 RDW_ERASENOW | RDW_ERASE | RDW_FRAME |
1103 RDW_ALLCHILDREN);
1104 }
1105 DeleteObject(hRgn);
1106 return (0);
1107 }
1108
1109 case WM_SETREDRAW:
1110 {
1111 DefWndSetRedraw(hWnd, wParam);
1112 return (0);
1113 }
1114
1115 case WM_CLOSE:
1116 {
1117 DestroyWindow(hWnd);
1118 return (0);
1119 }
1120
1121 case WM_MOUSEACTIVATE:
1122 {
1123 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1124 {
1125 LONG Ret;
1126 if (bUnicode)
1127 {
1128 Ret = SendMessageW(GetParent(hWnd), WM_MOUSEACTIVATE,
1129 wParam, lParam);
1130 }
1131 else
1132 {
1133 Ret = SendMessageA(GetParent(hWnd), WM_MOUSEACTIVATE,
1134 wParam, lParam);
1135 }
1136 if (Ret)
1137 {
1138 return (Ret);
1139 }
1140 }
1141 return ((LOWORD(lParam) >= HTCLIENT) ? MA_ACTIVATE : MA_NOACTIVATE);
1142 }
1143
1144 case WM_ACTIVATE:
1145 {
1146 /* Check if the window is minimized. */
1147 if (LOWORD(wParam) != WA_INACTIVE &&
1148 !(GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE))
1149 {
1150 SetFocus(hWnd);
1151 }
1152 break;
1153 }
1154
1155 case WM_MOUSEWHEEL:
1156 {
1157 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1158 {
1159 if (bUnicode)
1160 {
1161 return (SendMessageW(GetParent(hWnd), WM_MOUSEWHEEL,
1162 wParam, lParam));
1163 }
1164 else
1165 {
1166 return (SendMessageA(GetParent(hWnd), WM_MOUSEWHEEL,
1167 wParam, lParam));
1168 }
1169 }
1170 break;
1171 }
1172
1173 case WM_ERASEBKGND:
1174 case WM_ICONERASEBKGND:
1175 {
1176 RECT Rect;
1177 HBRUSH hBrush = (HBRUSH)GetClassLongW(hWnd, GCL_HBRBACKGROUND);
1178
1179 if (NULL == hBrush)
1180 {
1181 return 0;
1182 }
1183 if (GetClassLongW(hWnd, GCL_STYLE) & CS_PARENTDC)
1184 {
1185 /* can't use GetClipBox with a parent DC or we fill the whole parent */
1186 GetClientRect(hWnd, &Rect);
1187 DPtoLP((HDC)wParam, (LPPOINT)&Rect, 2);
1188 }
1189 else
1190 {
1191 GetClipBox((HDC)wParam, &Rect);
1192 }
1193 FillRect((HDC)wParam, &Rect, hBrush);
1194 return (1);
1195 }
1196
1197 case WM_CTLCOLORMSGBOX:
1198 case WM_CTLCOLOREDIT:
1199 case WM_CTLCOLORLISTBOX:
1200 case WM_CTLCOLORBTN:
1201 case WM_CTLCOLORDLG:
1202 case WM_CTLCOLORSTATIC:
1203 case WM_CTLCOLORSCROLLBAR:
1204 return (LRESULT) DefWndControlColor((HDC)wParam, Msg - WM_CTLCOLORMSGBOX);
1205
1206 case WM_SETCURSOR:
1207 {
1208 ULONG Style = GetWindowLongW(hWnd, GWL_STYLE);
1209
1210 if (Style & WS_CHILD)
1211 {
1212 if (LOWORD(lParam) < HTLEFT || LOWORD(lParam) > HTBOTTOMRIGHT)
1213 {
1214 BOOL bResult;
1215 if (bUnicode)
1216 {
1217 bResult = SendMessageW(GetParent(hWnd), WM_SETCURSOR,
1218 wParam, lParam);
1219 }
1220 else
1221 {
1222 bResult = SendMessageA(GetParent(hWnd), WM_SETCURSOR,
1223 wParam, lParam);
1224 }
1225 if (bResult)
1226 {
1227 return(TRUE);
1228 }
1229 }
1230 }
1231 return (DefWndHandleSetCursor(hWnd, wParam, lParam, Style));
1232 }
1233
1234 case WM_SYSCOMMAND:
1235 {
1236 POINT Pt;
1237 Pt.x = GET_X_LPARAM(lParam);
1238 Pt.y = GET_Y_LPARAM(lParam);
1239 return (DefWndHandleSysCommand(hWnd, wParam, Pt));
1240 }
1241
1242 /* FIXME: Handle key messages. */
1243 /*
1244 case WM_KEYDOWN:
1245 case WM_KEYUP:
1246 case WM_SYSKEYUP:
1247 case WM_SYSCHAR:
1248 */
1249
1250 /* FIXME: This is also incomplete. */
1251 case WM_SYSKEYDOWN:
1252 {
1253 if (HIWORD(lParam) & KEYDATA_ALT)
1254 {
1255 if (wParam == VK_F4) /* Try to close the window */
1256 {
1257 HWND top = GetAncestor(hWnd, GA_ROOT);
1258 if (!(GetClassLongW(top, GCL_STYLE) & CS_NOCLOSE))
1259 {
1260 if (bUnicode)
1261 PostMessageW(top, WM_SYSCOMMAND, SC_CLOSE, 0);
1262 else
1263 PostMessageA(top, WM_SYSCOMMAND, SC_CLOSE, 0);
1264 }
1265 }
1266 else if (wParam == VK_SNAPSHOT)
1267 {
1268 DefWndScreenshot(hWnd);
1269 }
1270 }
1271 break;
1272 }
1273
1274 case WM_SHOWWINDOW:
1275 {
1276 LONG Style;
1277
1278 if (!lParam)
1279 return 0;
1280 Style = GetWindowLongW(hWnd, GWL_STYLE);
1281 if (!(Style & WS_POPUP))
1282 return 0;
1283 if ((Style & WS_VISIBLE) && wParam)
1284 return 0;
1285 if (!(Style & WS_VISIBLE) && !wParam)
1286 return 0;
1287 if (!GetWindow(hWnd, GW_OWNER))
1288 return 0;
1289 ShowWindow(hWnd, wParam ? SW_SHOWNA : SW_HIDE);
1290 break;
1291 }
1292
1293 case WM_CANCELMODE:
1294 {
1295 /* FIXME: Check for a desktop. */
1296 if (GetCapture() == hWnd)
1297 {
1298 ReleaseCapture();
1299 }
1300 break;
1301 }
1302
1303 case WM_VKEYTOITEM:
1304 case WM_CHARTOITEM:
1305 return (-1);
1306 /*
1307 case WM_DROPOBJECT:
1308
1309 break;
1310 */
1311 case WM_QUERYDROPOBJECT:
1312 {
1313 if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES)
1314 {
1315 return(1);
1316 }
1317 break;
1318 }
1319
1320 case WM_QUERYDRAGICON:
1321 {
1322 UINT Len;
1323 HICON hIcon;
1324
1325 hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON);
1326 if (hIcon)
1327 {
1328 return ((LRESULT)hIcon);
1329 }
1330 for (Len = 1; Len < 64; Len++)
1331 {
1332 if ((hIcon = LoadIconW(NULL, MAKEINTRESOURCEW(Len))) != NULL)
1333 {
1334 return((LRESULT)hIcon);
1335 }
1336 }
1337 return ((LRESULT)LoadIconW(0, IDI_APPLICATION));
1338 }
1339
1340 /* FIXME: WM_ISACTIVEICON */
1341
1342 case WM_NOTIFYFORMAT:
1343 {
1344 if (IsWindowUnicode(hWnd))
1345 {
1346 return(NFR_UNICODE);
1347 }
1348 else
1349 {
1350 return(NFR_ANSI);
1351 }
1352 }
1353
1354 case WM_SETICON:
1355 {
1356 INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
1357 HICON hOldIcon = (HICON)GetClassLongW(hWnd, Index);
1358 SetClassLongW(hWnd, Index, lParam);
1359 SetWindowPos(hWnd, 0, 0, 0, 0, 0,
1360 SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
1361 SWP_NOACTIVATE | SWP_NOZORDER);
1362 return ((LRESULT)hOldIcon);
1363 }
1364
1365 case WM_GETICON:
1366 {
1367 INT Index = (wParam == ICON_BIG) ? GCL_HICON : GCL_HICONSM;
1368 return (GetClassLongW(hWnd, Index));
1369 }
1370
1371 case WM_HELP:
1372 {
1373 if (bUnicode)
1374 {
1375 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1376 }
1377 else
1378 {
1379 SendMessageA(GetParent(hWnd), Msg, wParam, lParam);
1380 }
1381 break;
1382 }
1383
1384 case WM_SYSTIMER:
1385 {
1386 THRDCARETINFO CaretInfo;
1387 switch(wParam)
1388 {
1389 case 0xffff: /* Caret timer */
1390 /* switch showing byte in win32k and get information about the caret */
1391 if(NtUserSwitchCaretShowing(&CaretInfo) && (CaretInfo.hWnd == hWnd))
1392 {
1393 DrawCaret(hWnd, &CaretInfo);
1394 }
1395 break;
1396 }
1397 break;
1398 }
1399
1400 case WM_QUERYOPEN:
1401 case WM_QUERYENDSESSION:
1402 {
1403 return (1);
1404 }
1405 }
1406 return 0;
1407 }
1408
1409
1410 LRESULT STDCALL
1411 DefWindowProcA(HWND hWnd,
1412 UINT Msg,
1413 WPARAM wParam,
1414 LPARAM lParam)
1415 {
1416 switch (Msg)
1417 {
1418 case WM_NCCREATE:
1419 {
1420 return TRUE;
1421 }
1422
1423 case WM_GETTEXTLENGTH:
1424 {
1425 return (LRESULT)NtUserInternalGetWindowText(hWnd, NULL, 0);
1426 }
1427
1428 case WM_GETTEXT:
1429 {
1430 LPWSTR Buffer;
1431 LPSTR AnsiBuffer = (LPSTR)lParam;
1432 INT Length;
1433
1434 if (wParam > 1)
1435 {
1436 *((PWSTR)lParam) = '\0';
1437 }
1438 Buffer = HeapAlloc(GetProcessHeap(), 0, wParam * sizeof(WCHAR));
1439 if (!Buffer)
1440 return FALSE;
1441 Length = NtUserInternalGetWindowText(hWnd, Buffer, wParam);
1442 if (Length > 0 && wParam > 0 &&
1443 !WideCharToMultiByte(CP_ACP, 0, Buffer, -1,
1444 AnsiBuffer, wParam, NULL, NULL))
1445 {
1446 AnsiBuffer[0] = '\0';
1447 }
1448
1449 HeapFree(GetProcessHeap(), 0, Buffer);
1450
1451 return (LRESULT)Length;
1452 }
1453
1454 case WM_SETTEXT:
1455 {
1456 ANSI_STRING AnsiString;
1457 UNICODE_STRING UnicodeString;
1458
1459 if(lParam)
1460 {
1461 RtlInitAnsiString(&AnsiString, (LPSTR)lParam);
1462 RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
1463 NtUserDefSetText(hWnd, &UnicodeString);
1464 RtlFreeUnicodeString(&UnicodeString);
1465 }
1466 else
1467 NtUserDefSetText(hWnd, NULL);
1468
1469 if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
1470 {
1471 DefWndNCPaint(hWnd, (HRGN)1);
1472 }
1473 return TRUE;
1474 }
1475
1476 /*
1477 FIXME: Implement these.
1478 case WM_IME_CHAR:
1479 case WM_IME_KEYDOWN:
1480 case WM_IME_KEYUP:
1481 case WM_IME_STARTCOMPOSITION:
1482 case WM_IME_COMPOSITION:
1483 case WM_IME_ENDCOMPOSITION:
1484 case WM_IME_SELECT:
1485 case WM_IME_SETCONTEXT:
1486 */
1487 }
1488
1489 return User32DefWindowProc(hWnd, Msg, wParam, lParam, FALSE);
1490 }
1491
1492
1493 LRESULT STDCALL
1494 DefWindowProcW(HWND hWnd,
1495 UINT Msg,
1496 WPARAM wParam,
1497 LPARAM lParam)
1498 {
1499 switch (Msg)
1500 {
1501 case WM_NCCREATE:
1502 {
1503 return TRUE;
1504 }
1505
1506 case WM_GETTEXTLENGTH:
1507 {
1508 return (LRESULT)NtUserInternalGetWindowText(hWnd, NULL, 0);
1509 }
1510
1511 case WM_GETTEXT:
1512 {
1513 if (wParam > 1)
1514 {
1515 *((PWSTR)lParam) = L'\0';
1516 }
1517 return (LRESULT)NtUserInternalGetWindowText(hWnd, (PWSTR)lParam, wParam);
1518 }
1519
1520 case WM_SETTEXT:
1521 {
1522 UNICODE_STRING UnicodeString;
1523
1524 if(lParam)
1525 RtlInitUnicodeString(&UnicodeString, (LPWSTR)lParam);
1526
1527 NtUserDefSetText(hWnd, (lParam ? &UnicodeString : NULL));
1528
1529 if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
1530 {
1531 DefWndNCPaint(hWnd, (HRGN)1);
1532 }
1533 return (1);
1534 }
1535
1536 case WM_IME_CHAR:
1537 {
1538 SendMessageW(hWnd, WM_CHAR, wParam, lParam);
1539 return (0);
1540 }
1541
1542 case WM_IME_SETCONTEXT:
1543 {
1544 /* FIXME */
1545 return (0);
1546 }
1547 }
1548
1549 return User32DefWindowProc(hWnd, Msg, wParam, lParam, TRUE);
1550 }
1551