home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / winmini.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  22KB  |  797 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef AFX_CORE4_SEG
  14. #pragma code_seg(AFX_CORE4_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. #pragma warning(disable: 4706) // assignment within conditional
  23.  
  24. /////////////////////////////////////////////////////////////////////////////
  25. // CMiniFrameWnd global data
  26.  
  27. AFX_STATIC_DATA HBITMAP _afx_hbmMiniSys = 0;
  28. AFX_STATIC_DATA HFONT _afx_hfontMiniSys = 0;
  29. AFX_STATIC_DATA SIZE _afx_sizeMiniSys = { 0, 0 };
  30.  
  31. void AFX_CDECL _AfxWinminiTerm()
  32. {
  33.     AfxDeleteObject((HGDIOBJ*)&_afx_hbmMiniSys);
  34.     AfxDeleteObject((HGDIOBJ*)&_afx_hfontMiniSys);
  35. }
  36. int _afxWinminiTerm = atexit(_AfxWinminiTerm);
  37.  
  38. /////////////////////////////////////////////////////////////////////////////
  39. // CMiniFrameWnd
  40.  
  41. BEGIN_MESSAGE_MAP(CMiniFrameWnd, CFrameWnd)
  42.     //{{AFX_MSG_MAP(CMiniFrameWnd)
  43.     ON_WM_NCPAINT()
  44.     ON_WM_NCACTIVATE()
  45.     ON_WM_NCCALCSIZE()
  46.     ON_WM_NCHITTEST()
  47.     ON_WM_NCLBUTTONDOWN()
  48.     ON_WM_MOUSEMOVE()
  49.     ON_WM_LBUTTONUP()
  50.     ON_WM_SYSCOMMAND()
  51.     ON_WM_GETMINMAXINFO()
  52.     ON_WM_NCCREATE()
  53.     ON_MESSAGE(WM_GETTEXT, OnGetText)
  54.     ON_MESSAGE(WM_GETTEXTLENGTH, OnGetTextLength)
  55.     ON_MESSAGE(WM_SETTEXT, OnSetText)
  56.     ON_MESSAGE(WM_FLOATSTATUS, OnFloatStatus)
  57.     ON_MESSAGE(WM_QUERYCENTERWND, OnQueryCenterWnd)
  58.     //}}AFX_MSG_MAP
  59. END_MESSAGE_MAP()
  60.  
  61. #define new DEBUG_NEW
  62.  
  63. /////////////////////////////////////////////////////////////////////////////
  64. // CMiniFrameWnd constructors
  65.  
  66. CMiniFrameWnd::CMiniFrameWnd()
  67. {
  68.     m_bActive = FALSE;
  69.     Initialize();
  70. }
  71.  
  72. void AFX_CDECL CMiniFrameWnd::Initialize()
  73. {
  74.     // initialization not required if running latest Windows
  75.     if (afxData.bSmCaption)
  76.         return;
  77.  
  78.     AfxLockGlobals(CRIT_MINIFRAMEWND);
  79.     if (_afx_hbmMiniSys == NULL)
  80.     {
  81.         HINSTANCE hInst = AfxFindResourceHandle(
  82.             MAKEINTRESOURCE(AFX_IDB_MINIFRAME_MENU), RT_BITMAP);
  83.         VERIFY(_afx_hbmMiniSys =
  84.             LoadBitmap(hInst, MAKEINTRESOURCE(AFX_IDB_MINIFRAME_MENU)));
  85.         BITMAP bmStruct;
  86.         if (::GetObject(_afx_hbmMiniSys, sizeof(BITMAP), &bmStruct))
  87.         {
  88.             _afx_sizeMiniSys.cx = bmStruct.bmWidth;
  89.             _afx_sizeMiniSys.cy = bmStruct.bmHeight;
  90.         }
  91.     }
  92.     if (_afx_hfontMiniSys == NULL)
  93.     {
  94.         LOGFONT logFont; memset(&logFont, 0, sizeof(LOGFONT));
  95.         logFont.lfHeight = -(_afx_sizeMiniSys.cy-1);
  96.         logFont.lfCharSet = DEFAULT_CHARSET;
  97.         logFont.lfWeight = FW_NORMAL;
  98.         if (GetSystemMetrics(SM_DBCSENABLED))
  99.             lstrcpy(logFont.lfFaceName, _T("Terminal"));
  100.         else
  101.             lstrcpy(logFont.lfFaceName, _T("Small Fonts"));
  102.         if (!AfxCustomLogFont(AFX_IDS_MINI_FONT, &logFont))
  103.             logFont.lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
  104.         _afx_hfontMiniSys = ::CreateFontIndirect(&logFont);
  105.     }
  106.  
  107.     if (_afx_hfontMiniSys != NULL)
  108.     {
  109.         CClientDC dc(NULL);
  110.         TEXTMETRIC tm;
  111.         HFONT hFontOld = (HFONT)dc.SelectObject(_afx_hfontMiniSys);
  112.         BOOL bResult = dc.GetTextMetrics(&tm);
  113.         dc.SelectObject(hFontOld);
  114.  
  115.         if (!bResult || tm.tmHeight - tm.tmInternalLeading > _afx_sizeMiniSys.cy)
  116.             AfxDeleteObject((HGDIOBJ*)&_afx_hfontMiniSys);
  117.     }
  118.     AfxUnlockGlobals(CRIT_MINIFRAMEWND);
  119. }
  120.  
  121. CMiniFrameWnd::~CMiniFrameWnd()
  122. {
  123.     DestroyWindow();
  124. }
  125.  
  126. BOOL CMiniFrameWnd::Create(LPCTSTR lpClassName, LPCTSTR lpszWindowName,
  127.     DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)
  128. {
  129.     return CMiniFrameWnd::CreateEx(0, lpClassName, lpszWindowName, dwStyle,
  130.         rect, pParentWnd, nID);
  131. }
  132.  
  133. BOOL CMiniFrameWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpClassName,
  134.     LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect,
  135.     CWnd* pParentWnd, UINT nID)
  136. {
  137.     m_strCaption = lpszWindowName;
  138.     return CWnd::CreateEx(dwExStyle, lpClassName ? lpClassName :
  139.         AfxRegisterWndClass(CS_DBLCLKS, ::LoadCursor(NULL, IDC_ARROW)),
  140.         lpszWindowName, dwStyle, rect.left, rect.top, rect.right - rect.left,
  141.         rect.bottom - rect.top, pParentWnd->GetSafeHwnd(), (HMENU)nID);
  142. }
  143.  
  144. /////////////////////////////////////////////////////////////////////////////
  145. // CMiniFrameWnd message handlers
  146.  
  147. BOOL CMiniFrameWnd::OnNcCreate(LPCREATESTRUCT lpcs)
  148. {
  149.     if (!CFrameWnd::OnNcCreate(lpcs))
  150.         return FALSE;
  151.  
  152.     if (GetStyle() & MFS_SYNCACTIVE)
  153.     {
  154.         // syncronize activation state with top level parent
  155.         CWnd* pParentWnd = GetTopLevelParent();
  156.         ASSERT(pParentWnd != NULL);
  157.         CWnd* pActiveWnd = GetForegroundWindow();
  158.         BOOL bActive = (pParentWnd == pActiveWnd) ||
  159.             (pParentWnd->GetLastActivePopup() == pActiveWnd &&
  160.              pActiveWnd->SendMessage(WM_FLOATSTATUS, FS_SYNCACTIVE) != 0);
  161.  
  162.         // the WM_FLOATSTATUS does the actual work
  163.         SendMessage(WM_FLOATSTATUS, bActive ? FS_ACTIVATE : FS_DEACTIVATE);
  164.     }
  165.  
  166.     return TRUE;
  167. }
  168.  
  169. BOOL CMiniFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
  170. {
  171.     if (afxData.bSmCaption)
  172.     {
  173.         // WS_4THICKFRAME and MFS_THICKFRAME imply WS_THICKFRAME
  174.         if (cs.style & (MFS_4THICKFRAME | MFS_THICKFRAME))
  175.             cs.style |= WS_THICKFRAME;
  176.  
  177.         // WS_CAPTION implies WS_EX_TOOLWINDOW
  178.         if (cs.style & WS_CAPTION)
  179.             cs.dwExStyle |= WS_EX_TOOLWINDOW;
  180.     }
  181.  
  182.     VERIFY(CFrameWnd::PreCreateWindow(cs));
  183.     cs.dwExStyle &= ~(WS_EX_CLIENTEDGE);
  184.  
  185.     return TRUE;
  186. }
  187.  
  188. void CMiniFrameWnd::OnGetMinMaxInfo(MINMAXINFO* pMMI)
  189. {
  190.     // allow Windows to fill in the defaults
  191.     CFrameWnd::OnGetMinMaxInfo(pMMI);
  192.  
  193.     // don't allow sizing smaller than the non-client area
  194.     CRect rectWindow, rectClient;
  195.     GetWindowRect(rectWindow);
  196.     GetClientRect(rectClient);
  197.     pMMI->ptMinTrackSize.x = rectWindow.Width() - rectClient.right;
  198.     pMMI->ptMinTrackSize.y = rectWindow.Height() - rectClient.bottom;
  199. }
  200.  
  201. BOOL CMiniFrameWnd::OnNcActivate(BOOL bActive)
  202. {
  203.     if ((GetStyle() & MFS_SYNCACTIVE) == 0)
  204.     {
  205.         if (afxData.bSmCaption)
  206.             return Default();
  207.  
  208.         if (m_bActive != bActive)
  209.         {
  210.             m_bActive = bActive;
  211.             SendMessage(WM_NCPAINT);
  212.         }
  213.     }
  214.     else if(m_nFlags & WF_KEEPMINIACTIVE)
  215.     {
  216.         return FALSE;
  217.     }
  218.     return TRUE;
  219. }
  220.  
  221. void CMiniFrameWnd::OnNcCalcSize(BOOL, NCCALCSIZE_PARAMS *lpParams)
  222. {
  223.     if (afxData.bSmCaption)
  224.     {
  225.         Default();
  226.         return;
  227.     }
  228.  
  229.     // Modify the first rectangle in rgrc.
  230.     LONG dwStyle = GetStyle();
  231.     if (dwStyle & (MFS_4THICKFRAME | MFS_THICKFRAME | WS_THICKFRAME))
  232.     {
  233.         ::InflateRect(lpParams->rgrc,
  234.             -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME));
  235.     }
  236.     else
  237.     {
  238.         ::InflateRect(lpParams->rgrc,
  239.             -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
  240.     }
  241.     if (dwStyle & WS_CAPTION)
  242.         lpParams->rgrc[0].top += _afx_sizeMiniSys.cy;
  243. }
  244.  
  245. UINT CMiniFrameWnd::OnNcHitTest(CPoint point)
  246. {
  247.     DWORD dwStyle = GetStyle();
  248.     CRect rectWindow;
  249.     GetWindowRect(&rectWindow);
  250.  
  251.     CSize sizeFrame(GetSystemMetrics(SM_CXFRAME),
  252.         GetSystemMetrics(SM_CYFRAME));
  253.  
  254.     if (afxData.bSmCaption)
  255.     {
  256.         UINT nHit = CFrameWnd::OnNcHitTest(point);
  257.  
  258.         // MFS_BLOCKSYSMENU translates system menu hit to caption hit
  259.         if (afxData.bWin4 && (dwStyle & MFS_BLOCKSYSMENU))
  260.         {
  261.             if (nHit == HTSYSMENU)
  262.                 nHit = HTCAPTION;
  263.             if (GetKeyState(VK_RBUTTON) < 0)
  264.                 return HTNOWHERE;
  265.         }
  266.  
  267.         if ((nHit < HTSIZEFIRST || nHit > HTSIZELAST) && nHit != HTGROWBOX)
  268.             return nHit;
  269.  
  270.         // MFS_MOVEFRAME translates all size requests to move requests
  271.         if (dwStyle & MFS_MOVEFRAME)
  272.             return HTCAPTION;
  273.  
  274.         // MFS_4THICKFRAME does not allow diagonal sizing
  275.         rectWindow.InflateRect(-sizeFrame.cx, -sizeFrame.cy);
  276.         if (dwStyle & MFS_4THICKFRAME)
  277.         {
  278.             switch (nHit)
  279.             {
  280.             case HTTOPLEFT:
  281.                 return point.y < rectWindow.top ? HTTOP : HTLEFT;
  282.             case HTTOPRIGHT:
  283.                 return point.y < rectWindow.top ? HTTOP : HTRIGHT;
  284.             case HTBOTTOMLEFT:
  285.                 return point.y > rectWindow.bottom ? HTBOTTOM : HTLEFT;
  286.             case HTGROWBOX:
  287.             case HTBOTTOMRIGHT:
  288.                 return point.y > rectWindow.bottom ? HTBOTTOM : HTRIGHT;
  289.             }
  290.         }
  291.  
  292.         return nHit;    // no special translation
  293.     }
  294.  
  295.     if (!rectWindow.PtInRect(point))
  296.         return (UINT)HTNOWHERE;
  297.  
  298.     CSize sizeBorder(GetSystemMetrics(SM_CXBORDER),
  299.         GetSystemMetrics(SM_CYBORDER));
  300.  
  301.     NCCALCSIZE_PARAMS Params;
  302.     Params.rgrc[0].top = rectWindow.top;
  303.     Params.rgrc[0].left = rectWindow.left;
  304.     Params.rgrc[0].bottom = rectWindow.bottom;
  305.     Params.rgrc[0].right = rectWindow.right;
  306.     OnNcCalcSize(FALSE, &Params);
  307.  
  308.     CRect rcClient(Params.rgrc);
  309.     if (rcClient.PtInRect(point))
  310.         return HTCLIENT;
  311.  
  312.     if (dwStyle & (MFS_4THICKFRAME | MFS_THICKFRAME | WS_THICKFRAME))
  313.     {
  314.         UINT ht = HTNOWHERE;
  315.         CSize sizeOffset(sizeFrame.cx + _afx_sizeMiniSys.cx - sizeBorder.cx * 3,
  316.             sizeFrame.cy + _afx_sizeMiniSys.cy - sizeBorder.cy * 2);
  317.  
  318.         if (point.y < rectWindow.top + sizeFrame.cy)
  319.         {
  320.             if (dwStyle & MFS_4THICKFRAME)
  321.                 ht = HTTOP;
  322.             else if (point.x <= rectWindow.left + sizeOffset.cx)
  323.                 ht = HTTOPLEFT;
  324.             else if (point.x >= rectWindow.right - sizeOffset.cx)
  325.                 ht = HTTOPRIGHT;
  326.             else
  327.                 ht = HTTOP;
  328.         }
  329.         else if (point.y >= rectWindow.bottom - sizeFrame.cy)
  330.         {
  331.             if (dwStyle & MFS_4THICKFRAME)
  332.                 ht = HTBOTTOM;
  333.             else if (point.x <= rectWindow.left + sizeOffset.cx)
  334.                 ht = HTBOTTOMLEFT;
  335.             else if (point.x >= rectWindow.right - sizeOffset.cx)
  336.                 ht = HTBOTTOMRIGHT;
  337.             else
  338.                 ht = HTBOTTOM;
  339.         }
  340.         else if (point.x < rectWindow.left + sizeFrame.cx)
  341.         {
  342.             if (dwStyle & MFS_4THICKFRAME)
  343.                 ht = HTLEFT;
  344.             else if (point.y <= rectWindow.top + sizeOffset.cy)
  345.                 ht = HTTOPLEFT;
  346.             else if (point.y >= rectWindow.bottom - sizeOffset.cy)
  347.                 ht = HTBOTTOMLEFT;
  348.             else
  349.                 ht = HTLEFT;
  350.         }
  351.         else if (point.x >= rectWindow.right - sizeFrame.cx)
  352.         {
  353.             if (dwStyle & MFS_4THICKFRAME)
  354.                 ht = HTRIGHT;
  355.             else if (point.y <= rectWindow.top + sizeOffset.cy)
  356.                 ht = HTTOPRIGHT;
  357.             else if (point.y >= rectWindow.bottom - sizeOffset.cy)
  358.                 ht = HTBOTTOMRIGHT;
  359.             else
  360.                 ht = HTRIGHT;
  361.         }
  362.  
  363.         if (ht != HTNOWHERE)
  364.             return (dwStyle & MFS_MOVEFRAME) ? HTCAPTION : ht;
  365.  
  366.         rectWindow.InflateRect(-sizeFrame.cx, -sizeFrame.cy);
  367.     }
  368.  
  369.     rectWindow.bottom = rectWindow.top + _afx_sizeMiniSys.cy + sizeBorder.cy;
  370.     if (rectWindow.PtInRect(point))
  371.     {
  372.         if (point.x < rectWindow.left + (_afx_sizeMiniSys.cx - 2) &&
  373.             (dwStyle & WS_SYSMENU))
  374.             return HTSYSMENU;
  375.  
  376.         return HTCAPTION;
  377.     }
  378.  
  379.     return (UINT)HTERROR;
  380. }
  381.  
  382.  
  383. void CMiniFrameWnd::OnNcLButtonDown(UINT nHitTest, CPoint pt)
  384. {
  385.     if (afxData.bSmCaption || nHitTest != HTSYSMENU)
  386.     {
  387.         CFrameWnd::OnNcLButtonDown(nHitTest, pt);
  388.         return;
  389.     }
  390.  
  391.     m_bSysTracking = TRUE;
  392.     m_bInSys = TRUE;
  393.     SetCapture();
  394.     InvertSysMenu();
  395. }
  396.  
  397. void CMiniFrameWnd::OnMouseMove(UINT /*nFlags*/, CPoint pt)
  398. {
  399.     if (!m_bSysTracking)
  400.     {
  401.         Default();
  402.         return;
  403.     }
  404.  
  405.     ClientToScreen(&pt);
  406.     if (GetCapture() != this)
  407.     {
  408.         m_bSysTracking = FALSE;
  409.         SendMessage(WM_NCPAINT);
  410.     }
  411.     else if ((OnNcHitTest(pt) == HTSYSMENU) != m_bInSys)
  412.     {
  413.         m_bInSys = !m_bInSys;
  414.         InvertSysMenu();
  415.     }
  416. }
  417.  
  418. void CMiniFrameWnd::OnLButtonUp(UINT /*nFlags*/, CPoint pt)
  419. {
  420.     if (!m_bSysTracking)
  421.     {
  422.         Default();
  423.         return;
  424.     }
  425.  
  426.     ReleaseCapture();
  427.     m_bSysTracking = FALSE;
  428.     ClientToScreen(&pt);
  429.  
  430.     if (OnNcHitTest(pt) == HTSYSMENU)
  431.     {
  432.         InvertSysMenu();
  433.         SendMessage(WM_CLOSE);
  434.     }
  435. }
  436.  
  437. void CMiniFrameWnd::InvertSysMenu()
  438. {
  439.     CSize sizeBorder(GetSystemMetrics(SM_CXBORDER),
  440.         GetSystemMetrics(SM_CYBORDER));
  441.     CSize sizeFrame(GetSystemMetrics(SM_CXFRAME),
  442.         GetSystemMetrics(SM_CYFRAME));
  443.  
  444.     CRect rect(sizeBorder.cx, sizeBorder.cy,
  445.         _afx_sizeMiniSys.cx - sizeBorder.cx, _afx_sizeMiniSys.cy);
  446.     if (GetStyle() & (MFS_4THICKFRAME | MFS_THICKFRAME | WS_THICKFRAME))
  447.         rect.OffsetRect(sizeFrame.cx - sizeBorder.cx, sizeFrame.cy - sizeBorder.cy);
  448.  
  449.     CDC* pDC = GetWindowDC();
  450.     pDC->InvertRect(rect);
  451.     ReleaseDC(pDC);
  452. }
  453.  
  454.  
  455. // _AfxDrawFrame: [static]
  456. // Draws a frame in a given brush, with a given width for the lines.
  457. // Works like the doors to a cabinet: two tall stiles up and down the sides
  458. // and two short spacers across the top and bottom.  The thickness of the
  459. // lines are painted inside the rectangle.
  460. //
  461. AFX_STATIC void AFXAPI
  462. _AfxDrawFrame(CDC* dc, LPCRECT lpRect, int nWidth, int nHeight, CBrush& br)
  463. {
  464.     CRect rect;
  465.  
  466.     // left stile
  467.     rect = *lpRect;
  468.     rect.right = rect.left + nWidth;
  469.     dc->FillRect(rect, &br);
  470.  
  471.     // right stile
  472.     rect.right = lpRect->right;
  473.     rect.left = rect.right - nWidth;
  474.     dc->FillRect(rect, &br);
  475.  
  476.     // top spacer
  477.     rect = *lpRect;
  478.     rect.bottom = rect.top + nHeight;
  479.     rect.left += nWidth;
  480.     rect.right -= nWidth;
  481.     dc->FillRect(rect, &br);
  482.  
  483.     // bottom spacer
  484.     rect.bottom = lpRect->bottom;
  485.     rect.top = rect.bottom - nHeight;
  486.     dc->FillRect(rect, &br);
  487. }
  488.  
  489. void CMiniFrameWnd::OnNcPaint()
  490. {
  491.     if (afxData.bSmCaption)
  492.     {
  493.         Default();
  494.         return;
  495.     }
  496.  
  497.     // Prepare for drawing the non-client area of the mini frame
  498.     CWindowDC dc(this);
  499.     CRect rect, rectCaption;
  500.     LONG dwStyle = GetStyle();
  501.     GetWindowRect(&rect);
  502.     rect.OffsetRect(-rect.left, -rect.top);
  503.  
  504.     // Create brushes we might need.
  505.     CBrush brFrame;
  506.     brFrame.CreateSolidBrush(::GetSysColor(COLOR_WINDOWFRAME));
  507.     CBrush brBorder;
  508.     brBorder.CreateSolidBrush(::GetSysColor(m_bActive ?
  509.         COLOR_ACTIVEBORDER : COLOR_INACTIVEBORDER));
  510.     CBrush brCaption;
  511.     brCaption.CreateSolidBrush(::GetSysColor(m_bActive ?
  512.         COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
  513.  
  514.     CSize sizeBorder(GetSystemMetrics(SM_CXBORDER),
  515.         GetSystemMetrics(SM_CYBORDER));
  516.     CSize sizeFrame(GetSystemMetrics(SM_CXFRAME),
  517.         GetSystemMetrics(SM_CYFRAME));
  518.  
  519.     // Draw the thickframe.  Remove it from the rect.
  520.     if (dwStyle & (MFS_4THICKFRAME | WS_THICKFRAME | MFS_THICKFRAME))
  521.     {
  522.         _AfxDrawFrame(&dc, rect, sizeBorder.cx, sizeBorder.cy, brFrame);
  523.         rect.InflateRect(-sizeBorder.cx, -sizeBorder.cy);
  524.         _AfxDrawFrame(&dc, rect, sizeFrame.cx - sizeBorder.cx,
  525.             sizeFrame.cy - sizeBorder.cy, brBorder);
  526.  
  527.         CSize sizeTick(sizeFrame.cx - sizeBorder.cx * 2,
  528.             sizeFrame.cy - sizeBorder.cy * 2);
  529.  
  530.         if (!(dwStyle & MFS_4THICKFRAME))
  531.         {
  532.             CSize sizeOffset(sizeFrame.cx + _afx_sizeMiniSys.cx - sizeBorder.cx * 3,
  533.                 sizeFrame.cy + _afx_sizeMiniSys.cy - sizeBorder.cy * 2);
  534.  
  535.             dc.FillSolidRect(rect.left, rect.top + sizeOffset.cy,
  536.                 sizeTick.cx, 1, RGB(0, 0, 0));
  537.             dc.FillSolidRect(rect.left, rect.bottom - sizeOffset.cy,
  538.                 sizeTick.cx, 1, RGB(0, 0, 0));
  539.             dc.FillSolidRect(rect.right - sizeTick.cx,
  540.                 rect.top + sizeOffset.cy, sizeTick.cx, 1, RGB(0, 0, 0));
  541.             dc.FillSolidRect(rect.right - sizeTick.cx,
  542.                 rect.bottom - sizeOffset.cy, sizeTick.cx, 1, RGB(0, 0, 0));
  543.  
  544.             dc.FillSolidRect(rect.left + sizeOffset.cx, rect.top,
  545.                 1, sizeTick.cy, RGB(0, 0, 0));
  546.             dc.FillSolidRect(rect.right - sizeOffset.cx, rect.top,
  547.                 1, sizeTick.cy, RGB(0, 0, 0));
  548.             dc.FillSolidRect(rect.left + sizeOffset.cx,
  549.                 rect.bottom - sizeTick.cy, 1, sizeTick.cy, RGB(0, 0, 0));
  550.             dc.FillSolidRect(rect.right - sizeOffset.cx,
  551.                 rect.bottom - sizeTick.cy, 1, sizeTick.cy, RGB(0, 0, 0));
  552.         }
  553.  
  554.         rect.InflateRect(-sizeTick.cx, -sizeTick.cy);
  555.     }
  556.  
  557.     // Draw the caption.  Remove it from rect.
  558.     if (dwStyle & WS_CAPTION)
  559.     {
  560.         rectCaption = rect;
  561.         rectCaption.bottom = rectCaption.top + _afx_sizeMiniSys.cy + sizeBorder.cy;
  562.  
  563.         _AfxDrawFrame(&dc, rectCaption, sizeBorder.cx, sizeBorder.cy, brFrame);
  564.         rectCaption.InflateRect(-sizeBorder.cx, -sizeBorder.cy);
  565.  
  566.         dc.FillRect(&rectCaption, &brCaption);
  567.  
  568.         // Draw the border around the client area.
  569.         // At this point, rc==rcClient.InflateRect(cxBorder, cyBorder).
  570.         //
  571.         _AfxDrawFrame(&dc, rect, sizeBorder.cx, sizeBorder.cy, brFrame);
  572.  
  573.         if (_afx_hfontMiniSys != NULL)
  574.         {
  575.             HFONT hFontOld = (HFONT)dc.SelectObject(_afx_hfontMiniSys);
  576.  
  577.             CString strTitle;
  578.             GetWindowText(strTitle);
  579.             int xLeft = rectCaption.left +
  580.                 (dwStyle & WS_SYSMENU ? _afx_sizeMiniSys.cx : 0);
  581.  
  582.             CSize sizeText = dc.GetTextExtent(strTitle, strTitle.GetLength());
  583.             if (sizeText.cx <= rectCaption.Width())
  584.             {
  585.                 dc.SetTextAlign(TA_CENTER);
  586.                 xLeft += (rectCaption.right - xLeft) / 2;
  587.             }
  588.  
  589.             TEXTMETRIC tm;
  590.             VERIFY(dc.GetTextMetrics(&tm));
  591.             int yHeight = tm.tmAscent + tm.tmDescent + tm.tmInternalLeading;
  592.             rectCaption.InflateRect(0, 1);
  593.             int yHeightDiff = (rectCaption.Height() - yHeight + 1) / 2;
  594.  
  595.             dc.SetTextColor(::GetSysColor(m_bActive ?
  596.                 COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT));
  597.             dc.SetBkMode(TRANSPARENT);
  598.             dc.ExtTextOut(xLeft, rectCaption.top + yHeightDiff, ETO_CLIPPED,
  599.                 rectCaption, strTitle, strTitle.GetLength(), NULL);
  600.  
  601.             dc.SelectObject(hFontOld);
  602.         }
  603.  
  604.         // Draw the system menu.
  605.         if (dwStyle & WS_SYSMENU)
  606.         {
  607.             CDC dcBitmap;
  608.             HBITMAP hBitmapOld;
  609.             if (!dcBitmap.CreateCompatibleDC(&dc))
  610.                 return;
  611.             hBitmapOld = (HBITMAP)dcBitmap.SelectObject(_afx_hbmMiniSys);
  612.             dc.BitBlt(rect.left, rect.top, _afx_sizeMiniSys.cx, _afx_sizeMiniSys.cy,
  613.                 &dcBitmap, 0, 0, SRCCOPY);
  614.             dcBitmap.SelectObject(hBitmapOld);
  615.         }
  616.  
  617.         rect.top = rectCaption.bottom;
  618.     }
  619.     else
  620.     {
  621.         // Draw the border around the client area.
  622.         // At this point, rect == rcClient.InflateRect(cxBorder, cyBorder).
  623.         _AfxDrawFrame(&dc, rect, sizeBorder.cx, sizeBorder.cy, brFrame);
  624.     }
  625. }
  626.  
  627. void CMiniFrameWnd::OnSysCommand(UINT nID, LPARAM lParam)
  628. {
  629.     DWORD dwStyle = GetStyle();
  630.     if ((dwStyle & WS_POPUP) &&
  631.         ((nID & 0xFFF0) != SC_CLOSE ||
  632.         (GetKeyState(VK_F4) < 0 && GetKeyState(VK_MENU) < 0 &&
  633.         (dwStyle & MFS_SYNCACTIVE))))
  634.     {
  635.         if (HandleFloatingSysCommand(nID, lParam))
  636.             return;
  637.     }
  638.     CFrameWnd::OnSysCommand(nID, lParam);
  639. }
  640.  
  641. void CMiniFrameWnd::CalcWindowRect(LPRECT lpClientRect, UINT nAdjustType)
  642. {
  643.     if (afxData.bSmCaption)
  644.     {
  645.         CFrameWnd::CalcWindowRect(lpClientRect, nAdjustType);
  646.         return;
  647.     }
  648.  
  649.     LONG dwStyle = GetStyle();
  650.     if (dwStyle & (MFS_4THICKFRAME | WS_THICKFRAME | MFS_THICKFRAME))
  651.     {
  652.         ::InflateRect(lpClientRect,
  653.             GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME));
  654.     }
  655.     else
  656.     {
  657.         ::InflateRect(lpClientRect,
  658.             GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
  659.     }
  660.  
  661.     if (dwStyle & WS_CAPTION)
  662.         lpClientRect->top -= _afx_sizeMiniSys.cy;
  663. }
  664.  
  665. void PASCAL CMiniFrameWnd::CalcBorders(
  666.     LPRECT lpClientRect, DWORD dwStyle, DWORD dwExStyle)
  667. {
  668.     UNUSED_ALWAYS(dwExStyle);
  669.  
  670.     if (afxData.bSmCaption)
  671.     {
  672.         AdjustWindowRectEx(lpClientRect, dwStyle, FALSE, WS_EX_PALETTEWINDOW);
  673.         return;
  674.     }
  675.  
  676.     if (dwStyle & (MFS_4THICKFRAME | WS_THICKFRAME | MFS_THICKFRAME))
  677.     {
  678.         ::InflateRect(lpClientRect,
  679.             GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME));
  680.     }
  681.     else
  682.     {
  683.         ::InflateRect(lpClientRect,
  684.             GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
  685.     }
  686.  
  687.     if (dwStyle & WS_CAPTION)
  688.     {
  689.         Initialize();
  690.         lpClientRect->top -= _afx_sizeMiniSys.cy;
  691.     }
  692. }
  693.  
  694. LRESULT CMiniFrameWnd::OnGetText(WPARAM wParam, LPARAM lParam)
  695. {
  696.     if (afxData.bSmCaption)
  697.         return Default();
  698.  
  699.     lstrcpyn((LPTSTR)lParam, (LPCTSTR)m_strCaption, wParam);
  700.     if ((int)wParam > m_strCaption.GetLength())
  701.         wParam = m_strCaption.GetLength();
  702.     return wParam;
  703. }
  704.  
  705. LRESULT CMiniFrameWnd::OnGetTextLength(WPARAM, LPARAM)
  706. {
  707.     if (afxData.bSmCaption)
  708.         return Default();
  709.  
  710.     return m_strCaption.GetLength();
  711. }
  712.  
  713. // CMiniFrameWnd::OnSetText
  714. //  Windows will repaint just the caption, as a thick caption, if
  715. //  we don't override WM_SETTEXT.  NOTE: Unfortunately, this will never
  716. //  get called if you do a SetWindowText() on this window from another
  717. //  task.  Use SendMessage instead.
  718. LRESULT CMiniFrameWnd::OnSetText(WPARAM, LPARAM lParam)
  719. {
  720.     if (afxData.bSmCaption)
  721.         return Default();
  722.  
  723.     TRY
  724.     {
  725.         if (lParam == NULL)
  726.         {
  727.             // NULL lParam means set caption to nothing
  728.             m_strCaption.Empty();
  729.         }
  730.         else
  731.         {
  732.             // non-NULL sets caption to that specified by lParam
  733.             lstrcpy(m_strCaption.GetBufferSetLength(lstrlen((LPCTSTR)lParam)),
  734.                 (LPCTSTR)lParam);
  735.         }
  736.         SendMessage(WM_NCPAINT);
  737.     }
  738.     CATCH_ALL(e)
  739.     {
  740.         // Note: DELETE_EXCEPTION(e) not required
  741.         return FALSE;
  742.     }
  743.     END_CATCH_ALL
  744.  
  745.     return TRUE;
  746. }
  747.  
  748. LRESULT CMiniFrameWnd::OnFloatStatus(WPARAM wParam, LPARAM)
  749. {
  750.     // these asserts make sure no conflicting actions are requested
  751.     ASSERT(!((wParam & FS_SHOW) && (wParam & FS_HIDE)));
  752.     ASSERT(!((wParam & FS_ENABLE) && (wParam & FS_DISABLE)));
  753.     ASSERT(!((wParam & FS_ACTIVATE) && (wParam & FS_DEACTIVATE)));
  754.  
  755.     // FS_SYNCACTIVE is used to detect MFS_SYNCACTIVE windows
  756.     LRESULT lResult = 0;
  757.     if ((GetStyle() & MFS_SYNCACTIVE) && (wParam & FS_SYNCACTIVE))
  758.         lResult = 1;
  759.  
  760.     if (wParam & (FS_SHOW|FS_HIDE))
  761.     {
  762.         SetWindowPos(NULL, 0, 0, 0, 0,
  763.             ((wParam & FS_SHOW) ? SWP_SHOWWINDOW : SWP_HIDEWINDOW) | SWP_NOZORDER |
  764.             SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
  765.     }
  766.     if (wParam & (FS_ENABLE|FS_DISABLE))
  767.         EnableWindow((wParam & FS_ENABLE) != 0);
  768.  
  769.     if ((wParam & (FS_ACTIVATE|FS_DEACTIVATE)) &&
  770.         GetStyle() & MFS_SYNCACTIVE)
  771.     {
  772.         ModifyStyle(MFS_SYNCACTIVE, 0);
  773.         SendMessage(WM_NCACTIVATE, (wParam & FS_ACTIVATE) != 0);
  774.         ModifyStyle(0, MFS_SYNCACTIVE);
  775.     }
  776.  
  777.     return lResult;
  778. }
  779.  
  780. LRESULT CMiniFrameWnd::OnQueryCenterWnd(WPARAM, LPARAM)
  781. {
  782.     // forward WM_QUERYCENTERWND to parent window
  783.     HWND hWndParent = ::GetParent(m_hWnd);
  784.     LRESULT lResult = ::SendMessage(hWndParent, WM_QUERYCENTERWND, 0, 0);
  785.     if (lResult == 0)
  786.         lResult = (LRESULT)hWndParent;
  787.     return lResult;
  788. }
  789.  
  790. #ifdef AFX_INIT_SEG
  791. #pragma code_seg(AFX_INIT_SEG)
  792. #endif
  793.  
  794. IMPLEMENT_DYNCREATE(CMiniFrameWnd, CFrameWnd)
  795.  
  796. ////////////////////////////////////////////////////////////////////////////
  797.