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