]> git.saurik.com Git - wxWidgets.git/blame - src/msw/minifram.cpp
Some but not all compile fixes for typetest (VC++ 1.5); added datetime.cpp
[wxWidgets.git] / src / msw / minifram.cpp
CommitLineData
2bda0e17
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: minifram.cpp
3// Purpose: wxMiniFrame
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "minifram.h"
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
0c589ad0
BM
23#include "wx/window.h"
24#include "wx/msw/private.h"
25
2bda0e17
KB
26#ifndef WX_PRECOMP
27#include "wx/setup.h"
2432b92d 28#include "wx/event.h"
2bda0e17
KB
29#include "wx/app.h"
30#include "wx/utils.h"
31#endif
32
7309b92d
VS
33
34#ifdef __WIN32__
35
36#include "wx/minifram.h"
37
7309b92d 38IMPLEMENT_DYNAMIC_CLASS(wxMiniFrame, wxFrame)
7309b92d
VS
39
40
41#else
42
43
47d67540 44#if wxUSE_ITSY_BITSY
2bda0e17
KB
45
46#include "wx/minifram.h"
2bda0e17 47
57c208c5 48#ifndef __TWIN32__
2bda0e17 49#ifdef __GNUWIN32__
65fd5cb0 50#ifndef wxUSE_NORLANDER_HEADERS
2bda0e17
KB
51#include "wx/msw/gnuwin32/extra.h"
52#endif
57c208c5 53#endif
65fd5cb0 54#endif
2bda0e17 55
2bda0e17 56IMPLEMENT_DYNAMIC_CLASS(wxMiniFrame, wxFrame)
2bda0e17
KB
57
58long wxMiniFrame::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
59{
60 if ((GetWindowStyleFlag() & wxTINY_CAPTION_HORIZ) ||
61 (GetWindowStyleFlag() & wxTINY_CAPTION_VERT))
62 return ::ibDefWindowProc((HWND) GetHWND(), nMsg, wParam, lParam);
63 else if ( m_oldWndProc )
bbcdf8bc 64 return ::CallWindowProc(CASTWNDPROC m_oldWndProc, (HWND) GetHWND(), (UINT) nMsg, (WPARAM) wParam, (LPARAM) lParam);
2bda0e17
KB
65 else
66 return ::DefWindowProc((HWND) GetHWND(), nMsg, wParam, lParam);
67}
68
69wxMiniFrame::~wxMiniFrame(void)
70{
71}
72
73/////////////////////////////////////////////////////////////////////////
74//
75// Project: ItsyBitsy window support module
76// Module: itsybits.c
77//
78//
79// ItsyBitsy is a support module that allows you to create windows
80// that look and act very much like a popup window witha system
81// menu and caption bar, except everything is scaled to about 2/3
82// scale.
83//
84// For documentation on how to use ItsyBits, read the document
85// ITSYBITS.DOC.
86//
87// Revisions:
88// 9/27/91 Charlie Kindel (cek/ckindel)
89// Wrote and documented it.
90//
91// 1/14/93 cek
92// 2/23/93 cek Added minimize/maximize buttons.
93// 3/18/93 cek Fixed system menu bug where system menu
94// popped back up if you clicked on the
95// icon again while it was up.
96// 3/24/93 cek More comments. Fixed DS_MODALDIALOG style
97// problem. Use auto precompiled headers
98// in MSVC.
99//
100//////////////////////////////////////////////////////////////////////////
101
0c589ad0
BM
102#include "wx/window.h"
103#include "wx/msw/private.h"
2bda0e17
KB
104
105#include <string.h>
106
ce3ed50d 107#if !defined( __WATCOMC__ ) && !defined( __MWERKS__ ) && !defined(__SALFORDC__)
2bda0e17
KB
108#include <memory.h>
109#endif
110
111#include <stdlib.h>
112
113#ifndef _RGB_H_
114#define _RGB_H_
115
116 // Some mildly useful macros for the standard 16 colors
117 #define RGBBLACK RGB(0,0,0)
118 #define RGBRED RGB(128,0,0)
119 #define RGBGREEN RGB(0,128,0)
120 #define RGBBLUE RGB(0,0,128)
121
122 #define RGBBROWN RGB(128,128,0)
123 #define RGBMAGENTA RGB(128,0,128)
124 #define RGBCYAN RGB(0,128,128)
125 #define RGBLTGRAY RGB(192,192,192)
126
127 #define RGBGRAY RGB(128,128,128)
128 #define RGBLTRED RGB(255,0,0)
129 #define RGBLTGREEN RGB(0,255,0)
130 #define RGBLTBLUE RGB(0,0,255)
131
132 #define RGBYELLOW RGB(255,255,0)
133 #define RGBLTMAGENTA RGB(255,0,255)
134 #define RGBLTCYAN RGB(0,255,255)
135 #define RGBWHITE RGB(255,255,255)
136#endif
137
138#ifndef GlobalAllocPtr
139#define GlobalPtrHandle(lp) \
140 ((HGLOBAL)GlobalHandle(lp))
141
142#define GlobalLockPtr(lp) \
143 ((BOOL)GlobalLock(GlobalPtrHandle(lp)))
144#define GlobalUnlockPtr(lp) \
145 GlobalUnlock(GlobalPtrHandle(lp))
146
147#define GlobalAllocPtr(flags, cb) \
148 (GlobalLock(GlobalAlloc((flags), (cb))))
149#define GlobalReAllocPtr(lp, cbNew, flags) \
150 (GlobalUnlockPtr(lp), GlobalLock(GlobalReAlloc(GlobalPtrHandle(lp) , (cbNew), (flags))))
151#define GlobalFreePtr(lp) \
152 (GlobalUnlockPtr(lp), (BOOL)GlobalFree(GlobalPtrHandle(lp)))
153#endif
154
155#if defined(__BORLANDC__) || defined(__WATCOMC__)
156#define max(a,b) (((a) > (b)) ? (a) : (b))
157#define min(a,b) (((a) < (b)) ? (a) : (b))
158#endif
159
160// CAPTIONXY is the default size of the system menu icon. This
161// determines the height/width of the caption.
162//
163// The value that results from the following formula works out
164// nicely for the veritcal caption on VGA, 8514 (Large Fonts),
165// 8514 (Small Fonts), XGA (Small Fonts), XGA (Large Fonts),
166// and TIGA (Small Fonts). It may not be good on other displays.
167//
168// The problem is that TT fonts turn into bitmap fonts when they
169// are sized below a certain threshold. The idea is to make the
170// size of the caption just big enough to get the smallest TT
171// (scalable) font to fit.
172//
173#define CAPTIONXY (GetSystemMetrics( SM_CYCAPTION ) / 2 + 1)
174
175#define TestWinStyle( hWnd, dwStyleBit ) \
176 (((DWORD)GetWindowLong( hWnd, GWL_STYLE ) & (DWORD)dwStyleBit) ? TRUE : FALSE )
177#define HASCAPTION( hwnd ) (TestWinStyle( hwnd, IBS_VERTCAPTION ) ||\
178 TestWinStyle( hwnd, IBS_HORZCAPTION ))
179
223d09f6
KB
180#define SETCAPTIONSIZE(h,i) (UINT)SetProp(h,wxT("ibSize"),(HANDLE)i)
181#define GETCAPTIONSIZE(h) (UINT)GetProp(h,wxT("ibSize"))
182#define FREECAPTIONSIZE(h) RemoveProp(h,wxT("ibSize"))
2bda0e17 183
223d09f6
KB
184#define SETMENUWASUPFLAG(h,i) (UINT)SetProp(h,wxT("ibFlag"),(HANDLE)i)
185#define GETMENUWASUPFLAG(h) (UINT)GetProp(h,wxT("ibFlag"))
186#define FREEMENUWASUPFLAG(h) RemoveProp(h,wxT("ibFlag"))
2bda0e17
KB
187
188/////////////////////////////////////////////////////////////////////
189// Little known fact:
190// ExtTextOut() is the fastest way to draw a filled rectangle
191// in Windows (if you don't want dithered colors or borders).
192//
193// Unfortunately there is a bug in the Windows 3.0 8514 driver
194// in using ExtTextOut() to a memory DC. If you are drawing
195// to an off screen bitmap, then blitting that bitmap to the
47d67540 196// display, do not #define wxUSE_EXTTEXTOUT below.
2bda0e17
KB
197//
198// The following macro (DRAWFASTRECT) draws a filled rectangle
199// with no border and a solid color. It uses the current back-
200// ground color as the fill color.
201//////////////////////////////////////////////////////////////////////
47d67540
VZ
202#define wxUSE_EXTTEXTOUT
203#ifdef wxUSE_EXTTEXTOUT
2bda0e17
KB
204 #define DRAWFASTRECT(hdc,lprc) ExtTextOut(hdc,0,0,ETO_OPAQUE,lprc,NULL,0,NULL)
205#else
206 #define DRAWFASTRECT(hdc,lprc) {\
207 HBRUSH hbr = CreateSolidBrush( GetBkColor( hdc ) ) ;\
208 hbr = SelectObject(hdc, hbr) ;\
209 PatBlt(hdc,(lprc)->left,(lprc)->top,(lprc)->right-(lprc)->left,(lprc)->bottom-(lprc)->top,PATCOPY) ;\
210 hbr = SelectObject(hdc, hbr) ;\
211 DeleteObject( hbr ) ;\
212 }
213#endif
214
215// The DrawArrow function takes the following to indicate what
216// kind of arrow to draw.
217//
218#define ARROW_UP 0
219#define ARROW_DOWN 1
220#define ARROW_RESTORE 2
221
222BOOL PASCAL DepressMinMaxButton( HWND hWnd, UINT uiHT, LPRECT ) ;
223BOOL PASCAL DoMenu( HWND hWnd ) ;
224void PASCAL SetupSystemMenu( HWND hWnd, HMENU hMenu ) ;
225BOOL PASCAL GetCaptionRect( HWND hWnd, LPRECT lprc ) ;
226BOOL PASCAL GetIconRect( HWND hWnd, LPRECT lprc ) ;
227BOOL PASCAL GetButtonRect( HWND hWnd, UINT nPos, LPRECT lprc ) ;
228BOOL PASCAL GetMinButtonRect( HWND hWnd, LPRECT lprc ) ;
229BOOL PASCAL GetMaxButtonRect( HWND hWnd, LPRECT lprc ) ;
230BOOL PASCAL DrawCaption( HDC hDC, HWND hWnd, LPRECT lprc,
231 BOOL fVert, BOOL fSysMenu,
232 BOOL fMin, BOOL fMax, BOOL fActive ) ;
233void PASCAL DrawSysMenu( HDC hDC, HWND hWnd, BOOL fInvert ) ;
234void PASCAL DrawButton( HDC hDC, HWND hWnd, BOOL fMin, BOOL fDepressed ) ;
235void PASCAL DrawArrow( HDC hdc, LPRECT lprc, UINT uiStyle ) ;
236
237// Global vars
238//
239static BOOL fWin31 ;
240
241///////////////////////////////////////////////////////////////////////
242// External/Public functions
243///////////////////////////////////////////////////////////////////////
244
245/////////////////////////////////////////////////////////////////
246// UINT WINAPI ibGetCaptionSize( HWND hWnd )
247//
248// Description:
249//
250// Gets the size of the caption (height if horz, width if
251// vertical).
252//
253// Comments:
254//
255///////////////////////////////////////////////////////////////
256UINT WINAPI ibGetCaptionSize( HWND hWnd )
257{
258 return GETCAPTIONSIZE( hWnd ) + 1 ;
259} // ibSetCaptionSize()
260
261/////////////////////////////////////////////////////////////////
262// UINT WINAPI ibSetCaptionSize( HWND hWnd, UINT nSize )
263//
264// Description:
265//
266// Changes the size of the caption (height if horz, width if
267// vertical).
268//
269// Comments:
270//
271//////////////////////////////////////////////////////////////////
272UINT WINAPI ibSetCaptionSize( HWND hWnd, UINT nSize )
273{
274 UINT ui ;
275
276 if (nSize <= 0)
277 return 0 ;
278
279 nSize-- ;
280 ui = SETCAPTIONSIZE( hWnd, nSize ) ;
281
282 // Once we change the window style, we need a WM_NCCALCRECT
283 // to be generated.
284 //
285 // SWP_FRAMECHANGED is not documented in the 3.1 SDK docs,
286 // but *is* in WINDOWS.H.
287 //
288 SetWindowPos( hWnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED |
289 SWP_NOSIZE | SWP_NOMOVE |
290 SWP_NOACTIVATE | SWP_NOZORDER) ;
291
292 return ui ;
293
294} // ibSetCaptionSize()
295
296/////////////////////////////////////////////////////////////////
297// LRESULT WINAPI ibDefWindowProc( HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam )
298//
299// Description:
300//
301// This function should be called instead of DefWindowProc() for
302// windows that want to have itsybitsy captions.
303//
304// Comments:
305//
306//////////////////////////////////////////////////////////////////
307LRESULT WINAPI ibDefWindowProc( HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam )
308{
309 LRESULT lRet ;
310 UINT nCapSize ;
311
312 switch( uiMsg )
313 {
314 case WM_SYSCHAR:
315 // If ALT-SPACE
316 // was hit then pop up the menu
317 //
318 if (HASCAPTION( hWnd ) && (wParam == VK_SPACE))
319 {
320 DoMenu( hWnd ) ;
321 break ;
322 }
323
324 // FALL THROUGH!!!!
325 //
326
327 case WM_SYSKEYDOWN:
328 case WM_SYSKEYUP:
329 case WM_KEYDOWN:
330 case WM_KEYUP:
331 {
332 DWORD dw = GetWindowLong( hWnd, GWL_STYLE ) ;
333
334 // Fool DefWindowProc into thinking we do not have
335 // a system menu. Otherwise it will try to
336 // pop up its own.
337 //
338 SetWindowLong( hWnd, GWL_STYLE, dw &~WS_SYSMENU ) ;
339 lRet = DefWindowProc( hWnd, uiMsg, wParam, lParam ) ;
340 SetWindowLong( hWnd, GWL_STYLE, dw ) ;
341 return lRet ;
342 }
343 break ;
344
345 case WM_COMMAND:
346 // The menu that is poped up for the system menu with
347 // TrackPopupMenu() sends it's notifications as WM_COMMAND
348 // messages. We need to translate these into
349 // WM_SYSCOMMAND messages. All standard WM_SYSCOMMAND
350 // ids are greater than 0xF000.
351 //
352 // This could be a possible cause of confusion if the
353 // itsybitsy window had children that used SC_MOVE or SC_CLOSE
354 // as their IDs. Take note and be careful.
355 //
356 // Also, because ibDefWindowProc looks at WM_COMMAND messages,
357 // you will need to be careful to call ibDefWindowProc() for
358 // any wm_command messages that you would normally ignore.
359 // Otherwise the system menu won't work.
360 //
361 if (wParam >= 0xF000)
362 // Call PostMessage() here instead of SendMessage!
363 // Here's why:
364 // Our menu was created by TrackPopupMenu(). TPM() does
365 // not return until after the menu has been destroyed
366 // (and thus the command associated with the menu selection
367 // sent). Therefore when we get here, we are still
368 // *inside* TPM(). If we Send WM_SYSCOMMAND, SC_CLOSE
369 // to the window, the window will be destroyed before
370 // TPM() returns to our code within DoMenu() below. Wel...
371 // We do stuff with the window handle after DoMenu()
372 // returns (namely GetProp()). Since the window has
373 // been destroyed,this is bad.
374 PostMessage( hWnd, WM_SYSCOMMAND, wParam, lParam ) ;
375
376 return DefWindowProc( hWnd, uiMsg, wParam, lParam ) ;
377
378 case WM_GETMINMAXINFO:
379 {
380 nCapSize = GETCAPTIONSIZE( hWnd ) ;
381 if (HASCAPTION( hWnd ) && TestWinStyle( hWnd, WS_THICKFRAME ))
382 {
383 LPPOINT lppt = (LPPOINT)lParam ;
384 RECT rcMenu ;
385 RECT rcMin ;
386 RECT rcMax ;
387 int nX ;
388 int cx, cy ; // window frame/border width
389
390 if (TestWinStyle( hWnd, WS_THICKFRAME ))
391 {
392 cx = GetSystemMetrics( SM_CXFRAME ) ;
393 cy = GetSystemMetrics( SM_CYFRAME ) ;
394 }
fd3f686c
VZ
395 else if (TestWinStyle(hWnd, WS_BORDER ))
396 {
397 cx = GetSystemMetrics( SM_CXBORDER ) ;
398 cy = GetSystemMetrics( SM_CYBORDER ) ;
399 }
2bda0e17 400 else
fd3f686c
VZ
401 {
402 // VZ: I don't know what should be here, but the vars must
403 // be inited!
223d09f6 404 wxFAIL_MSG(wxT("don't know how to initialize cx, cy"));
fd3f686c
VZ
405
406 cx = cy = 0;
407 }
2bda0e17
KB
408
409 GetIconRect( hWnd, &rcMenu ) ;
410 GetMinButtonRect( hWnd, &rcMin ) ;
411 GetMaxButtonRect( hWnd, &rcMax ) ;
412 nX = (rcMenu.right-rcMenu.left) +
413 (rcMin.right-rcMin.left) +
414 (rcMin.right-rcMin.left) ;
415
416
417 if (TestWinStyle( hWnd, IBS_VERTCAPTION ) )
418 {
419 lppt[3].x = nCapSize + cx * 2 - 1 ;
420 lppt[3].y = nX + (2* nCapSize) ;
421 }
422 else
423 {
424 lppt[3].x = nX + (2* nCapSize) ;
425 lppt[3].y = nCapSize + cy * 2 - 1 ;
426 }
427 }
428 return DefWindowProc( hWnd, uiMsg, wParam, lParam ) ;
429 }
430 break ;
431
432 /////////////////////////////////////////////////////////////////////
433 // Non-client area messages. These are used to allow the
434 // minature caption bar to be handled correctly.
435 //
436 case WM_NCCREATE:
437 {
438 DWORD dwStyle ;
439
440 // We have two things that we need to store somewhere:
441 // 1) The caption height (width).
442 // and 2) A flag indicating whether the sysmenu was
443 // just up or not.
444 //
445 // CAPTIONXY is a macro that calls GetSystemMetrics.
446 //
447 SETCAPTIONSIZE( hWnd, CAPTIONXY ) ;
448
449 // Set our flag that tells us whether the system menu was
450 // 'just up'.
451 //
452 SETMENUWASUPFLAG( hWnd, FALSE ) ;
453
454 // Are we in 3.1? If so we have some neat features
455 // we can use like rotated TrueType fonts.
456 //
457 fWin31 = (BOOL)(LOWORD( GetVersion() ) >= 0x030A) ;
458
459 // If IBS_????CAPTION was specified and the WS_DLGFRAME (or
460 // WS_DLGFRAME 'cause it == WS_CAPTION | WS_BORDER)
461 // was specified the creator made a mistake. Things get really
462 // ugly if DefWindowProc sees WS_DLGFRAME, so we strip
463 // the WS_DLGFRAME part off!
464 //
465 dwStyle = GetWindowLong( hWnd, GWL_STYLE ) ;
466 if ((dwStyle & IBS_VERTCAPTION || dwStyle & IBS_HORZCAPTION) &&
467 dwStyle & WS_DLGFRAME)
468 {
469 dwStyle &= (DWORD)~WS_DLGFRAME ;
470 SetWindowLong( hWnd, GWL_STYLE, dwStyle ) ;
471 }
472 }
473 return DefWindowProc( hWnd, uiMsg, wParam, lParam ) ;
474
475 case WM_NCDESTROY:
476 // We store the caption size in a window prop. so we
477 // must remove props.
478 //
479 FREECAPTIONSIZE( hWnd ) ;
480 FREEMENUWASUPFLAG( hWnd ) ;
481 return DefWindowProc( hWnd, uiMsg, wParam, lParam ) ;
482
483 case WM_NCCALCSIZE:
484 // This is sent when the window manager wants to find out
485 // how big our client area is to be. If we have a mini-caption
486 // then we trap this message and calculate the cleint area rect,
487 // which is the client area rect calculated by DefWindowProc()
488 // minus the width/height of the mini-caption bar
489 //
490 lRet = DefWindowProc( hWnd, uiMsg, wParam, lParam ) ;
491 if (!IsIconic( hWnd ) && HASCAPTION( hWnd ))
492 {
493 nCapSize = GETCAPTIONSIZE( hWnd ) ;
494
495 if (TestWinStyle( hWnd, IBS_VERTCAPTION ) )
496 ((LPRECT)lParam)->left += nCapSize ;
497 else
498 ((LPRECT)lParam)->top += nCapSize ;
499 }
500 return lRet ;
501
502 case WM_NCHITTEST:
503 // This message is sent whenever the mouse moves over us.
504 // We will depend on DefWindowProc for everything unless
505 // there is a mini-caption, in which case we will
506 // return HTCAPTION or HTSYSMENU. When the user clicks
507 // or double clicks, NC_LBUTTON/ message are sent with
508 // wParam equal to what we return here.
509 // This means that this is an ideal place to figure out
510 // where we are!
511 //
512 // let defwindowproc handle the standard borders etc...
513 //
514 lRet = DefWindowProc( hWnd, uiMsg, wParam, lParam ) ;
515 if (!IsIconic( hWnd ) && HASCAPTION( hWnd ) && lRet == HTNOWHERE)
516 {
517 RECT rc ;
518 RECT rcMenu ;
519 RECT rcMinButton ;
520 RECT rcMaxButton ;
521 POINT pt ;
522
523 nCapSize = GETCAPTIONSIZE( hWnd ) ;
524
525 // if DefWindowProc returned HTCAPTION then we have to
526 // refine the area and return HTSYSMENU if appropriate
527 //
528 pt.x = LOWORD( lParam ) ;
529 pt.y = HIWORD( lParam ) ;
530
531 GetCaptionRect( hWnd, &rc ) ; // window coords
532 if (PtInRect( &rc, pt ))
533 {
534 lRet = HTCAPTION ;
535
536 // rely on the fact that Get???Rect() return an invalid
537 // (empty) rectangle if the menu/buttons don't exist
538 //
539 GetIconRect( hWnd, &rcMenu ) ;
540 GetMinButtonRect( hWnd, &rcMinButton ) ;
541 GetMaxButtonRect( hWnd, &rcMaxButton ) ;
542
543 if (PtInRect( &rcMenu, pt ))
544 lRet = HTSYSMENU ;
545
546 if (PtInRect( &rcMinButton, pt ))
547 lRet = HTMINBUTTON ;
548 else
549 if (PtInRect( &rcMaxButton, pt ))
550 lRet = HTMAXBUTTON ;
551 }
552 }
553 if (lRet != HTSYSMENU)
554 SETMENUWASUPFLAG( hWnd, FALSE ) ;
555 return lRet ;
556
557 case WM_NCLBUTTONDBLCLK:
558 // Windows recieve WM_NC?BUTTONDBLCLK messages whether they
559 // have CS_DBLCLKS or not. We watch for one of these
560 // to see if the user double clicked on the system menu (to
561 // close the window) or on the caption (to maximize the window).
562 //
563 if (!IsIconic( hWnd ) && HASCAPTION( hWnd ) && wParam == HTSYSMENU)
564 {
565 SendMessage( hWnd, WM_CLOSE, 0, 0L ) ;
566 break ;
567 }
568 return DefWindowProc( hWnd, uiMsg, wParam, lParam ) ;
569
570 case WM_NCLBUTTONDOWN:
571 {
572 RECT rc ;
573
574 // If we're iconic or we don't have a caption then
575 // DefWindowProc will do the job just fine.
576 //
577 if (IsIconic( hWnd ) || !HASCAPTION( hWnd ))
578 return DefWindowProc( hWnd, uiMsg, wParam, lParam ) ;
579
580 // Here's were we handle the system menu, the min and max buttons.
581 // If you wanted to change the behavior of the min/max buttons
582 // do something like swap tool palettes or something, you
583 // would change the SendMessage() calls below.
584 //
585 switch (wParam)
586 {
587 case HTSYSMENU:
588 if (GETMENUWASUPFLAG( hWnd ) == FALSE && DoMenu( hWnd ))
589 SETMENUWASUPFLAG( hWnd, TRUE ) ;
590 else
591 SETMENUWASUPFLAG( hWnd, FALSE ) ;
592 break ;
593
594 case HTMINBUTTON:
595 GetMinButtonRect( hWnd, &rc ) ;
596 // Note that DepressMinMaxButton() goes into
597 // a PeekMessage() loop waiting for the mouse
598 // to come back up.
599 //
600 if (DepressMinMaxButton( hWnd, wParam, &rc ))
601 SendMessage( hWnd, WM_SYSCOMMAND, SC_MINIMIZE, lParam ) ;
602 break ;
603
604 case HTMAXBUTTON:
605 GetMaxButtonRect( hWnd, &rc ) ;
606 // Note that DepressMinMaxButton() goes into
607 // a PeekMessage() loop waiting for the mouse
608 // to come back up.
609 //
610 if (DepressMinMaxButton( hWnd, wParam, &rc ))
611 {
612 if (IsZoomed(hWnd))
613 SendMessage( hWnd, WM_SYSCOMMAND, SC_RESTORE, lParam ) ;
614 else
615 SendMessage( hWnd, WM_SYSCOMMAND, SC_MAXIMIZE, lParam ) ;
616 }
617 break ;
618
619 default:
620 // Well, it appears as though the user clicked somewhere other
621 // than the buttons. We let DefWindowProc do it's magic.
622 // This is where things like dragging and sizing the
623 // window happen.
624 //
625 return DefWindowProc( hWnd, uiMsg, wParam, lParam ) ;
626 }
627 }
628 break ;
629
630 case WM_NCPAINT:
631 case WM_NCACTIVATE:
632 if (IsIconic( hWnd ))
633 return DefWindowProc( hWnd, uiMsg, wParam, lParam ) ;
634
635 // Paint the non-client area here. We will call DefWindowProc
636 // after we are done so it can paint the borders and so
637 // forth...
638 //
639 lRet = DefWindowProc( hWnd, uiMsg, wParam, lParam ) ;
640 if (HASCAPTION( hWnd ))
641 {
642 RECT rcCap ;
643 RECT rc ;
644 HDC hDC = GetWindowDC( hWnd ) ;
645 BOOL fActive ;
646
647 GetCaptionRect( hWnd, &rcCap ) ; // Convert to window coords
648 GetWindowRect( hWnd, &rc ) ;
649 OffsetRect( &rcCap, -rc.left, -rc.top ) ;
650
651 if (uiMsg == WM_NCPAINT)
652 fActive = (hWnd == GetActiveWindow()) ;
653 else
654 fActive = wParam ;
655
656 DrawCaption( hDC, hWnd, &rcCap,
657 TestWinStyle(hWnd, IBS_VERTCAPTION),
658 TestWinStyle(hWnd, WS_SYSMENU),
659 TestWinStyle(hWnd, WS_MINIMIZEBOX),
660 TestWinStyle(hWnd, WS_MAXIMIZEBOX),
661 fActive ) ;
662
663 ReleaseDC( hWnd, hDC ) ;
664 }
665 return lRet;
666 break;
667
668 default:
669 return DefWindowProc( hWnd, uiMsg, wParam, lParam ) ;
670 }
671
672 return 0L ;
673
674} // ibDefWindowProc()
675
676// ibAdjustWindowRect( HWND hWnd, LPRECT lprc )
677//
678// Does the same thing as the USER function AdjustWindowRect(),
679// but knows about itsybitsy windows. AdjustWindowRect() is
680// bogus for stuff like this.
681//
682void WINAPI ibAdjustWindowRect( HWND hWnd, LPRECT lprc )
683{
684 short cx = 0, cy = 0 ;
685 UINT nCapSize ;
686
687 nCapSize = GETCAPTIONSIZE( hWnd ) ;
688
689 // First check Windows's styles, then our own.
690 //
691 if (TestWinStyle( hWnd, WS_THICKFRAME ))
692 {
693 cx = GetSystemMetrics( SM_CXFRAME ) ;
694 cy = GetSystemMetrics( SM_CYFRAME ) ;
695 }
696 else
697 if (TestWinStyle(hWnd, DS_MODALFRAME ))
698 {
699 cx = GetSystemMetrics( SM_CXDLGFRAME ) + GetSystemMetrics( SM_CXBORDER ) ;
700 cy = GetSystemMetrics( SM_CYDLGFRAME ) + GetSystemMetrics( SM_CYBORDER ) ;
701 }
702 else
703 if (TestWinStyle(hWnd, WS_BORDER ))
704 {
705 cx = GetSystemMetrics( SM_CXBORDER ) ;
706 cy = GetSystemMetrics( SM_CYBORDER ) ;
707 }
708
709 InflateRect( lprc, cx, cy ) ;
710
711 if (TestWinStyle( hWnd, IBS_VERTCAPTION ))
712 lprc->left -= nCapSize ;
713 else
714 if (TestWinStyle( hWnd, IBS_HORZCAPTION ))
715 lprc->top -= nCapSize ;
716
717} // ibAdjustWindowRect()
718
719
720///////////////////////////////////////////////////////////////////////
721// Internal functions
722///////////////////////////////////////////////////////////////////////
723
724// DepressMinMaxButton()
725//
726// This function is called when the user has pressed either the min or
727// max button (i.e. WM_NCLBUTTONDOWN). We go into a Peekmessage() loop,
728// waiting for the mouse to come back up. This allows us to make the
729// button change up/down state like a real button does.
730//
731// lprc points to the rectangle that describes the button the
732// user has clicked on.
733//
734BOOL PASCAL DepressMinMaxButton( HWND hWnd, UINT uiHT, LPRECT lprc )
735{
736 BOOL fDepressed = TRUE ;
737 MSG msg ;
738
739 // Draw button in down state
740 DrawButton( NULL, hWnd, uiHT == HTMINBUTTON, fDepressed ) ;
741 SetCapture( hWnd ) ;
742
743 while (TRUE)
744 {
745 if (PeekMessage((LPMSG)&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE))
746 {
747 switch (msg.message)
748 {
749 case WM_LBUTTONUP:
750 if (fDepressed)
751 DrawButton( NULL, hWnd, uiHT == HTMINBUTTON, !fDepressed ) ;
752 ReleaseCapture();
753 return PtInRect( lprc, msg.pt ) ;
754
755 case WM_MOUSEMOVE:
756 if (PtInRect( lprc, msg.pt ))
757 {
758 if (!fDepressed)
759 DrawButton( NULL, hWnd, uiHT == HTMINBUTTON, fDepressed = TRUE ) ;
760 }
761 else
762 {
763 if (fDepressed)
764 DrawButton( NULL, hWnd, uiHT == HTMINBUTTON, fDepressed = FALSE ) ;
765 }
766 break;
767 }
768 }
769 }
770
771} // DepressMinMaxButton()
772
773// DrawCaption( HDC hDC, HWND hWnd, LPRECT lprc,
774// BOOL fVert, BOOL fSysMenu, BOOL fActive )
775//
776// This function draws an itsy bitsy caption bar with or
777// without system menu to the dc specified by hDC. The
778// caption is drawn to fit within the lprc RECT and is
779// drawn//withOut/ borders.
780//
781BOOL PASCAL DrawCaption( HDC hDC, HWND hWnd, LPRECT lprc,
782 BOOL fVert, BOOL fSysMenu, BOOL fMin,
783 BOOL fMax, BOOL fActive )
784{
785 RECT rc ;
786 RECT rcCap ;
787 COLORREF rgbCaptionBG ;
788 COLORREF rgbText ;
789 COLORREF rgbWindowFrame ;
790 HBRUSH hbrCaption ;
791 UINT ui ;
792 UINT nCapSize ;
793
794 nCapSize = GETCAPTIONSIZE( hWnd ) ;
795
796 // Get the colors.
797 //
798 rgbWindowFrame = GetSysColor( COLOR_WINDOWFRAME ) ;
799
800 // if we have focus use the active caption color
801 // otherwise use the inactive caption color
802 //
803 if (fActive)
804 {
805 rgbText = GetSysColor( COLOR_CAPTIONTEXT ) ;
806 rgbCaptionBG = GetSysColor( COLOR_ACTIVECAPTION ) ;
807 }
808 else
809 {
810 if (fWin31)
811 rgbText = GetSysColor( COLOR_INACTIVECAPTIONTEXT ) ;
812 else
813 rgbText = GetSysColor( COLOR_CAPTIONTEXT ) ;
814
815 rgbCaptionBG = GetSysColor( COLOR_INACTIVECAPTION ) ;
816 }
817
818 SetBkMode( hDC, TRANSPARENT ) ;
819 SelectObject( hDC, GetStockObject( NULL_BRUSH ) ) ;
820 SelectObject( hDC, GetStockObject( NULL_PEN ) ) ;
821
822 rcCap = *lprc ;
823
824 if (fSysMenu)
825 {
826 if (fVert)
827 rcCap.top += nCapSize ;
828 else
829 rcCap.left += nCapSize ;
830 }
831
832 if (fMax)
833 {
834 if (fVert)
835 rcCap.bottom -= nCapSize ;
836 else
837 rcCap.right -= nCapSize ;
838 }
839
840 if (fMin)
841 {
842 if (fVert)
843 rcCap.bottom -= nCapSize ;
844 else
845 rcCap.right -= nCapSize ;
846 }
847
848 if (fVert)
849 {
850 rc.left = lprc->right - 1 ;
851 rc.right = lprc->right ;
852 rc.top = lprc->top ;
853 rc.bottom = lprc->bottom ;
854 }
855 else
856 {
857 rc.left = lprc->left ;
858 rc.right = lprc->right ;
859 rc.bottom = lprc->bottom ;
860 rc.top = rc.bottom - 1 ;
861 }
862
863 SetBkColor( hDC, rgbWindowFrame ) ;
864 DRAWFASTRECT( hDC, &rc ) ;
865
866 hbrCaption = CreateSolidBrush( rgbCaptionBG ) ;
c4e7c2aa
JS
867 hbrCaption = (HBRUSH) SelectObject( hDC, hbrCaption ) ;
868 SelectObject( hDC, (HPEN) GetStockObject( NULL_PEN ) ) ;
2bda0e17
KB
869 if (fVert)
870 Rectangle( hDC, rcCap.left, rcCap.top, rcCap.right, rcCap.bottom + 1 ) ;
871 else
872 Rectangle( hDC, rcCap.left, rcCap.top, rcCap.right+1, rcCap.bottom ) ;
c4e7c2aa 873 hbrCaption = (HBRUSH) SelectObject( hDC, hbrCaption ) ;
2bda0e17
KB
874 DeleteObject( hbrCaption ) ;
875
876
877 // Draw caption text here. Only do it in 3.1 'cause 3.1 gives
878 // us 'small fonts'.
879 //
880 ui = GetWindowTextLength( hWnd ) ;
881 if (fWin31)
882 {
883 HFONT hFont ;
837e5743 884 LPTSTR lpsz ;
2bda0e17
KB
885 LOGFONT lf ;
886 TEXTMETRIC tm ;
887 int cx ;
888 int cy ;
889 SIZE Size ;
890
837e5743 891 lpsz = (wxChar*)GlobalAllocPtr( GHND, (ui + 2) * sizeof(wxChar) );
fd3f686c 892 if (lpsz)
2bda0e17
KB
893 {
894 UINT nBkMode ;
895
896 GetWindowText( hWnd, lpsz, ui + 1 ) ;
897 nBkMode = SetBkMode( hDC, TRANSPARENT ) ;
898 rgbText = SetTextColor( hDC, rgbText ) ;
899
900 memset( &lf, '\0', sizeof(LOGFONT) ) ;
901
902 lf.lfHeight = -(int)(nCapSize - 3) ;
903 lf.lfCharSet = ANSI_CHARSET ;
904 lf.lfQuality = DEFAULT_QUALITY ;
905 lf.lfClipPrecision = CLIP_LH_ANGLES | CLIP_STROKE_PRECIS ;
906 if (nCapSize >= 20)
907 {
908 lf.lfWeight = FW_BOLD ;
909 }
910
911 if (fVert)
912 {
913 // Can only rotate true type fonts (well, ok, we could
914 // try and use "modern").
223d09f6 915 wxStrcpy( lf.lfFaceName, wxT("Arial") ) ;
2bda0e17
KB
916 lf.lfPitchAndFamily = FF_SWISS | 0x04;
917 lf.lfEscapement = 900 ;
918
919 // Note: The Win 3.1 documentation for CreateFont() say's
920 // that the lfOrientation member is ignored. It appears,
921 // that on Windows 16 3.1 this is true, but when running
922 // as a 16 bit WinApp on WindowsNT 3.1 the lfOrientation
923 // must be set or the text does not rotate!
924 //
925 lf.lfOrientation = 900 ;
926
927 hFont = CreateFontIndirect( &lf ) ;
c4e7c2aa 928 hFont = (HFONT) SelectObject( hDC, hFont ) ;
2bda0e17
KB
929
930 GetTextExtentPoint( hDC, lpsz, ui, &Size ) ;
931 cx = rcCap.bottom - ((rcCap.bottom - rcCap.top - Size.cx) / 2) ;
932 cy = rcCap.left - 1 + ((rcCap.right - rcCap.left - Size.cy) / 2) ;
933
934 // Make sure we got a rotatable font back.
935 //
936 GetTextMetrics( hDC, &tm ) ;
937 if (tm.tmPitchAndFamily & TMPF_VECTOR ||
938 tm.tmPitchAndFamily & TMPF_TRUETYPE)
939 {
940 ExtTextOut( hDC,
941 cy,
942 min( (long)cx, rcCap.bottom),
943 ETO_CLIPPED, &rcCap,
944 lpsz, ui, NULL ) ;
945 }
946
c4e7c2aa 947 hFont = (HFONT) SelectObject( hDC, hFont ) ;
2bda0e17
KB
948 DeleteObject( hFont ) ;
949 }
950 else
951 {
952 // Use small fonts always for the horizontal. Cause it looks
953 // more like "System" than Arial.
954 //
955 lf.lfPitchAndFamily = FF_SWISS ;
956
957 hFont = CreateFontIndirect( &lf ) ;
c4e7c2aa 958 hFont = (HFONT) SelectObject( hDC, hFont ) ;
2bda0e17
KB
959
960 GetTextExtentPoint( hDC, lpsz, ui, &Size ) ;
961 cx = rcCap.left + ((rcCap.right - rcCap.left - Size.cx) / 2) ;
962 cy = rcCap.top + ((rcCap.bottom - rcCap.top - Size.cy) / 2) ;
963
964 // Figger out how big the string is
965 //
966 ExtTextOut( hDC,
967 max( (long)cx, rcCap.left ),
968 cy,
969 ETO_CLIPPED, &rcCap,
970 lpsz, ui, NULL ) ;
971
c4e7c2aa 972 hFont = (HFONT) SelectObject( hDC, hFont ) ;
2bda0e17
KB
973 DeleteObject( hFont ) ;
974 }
975
976 // Unsetup the DC
977 //
978 rgbText = SetTextColor( hDC, rgbText ) ;
979 SetBkMode( hDC, nBkMode ) ;
980
25889d3c 981#ifdef __WIN16__
48c12cb1 982 GlobalFreePtr( (unsigned int)(DWORD) lpsz ) ;
25889d3c 983#else
2bda0e17 984 GlobalFreePtr( lpsz ) ;
25889d3c 985#endif
2bda0e17
KB
986 }
987 }
988
989 if (fSysMenu)
990 DrawSysMenu( hDC, hWnd, FALSE ) ;
991
992 if (fMin)
993 DrawButton( hDC, hWnd, TRUE, FALSE ) ;
994
995 if (fMax)
996 DrawButton( hDC, hWnd, FALSE, FALSE ) ;
997
998 return TRUE ;
999
1000} // DrawCaption()
1001
1002
1003// DrawSysMenu( HDC hDC, hWnd, BOOL fInvert )
1004//
1005// Draws the little system menu icon.
1006//
1007void PASCAL DrawSysMenu( HDC hDC, HWND hWnd, BOOL fInvert )
1008{
1009 RECT rcIcon ;
1010 RECT rcTemp ;
1011 RECT rc ;
1012 COLORREF rgbIconFace ;
1013 COLORREF rgbWindowFrame ;
1014 BOOL fDC ;
1015 UINT nCapSize ;
1016
1017 nCapSize = GETCAPTIONSIZE( hWnd ) ;
1018
1019 if (!hDC)
1020 {
1021 fDC = TRUE ;
1022 hDC = GetWindowDC( hWnd ) ;
1023 }
1024 else
1025 fDC = FALSE ;
1026
1027 if (hDC)
1028 {
1029 rgbIconFace = GetNearestColor( hDC, RGBLTGRAY ) ;
1030 rgbWindowFrame = GetSysColor( COLOR_WINDOWFRAME ) ;
1031
1032 GetIconRect( hWnd, &rcIcon ) ;
1033 GetWindowRect( hWnd, &rc ) ;
1034
1035 OffsetRect( &rcIcon, -rc.left, -rc.top ) ;
1036
1037 rcTemp = rcIcon ;
1038
1039 if (TestWinStyle( hWnd, IBS_VERTCAPTION ))
1040 {
1041 rc = rcIcon ; // separator line
1042 rc.top = ++rc.bottom - 1 ;
1043 }
1044 else
1045 {
1046 rc = rcIcon ; // separator line
1047 rc.left = ++rc.right - 1 ;
1048 }
1049
1050 // Fill
1051 SetBkColor( hDC, rgbIconFace ) ;
1052 DRAWFASTRECT( hDC, &rcTemp ) ;
1053
1054 // Draw separator line
1055 SetBkColor( hDC, rgbWindowFrame ) ;
1056 DRAWFASTRECT( hDC, &rc ) ;
1057
1058 if (nCapSize > 4)
1059 {
1060 // Draw the little horizontal doo-hickey
1061 //
1062 rcTemp.top = rcIcon.top + ((nCapSize-1) / 2) ;
1063 rcTemp.bottom = rcTemp.top + 3 ;
1064 rcTemp.left = rcTemp.left + 3 ;
1065 rcTemp.right = rcTemp.right - 1 ;
1066
1067 SetBkColor( hDC, RGBGRAY ) ;
1068 DRAWFASTRECT( hDC, &rcTemp ) ;
1069
1070 rc = rcTemp ;
1071 OffsetRect( &rc, -1, -1 ) ;
1072 SetBkColor( hDC, RGBBLACK ) ;
1073 DRAWFASTRECT( hDC, &rc ) ;
1074
1075 InflateRect( &rc, -1, -1 ) ;
1076 SetBkColor( hDC, RGBWHITE ) ;
1077 DRAWFASTRECT( hDC, &rc ) ;
1078 }
1079
1080 if (fInvert)
1081 InvertRect( hDC, &rcIcon ) ;
1082
1083 if (fDC)
1084 ReleaseDC( hWnd, hDC ) ;
1085 }
1086
1087} // DrawSysMenu()
1088
1089// DoMenu( HWND hWnd )
1090//
1091// Pops up the system menu.
1092//
1093BOOL PASCAL DoMenu( HWND hWnd )
1094{
1095 HDC hDC ;
1096 RECT rcIcon ;
1097 RECT rc ;
1098 POINT pt ;
1099 HMENU hMenu ;
1100 DWORD dw ;
1101
1102 if (!TestWinStyle(hWnd, WS_SYSMENU))
1103 return FALSE ;
1104
fd3f686c
VZ
1105 hDC = GetWindowDC( hWnd );
1106 if (hDC)
2bda0e17
KB
1107 {
1108 // Invert the icon
1109 //
1110 DrawSysMenu( hDC, hWnd, TRUE ) ;
1111
1112 // Pop up the menu
1113 //
1114 if (TestWinStyle( hWnd, IBS_VERTCAPTION ))
1115 {
1116 pt.x = -1 ;
1117 pt.y = 0 ;
1118 }
1119 else
1120 {
1121 pt.x = 0 ;
1122 pt.y = -1 ;
1123 }
1124
1125 GetIconRect( hWnd, &rcIcon ) ;
1126 GetWindowRect( hWnd, &rc ) ;
1127 OffsetRect( &rcIcon, -rc.left, -rc.top ) ;
1128
1129 ClientToScreen( hWnd, &pt ) ;
1130 ClientToScreen( hWnd, (LPPOINT)&rc.right ) ;
1131
1132 dw = GetWindowLong( hWnd, GWL_STYLE ) ;
1133 SetWindowLong( hWnd, GWL_STYLE, dw | WS_SYSMENU ) ;
1134
1135 hMenu = GetSystemMenu( hWnd, FALSE ) ;
1136 SetupSystemMenu( hWnd, hMenu ) ;
1137
1138 SetWindowLong( hWnd, GWL_STYLE, dw ) ;
1139
1140 TrackPopupMenu( hMenu, 0, //TPM_LEFTALIGN,
1141 pt.x,
1142 pt.y,
1143 0,
1144 hWnd,
1145 &rc ) ;
1146
1147 DrawSysMenu( hDC, hWnd, FALSE ) ;
1148 ReleaseDC( hWnd, hDC ) ;
1149 }
1150 return TRUE ;
1151
1152} // DoMenu()
1153
1154// SetupSystemMenu( HWND hWnd, HMENU hMenu )
1155//
1156// Enables/Disables the appropriate menu items on the
1157// menu passed for the window passed.
1158//
1159void PASCAL SetupSystemMenu( HWND hWnd, HMENU hMenu )
1160{
1161 UINT wMove ;
1162 UINT wSize ;
1163 UINT wMinBox ;
1164 UINT wMaxBox ;
1165 UINT wRestore ;
1166
1167 // Assume all should be grayed.
1168 //
1169 wSize = wMove = wMinBox = wMaxBox = wRestore = MF_GRAYED ;
1170
1171 if (TestWinStyle( hWnd, WS_MAXIMIZEBOX ) || IsIconic( hWnd ))
1172 wMaxBox = MF_ENABLED ;
1173
1174 if (TestWinStyle( hWnd, WS_MINIMIZEBOX ))
1175 wMinBox = MF_ENABLED ;
1176
1177 if (IsZoomed( hWnd ))
1178 wRestore = MF_ENABLED ;
1179
1180 if (TestWinStyle( hWnd, WS_THICKFRAME ) &&
1181 !(IsIconic( hWnd ) || IsZoomed( hWnd )))
1182 wSize = MF_ENABLED ;
1183
1184 if (!IsZoomed( hWnd ) &&
1185 !IsIconic( hWnd ) &&
1186 TestWinStyle( hWnd, WS_CAPTION ) )
1187 wMove = MF_ENABLED ;
1188
1189 EnableMenuItem( hMenu, SC_MOVE, wMove ) ;
1190 EnableMenuItem( hMenu, SC_SIZE, wSize ) ;
1191 EnableMenuItem( hMenu, SC_MINIMIZE, wMinBox ) ;
1192 EnableMenuItem( hMenu, SC_MAXIMIZE, wMaxBox ) ;
1193 EnableMenuItem( hMenu, SC_RESTORE, wRestore ) ;
1194
1195} // SetupSystemMenu()
1196
1197// GetCaptionRect( HWND hWnd, LPRECT lprc )
1198//
1199// calcluales the rectangle of the mini-caption in screen coords.
1200//
1201BOOL PASCAL GetCaptionRect( HWND hWnd, LPRECT lprc )
1202{
1203 UINT nCapSize ;
1204
1205 nCapSize = GETCAPTIONSIZE( hWnd ) ;
1206
1207 if (!HASCAPTION( hWnd ))
1208 {
1209 SetRectEmpty( lprc ) ;
1210 return FALSE ;
1211 }
1212
1213 GetWindowRect( hWnd, lprc ) ;
1214
1215 // the window might have other non-client components like
1216 // borders
1217 //
1218 if (TestWinStyle( hWnd, WS_THICKFRAME ))
1219 {
1220 lprc->left += GetSystemMetrics( SM_CXFRAME ) ;
1221 lprc->top += GetSystemMetrics( SM_CYFRAME ) ;
1222 lprc->right -= GetSystemMetrics( SM_CXFRAME ) ;
1223 lprc->bottom -= GetSystemMetrics( SM_CYFRAME ) ;
1224 }
1225 else
1226 if (TestWinStyle( hWnd, DS_MODALFRAME )) // if it's a dialog box
1227 {
1228 lprc->left += GetSystemMetrics( SM_CXDLGFRAME ) + GetSystemMetrics( SM_CXBORDER ) ;
1229 lprc->top += GetSystemMetrics( SM_CYDLGFRAME ) + GetSystemMetrics( SM_CYBORDER ) ;
1230 lprc->right -= GetSystemMetrics( SM_CXDLGFRAME ) + GetSystemMetrics( SM_CXBORDER ) ;
1231 lprc->bottom -= GetSystemMetrics( SM_CYDLGFRAME ) + GetSystemMetrics( SM_CYBORDER ) ;
1232 }
1233 else
1234 if (TestWinStyle( hWnd, WS_BORDER ))
1235 {
1236 lprc->left += GetSystemMetrics( SM_CXBORDER ) ;
1237 lprc->top += GetSystemMetrics( SM_CYBORDER ) ;
1238 lprc->right -= GetSystemMetrics( SM_CXBORDER ) ;
1239 lprc->bottom -= GetSystemMetrics( SM_CYBORDER ) ;
1240 }
1241
1242 if (TestWinStyle( hWnd, IBS_VERTCAPTION ))
1243 lprc->right = lprc->left + nCapSize ;
1244 else
1245 lprc->bottom = lprc->top + nCapSize ;
1246
1247 return TRUE ;
1248} // GetCaptionRect()
1249
1250// GetIconRect( HWND hWnd, LPRECT lprc )
1251//
1252// Calculates the rect of the icon in screen coordinates.
1253//
1254BOOL PASCAL GetIconRect( HWND hWnd, LPRECT lprc )
1255{
1256 UINT nCapSize ;
1257 BOOL fMenu, fVert ;
1258
1259 fMenu= TestWinStyle( hWnd, WS_SYSMENU ) ;
1260 fVert = TestWinStyle( hWnd, IBS_VERTCAPTION ) ;
1261
1262 if (!GetCaptionRect( hWnd, lprc )) // window coords
1263 return FALSE ;
1264
1265 if (!fMenu)
1266 {
1267 SetRectEmpty( lprc ) ;
1268 return FALSE ;
1269 }
1270
1271 nCapSize = GETCAPTIONSIZE( hWnd ) ;
1272
1273 if (fVert)
1274 lprc->bottom = lprc->top + nCapSize ;
1275 else
1276 lprc->right = lprc->left + nCapSize ;
1277
1278 lprc->bottom-- ;
1279 lprc->right-- ;
1280
1281 return TRUE ;
1282
1283} // GetIconRect()
1284
1285// GetMinButtonRect()
1286//
1287// Calculates the rect of the minimize button in screen
1288// coordinates.
1289//
1290// For horizontal captions, we have the following situation ('Y' is minimize
1291// and '^' is maximize or restore):
1292//
1293// +---------------------------------+
1294// | - | | Y | ^ |
1295// +---------------------------------+
1296// | |.......| <-- This is the width (nSize)
1297//
1298// For vertical captions, we have the following:
1299//
1300// | |
1301// | |
1302// | |
1303// | |
1304// | |
1305// | |
1306// |--|--
1307// | Y| .
1308// |--| . <-- This is the height of the rectangle (nSize)
1309// | ^| .
1310// +--+--
1311//
1312// In order to figure out where the minimize button goes, we first need
1313// to know if there is a maximize button. If so, use GetMaxButtonRect()
1314// to place...
1315//
1316BOOL PASCAL GetMinButtonRect( HWND hWnd, LPRECT lprc )
1317{
1318 if (!TestWinStyle( hWnd, WS_MINIMIZEBOX ))
1319 {
1320 SetRectEmpty( lprc ) ;
1321 return FALSE ;
1322 }
1323
1324 // The minimize button can be in either position 1 or 2. If there
1325 // is a maximize button, it's in position 2.
1326 //
1327 if (TestWinStyle( hWnd, WS_MAXIMIZEBOX ))
1328 return GetButtonRect( hWnd, 2, lprc ) ;
1329 else
1330 return GetButtonRect( hWnd, 1, lprc ) ;
1331}
1332
1333// GetMaxButtonRect()
1334//
1335// Calculates the rect of the maximize button in screen
1336// coordinates.
1337//
1338// The maximize button, if present, is always to the far right
1339// or bottom.
1340//
1341BOOL PASCAL GetMaxButtonRect( HWND hWnd, LPRECT lprc )
1342{
1343 //The maximize button can only be in position 1.
1344 //
1345 if (TestWinStyle( hWnd, WS_MAXIMIZEBOX ))
1346 return GetButtonRect( hWnd, 1, lprc ) ;
1347 else
1348 {
1349 SetRectEmpty( lprc ) ;
1350 return FALSE ;
1351 }
1352}
1353
1354// Get the rect where a button would go.
1355//
1356// This function does not care if it's a min or max, just whether
1357// it is the first from the right/bottom or second from the right/bottom
1358// and so on..
1359//
1360BOOL PASCAL GetButtonRect( HWND hWnd, UINT nPos, LPRECT lprc )
1361{
1362 UINT nSize = 0 ;
1363
1364 if (!GetCaptionRect( hWnd, lprc )) //window coords
1365 return FALSE ;
1366
1367 nSize = GETCAPTIONSIZE( hWnd ) ;
1368
1369 if (TestWinStyle( hWnd, IBS_VERTCAPTION ))
1370 {
1371 lprc->bottom -= nSize * (nPos-1) ;
1372 lprc->top = lprc->bottom - nSize + 1 ;
1373 }
1374 else
1375 {
1376 lprc->right -= nSize * (nPos-1) ;
1377 lprc->left = lprc->right - nSize + 1 ;
1378 }
1379
1380 return TRUE ;
1381} // GetButtonRect()
1382
1383// DrawButton( HDC hDC, HWND hWnd, BOOL fMin, BOOL fDepressed )
1384//
1385// Draws either the min, max, or restore buttons. If fMin is FALSE then it
1386// will draw either the Max or Restore button. If fDepressed is TRUE it will
1387// draw the button in a down state.
1388//
1389void PASCAL DrawButton( HDC hDC, HWND hWnd, BOOL fMin, BOOL fDepressed)
1390{
1391 RECT rcButton ;
1392 RECT rc ;
1393 COLORREF rgbWindowFrame ;
1394 BOOL fDC ;
1395 UINT nCapSize ;
1396 UINT nOffset ;
1397 int n ;
1398
1399 nCapSize = GETCAPTIONSIZE( hWnd ) ;
1400
1401 // If you look at the standard Windows' min/max buttons, you will notice
1402 // that they have two pixels of 'shadow' to the bottom and right. Since
1403 // our buttons can be really, really small, we only want one pixel of
1404 // shadow when they are small. I arbitrarily decided that if the
1405 // caption size is greater than or equal to 20 we will use two
1406 // pixels. That's what this THREASHOLD stuff does.
1407 //
1408 #define THRESHOLD 20
1409 nOffset = (nCapSize >= THRESHOLD) ? 2 : 1 ;
1410
1411 if (!hDC)
1412 {
1413 fDC = TRUE ;
1414 hDC = GetWindowDC( hWnd ) ;
1415 }
1416 else
1417 fDC = FALSE ;
1418
1419 if (hDC)
1420 {
1421 rgbWindowFrame = GetSysColor( COLOR_WINDOWFRAME ) ;
1422
1423 if (fMin)
1424 GetMinButtonRect( hWnd, &rcButton ) ;
1425 else
1426 GetMaxButtonRect( hWnd, &rcButton ) ;
1427
1428 GetWindowRect( hWnd, &rc ) ;
1429 OffsetRect( &rcButton, -rc.left, -rc.top ) ;
1430
1431 rc = rcButton ;
1432 if (TestWinStyle( hWnd, IBS_VERTCAPTION ))
1433 {
1434 rc = rcButton ; //separator line
1435 rc.bottom = --rc.top + 1 ;
1436 rcButton.right-- ;
1437 }
1438 else
1439 {
1440 rc = rcButton ; //separator line
1441 rc.right = --rc.left + 1 ;
1442 rcButton.bottom-- ;
1443 }
1444
1445 //Draw separator line
1446 SetBkColor( hDC, rgbWindowFrame ) ;
1447 DRAWFASTRECT( hDC, &rc ) ;
1448
1449 //Fill
1450 SetBkColor( hDC, RGBLTGRAY ) ;
1451 DRAWFASTRECT( hDC, &rcButton ) ;
1452
1453 if (!fDepressed)
1454 {
1455 //The normal min/max buttons have one pixel on the top and left
1456 //sides for the highlight, and two pixels on the bottom and
1457 //right side for the shadow.
1458 //
1459 //When our caption is 'small' we only use one pixel on all
1460 //sides.
1461 //
1462 SetBkColor( hDC, RGBWHITE ) ;
1463 //Draw left side
1464 rc = rcButton ;
1465 rc.right = rc.left + 1 ;
1466 DRAWFASTRECT( hDC, &rc ) ;
1467
1468 //Draw Top
1469 rc = rcButton ;
1470 rc.bottom = rc.top + 1 ;
1471 DRAWFASTRECT( hDC, &rc ) ;
1472
1473 SetBkColor( hDC, RGBGRAY ) ;
1474 //Draw right side
1475 rc = rcButton ;
1476 rc.left = rc.right - 1 ;
1477 DRAWFASTRECT( hDC, &rc ) ;
1478 if (nCapSize > THRESHOLD)
1479 {
1480 rc.left-- ;
1481 rc.top++ ;
1482 DRAWFASTRECT( hDC, &rc ) ;
1483 }
1484
1485 //Draw bottom
1486 rc = rcButton ;
1487 rc.top = rc.bottom - 1 ;
1488 DRAWFASTRECT( hDC, &rc ) ;
1489 if (nCapSize > THRESHOLD)
1490 {
1491 rc.top-- ;
1492 rc.left++ ;
1493 DRAWFASTRECT( hDC, &rc ) ;
1494 }
1495
1496 rcButton.left++ ;
1497 rcButton.top++ ;
1498 rcButton.right -= nOffset ;
1499 rcButton.bottom -= nOffset ;
1500 }
1501 else
1502 {
1503 //Draw depressed state
1504
1505 SetBkColor( hDC, RGBGRAY ) ;
1506 //Draw left side
1507 rc = rcButton ;
1508 rc.right = rc.left + nOffset ;
1509 DRAWFASTRECT( hDC, &rc ) ;
1510
1511 //Draw Top
1512 rc = rcButton ;
1513 rc.bottom = rc.top + nOffset ;
1514 DRAWFASTRECT( hDC, &rc ) ;
1515
1516 rcButton.left += 2 * nOffset ;
1517 rcButton.top += 2 * nOffset ;
1518 }
1519
1520 // Now draw the arrows. We do not want the
1521 // arrows to grow too large when we have a bigger than
1522 // normal caption, so we restrict their size.
1523 //
1524 // rcButton now represents where we can place our
1525 // arrows.
1526 //
1527 // The maximum size of our arrows (i.e. the width of rcButton)
1528 // has been empirically determined to be SM_CYCAPTION / 2
1529 //
1530 n = ((GetSystemMetrics( SM_CYCAPTION )) / 2) -
1531 (rcButton.right - rcButton.left) ;
1532 if (n < 1)
1533 InflateRect( &rcButton, n/2-1, n/2-1 ) ;
1534
1535 if (fMin)
1536 DrawArrow( hDC, &rcButton, ARROW_DOWN ) ;
1537 else
1538 if (IsZoomed( hWnd ))
1539 {
1540 DrawArrow( hDC, &rcButton, ARROW_RESTORE ) ;
1541 }
1542 else
1543 DrawArrow( hDC, &rcButton, ARROW_UP ) ;
1544
1545 if (fDC)
1546 ReleaseDC( hWnd, hDC ) ;
1547 }
1548
1549} // DrawButton()
1550
1551
1552// DrawArrow
1553//
1554// Draws either a up or down arrow. The arrow is bound by the rectangle
1555//
1556void PASCAL DrawArrow( HDC hdc, LPRECT lprc, UINT uiStyle )
1557{
1558 int row ;
1559 int xTip ;
1560 int yTip ;
1561 RECT rc ;
1562 int nMax = (lprc->bottom - lprc->top) >> 1 ;
1563
1564 SetBkColor( hdc, RGBBLACK ) ;
1565
1566 // We draw the arrow by drawing a series of horizontal lines
1567 //
1568 xTip = lprc->left + ((lprc->right - lprc->left+1) >> 1) ;
1569 switch (uiStyle)
1570 {
1571 case ARROW_UP:
1572 yTip = lprc->top + ((lprc->bottom - lprc->top-1) >> 2) ;
1573 for (row = 1 ; row <= nMax ; row++ )
1574 {
1575 rc.left = xTip - row ;
1576 rc.right = xTip + row - 1 ;
1577 rc.top = yTip + row ;
1578 rc.bottom = rc.top + 1 ;
1579 DRAWFASTRECT( hdc, &rc ) ;
1580 }
1581 break ;
1582
1583 case ARROW_DOWN:
1584 yTip = lprc->bottom - ((lprc->bottom - lprc->top-1) >> 2) ;
1585 for ( row = nMax ; row > 0 ; row-- )
1586 {
1587 rc.left = xTip - row ;
1588 rc.right = xTip + row - 1 ;
1589 rc.top = yTip - row ;
1590 rc.bottom = rc.top + 1 ;
1591 DRAWFASTRECT( hdc, &rc ) ;
1592 }
1593 break ;
1594
1595 case ARROW_RESTORE:
1596 default:
1597 yTip = lprc->top + ((lprc->bottom - lprc->top-1) >> 3) - 2;
1598 for (row = 1 ; row <= nMax ; row++ )
1599 {
1600 rc.left = xTip - row ;
1601 rc.right = xTip + row - 1 ;
1602 rc.top = yTip + row ;
1603 rc.bottom = rc.top + 1 ;
1604 DRAWFASTRECT( hdc, &rc ) ;
1605 }
1606
1607 yTip += (nMax+1) * 2 ;
1608 for ( row = nMax ; row > 0 ; row-- )
1609 {
1610 rc.left = xTip - row ;
1611 rc.right = xTip + row - 1 ;
1612 rc.top = yTip - row ;
1613 rc.bottom = rc.top + 1 ;
1614 DRAWFASTRECT( hdc, &rc ) ;
1615 }
1616 break ;
1617 }
1618
1619} // DrawArrow()
1620
47d67540 1621#endif // wxUSE_ITSY_BITSY
7309b92d
VS
1622
1623#endif // __WIN32__