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