00001
00002
00003
00004
00005
00006 #include "stdafx.h"
00007 #include "FdmApp.h"
00008 #include "fsODMenu.h"
00009 #include "grutil.h"
00010 #include "misc.h"
00011
00012 #ifdef _DEBUG
00013 #undef THIS_FILE
00014 static char THIS_FILE[]=__FILE__;
00015 #define new DEBUG_NEW
00016 #endif
00017
00018 fsODMenu::fsODMenu()
00019 {
00020 m_hMenu = NULL;
00021 m_cxIcon = 16;
00022 m_cyIcon = 16;
00023
00024 LOGFONT lf;
00025 NONCLIENTMETRICS nm;
00026
00027 ZeroMemory (&nm, sizeof (nm));
00028 nm.cbSize = sizeof (nm);
00029 SystemParametersInfo (SPI_GETNONCLIENTMETRICS, nm.cbSize, &nm, 0);
00030 lf = nm.lfMenuFont;
00031 lf.lfCharSet = DEFAULT_CHARSET;
00032
00033 m_font.CreateFontIndirect (&lf);
00034
00035 lf.lfWeight = FW_BOLD;
00036 m_fontBold.CreateFontIndirect (&lf);
00037
00038 m_pImages = NULL;
00039 }
00040
00041 fsODMenu::~fsODMenu()
00042 {
00043 Detach ();
00044 }
00045
00046 void fsODMenu::Attach(CMenu *pMenu, BOOL bMainMenu)
00047 {
00048 Detach ();
00049 m_hMenu = pMenu->m_hMenu;
00050 AttachMenu (pMenu, bMainMenu);
00051 }
00052
00053 void fsODMenu::AttachMenu(CMenu *pMenu, BOOL bMenuBar)
00054 {
00055 for (UINT i = 0; i < pMenu->GetMenuItemCount (); i++)
00056 {
00057 UINT uState = pMenu->GetMenuState (i, MF_BYPOSITION);
00058
00059 fsODMenuItemData* pData = AttachMenuItem (pMenu, i);
00060 pData->bMenuBar = bMenuBar;
00061 pData->bBold = pMenu->GetDefaultItem (GMDI_USEDISABLED, TRUE) == i;
00062
00063
00064 if (uState & MF_POPUP)
00065 {
00066 CMenu *pSubMenu = pMenu->GetSubMenu (i);
00067 AttachMenu (pSubMenu);
00068 }
00069 }
00070 }
00071
00072 fsODMenuItemData* fsODMenu::AttachMenuItem(CMenu *pMenu, UINT iPos, BOOL bByPos)
00073 {
00074 fsODMenuItemData *pData;
00075
00076 fsnew1 (pData, fsODMenuItemData);
00077
00078 UINT nByPosFl = bByPos ? MF_BYPOSITION : MF_BYCOMMAND;
00079
00080 UINT uState = pMenu->GetMenuState (iPos, nByPosFl);
00081
00082 UINT nID;
00083
00084 if (uState & MF_POPUP)
00085 nID = (UINT) pMenu->GetSubMenu (iPos)->m_hMenu;
00086 else if (bByPos)
00087 nID = pMenu->GetMenuItemID (iPos);
00088 else
00089 nID = iPos;
00090
00091 pMenu->GetMenuString (iPos, pData->strMenuText, nByPosFl);
00092
00093 if (uState & MF_POPUP)
00094 uState = MF_POPUP;
00095
00096 pMenu->ModifyMenu (iPos, uState | MF_OWNERDRAW | nByPosFl, nID, (LPCSTR)pData);
00097
00098 pData->iImage = pData->iCheckImage = -1;
00099 pData->bBold = pData->bMenuBar = FALSE;
00100
00101 return pData;
00102 }
00103
00104 void fsODMenu::Detach()
00105 {
00106 if (m_hMenu == NULL)
00107 return;
00108
00109 DetachMenu (CMenu::FromHandle (m_hMenu));
00110
00111 m_hMenu = NULL;
00112 }
00113
00114 void fsODMenu::DetachMenu(CMenu *pMenu)
00115 {
00116 if (pMenu == NULL)
00117 return;
00118
00119 for (UINT i = 0; i < pMenu->GetMenuItemCount (); i++)
00120 {
00121 UINT uState = pMenu->GetMenuState (i, MF_BYPOSITION);
00122
00123 if (uState & MF_POPUP)
00124 {
00125 CMenu *pSubMenu = pMenu->GetSubMenu (i);
00126 DetachMenu (pSubMenu);
00127 }
00128
00129 DetachMenuItem (pMenu, i);
00130 }
00131 }
00132
00133 void fsODMenu::DetachMenuItem(CMenu *pMenu, UINT iPos, BOOL bByPos)
00134 {
00135 MENUITEMINFO info;
00136 ZeroMemory (&info, sizeof (info));
00137 info.cbSize = sizeof (info);
00138 info.fMask = MIIM_DATA | MIIM_STATE | MIIM_ID | MIIM_SUBMENU;
00139 pMenu->GetMenuItemInfo (iPos, &info, bByPos);
00140
00141 UINT uID = info.fState & MF_POPUP ? (UINT) info.hSubMenu : info.wID;
00142
00143 fsODMenuItemData* pData = (fsODMenuItemData*) info.dwItemData;
00144
00145 UINT nPosFl = bByPos ? MF_BYPOSITION : MF_BYCOMMAND;
00146 info.fState &= ~MF_OWNERDRAW;
00147
00148
00149 pMenu->ModifyMenu (iPos, info.fState | nPosFl, uID, pData->strMenuText);
00150
00151 delete pData;
00152 }
00153
00154 void fsODMenu::OnMeasureItem(LPMEASUREITEMSTRUCT pmis)
00155 {
00156 SIZE sz = {0, 0};
00157 fsODMenuItemData *pData = (fsODMenuItemData*) pmis->itemData;
00158
00159
00160 if (pData->strMenuText.GetLength () == 0)
00161 {
00162 pmis->itemWidth = 0;
00163 pmis->itemHeight = 5;
00164 return;
00165 }
00166
00167 CDC* dc = AfxGetApp ()->m_pMainWnd->GetDC ();
00168 CFont *oldfont = dc->SelectObject (pData->bBold ? &m_fontBold : &m_font);
00169
00170 sz = dc->GetTextExtent (pData->strMenuText);
00171
00172 pmis->itemWidth = sz.cx;
00173 pmis->itemHeight = sz.cy;
00174
00175 if (pData->bMenuBar == FALSE)
00176 {
00177 pmis->itemWidth += m_cxIcon + 6 + 10;
00178
00179 UINT mincy = m_cyIcon + 6;
00180 if (pmis->itemHeight < mincy)
00181 pmis->itemHeight = mincy;
00182
00183 if (strchr (pData->strMenuText, '\t') != NULL)
00184 pmis->itemWidth += 15;
00185 }
00186 else
00187 {
00188 pmis->itemWidth -= 3;
00189 UINT temp = GetSystemMetrics (SM_CYMENU);
00190 pmis->itemHeight = temp > m_cyIcon + 8 ? temp : m_cyIcon + 7;
00191
00192 if(pmis->itemHeight < (UINT)sz.cy)
00193 pmis->itemHeight = sz.cy;
00194 }
00195
00196 dc->SelectObject (oldfont);
00197 AfxGetApp ()->m_pMainWnd->ReleaseDC (dc);
00198 }
00199
00200 void fsODMenu::OnDrawItem(LPDRAWITEMSTRUCT pdis)
00201 {
00202 CDC *dc = CDC::FromHandle (pdis->hDC);
00203 fsODMenuItemData* pData = (fsODMenuItemData*) pdis->itemData;
00204 UINT uState = pdis->itemState;
00205 CFont *oldfont = dc->SelectObject (pData->bBold ? &m_fontBold : &m_font);
00206
00207 RECT rcItem = pdis->rcItem;
00208
00209 RECT rcIcon = rcItem;
00210 rcIcon.left += 3;
00211 rcIcon.right = rcIcon.left + m_cxIcon;
00212 rcIcon.top += (rcIcon.bottom - rcIcon.top - m_cyIcon) / 2;
00213 rcIcon.bottom = rcIcon.top + m_cyIcon;
00214
00215 RECT rcIconFrame = rcIcon;
00216 InflateRect (&rcIconFrame, 2, 2);
00217
00218 RECT rcSel;
00219
00220 if (pData->bMenuBar)
00221 {
00222 rcSel = pdis->rcItem;
00223 InflateRect (&rcSel, -1, -1);
00224 fsFillSolidRect (dc, &rcItem, GetSysColor (COLOR_3DFACE));
00225 }
00226 else
00227 {
00228 rcSel = rcIconFrame;
00229 rcSel.right = rcItem.right;
00230 rcSel.bottom++;
00231
00232 fsFillSolidRect (dc, &rcItem, GetSysColor (COLOR_MENU));
00233 rcItem.left += m_cxIcon;
00234 }
00235
00236 if (pData->strMenuText.GetLength () == 0)
00237 {
00238 RECT rect = rcItem;
00239 rect.left -= m_cxIcon;
00240 rect.top += (rect.bottom - rect.top) / 2;
00241 rect.bottom = rect.top+1;
00242 rect.right = rcItem.right;
00243 fsFillSolidRect (dc, &rect, GetSysColor (COLOR_GRAYTEXT));
00244 return;
00245 }
00246
00247 if (uState & 0x40 )
00248 if (pData->bMenuBar)
00249 fsDrawFrame (dc, &rcSel, 1);
00250
00251 if (uState & ODS_SELECTED)
00252 {
00253 if (pData->bMenuBar)
00254 fsDrawPressedFrame (dc, &rcSel, 1);
00255 else
00256 {
00257
00258 fsFillSolidRect (dc, &rcSel, GetSysColor (COLOR_HIGHLIGHT));
00259 }
00260 }
00261
00262 dc->SetBkMode (TRANSPARENT);
00263
00264 if (pData->bMenuBar)
00265 {
00266
00267 if (uState & ODS_GRAYED || uState & ODS_DISABLED)
00268 dc->SetTextColor (GetSysColor (COLOR_GRAYTEXT));
00269 dc->DrawText (pData->strMenuText, &rcItem, DT_VCENTER | DT_SINGLELINE | DT_CENTER);
00270 }
00271 else
00272 {
00273 CPen pen (PS_SOLID, 1, GetSystemMetrics (COLOR_HIGHLIGHTTEXT));
00274
00275 CPen *oldpen = dc->SelectObject (&pen);
00276
00277 if (uState & ODS_GRAYED || uState & ODS_DISABLED)
00278 dc->SetTextColor (GetSysColor (COLOR_GRAYTEXT));
00279 else if (uState & ODS_SELECTED)
00280 dc->SetTextColor (GetSysColor (COLOR_HIGHLIGHTTEXT));
00281 else
00282 dc->SetTextColor (GetSysColor (COLOR_MENUTEXT));
00283
00284 LPCSTR pszTab = strchr (pData->strMenuText, '\t');
00285 int left = pszTab ? pszTab - pData->strMenuText : pData->strMenuText.GetLength ();
00286
00287 rcItem.left += 9; rcItem.right -= 15;
00288 dc->DrawText (pData->strMenuText, left, &rcItem, DT_VCENTER | DT_SINGLELINE);
00289
00290 if (pszTab)
00291 dc->DrawText (pszTab+1, -1, &rcItem, DT_VCENTER | DT_SINGLELINE | DT_RIGHT);
00292
00293 dc->SelectObject (oldpen);
00294 }
00295
00296 POINT ptIcon;
00297 ptIcon.x = rcIcon.left + 1;
00298 ptIcon.y = rcIcon.top + 1;
00299
00300 RECT rcClr = pdis->rcItem;
00301 rcClr.right = m_cxIcon + 5;
00302
00303 if (uState & ODS_CHECKED)
00304 {
00305 if (pData->iCheckImage >= 0)
00306 {
00307 fsFillSolidRect (dc, &rcClr, GetSysColor (COLOR_MENU));
00308 m_pImages->Draw (dc, pData->iCheckImage, ptIcon, ILD_TRANSPARENT);
00309 }
00310 else if (pData->iImage >= 0)
00311 {
00312 fsFillSolidRect (dc, &rcClr, GetSysColor (COLOR_MENU));
00313
00314
00315 rcIconFrame.right--;
00316 fsDrawPressedFrame (dc, &rcIconFrame, 1);
00317 m_pImages->Draw (dc, pData->iImage, ptIcon, ILD_TRANSPARENT);
00318 }
00319 else
00320 {
00321 CFont font;
00322 char check;
00323 int fsize;
00324
00325 switch (pData->iCheckImage)
00326 {
00327 case ODMENU_CHECKIMAGE_CHECK:
00328 {
00329 DrawCheckMark (dc, rcIcon, uState & ODS_SELECTED, uState & ODS_GRAYED);
00330
00331 }
00332 break;
00333
00334 case ODMENU_CHECKIMAGE_RADIO:
00335 {
00336 check = 105;
00337 fsize = m_cyIcon;
00338 font.CreateFont (fsize, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, 0, 0, 0, 0, "Marlett");
00339 CFont* oldfont = dc->SelectObject (&font);
00340 dc->DrawText (&check, 1, &rcIcon, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
00341 dc->SelectObject (oldfont);
00342 }
00343 break;
00344
00345 default:
00346 return;
00347 }
00348 }
00349 }
00350 else if (pData->iImage != -1)
00351 {
00352 fsFillSolidRect (dc, &rcClr, GetSysColor (COLOR_MENU));
00353
00354 if (uState & ODS_GRAYED || uState & ODS_DISABLED)
00355 {
00356 if (m_pDisImages == NULL)
00357 {
00358 HICON hI = m_pImages->ExtractIcon (pData->iImage);
00359
00360 DrawState (dc->m_hDC, NULL, NULL, LPARAM (hI), 0, ptIcon.x, ptIcon.y, m_cxIcon, m_cyIcon,
00361 DST_ICON | DSS_DISABLED);
00362
00363 DestroyIcon (hI);
00364 }
00365 else
00366 m_pDisImages->Draw (dc, pData->iImage, ptIcon, ILD_TRANSPARENT);
00367
00368 }
00369 else
00370 {
00371 if (uState & ODS_SELECTED)
00372 fsDrawFrame (dc, &rcIconFrame, 1);
00373
00374 m_pImages->Draw (dc, pData->iImage, ptIcon, ILD_TRANSPARENT);
00375 }
00376 }
00377
00378 dc->SelectObject (oldfont);
00379 }
00380
00381 void fsODMenu::SetImageList(CImageList *pList, CImageList *pDisList)
00382 {
00383 m_pImages = pList;
00384 m_pDisImages = pDisList;
00385 }
00386
00387 int fsODMenu::InsertMenu(CMenu *pMenu, int iWhere, CMenu *pMenuWhere)
00388 {
00389 BOOL bMenuBar = FALSE;
00390 if (pMenuWhere == NULL)
00391 {
00392 pMenuWhere = CMenu::FromHandle (m_hMenu);
00393 bMenuBar = TRUE;
00394 }
00395
00396 for (UINT i = 0; i < pMenu->GetMenuItemCount (); i++)
00397 {
00398 CString strText;
00399
00400 pMenu->GetMenuString (i, strText, MF_BYPOSITION);
00401
00402 HMENU hMenu = CopyMenu (pMenu->GetSubMenu (i)->m_hMenu);
00403 CMenu *menu = CMenu::FromHandle (hMenu);
00404
00405 pMenuWhere->InsertMenu (iWhere, MF_BYPOSITION | MF_POPUP, (UINT_PTR) menu->m_hMenu, strText);
00406
00407 AttachMenu (menu);
00408 AttachMenuItem (pMenuWhere, iWhere++)->bMenuBar = bMenuBar;
00409 }
00410
00411 return pMenu->GetMenuItemCount ();
00412 }
00413
00414 void fsODMenu::RemoveMenu(int iWhere, int iCount, CMenu *pMenuWhere)
00415 {
00416 if (pMenuWhere == NULL)
00417 pMenuWhere = CMenu::FromHandle (m_hMenu);
00418
00419 while (iCount--)
00420 {
00421 CMenu *pSubMenu = pMenuWhere->GetSubMenu (iWhere);
00422 DetachMenu (pSubMenu);
00423 DetachMenuItem (pMenuWhere, iWhere);
00424 pMenuWhere->RemoveMenu (iWhere, MF_BYPOSITION);
00425 pSubMenu->DestroyMenu ();
00426 iWhere--;
00427 }
00428 }
00429
00430 HMENU fsODMenu::CopyMenu(HMENU hMenu)
00431 {
00432 HMENU hCopy = CreateMenu ();
00433
00434 for (int i = 0; i < GetMenuItemCount (hMenu); i++)
00435 {
00436 UINT uState = GetMenuState (hMenu, i, MF_BYPOSITION);
00437 UINT nID;
00438 char szMenuText [100];
00439
00440 if (uState & MF_POPUP)
00441 {
00442 nID = (UINT) CopyMenu (GetSubMenu (hMenu, i));
00443 uState = MF_POPUP | MF_STRING;
00444 }
00445 else
00446 nID = GetMenuItemID (hMenu, i);
00447
00448 GetMenuString (hMenu, i, szMenuText, sizeof (szMenuText), MF_BYPOSITION);
00449
00450
00451 AppendMenu (hCopy, uState, nID, szMenuText);
00452 }
00453
00454 return hCopy;
00455 }
00456
00457 void fsODMenu::SetImages(fsSetImage *pImages, int cImages, CMenu *pMenu, BOOL fByPos)
00458 {
00459 if (pMenu == NULL)
00460 pMenu = CMenu::FromHandle (m_hMenu);
00461
00462 MENUITEMINFO info;
00463 ZeroMemory (&info, sizeof (info));
00464 info.cbSize = sizeof (info);
00465 info.fMask = MIIM_DATA;
00466
00467 for (int i = 0; i < cImages; i++)
00468 {
00469 if (pMenu->GetMenuItemInfo (pImages [i].iIdItem, &info, fByPos))
00470 {
00471 fsODMenuItemData *pData = (fsODMenuItemData*) info.dwItemData;
00472 ASSERT (pData);
00473 pData->iImage = pImages [i].iImage;
00474 pData->iCheckImage = pImages [i].iCheckImage;
00475 }
00476 }
00477 }
00478
00479 fsODMenuItemData* fsODMenu::AddItem(CMenu *pMenu, UINT nID, LPCSTR pszItem)
00480 {
00481 pMenu->AppendMenu (pszItem ? MF_STRING : MF_SEPARATOR, nID, pszItem);
00482 return AttachMenuItem (pMenu, nID, FALSE);
00483 }
00484
00485 void fsODMenu::RemoveMenuItem(CMenu *pMenu, UINT nID, BOOL bByPos)
00486 {
00487 DetachMenuItem (pMenu, nID, bByPos);
00488 pMenu->RemoveMenu (nID, bByPos ? MF_BYPOSITION : MF_BYCOMMAND);
00489 }
00490
00491 void fsODMenu::InsertMenuItem(CMenu* pMenu, LPCSTR pszItem, UINT nID, UINT uWhere, BOOL bByPos)
00492 {
00493 pMenu->InsertMenu (uWhere, bByPos ? MF_BYPOSITION : MF_BYCOMMAND, nID, pszItem);
00494 AttachMenuItem (pMenu, nID, FALSE);
00495 }
00496
00497 void fsODMenu::SetMenuItemText(CMenu *pMenu, LPCSTR pszText, UINT nID, BOOL bByPos)
00498 {
00499 MENUITEMINFO info;
00500 ZeroMemory (&info, sizeof (info));
00501 info.cbSize = sizeof (info);
00502 info.fMask = MIIM_DATA | MIIM_ID;
00503 pMenu->GetMenuItemInfo (nID, &info, bByPos);
00504
00505 fsODMenuItemData* pData = (fsODMenuItemData*) info.dwItemData;
00506 if (pData == NULL)
00507 return;
00508
00509 UINT nFlags = bByPos ? MF_BYPOSITION : MF_BYCOMMAND;
00510 pMenu->ModifyMenu (nID, nFlags|MF_STRING, info.wID, pszText);
00511 pMenu->ModifyMenu (nID, nFlags|MF_OWNERDRAW, info.wID, (LPCSTR)pData);
00512
00513 pData->strMenuText = pszText;
00514 }
00515
00516 void fsODMenu::SetMenuItemsText(CMenu *pMenu, fsSetText *pTexts, UINT nSize, BOOL bByPos)
00517 {
00518 for (UINT i = 0; i < nSize; i++)
00519 SetMenuItemText (pMenu, pTexts [i].pszText, pTexts [i].nIDItem, bByPos);
00520 }
00521
00522 void fsODMenu::DrawCheckMark(CDC *dc, RECT &rc, BOOL bSelected, BOOL bGrayed)
00523 {
00524 int cx = rc.right - rc.left - 4 - 1;
00525
00526 int xs = rc.left + 2 + 2 + 1;
00527 int ys = rc.top + 2 + 2 + 3;
00528 int d1 = (cx-4) / 2;
00529 int d2 = (cx-4) - d1;
00530
00531 if (d1 == d2)
00532 d1--;
00533
00534 COLORREF clr;
00535
00536 if (bGrayed)
00537 clr = GetSysColor (COLOR_GRAYTEXT);
00538 else if (bSelected)
00539 clr = GetSysColor (COLOR_HIGHLIGHTTEXT);
00540 else
00541 clr = GetSysColor (COLOR_MENUTEXT);
00542
00543 CPen pen (PS_SOLID, 1, clr);
00544 CPen *oldpen = dc->SelectObject (&pen);
00545
00546 for (int i = 0; i < 2; i++)
00547 {
00548 dc->MoveTo (xs-i, ys+i);
00549 dc->LineTo (xs+d1-1, ys+d1+i*2-1);
00550 dc->LineTo (xs+d1+d2+i, ys-3+i);
00551
00552 if (i < 1)
00553 {
00554 dc->MoveTo (xs-i, ys+i+1);
00555 dc->LineTo (xs+d1-1, ys+d1+i*2);
00556 dc->LineTo (xs+d1+d2+i, ys-2+i);
00557 }
00558 }
00559
00560 dc->SelectObject (oldpen);
00561 }