1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxMiniFrame
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "minifram.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
31 #include "wx/minifram.h"
32 #include "wx/msw/private.h"
35 #include "wx/msw/gnuwin32/extra.h"
38 #if !USE_SHARED_LIBRARY
39 IMPLEMENT_DYNAMIC_CLASS(wxMiniFrame
, wxFrame
)
42 long wxMiniFrame::MSWDefWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
)
44 if ((GetWindowStyleFlag() & wxTINY_CAPTION_HORIZ
) ||
45 (GetWindowStyleFlag() & wxTINY_CAPTION_VERT
))
46 return ::ibDefWindowProc((HWND
) GetHWND(), nMsg
, wParam
, lParam
);
47 else if ( m_oldWndProc
)
48 return ::CallWindowProc(CASTWNDPROC (FARPROC
) m_oldWndProc
, (HWND
) GetHWND(), (UINT
) nMsg
, (WPARAM
) wParam
, (LPARAM
) lParam
);
50 return ::DefWindowProc((HWND
) GetHWND(), nMsg
, wParam
, lParam
);
53 wxMiniFrame::~wxMiniFrame(void)
57 /////////////////////////////////////////////////////////////////////////
59 // Project: ItsyBitsy window support module
63 // ItsyBitsy is a support module that allows you to create windows
64 // that look and act very much like a popup window witha system
65 // menu and caption bar, except everything is scaled to about 2/3
68 // For documentation on how to use ItsyBits, read the document
72 // 9/27/91 Charlie Kindel (cek/ckindel)
73 // Wrote and documented it.
76 // 2/23/93 cek Added minimize/maximize buttons.
77 // 3/18/93 cek Fixed system menu bug where system menu
78 // popped back up if you clicked on the
79 // icon again while it was up.
80 // 3/24/93 cek More comments. Fixed DS_MODALDIALOG style
81 // problem. Use auto precompiled headers
84 //////////////////////////////////////////////////////////////////////////
100 // Some mildly useful macros for the standard 16 colors
101 #define RGBBLACK RGB(0,0,0)
102 #define RGBRED RGB(128,0,0)
103 #define RGBGREEN RGB(0,128,0)
104 #define RGBBLUE RGB(0,0,128)
106 #define RGBBROWN RGB(128,128,0)
107 #define RGBMAGENTA RGB(128,0,128)
108 #define RGBCYAN RGB(0,128,128)
109 #define RGBLTGRAY RGB(192,192,192)
111 #define RGBGRAY RGB(128,128,128)
112 #define RGBLTRED RGB(255,0,0)
113 #define RGBLTGREEN RGB(0,255,0)
114 #define RGBLTBLUE RGB(0,0,255)
116 #define RGBYELLOW RGB(255,255,0)
117 #define RGBLTMAGENTA RGB(255,0,255)
118 #define RGBLTCYAN RGB(0,255,255)
119 #define RGBWHITE RGB(255,255,255)
122 #ifndef GlobalAllocPtr
123 #define GlobalPtrHandle(lp) \
124 ((HGLOBAL)GlobalHandle(lp))
126 #define GlobalLockPtr(lp) \
127 ((BOOL)GlobalLock(GlobalPtrHandle(lp)))
128 #define GlobalUnlockPtr(lp) \
129 GlobalUnlock(GlobalPtrHandle(lp))
131 #define GlobalAllocPtr(flags, cb) \
132 (GlobalLock(GlobalAlloc((flags), (cb))))
133 #define GlobalReAllocPtr(lp, cbNew, flags) \
134 (GlobalUnlockPtr(lp), GlobalLock(GlobalReAlloc(GlobalPtrHandle(lp) , (cbNew), (flags))))
135 #define GlobalFreePtr(lp) \
136 (GlobalUnlockPtr(lp), (BOOL)GlobalFree(GlobalPtrHandle(lp)))
139 #if defined(__BORLANDC__) || defined(__WATCOMC__)
140 #define max(a,b) (((a) > (b)) ? (a) : (b))
141 #define min(a,b) (((a) < (b)) ? (a) : (b))
144 // CAPTIONXY is the default size of the system menu icon. This
145 // determines the height/width of the caption.
147 // The value that results from the following formula works out
148 // nicely for the veritcal caption on VGA, 8514 (Large Fonts),
149 // 8514 (Small Fonts), XGA (Small Fonts), XGA (Large Fonts),
150 // and TIGA (Small Fonts). It may not be good on other displays.
152 // The problem is that TT fonts turn into bitmap fonts when they
153 // are sized below a certain threshold. The idea is to make the
154 // size of the caption just big enough to get the smallest TT
155 // (scalable) font to fit.
157 #define CAPTIONXY (GetSystemMetrics( SM_CYCAPTION ) / 2 + 1)
159 #define TestWinStyle( hWnd, dwStyleBit ) \
160 (((DWORD)GetWindowLong( hWnd, GWL_STYLE ) & (DWORD)dwStyleBit) ? TRUE : FALSE )
161 #define HASCAPTION( hwnd ) (TestWinStyle( hwnd, IBS_VERTCAPTION ) ||\
162 TestWinStyle( hwnd, IBS_HORZCAPTION ))
164 #define SETCAPTIONSIZE(h,i) (UINT)SetProp(h,"ibSize",(HANDLE)i)
165 #define GETCAPTIONSIZE(h) (UINT)GetProp(h,"ibSize")
166 #define FREECAPTIONSIZE(h) RemoveProp(h,"ibSize")
168 #define SETMENUWASUPFLAG(h,i) (UINT)SetProp(h,"ibFlag",(HANDLE)i)
169 #define GETMENUWASUPFLAG(h) (UINT)GetProp(h,"ibFlag")
170 #define FREEMENUWASUPFLAG(h) RemoveProp(h,"ibFlag")
172 /////////////////////////////////////////////////////////////////////
173 // Little known fact:
174 // ExtTextOut() is the fastest way to draw a filled rectangle
175 // in Windows (if you don't want dithered colors or borders).
177 // Unfortunately there is a bug in the Windows 3.0 8514 driver
178 // in using ExtTextOut() to a memory DC. If you are drawing
179 // to an off screen bitmap, then blitting that bitmap to the
180 // display, do not #define USE_EXTTEXTOUT below.
182 // The following macro (DRAWFASTRECT) draws a filled rectangle
183 // with no border and a solid color. It uses the current back-
184 // ground color as the fill color.
185 //////////////////////////////////////////////////////////////////////
186 #define USE_EXTTEXTOUT
187 #ifdef USE_EXTTEXTOUT
188 #define DRAWFASTRECT(hdc,lprc) ExtTextOut(hdc,0,0,ETO_OPAQUE,lprc,NULL,0,NULL)
190 #define DRAWFASTRECT(hdc,lprc) {\
191 HBRUSH hbr = CreateSolidBrush( GetBkColor( hdc ) ) ;\
192 hbr = SelectObject(hdc, hbr) ;\
193 PatBlt(hdc,(lprc)->left,(lprc)->top,(lprc)->right-(lprc)->left,(lprc)->bottom-(lprc)->top,PATCOPY) ;\
194 hbr = SelectObject(hdc, hbr) ;\
195 DeleteObject( hbr ) ;\
199 // The DrawArrow function takes the following to indicate what
200 // kind of arrow to draw.
204 #define ARROW_RESTORE 2
206 BOOL PASCAL
DepressMinMaxButton( HWND hWnd
, UINT uiHT
, LPRECT
) ;
207 BOOL PASCAL
DoMenu( HWND hWnd
) ;
208 void PASCAL
SetupSystemMenu( HWND hWnd
, HMENU hMenu
) ;
209 BOOL PASCAL
GetCaptionRect( HWND hWnd
, LPRECT lprc
) ;
210 BOOL PASCAL
GetIconRect( HWND hWnd
, LPRECT lprc
) ;
211 BOOL PASCAL
GetButtonRect( HWND hWnd
, UINT nPos
, LPRECT lprc
) ;
212 BOOL PASCAL
GetMinButtonRect( HWND hWnd
, LPRECT lprc
) ;
213 BOOL PASCAL
GetMaxButtonRect( HWND hWnd
, LPRECT lprc
) ;
214 BOOL PASCAL
DrawCaption( HDC hDC
, HWND hWnd
, LPRECT lprc
,
215 BOOL fVert
, BOOL fSysMenu
,
216 BOOL fMin
, BOOL fMax
, BOOL fActive
) ;
217 void PASCAL
DrawSysMenu( HDC hDC
, HWND hWnd
, BOOL fInvert
) ;
218 void PASCAL
DrawButton( HDC hDC
, HWND hWnd
, BOOL fMin
, BOOL fDepressed
) ;
219 void PASCAL
DrawArrow( HDC hdc
, LPRECT lprc
, UINT uiStyle
) ;
225 ///////////////////////////////////////////////////////////////////////
226 // External/Public functions
227 ///////////////////////////////////////////////////////////////////////
229 /////////////////////////////////////////////////////////////////
230 // UINT WINAPI ibGetCaptionSize( HWND hWnd )
234 // Gets the size of the caption (height if horz, width if
239 ///////////////////////////////////////////////////////////////
240 UINT WINAPI
ibGetCaptionSize( HWND hWnd
)
242 return GETCAPTIONSIZE( hWnd
) + 1 ;
243 } // ibSetCaptionSize()
245 /////////////////////////////////////////////////////////////////
246 // UINT WINAPI ibSetCaptionSize( HWND hWnd, UINT nSize )
250 // Changes the size of the caption (height if horz, width if
255 //////////////////////////////////////////////////////////////////
256 UINT WINAPI
ibSetCaptionSize( HWND hWnd
, UINT nSize
)
264 ui
= SETCAPTIONSIZE( hWnd
, nSize
) ;
266 // Once we change the window style, we need a WM_NCCALCRECT
269 // SWP_FRAMECHANGED is not documented in the 3.1 SDK docs,
270 // but *is* in WINDOWS.H.
272 SetWindowPos( hWnd
, NULL
, 0, 0, 0, 0, SWP_FRAMECHANGED
|
273 SWP_NOSIZE
| SWP_NOMOVE
|
274 SWP_NOACTIVATE
| SWP_NOZORDER
) ;
278 } // ibSetCaptionSize()
280 /////////////////////////////////////////////////////////////////
281 // LRESULT WINAPI ibDefWindowProc( HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam )
285 // This function should be called instead of DefWindowProc() for
286 // windows that want to have itsybitsy captions.
290 //////////////////////////////////////////////////////////////////
291 LRESULT WINAPI
ibDefWindowProc( HWND hWnd
, UINT uiMsg
, WPARAM wParam
, LPARAM lParam
)
300 // was hit then pop up the menu
302 if (HASCAPTION( hWnd
) && (wParam
== VK_SPACE
))
316 DWORD dw
= GetWindowLong( hWnd
, GWL_STYLE
) ;
318 // Fool DefWindowProc into thinking we do not have
319 // a system menu. Otherwise it will try to
322 SetWindowLong( hWnd
, GWL_STYLE
, dw
&~WS_SYSMENU
) ;
323 lRet
= DefWindowProc( hWnd
, uiMsg
, wParam
, lParam
) ;
324 SetWindowLong( hWnd
, GWL_STYLE
, dw
) ;
330 // The menu that is poped up for the system menu with
331 // TrackPopupMenu() sends it's notifications as WM_COMMAND
332 // messages. We need to translate these into
333 // WM_SYSCOMMAND messages. All standard WM_SYSCOMMAND
334 // ids are greater than 0xF000.
336 // This could be a possible cause of confusion if the
337 // itsybitsy window had children that used SC_MOVE or SC_CLOSE
338 // as their IDs. Take note and be careful.
340 // Also, because ibDefWindowProc looks at WM_COMMAND messages,
341 // you will need to be careful to call ibDefWindowProc() for
342 // any wm_command messages that you would normally ignore.
343 // Otherwise the system menu won't work.
345 if (wParam
>= 0xF000)
346 // Call PostMessage() here instead of SendMessage!
348 // Our menu was created by TrackPopupMenu(). TPM() does
349 // not return until after the menu has been destroyed
350 // (and thus the command associated with the menu selection
351 // sent). Therefore when we get here, we are still
352 // *inside* TPM(). If we Send WM_SYSCOMMAND, SC_CLOSE
353 // to the window, the window will be destroyed before
354 // TPM() returns to our code within DoMenu() below. Wel...
355 // We do stuff with the window handle after DoMenu()
356 // returns (namely GetProp()). Since the window has
357 // been destroyed,this is bad.
358 PostMessage( hWnd
, WM_SYSCOMMAND
, wParam
, lParam
) ;
360 return DefWindowProc( hWnd
, uiMsg
, wParam
, lParam
) ;
362 case WM_GETMINMAXINFO
:
364 nCapSize
= GETCAPTIONSIZE( hWnd
) ;
365 if (HASCAPTION( hWnd
) && TestWinStyle( hWnd
, WS_THICKFRAME
))
367 LPPOINT lppt
= (LPPOINT
)lParam
;
372 int cx
, cy
; // window frame/border width
374 if (TestWinStyle( hWnd
, WS_THICKFRAME
))
376 cx
= GetSystemMetrics( SM_CXFRAME
) ;
377 cy
= GetSystemMetrics( SM_CYFRAME
) ;
380 if (TestWinStyle(hWnd
, WS_BORDER
))
382 cx
= GetSystemMetrics( SM_CXBORDER
) ;
383 cy
= GetSystemMetrics( SM_CYBORDER
) ;
386 GetIconRect( hWnd
, &rcMenu
) ;
387 GetMinButtonRect( hWnd
, &rcMin
) ;
388 GetMaxButtonRect( hWnd
, &rcMax
) ;
389 nX
= (rcMenu
.right
-rcMenu
.left
) +
390 (rcMin
.right
-rcMin
.left
) +
391 (rcMin
.right
-rcMin
.left
) ;
394 if (TestWinStyle( hWnd
, IBS_VERTCAPTION
) )
396 lppt
[3].x
= nCapSize
+ cx
* 2 - 1 ;
397 lppt
[3].y
= nX
+ (2* nCapSize
) ;
401 lppt
[3].x
= nX
+ (2* nCapSize
) ;
402 lppt
[3].y
= nCapSize
+ cy
* 2 - 1 ;
405 return DefWindowProc( hWnd
, uiMsg
, wParam
, lParam
) ;
409 /////////////////////////////////////////////////////////////////////
410 // Non-client area messages. These are used to allow the
411 // minature caption bar to be handled correctly.
417 // We have two things that we need to store somewhere:
418 // 1) The caption height (width).
419 // and 2) A flag indicating whether the sysmenu was
422 // CAPTIONXY is a macro that calls GetSystemMetrics.
424 SETCAPTIONSIZE( hWnd
, CAPTIONXY
) ;
426 // Set our flag that tells us whether the system menu was
429 SETMENUWASUPFLAG( hWnd
, FALSE
) ;
431 // Are we in 3.1? If so we have some neat features
432 // we can use like rotated TrueType fonts.
434 fWin31
= (BOOL
)(LOWORD( GetVersion() ) >= 0x030A) ;
436 // If IBS_????CAPTION was specified and the WS_DLGFRAME (or
437 // WS_DLGFRAME 'cause it == WS_CAPTION | WS_BORDER)
438 // was specified the creator made a mistake. Things get really
439 // ugly if DefWindowProc sees WS_DLGFRAME, so we strip
440 // the WS_DLGFRAME part off!
442 dwStyle
= GetWindowLong( hWnd
, GWL_STYLE
) ;
443 if ((dwStyle
& IBS_VERTCAPTION
|| dwStyle
& IBS_HORZCAPTION
) &&
444 dwStyle
& WS_DLGFRAME
)
446 dwStyle
&= (DWORD
)~WS_DLGFRAME
;
447 SetWindowLong( hWnd
, GWL_STYLE
, dwStyle
) ;
450 return DefWindowProc( hWnd
, uiMsg
, wParam
, lParam
) ;
453 // We store the caption size in a window prop. so we
454 // must remove props.
456 FREECAPTIONSIZE( hWnd
) ;
457 FREEMENUWASUPFLAG( hWnd
) ;
458 return DefWindowProc( hWnd
, uiMsg
, wParam
, lParam
) ;
461 // This is sent when the window manager wants to find out
462 // how big our client area is to be. If we have a mini-caption
463 // then we trap this message and calculate the cleint area rect,
464 // which is the client area rect calculated by DefWindowProc()
465 // minus the width/height of the mini-caption bar
467 lRet
= DefWindowProc( hWnd
, uiMsg
, wParam
, lParam
) ;
468 if (!IsIconic( hWnd
) && HASCAPTION( hWnd
))
470 nCapSize
= GETCAPTIONSIZE( hWnd
) ;
472 if (TestWinStyle( hWnd
, IBS_VERTCAPTION
) )
473 ((LPRECT
)lParam
)->left
+= nCapSize
;
475 ((LPRECT
)lParam
)->top
+= nCapSize
;
480 // This message is sent whenever the mouse moves over us.
481 // We will depend on DefWindowProc for everything unless
482 // there is a mini-caption, in which case we will
483 // return HTCAPTION or HTSYSMENU. When the user clicks
484 // or double clicks, NC_LBUTTON/ message are sent with
485 // wParam equal to what we return here.
486 // This means that this is an ideal place to figure out
489 // let defwindowproc handle the standard borders etc...
491 lRet
= DefWindowProc( hWnd
, uiMsg
, wParam
, lParam
) ;
492 if (!IsIconic( hWnd
) && HASCAPTION( hWnd
) && lRet
== HTNOWHERE
)
500 nCapSize
= GETCAPTIONSIZE( hWnd
) ;
502 // if DefWindowProc returned HTCAPTION then we have to
503 // refine the area and return HTSYSMENU if appropriate
505 pt
.x
= LOWORD( lParam
) ;
506 pt
.y
= HIWORD( lParam
) ;
508 GetCaptionRect( hWnd
, &rc
) ; // window coords
509 if (PtInRect( &rc
, pt
))
513 // rely on the fact that Get???Rect() return an invalid
514 // (empty) rectangle if the menu/buttons don't exist
516 GetIconRect( hWnd
, &rcMenu
) ;
517 GetMinButtonRect( hWnd
, &rcMinButton
) ;
518 GetMaxButtonRect( hWnd
, &rcMaxButton
) ;
520 if (PtInRect( &rcMenu
, pt
))
523 if (PtInRect( &rcMinButton
, pt
))
526 if (PtInRect( &rcMaxButton
, pt
))
530 if (lRet
!= HTSYSMENU
)
531 SETMENUWASUPFLAG( hWnd
, FALSE
) ;
534 case WM_NCLBUTTONDBLCLK
:
535 // Windows recieve WM_NC?BUTTONDBLCLK messages whether they
536 // have CS_DBLCLKS or not. We watch for one of these
537 // to see if the user double clicked on the system menu (to
538 // close the window) or on the caption (to maximize the window).
540 if (!IsIconic( hWnd
) && HASCAPTION( hWnd
) && wParam
== HTSYSMENU
)
542 SendMessage( hWnd
, WM_CLOSE
, 0, 0L ) ;
545 return DefWindowProc( hWnd
, uiMsg
, wParam
, lParam
) ;
547 case WM_NCLBUTTONDOWN
:
551 // If we're iconic or we don't have a caption then
552 // DefWindowProc will do the job just fine.
554 if (IsIconic( hWnd
) || !HASCAPTION( hWnd
))
555 return DefWindowProc( hWnd
, uiMsg
, wParam
, lParam
) ;
557 // Here's were we handle the system menu, the min and max buttons.
558 // If you wanted to change the behavior of the min/max buttons
559 // do something like swap tool palettes or something, you
560 // would change the SendMessage() calls below.
565 if (GETMENUWASUPFLAG( hWnd
) == FALSE
&& DoMenu( hWnd
))
566 SETMENUWASUPFLAG( hWnd
, TRUE
) ;
568 SETMENUWASUPFLAG( hWnd
, FALSE
) ;
572 GetMinButtonRect( hWnd
, &rc
) ;
573 // Note that DepressMinMaxButton() goes into
574 // a PeekMessage() loop waiting for the mouse
577 if (DepressMinMaxButton( hWnd
, wParam
, &rc
))
578 SendMessage( hWnd
, WM_SYSCOMMAND
, SC_MINIMIZE
, lParam
) ;
582 GetMaxButtonRect( hWnd
, &rc
) ;
583 // Note that DepressMinMaxButton() goes into
584 // a PeekMessage() loop waiting for the mouse
587 if (DepressMinMaxButton( hWnd
, wParam
, &rc
))
590 SendMessage( hWnd
, WM_SYSCOMMAND
, SC_RESTORE
, lParam
) ;
592 SendMessage( hWnd
, WM_SYSCOMMAND
, SC_MAXIMIZE
, lParam
) ;
597 // Well, it appears as though the user clicked somewhere other
598 // than the buttons. We let DefWindowProc do it's magic.
599 // This is where things like dragging and sizing the
602 return DefWindowProc( hWnd
, uiMsg
, wParam
, lParam
) ;
609 if (IsIconic( hWnd
))
610 return DefWindowProc( hWnd
, uiMsg
, wParam
, lParam
) ;
612 // Paint the non-client area here. We will call DefWindowProc
613 // after we are done so it can paint the borders and so
616 lRet
= DefWindowProc( hWnd
, uiMsg
, wParam
, lParam
) ;
617 if (HASCAPTION( hWnd
))
621 HDC hDC
= GetWindowDC( hWnd
) ;
624 GetCaptionRect( hWnd
, &rcCap
) ; // Convert to window coords
625 GetWindowRect( hWnd
, &rc
) ;
626 OffsetRect( &rcCap
, -rc
.left
, -rc
.top
) ;
628 if (uiMsg
== WM_NCPAINT
)
629 fActive
= (hWnd
== GetActiveWindow()) ;
633 DrawCaption( hDC
, hWnd
, &rcCap
,
634 TestWinStyle(hWnd
, IBS_VERTCAPTION
),
635 TestWinStyle(hWnd
, WS_SYSMENU
),
636 TestWinStyle(hWnd
, WS_MINIMIZEBOX
),
637 TestWinStyle(hWnd
, WS_MAXIMIZEBOX
),
640 ReleaseDC( hWnd
, hDC
) ;
646 return DefWindowProc( hWnd
, uiMsg
, wParam
, lParam
) ;
651 } // ibDefWindowProc()
653 // ibAdjustWindowRect( HWND hWnd, LPRECT lprc )
655 // Does the same thing as the USER function AdjustWindowRect(),
656 // but knows about itsybitsy windows. AdjustWindowRect() is
657 // bogus for stuff like this.
659 void WINAPI
ibAdjustWindowRect( HWND hWnd
, LPRECT lprc
)
661 short cx
= 0, cy
= 0 ;
664 nCapSize
= GETCAPTIONSIZE( hWnd
) ;
666 // First check Windows's styles, then our own.
668 if (TestWinStyle( hWnd
, WS_THICKFRAME
))
670 cx
= GetSystemMetrics( SM_CXFRAME
) ;
671 cy
= GetSystemMetrics( SM_CYFRAME
) ;
674 if (TestWinStyle(hWnd
, DS_MODALFRAME
))
676 cx
= GetSystemMetrics( SM_CXDLGFRAME
) + GetSystemMetrics( SM_CXBORDER
) ;
677 cy
= GetSystemMetrics( SM_CYDLGFRAME
) + GetSystemMetrics( SM_CYBORDER
) ;
680 if (TestWinStyle(hWnd
, WS_BORDER
))
682 cx
= GetSystemMetrics( SM_CXBORDER
) ;
683 cy
= GetSystemMetrics( SM_CYBORDER
) ;
686 InflateRect( lprc
, cx
, cy
) ;
688 if (TestWinStyle( hWnd
, IBS_VERTCAPTION
))
689 lprc
->left
-= nCapSize
;
691 if (TestWinStyle( hWnd
, IBS_HORZCAPTION
))
692 lprc
->top
-= nCapSize
;
694 } // ibAdjustWindowRect()
697 ///////////////////////////////////////////////////////////////////////
698 // Internal functions
699 ///////////////////////////////////////////////////////////////////////
701 // DepressMinMaxButton()
703 // This function is called when the user has pressed either the min or
704 // max button (i.e. WM_NCLBUTTONDOWN). We go into a Peekmessage() loop,
705 // waiting for the mouse to come back up. This allows us to make the
706 // button change up/down state like a real button does.
708 // lprc points to the rectangle that describes the button the
709 // user has clicked on.
711 BOOL PASCAL
DepressMinMaxButton( HWND hWnd
, UINT uiHT
, LPRECT lprc
)
713 BOOL fDepressed
= TRUE
;
716 // Draw button in down state
717 DrawButton( NULL
, hWnd
, uiHT
== HTMINBUTTON
, fDepressed
) ;
722 if (PeekMessage((LPMSG
)&msg
, NULL
, WM_MOUSEFIRST
, WM_MOUSELAST
, PM_REMOVE
))
728 DrawButton( NULL
, hWnd
, uiHT
== HTMINBUTTON
, !fDepressed
) ;
730 return PtInRect( lprc
, msg
.pt
) ;
733 if (PtInRect( lprc
, msg
.pt
))
736 DrawButton( NULL
, hWnd
, uiHT
== HTMINBUTTON
, fDepressed
= TRUE
) ;
741 DrawButton( NULL
, hWnd
, uiHT
== HTMINBUTTON
, fDepressed
= FALSE
) ;
748 } // DepressMinMaxButton()
750 // DrawCaption( HDC hDC, HWND hWnd, LPRECT lprc,
751 // BOOL fVert, BOOL fSysMenu, BOOL fActive )
753 // This function draws an itsy bitsy caption bar with or
754 // without system menu to the dc specified by hDC. The
755 // caption is drawn to fit within the lprc RECT and is
756 // drawn//withOut/ borders.
758 BOOL PASCAL
DrawCaption( HDC hDC
, HWND hWnd
, LPRECT lprc
,
759 BOOL fVert
, BOOL fSysMenu
, BOOL fMin
,
760 BOOL fMax
, BOOL fActive
)
764 COLORREF rgbCaptionBG
;
766 COLORREF rgbWindowFrame
;
771 nCapSize
= GETCAPTIONSIZE( hWnd
) ;
775 rgbWindowFrame
= GetSysColor( COLOR_WINDOWFRAME
) ;
777 // if we have focus use the active caption color
778 // otherwise use the inactive caption color
782 rgbText
= GetSysColor( COLOR_CAPTIONTEXT
) ;
783 rgbCaptionBG
= GetSysColor( COLOR_ACTIVECAPTION
) ;
788 rgbText
= GetSysColor( COLOR_INACTIVECAPTIONTEXT
) ;
790 rgbText
= GetSysColor( COLOR_CAPTIONTEXT
) ;
792 rgbCaptionBG
= GetSysColor( COLOR_INACTIVECAPTION
) ;
795 SetBkMode( hDC
, TRANSPARENT
) ;
796 SelectObject( hDC
, GetStockObject( NULL_BRUSH
) ) ;
797 SelectObject( hDC
, GetStockObject( NULL_PEN
) ) ;
804 rcCap
.top
+= nCapSize
;
806 rcCap
.left
+= nCapSize
;
812 rcCap
.bottom
-= nCapSize
;
814 rcCap
.right
-= nCapSize
;
820 rcCap
.bottom
-= nCapSize
;
822 rcCap
.right
-= nCapSize
;
827 rc
.left
= lprc
->right
- 1 ;
828 rc
.right
= lprc
->right
;
830 rc
.bottom
= lprc
->bottom
;
834 rc
.left
= lprc
->left
;
835 rc
.right
= lprc
->right
;
836 rc
.bottom
= lprc
->bottom
;
837 rc
.top
= rc
.bottom
- 1 ;
840 SetBkColor( hDC
, rgbWindowFrame
) ;
841 DRAWFASTRECT( hDC
, &rc
) ;
843 hbrCaption
= CreateSolidBrush( rgbCaptionBG
) ;
844 hbrCaption
= SelectObject( hDC
, hbrCaption
) ;
845 SelectObject( hDC
, GetStockObject( NULL_PEN
) ) ;
847 Rectangle( hDC
, rcCap
.left
, rcCap
.top
, rcCap
.right
, rcCap
.bottom
+ 1 ) ;
849 Rectangle( hDC
, rcCap
.left
, rcCap
.top
, rcCap
.right
+1, rcCap
.bottom
) ;
850 hbrCaption
= SelectObject( hDC
, hbrCaption
) ;
851 DeleteObject( hbrCaption
) ;
854 // Draw caption text here. Only do it in 3.1 'cause 3.1 gives
857 ui
= GetWindowTextLength( hWnd
) ;
868 if ((lpsz
= (char*)GlobalAllocPtr( GHND
, ui
+ 2 )))
872 GetWindowText( hWnd
, lpsz
, ui
+ 1 ) ;
873 nBkMode
= SetBkMode( hDC
, TRANSPARENT
) ;
874 rgbText
= SetTextColor( hDC
, rgbText
) ;
876 memset( &lf
, '\0', sizeof(LOGFONT
) ) ;
878 lf
.lfHeight
= -(int)(nCapSize
- 3) ;
879 lf
.lfCharSet
= ANSI_CHARSET
;
880 lf
.lfQuality
= DEFAULT_QUALITY
;
881 lf
.lfClipPrecision
= CLIP_LH_ANGLES
| CLIP_STROKE_PRECIS
;
884 lf
.lfWeight
= FW_BOLD
;
889 // Can only rotate true type fonts (well, ok, we could
890 // try and use "modern").
891 strcpy( lf
.lfFaceName
, "Arial" ) ;
892 lf
.lfPitchAndFamily
= FF_SWISS
| 0x04;
893 lf
.lfEscapement
= 900 ;
895 // Note: The Win 3.1 documentation for CreateFont() say's
896 // that the lfOrientation member is ignored. It appears,
897 // that on Windows 16 3.1 this is true, but when running
898 // as a 16 bit WinApp on WindowsNT 3.1 the lfOrientation
899 // must be set or the text does not rotate!
901 lf
.lfOrientation
= 900 ;
903 hFont
= CreateFontIndirect( &lf
) ;
904 hFont
= SelectObject( hDC
, hFont
) ;
906 GetTextExtentPoint( hDC
, lpsz
, ui
, &Size
) ;
907 cx
= rcCap
.bottom
- ((rcCap
.bottom
- rcCap
.top
- Size
.cx
) / 2) ;
908 cy
= rcCap
.left
- 1 + ((rcCap
.right
- rcCap
.left
- Size
.cy
) / 2) ;
910 // Make sure we got a rotatable font back.
912 GetTextMetrics( hDC
, &tm
) ;
913 if (tm
.tmPitchAndFamily
& TMPF_VECTOR
||
914 tm
.tmPitchAndFamily
& TMPF_TRUETYPE
)
918 min( (long)cx
, rcCap
.bottom
),
923 hFont
= SelectObject( hDC
, hFont
) ;
924 DeleteObject( hFont
) ;
928 // Use small fonts always for the horizontal. Cause it looks
929 // more like "System" than Arial.
931 lf
.lfPitchAndFamily
= FF_SWISS
;
933 hFont
= CreateFontIndirect( &lf
) ;
934 hFont
= SelectObject( hDC
, hFont
) ;
936 GetTextExtentPoint( hDC
, lpsz
, ui
, &Size
) ;
937 cx
= rcCap
.left
+ ((rcCap
.right
- rcCap
.left
- Size
.cx
) / 2) ;
938 cy
= rcCap
.top
+ ((rcCap
.bottom
- rcCap
.top
- Size
.cy
) / 2) ;
940 // Figger out how big the string is
943 max( (long)cx
, rcCap
.left
),
948 hFont
= SelectObject( hDC
, hFont
) ;
949 DeleteObject( hFont
) ;
954 rgbText
= SetTextColor( hDC
, rgbText
) ;
955 SetBkMode( hDC
, nBkMode
) ;
957 GlobalFreePtr( lpsz
) ;
962 DrawSysMenu( hDC
, hWnd
, FALSE
) ;
965 DrawButton( hDC
, hWnd
, TRUE
, FALSE
) ;
968 DrawButton( hDC
, hWnd
, FALSE
, FALSE
) ;
975 // DrawSysMenu( HDC hDC, hWnd, BOOL fInvert )
977 // Draws the little system menu icon.
979 void PASCAL
DrawSysMenu( HDC hDC
, HWND hWnd
, BOOL fInvert
)
984 COLORREF rgbIconFace
;
985 COLORREF rgbWindowFrame
;
989 nCapSize
= GETCAPTIONSIZE( hWnd
) ;
994 hDC
= GetWindowDC( hWnd
) ;
1001 rgbIconFace
= GetNearestColor( hDC
, RGBLTGRAY
) ;
1002 rgbWindowFrame
= GetSysColor( COLOR_WINDOWFRAME
) ;
1004 GetIconRect( hWnd
, &rcIcon
) ;
1005 GetWindowRect( hWnd
, &rc
) ;
1007 OffsetRect( &rcIcon
, -rc
.left
, -rc
.top
) ;
1011 if (TestWinStyle( hWnd
, IBS_VERTCAPTION
))
1013 rc
= rcIcon
; // separator line
1014 rc
.top
= ++rc
.bottom
- 1 ;
1018 rc
= rcIcon
; // separator line
1019 rc
.left
= ++rc
.right
- 1 ;
1023 SetBkColor( hDC
, rgbIconFace
) ;
1024 DRAWFASTRECT( hDC
, &rcTemp
) ;
1026 // Draw separator line
1027 SetBkColor( hDC
, rgbWindowFrame
) ;
1028 DRAWFASTRECT( hDC
, &rc
) ;
1032 // Draw the little horizontal doo-hickey
1034 rcTemp
.top
= rcIcon
.top
+ ((nCapSize
-1) / 2) ;
1035 rcTemp
.bottom
= rcTemp
.top
+ 3 ;
1036 rcTemp
.left
= rcTemp
.left
+ 3 ;
1037 rcTemp
.right
= rcTemp
.right
- 1 ;
1039 SetBkColor( hDC
, RGBGRAY
) ;
1040 DRAWFASTRECT( hDC
, &rcTemp
) ;
1043 OffsetRect( &rc
, -1, -1 ) ;
1044 SetBkColor( hDC
, RGBBLACK
) ;
1045 DRAWFASTRECT( hDC
, &rc
) ;
1047 InflateRect( &rc
, -1, -1 ) ;
1048 SetBkColor( hDC
, RGBWHITE
) ;
1049 DRAWFASTRECT( hDC
, &rc
) ;
1053 InvertRect( hDC
, &rcIcon
) ;
1056 ReleaseDC( hWnd
, hDC
) ;
1061 // DoMenu( HWND hWnd )
1063 // Pops up the system menu.
1065 BOOL PASCAL
DoMenu( HWND hWnd
)
1074 if (!TestWinStyle(hWnd
, WS_SYSMENU
))
1077 if ((hDC
= GetWindowDC( hWnd
)))
1081 DrawSysMenu( hDC
, hWnd
, TRUE
) ;
1085 if (TestWinStyle( hWnd
, IBS_VERTCAPTION
))
1096 GetIconRect( hWnd
, &rcIcon
) ;
1097 GetWindowRect( hWnd
, &rc
) ;
1098 OffsetRect( &rcIcon
, -rc
.left
, -rc
.top
) ;
1100 ClientToScreen( hWnd
, &pt
) ;
1101 ClientToScreen( hWnd
, (LPPOINT
)&rc
.right
) ;
1103 dw
= GetWindowLong( hWnd
, GWL_STYLE
) ;
1104 SetWindowLong( hWnd
, GWL_STYLE
, dw
| WS_SYSMENU
) ;
1106 hMenu
= GetSystemMenu( hWnd
, FALSE
) ;
1107 SetupSystemMenu( hWnd
, hMenu
) ;
1109 SetWindowLong( hWnd
, GWL_STYLE
, dw
) ;
1111 TrackPopupMenu( hMenu
, 0, //TPM_LEFTALIGN,
1118 DrawSysMenu( hDC
, hWnd
, FALSE
) ;
1119 ReleaseDC( hWnd
, hDC
) ;
1125 // SetupSystemMenu( HWND hWnd, HMENU hMenu )
1127 // Enables/Disables the appropriate menu items on the
1128 // menu passed for the window passed.
1130 void PASCAL
SetupSystemMenu( HWND hWnd
, HMENU hMenu
)
1138 // Assume all should be grayed.
1140 wSize
= wMove
= wMinBox
= wMaxBox
= wRestore
= MF_GRAYED
;
1142 if (TestWinStyle( hWnd
, WS_MAXIMIZEBOX
) || IsIconic( hWnd
))
1143 wMaxBox
= MF_ENABLED
;
1145 if (TestWinStyle( hWnd
, WS_MINIMIZEBOX
))
1146 wMinBox
= MF_ENABLED
;
1148 if (IsZoomed( hWnd
))
1149 wRestore
= MF_ENABLED
;
1151 if (TestWinStyle( hWnd
, WS_THICKFRAME
) &&
1152 !(IsIconic( hWnd
) || IsZoomed( hWnd
)))
1153 wSize
= MF_ENABLED
;
1155 if (!IsZoomed( hWnd
) &&
1156 !IsIconic( hWnd
) &&
1157 TestWinStyle( hWnd
, WS_CAPTION
) )
1158 wMove
= MF_ENABLED
;
1160 EnableMenuItem( hMenu
, SC_MOVE
, wMove
) ;
1161 EnableMenuItem( hMenu
, SC_SIZE
, wSize
) ;
1162 EnableMenuItem( hMenu
, SC_MINIMIZE
, wMinBox
) ;
1163 EnableMenuItem( hMenu
, SC_MAXIMIZE
, wMaxBox
) ;
1164 EnableMenuItem( hMenu
, SC_RESTORE
, wRestore
) ;
1166 } // SetupSystemMenu()
1168 // GetCaptionRect( HWND hWnd, LPRECT lprc )
1170 // calcluales the rectangle of the mini-caption in screen coords.
1172 BOOL PASCAL
GetCaptionRect( HWND hWnd
, LPRECT lprc
)
1176 nCapSize
= GETCAPTIONSIZE( hWnd
) ;
1178 if (!HASCAPTION( hWnd
))
1180 SetRectEmpty( lprc
) ;
1184 GetWindowRect( hWnd
, lprc
) ;
1186 // the window might have other non-client components like
1189 if (TestWinStyle( hWnd
, WS_THICKFRAME
))
1191 lprc
->left
+= GetSystemMetrics( SM_CXFRAME
) ;
1192 lprc
->top
+= GetSystemMetrics( SM_CYFRAME
) ;
1193 lprc
->right
-= GetSystemMetrics( SM_CXFRAME
) ;
1194 lprc
->bottom
-= GetSystemMetrics( SM_CYFRAME
) ;
1197 if (TestWinStyle( hWnd
, DS_MODALFRAME
)) // if it's a dialog box
1199 lprc
->left
+= GetSystemMetrics( SM_CXDLGFRAME
) + GetSystemMetrics( SM_CXBORDER
) ;
1200 lprc
->top
+= GetSystemMetrics( SM_CYDLGFRAME
) + GetSystemMetrics( SM_CYBORDER
) ;
1201 lprc
->right
-= GetSystemMetrics( SM_CXDLGFRAME
) + GetSystemMetrics( SM_CXBORDER
) ;
1202 lprc
->bottom
-= GetSystemMetrics( SM_CYDLGFRAME
) + GetSystemMetrics( SM_CYBORDER
) ;
1205 if (TestWinStyle( hWnd
, WS_BORDER
))
1207 lprc
->left
+= GetSystemMetrics( SM_CXBORDER
) ;
1208 lprc
->top
+= GetSystemMetrics( SM_CYBORDER
) ;
1209 lprc
->right
-= GetSystemMetrics( SM_CXBORDER
) ;
1210 lprc
->bottom
-= GetSystemMetrics( SM_CYBORDER
) ;
1213 if (TestWinStyle( hWnd
, IBS_VERTCAPTION
))
1214 lprc
->right
= lprc
->left
+ nCapSize
;
1216 lprc
->bottom
= lprc
->top
+ nCapSize
;
1219 } // GetCaptionRect()
1221 // GetIconRect( HWND hWnd, LPRECT lprc )
1223 // Calculates the rect of the icon in screen coordinates.
1225 BOOL PASCAL
GetIconRect( HWND hWnd
, LPRECT lprc
)
1230 fMenu
= TestWinStyle( hWnd
, WS_SYSMENU
) ;
1231 fVert
= TestWinStyle( hWnd
, IBS_VERTCAPTION
) ;
1233 if (!GetCaptionRect( hWnd
, lprc
)) // window coords
1238 SetRectEmpty( lprc
) ;
1242 nCapSize
= GETCAPTIONSIZE( hWnd
) ;
1245 lprc
->bottom
= lprc
->top
+ nCapSize
;
1247 lprc
->right
= lprc
->left
+ nCapSize
;
1256 // GetMinButtonRect()
1258 // Calculates the rect of the minimize button in screen
1261 // For horizontal captions, we have the following situation ('Y' is minimize
1262 // and '^' is maximize or restore):
1264 // +---------------------------------+
1266 // +---------------------------------+
1267 // | |.......| <-- This is the width (nSize)
1269 // For vertical captions, we have the following:
1279 // |--| . <-- This is the height of the rectangle (nSize)
1283 // In order to figure out where the minimize button goes, we first need
1284 // to know if there is a maximize button. If so, use GetMaxButtonRect()
1287 BOOL PASCAL
GetMinButtonRect( HWND hWnd
, LPRECT lprc
)
1289 if (!TestWinStyle( hWnd
, WS_MINIMIZEBOX
))
1291 SetRectEmpty( lprc
) ;
1295 // The minimize button can be in either position 1 or 2. If there
1296 // is a maximize button, it's in position 2.
1298 if (TestWinStyle( hWnd
, WS_MAXIMIZEBOX
))
1299 return GetButtonRect( hWnd
, 2, lprc
) ;
1301 return GetButtonRect( hWnd
, 1, lprc
) ;
1304 // GetMaxButtonRect()
1306 // Calculates the rect of the maximize button in screen
1309 // The maximize button, if present, is always to the far right
1312 BOOL PASCAL
GetMaxButtonRect( HWND hWnd
, LPRECT lprc
)
1314 //The maximize button can only be in position 1.
1316 if (TestWinStyle( hWnd
, WS_MAXIMIZEBOX
))
1317 return GetButtonRect( hWnd
, 1, lprc
) ;
1320 SetRectEmpty( lprc
) ;
1325 // Get the rect where a button would go.
1327 // This function does not care if it's a min or max, just whether
1328 // it is the first from the right/bottom or second from the right/bottom
1331 BOOL PASCAL
GetButtonRect( HWND hWnd
, UINT nPos
, LPRECT lprc
)
1335 if (!GetCaptionRect( hWnd
, lprc
)) //window coords
1338 nSize
= GETCAPTIONSIZE( hWnd
) ;
1340 if (TestWinStyle( hWnd
, IBS_VERTCAPTION
))
1342 lprc
->bottom
-= nSize
* (nPos
-1) ;
1343 lprc
->top
= lprc
->bottom
- nSize
+ 1 ;
1347 lprc
->right
-= nSize
* (nPos
-1) ;
1348 lprc
->left
= lprc
->right
- nSize
+ 1 ;
1352 } // GetButtonRect()
1354 // DrawButton( HDC hDC, HWND hWnd, BOOL fMin, BOOL fDepressed )
1356 // Draws either the min, max, or restore buttons. If fMin is FALSE then it
1357 // will draw either the Max or Restore button. If fDepressed is TRUE it will
1358 // draw the button in a down state.
1360 void PASCAL
DrawButton( HDC hDC
, HWND hWnd
, BOOL fMin
, BOOL fDepressed
)
1364 COLORREF rgbWindowFrame
;
1370 nCapSize
= GETCAPTIONSIZE( hWnd
) ;
1372 // If you look at the standard Windows' min/max buttons, you will notice
1373 // that they have two pixels of 'shadow' to the bottom and right. Since
1374 // our buttons can be really, really small, we only want one pixel of
1375 // shadow when they are small. I arbitrarily decided that if the
1376 // caption size is greater than or equal to 20 we will use two
1377 // pixels. That's what this THREASHOLD stuff does.
1379 #define THRESHOLD 20
1380 nOffset
= (nCapSize
>= THRESHOLD
) ? 2 : 1 ;
1385 hDC
= GetWindowDC( hWnd
) ;
1392 rgbWindowFrame
= GetSysColor( COLOR_WINDOWFRAME
) ;
1395 GetMinButtonRect( hWnd
, &rcButton
) ;
1397 GetMaxButtonRect( hWnd
, &rcButton
) ;
1399 GetWindowRect( hWnd
, &rc
) ;
1400 OffsetRect( &rcButton
, -rc
.left
, -rc
.top
) ;
1403 if (TestWinStyle( hWnd
, IBS_VERTCAPTION
))
1405 rc
= rcButton
; //separator line
1406 rc
.bottom
= --rc
.top
+ 1 ;
1411 rc
= rcButton
; //separator line
1412 rc
.right
= --rc
.left
+ 1 ;
1416 //Draw separator line
1417 SetBkColor( hDC
, rgbWindowFrame
) ;
1418 DRAWFASTRECT( hDC
, &rc
) ;
1421 SetBkColor( hDC
, RGBLTGRAY
) ;
1422 DRAWFASTRECT( hDC
, &rcButton
) ;
1426 //The normal min/max buttons have one pixel on the top and left
1427 //sides for the highlight, and two pixels on the bottom and
1428 //right side for the shadow.
1430 //When our caption is 'small' we only use one pixel on all
1433 SetBkColor( hDC
, RGBWHITE
) ;
1436 rc
.right
= rc
.left
+ 1 ;
1437 DRAWFASTRECT( hDC
, &rc
) ;
1441 rc
.bottom
= rc
.top
+ 1 ;
1442 DRAWFASTRECT( hDC
, &rc
) ;
1444 SetBkColor( hDC
, RGBGRAY
) ;
1447 rc
.left
= rc
.right
- 1 ;
1448 DRAWFASTRECT( hDC
, &rc
) ;
1449 if (nCapSize
> THRESHOLD
)
1453 DRAWFASTRECT( hDC
, &rc
) ;
1458 rc
.top
= rc
.bottom
- 1 ;
1459 DRAWFASTRECT( hDC
, &rc
) ;
1460 if (nCapSize
> THRESHOLD
)
1464 DRAWFASTRECT( hDC
, &rc
) ;
1469 rcButton
.right
-= nOffset
;
1470 rcButton
.bottom
-= nOffset
;
1474 //Draw depressed state
1476 SetBkColor( hDC
, RGBGRAY
) ;
1479 rc
.right
= rc
.left
+ nOffset
;
1480 DRAWFASTRECT( hDC
, &rc
) ;
1484 rc
.bottom
= rc
.top
+ nOffset
;
1485 DRAWFASTRECT( hDC
, &rc
) ;
1487 rcButton
.left
+= 2 * nOffset
;
1488 rcButton
.top
+= 2 * nOffset
;
1491 // Now draw the arrows. We do not want the
1492 // arrows to grow too large when we have a bigger than
1493 // normal caption, so we restrict their size.
1495 // rcButton now represents where we can place our
1498 // The maximum size of our arrows (i.e. the width of rcButton)
1499 // has been empirically determined to be SM_CYCAPTION / 2
1501 n
= ((GetSystemMetrics( SM_CYCAPTION
)) / 2) -
1502 (rcButton
.right
- rcButton
.left
) ;
1504 InflateRect( &rcButton
, n
/2-1, n
/2-1 ) ;
1507 DrawArrow( hDC
, &rcButton
, ARROW_DOWN
) ;
1509 if (IsZoomed( hWnd
))
1511 DrawArrow( hDC
, &rcButton
, ARROW_RESTORE
) ;
1514 DrawArrow( hDC
, &rcButton
, ARROW_UP
) ;
1517 ReleaseDC( hWnd
, hDC
) ;
1525 // Draws either a up or down arrow. The arrow is bound by the rectangle
1527 void PASCAL
DrawArrow( HDC hdc
, LPRECT lprc
, UINT uiStyle
)
1533 int nMax
= (lprc
->bottom
- lprc
->top
) >> 1 ;
1535 SetBkColor( hdc
, RGBBLACK
) ;
1537 // We draw the arrow by drawing a series of horizontal lines
1539 xTip
= lprc
->left
+ ((lprc
->right
- lprc
->left
+1) >> 1) ;
1543 yTip
= lprc
->top
+ ((lprc
->bottom
- lprc
->top
-1) >> 2) ;
1544 for (row
= 1 ; row
<= nMax
; row
++ )
1546 rc
.left
= xTip
- row
;
1547 rc
.right
= xTip
+ row
- 1 ;
1548 rc
.top
= yTip
+ row
;
1549 rc
.bottom
= rc
.top
+ 1 ;
1550 DRAWFASTRECT( hdc
, &rc
) ;
1555 yTip
= lprc
->bottom
- ((lprc
->bottom
- lprc
->top
-1) >> 2) ;
1556 for ( row
= nMax
; row
> 0 ; row
-- )
1558 rc
.left
= xTip
- row
;
1559 rc
.right
= xTip
+ row
- 1 ;
1560 rc
.top
= yTip
- row
;
1561 rc
.bottom
= rc
.top
+ 1 ;
1562 DRAWFASTRECT( hdc
, &rc
) ;
1568 yTip
= lprc
->top
+ ((lprc
->bottom
- lprc
->top
-1) >> 3) - 2;
1569 for (row
= 1 ; row
<= nMax
; row
++ )
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
) ;
1578 yTip
+= (nMax
+1) * 2 ;
1579 for ( row
= nMax
; row
> 0 ; row
-- )
1581 rc
.left
= xTip
- row
;
1582 rc
.right
= xTip
+ row
- 1 ;
1583 rc
.top
= yTip
- row
;
1584 rc
.bottom
= rc
.top
+ 1 ;
1585 DRAWFASTRECT( hdc
, &rc
) ;
1592 #endif // USE_ITSY_BITSY