xoblite™ / Blackbox for Windows bb5 | RC6 preview | 0.25.2.14
http://xoblite.net/
MenuCommon Class Reference

#include <MenuCommon.h>

Public Member Functions

 MenuCommon ()
 
 ~MenuCommon ()
 
void Initialize (HINSTANCE hInst)
 
void Configure ()
 
void UpdateMainMenu (bool createAllMenus)
 
void ParseFolder (FILE *file, Menu *pMenu)
 
bool ParseLine (FILE *file, Menu *pMenu, char *pszLine)
 
void AddHeaderItem (Menu *pMenu, LPSTR pszTitle)
 
void AddFooterItem (Menu *pMenu, LPSTR pszTitle)
 
void InsertFolder (Menu *pMenu, char *pszFolder, int menuType, bool includeSubFolders)
 
bool Hide (int index=0)
 
MenuItemCreateMenuItem (Menu *pMenu, int itemType, char *pszCommand, char *pszArgument, char *pszTitle, bool isSelected)
 
MenuItemCreateMenuItemUnicode (Menu *pMenu, int itemType, char *pszCommand, char *pszArgument, wchar_t *pszTitleUnicode, bool isSelected)
 
void Invoke (MenuItem *item, int button)
 
void HideAfterInvoke (MenuItem *item, int button)
 
void DrawMenuBullet (FolderItem *item, HDC hDC, int nTop, int type)
 
void DrawMenuIndicator (MenuItem *item, HDC hDC, int nTop)
 
int DrawMenuPinned (MenuItem *item, HDC hDC, RECT itemRect)
 
bool FindActiveAndDeactivate (Menu *m, bool repaint)
 
void FindAndSelect (MenuItem *item, LPSTR title, bool selected)
 
void ScrollToItem (Menu *m, MenuItem *item)
 

Public Attributes

vector< Menu * > m_MenusVector
 
HINSTANCE hInst
 
char m_szHotListName [256]
 
DWORD m_nGradientTitle
 
DWORD m_nGradientEntry
 
DWORD m_nGradientSelEntry
 
int m_nTitleHeight
 
bool m_nTitleDisabled
 
int m_nSubmenuHeight
 
int m_nMarginHeight
 
int m_nSeparatorHeight
 
int m_nGripHeight
 
bool m_nGripDisabled
 
int m_nLeftIndent
 
int m_nRightIndent
 
int m_nBulletSize
 
int m_nBulletPosition
 
int m_nBulletStyle
 
Menum_pMainMenu
 
Menum_pStylesMenu
 
Menum_pThemesMenu
 
Menum_pWorkspacesMenu
 
Menum_pConfigMenu
 
Menum_pPluginMenu
 
HFONT m_hTitleFont
 
HFONT m_hFrameFont
 
HFONT m_hGripFont
 
HFONT m_hEditStringFont
 
MenuItemcurrentStyleMenuItem
 
int stylesMenusPinned
 

Constructor & Destructor Documentation

◆ MenuCommon()

MenuCommon::MenuCommon ( )
72{
73 m_pMainMenu = NULL;
74 m_pStylesMenu = NULL;
75 m_pThemesMenu = NULL;
76 m_pWorkspacesMenu = NULL;
77 m_pConfigMenu = NULL;
78 m_pPluginMenu = NULL;
79
80 m_hTitleFont = 0;
81 m_hFrameFont = 0;
82 m_hGripFont = 0;
84
86
87 // Start GDI+... (used by e.g. the menu PreviewItem)
88// GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
89}
HFONT m_hEditStringFont
Definition MenuCommon.h:127
Menu * m_pMainMenu
Definition MenuCommon.h:117
Menu * m_pConfigMenu
Definition MenuCommon.h:121
HFONT m_hTitleFont
Definition MenuCommon.h:124
Menu * m_pWorkspacesMenu
Definition MenuCommon.h:120
Menu * m_pThemesMenu
Definition MenuCommon.h:119
Menu * m_pStylesMenu
Definition MenuCommon.h:118
MenuItem * currentStyleMenuItem
Definition MenuCommon.h:129
HFONT m_hGripFont
Definition MenuCommon.h:126
HFONT m_hFrameFont
Definition MenuCommon.h:125
Menu * m_pPluginMenu
Definition MenuCommon.h:122

◆ ~MenuCommon()

MenuCommon::~MenuCommon ( )
94{
95 if (m_pMainMenu)
96 {
97 // Unsubscribe to previously subscribed Blackbox messages...
98 SendMessage (GetBBWnd(), BB_UNREGISTERMESSAGE, (WPARAM)m_MenusVector[0]->GetWindow(), (LPARAM)menuCommonMessageSubscription);
99 }
100
101 // Delete all menu objects...
102 if (m_pMainMenu) delete m_pMainMenu;
103 if (m_pStylesMenu) delete m_pStylesMenu;
104 if (m_pThemesMenu) delete m_pThemesMenu;
106 if (m_pConfigMenu) delete m_pConfigMenu;
108
109 // Delete all menu fonts...
110 DeleteObject(m_hTitleFont);
111 DeleteObject(m_hFrameFont);
112 DeleteObject(m_hGripFont);
113 DeleteObject(m_hEditStringFont);
114
115 // Shutdown GDI+... (used by e.g. the menu PreviewItem)
116// GdiplusShutdown(gdiplusToken);
117}
void DelMenu(Menu *PluginMenu)
Definition BBApi.cpp:2823
HWND GetBBWnd()
Definition BBApi.cpp:128
#define BB_UNREGISTERMESSAGE
Definition BBApi.h:143
int menuCommonMessageSubscription[]
Definition MenuCommon.cpp:67
vector< Menu * > m_MenusVector
Definition MenuCommon.h:90

Member Function Documentation

◆ Initialize()

void MenuCommon::Initialize ( HINSTANCE hInst)
125{
126 hInst = hInstance;
127
128 // Read menu configuration and update menus...
129 Configure();
130 UpdateMainMenu(true);
131
132 // Assign a default menu root if not explicitly defined...
133 if (!m_pMainMenu)
134 {
135 if (!m_MenusVector.empty()) m_pMainMenu = m_MenusVector[0];
136 }
137
138 if (m_pMainMenu)
139 {
140 // Subscribe to Blackbox messages applicable to menus...
141 SendMessage(GetBBWnd(), BB_REGISTERMESSAGE, (WPARAM) m_MenusVector[0]->GetWindow(), (LPARAM)menuCommonMessageSubscription);
142 }
143}
#define BB_REGISTERMESSAGE
Definition BBApi.h:142
void Configure()
Definition MenuCommon.cpp:150
void UpdateMainMenu(bool createAllMenus)
Definition MenuCommon.cpp:451
HINSTANCE hInst
Definition MenuCommon.h:94

◆ Configure()

void MenuCommon::Configure ( )
151{
152 // menu.title configuration
153
154 //====================
155
156 // menu.frame configuration
157
158 //====================
159
160 // menu.hilite (= selected item) configuration
161
162 //====================
163
164 // menu.frame top/bottom padding
165
166 //====================
167
168 // Menu bullet configuration...
171 if (!_stricmp(pSettings->menuBulletPosition, "LeftJustify") || !_stricmp(pSettings->menuBulletPosition, "Left")) m_nBulletPosition = DT_LEFT;
172 else m_nBulletPosition = DT_RIGHT;
173
174 //====================
175
176 SIZE size;
177 HDC fonthdc = CreateDC("DISPLAY", NULL, NULL, NULL);
178
179 //====================
180
181 // Create the menu.title font... (common for all menus)
182 if (m_hTitleFont) DeleteObject(m_hTitleFont);
183 if (strlen(pSettings->MenuTitle->Font)) m_hTitleFont = CreateFont(pSettings->MenuTitle->FontHeight, 0, 0, 0, pSettings->MenuTitle->FontWeight, false, false, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH|FF_DONTCARE, pSettings->MenuTitle->Font);
184 else
185 {
186 LOGFONT logFont;
187 SystemParametersInfo(SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
188 m_hTitleFont = CreateFontIndirect(&logFont);
189 }
190
191 // Calculate the menu.title item height... (common for all menus)
193 {
194 m_nTitleDisabled = true;
196 }
197 else
198 {
199 m_nTitleDisabled = false;
200
201 HGDIOBJ oldTitleFont = SelectObject(fonthdc, m_hTitleFont);
202 if (!_stricmp(pSettings->MenuTitle->Font, "nu"))
203 {
204 // ...special handling of an odd font...
205 size.cy = 7 * pSettings->scalingFactorHiDPI;
206 }
207 else GetTextExtentPoint32(fonthdc, "TQkgfp/", 8, &size);
208
210 {
211 // Note: We add to the height for outlined text only; for text shadows we don't [yet?] as they're supposed to be just that, shadows...
212 size.cy += (2 * pSettings->scalingFactorHiDPI);
213 }
214
216 {
218
219// char msg[255];
220// sprintf(msg, "MenuCommon -> m_nTitleHeight == %d", m_nTitleHeight);
221// SendMessage(GetBBWnd(), BB_CONSOLEMESSAGE, (WPARAM)CONSOLE_INFORMATION_MESSAGE, (LPARAM)msg);
222 }
223 else
224 {
226 {
227 if (pSettings->MenuTitle->bevelposition == BEVEL2) m_nTitleHeight = size.cy + 6; // ...i.e. above+below the text we have a bevel of 2 pixels + a "minimum" padding of 1 pixel -> adding 6 pixels to the height...
228 else m_nTitleHeight = size.cy + 4; // ...i.e. above+below the text we have a bevel of 1 pixel + a "minimum" padding of 1 pixel -> adding 4 pixels to the height...
229 }
230 else m_nTitleHeight = size.cy + 2; // ...i.e. above+below the text we only have a "minimum" padding of 1 pixel -> adding 2 pixels to the height...
231
232 m_nTitleHeight += (2 * pSettings->MenuTitle->borderWidth); // ...and then we add the border on each side to the height as well. Done!
233 }
234
235// int minTitleFontHeight = pSettings->MenuTitle->FontHeight + (2 * pSettings->MenuTitle->borderWidth);
236// if (pSettings->MenuTitle->FontOutline) minTitleFontHeight += 2;
237// if (m_nTitleHeight < minTitleFontHeight) m_nTitleHeight = minTitleFontHeight;
238
239// if (!pSettings->doubleScaleHiDPI) m_nTitleHeight = m_nTitleHeight | 1; // Force odd sized height for non-HiDPI menu bullets to be vertically centered... (cf. heights with HiDPI will instead "always" be even due to the 2x everything)
240
241 SelectObject(fonthdc, oldTitleFont);
242 }
243
244 //====================
245
246 // Create the menu.frame font... (common for all menus)
247 if (m_hFrameFont) DeleteObject(m_hFrameFont);
248 if (strlen(pSettings->MenuFrame->Font)) m_hFrameFont = CreateFont(pSettings->MenuFrame->FontHeight, 0, 0, 0, pSettings->MenuFrame->FontWeight, false, false, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH|FF_DONTCARE, pSettings->MenuFrame->Font);
250
251 // Calculate the menu.frame item == menu hilite item height... (common for all menus)
252 HGDIOBJ oldFrameFont = SelectObject(fonthdc, m_hFrameFont);
253 if (!_stricmp(pSettings->MenuTitle->Font, "nu"))
254 {
255 // ...special handling of an odd font...
256 size.cy = 7 * pSettings->scalingFactorHiDPI;
257 }
258 else GetTextExtentPoint32(fonthdc, "TQkgfp/", 8, &size);
259
261 {
262 // Note: We add to the height for outlined text only; for text shadows we don't [yet?] as they're supposed to be just that, shadows...
263 size.cy += (2 * pSettings->scalingFactorHiDPI);
264 }
265
266// if (pSettings->MenuFrame->marginWidth > 0)
267// {
268// m_nSubmenuHeight = size.cy + (2 * pSettings->MenuFrame->marginWidth);
269// }
270// else
271 {
273 {
274// if (pSettings->MenuActive->bevelposition == BEVEL2) m_nSubmenuHeight = size.cy + 4;
275// else m_nSubmenuHeight = size.cy + 2;
276 if (pSettings->MenuActive->bevelposition == BEVEL2) m_nSubmenuHeight = size.cy + 6; // ...i.e. above+below the text we have a bevel of 2 pixels + a "minimum" padding of 1 pixel -> adding 6 pixels to the height...
277 else m_nSubmenuHeight = size.cy + 4; // ...i.e. above+below the text we have a bevel of 1 pixel + a "minimum" padding of 1 pixel -> adding 4 pixels to the height...
278 }
279 else m_nSubmenuHeight = size.cy + 2; // ...i.e. above+below the text we only have a "minimum" padding of 1 pixel -> adding 2 pixels to the height...
280
281 m_nSubmenuHeight += (2 * pSettings->MenuActive->borderWidth); // ...and then we add the border on each side to the height as well. Done!
282 }
283
284 if (m_nSubmenuHeight < pSettings->MenuFrame->FontHeight) m_nSubmenuHeight = pSettings->MenuFrame->FontHeight; // Failsafe? (e.g. potential menu.frame/hilite mismatch corner cases)
285
286// if (!pSettings->doubleScaleHiDPI) m_nSubmenuHeight = m_nSubmenuHeight | 1; // Force odd sized height for non-HiDPI menu bullets to be vertically centered... (cf. heights with HiDPI will instead "always" be even due to the 2x everything)
287
288 SelectObject(fonthdc, oldFrameFont);
289
290 //====================
291
293 {
294 m_nGripDisabled = false;
295
296 // Create the menu.grip font... (common for all menus)
297 if (m_hGripFont) DeleteObject(m_hGripFont);
298 if (strlen(pSettings->MenuGrip->Font)) m_hGripFont = CreateFont(pSettings->MenuGrip->FontHeight, 0, 0, 0, pSettings->MenuGrip->FontWeight, false, false, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, pSettings->MenuGrip->Font);
300
301 // Calculate the menu.grip item height... (common for all menus)
302 if (pSettings->MenuGrip->FontHeight >= 2)
303 {
304 // menu.grip.fontHeight was defined in the style file
305 // -> use as input to grip height regardless whether text is drawn or not...
306 HGDIOBJ oldGripFont = SelectObject(fonthdc, m_hGripFont);
307 if (!_stricmp(pSettings->MenuTitle->Font, "nu"))
308 {
309 // ...special handling of an odd font...
310 size.cy = 7 * pSettings->scalingFactorHiDPI;
311 }
312 else GetTextExtentPoint32(fonthdc, "TQkgfp/", 8, &size);
313
315 {
316 // Note: We add to the height for outlined text only; for text shadows we don't [yet?] as they're supposed to be just that, shadows...
317 size.cy += (2 * pSettings->scalingFactorHiDPI);
318 }
319
320 if (pSettings->MenuGrip->marginWidth != 0)
321 {
323 }
324 else
325 {
327 {
328 if (pSettings->MenuGrip->bevelposition == BEVEL2) m_nGripHeight = size.cy + 6; // ...i.e. above+below the text we have a bevel of 2 pixels + a "minimum" padding of 1 pixel -> adding 6 pixels to the height...
329 else m_nGripHeight = size.cy + 4; // ...i.e. above+below the text we have a bevel of 1 pixel + a "minimum" padding of 1 pixel -> adding 4 pixels to the height...
330 }
331 else m_nGripHeight = size.cy + 2; // ...i.e. above+below the text we only have a "minimum" padding of 1 pixel -> adding 2 pixels to the height...
332
333 m_nGripHeight += (2 * pSettings->MenuGrip->borderWidth); // ...and then we add the border on each side to the height as well. Done!
334 }
335
336// int minimumGripHeight = pSettings->MenuGrip->FontHeight + (2 * pSettings->MenuGrip->borderWidth);
337// if (pSettings->MenuGrip->FontOutline) minimumGripHeight += 2;
338// if (m_nGripHeight < minimumGripHeight) m_nGripHeight = minimumGripHeight;
339
340 SelectObject(fonthdc, oldGripFont);
341 }
342 else
343 {
344 // menu.grip.fontHeight was not defined in the style file
345 // -> menu.grip.marginWidth defines the grip height (excluding borders)...
346// int tempHeight = pSettings->MenuGrip->marginWidth;
347// if (tempHeight < 4) tempHeight = 4;
348// m_nGripHeight = tempHeight + (pSettings->MenuGrip->borderWidth * 2);
349 if (pSettings->MenuGrip->marginWidth == 0)
350 {
351 m_nGripDisabled = true;
353 }
354 else
355 {
357 {
359 }
361 }
362 }
363/*
364 int tempHeight;
365
366 if (pSettings->MenuGrip->FontHeight > 0)
367 {
368 // menu.grip.fontHeight was defined in the style file -> use as input to grip height regardless whether text is drawn or not...
369 tempHeight = pSettings->MenuGrip->FontHeight + (pSettings->MenuGrip->marginWidth * 2);
370 }
371 else
372 {
373 // menu.grip.fontHeight was not defined in the style file -> menu.grip.marginWidth defines the grip height (excluding borders)...
374 tempHeight = pSettings->MenuGrip->marginWidth;
375 }
376
377 if (tempHeight < 4) tempHeight = 4;
378 m_nGripHeight = tempHeight + (pSettings->MenuGrip->borderWidth * 2);
379*/
380 }
381 else // -> menu.grip disabled
382 {
383 m_nGripDisabled = true;
385 }
386
387 //====================
388
389 // Create the font for the StringItem editor popup window... (common for all menus, always using the Windows default font - Segoe UI - for easy readability)
390 if (m_hEditStringFont) DeleteObject(m_hEditStringFont);
391 int editStringFontSize = (15 * pSettings->scalingFactorHiDPI);
392 m_hEditStringFont = CreateFont(editStringFontSize, 0, 0, 0, FW_BOLD, false, false, false, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Segoe UI");
393
394 //====================
395
396 DeleteDC(fonthdc);
397
398 //====================
399
400 // Calculate the height of menu separators... (common for all menus)
402
403 // Calculate the height of menu margins... (common for all menus)
405
406 //====================
407
408 // Calculate the width of menu indents... (common for all menus)
409// int smallIndent = 3 + pSettings->MenuFrame->marginWidth + pSettings->MenuFrame->borderWidth;
410// if (pSettings->doubleScaleHiDPI) smallIndent += 3;
411// int bulletIndent = 13 + pSettings->MenuFrame->marginWidth + pSettings->MenuFrame->borderWidth;
412// if (pSettings->doubleScaleHiDPI) bulletIndent += 13;
414// int bulletIndent = (2 * (pSettings->MenuFrame->borderWidth + pSettings->MenuFrame->marginWidth)) + m_nBulletSize + ((m_nSubmenuHeight - m_nBulletSize) / 2);
416
418 {
419 // If no bullet is used, we use equal left/right indents...
420 // (using large indent to still fit bool indicators)
421 m_nLeftIndent = bulletIndent;
422 m_nRightIndent = bulletIndent;
423 }
424 else if (m_nBulletPosition == DT_LEFT)
425 {
426 // If the bullet is on the left, we make the right indent smaller...
427 m_nLeftIndent = bulletIndent;
428 m_nRightIndent = smallIndent;
429 }
430 else
431 {
432 // If the bullet is on the right, we make the left indent smaller...
433 m_nLeftIndent = smallIndent;
434 m_nRightIndent = bulletIndent;
435 }
436
437 //====================
438
439 // Calculate submenu gap for rounded corner menus...
440 // (nb. dependence toward the HiDPI adjustments calculated above, so order is important)
441 if (pSettings->MenuFrame->borderWidth > 0) pSettings->submenuGap = (pSettings->MenuFrame->borderWidth * 2); // Note: Use borderWidth*2 due to how menu borders overlap for non-rounded menus!
444}
Settings * pSettings
Definition Blackbox.cpp:46
#define BEVEL_FLAT
Definition BBApi.h:105
#define BEVEL2
Definition BBApi.h:109
#define MENU_BULLET_EMPTY
Definition Settings.h:54
int m_nTitleHeight
Definition MenuCommon.h:102
int m_nRightIndent
Definition MenuCommon.h:111
int m_nGripHeight
Definition MenuCommon.h:107
bool m_nTitleDisabled
Definition MenuCommon.h:103
int m_nLeftIndent
Definition MenuCommon.h:110
int m_nBulletSize
Definition MenuCommon.h:113
int m_nBulletStyle
Definition MenuCommon.h:115
int m_nSubmenuHeight
Definition MenuCommon.h:104
int m_nMarginHeight
Definition MenuCommon.h:105
bool m_nGripDisabled
Definition MenuCommon.h:108
int m_nSeparatorHeight
Definition MenuCommon.h:106
int m_nBulletPosition
Definition MenuCommon.h:114
int scalingFactorHiDPI
Definition Settings.h:327
StyleItem * MenuFrame
Definition Settings.h:434
int submenuGap
Definition Settings.h:182
StyleItem * MenuTitle
Definition Settings.h:433
int menuBullet
Definition Settings.h:539
StyleItem * MenuGrip
Definition Settings.h:436
StyleItem * MenuActive
Definition Settings.h:435
char menuBulletPosition[MAX_LINE_LENGTH]
Definition Settings.h:542
int borderWidth
Definition BBApi.h:417
int bevelstyle
Definition BBApi.h:400
bool parentRelative
Definition BBApi.h:403
bool FontOutline
Definition BBApi.h:430
int bevelposition
Definition BBApi.h:401
int FontWeight
Definition BBApi.h:410
int marginWidth
Definition BBApi.h:416
int FontHeight
Definition BBApi.h:409
char Font[128]
Definition BBApi.h:413

◆ UpdateMainMenu()

void MenuCommon::UpdateMainMenu ( bool createAllMenus)
452{
454
455 FILE *file = FileOpen(pSettings->menuFile);
456
457 //====================
458
459 // Failsafe: The menu.rc configuration file is considered invalid if it does not contain a [begin]...
460 if (!_stricmp(ReadString(pSettings->menuFile, "[begin]", ""), ""))
461 {
462 FileClose(file);
463
464 char msg[MAX_LINE_LENGTH];
465 strcpy(msg, pSettings->menuFile);
466 strcat(msg,
467 "\n\nYour menu configuration file does not seem to be valid. \n\n"
468 "Do you want to create a new menu configuration file with default items? \n\n"
469 "(clicking \"No\" will open your current menu configuration file for editing) ");
470
471 if (MessageBox(GetDesktopWindow(), msg, "xoblite", MB_YESNO | MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST) == IDYES)
472 {
474 }
475 else PostMessage(GetBBWnd(), BB_EDITFILE, 1, 0); // Open the current menu.rc file for editing...
476
477 file = FileOpen(pSettings->menuFile);
478 }
479
480 //====================
481
482 // Create the Main menu...
483 if (createAllMenus)
484 {
485 m_pMainMenu = new Menu(hInst);
486 HANDLE hFind = FindFirstFile(pSettings->menuFile, &m_pMainMenu->data);
487 FindClose(hFind);
488 m_MenusVector.push_back(m_pMainMenu);
489 }
490 else m_pMainMenu->DeleteMenuItems();
491
493
494 m_pMainMenu->Invalidate();
495 m_pMainMenu->Validate();
496
497 FileClose(file);
498
499 //====================
500
501 if (createAllMenus)
502 {
503 // Create the Styles menu...
504 m_pStylesMenu = new StylesMenu("Styles");
505 m_MenusVector.push_back(m_pStylesMenu);
506
507 // Create the Themes menu...
508 m_pThemesMenu = new ThemesMenu("Themes");
509 m_MenusVector.push_back(m_pThemesMenu);
510
511 // Create the Workspaces menu...
512 m_pWorkspacesMenu = new WorkspacesMenu("Workspaces");
514
515 // Create the Configuration menu...
516 m_pConfigMenu = new ConfigMenu("Configuration");
517 m_MenusVector.push_back(m_pConfigMenu);
518 }
519}
FILE * FileOpen(LPCSTR szPath)
Definition BBApi.cpp:239
LPSTR ReadString(LPCSTR fp, LPCSTR szString, LPSTR szDefault)
Definition BBApi.cpp:544
bool FileExists(LPCSTR szFileName)
Definition BBApi.cpp:819
bool FileClose(FILE *fp)
Definition BBApi.cpp:254
#define BB_EDITFILE
Definition BBApi.h:155
#define MAX_LINE_LENGTH
Definition BBApi.h:64
void ParseFolder(FILE *file, Menu *pMenu)
Definition MenuCommon.cpp:526
void WriteDefaultMenu()
Definition Settings.cpp:894
char menuFile[MAX_LINE_LENGTH]
Definition Settings.h:174

◆ ParseFolder()

void MenuCommon::ParseFolder ( FILE * file,
Menu * pMenu )
527{
528 for (;;)
529 {
530 char szLineBuffer[MAX_LINE_LENGTH] = "";
531
532 if (!ReadNextCommand(file, szLineBuffer, sizeof(szLineBuffer))) break;
533 if (!ParseLine(file, pMenu, szLineBuffer)) break;
534 }
535}
bool ReadNextCommand(FILE *f, LPSTR szBuffer, DWORD dwLength)
Definition BBApi.cpp:713
Menu * pMenu
Definition Blackbox.cpp:40
bool ParseLine(FILE *file, Menu *pMenu, char *pszLine)
Definition MenuCommon.cpp:544

◆ ParseLine()

bool MenuCommon::ParseLine ( FILE * file,
Menu * pMenu,
char * pszLine )
545{
546 itemCommand[0] = itemLabel[0] = itemData[0] = '\0';
547 MenuItem* pMenuItem = NULL;
548 LPSTR tokenBegin, tokenEnd, tokenPtr = pszLine;
549 int nLen;
550
551 //====================
552
553 // Skip whitespaces at the beginning of the line...
554 while (*pszLine && isspace(*pszLine)) pszLine++;
555/*
556 // Check if the line is a valid config line (if it contains a [ it's considered ok)
557 if (!strchr(pszLine, '[')) return true;
558
559 // Substitute any applivation environment variables, e.g. "$ProgramFiles$"
560 if (strchr(pszLine, '$')) ReplaceShellFolders(pszLine);
561 // Substitute any "%VAR%" for the VAR value if it's a real VAR
562 if (strchr(pszLine, '%')) ReplaceEnvVars(pszLine);
563
564 // Extract the menu command tag (e.g. [exec])...
565 strcpy(itemData, Tokenize(pszLine, itemCommand, " "));
566 // Check if the line contains a label tag and if so extract it...
567 if (*itemData == '(') strcpy(itemData, Tokenize(itemData+1, itemLabel, ")"));
568 // Check if the line contains a data tag and if so extract it...
569 if (*itemData == '{') Tokenize(itemData+1, itemData, "}");
570*/
571
572 // Extract the menu command tag (e.g. [exec])...
573 tokenBegin = strchr(tokenPtr, '[');
574 if (tokenBegin != NULL)
575 {
576 tokenEnd = strchr(tokenBegin, ']');
577 if (tokenEnd != NULL)
578 {
579 nLen = tokenEnd-tokenBegin+1;
580 if (nLen > 0)
581 {
582// strncpy(itemCommand, tokenBegin, nLen);
583 strncpy_s(itemCommand, sizeof(itemCommand), tokenBegin, nLen);
584 itemCommand[nLen] = '\0';
585 }
586 else return true;
587 tokenPtr = tokenEnd+1;
588 }
589 else return true;
590 }
591 else return true; // Not a valid menu config line since it does not include a command token, skip to the next line...
592
593 // Check if the line contains a label tag and if so extract it...
594 tokenBegin = strchr(tokenPtr, '(');
595 if (tokenBegin != NULL)
596 {
597 tokenEnd = strchr(tokenBegin++, ')');
598 if (tokenEnd != NULL)
599 {
600 nLen = tokenEnd-tokenBegin;
601 if (nLen > 0)
602 {
603// strncpy(itemLabel, tokenBegin, nLen);
604 strncpy_s(itemLabel, sizeof(itemLabel), tokenBegin, nLen);
605 itemLabel[nLen] = '\0';
606 }
607 tokenPtr = tokenEnd+1;
608 }
609 }
610
611 // Check if the line contains a data tag and if so extract it...
612 tokenBegin = strchr(tokenPtr, '{');
613 if (tokenBegin != NULL)
614 {
615 tokenEnd = strchr(tokenBegin++, '}');
616 if (tokenEnd != NULL)
617 {
618 nLen = tokenEnd-tokenBegin;
619 if (nLen > 0)
620 {
621// strncpy(itemData, tokenBegin, nLen);
622 strncpy_s(itemData, sizeof(itemData), tokenBegin, nLen);
623 itemData[nLen] = '\0';
624 // Substitute any applivation environment variables, e.g. "$ProgramFiles$"
625 if (strchr(itemData, '$')) ReplaceShellFolders(itemData);
626 // Substitute any "%VAR%" for the VAR value if it's a real VAR
627 if (strchr(itemData, '%')) ReplaceEnvVars(itemData);
628 }
629 }
630 }
631
632 //====================
633
634 // If the line contains [begin] we create a title item...
635 if (!_stricmp(itemCommand, "[begin]"))
636 {
637 // If no menu title has been defined, display xoblite version...
638 if (!_stricmp(itemLabel, ""))
639 {
640 strcpy(m_szHotListName, "xoblite ");
641 strcat(m_szHotListName, (LPSTR)GetBBVersion());
642 }
643 else strcpy(m_szHotListName, itemLabel);
644
646 return true;
647 }
648
649 //====================
650
651 // If the line contains [submenu] we create a subfolder...
652 else if (!_stricmp(itemCommand, "[submenu]"))
653 {
654 // NOTE: We need to save the label string as the ParseLine function uses a single
655 // set of temporary item strings which is also used when parsing the subfolder items
656 // (i.e. the current item label will be replaced by subfolder item labels)
657 char folderLabel[MAX_LINE_LENGTH];
658 strcpy(folderLabel, itemLabel);
659
660 Menu* pSub = new Menu(hInst);
661 AddHeaderItem(pSub, strlen(itemData) ? itemData : itemLabel);
662 ParseFolder(file, pSub);
663
664 pSub->Invalidate();
665 pSub->Validate();
666
667 pMenuItem = new FolderItem(pSub, folderLabel, NULL);
668 }
669
670 //====================
671
672 // If the line contains [end] we terminate the line parsing by returning false...
673 else if (!_stricmp(itemCommand, "[end]"))
674 {
676 return false;
677 }
678
679 //====================
680
681 // If the line contains [include] we parse the file to be included...
682 else if (!_stricmp(itemCommand, "[include]"))
683 {
684 char path[MAX_LINE_LENGTH];
685 strcpy(path, itemLabel);
686 if (strchr(path, '\"')) StrRemoveEncap(path);
687 if (strchr(path, '$')) ReplaceShellFolders(path);
688 if (strchr(path, '%')) ReplaceEnvVars(path);
689
690 if (!FileExists(path))
691 {
692 // If the file does not exist, display an error messagebox...
693// char message[MAX_LINE_LENGTH];
694// strcpy(message, "xoblite was unable to include...\n\n");
695// strcat(message, itemLabel);
696// strcat(message, "\n\n...into the menu. Please check your menu configuration file. ");
697// MessageBox(GetBBWnd(), message, "xoblite", MB_OK | MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST);
698 // ...and insert a placeholder "error" menu item...
699 CreateMenuItem(pMenu, MENUITEM_NOP, NULL, NULL, "...[include] failed!", false);
700 }
701 else
702 {
703 // ...otherwise open and parse the file...
704 FILE* includeFile = FileOpen(path);
705 ParseFolder(includeFile, pMenu);
706 FileClose(includeFile);
707 }
708
709 return true;
710 }
711
712 //====================
713
714 // Check if the line is pointing to a dynamic folder...
715 else if (!_stricmp(itemCommand, "[path]"))
716 {
717 pMenuItem = new SpecialFolder(itemLabel, NULL, itemData, FOLDER_PATH);
718 }
719/*
720 else if (!_stricmp(itemCommand, "[stylesmenu]"))
721 {
722 pMenuItem = new SpecialFolder(itemLabel, NULL, itemData, FOLDER_STYLES);
723 }
724 else if (!_stricmp(itemCommand, "[themesmenu]"))
725 {
726 pMenuItem = new SpecialFolder(itemLabel, NULL, pSettings->themesFolder, FOLDER_THEMES);
727 }
728
729 else if (!_stricmp(itemCommand, "[stylesdir]"))
730 {
731 InsertFolder(pMenu, itemLabel, FOLDER_STYLES, false);
732 return true;
733 }
734 else if (!_stricmp(itemCommand, "[stylestree]"))
735 {
736 InsertFolder(pMenu, itemLabel, FOLDER_STYLES, true);
737 return true;
738 }
739*/
740 //====================
741 // Check if the line is specifying a special item...
742/*
743 else if (!_stricmp(itemCommand, "[workspaces]"))
744 {
745 pMenuItem = new FolderItem(new WorkspacesMenu(itemLabel ? itemLabel : "Workspaces"), itemLabel ? itemLabel : "Workspaces", NULL);
746 }
747 else if (!_stricmp(itemCommand, "[tasks]"))
748 {
749// pMenuItem = new WorkspacesMenuItem("Tasks", L"Tasks", 254);
750 pMenuItem = new WorkspacesMenuItem("Icons", L"Icons", 255);
751 }
752*/
753 else if (!_stricmp(itemCommand, "[configuration]") || !_stricmp(itemCommand, "[config]"))
754 {
755 pMenuItem = new FolderItem(new ConfigMenu(itemLabel ? itemLabel : "Configuration"), itemLabel ? itemLabel : "Configuration", NULL);
756 }
757
758 //====================
759
760 else if (!_stricmp(itemCommand, "[separator]"))
761 {
762 CreateMenuItem(pMenu, MENUITEM_SEPARATOR, NULL, NULL, NULL, false);
763 return true;
764 }
765 else if (!_stricmp(itemCommand, "[nop]"))
766 {
767 CreateMenuItem(pMenu, MENUITEM_NOP, NULL, NULL, itemLabel, false);
768 return true;
769 }
770 else
771 {
772 // All other menu items, including regular [exec] items etc...
774 return true;
775 }
776
777 //====================
778
779 // Finally, we add the new item to the menu...
780 pMenuItem->SetHeight(m_nSubmenuHeight);
781 pMenu->AddMenuItem(pMenuItem);
782
783 return true;
784}
LPCSTR GetBBVersion()
Definition BBApi.cpp:105
LPSTR StrRemoveEncap(LPSTR string)
Definition BBApi.cpp:406
void ReplaceEnvVars(LPSTR string)
Definition BBApi.cpp:2594
void ReplaceShellFolders(LPSTR string)
Definition BBApi.cpp:2633
#define FOLDER_PATH
Definition FolderItem.h:37
char itemCommand[MAX_LINE_LENGTH]
Definition MenuCommon.cpp:542
char itemData[MAX_LINE_LENGTH]
Definition MenuCommon.cpp:542
char itemLabel[MAX_LINE_LENGTH]
Definition MenuCommon.cpp:542
#define MENUITEM_COMMAND
Definition MenuItem.h:42
#define MENUITEM_NOP
Definition MenuItem.h:46
#define MENUITEM_SEPARATOR
Definition MenuItem.h:47
void AddFooterItem(Menu *pMenu, LPSTR pszTitle)
Definition MenuCommon.cpp:813
char m_szHotListName[256]
Definition MenuCommon.h:96
MenuItem * CreateMenuItem(Menu *pMenu, int itemType, char *pszCommand, char *pszArgument, char *pszTitle, bool isSelected)
Definition MenuCommon.cpp:1065
void AddHeaderItem(Menu *pMenu, LPSTR pszTitle)
Definition MenuCommon.cpp:791
void Validate()
Definition Menu.cpp:1325
void Invalidate()
Definition Menu.cpp:1318
void AddMenuItem(MenuItem *m)
Definition Menu.cpp:1061
virtual void SetHeight(int nHeight)
Definition MenuItem.h:121

◆ AddHeaderItem()

void MenuCommon::AddHeaderItem ( Menu * pMenu,
LPSTR pszTitle )
792{
793 // Placeholder fix to support Unicode text for the menu titles...
794 char pszTitleANSI[MAX_LINE_LENGTH];
795 strcpy(pszTitleANSI, pszTitle);
796 strcat(pszTitleANSI, "\0"); // Just in case...
797 wchar_t pszTitleUnicode[MAX_LINE_LENGTH];
798 MultiByteToWideChar(CP_UTF8, 0, pszTitleANSI, strlen(pszTitleANSI)+1, pszTitleUnicode, MAX_LINE_LENGTH);
799
800 MenuItem* pHeader = new MenuItem(MENUITEM_HEADER, pszTitle, pszTitleUnicode, NULL, NULL, false);
801 pHeader->SetHeight(m_nTitleHeight);
803 pMenu->AddMenuItem(pHeader);
804
805 MenuItem* pMenuItem = new MenuItem(MENUITEM_MARGINPAD, "", NULL, NULL, NULL, false);
806 pMenuItem->SetHeight(m_nMarginHeight);
808 pMenu->AddMenuItem(pMenuItem);
809}
#define PRIORITY_MARGINPAD_TOP
Definition MenuItem.h:54
#define MENUITEM_HEADER
Definition MenuItem.h:38
#define MENUITEM_MARGINPAD
Definition MenuItem.h:39
#define PRIORITY_HEADER
Definition MenuItem.h:53
virtual void SetSortPriority(int nSortPriority)
Definition MenuItem.h:131

◆ AddFooterItem()

void MenuCommon::AddFooterItem ( Menu * pMenu,
LPSTR pszTitle )
814{
815 // Placeholder fix to support Unicode text for the menu grips...
816 char pszTitleANSI[MAX_LINE_LENGTH];
817 strcpy(pszTitleANSI, pszTitle);
818 strcat(pszTitleANSI, "\0"); // Just in case...
819 wchar_t pszTitleUnicode[MAX_LINE_LENGTH];
820 MultiByteToWideChar(CP_UTF8, 0, pszTitleANSI, strlen(pszTitleANSI)+1, pszTitleUnicode, MAX_LINE_LENGTH);
821
822 if (pMenu->m_MenuItems.size() <= 2) // -> Only the menu's title and top marginpad previously created -> This is an otherwise *empty* menu/submenu with no regular menu frame items!
823 {
824 CreateMenuItem(pMenu, MENUITEM_NOP, NULL, NULL, "(No items)", false); // Note: This cunningly also prevents crashes if menu.titles+grips are disabled too... (i.e. no title/frame/grip oddball scenario)
825 }
826
827 MenuItem* pMenuItem = new MenuItem(MENUITEM_MARGINPAD, "", NULL, NULL, NULL, false);
828 pMenuItem->SetHeight(m_nMarginHeight);
830 pMenu->AddMenuItem(pMenuItem);
831
832 MenuItem* pBorder = new MenuItem(MENUITEM_FOOTER, pszTitle, pszTitleUnicode, NULL, NULL, false);
833 pBorder->SetHeight(m_nGripHeight);
835 pMenu->AddMenuItem(pBorder);
836}
#define PRIORITY_FOOTER
Definition MenuItem.h:59
#define PRIORITY_MARGINPAD_BOTTOM
Definition MenuItem.h:58
#define MENUITEM_FOOTER
Definition MenuItem.h:40
vector< MenuItem * > m_MenuItems
Definition Menu.h:146

◆ InsertFolder()

void MenuCommon::InsertFolder ( Menu * pMenu,
char * pszFolder,
int menuType,
bool includeSubFolders )
844{
845 char folder[MAX_LINE_LENGTH];
846 strcpy(folder, pszFolder);
847
848 MenuItem* pItem = NULL;
849 char itemCmd[MAX_LINE_LENGTH], itemTitle[MAX_LINE_LENGTH], dirPath[MAX_LINE_LENGTH];
850 bool directoryFound = false, itemFound = false;
851 bool currentStyleFound;
852
853 //====================
854
855 // If we're creating a [themesmenu] subfolder we first add the default theme to the menu...
856 if (menuType == FOLDER_THEMES)
857 {
858 char bbpath[MAX_LINE_LENGTH];
860 bbpath[strlen(bbpath)-1] = 0;
861 CreateMenuItem(pMenu, MENUITEM_COMMAND, "[theme]", bbpath, "[Default]", !IsInString(pSettings->SF_currentThemePath, "themes"));
862 }
863
864 //====================
865
866 char folderToken[MAX_LINE_LENGTH], folderPattern[MAX_LINE_LENGTH];
867
868 while (strlen(folder))
869 {
870 // Get the next folder path token from the input string...
871 strcpy(folder, Tokenize(folder, folderToken, "|"));
872 if (folderToken[0] == '\"') StrRemoveEncap(folderToken);
873
874 // Does the folder path already contain a wildcard?
875 LPSTR wildcardPointer = strchr(folderToken, '*');
876 if (wildcardPointer != NULL)
877 {
878 // If so, we use the folder path without alteration as search pattern...
879 strcpy(folderPattern, folderToken);
880 int i = (int)(wildcardPointer - folderToken);
881 folderToken[i] = '\0';
882 }
883 else
884 {
885 // If not, we use the default "all files" search pattern...
886 if (folderToken[strlen(folderToken)] != '\\') strcat(folderToken, "\\");
887 strcpy(folderPattern, folderToken);
888 strcat(folderPattern, "*");
889 }
890
891 //====================
892
893 // Using this pattern, we then search for items in the directory
894 // and process them according to name, attributes etc.
895 _finddata_t found;
896 long handle = _findfirst(folderPattern, &found);
897
898 if (handle != -1)
899 {
900 do
901 {
902 // Skip hidden files...
903 if (strcmp(found.name, ".") == 0 || strcmp(found.name, "..") == 0 || (found.attrib & _A_HIDDEN))
904 continue;
905
906 //====================
907
908 if (found.attrib & _A_SUBDIR)
909 {
910 if (menuType == FOLDER_THEMES) // [themesmenu] items
911 {
912 // To get the full path to the file we copy
913 // the folder path and add the filename...
914 strcpy(itemCmd, folderToken);
915 strcat(itemCmd, found.name);
916
917 // The title of the menu item is the name of the file
918 strcpy(itemTitle, found.name);
919
920 // Finally, we create the new menu item...
921 CreateMenuItem(pMenu, MENUITEM_COMMAND, "[theme]", itemCmd, itemTitle, !_stricmp(pSettings->SF_currentThemePath, itemCmd));
922 }
923 else if (includeSubFolders)
924 {
925 // To get the full path to the file we copy the folder path
926 // and add the filename, then add quotes to be on the safe
927 // side during further processing if the path contains spaces...
928 strcpy(dirPath,"\"");
929 strcat(dirPath, folderToken);
930 strcat(dirPath, found.name);
931 strcat(dirPath, "\"");
932
933 // Subfolders are created by adding a new SpecialFolder...
934 pItem = new SpecialFolder(found.name, NULL, dirPath, menuType);
936 pMenu->AddMenuItem(pItem);
937
938 directoryFound = true;
939 }
940 }
941
942 //====================
943
944 else
945 {
946 if (menuType == FOLDER_STYLES) // [stylesmenu] items
947 {
948 if (IsInString(found.name, ".3dc")) continue;
949
950 // To get the full path to the file we copy
951 // the folder path and add the filename...
952 strcpy(itemCmd, folderToken);
953 strcat(itemCmd, found.name);
954
955 // The title of the menu item is the name of the file
956 strcpy(itemTitle, found.name);
957 // Remove any .style or .sty extensions...
958 if (IsInString(itemTitle, ".sty")) PathRemoveExtension(itemTitle);
959
960 // Is this file the currently applied style?
961 // If so, show the "current style" indicator for this menu item...
962 currentStyleFound = !_stricmp(itemCmd, pSettings->styleFile);
963
964 // Finally, we create the new menu item...
965 MenuItem *newMenuItem = CreateMenuItem(pMenu, MENUITEM_COMMAND, "[style]", itemCmd, itemTitle, currentStyleFound);
966 if (currentStyleFound) currentStyleMenuItem = newMenuItem;
967
968 itemFound = true;
969 }
970 else if (menuType == FOLDER_PATH) // [path] items
971 {
972 // To get the full path to the file we copy the folder path
973 // and add the filename, then add quotes to be on the safe
974 // side during further processing if the path contains spaces...
975 strcpy(itemCmd, "\"");
976 strcat(itemCmd, folderToken);
977 strcat(itemCmd, found.name);
978 strcat(itemCmd, "\"");
979
980 // The title of the menu item is the name of the file,
981 // minus .lnk if it's a symbolic link or .url if it's a URL...
982 strcpy(itemTitle, found.name);
983 if (IsInString(itemTitle, ".lnk") || IsInString(itemTitle, ".url")) PathRemoveExtension(itemTitle);
984
985// // Finally, we create the new menu item...
986// CreateMenuItem(pMenu, MENUITEM_COMMAND, "[exec]", itemCmd, itemTitle, false);
987 // Finally, we create the new menu item... (nb. we convert the title to Unicode here
988 // only to avoid possible later re-conversion mishaps via the regular CreateMenuItem())
989 wchar_t itemTitleUnicode[MAX_LINE_LENGTH];
990 MultiByteToWideChar(CP_ACP, 0, itemTitle, strlen(itemTitle)+1, itemTitleUnicode, MAX_LINE_LENGTH);
991 CreateMenuItemUnicode(pMenu, MENUITEM_COMMAND, "[exec]", itemCmd, itemTitleUnicode, false);
992
993 itemFound = true;
994 }
995 }
996
997 //====================
998 }
999 while (_findnext(handle, &found) == 0);
1000 }
1001
1002 _findclose(handle);
1003 }
1004
1005 //====================
1006
1007 if (directoryFound && itemFound) CreateMenuItem(pMenu, MENUITEM_SEPARATOR, NULL, NULL, NULL, false);
1008
1009 // When the search is completed, we sort the items,
1010 // but skip the title and top marginWidth padding...
1011 pMenu->Sort(2,0);
1012}
LPSTR Tokenize(LPCSTR string, LPSTR buf, LPSTR delims)
Definition BBApi.cpp:273
bool IsInString(LPCSTR inputString, LPCSTR searchString)
Definition BBApi.cpp:2519
bool WINAPI GetBlackboxPath(LPSTR pszPath, int nMaxLen)
Definition BBApi.cpp:214
#define FOLDER_THEMES
Definition FolderItem.h:39
#define FOLDER_STYLES
Definition FolderItem.h:38
MenuItem * CreateMenuItemUnicode(Menu *pMenu, int itemType, char *pszCommand, char *pszArgument, wchar_t *pszTitleUnicode, bool isSelected)
Definition MenuCommon.cpp:1131
void Sort(int beginOffset, int endOffset)
Definition Menu.cpp:1306
char SF_currentThemePath[MAX_PATH]
Definition Settings.h:385
char styleFile[MAX_LINE_LENGTH]
Definition Settings.h:324

◆ Hide()

bool MenuCommon::Hide ( int index = 0)
1029{
1030 bool menusHaveBeenHidden = false;
1031
1032 // Hide all core shell menus...
1033 // (note that since we're addressing the top level parent
1034 // menus we only need to call using the HIDE_CHILDREN flag,
1035 // which will hide the top level menus *and* all of their submenus)
1036 for (int i=0; i < (int)m_MenusVector.size(); i++)
1037 {
1038 if (m_MenusVector[i]->Hide(HIDE_CHILDREN)) menusHaveBeenHidden = true;
1039 }
1040
1041 // Hide all plugin menus...
1042 if ((m_pPluginMenu != NULL) && !m_pPluginMenu->IsPinned()) // Note: At least for now we only support a single open/pinned plugin menu at a time.
1043 {
1044 if (IsWindowVisible(m_pPluginMenu->GetWindow()))
1045 {
1046 ShowWindow(m_pPluginMenu->GetWindow(), SW_HIDE);
1047 menusHaveBeenHidden = true;
1048 }
1049// if (m_pPluginMenu->Hide(HIDE_PARENTS)) menusHaveBeenHidden = true;
1050 if (m_pPluginMenu->Hide(HIDE_CHILDREN)) menusHaveBeenHidden = true;
1051 }
1052
1054
1055 if (menusHaveBeenHidden) PlaySoundFX(SFX_MENU_HIDE);
1056
1057 return menusHaveBeenHidden;
1058}
PreviewItem * pPreviewItem
Definition Blackbox.cpp:45
#define HIDE_CHILDREN
Definition Menu.h:39
void PlaySoundFX(int sound)
Definition Sounds.cpp:40
@ SFX_MENU_HIDE
Definition Sounds.h:46
bool Hide(int index=0)
Definition MenuCommon.cpp:1028
void Hide()
Definition PreviewItem.cpp:316

◆ CreateMenuItem()

MenuItem * MenuCommon::CreateMenuItem ( Menu * pMenu,
int itemType,
char * pszCommand,
char * pszArgument,
char * pszTitle,
bool isSelected )
1066{
1067 MenuItem *newMenuItem = NULL;
1068
1069 wchar_t pszTitleUnicode[MAX_LINE_LENGTH];
1070 if (!pSettings->disableUnicodeParsing && (pszTitle != NULL))
1071 {
1072 char pszTitleANSI[MAX_LINE_LENGTH];
1073 strcpy(pszTitleANSI, pszTitle);
1074 strcat(pszTitleANSI, "\0"); // Just in case...
1075 MultiByteToWideChar(CP_UTF8, 0, pszTitleANSI, strlen(pszTitleANSI)+1, pszTitleUnicode, MAX_LINE_LENGTH);
1076 }
1077 else wcscpy(pszTitleUnicode, L"\0");
1078
1079 if (pMenu)
1080 {
1081 if (itemType == MENUITEM_SEPARATOR)
1082 {
1084 {
1085 newMenuItem = new MenuItem(MENUITEM_SEPARATOR, "", pszTitleUnicode, NULL, NULL, false);
1086
1087 // Set a higher sort priority for [separator] items to make them sort
1088 // before any regular menu items (i.e. between folders regular menu items)
1089 newMenuItem->SetSortPriority(PRIORITY_SEPARATOR);
1090
1091 newMenuItem->SetHeight(m_nSeparatorHeight);
1092 pMenu->AddMenuItem(newMenuItem);
1093 return newMenuItem;
1094 }
1095 else return NULL;
1096 }
1097
1098 //====================
1099
1100 else if (itemType == MENUITEM_NOP)
1101 {
1102 if (pszTitle == NULL) newMenuItem = new MenuItem(MENUITEM_NOP, "", NULL, NULL, NULL, false);
1103 else newMenuItem = new MenuItem(MENUITEM_NOP, pszTitle, pszTitleUnicode, NULL, NULL, false);
1104 }
1105
1106 //====================
1107
1108 else if (itemType == MENUITEM_EDITSTRING) // Used by MakeMenuItemString
1109 {
1110 newMenuItem = new StringItem(pszTitle, pszTitleUnicode, pszCommand, pszArgument, isSelected);
1111 }
1112
1113 //====================
1114
1115 else // [exec] MENUITEM_COMMAND, MENUITEM_BOOLEAN, MENUITEM_EDITINT (used by MakeMenuItemInt), etc
1116 {
1117 newMenuItem = new MenuItem(itemType, pszTitle, pszTitleUnicode, pszCommand, pszArgument, isSelected);
1118 }
1119
1120 //====================
1121
1122 newMenuItem->SetHeight(m_nSubmenuHeight);
1123 pMenu->AddMenuItem(newMenuItem);
1124 }
1125
1126 return newMenuItem;
1127}
#define MENUITEM_EDITSTRING
Definition MenuItem.h:43
#define PRIORITY_SEPARATOR
Definition MenuItem.h:56
bool menuSeparators
Definition Settings.h:175
bool disableUnicodeParsing
Definition Settings.h:335

◆ CreateMenuItemUnicode()

MenuItem * MenuCommon::CreateMenuItemUnicode ( Menu * pMenu,
int itemType,
char * pszCommand,
char * pszArgument,
wchar_t * pszTitleUnicode,
bool isSelected )
1132{
1133 MenuItem *newMenuItem = NULL;
1134
1135 if (pMenu && (itemType == MENUITEM_COMMAND))
1136 {
1137 newMenuItem = new MenuItem(itemType, "", pszTitleUnicode, pszCommand, pszArgument, isSelected);
1138 newMenuItem->SetHeight(m_nSubmenuHeight);
1139 pMenu->AddMenuItem(newMenuItem);
1140 }
1141
1142 return newMenuItem;
1143}

◆ Invoke()

void MenuCommon::Invoke ( MenuItem * item,
int button )
1151{
1152 if (item->itemType == MENUITEM_COMMAND || item->itemType == MENUITEM_BOOLEAN)
1153 {
1154 if (item->m_pszCommand == NULL) return;
1155
1156 if (item->m_pszCommand[0] == '@') // -> Direct bro@m command (i.e. not via an [exec] type menu item, see below)
1157 {
1158 char broam[MAX_LINE_LENGTH];
1159 strcpy(broam, item->m_pszCommand);
1160 if (item->m_pszArgument != NULL)
1161 {
1162 if (strlen(item->m_pszArgument))
1163 {
1164 strcat(broam, " ");
1165 strcat(broam, item->m_pszArgument);
1166 }
1167 }
1168
1169 // Update the menu item boolean status if applicable...
1170 if (item->m_selectionGroup > GROUP_DEFAULT)
1171 {
1173 item->m_isSelected = true;
1174 }
1175 else if (item->itemType == MENUITEM_BOOLEAN) item->ToggleSelected();
1176
1177 // Hide any currently open non-pinned menu(s) first, just in case the command is to open *another* menu...
1178 if (item->m_pParent->IsPinned() || (button >= 2)) item->m_pParent->UpdateMenuWindow();
1179 else HideAfterInvoke(item, button);
1180
1181 // Execute the command associated with the menu item...
1182 BBSmartExecute(broam);
1184
1185 return;
1186 }
1187 else if (item->m_pszArgument != NULL)
1188 {
1189 if (!_stricmp(item->m_pszCommand, "[exec]") && (item->m_pszArgument[0] == '@')) // -> Non-direct bro@m command (i.e. via an [exec] type menu item)
1190 {
1191 // Update the menu item boolean status if applicable...
1192 if (item->m_selectionGroup > GROUP_DEFAULT)
1193 {
1195 item->m_isSelected = true;
1196 }
1197 else if (item->itemType == MENUITEM_BOOLEAN) item->ToggleSelected();
1198
1199 // Hide any currently open non-pinned menu(s) first, just in case the command is to open *another* menu...
1200 if (item->m_pParent->IsPinned() || (button >= 2)) item->m_pParent->UpdateMenuWindow();
1201 else HideAfterInvoke(item, button);
1202
1203 // Execute the command associated with the menu item...
1206
1207 return;
1208 }
1209 }
1210 }
1211
1212 //====================
1213
1214 if (item->itemType == MENUITEM_EDITSTRING)
1215 {
1216 StringItem* si = (StringItem*)item;
1217 if (si->m_pszCommand == NULL) return;
1218
1219 char broam[MAX_LINE_LENGTH];
1220
1221 if (IsInString(si->m_pszCommand, "@BBInterface"))
1222 {
1223 // Add "" encapsulation to the broam parameters string to
1224 // allow spaces in strings sent back to BBInterface...
1225 char encappedInit[MAX_LINE_LENGTH];
1226 strcpy(encappedInit, si->m_pszInit);
1227 int nLen = strlen(encappedInit);
1228 memmove(encappedInit+1, encappedInit, strlen(encappedInit));
1229 encappedInit[0] = encappedInit[nLen+1] = '\"';
1230 encappedInit[nLen+2] = '\0';
1231 sprintf(broam, "%s %s", si->m_pszCommand, encappedInit);
1232 }
1233 else sprintf(broam, "%s %s", si->m_pszCommand, si->m_pszInit);
1234
1235 // Update the menu item boolean status if applicable...
1237 {
1239 si->m_isSelected = true;
1240 }
1241
1242 // Hide any currently open non-pinned menu(s) first, just in case the command is to open *another* menu...
1243 if (si->m_pParent->IsPinned()) si->m_pParent->UpdateMenuWindow();
1244 else Hide();
1245
1246 // Execute the command associated with the menu item...
1247 BBSmartExecute(broam);
1249
1250 return;
1251 }
1252
1253 //====================
1254
1255 if (item->itemType == MENUITEM_EDITINT)
1256 {
1257 if (item->m_pszCommand == NULL) return;
1258
1259 if (item->m_mousePos.x > (item->m_nWidth / 2))
1260 {
1261 if (item->m_currentValue == item->m_maxValue) return;
1262
1263 // Increase the value...
1264 if ((button == 2) || (GetAsyncKeyState(VK_CONTROL) & 0x8000))
1265 {
1266 if (item->m_currentValue <= (item->m_maxValue - 10)) item->m_currentValue = item->m_currentValue + 10;
1267 else item->m_currentValue = item->m_maxValue;
1268 }
1269 else if (item->m_currentValue < item->m_maxValue) item->m_currentValue++;
1270 }
1271 else
1272 {
1273 if (item->m_currentValue == item->m_minValue) return;
1274
1275 // Decrease the value...
1276 if ((button == 2) || (GetAsyncKeyState(VK_CONTROL) & 0x8000))
1277 {
1278 if (item->m_currentValue >= (item->m_minValue + 10)) item->m_currentValue = item->m_currentValue - 10;
1279 else item->m_currentValue = item->m_minValue;
1280 }
1281 else if (item->m_currentValue > item->m_minValue) item->m_currentValue--;
1282 }
1283
1284 // Update the menu item's title text... (nb. both ANSI and Unicode representations, for now at least)
1285 char temp[MAX_LINE_LENGTH];
1286 sprintf(temp, "%s <%d>", item->m_pszOriginalTitleANSI, item->m_currentValue);
1287 item->SetTitleANSI(temp);
1288 wchar_t tempUnicode[MAX_LINE_LENGTH];
1289 swprintf(tempUnicode, sizeof(tempUnicode), L"%s <%d>", item->m_pszOriginalTitleUnicode, item->m_currentValue);
1290 item->SetTitleUnicode(tempUnicode);
1291
1292 // Revalidate and update the menu item's parent menu...
1293 // (both as the item's width may have changed along with its title text,
1294 // and because the cached menu bitmap may need to be updated accordingly)
1295 item->m_pParent->Invalidate();
1296 item->m_pParent->Validate();
1297 item->m_pParent->UpdateMenuWindow();
1298
1299 // Broadcast the updated value to the recipient(s)...
1300 sprintf(temp, "%s %d", item->m_pszCommand, item->m_currentValue);
1301 SendMessage(GetBBWnd(), BB_BROADCAST, 0, (LPARAM)temp);
1303
1304 return;
1305 }
1306
1307 //====================
1308
1309 if (item->m_pszCommand != NULL)
1310 {
1311 // BELOW: Normal menu commands (i.e. [something] format as used by menu.rc)
1312
1313 if (!strncmp(item->m_pszCommand, "[", 1))
1314 {
1315 if (!_stricmp(item->m_pszCommand, "[exec]"))
1316 {
1317 if (button == 2) // Right mouse button...
1318 {
1319 if (!strlen(item->m_pszArgument)) return;
1320 if (item->m_pszArgument[0] == '@') return;
1321
1322 // We only need to check the last 4 characters to get the extension...
1323 char path[MAX_LINE_LENGTH];
1324 strcpy(path, item->m_pszArgument);
1325 if (path[0] == '\"') StrRemoveEncap(path);
1326 int pointer = strlen(path) - 4;
1327
1328 if (!_stricmp(&path[pointer], ".jpg")
1329 || !_stricmp(&path[pointer], ".png")
1330 || !_stricmp(&path[pointer], ".bmp")
1331 || !_stricmp(&path[pointer], "jpeg"))
1332 {
1333 // -> Set the image to be the desktop wallpaper...
1334 // (please note that we leave the menu open in this case)
1335 if (GetAsyncKeyState(VK_CONTROL) & 0x8000) pWallpaper->SetWallpaper(path, "center"); // Is the control key held down? -> center mode
1336 else if (GetAsyncKeyState(VK_MENU) & 0x8000) pWallpaper->SetWallpaper(path, "tile"); // Is the alt key held down? -> tile mode
1337 else if (GetAsyncKeyState(VK_SHIFT) & 0x8000) pWallpaper->SetWallpaper(path, "span"); // Is the shift key held down? -> span mode
1338 else pWallpaper->SetWallpaper(path, "stretch"); // Default -> stretch/full mode
1340 pSettings->Statistics.changedWallpaper++; // Update statistics...
1341 return;
1342 }
1343 else if (!_strnicmp(item->m_pszArgument, "http", 4))
1344 {
1345 // -> Right click on HTTP(S) URL:
1346 // Instead of opening the link in the default browser,
1347 // download it to temporary file "xoblite.tmp"
1348 // (nb. this is typically only for some specific use cases)
1349 char path[MAX_PATH];
1350 GetBlackboxPath(path, MAX_PATH);
1351 strcat(path, "xoblite.tmp");
1352 Log(path, path);
1353 DownloadFile(item->m_pszArgument, path);
1355 return;
1356 }
1357 else
1358 {
1359 if (IsInString(path, "http://")) return;
1360
1361 // If the item points to an application .exe we execute that just
1362 // like on a left click... (but keeping the menu open afterwards)
1363 if (IsInString(path, ".exe")) BBSmartExecute(item->m_pszArgument); // -> Regular .exe apps
1364 else if (!_strnicmp(item->m_pszArgument, "ms-", 3) && (item->m_pszArgument[strlen(item->m_pszArgument) - 1] == ':')) BBSmartExecute(item->m_pszArgument); // -> Windows system apps, e.g. ms-settings: and ms-windows-store:
1365 else
1366 {
1367 // ...otherwise we open an Explorer
1368 // window where the file is selected...
1369 char arg[MAX_LINE_LENGTH];
1370 strcpy(arg, "/e,/select,");
1371 strcat(arg, path);
1372 BBExecute(GetDesktopWindow(), NULL, "explorer.exe", arg, NULL, SW_SHOWNORMAL, false);
1373
1374 }
1376 return;
1377 }
1378 }
1379
1380 //====================
1381
1382 else if (button == 3) // Mid mouse button...
1383 {
1384 if (!strlen(item->m_pszArgument)) return;
1385 if (item->m_pszArgument[0] == '@') return;
1386
1387 char string[MAX_LINE_LENGTH];
1388 strcpy(string, item->m_pszArgument);
1389 if (string[0] == '\"') StrRemoveEncap(string);
1390
1391 // Is the control key held down? -> copy path *without* the Blackbox
1392 // or current theme directory, adding quotes to enable portability
1393 // (useful for e.g. wallpaper rootCommands)
1394 if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
1395 {
1396 char string2[MAX_LINE_LENGTH];
1397
1399 {
1400 strcpy(string2, "\"$CurrentTheme$");
1401 strcat(string2, &string[strlen(pSettings->SF_currentThemePath)]);
1402 strcat(string2, "\"");
1403 }
1404 else if (IsInString(string, pSettings->SF_blackboxPath))
1405 {
1406 // strcpy(string2, "\"$Blackbox$");
1407 strcpy(string2, "\"");
1408 strcat(string2, &string[strlen(pSettings->SF_blackboxPath) + 1]);
1409 strcat(string2, "\"");
1410 }
1411 else
1412 {
1413 strcpy(string2, "\"");
1414 strcat(string2, string);
1415 strcat(string2, "\"");
1416 }
1417
1418 // If the alt key is held down too we create a
1419 // bsetbg -full command including the path as argument...
1420 if (GetAsyncKeyState(VK_MENU) & 0x8000)
1421 {
1422 strcpy(string, "rootCommand: bsetbg -full ");
1423 strcat(string, string2);
1424 CopyStringToClipboard(string);
1425 }
1426 else CopyStringToClipboard(string2);
1427 }
1428 // ...if not we copy the full path to the file (without quotes)...
1429 else CopyStringToClipboard(string);
1430 }
1431
1432 //====================
1433
1434 else // Left mouse button...
1435 {
1436 /*
1437 if (item->itemType == MENUITEM_BOOLEAN) item->ToggleSelected();
1438
1439 if (item->m_pParent->IsPinned()) item->m_pParent->UpdateMenuWindow();
1440 else HideAfterInvoke(item, button);
1441 */
1442 if (!item->m_pParent->IsPinned()) HideAfterInvoke(item, button);
1443
1446
1447 return;
1448 }
1449 }
1450
1451 //====================
1452
1453 else if (!_stricmp(item->m_pszCommand, "[shutdown]")) {
1454 HideAfterInvoke(item, button);
1455 PostMessage(GetBBWnd(), BB_SHUTDOWN, 0, 0);
1456 return;
1457 }
1458 else if (!_stricmp(item->m_pszCommand, "[reboot]")) {
1459 HideAfterInvoke(item, button);
1460 PostMessage(GetBBWnd(), BB_SHUTDOWN, 1, 0);
1461 return;
1462 }
1463 else if (!_stricmp(item->m_pszCommand, "[logoff]")) {
1464 HideAfterInvoke(item, button);
1465 PostMessage(GetBBWnd(), BB_SHUTDOWN, 2, 0);
1466 return;
1467 }
1468 else if (!_stricmp(item->m_pszCommand, "[hibernate]")) {
1469 HideAfterInvoke(item, button);
1470 PostMessage(GetBBWnd(), BB_SHUTDOWN, 3, 0);
1471 return;
1472 }
1473 else if (!_stricmp(item->m_pszCommand, "[standby]")) {
1474 HideAfterInvoke(item, button);
1475 PostMessage(GetBBWnd(), BB_SHUTDOWN, 4, 0);
1476 return;
1477 }
1478 else if (!_stricmp(item->m_pszCommand, "[lockworkstation]")) {
1479 HideAfterInvoke(item, button);
1480 PostMessage(GetBBWnd(), BB_SHUTDOWN, 5, 0);
1481 return;
1482 }
1483
1484 //====================
1485
1486 else if (!_stricmp(item->m_pszCommand, "[run]")) {
1487 HideAfterInvoke(item, button);
1488 PostMessage(GetBBWnd(), BB_RUN, 0, 0);
1489 return;
1490 }
1491
1492 //====================
1493
1494 else if (!_stricmp(item->m_pszCommand, "[restart]"))
1495 {
1496 HideAfterInvoke(item, button);
1497 PostMessage(GetBBWnd(), BB_RESTART, 0, 0);
1498 return;
1499 }
1500 else if (!_stricmp(item->m_pszCommand, "[reconfigure]") || !_stricmp(item->m_pszCommand, "[reconfig]"))
1501 {
1502 HideAfterInvoke(item, button);
1503 PostMessage(GetBBWnd(), BB_SETSTYLE, 0, 0);
1504 return;
1505 }
1506 else if (!_stricmp(item->m_pszCommand, "[exit]"))
1507 {
1508 HideAfterInvoke(item, button);
1509 PostMessage(GetBBWnd(), BB_QUIT, 0, 0);
1510 return;
1511 }
1512
1513 //====================
1514
1515 else if (!_stricmp(item->m_pszCommand, "[style]"))
1516 {
1517 if (button == 2) // Right mouse button
1518 {
1519 // Open the chosen style in the preferred editor...
1520 BBExecute(GetDesktopWindow(), NULL, pSettings->preferredEditor, item->m_pszArgument, NULL, SW_SHOWNORMAL, false);
1522 HideAfterInvoke(item, button);
1523 }
1524 else if (button == 3) // Mid mouse button
1525 {
1526 if (!strlen(item->m_pszArgument)) return;
1527 if (item->m_pszArgument[0] == '@') return;
1528
1529 // Copy the full path of the style to the clipboard...
1530 char string[MAX_LINE_LENGTH];
1531 strcpy(string, item->m_pszArgument);
1532 if (string[0] == '\"') StrRemoveEncap(string);
1533 CopyStringToClipboard(string);
1535 }
1536 else // Left mouse button
1537 {
1538 // Update the "current style" indicator to reflect the style change...
1539 if (currentStyleMenuItem != NULL) currentStyleMenuItem->m_isSelected = false;
1540 currentStyleMenuItem = item;
1541 item->m_isSelected = true;
1542
1543 // Apply the new style...
1544 HideAfterInvoke(item, button);
1545 PostMessage(GetBBWnd(), BB_SETSTYLE, 0, (LPARAM)item->m_pszArgument);
1546 }
1547
1548 return;
1549 }
1550
1551 //====================
1552
1553 else if (!_stricmp(item->m_pszCommand, "[theme]"))
1554 {
1555 if (button == 2) // Right mouse button
1556 {
1557 // Open the theme folder in Explorer...
1558 char arg[MAX_LINE_LENGTH];
1559 strcpy(arg, "/e,");
1560 strcat(arg, item->m_pszArgument);
1561 BBExecute(GetDesktopWindow(), NULL, "explorer.exe", arg, NULL, SW_SHOWNORMAL, false);
1563 }
1564 else // Left mouse button
1565 {
1566 HideAfterInvoke(item, button);
1567 PostMessage(GetBBWnd(), BB_SETTHEME, 0, (LPARAM)item->m_pszArgument);
1568 }
1569
1570 return;
1571 }
1572
1573 //====================
1574/*
1575 else if (!_stricmp(item->m_pszCommand, "[loadplugin]"))
1576 {
1577 HideAfterInvoke(item, button);
1578 pPluginManager->LoadPluginDialog();
1579 return;
1580 }
1581*/
1582 //====================
1583/*
1584 else if (!_stricmp(item->m_pszCommand, "[editstyle]"))
1585 {
1586 HideAfterInvoke(item, button);
1587 PostMessage(GetBBWnd(), BB_EDITFILE, 0, 0);
1588 PlaySoundFX(SFX_MENU_CLICK);
1589 return;
1590 }
1591 else if (!_stricmp(item->m_pszCommand, "[editmenu]"))
1592 {
1593 HideAfterInvoke(item, button);
1594 PostMessage(GetBBWnd(), BB_EDITFILE, 1, 0);
1595 PlaySoundFX(SFX_MENU_CLICK);
1596 return;
1597 }
1598 else if (!_stricmp(item->m_pszCommand, "[editplugins]"))
1599 {
1600 HideAfterInvoke(item, button);
1601 PostMessage(GetBBWnd(), BB_EDITFILE, 2, 0);
1602 PlaySoundFX(SFX_MENU_CLICK);
1603 return;
1604 }
1605 else if (!_stricmp(item->m_pszCommand, "[editextensions]"))
1606 {
1607 HideAfterInvoke(item, button);
1608 PostMessage(GetBBWnd(), BB_EDITFILE, 3, 0);
1609 PlaySoundFX(SFX_MENU_CLICK);
1610 return;
1611 }
1612 else if (!_stricmp(item->m_pszCommand, "[editblackbox]"))
1613 {
1614 HideAfterInvoke(item, button);
1615 PostMessage(GetBBWnd(), BB_EDITFILE, 4, 0);
1616 PlaySoundFX(SFX_MENU_CLICK);
1617 return;
1618 }
1619*/
1620 //====================
1621/*
1622 else if (!_stricmp(item->m_pszCommand, "[aboutstyle]"))
1623 {
1624 HideAfterInvoke(item, button);
1625 char aboutStyle[MAX_LINE_LENGTH], a1[MAX_LINE_LENGTH], a2[MAX_LINE_LENGTH], a3[MAX_LINE_LENGTH], a4[MAX_LINE_LENGTH], a5[MAX_LINE_LENGTH];
1626 strcpy(a1, ReadString(pSettings->styleFile, "style.name:", "[Style name not specified]"));
1627 strcpy(a2, ReadString(pSettings->styleFile, "style.author:", "[Author not specified]"));
1628 strcpy(a3, ReadString(pSettings->styleFile, "style.date:", ""));
1629 strcpy(a4, ReadString(pSettings->styleFile, "style.credits:", ""));
1630 strcpy(a5, ReadString(pSettings->styleFile, "style.comments:", ""));
1631 sprintf(aboutStyle, "%s \nby %s \n%s \n\n%s \n\n%s ", a1, a2, a3, a4, a5);
1632 // MessageBox(GetBBWnd(), aboutStyle, "xoblite: Style information", MB_OK | MB_SETFOREGROUND | MB_ICONINFORMATION);
1633 SendMessage(GetBBWnd(), BB_POPUPMESSAGE, (WPARAM)"About the current style...", (LPARAM)aboutStyle);
1634 PlaySoundFX(SFX_MENU_CLICK);
1635 return;
1636 }
1637 else if (!_stricmp(item->m_pszCommand, "[aboutplugins]"))
1638 {
1639 HideAfterInvoke(item, button);
1640 pPluginManager->AboutPlugins();
1641 PlaySoundFX(SFX_MENU_CLICK);
1642 return;
1643 }
1644*/
1645 //====================
1646/*
1647 else if (!_stricmp(item->m_pszCommand, "[toggletoolbar]"))
1648 {
1649 HideAfterInvoke(item, button);
1650 PostMessage(GetBBWnd(), BB_TOGGLETOOLBAR, 0, 0);
1651 return;
1652 }
1653 else if (!_stricmp(item->m_pszCommand, "[toggleplugins]"))
1654 {
1655 HideAfterInvoke(item, button);
1656 PostMessage(GetBBWnd(), BB_TOGGLEPLUGINS, 0, 0);
1657 return;
1658 }
1659 else if (!_stricmp(item->m_pszCommand, "[toggledock]"))
1660 {
1661 HideAfterInvoke(item, button);
1662 PostMessage(GetBBWnd(), BB_TOGGLEDOCK, 0, 0);
1663 return;
1664 }
1665 else if (!_stricmp(item->m_pszCommand, "[toggleconsole]"))
1666 {
1667 HideAfterInvoke(item, button);
1668 PostMessage(GetBBWnd(), BB_TOGGLECONSOLE, 0, 0);
1669 return;
1670 }
1671*/
1672 //====================
1673/*
1674 else if (!_stricmp(item->m_pszCommand, "[add]"))
1675 {
1676 HideAfterInvoke(item, button);
1677 PostMessage(GetBBWnd(), BB_WORKSPACE, 2, 0);
1678 return;
1679 }
1680 else if (!_stricmp(item->m_pszCommand, "[del]"))
1681 {
1682 HideAfterInvoke(item, button);
1683 PostMessage(GetBBWnd(), BB_WORKSPACE, 3, 0);
1684 return;
1685 }
1686 else if (!_stricmp(item->m_pszCommand, "[gather]"))
1687 {
1688 HideAfterInvoke(item, button);
1689 PostMessage(GetBBWnd(), BB_WORKSPACE, 5, 0);
1690 return;
1691 }
1692*/
1693 //====================
1694
1695// else HideAfterInvoke(1); // The command was unvalid -> close the menu!
1696 }
1697
1698 //===========================================================================
1699
1700 // BELOW: Some additional xoblite internal menu handling... (using <something> format)
1701
1702 else if (!strncmp(item->m_pszCommand, "<", 1))
1703 {
1704 if (!_stricmp(item->m_pszCommand, "<task_item>"))
1705 {
1706 HideAfterInvoke(item, button);
1707
1708 // Convert the hexadecimal format string back to HWND... (pretty cool, eh? :D )
1709 HWND hWnd = (HWND)strtoul(item->m_pszArgument, 0, 16);
1710 // ...and bring the window to the front of the z-order!
1711 if (IsIconic(hWnd)) ShowWindow(hWnd, SW_RESTORE);
1712 SetForegroundWindow(hWnd);
1713 SendMessage(GetBBWnd(), BB_BRINGTOFRONT, 0, (LPARAM)hWnd);
1714
1715 return;
1716 }
1717
1718 //===========================================================================
1719
1720 // Some remaining legacy configuration menu handling...
1721/*
1722 else if (!_stricmp(item->m_pszCommand, "<config_menu_item>"))
1723 {
1724 HideAfterInvoke(item, button);
1725
1726 if (!_stricmp(item->m_pszArgument, "ClickToFocus"))
1727 {
1728 strcpy(pSettings->focusModel, item->m_pszArgument);
1729 SystemParametersInfo(SPI_SETACTIVEWINDOWTRACKING, 0, (PVOID)false, SPIF_SENDCHANGE);
1730 SystemParametersInfo(SPI_SETACTIVEWNDTRKZORDER, 0, (PVOID)false, SPIF_SENDCHANGE);
1731 WriteString(pSettings->xobrcDefaultFile, "session.screen0.focusModel:", pSettings->focusModel);
1732 FindAndSelect(item, "Click to focus", true);
1733 FindAndSelect(item, "Sloppy focus", false);
1734 FindAndSelect(item, "Auto raise", false);
1735 return;
1736 }
1737 else if (!_stricmp(item->m_pszArgument, "SloppyFocus"))
1738 {
1739 strcpy(pSettings->focusModel, item->m_pszArgument);
1740 SystemParametersInfo(SPI_SETACTIVEWINDOWTRACKING, 0, (PVOID)true, SPIF_SENDCHANGE);
1741 SystemParametersInfo(SPI_SETACTIVEWNDTRKZORDER, 0, (PVOID)false, SPIF_SENDCHANGE);
1742 WriteString(pSettings->xobrcDefaultFile, "session.screen0.focusModel:", pSettings->focusModel);
1743 FindAndSelect(item, "Click to focus", false);
1744 FindAndSelect(item, "Sloppy focus", true);
1745 FindAndSelect(item, "Auto raise", false);
1746 return;
1747 }
1748 else if (!_stricmp(item->m_pszArgument, "AutoRaiseSloppyFocus"))
1749 {
1750 strcpy(pSettings->focusModel, item->m_pszArgument);
1751 SystemParametersInfo(SPI_SETACTIVEWINDOWTRACKING, 0, (PVOID)true, SPIF_SENDCHANGE);
1752 SystemParametersInfo(SPI_SETACTIVEWNDTRKZORDER, 0, (PVOID)true, SPIF_SENDCHANGE);
1753 WriteString(pSettings->xobrcDefaultFile, "session.screen0.focusModel:", pSettings->focusModel);
1754 FindAndSelect(item, "Click to focus", false);
1755 FindAndSelect(item, "Sloppy focus", false);
1756 FindAndSelect(item, "Auto raise", true);
1757 return;
1758 }
1759 else if (!_stricmp(item->m_pszArgument, "SmartPlacementRows"))
1760 {
1761 strcpy(pSettings->windowPlacement, "RowSmartPlacement");
1762 WriteString(pSettings->xobrcDefaultFile, "session.screen0.windowPlacement:", pSettings->windowPlacement);
1763 return;
1764 }
1765 else if (!_stricmp(item->m_pszArgument, "SmartPlacementColumns"))
1766 {
1767 strcpy(pSettings->windowPlacement, "ColSmartPlacement");
1768 WriteString(pSettings->xobrcDefaultFile, "session.screen0.windowPlacement:", pSettings->windowPlacement);
1769 return;
1770 }
1771 else if (!_stricmp(item->m_pszArgument, "CascadePlacement"))
1772 {
1773 strcpy(pSettings->windowPlacement, "CascadePlacement");
1774 WriteString(pSettings->xobrcDefaultFile, "session.screen0.windowPlacement:", pSettings->windowPlacement);
1775 return;
1776 }
1777 else if (!_stricmp(item->m_pszArgument, "LeftToRight"))
1778 {
1779 strcpy(pSettings->rowPlacementDirection, item->m_pszArgument);
1780 WriteString(pSettings->xobrcDefaultFile, "session.screen0.rowPlacementDirection:", pSettings->rowPlacementDirection);
1781 return;
1782 }
1783 else if (!_stricmp(item->m_pszArgument, "RightToLeft"))
1784 {
1785 strcpy(pSettings->rowPlacementDirection, item->m_pszArgument);
1786 WriteString(pSettings->xobrcDefaultFile, "session.screen0.rowPlacementDirection:", pSettings->rowPlacementDirection);
1787 return;
1788 }
1789 else if (!_stricmp(item->m_pszArgument, "TopToBottom"))
1790 {
1791 strcpy(pSettings->colPlacementDirection, item->m_pszArgument);
1792 WriteString(pSettings->xobrcDefaultFile, "session.screen0.colPlacementDirection:", pSettings->colPlacementDirection);
1793 return;
1794 }
1795 else if (!_stricmp(item->m_pszArgument, "BottomToTop"))
1796 {
1797 strcpy(pSettings->colPlacementDirection, item->m_pszArgument);
1798 WriteString(pSettings->xobrcDefaultFile, "session.screen0.colPlacementDirection:", pSettings->colPlacementDirection);
1799 return;
1800 }
1801 }
1802*/
1803 }
1804 }
1805}
bool DownloadFile(LPCSTR url, LPCSTR path)
Definition BBApi.cpp:3296
void BBSmartExecute(LPSTR inputString)
Definition BBApi.cpp:1767
Wallpaper * pWallpaper
Definition Blackbox.cpp:50
bool CopyStringToClipboard(LPSTR string)
Definition BBApi.cpp:3450
void Log(LPCSTR des, LPCSTR line)
Definition BBApi.cpp:638
HINSTANCE BBExecute(HWND Owner, LPCSTR szOperation, LPCSTR szCommand, LPCSTR szArgs, LPCSTR szDirectory, int nShowCmd, bool noErrorMsgs)
Definition BBApi.cpp:1648
#define BB_SHUTDOWN
Definition BBApi.h:175
#define BB_QUIT
Definition BBApi.h:145
#define BB_RUN
Definition BBApi.h:176
#define BB_RESTART
Definition BBApi.h:146
#define BB_BROADCAST
Definition BBApi.h:245
#define BB_SETTHEME
Definition BBApi.h:151
#define BB_SETSTYLE
Definition BBApi.h:148
#define BB_BRINGTOFRONT
Definition BBApi.h:182
#define MENUITEM_EDITINT
Definition MenuItem.h:44
#define GROUP_DEFAULT
Definition MenuItem.h:62
#define MENUITEM_BOOLEAN
Definition MenuItem.h:45
@ SFX_MENU_CLICK
Definition Sounds.h:45
void HideAfterInvoke(MenuItem *item, int button)
Definition MenuCommon.cpp:1812
void UpdateMenuWindow()
Definition Menu.cpp:181
void ClearSelectionGroup(int group)
Definition Menu.cpp:1507
bool IsPinned()
Definition Menu.cpp:1497
char * m_pszArgument
Definition MenuItem.h:98
int m_currentValue
Definition MenuItem.h:104
int m_minValue
Definition MenuItem.h:105
char * m_pszCommand
Definition MenuItem.h:97
int m_nWidth
Definition MenuItem.h:185
POINT m_mousePos
Definition MenuItem.h:176
Menu * m_pParent
Definition MenuItem.h:180
bool m_isSelected
Definition MenuItem.h:101
wchar_t * m_pszOriginalTitleUnicode
Definition MenuItem.h:100
int m_maxValue
Definition MenuItem.h:106
void ToggleSelected()
Definition MenuItem.cpp:523
int m_selectionGroup
Definition MenuItem.h:102
virtual void SetTitleANSI(char *pszTitleANSI)
Definition MenuItem.cpp:449
virtual void SetTitleUnicode(wchar_t *pszTitleUnicode)
Definition MenuItem.cpp:456
char * m_pszOriginalTitleANSI
Definition MenuItem.h:99
int itemType
Definition MenuItem.h:95
bool usingDefaultTheme
Definition Settings.h:386
char preferredEditor[MAX_LINE_LENGTH]
Definition Settings.h:341
struct Settings::Statistics Statistics
char SF_blackboxPath[MAX_PATH]
Definition Settings.h:377
char * m_pszInit
Definition StringItem.h:55
char * m_pszCommand
Definition StringItem.h:54
void SetWallpaper(LPSTR wpPath, LPSTR wpStyle)
Definition Wallpaper.cpp:238
int changedWallpaper
Definition Settings.h:397

◆ HideAfterInvoke()

void MenuCommon::HideAfterInvoke ( MenuItem * item,
int button )
1813{
1814 if (item->itemType == MENUITEM_BOOLEAN)
1815 {
1816 if (!item->m_isSelected) item->m_isSelected = true;
1817 else item->m_isSelected = false;
1818 }
1819
1820 //====================
1821
1822 if (item->m_pParent->IsPinned() || (button != 1))
1823 {
1824 item->m_pParent->UpdateMenuWindow();
1825 }
1826
1827 //====================
1828
1829 if (button == 1)
1830 {
1831 // First we set focus to the toolbar to prevent
1832 // the focus from going back to the previous task
1833 // after the menu is closed...
1834// if (pSettings->followActive) SetForegroundWindow(pToolbar->hToolbarWnd);
1835 // ...and then we hide all non-pinned menus...
1836 Hide();
1837 }
1838}

◆ DrawMenuBullet()

void MenuCommon::DrawMenuBullet ( FolderItem * item,
HDC hDC,
int nTop,
int type )
1846{
1847 if (type == MENU_BULLET_EMPTY) return;
1848
1849 //====================
1850
1851 HPEN hPen, hOldPen;
1852
1853 COLORREF penColor;
1854 if (item->IsActive()) penColor = pSettings->MenuActive->BulletColor;
1855 else penColor = pSettings->MenuFrame->BulletColor;
1856 hPen = CreatePen(PS_SOLID, 1, penColor);
1857
1858 hOldPen = (HPEN) SelectObject(hDC, hPen);
1859 SelectObject(hDC, GetStockObject(NULL_BRUSH)); // -> Do not automatically fill any drawn shapes below...
1860
1861 int bulletPadding = (item->GetHeight() - m_nBulletSize) / 2;
1862
1863 int x;
1864 if (m_nBulletPosition == DT_RIGHT)
1865 {
1866// x = item->GetWidth() - pSettings->MenuFrame->borderWidth - pSettings->MenuFrame->marginWidth;
1867// if (pSettings->doubleScaleHiDPI) x -= 15;
1868// else x -= 8;
1869 x = item->GetWidth() - pSettings->MenuFrame->borderWidth - pSettings->MenuFrame->marginWidth - bulletPadding - (m_nBulletSize / 2);
1870// x = item->GetWidth() - m_nRightIndent + (m_nBulletSize / 2);
1871 }
1872 else
1873 {
1874// x = pSettings->MenuFrame->borderWidth + pSettings->MenuFrame->marginWidth;
1875// if (pSettings->doubleScaleHiDPI) x += 15;
1876// else x += 8;
1878// x = m_nLeftIndent - (m_nBulletSize / 2);
1879 }
1880
1881 int y = nTop + (item->GetHeight() / 2);
1882
1883 RECT bulletRect;
1884// if (pSettings->doubleScaleHiDPI) SetRect(&bulletRect, x-5, y-5, x+5, y+5);
1885 if (pSettings->scalingFactorHiDPI == 4) SetRect(&bulletRect, x-10, y-10, x+10, y+10); // -> 20x20 pixel bullet
1886 else if (pSettings->scalingFactorHiDPI == 3) SetRect(&bulletRect, x-7, y-7, x+8, y+8); // -> 15x15 pixel bullet
1887 else if (pSettings->scalingFactorHiDPI == 2) SetRect(&bulletRect, x-5, y-5, x+5, y+5); // -> 10x10 pixel bullet
1888 else SetRect(&bulletRect, x-2, y-2, x+3, y+3); // -> 5x5 pixel bullet
1889
1890 //====================
1891
1892 if (type == MENU_BULLET_IMAGE)
1893 {
1894 if (pSettings->MenuFrameBullet->Image.bitmap != NULL)
1895 {
1896 // Draw menu bullet image, preserving any per pixel alpha transparency...
1897 // (-> supporting both 32bpp ARGB and 24bpp RGB format images)
1898
1899 if (item->IsActive()) DrawImageIntoRect(hDC, bulletRect, pSettings->MenuActiveBullet, true, false);
1900 else DrawImageIntoRect(hDC, bulletRect, pSettings->MenuFrameBullet, true, false);
1901/*
1902 HDC buf = CreateCompatibleDC(hDC);
1903 int bulletWidth, bulletHeight;
1904 if (item->IsActive() && (pSettings->MenuActiveBullet->Image.bitmap != NULL))
1905 {
1906 DeleteObject(SelectObject(buf, pSettings->MenuActiveBullet->Image.bitmap));
1907 bulletWidth = pSettings->MenuActiveBullet->Image.width;
1908 bulletHeight = pSettings->MenuActiveBullet->Image.height;
1909 }
1910 else
1911 {
1912 DeleteObject(SelectObject(buf, pSettings->MenuFrameBullet->Image.bitmap));
1913 bulletWidth = pSettings->MenuFrameBullet->Image.width;
1914 bulletHeight = pSettings->MenuFrameBullet->Image.height;
1915 }
1916
1917 SetStretchBltMode(hDC, HALFTONE);
1918// if (pSettings->doubleScaleHiDPI) StretchBlt(hDC, x-5, y-5, 10, 10, buf, 0, 0, imageWidth, imageHeight, SRCCOPY);
1919// else StretchBlt(hDC, x-2, y-2, 5, 5, buf, 0, 0, imageWidth, imageHeight, SRCCOPY);
1920 // ### Note: While AlphaBlend() can be used to draw 32bpp ARGB images with per pixel alpha transparency, it also scales images down
1921 // much less smoothly than StretchBlt() as it reverts from HALFTONE (i.e. pixel averaging) to COLORONCOLOR (i.e. pixel deleting) mode;
1922 // for more information see https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-alphablend ###
1923 BLENDFUNCTION bf;
1924 ZeroMemory(&bf, sizeof(BLENDFUNCTION));
1925 bf.BlendOp = AC_SRC_OVER;
1926 bf.SourceConstantAlpha = 255;
1927 bf.AlphaFormat = AC_SRC_ALPHA;
1928 if (pSettings->doubleScaleHiDPI) AlphaBlend(hDC, x-5, y-5, 10, 10, buf, 0, 0, bulletWidth, bulletHeight, bf);
1929 else AlphaBlend(hDC, x-2, y-2, 5, 5, buf, 0, 0, bulletWidth, bulletHeight, bf);
1930 DeleteDC(buf);
1931*/
1932 }
1933 }
1934 else if (type == MENU_BULLET_TRIANGLE)
1935 {
1936 if (m_nBulletPosition == DT_LEFT) // Backward pointing arrow
1937 {
1939 {
1940 MoveToEx(hDC, x - 3, y, NULL);
1941 LineTo(hDC, x - 3, y + 1);
1942 MoveToEx(hDC, x - 2, y - 1, NULL);
1943 LineTo(hDC, x - 2, y + 2);
1944 MoveToEx(hDC, x - 1, y - 2, NULL);
1945 LineTo(hDC, x - 1, y + 3);
1946 MoveToEx(hDC, x, y - 3, NULL);
1947 LineTo(hDC, x, y + 4);
1948 MoveToEx(hDC, x + 1, y - 4, NULL);
1949 LineTo(hDC, x + 1, y + 5);
1950 }
1951 else
1952 {
1953 MoveToEx(hDC, x - 3, y, NULL);
1954 LineTo(hDC, x - 3, y + 1);
1955 MoveToEx(hDC, x - 2, y - 1, NULL);
1956 LineTo(hDC, x - 2, y + 2);
1957 MoveToEx(hDC, x - 1, y - 2, NULL);
1958 LineTo(hDC, x - 1, y + 3);
1959 MoveToEx(hDC, x, y - 3, NULL);
1960 LineTo(hDC, x, y + 4);
1961 }
1962 }
1963 else // Forward pointing arrow (default)
1964 {
1966 {
1967 MoveToEx(hDC, x - 2, y - 4, NULL);
1968 LineTo(hDC, x - 2, y + 5);
1969 MoveToEx(hDC, x - 1, y - 3, NULL);
1970 LineTo(hDC, x - 1, y + 4);
1971 MoveToEx(hDC, x, y - 2, NULL);
1972 LineTo(hDC, x, y + 3);
1973 MoveToEx(hDC, x + 1, y - 1, NULL);
1974 LineTo(hDC, x + 1, y + 2);
1975 MoveToEx(hDC, x + 2, y, NULL);
1976 LineTo(hDC, x + 2, y + 1);
1977 }
1978 else
1979 {
1980 MoveToEx(hDC, x - 1, y - 3, NULL);
1981 LineTo(hDC, x - 1, y + 4);
1982 MoveToEx(hDC, x, y - 2, NULL);
1983 LineTo(hDC, x, y + 3);
1984 MoveToEx(hDC, x + 1, y - 1, NULL);
1985 LineTo(hDC, x + 1, y + 2);
1986 MoveToEx(hDC, x + 2, y, NULL);
1987 LineTo(hDC, x + 2, y + 1);
1988 }
1989 }
1990
1991 }
1992
1993 //====================
1994
1995 else if (type == MENU_BULLET_SQUARE)
1996 {
1997// if (pSettings->doubleScaleHiDPI)
1998// {
1999// Rectangle(hDC, x - 5, y - 5, x + 5, y + 5);
2000// Rectangle(hDC, x - 4, y - 4, x + 4, y + 4);
2001// }
2002// else
2003// {
2004// // ### To be updated to use Rectangle(). cf. HiDPI above, easier to read... ###
2005//
2006// MoveToEx(hDC, x + 2, y + 2, NULL);
2007// LineTo(hDC, x + 2, y - 3);
2008// LineTo(hDC, x - 3, y - 3);
2009// LineTo(hDC, x - 3, y + 2);
2010// LineTo(hDC, x + 2, y + 2);
2011// }
2012
2013 for (int n = 1; n <= pSettings->scalingFactorHiDPI; n++)
2014 {
2015 Rectangle(hDC, bulletRect.left, bulletRect.top, bulletRect.right, bulletRect.bottom);
2016 InflateRect(&bulletRect, -1, -1);
2017 }
2018
2019// if (item->IsActive()) DrawGlyph(hDC, bulletRect, GLYPH_MENU_SQUARE, pSettings->MenuActive->BulletColor);
2020// else DrawGlyph(hDC, bulletRect, GLYPH_MENU_SQUARE, pSettings->MenuFrame->BulletColor);
2021 }
2022
2023 //====================
2024
2025 else if (type == MENU_BULLET_CIRCLE)
2026 {
2028 {
2029 Ellipse(hDC, x - 5, y - 5, x + 5, y + 5);
2030
2031 COLORREF blendColor = pSettings->MixColors(GetPixel(hDC, x, y), penColor);
2032
2033 // Smooth out outer edge...
2034 SetPixel(hDC, x - 2, y - 5, blendColor);
2035 SetPixel(hDC, x + 1, y - 5, blendColor);
2036 SetPixel(hDC, x - 5, y - 2, blendColor);
2037 SetPixel(hDC, x - 5, y + 1, blendColor);
2038 SetPixel(hDC, x + 4, y - 2, blendColor);
2039 SetPixel(hDC, x + 4, y + 1, blendColor);
2040 SetPixel(hDC, x - 2, y + 4, blendColor);
2041 SetPixel(hDC, x + 1, y + 4, blendColor);
2042
2043 // Smooth out inner edge...
2044 SetPixel(hDC, x - 1, y - 4, blendColor);
2045 SetPixel(hDC, x, y - 4, blendColor);
2046 SetPixel(hDC, x - 3, y - 3, blendColor);
2047 SetPixel(hDC, x + 2, y - 3, blendColor);
2048 SetPixel(hDC, x - 4, y - 1, blendColor);
2049 SetPixel(hDC, x - 4, y, blendColor);
2050 SetPixel(hDC, x + 3, y - 1, blendColor);
2051 SetPixel(hDC, x + 3, y, blendColor);
2052 SetPixel(hDC, x - 3, y + 2, blendColor);
2053 SetPixel(hDC, x + 2, y + 2, blendColor);
2054 SetPixel(hDC, x - 1, y + 3, blendColor);
2055 SetPixel(hDC, x, y + 3, blendColor);
2056
2057 // Smooth out corner pixels... (these pixels are more visually noticeable if off, so here we blend per pixel as well)
2058// blendColor = pSettings->MixColors(GetPixel(hDC, x, y), blendColor);
2059 blendColor = pSettings->MixColors(GetPixel(hDC, x - 4, y - 4), blendColor);
2060 SetPixel(hDC, x - 4, y - 4, blendColor);
2061 blendColor = pSettings->MixColors(GetPixel(hDC, x + 3, y - 4), blendColor);
2062 SetPixel(hDC, x + 3, y - 4, blendColor);
2063 blendColor = pSettings->MixColors(GetPixel(hDC, x - 4, y + 3), blendColor);
2064 SetPixel(hDC, x - 4, y + 3, blendColor);
2065 blendColor = pSettings->MixColors(GetPixel(hDC, x + 3, y + 3), blendColor);
2066 SetPixel(hDC, x + 3, y + 3, blendColor);
2067 }
2068 else
2069 {
2070 Arc(hDC, x - 4, y - 3, x + 3, y + 4, x - 1, y - 3, x - 1, y - 3);
2071// Ellipse(hDC, x - 4, y - 3, x + 3, y + 4);
2072 }
2073 }
2074
2075 //====================
2076
2077 else if (type == MENU_BULLET_DIAMOND)
2078 {
2080 {
2081 MoveToEx(hDC, x - 4, y, NULL);
2082 LineTo(hDC, x - 4, y + 1);
2083 MoveToEx(hDC, x - 3, y - 1, NULL);
2084 LineTo(hDC, x - 3, y + 2);
2085 MoveToEx(hDC, x - 2, y - 2, NULL);
2086 LineTo(hDC, x - 2, y + 3);
2087 MoveToEx(hDC, x - 1, y - 3, NULL);
2088 LineTo(hDC, x - 1, y + 4);
2089 MoveToEx(hDC, x, y - 4, NULL);
2090 LineTo(hDC, x, y + 5);
2091 MoveToEx(hDC, x + 1, y - 3, NULL);
2092 LineTo(hDC, x + 1, y + 4);
2093 MoveToEx(hDC, x + 2, y - 2, NULL);
2094 LineTo(hDC, x + 2, y + 3);
2095 MoveToEx(hDC, x + 3, y - 1, NULL);
2096 LineTo(hDC, x + 3, y + 2);
2097 MoveToEx(hDC, x + 4, y, NULL);
2098 LineTo(hDC, x + 4, y + 1);
2099 }
2100 else
2101 {
2102 // ### To be updated to not use a loop. cf. HiDPI above, easier to read... ###
2103
2104 int r = 3;
2105
2106 int fromX, toX, lineY;
2107 for (fromX = x, toX = x + 1, lineY = y - r; lineY <= y + r; lineY++)
2108 {
2109 MoveToEx(hDC, fromX, lineY, NULL);
2110 LineTo(hDC, toX, lineY);
2111 if (lineY < y) fromX--, toX++;
2112 else fromX++, toX--;
2113 }
2114 }
2115 }
2116
2117 //====================
2118
2119 else if (type == MENU_BULLET_TRIPLE)
2120 {
2122 {
2123 if (item->IsActive()) // Draw horizontal lines...
2124 {
2125 MoveToEx(hDC, x + 4, y - 5, NULL);
2126 LineTo(hDC, x - 6, y - 5);
2127 MoveToEx(hDC, x + 4, y - 4, NULL);
2128 LineTo(hDC, x - 6, y - 4);
2129
2130 MoveToEx(hDC, x + 4, y - 1, NULL);
2131 LineTo(hDC, x - 6, y - 1);
2132 MoveToEx(hDC, x + 4, y, NULL);
2133 LineTo(hDC, x - 6, y);
2134
2135 MoveToEx(hDC, x + 4, y + 3, NULL);
2136 LineTo(hDC, x - 6, y + 3);
2137 MoveToEx(hDC, x + 4, y + 4, NULL);
2138 LineTo(hDC, x - 6, y + 4);
2139 }
2140 else // Draw vertical lines...
2141 {
2142 MoveToEx(hDC, x + 4, y + 4, NULL);
2143 LineTo(hDC, x + 4, y - 6);
2144 MoveToEx(hDC, x + 3, y + 4, NULL);
2145 LineTo(hDC, x + 3, y - 6);
2146
2147 MoveToEx(hDC, x, y + 4, NULL);
2148 LineTo(hDC, x, y - 6);
2149 MoveToEx(hDC, x - 1, y + 4, NULL);
2150 LineTo(hDC, x - 1, y - 6);
2151
2152 MoveToEx(hDC, x - 4, y + 4, NULL);
2153 LineTo(hDC, x - 4, y - 6);
2154 MoveToEx(hDC, x - 5, y + 4, NULL);
2155 LineTo(hDC, x - 5, y - 6);
2156 }
2157 }
2158 else
2159 {
2160 if (item->IsActive()) // Draw horizontal lines...
2161 {
2162 MoveToEx(hDC, x + 2, y - 2, NULL);
2163 LineTo(hDC, x - 3, y - 2);
2164 MoveToEx(hDC, x + 2, y, NULL);
2165 LineTo(hDC, x - 3, y);
2166 MoveToEx(hDC, x + 2, y + 2, NULL);
2167 LineTo(hDC, x - 3, y + 2);
2168 }
2169 else // Draw vertical lines...
2170 {
2171 MoveToEx(hDC, x + 2, y + 2, NULL);
2172 LineTo(hDC, x + 2, y - 3);
2173 MoveToEx(hDC, x, y + 2, NULL);
2174 LineTo(hDC, x, y - 3);
2175 MoveToEx(hDC, x - 2, y + 2, NULL);
2176 LineTo(hDC, x - 2, y - 3);
2177 }
2178 }
2179 }
2180
2181 //====================
2182
2183 else if (type == MENU_BULLET_COMMENT)
2184 {
2186 {
2187 MoveToEx(hDC, x - 1, y - 5, NULL);
2188 LineTo(hDC, x - 6, y);
2189 MoveToEx(hDC, x, y - 5, NULL);
2190 LineTo(hDC, x - 6, y + 1);
2191 MoveToEx(hDC, x, y - 4, NULL);
2192 LineTo(hDC, x - 5, y + 1);
2193
2194 MoveToEx(hDC, x + 3, y - 1, NULL);
2195 LineTo(hDC, x - 2, y + 4);
2196 MoveToEx(hDC, x + 4, y - 1, NULL);
2197 LineTo(hDC, x - 2, y + 5);
2198 MoveToEx(hDC, x + 4, y, NULL);
2199 LineTo(hDC, x - 1, y + 5);
2200 }
2201 else
2202 {
2203 MoveToEx(hDC, x, y - 3, NULL);
2204 LineTo(hDC, x - 4, y + 1);
2205 MoveToEx(hDC, x + 2, y - 1, NULL);
2206 LineTo(hDC, x - 2, y + 3);
2207 }
2208 }
2209
2210 //====================
2211
2212 else if (type == MENU_BULLET_GRID)
2213 {
2215 {
2216 // Draw horizontal lines x 3... (nb. the same draw commands as Triple active!)
2217 MoveToEx(hDC, x + 4, y - 5, NULL);
2218 LineTo(hDC, x - 6, y - 5);
2219 MoveToEx(hDC, x + 4, y - 4, NULL);
2220 LineTo(hDC, x - 6, y - 4);
2221
2222 MoveToEx(hDC, x + 4, y - 1, NULL);
2223 LineTo(hDC, x - 6, y - 1);
2224 MoveToEx(hDC, x + 4, y, NULL);
2225 LineTo(hDC, x - 6, y);
2226
2227 MoveToEx(hDC, x + 4, y + 3, NULL);
2228 LineTo(hDC, x - 6, y + 3);
2229 MoveToEx(hDC, x + 4, y + 4, NULL);
2230 LineTo(hDC, x - 6, y + 4);
2231
2232 // Draw vertical lines x 3... (nb. the same draw commands as Triple non-active!)
2233 MoveToEx(hDC, x + 4, y + 4, NULL);
2234 LineTo(hDC, x + 4, y - 6);
2235 MoveToEx(hDC, x + 3, y + 4, NULL);
2236 LineTo(hDC, x + 3, y - 6);
2237
2238 MoveToEx(hDC, x, y + 4, NULL);
2239 LineTo(hDC, x, y - 6);
2240 MoveToEx(hDC, x - 1, y + 4, NULL);
2241 LineTo(hDC, x - 1, y - 6);
2242
2243 MoveToEx(hDC, x - 4, y + 4, NULL);
2244 LineTo(hDC, x - 4, y - 6);
2245 MoveToEx(hDC, x - 5, y + 4, NULL);
2246 LineTo(hDC, x - 5, y - 6);
2247 }
2248 else
2249 {
2250 // Draw horizontal lines x 3...
2251 MoveToEx(hDC, x + 1, y - 2, NULL);
2252 LineTo(hDC, x - 3, y - 2);
2253 MoveToEx(hDC, x + 1, y, NULL);
2254 LineTo(hDC, x - 3, y);
2255 MoveToEx(hDC, x + 1, y + 2, NULL);
2256 LineTo(hDC, x - 3, y + 2);
2257
2258 // Draw vertical lines x 3...
2259 MoveToEx(hDC, x + 2, y + 2, NULL);
2260 LineTo(hDC, x + 2, y - 3);
2261 MoveToEx(hDC, x, y + 2, NULL);
2262 LineTo(hDC, x, y - 3);
2263 MoveToEx(hDC, x - 2, y + 2, NULL);
2264 LineTo(hDC, x - 2, y - 3);
2265 }
2266 }
2267
2268 //====================
2269
2270 else if (type == MENU_BULLET_QUAD)
2271 {
2273 {
2274 Rectangle(hDC, x - 5, y - 5, x - 1, y - 1);
2275 Rectangle(hDC, x + 1, y - 5, x + 5, y - 1);
2276 Rectangle(hDC, x - 5, y + 1, x - 1, y + 5);
2277 Rectangle(hDC, x + 1, y + 1, x + 5, y + 5);
2278 }
2279 else
2280 {
2281 // ##### WORK IN PROGRESS :) #####
2282 }
2283 }
2284
2285 //====================
2286
2287 SelectObject(hDC, hOldPen);
2288 DeleteObject(hPen);
2289 DeleteObject(hOldPen);
2290}
void DrawImageIntoRect(HDC hdc, RECT r, StyleItem *styleItem, bool useAlpha, bool drawBorder)
Definition BBApi.cpp:2333
#define MENU_BULLET_TRIPLE
Definition Settings.h:59
#define MENU_BULLET_COMMENT
Definition Settings.h:60
#define MENU_BULLET_SQUARE
Definition Settings.h:56
#define MENU_BULLET_QUAD
Definition Settings.h:62
#define MENU_BULLET_DIAMOND
Definition Settings.h:55
#define MENU_BULLET_CIRCLE
Definition Settings.h:58
#define MENU_BULLET_TRIANGLE
Definition Settings.h:57
#define MENU_BULLET_IMAGE
Definition Settings.h:63
#define MENU_BULLET_GRID
Definition Settings.h:61
virtual bool IsActive()
Definition MenuItem.h:77
virtual int GetWidth()
Definition MenuItem.h:120
virtual int GetHeight()
Definition MenuItem.h:122
bool doubleScaleHiDPI
Definition Settings.h:326
StyleItem * MenuFrameBullet
Definition Settings.h:437
StyleItem * MenuActiveBullet
Definition Settings.h:438
COLORREF MixColors(COLORREF colorA, COLORREF colorB)
Definition Settings.cpp:2231
StyleItemImage Image
Definition BBApi.h:441
HBITMAP bitmap
Definition BBApi.h:386

◆ DrawMenuIndicator()

void MenuCommon::DrawMenuIndicator ( MenuItem * item,
HDC hDC,
int nTop )
2298{
2299/*
2300 int x;
2301 if (m_nBulletPosition == DT_RIGHT)
2302 {
2303 x = item->GetWidth() - pSettings->MenuFrame->borderWidth - pSettings->MenuFrame->marginWidth;
2304 if (pSettings->doubleScaleHiDPI) x -= 15;
2305 else x -= 8;
2306 }
2307 else
2308 {
2309 x = pSettings->MenuFrame->borderWidth + pSettings->MenuFrame->marginWidth;
2310 if (pSettings->doubleScaleHiDPI) x += 15;
2311 else x += 8;
2312 }
2313
2314 int y = nTop + ((item->GetHeight()) / 2);
2315
2316 RECT indicatorRect;
2317
2318 if (pSettings->doubleScaleHiDPI)
2319 {
2320 // Indicator bullet -> 10x10 pixels filled square
2321 indicatorRect.left = x - 5;
2322 indicatorRect.top = y - 5;
2323 indicatorRect.right = x + 5;
2324 indicatorRect.bottom = y + 5;
2325 }
2326 else
2327 {
2328 // Indicator bullet -> 5x5 pixels filled square
2329 indicatorRect.left = x - 2;
2330 indicatorRect.top = y - 2;
2331 indicatorRect.right = x + 3;
2332 indicatorRect.bottom = y + 3;
2333 }
2334*/
2335 int indicatorPadding = (item->GetHeight() - m_nBulletSize) / 2;
2336
2337 int x;
2338// if (m_nBulletPosition == DT_RIGHT) x = item->GetWidth() - m_nRightIndent; // pSettings->MenuFrame->borderWidth - pSettings->MenuFrame->marginWidth - indicatorPadding - (m_nBulletSize / 2);
2339// else x = m_nLeftIndent; // pSettings->MenuFrame->borderWidth + pSettings->MenuFrame->marginWidth + indicatorPadding + (m_nBulletSize / 2);
2340// if (m_nBulletPosition == DT_RIGHT) x = item->GetWidth() - m_nRightIndent + (m_nBulletSize / 2);
2341// else x = m_nLeftIndent - (m_nBulletSize / 2)
2342 if (m_nBulletPosition == DT_RIGHT) x = item->GetWidth() - pSettings->MenuFrame->borderWidth - pSettings->MenuFrame->marginWidth - indicatorPadding - (m_nBulletSize / 2);
2343 else x = pSettings->MenuFrame->borderWidth + pSettings->MenuFrame->marginWidth + indicatorPadding + (m_nBulletSize / 2);
2344
2345
2346 int y = nTop + (item->GetHeight() / 2);
2347
2348 RECT indicatorRect;
2349 if (pSettings->scalingFactorHiDPI == 4) SetRect(&indicatorRect, x-10, y-10, x+10, y+10); // -> 20x20 pixel indicator
2350 else if (pSettings->scalingFactorHiDPI == 3) SetRect(&indicatorRect, x-7, y-7, x+8, y+8); // -> 15x15 pixel indicator
2351 else if (pSettings->scalingFactorHiDPI == 2) SetRect(&indicatorRect, x-5, y-5, x+5, y+5); // -> 10x10 pixel indicator
2352 else SetRect(&indicatorRect, x-2, y-2, x+3, y+3); // -> 5x5 pixel indicator
2353
2355 {
2356 // Draw menu indicator image, preserving any per pixel alpha transparency...
2357 // (-> supporting both 32bpp ARGB and 24bpp RGB format images)
2358 DrawImageIntoRect(hDC, indicatorRect, pSettings->MenuIndicator, true, false);
2359/*
2360 HDC buf = CreateCompatibleDC(hDC);
2361 DeleteObject(SelectObject(buf, pSettings->MenuIndicator->Image.bitmap));
2362 SetStretchBltMode(hDC, HALFTONE);
2363 // ### Note: While AlphaBlend() can be used to draw 32bpp ARGB images with per pixel alpha transparency, it also scales images down
2364 // much less smoothly than StretchBlt() as it reverts from HALFTONE (i.e. pixel averaging) to COLORONCOLOR (i.e. pixel deleting) mode;
2365 // for more information see https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-alphablend ###
2366 BLENDFUNCTION bf;
2367 ZeroMemory(&bf, sizeof(BLENDFUNCTION));
2368 bf.BlendOp = AC_SRC_OVER;
2369 bf.SourceConstantAlpha = 255;
2370 bf.AlphaFormat = AC_SRC_ALPHA;
2371 if (pSettings->doubleScaleHiDPI) AlphaBlend(hDC, indicatorRect.left, indicatorRect.top, 10, 10, buf, 0, 0, pSettings->MenuIndicator->Image.width, pSettings->MenuIndicator->Image.height, bf);
2372 else AlphaBlend(hDC, indicatorRect.left, indicatorRect.top, 5, 5, buf, 0, 0, pSettings->MenuIndicator->Image.width, pSettings->MenuIndicator->Image.height, bf);
2373 DeleteDC(buf);
2374*/
2375 }
2377}
void MakeGradientSuper(HDC hdc, RECT rect, int type, COLORREF color1, COLORREF color2, COLORREF color3, COLORREF color4, COLORREF color5, COLORREF color6, COLORREF color7, COLORREF color8, bool bInterlaced, int bevelStyle, int bevelPosition, int bevelWidth, COLORREF borderColour, int borderWidth)
Definition BBApi.cpp:2127
#define B_IMAGEFROMFILE
Definition BBApi.h:83
int bevelWidth
Definition Settings.h:564
StyleItem * MenuIndicator
Definition Settings.h:439
COLORREF Color5
Definition BBApi.h:436
COLORREF Color4
Definition BBApi.h:434
COLORREF Color6
Definition BBApi.h:437
int type
Definition BBApi.h:402
COLORREF Color7
Definition BBApi.h:438
COLORREF Color8
Definition BBApi.h:439
bool interlaced
Definition BBApi.h:404
COLORREF Color3
Definition BBApi.h:433

◆ DrawMenuPinned()

int MenuCommon::DrawMenuPinned ( MenuItem * item,
HDC hDC,
RECT itemRect )
2385{
2386 RECT tempRect;
2387 bool failsafe = false;
2388
2389 int height = item->GetHeight();
2390 if (pSettings->doubleScaleHiDPI && (height < 12)) failsafe = true;
2391 else if (!pSettings->doubleScaleHiDPI && (height < 7)) failsafe = true;
2392
2393 CopyRect(&tempRect, &itemRect);
2394
2395 int y = tempRect.top + height/2;
2396
2397 // If menu bullets are drawn on the right we draw the
2398 // menu pinned indicator on the left, and vice versa...
2399 int x;
2400 if (m_nBulletPosition == DT_LEFT) x = tempRect.right - y;
2401 else x = tempRect.left + y;
2402
2404 {
2405 tempRect.left = x - 5;
2406 tempRect.top = y - 5;
2407 tempRect.right = x + 5;
2408 tempRect.bottom = y + 5;
2409 }
2410 else
2411 {
2412 tempRect.left = x - 2;
2413 tempRect.top = y - 2;
2414 tempRect.right = x + 3;
2415 tempRect.bottom = y + 3;
2416 }
2417
2418 if (failsafe) SetPixel(hDC, x, y, pSettings->MenuIndicator->Color1); // Simple fallback...
2419 else
2420 {
2421 // MakeGradientSuper(hDC, tempRect, pSettings->MenuIndicator->type, pSettings->MenuIndicator->Color1, pSettings->MenuIndicator->Color2, pSettings->MenuIndicator->Color3, pSettings->MenuIndicator->Color4, pSettings->MenuIndicator->Color5, pSettings->MenuIndicator->Color6, pSettings->MenuIndicator->Color7, pSettings->MenuIndicator->Color8, false, pSettings->MenuIndicator->bevelstyle, pSettings->MenuIndicator->bevelposition, pSettings->bevelWidth, pSettings->MenuFrame->borderColor, 1);
2422 CreateBorder(hDC, &tempRect, pSettings->MenuTitle->TextColor, 1);
2423// InflateRect(&tempRect, -1, -1);
2424// CreateBorder(hDC, &tempRect, pSettings->MenuTitle->ShadowColor, 1);
2425// InflateRect(&tempRect, -1, -1);
2426 InflateRect(&tempRect, -2, -2);
2427 CreateBorder(hDC, &tempRect, pSettings->MenuTitle->TextColor, 1);
2428 }
2429/*
2430 if (m_nBulletPosition == DT_RIGHT)
2431 {
2432 // -> Menu pinned indicator on the left (see above)
2433 if (pSettings->MenuTitle->Justify == DT_CENTER) return (y * 2);
2434 else if (pSettings->MenuTitle->Justify == DT_LEFT) return (y * 2);
2435 else return 0;
2436 }
2437 else if (m_nBulletPosition == DT_LEFT)
2438 {
2439 // -> Menu pinned indicator on the right (see above)
2440 if (pSettings->MenuTitle->Justify == DT_CENTER)
2441 {
2442 if (pSettings->doubleScaleHiDPI) return (y + 5);
2443 else return (y + 3);
2444 }
2445 else if (pSettings->MenuTitle->Justify == DT_RIGHT) return (y * 2);
2446 else return 0;
2447 }
2448
2449 return 0; // Failsafe
2450*/
2451 return (y * 2);
2452}
void CreateBorder(HDC hdc, RECT *rect, int borderColour, int borderWidth)
Definition BBApi.cpp:2243
COLORREF TextColor
Definition BBApi.h:408

◆ FindActiveAndDeactivate()

bool MenuCommon::FindActiveAndDeactivate ( Menu * m,
bool repaint )
2460{
2461 MENUITERATOR i;
2462 bool success = false;
2463
2464 for (i = m->m_MenuItems.begin(); i != m->m_MenuItems.end(); ++i)
2465 {
2466 if ((*i)->IsActive())
2467 {
2468 if (repaint || ((*i)->itemType == MENUITEM_FOLDER)) (*i)->Active(false); // -> Automatically triggers a repaint... (nb. always done for folder items, which also need to close submenus)
2469 else (*i)->m_bActive = false; // -> Caller will have to trigger a repaint later...
2470
2471// return true;
2472 success = true;
2473 }
2474 }
2475
2476// return false; // If we did not find any active item...
2477 return success;
2478}
vector< MenuItem * >::iterator MENUITERATOR
Definition Menu.h:53
#define MENUITEM_FOLDER
Definition MenuItem.h:48

◆ FindAndSelect()

void MenuCommon::FindAndSelect ( MenuItem * item,
LPSTR title,
bool selected )
2486{
2487 MENUITERATOR i;
2488
2489 for (i = item->m_pParent->m_MenuItems.begin(); i != item->m_pParent->m_MenuItems.end(); ++i)
2490 {
2491 if (!_stricmp((*i)->m_pszTitleANSI, title))
2492 {
2493 (*i)->m_isSelected = selected;
2494 return;
2495 }
2496 }
2497}

◆ ScrollToItem()

void MenuCommon::ScrollToItem ( Menu * m,
MenuItem * item )
2505{
2506 if ((m == NULL) || (item == NULL)) return;
2507
2508 // Activate the specified menu item...
2509 FindActiveAndDeactivate(m, false);
2511 item->Active(true);
2512
2513 // If needed, scroll the menu to make the specified menu item visible on the screen...
2514 int screenY = GetSystemMetrics(SM_YVIRTUALSCREEN);
2515 int screenHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
2516 if ((m->menuY+item->m_nTop) >= screenHeight)
2517 {
2518 m->menuY = screenHeight - item->m_nTop - m_nSubmenuHeight;
2519 }
2520 else if ((m->menuY+item->m_nTop) <= screenY)
2521 {
2522 m->menuY = screenY + item->m_nTop - m_nSubmenuHeight;
2523 }
2524 SetWindowPos(m->hMenuWnd, HWND_TOP, m->menuX, m->menuY, 0, 0, SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOSIZE);
2525
2527}
@ SFX_MENU_NAVIGATE
Definition Sounds.h:43
bool FindActiveAndDeactivate(Menu *m, bool repaint)
Definition MenuCommon.cpp:2459
int menuX
Definition Menu.h:176
int menuY
Definition Menu.h:176
HWND hMenuWnd
Definition Menu.h:143
virtual bool Active(bool bActive)
Definition MenuItem.cpp:257
int m_nTop
Definition MenuItem.h:184

Member Data Documentation

◆ m_MenusVector

vector<Menu*> MenuCommon::m_MenusVector

◆ hInst

HINSTANCE MenuCommon::hInst

◆ m_szHotListName

char MenuCommon::m_szHotListName[256]

◆ m_nGradientTitle

DWORD MenuCommon::m_nGradientTitle

◆ m_nGradientEntry

DWORD MenuCommon::m_nGradientEntry

◆ m_nGradientSelEntry

DWORD MenuCommon::m_nGradientSelEntry

◆ m_nTitleHeight

int MenuCommon::m_nTitleHeight

◆ m_nTitleDisabled

bool MenuCommon::m_nTitleDisabled

◆ m_nSubmenuHeight

int MenuCommon::m_nSubmenuHeight

◆ m_nMarginHeight

int MenuCommon::m_nMarginHeight

◆ m_nSeparatorHeight

int MenuCommon::m_nSeparatorHeight

◆ m_nGripHeight

int MenuCommon::m_nGripHeight

◆ m_nGripDisabled

bool MenuCommon::m_nGripDisabled

◆ m_nLeftIndent

int MenuCommon::m_nLeftIndent

◆ m_nRightIndent

int MenuCommon::m_nRightIndent

◆ m_nBulletSize

int MenuCommon::m_nBulletSize

◆ m_nBulletPosition

int MenuCommon::m_nBulletPosition

◆ m_nBulletStyle

int MenuCommon::m_nBulletStyle

◆ m_pMainMenu

Menu* MenuCommon::m_pMainMenu

◆ m_pStylesMenu

Menu* MenuCommon::m_pStylesMenu

◆ m_pThemesMenu

Menu* MenuCommon::m_pThemesMenu

◆ m_pWorkspacesMenu

Menu* MenuCommon::m_pWorkspacesMenu

◆ m_pConfigMenu

Menu* MenuCommon::m_pConfigMenu

◆ m_pPluginMenu

Menu* MenuCommon::m_pPluginMenu

◆ m_hTitleFont

HFONT MenuCommon::m_hTitleFont

◆ m_hFrameFont

HFONT MenuCommon::m_hFrameFont

◆ m_hGripFont

HFONT MenuCommon::m_hGripFont

◆ m_hEditStringFont

HFONT MenuCommon::m_hEditStringFont

◆ currentStyleMenuItem

MenuItem* MenuCommon::currentStyleMenuItem

◆ stylesMenusPinned

int MenuCommon::stylesMenusPinned