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