Switch back to the command prompt when you press the "X" Close button
[reactos.git] / reactos / lib / user32 / windows / defwnd.c
1 /* $Id: defwnd.c,v 1.28 2003/03/06 23:57:00 gvg 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 <debug.h>
18 #include <user32/wininternal.h>
19 #include <string.h>
20
21 /* GLOBALS *******************************************************************/
22
23 static HBITMAP hbitmapClose;
24 static HBITMAP hbitmapMinimize;
25 static HBITMAP hbitmapMinimizeD;
26 static HBITMAP hbitmapMaximize;
27 static HBITMAP hbitmapMaximizeD;
28 static HBITMAP hbitmapRestore;
29 static HBITMAP hbitmapRestoreD;
30
31 static COLORREF SysColours[] =
32 {
33 RGB(224, 224, 224) /* COLOR_SCROLLBAR */,
34 RGB(58, 110, 165) /* COLOR_BACKGROUND */,
35 RGB(0, 0, 128) /* COLOR_ACTIVECAPTION */,
36 RGB(128, 128, 128) /* COLOR_INACTIVECAPTION */,
37 RGB(192, 192, 192) /* COLOR_MENU */,
38 RGB(192, 192, 192) /* COLOR_WINDOW */,
39 RGB(192, 192, 192) /* COLOR_WINDOWFRAME */,
40 RGB(0, 0, 0) /* COLOR_MENUTEXT */,
41 RGB(0, 0, 0) /* COLOR_WINDOWTEXT */,
42 RGB(255, 255, 255) /* COLOR_CAPTIONTEXT */,
43 RGB(128, 128, 128) /* COLOR_ACTIVEBORDER */,
44 RGB(255, 255, 255) /* COLOR_INACTIVEBORDER */,
45 RGB(255, 255, 232) /* COLOR_APPWORKSPACE */,
46 RGB(224, 224, 224) /* COLOR_HILIGHT */,
47 RGB(0, 0, 128) /* COLOR_HILIGHTTEXT */,
48 RGB(192, 192, 192) /* COLOR_BTNFACE */,
49 RGB(128, 128, 128) /* COLOR_BTNSHADOW */,
50 RGB(192, 192, 192) /* COLOR_GRAYTEXT */,
51 RGB(0, 0, 0) /* COLOR_BTNTEXT */,
52 RGB(192, 192, 192) /* COLOR_INACTIVECAPTIONTEXT */,
53 RGB(255, 255, 255) /* COLOR_BTNHILIGHT */,
54 RGB(32, 32, 32) /* COLOR_3DDKSHADOW */,
55 RGB(192, 192, 192) /* COLOR_3DLIGHT */,
56 RGB(0, 0, 0) /* COLOR_INFOTEXT */,
57 RGB(255, 255, 192) /* COLOR_INFOBK */,
58 RGB(184, 180, 184) /* COLOR_ALTERNATEBTNFACE */,
59 RGB(0, 0, 255) /* COLOR_HOTLIGHT */,
60 RGB(16, 132, 208) /* COLOR_GRADIENTACTIVECAPTION */,
61 RGB(181, 181, 181) /* COLOR_GRADIENTINACTIVECAPTION */,
62 };
63
64 static ATOM AtomInternalPos;
65
66 /* FUNCTIONS *****************************************************************/
67
68 VOID
69 UserSetupInternalPos(VOID)
70 {
71 LPSTR Str = "SysIP";
72 AtomInternalPos = GlobalAddAtomA(Str);
73 }
74
75 /* ReactOS extension */
76 HPEN STDCALL
77 GetSysColorPen(int nIndex)
78 {
79 return(CreatePen(PS_SOLID, 1, SysColours[nIndex]));
80 }
81
82 HBRUSH STDCALL
83 GetSysColorBrush(int nIndex)
84 {
85 return(CreateSolidBrush(SysColours[nIndex]));
86 }
87
88
89 LRESULT STDCALL
90 DefFrameProcA(HWND hWnd,
91 HWND hWndMDIClient,
92 UINT uMsg,
93 WPARAM wParam,
94 LPARAM lParam)
95 {
96 return((LRESULT)0);
97 }
98
99 LRESULT STDCALL
100 DefFrameProcW(HWND hWnd,
101 HWND hWndMDIClient,
102 UINT uMsg,
103 WPARAM wParam,
104 LPARAM lParam)
105 {
106 return((LRESULT)0);
107 }
108
109
110 BOOL
111 DefWndRedrawIconTitle(HWND hWnd)
112 {
113 PINTERNALPOS lpPos = (PINTERNALPOS)GetPropA(hWnd,
114 (LPSTR)(DWORD)AtomInternalPos);
115 if (lpPos != NULL)
116 {
117 if (lpPos->IconTitle != NULL)
118 {
119 SendMessageA(lpPos->IconTitle, WM_SHOWWINDOW, TRUE, 0);
120 InvalidateRect(lpPos->IconTitle, NULL, TRUE);
121 return(TRUE);
122 }
123 }
124 return(FALSE);
125 }
126
127 BOOL
128 UserHasMenu(HWND hWnd, ULONG Style)
129 {
130 return(!(Style & WS_CHILD) && GetWindowLong(hWnd, GWL_ID) != 0);
131 }
132
133 ULONG
134 UserHasAnyFrameStyle(ULONG Style, ULONG ExStyle)
135 {
136 return((Style & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) ||
137 (ExStyle & WS_EX_DLGMODALFRAME) ||
138 (!(Style & (WS_CHILD | WS_POPUP))));
139 }
140
141 ULONG
142 UserHasDlgFrameStyle(ULONG Style, ULONG ExStyle)
143 {
144 return((ExStyle & WS_EX_DLGMODALFRAME) ||
145 ((Style & WS_DLGFRAME) && (!(Style & WS_THICKFRAME))));
146 }
147
148 ULONG
149 UserHasThickFrameStyle(ULONG Style, ULONG ExStyle)
150 {
151 return((Style & WS_THICKFRAME) &&
152 (!((Style & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)));
153 }
154
155 ULONG
156 UserHasThinFrameStyle(ULONG Style, ULONG ExStyle)
157 {
158 return((Style & WS_BORDER) ||
159 (!(Style & (WS_CHILD | WS_POPUP))));
160 }
161
162 ULONG
163 UserHasBigFrameStyle(ULONG Style, ULONG ExStyle)
164 {
165 return((Style & (WS_THICKFRAME | WS_DLGFRAME)) ||
166 (ExStyle & WS_EX_DLGMODALFRAME));
167 }
168
169 void UserGetInsideRectNC( HWND hWnd, RECT *rect )
170 {
171 RECT WindowRect;
172 ULONG Style;
173 ULONG ExStyle;
174
175 Style = GetWindowLong(hWnd, GWL_STYLE);
176 ExStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
177 GetWindowRect(hWnd, &WindowRect);
178 rect->top = rect->left = 0;
179 rect->right = WindowRect.right - WindowRect.left;
180 rect->bottom = WindowRect.bottom - WindowRect.top;
181
182 if (Style & WS_ICONIC)
183 {
184 return;
185 }
186
187 /* Remove frame from rectangle */
188 if (UserHasThickFrameStyle(Style, ExStyle ))
189 {
190 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME),
191 -GetSystemMetrics(SM_CYFRAME) );
192 }
193 else
194 {
195 if (UserHasDlgFrameStyle(Style, ExStyle ))
196 {
197 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME),
198 -GetSystemMetrics(SM_CYDLGFRAME));
199 /* FIXME: this isn't in NC_AdjustRect? why not? */
200 if (ExStyle & WS_EX_DLGMODALFRAME)
201 InflateRect( rect, -1, 0 );
202 }
203 else
204 {
205 if (UserHasThinFrameStyle(Style, ExStyle))
206 {
207 InflateRect(rect, -GetSystemMetrics(SM_CXBORDER),
208 -GetSystemMetrics(SM_CYBORDER));
209 }
210 }
211 }
212 }
213
214 void UserDrawSysMenuButton( HWND hWnd, HDC hDC, BOOL down )
215 {
216 /* FIXME: Implement AppIcon loading/displaying, if AppIcon isn't present,
217 load default (OIC_SAMPLE I believe, not sure */
218 }
219
220 static void UserDrawCloseButton ( HWND hWnd, HDC hDC, BOOL down )
221 {
222 /* ported from wine code */
223 RECT rect;
224 BOOL bInactive = FALSE;
225
226 UserGetInsideRectNC( hWnd, &rect );
227
228 if (GetWindowLongA( hWnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
229 {
230 INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE */
231 INT iBmpWidth = 11; /* it uses 11x11 for the close button in tool window */
232 INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
233
234 rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
235 rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
236 rect.bottom = rect.top + iBmpHeight;
237 rect.right = rect.left + iBmpWidth;
238 }
239 else
240 {
241 rect.top++;
242 rect.right--;
243 /* Standard close/min/max button sizes appear to be 16x14, though
244 these change with the caption size, I'll fix this soon */
245 rect.left = rect.right - 16;
246 rect.bottom = rect.top + 14;
247
248 }
249 DrawFrameControl( hDC, &rect, DFC_CAPTION,
250 (DFCS_CAPTIONCLOSE |
251 (down ? DFCS_PUSHED : 0) |
252 (bInactive ? DFCS_INACTIVE : 0)) );
253 }
254
255 static void UserDrawMaxButton( HWND hWnd, HDC hDC, BOOL down )
256 {
257
258 RECT rect;
259 UINT flags = IsZoomed(hWnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
260
261 UserGetInsideRectNC( hWnd, &rect );
262 rect.top++;
263 rect.right--;
264 rect.left = rect.right - (GetSystemMetrics(SM_CXSIZE) - 1) * 2;
265 rect.right = rect.left + (GetSystemMetrics(SM_CXSIZE) - 2);
266 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 4;
267
268 if (down) flags |= DFCS_PUSHED;
269 DrawFrameControl( hDC, &rect, DFC_CAPTION, flags );
270
271 }
272
273 static void UserDrawMinButton( HWND hWnd, HDC hDC, BOOL down)
274 {
275
276 RECT rect;
277 UINT flags = DFCS_CAPTIONMIN;
278
279 BOOL bInactive = FALSE;
280 UserGetInsideRectNC( hWnd, &rect );
281 rect.top++;
282 rect.right--;
283 rect.left = rect.right - ((GetSystemMetrics(SM_CXSIZE)) * 3) + 4;
284 rect.right = rect.left + (GetSystemMetrics(SM_CXSIZE) - 2);
285 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 4;
286
287 if (down) flags |= DFCS_PUSHED;
288 if (bInactive) flags |= DFCS_INACTIVE;
289 DrawFrameControl( hDC, &rect, DFC_CAPTION, flags );
290
291 }
292
293 static void UserDrawCaptionNC( HDC hDC, RECT *rect, HWND hWnd,
294 DWORD style, BOOL active )
295 {
296 RECT r = *rect;
297 char buffer[256];
298
299 if (!hbitmapClose)
300 {
301 hbitmapClose = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_CLOSE));
302 hbitmapMinimize = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_REDUCE) );
303 hbitmapMinimizeD = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_REDUCED) );
304 hbitmapMaximize = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_ZOOM) );
305 hbitmapMaximizeD = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_ZOOMD) );
306 hbitmapRestore = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_RESTORE) );
307 hbitmapRestoreD = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_RESTORED) );
308 }
309
310 if (GetWindowLong(hWnd, GWL_EXSTYLE) & WS_EX_DLGMODALFRAME)
311 {
312 /* Unimplemented */
313 }
314
315 /* Fill the caption with COLOR_(IN)ACTIVECAPTION.
316 In the future this will be GradientFill() */
317
318 SelectObject( hDC, GetSysColorBrush(active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION) );
319 PatBlt(hDC,rect->left + 3, rect->top + 3, rect->right - 6, rect->bottom - 1, PATCOPY );
320
321 if (style & WS_SYSMENU)
322 {
323 UserDrawSysMenuButton( hWnd, hDC, FALSE );
324 r.left += GetSystemMetrics(SM_CXSIZE) + 1;
325 UserDrawCloseButton( hWnd, hDC, FALSE );
326 }
327 if (style & WS_MAXIMIZEBOX)
328 {
329 UserDrawMaxButton( hWnd, hDC, FALSE );
330 r.right -= GetSystemMetrics(SM_CXSMSIZE) + 1;
331 }
332 if (style & WS_MINIMIZEBOX)
333 {
334 UserDrawMinButton( hWnd, hDC, FALSE );
335 r.right -= GetSystemMetrics(SM_CXSMSIZE) + 1;
336 }
337
338
339 if (GetWindowTextA( hWnd, buffer, sizeof(buffer) ))
340 {
341 NONCLIENTMETRICS nclm;
342 HFONT hFont, hOldFont;
343
344 nclm.cbSize = sizeof(NONCLIENTMETRICS);
345 SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
346 if (style & WS_EX_TOOLWINDOW)
347 hFont = CreateFontIndirectW(&nclm.lfSmCaptionFont);
348 else
349 hFont = CreateFontIndirectW(&nclm.lfCaptionFont);
350 hOldFont = SelectObject(hDC, hFont);
351
352 SetTextColor(hDC, GetSysColor( (active ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT ) ) );
353 SetBkMode( hDC, TRANSPARENT );
354
355 /*FIXME: Need verticle centering code and other fixups */
356 TextOutA(hDC, r.left+5, r.top+5, buffer, strlen(buffer));
357 DeleteObject (SelectObject (hDC, hOldFont));
358 }
359 }
360
361 VOID
362 UserDrawFrameNC(HDC hDC, RECT* rect, BOOL dlgFrame, BOOL active)
363 {
364 SelectObject( hDC, GetSysColorBrush(COLOR_WINDOW) );
365 DrawEdge(hDC, rect,EDGE_RAISED, BF_RECT | BF_MIDDLE);
366 }
367
368 void SCROLL_DrawScrollBar (HWND hWnd, HDC hDC, INT nBar, BOOL arrows, BOOL interior);
369
370 VOID
371 DefWndDoPaintNC(HWND hWnd, HRGN clip)
372 {
373 ULONG Active;
374 HDC hDC;
375 RECT rect;
376 ULONG Style;
377 ULONG ExStyle;
378
379 Active = GetWindowLongW(hWnd, GWL_STYLE) & WIN_NCACTIVATED;
380 Style = GetWindowLong(hWnd, GWL_STYLE);
381 ExStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
382
383 hDC = GetDCEx(hWnd, (clip > (HRGN)1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
384 ((clip > (HRGN)1) ? (DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0));
385 if (hDC == 0)
386 {
387 return;
388 }
389
390 /* FIXME: Test whether we need to draw anything at all. */
391
392 GetWindowRect(hWnd, &rect);
393 rect.right = rect.right - rect.left;
394 rect.bottom = rect.bottom - rect.top;
395 rect.top = rect.left = 0;
396
397 SelectObject(hDC, GetSysColorPen(COLOR_WINDOWFRAME));
398 if (UserHasAnyFrameStyle(Style, ExStyle))
399 {
400 SelectObject(hDC, GetStockObject(NULL_BRUSH));
401 InflateRect(&rect, -1, -1);
402 }
403
404 if (UserHasThickFrameStyle(Style, ExStyle))
405 {
406 UserDrawFrameNC(hDC, &rect, FALSE, Active);
407 }
408 else if (UserHasDlgFrameStyle(Style, ExStyle))
409 {
410 UserDrawFrameNC(hDC, &rect, TRUE, Active);
411 }
412
413 if (Style & WS_CAPTION)
414 {
415 RECT r = rect;
416 r.bottom = rect.top + GetSystemMetrics(SM_CYSIZE);
417 rect.top += GetSystemMetrics(SM_CYSIZE) +
418 GetSystemMetrics(SM_CYBORDER);
419 UserDrawCaptionNC(hDC, &r, hWnd, Style, Active);
420 }
421
422 /* FIXME: Draw menu bar. */
423
424 DbgPrint("drawing scrollbars..\n");
425 /* Draw scrollbars */
426 if (Style & WS_VSCROLL)
427 SCROLL_DrawScrollBar(hWnd, hDC, SB_VERT, TRUE, TRUE);
428 if (Style & WS_HSCROLL)
429 SCROLL_DrawScrollBar(hWnd, hDC, SB_HORZ, TRUE, TRUE);
430
431 /* FIXME: Draw size box. */
432
433 ReleaseDC(hWnd, hDC);
434 }
435
436 LRESULT
437 DefWndPaintNC(HWND hWnd, HRGN clip)
438 {
439 if (IsWindowVisible(hWnd))
440 {
441 if (IsIconic(hWnd))
442 {
443 DefWndRedrawIconTitle(hWnd);
444 }
445 else
446 {
447 DefWndDoPaintNC(hWnd, clip);
448 }
449 }
450 return(0);
451 }
452
453 LRESULT
454 DefWndHitTestNC(HWND hWnd, POINT Point)
455 {
456 RECT WindowRect;
457 ULONG Style = GetWindowLong(hWnd, GWL_STYLE);
458 ULONG ExStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
459
460 GetWindowRect(hWnd, &WindowRect);
461
462 if (!PtInRect(&WindowRect, Point))
463 {
464 return(HTNOWHERE);
465 }
466 if (Style & WS_MINIMIZE)
467 {
468 return(HTCAPTION);
469 }
470 if (UserHasThickFrameStyle(Style, ExStyle))
471 {
472 InflateRect(&WindowRect, -GetSystemMetrics(SM_CXFRAME),
473 -GetSystemMetrics(SM_CYFRAME));
474 if (!PtInRect(&WindowRect, Point))
475 {
476 if (Point.y < WindowRect.top)
477 {
478 if (Point.x < (WindowRect.left + GetSystemMetrics(SM_CXSIZE)))
479 {
480 return(HTTOPLEFT);
481 }
482 if (Point.x >= (WindowRect.right - GetSystemMetrics(SM_CXSIZE)))
483 {
484 return(HTTOPRIGHT);
485 }
486 return(HTTOP);
487 }
488 if (Point.y >= WindowRect.bottom)
489 {
490 if (Point.x < (WindowRect.left + GetSystemMetrics(SM_CXSIZE)))
491 {
492 return(HTBOTTOMLEFT);
493 }
494 if (Point.x >= (WindowRect.right - GetSystemMetrics(SM_CXSIZE)))
495 {
496 return(HTBOTTOMRIGHT);
497 }
498 return(HTBOTTOM);
499 }
500 if (Point.x < WindowRect.left)
501 {
502 if (Point.y < (WindowRect.top + GetSystemMetrics(SM_CYSIZE)))
503 {
504 return(HTTOPLEFT);
505 }
506 if (Point.y >= (WindowRect.bottom - GetSystemMetrics(SM_CYSIZE)))
507 {
508 return(HTBOTTOMLEFT);
509 }
510 return(HTLEFT);
511 }
512 if (Point.x >= WindowRect.right)
513 {
514 if (Point.y < (WindowRect.top + GetSystemMetrics(SM_CYSIZE)))
515 {
516 return(HTTOPRIGHT);
517 }
518 if (Point.y >= (WindowRect.bottom - GetSystemMetrics(SM_CYSIZE)))
519 {
520 return(HTBOTTOMRIGHT);
521 }
522 return(HTRIGHT);
523 }
524 }
525 }
526 else
527 {
528 if (UserHasDlgFrameStyle(Style, ExStyle))
529 {
530 InflateRect(&WindowRect, -GetSystemMetrics(SM_CXDLGFRAME),
531 -GetSystemMetrics(SM_CYDLGFRAME));
532 }
533 else if (UserHasThinFrameStyle(Style, ExStyle))
534 {
535 InflateRect(&WindowRect, -GetSystemMetrics(SM_CXBORDER),
536 -GetSystemMetrics(SM_CYBORDER));
537 }
538 if (!PtInRect(&WindowRect, Point))
539 {
540 return(HTBORDER);
541 }
542 }
543
544 if ((Style & WS_CAPTION) == WS_CAPTION)
545 {
546 WindowRect.top += GetSystemMetrics(SM_CYCAPTION) -
547 GetSystemMetrics(SM_CYBORDER);
548 if (!PtInRect(&WindowRect, Point))
549 {
550 if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW))
551 {
552 WindowRect.left += GetSystemMetrics(SM_CXSIZE);
553 WindowRect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
554 }
555 if (Point.x <= WindowRect.left)
556 {
557 return(HTSYSMENU);
558 }
559 if (WindowRect.right <= Point.x)
560 {
561 return(HTCLOSE);
562 }
563
564 if (Style & WS_MAXIMIZEBOX)
565 {
566 WindowRect.right -= GetSystemMetrics(SM_CXSMSIZE) + 1;
567 }
568 if (Point.x >= WindowRect.right)
569 {
570 return(HTMAXBUTTON);
571 }
572
573 if (Style & WS_MINIMIZEBOX)
574 {
575 WindowRect.right -= GetSystemMetrics(SM_CXSMSIZE) + 1;
576 }
577 if (Point.x >= WindowRect.right)
578 {
579 return(HTMINBUTTON);
580 }
581 return(HTCAPTION);
582 }
583 }
584
585 ScreenToClient(hWnd, &Point);
586 GetClientRect(hWnd, &WindowRect);
587
588 if (PtInRect(&WindowRect, Point))
589 {
590 return(HTCLIENT);
591 }
592
593 if (Style & WS_VSCROLL)
594 {
595 WindowRect.right += GetSystemMetrics(SM_CXVSCROLL);
596 if (PtInRect(&WindowRect, Point))
597 {
598 return(HTVSCROLL);
599 }
600 }
601
602 if (Style & WS_HSCROLL)
603 {
604 WindowRect.bottom += GetSystemMetrics(SM_CYHSCROLL);
605 if (PtInRect(&WindowRect, Point))
606 {
607 if ((Style & WS_VSCROLL) &&
608 (Point.x >= (WindowRect.right - GetSystemMetrics(SM_CXVSCROLL))))
609 {
610 return(HTSIZE);
611 }
612 return(HTHSCROLL);
613 }
614 }
615
616 if (UserHasMenu(hWnd, Style))
617 {
618 if (Point.y < 0 && Point.x >= 0 && Point.x <= WindowRect.right)
619 {
620 return(HTMENU);
621 }
622 }
623
624 return(HTNOWHERE);
625 }
626
627 VOID
628 DefWndTrackMinMaxBox(HWND hWnd, WPARAM wParam)
629 {
630 HDC hDC = GetWindowDC(hWnd);
631 BOOL Pressed = TRUE;
632 MSG Msg;
633
634 SetCapture(hWnd);
635
636 if (wParam == HTMINBUTTON)
637 {
638 UserDrawMinButton(hWnd, hDC, TRUE);
639 }
640 else
641 {
642 UserDrawMaxButton(hWnd, hDC, TRUE);
643 }
644
645 for(;;)
646 {
647 BOOL OldState = Pressed;
648
649 GetMessageA(hWnd, &Msg, 0, 0);
650 if (Msg.message == WM_LBUTTONUP)
651 {
652 break;
653 }
654 if (Msg.message != WM_MOUSEMOVE)
655 {
656 continue;
657 }
658
659 Pressed = DefWndHitTestNC(hWnd, Msg.pt) == (LRESULT) wParam;
660 if (Pressed != OldState)
661 {
662 if (wParam == HTMINBUTTON)
663 {
664 UserDrawMinButton(hWnd, hDC, Pressed);
665 }
666 else
667 {
668 UserDrawMaxButton(hWnd, hDC, Pressed);
669 }
670 }
671 }
672
673 if (Pressed)
674 {
675 if (wParam == HTMINBUTTON)
676 {
677 UserDrawMinButton(hWnd, hDC, FALSE);
678 }
679 else
680 {
681 UserDrawMaxButton(hWnd, hDC, FALSE);
682 }
683 }
684
685 ReleaseCapture();
686 ReleaseDC(hWnd, hDC);
687
688 if (!Pressed)
689 {
690 return;
691 }
692
693 if (wParam == HTMINBUTTON)
694 {
695 SendMessageA(hWnd, WM_SYSCOMMAND, SC_MINIMIZE,
696 MAKELONG(Msg.pt.x, Msg.pt.y));
697 }
698 else
699 {
700 SendMessageA(hWnd, WM_SYSCOMMAND,
701 IsZoomed(hWnd) ? SC_RESTORE : SC_MAXIMIZE,
702 MAKELONG(Msg.pt.x, Msg.pt.y));
703 }
704 }
705
706 VOID
707 DefWndDrawSysButton(HWND hWnd, HDC hDC, BOOL Down)
708 {
709 RECT Rect;
710 HDC hDCMem;
711 HBITMAP hSavedBitmap;
712
713 UserGetInsideRectNC(hWnd, &Rect);
714 hDCMem = CreateCompatibleDC(hDC);
715 hSavedBitmap = SelectObject(hDCMem, hbitmapClose);
716 BitBlt(hDC, Rect.left, Rect.top, GetSystemMetrics(SM_CXSIZE),
717 GetSystemMetrics(SM_CYSIZE), hDCMem,
718 (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD) ?
719 GetSystemMetrics(SM_CXSIZE): 0, 0, Down ? NOTSRCCOPY : SRCCOPY);
720 SelectObject(hDCMem, hSavedBitmap);
721 DeleteDC(hDCMem);
722 }
723
724 LRESULT
725 DefWndHandleLButtonDownNC(HWND hWnd, WPARAM wParam, LPARAM lParam)
726 {
727 switch (wParam)
728 {
729 case HTCAPTION:
730 {
731 HWND hTopWnd = GetDesktopWindow(); //GetAncestor(hWnd, GA_ROOT); temp fix.
732 if (SetActiveWindow(hTopWnd) || GetActiveWindow() == hTopWnd)
733 {
734 SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam);
735 }
736 break;
737 }
738 case HTSYSMENU:
739 {
740 if (GetWindowLong(hWnd, GWL_STYLE) & WS_SYSMENU)
741 {
742 if (!(GetWindowLong(hWnd, GWL_STYLE) & WS_MINIMIZE))
743 {
744 HDC hDC = GetWindowDC(hWnd);
745 DefWndDrawSysButton(hWnd, hDC, TRUE);
746 ReleaseDC(hWnd, hDC);
747 }
748 SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU,
749 lParam);
750 }
751 break;
752 }
753
754 case HTMENU:
755 SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam);
756 break;
757
758 case HTHSCROLL:
759 SendMessageA(hWnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam);
760 break;
761
762 case HTVSCROLL:
763 SendMessageA(hWnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam);
764 break;
765
766 case HTMINBUTTON:
767 case HTMAXBUTTON:
768 DefWndTrackMinMaxBox(hWnd, wParam);
769 break;
770
771 case HTLEFT:
772 case HTRIGHT:
773 case HTTOP:
774 case HTBOTTOM:
775 case HTTOPLEFT:
776 case HTTOPRIGHT:
777 case HTBOTTOMLEFT:
778 case HTBOTTOMRIGHT:
779 SendMessageA(hWnd, WM_SYSCOMMAND, SC_SIZE + wParam - 2, lParam);
780 break;
781 }
782
783 return(0);
784 }
785
786 LRESULT
787 DefWndHandleLButtonDblClkNC(HWND hWnd, WPARAM wParam, LPARAM lParam)
788 {
789 /* FIXME: Implement this. */
790 return(0);
791 }
792
793 LRESULT
794 DefWndHandleLButtonUpNC(HWND hWnd, WPARAM wParam, LPARAM lParam)
795 {
796 switch (wParam)
797 {
798 case HTCLOSE:
799 SendMessageA(hWnd, WM_CLOSE, 0, 0);
800 break;
801 }
802
803 return(0);
804 }
805
806 LRESULT
807 DefWndHandleActiveNC(HWND hWnd, WPARAM wParam)
808 {
809 /* FIXME: Implement this. */
810 return(0);
811 }
812
813 VOID
814 DefWndSetRedraw(HWND hWnd, WPARAM wParam)
815 {
816 }
817
818 LRESULT
819 DefWndHandleSetCursor(HWND hWnd, WPARAM wParam, LPARAM lParam)
820 {
821 /* Not for child windows. */
822 if (hWnd != (HWND)wParam)
823 {
824 return(0);
825 }
826
827 switch(LOWORD(lParam))
828 {
829 case HTERROR:
830 {
831 WORD Msg = HIWORD(lParam);
832 if (Msg == WM_LBUTTONDOWN || Msg == WM_MBUTTONDOWN ||
833 Msg == WM_RBUTTONDOWN)
834 {
835 MessageBeep(0);
836 }
837 break;
838 }
839
840 case HTCLIENT:
841 {
842 HICON hCursor = (HICON)GetClassLong(hWnd, GCL_HCURSOR);
843 if (hCursor)
844 {
845 SetCursor(hCursor);
846 return(TRUE);
847 }
848 return(FALSE);
849 }
850
851 case HTLEFT:
852 case HTRIGHT:
853 {
854 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZEWE)));
855 }
856
857 case HTTOP:
858 case HTBOTTOM:
859 {
860 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENS)));
861 }
862
863 case HTTOPLEFT:
864 case HTBOTTOMRIGHT:
865 {
866 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENWSE)));
867 }
868
869 case HTBOTTOMLEFT:
870 case HTTOPRIGHT:
871 {
872 return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENESW)));
873 }
874 }
875 return((LRESULT)SetCursor(LoadCursorW(0, IDC_ARROW)));
876 }
877
878 LRESULT
879 DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, POINT Pt)
880 {
881 /* FIXME: Implement system commands. */
882 return(0);
883 }
884
885 VOID
886 DefWndAdjustRect(RECT* Rect, ULONG Style, BOOL Menu, ULONG ExStyle)
887 {
888 if (Style & WS_ICONIC)
889 {
890 return;
891 }
892
893 if (UserHasThickFrameStyle(Style, ExStyle))
894 {
895 InflateRect(Rect, GetSystemMetrics(SM_CXFRAME),
896 GetSystemMetrics(SM_CYFRAME));
897 }
898 else if (UserHasDlgFrameStyle(Style, ExStyle))
899 {
900 InflateRect(Rect, GetSystemMetrics(SM_CXDLGFRAME),
901 GetSystemMetrics(SM_CYDLGFRAME));
902 }
903 else if (UserHasThinFrameStyle(Style, ExStyle))
904 {
905 InflateRect(Rect, GetSystemMetrics(SM_CXBORDER),
906 GetSystemMetrics(SM_CYBORDER));
907 }
908 if (Style & WS_CAPTION)
909 {
910 Rect->top -= GetSystemMetrics(SM_CYCAPTION) -
911 GetSystemMetrics(SM_CYBORDER);
912 }
913 if (Menu)
914 {
915 Rect->top -= GetSystemMetrics(SM_CYMENU) + GetSystemMetrics(SM_CYBORDER);
916 }
917 if (Style & WS_VSCROLL)
918 {
919 Rect->right += GetSystemMetrics(SM_CXVSCROLL) - 1;
920 if (UserHasAnyFrameStyle(Style, ExStyle))
921 {
922 Rect->right++;
923 }
924 }
925 if (Style & WS_HSCROLL)
926 {
927 Rect->bottom += GetSystemMetrics(SM_CYHSCROLL) - 1;
928 if (UserHasAnyFrameStyle(Style, ExStyle))
929 {
930 Rect->bottom++;
931 }
932 }
933 }
934
935 LRESULT STDCALL
936 DefWndNCCalcSize(HWND hWnd, RECT* Rect)
937 {
938 LRESULT Result = 0;
939 LONG Style = GetClassLongW(hWnd, GCL_STYLE);
940 RECT TmpRect = {0, 0, 0, 0};
941
942 if (Style & CS_VREDRAW)
943 {
944 Result |= WVR_VREDRAW;
945 }
946 if (Style & CS_HREDRAW)
947 {
948 Result |= WVR_HREDRAW;
949 }
950
951 if (!(GetWindowLong(hWnd, GWL_STYLE) & WS_MINIMIZE))
952 {
953 DefWndAdjustRect(&TmpRect, GetWindowLong(hWnd, GWL_STYLE),
954 FALSE, GetWindowLong(hWnd, GWL_EXSTYLE));
955 Rect->left -= TmpRect.left;
956 Rect->top -= TmpRect.top;
957 Rect->right -= TmpRect.right;
958 Rect->bottom -= TmpRect.bottom;
959 /* FIXME: Adjust if the window has a menu. */
960 Rect->bottom = max(Rect->top, Rect->bottom);
961 Rect->right = max(Rect->left, Rect->right);
962 }
963 return(Result);
964 }
965
966 LRESULT
967 DefWndHandleWindowPosChanging(HWND hWnd, WINDOWPOS* Pos)
968 {
969 /* FIXME: Implement this. */
970 return(0);
971 }
972
973 LRESULT STDCALL
974 User32DefWindowProc(HWND hWnd,
975 UINT Msg,
976 WPARAM wParam,
977 LPARAM lParam,
978 BOOL bUnicode)
979 {
980 switch (Msg)
981 {
982 case WM_NCPAINT:
983 {
984 return(DefWndPaintNC(hWnd, (HRGN)wParam));
985 }
986
987 case WM_NCHITTEST:
988 {
989 POINT Point;
990 Point.x = SLOWORD(lParam);
991 Point.y = SHIWORD(lParam);
992 return(DefWndHitTestNC(hWnd, Point));
993 }
994
995 case WM_NCLBUTTONDOWN:
996 {
997 return(DefWndHandleLButtonDownNC(hWnd, wParam, lParam));
998 }
999
1000 case WM_NCLBUTTONUP:
1001 {
1002 return(DefWndHandleLButtonUpNC(hWnd, wParam, lParam));
1003 }
1004
1005 case WM_LBUTTONDBLCLK:
1006 case WM_NCLBUTTONDBLCLK:
1007 {
1008 return(DefWndHandleLButtonDblClkNC(hWnd, wParam, lParam));
1009 }
1010
1011 case WM_NCRBUTTONDOWN:
1012 {
1013 if (wParam == HTCAPTION)
1014 {
1015 SetCapture(hWnd);
1016 }
1017 break;
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_NCRBUTTONUP:
1043 {
1044 /* Wine does nothing here. */
1045 break;
1046 }
1047
1048 case WM_CONTEXTMENU:
1049 {
1050 if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)
1051 {
1052 if (bUnicode)
1053 {
1054 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1055 }
1056 else
1057 {
1058 SendMessageA(hWnd, WM_CONTEXTMENU, wParam, lParam);
1059 }
1060 }
1061 else
1062 {
1063 LONG HitCode;
1064 POINT Pt;
1065
1066 Pt.x = SLOWORD(lParam);
1067 Pt.y = SHIWORD(lParam);
1068
1069 if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)
1070 {
1071 ScreenToClient(GetParent(hWnd), &Pt);
1072 }
1073
1074 HitCode = DefWndHitTestNC(hWnd, Pt);
1075
1076 if (HitCode == HTCAPTION || HitCode == HTSYSMENU)
1077 {
1078 TrackPopupMenu(GetSystemMenu(hWnd, FALSE),
1079 TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
1080 Pt.x, Pt.y, 0, hWnd, NULL);
1081 }
1082 }
1083 break;
1084 }
1085
1086 case WM_NCACTIVATE:
1087 {
1088 return(DefWndHandleActiveNC(hWnd, wParam));
1089 }
1090
1091 case WM_NCDESTROY:
1092 {
1093 return(0);
1094 }
1095
1096 case WM_PRINT:
1097 {
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 WindowRect;
1113 INT x, y;
1114 GetWindowRect(hWnd, &WindowRect);
1115 x = (WindowRect.right - WindowRect.left -
1116 GetSystemMetrics(SM_CXICON)) / 2;
1117 y = (WindowRect.bottom - WindowRect.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 (GetWindowLong(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 if (LOWORD(lParam) != WA_INACTIVE &&
1178 GetWindowLong(hWnd, GWL_STYLE) & WS_MINIMIZE)
1179 {
1180 /* Check if the window is minimized. */
1181 SetFocus(hWnd);
1182 }
1183 break;
1184 }
1185
1186 case WM_MOUSEWHEEL:
1187 {
1188 if (GetWindowLong(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 GetClipBox((HDC)wParam, &Rect);
1210 FillRect((HDC)wParam, &Rect, hBrush);
1211 return(1);
1212 }
1213
1214 case WM_GETDLGCODE:
1215 {
1216 return(0);
1217 }
1218
1219 /* FIXME: Implement colour controls. */
1220
1221 case WM_SETCURSOR:
1222 {
1223 if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)
1224 {
1225 if (LOWORD(lParam) < HTLEFT || LOWORD(lParam) > HTBOTTOMRIGHT)
1226 {
1227 BOOL bResult;
1228 if (bUnicode)
1229 {
1230 bResult = SendMessageW(GetParent(hWnd), WM_SETCURSOR,
1231 wParam, lParam);
1232 }
1233 else
1234 {
1235 bResult = SendMessageA(GetParent(hWnd), WM_SETCURSOR,
1236 wParam, lParam);
1237 }
1238 if (bResult)
1239 {
1240 return(TRUE);
1241 }
1242 }
1243 }
1244 return(DefWndHandleSetCursor(hWnd, wParam, lParam));
1245 }
1246
1247 case WM_SYSCOMMAND:
1248 {
1249 POINT Pt;
1250 Pt.x = SLOWORD(lParam);
1251 Pt.y = SHIWORD(lParam);
1252 return(DefWndHandleSysCommand(hWnd, wParam, Pt));
1253 }
1254
1255 /* FIXME: Handle key messages. */
1256
1257 case WM_SHOWWINDOW:
1258 {
1259 if (lParam)
1260 {
1261 return(0);
1262 }
1263 /* FIXME: Check for a popup window. */
1264 if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_VISIBLE && !wParam) ||
1265 (!(GetWindowLongW(hWnd, GWL_STYLE) & WS_VISIBLE) && wParam))
1266 {
1267 return(0);
1268 }
1269 ShowWindow(hWnd, wParam ? SW_SHOWNOACTIVATE : SW_HIDE);
1270 break;
1271 }
1272
1273 case WM_CANCELMODE:
1274 {
1275 /* FIXME: Check for a desktop. */
1276 if (GetCapture() == hWnd)
1277 {
1278 ReleaseCapture();
1279 }
1280 break;
1281 }
1282
1283 case WM_VKEYTOITEM:
1284 case WM_CHARTOITEM:
1285 return(-1);
1286
1287 case WM_DROPOBJECT:
1288 /* FIXME: Implement this. */
1289 break;
1290
1291 case WM_QUERYDROPOBJECT:
1292 {
1293 if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES)
1294 {
1295 return(1);
1296 }
1297 break;
1298 }
1299
1300 case WM_QUERYDRAGICON:
1301 {
1302 UINT Len;
1303 HICON hIcon;
1304
1305 hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON);
1306 if (hIcon)
1307 {
1308 return((LRESULT)hIcon);
1309 }
1310 for (Len = 1; Len < 64; Len++)
1311 {
1312 if ((hIcon = LoadIconW(NULL, MAKEINTRESOURCE(Len))) != NULL)
1313 {
1314 return((LRESULT)hIcon);
1315 }
1316 }
1317 return((LRESULT)LoadIconW(0, IDI_APPLICATION));
1318 }
1319
1320 /* FIXME: WM_ISACTIVEICON */
1321
1322 case WM_NOTIFYFORMAT:
1323 {
1324 if (IsWindowUnicode(hWnd))
1325 {
1326 return(NFR_UNICODE);
1327 }
1328 else
1329 {
1330 return(NFR_ANSI);
1331 }
1332 }
1333
1334 case WM_SETICON:
1335 {
1336 INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
1337 HICON hOldIcon = (HICON)GetClassLongW(hWnd, Index);
1338 SetClassLongW(hWnd, Index, lParam);
1339 SetWindowPos(hWnd, 0, 0, 0, 0, 0,
1340 SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
1341 SWP_NOACTIVATE | SWP_NOZORDER);
1342 return((LRESULT)hOldIcon);
1343 }
1344
1345 case WM_GETICON:
1346 {
1347 INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
1348 return(GetClassLongW(hWnd, Index));
1349 }
1350
1351 case WM_HELP:
1352 {
1353 if (bUnicode)
1354 {
1355 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1356 }
1357 else
1358 {
1359 SendMessageA(GetParent(hWnd), Msg, wParam, lParam);
1360 }
1361 break;
1362 }
1363 }
1364 return 0;
1365 }
1366
1367 LRESULT STDCALL
1368 DefWindowProcA(HWND hWnd,
1369 UINT Msg,
1370 WPARAM wParam,
1371 LPARAM lParam)
1372 {
1373 LRESULT Result;
1374 static LPSTR WindowTextAtom = 0;
1375 PSTR WindowText;
1376
1377 switch (Msg)
1378 {
1379 case WM_NCCREATE:
1380 {
1381 CREATESTRUCTA* Cs = (CREATESTRUCTA*)lParam;
1382 if (HIWORD(Cs->lpszName))
1383 {
1384 WindowTextAtom =
1385 (LPSTR)(ULONG)GlobalAddAtomA("USER32!WindowTextAtomA");
1386 WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
1387 strlen(Cs->lpszName) * sizeof(CHAR));
1388 strcpy(WindowText, Cs->lpszName);
1389 SetPropA(hWnd, WindowTextAtom, WindowText);
1390 }
1391 return(1);
1392 }
1393
1394 case WM_NCCALCSIZE:
1395 {
1396 return(DefWndNCCalcSize(hWnd, (RECT*)lParam));
1397 }
1398
1399 case WM_WINDOWPOSCHANGING:
1400 {
1401 return(DefWndHandleWindowPosChanging(hWnd, (WINDOWPOS*)lParam));
1402 }
1403
1404 case WM_GETTEXTLENGTH:
1405 {
1406 if (WindowTextAtom == 0 ||
1407 (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
1408 {
1409 return(0);
1410 }
1411 return(strlen(WindowText));
1412 }
1413
1414 case WM_GETTEXT:
1415 {
1416 if (WindowTextAtom == 0 ||
1417 (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
1418 {
1419 if (wParam > 1)
1420 {
1421 ((PSTR)lParam) = '\0';
1422 }
1423 return(0);
1424 }
1425 strncpy((LPSTR)lParam, WindowText, wParam);
1426 return(min(wParam, strlen(WindowText)));
1427 }
1428
1429 case WM_SETTEXT:
1430 {
1431 if (WindowTextAtom != 0)
1432 {
1433 WindowTextAtom =
1434 (LPSTR)(DWORD)GlobalAddAtomA("USER32!WindowTextAtomW");
1435 }
1436 if (WindowTextAtom != 0 &&
1437 (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
1438 {
1439 RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
1440 }
1441 WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
1442 strlen((PSTR)lParam) * sizeof(CHAR));
1443 strcpy(WindowText, (PSTR)lParam);
1444 SetPropA(hWnd, WindowTextAtom, WindowText);
1445 }
1446
1447 case WM_NCDESTROY:
1448 {
1449 if (WindowTextAtom != 0 &&
1450 (WindowText = RemovePropA(hWnd, WindowTextAtom)) == NULL)
1451 {
1452 RtlFreeHeap(GetProcessHeap(), 0, WindowText);
1453 }
1454 if (WindowTextAtom != 0)
1455 {
1456 GlobalDeleteAtom((ATOM)(ULONG)WindowTextAtom);
1457 }
1458 /* FIXME: Destroy scroll bars here as well. */
1459 return(0);
1460 }
1461
1462 default:
1463 Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, FALSE);
1464 break;
1465 }
1466
1467 return(Result);
1468 }
1469
1470 LRESULT STDCALL
1471 DefWindowProcW(HWND hWnd,
1472 UINT Msg,
1473 WPARAM wParam,
1474 LPARAM lParam)
1475 {
1476 LRESULT Result;
1477 static LPWSTR WindowTextAtom = 0;
1478 PWSTR WindowText;
1479
1480 switch (Msg)
1481 {
1482 case WM_NCCREATE:
1483 {
1484 CREATESTRUCTW* Cs = (CREATESTRUCTW*)lParam;
1485 if (HIWORD(Cs->lpszName))
1486 {
1487 WindowTextAtom =
1488 (LPWSTR)(DWORD)GlobalAddAtomW(L"USER32!WindowTextAtomW");
1489 WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
1490 wcslen(Cs->lpszName) * sizeof(WCHAR));
1491 wcscpy(WindowText, Cs->lpszName);
1492 SetPropW(hWnd, WindowTextAtom, WindowText);
1493 }
1494 return(1);
1495 }
1496
1497 case WM_NCCALCSIZE:
1498 {
1499 return(DefWndNCCalcSize(hWnd, (RECT*)lParam));
1500 }
1501
1502 case WM_WINDOWPOSCHANGING:
1503 {
1504 return(DefWndHandleWindowPosChanging(hWnd, (WINDOWPOS*)lParam));
1505 }
1506
1507 case WM_GETTEXTLENGTH:
1508 {
1509 if (WindowTextAtom == 0 ||
1510 (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
1511 {
1512 return(0);
1513 }
1514 return(wcslen(WindowText));
1515 }
1516
1517 case WM_GETTEXT:
1518 {
1519 if (WindowTextAtom == 0 ||
1520 (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
1521 {
1522 if (wParam > 1)
1523 {
1524 ((PWSTR)lParam) = '\0';
1525 }
1526 return(0);
1527 }
1528 wcsncpy((PWSTR)lParam, WindowText, wParam);
1529 return(min(wParam, wcslen(WindowText)));
1530 }
1531
1532 case WM_SETTEXT:
1533 {
1534 if (WindowTextAtom != 0)
1535 {
1536 WindowTextAtom =
1537 (LPWSTR)(DWORD)GlobalAddAtom(L"USER32!WindowTextAtomW");
1538 }
1539 if (WindowTextAtom != 0 &&
1540 (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
1541 {
1542 RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
1543 }
1544 WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
1545 wcslen((PWSTR)lParam) * sizeof(WCHAR));
1546 wcscpy(WindowText, (PWSTR)lParam);
1547 SetPropW(hWnd, WindowTextAtom, WindowText);
1548 }
1549 //FIXME: return correct code
1550 return TRUE;
1551
1552 case WM_NCDESTROY:
1553 {
1554 if (WindowTextAtom != 0 &&
1555 (WindowText = RemovePropW(hWnd, WindowTextAtom)) == NULL)
1556 {
1557 RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
1558 }
1559 if (WindowTextAtom != 0)
1560 {
1561 GlobalDeleteAtom((ATOM)(DWORD)WindowTextAtom);
1562 }
1563 /* FIXME: Destroy scroll bars here as well. */
1564 return(0);
1565 }
1566
1567 default:
1568 Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, TRUE);
1569 break;
1570 }
1571
1572 return(Result);
1573 }