home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / WINMINI.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-30  |  21.9 KB  |  836 lines

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