00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "CATMenu.h"
00016 #include "CATWindow.h"
00017 #include <map>
00018 const CATUInt32 kCATMAXMENUHEIGHT = 400;
00019
00020
00021 void CATMenu::ClearMenu()
00022 {
00023 fIdMap.clear();
00024
00025 if (fMenuId == 0)
00026 return;
00027
00028
00029
00030
00031 HMENU menuId = 0;
00032 while (CATSUCCEEDED(fMenuStack.Pop(menuId)))
00033 {
00034 DestroyMenu(menuId);
00035 }
00036
00037
00038 DestroyMenu((HMENU)fMenuId);
00039 fMenuId = 0;
00040 }
00041
00042
00043 void CATMenu::DoMenu()
00044 {
00045 BuildMenu();
00046
00047 if (fMenuId == 0)
00048 return;
00049
00050 this->GetWindow()->OSHideToolTip();
00051
00052
00053
00054
00055 CATRect absRect = this->GetRectAbs(true);
00056
00057
00058
00059 CATInt32 vAlign = 0;
00060 CATInt32 left = absRect.left;
00061 CATInt32 top = absRect.top;
00062
00063 POINT cursorPos;
00064 ::GetCursorPos(&cursorPos);
00065
00066 switch (fMenuStyle)
00067 {
00068 case CATMENUSTYLE_UPMOUSE:
00069 vAlign = TPM_BOTTOMALIGN;
00070 left = cursorPos.x;
00071 top = cursorPos.y;
00072 break;
00073
00074 case CATMENUSTYLE_DOWNMOUSE:
00075 vAlign = TPM_TOPALIGN;
00076 left = cursorPos.x;
00077 top = cursorPos.y;
00078 break;
00079
00080 case CATMENUSTYLE_UP:
00081 vAlign = TPM_BOTTOMALIGN;
00082 break;
00083
00084 case CATMENUSTYLE_DOWN:
00085 default:
00086 vAlign = TPM_TOPALIGN;
00087 top = absRect.bottom;
00088 break;
00089 }
00090
00091 CATInt32 itemId = TrackPopupMenuEx( (HMENU)fMenuId,
00092 TPM_LEFTALIGN | vAlign| TPM_RETURNCMD | TPM_LEFTBUTTON,
00093 left,
00094 top,
00095 this->GetWindow()->OSGetWnd(),
00096 0);
00097
00098
00099 if (itemId == 0)
00100 return;
00101
00102 CATMENUITEM* selected = 0;
00103 std::map<CATUInt32,CATMENUITEM*>::iterator iter = fIdMap.find(itemId);
00104 if (iter != fIdMap.end())
00105 {
00106 selected = iter->second;
00107
00108 if (selected->AltCommand.IsEmpty() == false)
00109 {
00110
00111 ((CATGuiObj*)fParent)->OnCommand( CATCommand(selected->AltCommand,1.0f),0);
00112 return;
00113 }
00114
00115 this->SetCurItem(selected);
00116 }
00117 else
00118 {
00119 CATASSERT(false,"Invalid item id in menu!");
00120 }
00121
00122 ((CATGuiObj*)fParent)->OnCommand(this->GetCommand(),this);
00123 }
00124
00125
00126 void CATMenu::CreateSubMenu( std::vector<CATMENUITEM*>& itemList, HMENU parentMenu)
00127 {
00128 CATUInt32 numItems = itemList.size();
00129 CATUInt32 i;
00130
00131 for (i = 0; i < numItems; i++)
00132 {
00133 CATMENUITEM* curItem = itemList[i];
00134
00135
00136 if (curItem->IsSubMenu)
00137 {
00138 HMENU subMenu = ::CreatePopupMenu();
00139 fMenuStack.Push(subMenu);
00140 CreateSubMenu(curItem->Children, subMenu);
00141
00142
00143 MENUITEMINFO mi;
00144 mi.cbSize = sizeof(mi);
00145 mi.fMask = MIIM_ID | MIIM_DATA | MIIM_SUBMENU | MIIM_TYPE;
00146 mi.fType = MFT_OWNERDRAW;
00147 mi.dwItemData = (ULONG_PTR)curItem;
00148 mi.cch = curItem->DisplayText.Length();
00149 mi.dwTypeData = curItem->DisplayText.GetUnicodeBuffer();
00150 mi.hSubMenu = subMenu;
00151 mi.wID = this->fIdCount;
00152
00153
00154 this->fIdMap.insert(std::make_pair(fIdCount,curItem));
00155 fIdCount++;
00156
00157 ::InsertMenuItem(parentMenu,i,TRUE,&mi);
00158 curItem->DisplayText.ReleaseBuffer();
00159 }
00160 else
00161 {
00162
00163 MENUITEMINFO mi;
00164 mi.cbSize = sizeof(mi);
00165
00166
00167 if (curItem->DisplayText.IsEmpty() == false)
00168 {
00169 mi.fMask = MIIM_ID | MIIM_DATA | MIIM_STATE | MIIM_TYPE;
00170 mi.fState = (curItem == this->fCurSel)?MFS_CHECKED:MFS_ENABLED;
00171 mi.fType = MFT_OWNERDRAW;
00172 mi.dwItemData = (ULONG_PTR)curItem;
00173 mi.cch = curItem->DisplayText.Length();
00174 mi.dwTypeData = curItem->DisplayText.GetUnicodeBuffer();
00175 mi.wID = this->fIdCount;
00176 }
00177
00178 else
00179 {
00180 mi.fMask = MIIM_FTYPE | MIIM_DATA;
00181 mi.fType = MFT_SEPARATOR | MFT_OWNERDRAW;
00182 mi.dwItemData = (ULONG_PTR)curItem;
00183
00184 }
00185
00186
00187 this->fIdMap.insert(std::make_pair(fIdCount,curItem));
00188 fIdCount++;
00189
00190 ::InsertMenuItem(parentMenu,i,TRUE,&mi);
00191 curItem->DisplayText.ReleaseBuffer();
00192 }
00193 }
00194 }
00195
00196 void CATMenu::BuildMenu()
00197 {
00198 ClearMenu();
00199 fMenuId = (CATUInt32)::CreatePopupMenu();
00200 CreateSubMenu(this->fRootList, (HMENU)fMenuId);
00201 fMenuDirty = false;
00202 }
00203
00204 void CATMenu::OSOnMeasureItem(CATMENUITEM* menuItem, CATUInt32& width, CATUInt32& height)
00205 {
00206
00207 CATFONT measureFont = this->GetWindow()->OSGetFont(fFontName,fFontSize);
00208 HWND hwnd = this->GetWindow()->OSGetWnd();
00209 HDC curDC = ::GetDC(hwnd);
00210 CATFONT oldFont = (HFONT)::SelectObject(curDC,measureFont);
00211
00212
00213 SIZE textSize;
00214 textSize.cx = 0;
00215 textSize.cy = 0;
00216 CATString filtered = FilterGUIString(menuItem->DisplayText);
00217
00218 if (filtered.IsEmpty() == false)
00219 {
00220 ::GetTextExtentExPoint( curDC,
00221 filtered,
00222 filtered.Length(),
00223 this->GetWindow()->GetRect().Width(),
00224 NULL,
00225 NULL,
00226 &textSize);
00227
00228 }
00229
00230 height = CATMax((CATUInt32)(textSize.cy + 2), (CATUInt32)10 );
00231 width = textSize.cx + 25;
00232
00233
00234 ::SelectObject(curDC,oldFont);
00235 ::ReleaseDC(hwnd,curDC);
00236 this->GetWindow()->OSReleaseFont(measureFont);
00237
00238 if (menuItem->BaseMenu->ForceWidth())
00239 {
00240 CATRect controlRect = menuItem->BaseMenu->GetRect();
00241
00242
00243 width = controlRect.Width() - (textSize.cx/filtered.Length())*1.5;
00244 }
00245 }
00246
00247 void CATMenu::OSOnDrawItem( CATMENUITEM* menuItem, bool selected, CATDRAWCONTEXT hDC, CATRect rect )
00248 {
00249 CATColor colorFore = GetColorFore();
00250 CATColor colorBack = GetColorBack();
00251
00252 RECT drawRect;
00253 ::SetRect(&drawRect, rect.left, rect.top,rect.right,rect.bottom);
00254
00255 if (selected & ODS_SELECTED)
00256 {
00257 CATSwap(colorFore,colorBack);
00258 }
00259
00260 HBRUSH bgBrush = ::CreateSolidBrush(RGB(colorBack.r, colorBack.g, colorBack.b));
00261 ::FillRect(hDC, &drawRect, bgBrush);
00262
00263
00264 if ((menuItem == fCurSel) && (fShowSel))
00265 {
00266 CATInt32 startX = drawRect.left + 2;
00267 CATInt32 startY = ((drawRect.top + drawRect.bottom)/2);
00268
00269 HPEN fgPen = ::CreatePen( PS_SOLID,2,RGB(colorFore.r, colorFore.g, colorFore.b));
00270 HPEN oldPen = (HPEN)::SelectObject(hDC, fgPen);
00271
00272 ::MoveToEx( hDC,
00273 startX,
00274 startY - 3,
00275 0);
00276
00277 ::LineTo( hDC,
00278 startX + 5,
00279 startY );
00280
00281 ::MoveToEx( hDC,
00282 startX,
00283 startY + 3,
00284 0);
00285
00286 ::LineTo( hDC,
00287 startX + 5,
00288 startY );
00289
00290 ::SelectObject(hDC, oldPen);
00291 ::DeleteObject(fgPen);
00292 }
00293
00294
00295
00296 if (menuItem->IsSubMenu)
00297 {
00298 CATInt32 startX = drawRect.right - 8;
00299 CATInt32 startY = ((drawRect.top + drawRect.bottom)/2);
00300
00301 HPEN fgPen = ::CreatePen( PS_SOLID,2,RGB(colorFore.r, colorFore.g, colorFore.b));
00302 HPEN oldPen = (HPEN)::SelectObject(hDC, fgPen);
00303
00304 ::MoveToEx( hDC,
00305 startX,
00306 startY - 3,
00307 0);
00308
00309 ::LineTo( hDC,
00310 startX + 5,
00311 startY );
00312
00313 ::MoveToEx( hDC,
00314 startX,
00315 startY + 3,
00316 0);
00317
00318 ::LineTo( hDC,
00319 startX + 5,
00320 startY );
00321
00322
00323 ::SelectObject(hDC, oldPen);
00324 ::DeleteObject(fgPen);
00325 }
00326
00327 int oldMode = ::SetBkMode(hDC,TRANSPARENT);
00328 COLORREF oldColor = ::SetTextColor(hDC,RGB(colorFore.r,colorFore.g,colorFore.b));
00329
00330 if (menuItem->DisplayText.IsEmpty())
00331 {
00332
00333 CATInt32 yPos = (drawRect.top + drawRect.bottom)/2;
00334 HPEN linePen = ::CreatePen(PS_SOLID,1,RGB(colorFore.r, colorFore.g, colorFore.b));
00335 HPEN oldPen = (HPEN)::SelectObject(hDC, linePen);
00336
00337 ::MoveToEx (hDC, drawRect.left + 2, yPos, NULL);
00338 ::LineTo (hDC, drawRect.right - 2, yPos);
00339
00340 ::SelectObject(hDC,oldPen);
00341 ::DeleteObject(oldPen);
00342
00343 }
00344 else
00345 {
00346
00347 CATFONT drawFont = this->GetWindow()->OSGetFont(fFontName,fFontSize);
00348 CATFONT oldFont = (HFONT)::SelectObject(hDC,drawFont);
00349
00350
00351 DWORD textStyle = DT_LEFT | DT_VCENTER | DT_END_ELLIPSIS | DT_SINGLELINE;
00352
00353 RECT rcText;
00354 ::SetRect(&rcText, drawRect.left, drawRect.top, drawRect.right, drawRect.bottom);
00355 rcText.left += 10;
00356
00357
00358 CATString filtered = FilterGUIString(menuItem->DisplayText);
00359 ::DrawTextEx( hDC,
00360 filtered.GetUnicodeBuffer(),
00361 filtered.LengthCalc(),
00362 &rcText,textStyle,NULL);
00363 filtered.ReleaseBuffer();
00364 ::SelectObject(hDC,oldFont);
00365 this->GetWindow()->OSReleaseFont(drawFont);
00366 }
00367
00368
00369
00370
00371
00372 ::SetTextColor(hDC,oldColor);
00373 ::SetBkMode(hDC, oldMode);
00374
00375 ::DeleteObject(bgBrush);
00376 ::ExcludeClipRect(hDC,drawRect.left,drawRect.top,drawRect.right, drawRect.bottom);
00377 }