2 * Copyright 2003 Martin Fuchs
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 // Explorer start menu
27 // Martin Fuchs, 19.08.2003
29 // Credits: Thanks to Everaldo (http://www.everaldo.com) for his nice looking icons.
33 #include "../utility/utility.h"
35 #include "../explorer.h"
36 #include "../globals.h"
37 #include "../externals.h"
38 #include "../explorer_intres.h"
40 #include "desktopbar.h"
41 #include "startmenu.h"
42 #include "../dialogs/searchprogram.h"
45 StartMenu::StartMenu(HWND hwnd
)
48 _next_id
= IDC_FIRST_MENU
;
52 _last_pos
= WindowRect(hwnd
).pos();
53 #ifdef _LIGHT_STARTMENU
58 StartMenu::StartMenu(HWND hwnd
, const StartMenuCreateInfo
& create_info
)
60 _create_info(create_info
)
62 for(StartMenuFolders::const_iterator it
=create_info
._folders
.begin(); it
!=create_info
._folders
.end(); ++it
)
64 _dirs
.push_back(ShellDirectory(Desktop(), *it
, _hwnd
));
66 _next_id
= IDC_FIRST_MENU
;
69 _border_top
= create_info
._border_top
;
70 _last_pos
= WindowRect(hwnd
).pos();
71 #ifdef _LIGHT_STARTMENU
76 StartMenu::~StartMenu()
78 SendParent(PM_STARTMENU_CLOSED
);
82 // We need this wrapper function for s_wcStartMenu, it calls the WIN32 API,
83 // though static C++ initializers are not allowed for Winelib applications.
84 BtnWindowClass
& StartMenu::GetWndClasss()
86 static BtnWindowClass
s_wcStartMenu(CLASSNAME_STARTMENU
);
92 Window::CREATORFUNC
StartMenu::s_def_creator
= STARTMENU_CREATOR(StartMenu
);
94 HWND
StartMenu::Create(int x
, int y
, const StartMenuFolders
& folders
, HWND hwndParent
, LPCTSTR title
, CREATORFUNC creator
)
100 style
= WS_POPUP
|WS_THICKFRAME
|WS_CLIPCHILDREN
|WS_VISIBLE
;
102 top_height
= STARTMENU_TOP_BTN_SPACE
;
104 style
= WS_POPUP
|WS_CAPTION
|WS_SYSMENU
|WS_CLIPCHILDREN
|WS_VISIBLE
;
105 ex_style
= WS_EX_TOOLWINDOW
;
109 RECT rect
= {x
, y
-STARTMENU_LINE_HEIGHT
-top_height
, x
+STARTMENU_WIDTH_MIN
, y
};
111 #ifndef _LIGHT_STARTMENU
112 rect
.top
+= STARTMENU_LINE_HEIGHT
;
115 AdjustWindowRectEx(&rect
, style
, FALSE
, ex_style
);
117 StartMenuCreateInfo create_info
;
119 create_info
._folders
= folders
;
120 create_info
._border_top
= top_height
;
121 create_info
._creator
= creator
;
124 create_info
._title
= title
;
126 HWND hwnd
= Window::Create(creator
, &create_info
, ex_style
, GetWndClasss(), title
,
127 style
, rect
.left
, rect
.top
, rect
.right
-rect
.left
, rect
.bottom
-rect
.top
, hwndParent
);
129 // make sure the window is not off the screen
136 LRESULT
StartMenu::Init(LPCREATESTRUCT pcs
)
141 if (super::Init(pcs
))
144 // create buttons for registered entries in _entries
145 for(ShellEntryMap::const_iterator it
=_entries
.begin(); it
!=_entries
.end(); ++it
) {
146 const StartMenuEntry
& sme
= it
->second
;
147 bool hasSubmenu
= false;
149 for(ShellEntrySet::const_iterator it
=sme
._entries
.begin(); it
!=sme
._entries
.end(); ++it
)
150 if ((*it
)->_data
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
153 #ifdef _LIGHT_STARTMENU
154 _buttons
.push_back(SMBtnInfo(sme
, it
->first
, hasSubmenu
));
156 AddButton(sme
._title
, sme
._hIcon
, hasSubmenu
, it
->first
);
160 #ifdef _LIGHT_STARTMENU
161 if (_buttons
.empty())
163 if (!GetWindow(_hwnd
, GW_CHILD
))
165 AddButton(ResString(IDS_EMPTY
), ICID_NONE
, false, 0, false);
167 #ifdef _LIGHT_STARTMENU
171 #ifdef _LAZY_ICONEXTRACT
172 PostMessage(_hwnd
, PM_UPDATE_ICONS
, 0, 0);
174 } catch(COMException
& e
) {
175 HandleException(e
, pcs
->hwndParent
); // destroys the start menu window while switching focus
181 void StartMenu::AddEntries()
183 for(StartMenuShellDirs::iterator it
=_dirs
.begin(); it
!=_dirs
.end(); ++it
) {
184 StartMenuDirectory
& smd
= *it
;
185 ShellDirectory
& dir
= smd
._dir
;
190 #ifdef _LAZY_ICONEXTRACT
191 dir
.smart_scan(SCAN_FILESYSTEM
); // lazy icon extraction, try to read directly from filesystem
193 dir
.smart_scan(SCAN_EXTRACT_ICONS
|SCAN_FILESYSTEM
);
197 AddShellEntries(dir
, -1, smd
._subfolders
);
202 void StartMenu::AddShellEntries(const ShellDirectory
& dir
, int max
, bool subfolders
)
206 for(Entry
*entry
=dir
._down
; entry
; entry
=entry
->_next
) {
207 // hide files like "desktop.ini"
208 if (entry
->_shell_attribs
& SFGAO_HIDDEN
)
209 //not appropriate for drive roots: if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
212 // hide subfolders if requested
214 if (entry
->_data
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
217 // only 'max' entries shall be added.
221 if (entry
->_etype
== ET_SHELL
)
222 AddEntry(dir
._folder
, static_cast<ShellEntry
*>(entry
));
224 AddEntry(dir
._folder
, entry
);
229 LRESULT
StartMenu::WndProc(UINT nmsg
, WPARAM wparam
, LPARAM lparam
)
233 PaintCanvas
canvas(_hwnd
);
238 ResizeButtons(LOWORD(lparam
)-_border_left
);
242 POINTS
& pos
= MAKEPOINTS(lparam
);
244 // move open submenus of floating menus
246 int dx
= pos
.x
- _last_pos
.x
;
247 int dy
= pos
.y
- _last_pos
.y
;
250 WindowRect
rt(_submenu
);
251 SetWindowPos(_submenu
, 0, rt
.left
+dx
, rt
.top
+dy
, 0, 0, SWP_NOSIZE
|SWP_NOACTIVATE
);
252 //MoveVisible(_submenu);
261 LRESULT res
= super::WndProc(nmsg
, wparam
, lparam
);
263 if (res
>=HTSIZEFIRST
&& res
<=HTSIZELAST
)
264 return HTCLIENT
; // disable window resizing
268 case WM_LBUTTONDOWN
: {
271 // check mouse cursor for coordinates of floating button
272 GetFloatingButtonRect(&rect
);
274 if (PtInRect(&rect
, Point(lparam
))) {
275 // create a floating copy of the current start menu
276 WindowRect
pos(_hwnd
);
278 ///@todo do something similar to StartMenuRoot::TrackStartmenu() in order to automatically close submenus when clicking on the desktop background
279 StartMenu::Create(pos
.left
+3, pos
.bottom
-3, _create_info
._folders
, 0, _create_info
._title
, _create_info
._creator
);
283 #ifdef _LIGHT_STARTMENU
284 int id
= ButtonHitTest(Point(lparam
));
287 Command(id
, BN_CLICKED
);
292 if ((wparam
&0xFFF0) == SC_SIZE
)
293 return 0; // disable window resizing
297 // close start menu when activating another application
300 break; // don't call super::WndProc in case "this" has been deleted
306 #ifdef _LIGHT_STARTMENU
308 // automatically set the focus to startmenu entries when moving the mouse over them
309 int new_id
= ButtonHitTest(Point(lparam
));
311 if (new_id
!= _selected_id
)
312 SelectButton(new_id
);
316 if (wparam
==VK_RETURN
&& _selected_id
)
317 Command(_selected_id
, BN_CLICKED
);
320 case PM_STARTENTRY_FOCUSED
: { ///@todo use TrackMouseEvent() and WM_MOUSEHOVER to wait a bit before opening submenus
321 BOOL hasSubmenu
= wparam
;
322 HWND hctrl
= (HWND
)lparam
;
324 // automatically open submenus
326 UpdateWindow(_hwnd
); // draw focused button before waiting on submenu creation
327 //SendMessage(_hwnd, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hctrl),BN_CLICKED), (LPARAM)hctrl);
328 Command(GetDlgCtrlID(hctrl
), BN_CLICKED
);
330 // close any open submenu
331 CloseOtherSubmenus(0);
336 #ifdef _LAZY_ICONEXTRACT
337 case PM_UPDATE_ICONS
:
338 UpdateIcons(/*wparam*/);
342 case PM_STARTENTRY_LAUNCHED
:
343 if (GetWindowStyle(_hwnd
) & WS_CAPTION
) // don't automatically close floating menus
346 // route message to the parent menu and close menus after launching an entry
347 if (!SendParent(nmsg
, wparam
, lparam
))
349 return 1; // signal that we have received and processed the message
351 case PM_STARTMENU_CLOSED
:
356 return super::WndProc(nmsg
, wparam
, lparam
);
363 #ifdef _LIGHT_STARTMENU
365 int StartMenu::ButtonHitTest(POINT pt
)
367 ClientRect
clnt(_hwnd
);
368 RECT rect
= {_border_left
, _border_top
, clnt
.right
, STARTMENU_LINE_HEIGHT
};
370 if (pt
.x
<rect
.left
|| pt
.x
>rect
.right
)
373 for(SMBtnVector::const_iterator it
=_buttons
.begin(); it
!=_buttons
.end(); ++it
) {
374 const SMBtnInfo
& info
= *it
;
379 rect
.bottom
= rect
.top
+ (info
._id
==-1? STARTMENU_SEP_HEIGHT
: STARTMENU_LINE_HEIGHT
);
381 if (pt
.y
< rect
.bottom
) // PtInRect(&rect, pt)
384 rect
.top
= rect
.bottom
;
390 void StartMenu::InvalidateSelection()
395 ClientRect
clnt(_hwnd
);
396 RECT rect
= {_border_left
, _border_top
, clnt
.right
, STARTMENU_LINE_HEIGHT
};
398 for(SMBtnVector::const_iterator it
=_buttons
.begin(); it
!=_buttons
.end(); ++it
) {
399 const SMBtnInfo
& info
= *it
;
401 rect
.bottom
= rect
.top
+ (info
._id
==-1? STARTMENU_SEP_HEIGHT
: STARTMENU_LINE_HEIGHT
);
403 if (info
._id
== _selected_id
) {
404 InvalidateRect(_hwnd
, &rect
, TRUE
);
408 rect
.top
= rect
.bottom
;
412 const SMBtnInfo
* StartMenu::GetButtonInfo(int id
) const
414 for(SMBtnVector::const_iterator it
=_buttons
.begin(); it
!=_buttons
.end(); ++it
)
421 void StartMenu::SelectButton(int id
)
423 InvalidateSelection();
425 const SMBtnInfo
* btn
= GetButtonInfo(id
);
427 if (btn
&& btn
->_enabled
) {
430 InvalidateSelection();
432 // automatically open submenus
433 if (btn
->_hasSubmenu
) {
434 //@@ allows destroying of startmenu when processing PM_UPDATE_ICONS -> GPF
435 UpdateWindow(_hwnd
); // draw focused button before waiting on submenu creation
436 Command(_selected_id
, BN_CLICKED
);
438 CloseOtherSubmenus(0); // close any open submenu
446 bool StartMenu::GetButtonRect(int id
, PRECT prect
) const
448 #ifdef _LIGHT_STARTMENU
449 ClientRect
clnt(_hwnd
);
450 RECT rect
= {_border_left
, _border_top
, clnt
.right
, STARTMENU_LINE_HEIGHT
};
452 for(SMBtnVector::const_iterator it
=_buttons
.begin(); it
!=_buttons
.end(); ++it
) {
453 const SMBtnInfo
& info
= *it
;
455 rect
.bottom
= rect
.top
+ (info
._id
==-1? STARTMENU_SEP_HEIGHT
: STARTMENU_LINE_HEIGHT
);
457 if (info
._id
== id
) {
462 rect
.top
= rect
.bottom
;
467 HWND btn
= GetDlgItem(_hwnd
, id
);
470 GetWindowRect(btn
, prect
);
471 ScreenToClient(_hwnd
, prect
);
480 void StartMenu::DrawFloatingButton(HDC hdc
)
482 static ResIconEx
floatingIcon(IDI_FLOATING
, 8, 4);
484 ClientRect
clnt(_hwnd
);
486 DrawIconEx(hdc
, clnt
.right
-12, 0, floatingIcon
, 8, 4, 0, 0, DI_NORMAL
);
489 void StartMenu::GetFloatingButtonRect(LPRECT prect
)
491 GetClientRect(_hwnd
, prect
);
494 prect
->left
= prect
->right
- 8;
499 void StartMenu::Paint(PaintCanvas
& canvas
)
502 DrawFloatingButton(canvas
);
504 #ifdef _LIGHT_STARTMENU
505 ClientRect
clnt(_hwnd
);
506 RECT rect
= {_border_left
, _border_top
, clnt
.right
, STARTMENU_LINE_HEIGHT
};
508 int sep_width
= rect
.right
-rect
.left
- 4;
510 FontSelection
font(canvas
, GetStockFont(DEFAULT_GUI_FONT
));
511 BkMode
bk_mode(canvas
, TRANSPARENT
);
513 for(SMBtnVector::const_iterator it
=_buttons
.begin(); it
!=_buttons
.end(); ++it
) {
514 const SMBtnInfo
& btn
= *it
;
516 if (rect
.top
> canvas
.rcPaint
.bottom
)
519 if (btn
._id
== -1) { // a separator?
520 rect
.bottom
= rect
.top
+ STARTMENU_SEP_HEIGHT
;
522 BrushSelection
brush_sel(canvas
, GetSysColorBrush(COLOR_BTNSHADOW
));
523 PatBlt(canvas
, rect
.left
+2, rect
.top
+STARTMENU_SEP_HEIGHT
/2-1, sep_width
, 1, PATCOPY
);
525 SelectBrush(canvas
, GetSysColorBrush(COLOR_BTNHIGHLIGHT
));
526 PatBlt(canvas
, rect
.left
+2, rect
.top
+STARTMENU_SEP_HEIGHT
/2, sep_width
, 1, PATCOPY
);
528 rect
.bottom
= rect
.top
+ STARTMENU_LINE_HEIGHT
;
530 if (rect
.top
>= canvas
.rcPaint
.top
)
531 DrawStartMenuButton(canvas
, rect
, btn
._title
, btn
, btn
._id
==_selected_id
, false);
534 rect
.top
= rect
.bottom
;
539 #ifdef _LAZY_ICONEXTRACT
540 void StartMenu::UpdateIcons(/*int idx*/)
544 #ifdef _SINGLE_ICONEXTRACT
549 for(; idx
<(int)_buttons
.size(); ++idx
) {
550 SMBtnInfo
& btn
= _buttons
[idx
];
552 if (btn
._icon_id
==ICID_UNKNOWN
&& btn
._id
>0) {
553 StartMenuEntry
& sme
= _entries
[btn
._id
];
555 btn
._icon_id
= ICID_NONE
;
557 for(ShellEntrySet::iterator it
=sme
._entries
.begin(); it
!=sme
._entries
.end(); ++it
) {
560 if (entry
->_icon_id
== ICID_UNKNOWN
)
561 entry
->extract_icon();
563 if (entry
->_icon_id
> ICID_NONE
) {
564 btn
._icon_id
= (ICON_ID
)/*@@*/ entry
->_icon_id
;
568 GetButtonRect(btn
._id
, &rect
);
569 WindowCanvas
canvas(_hwnd
);
570 DrawStartMenuButton(canvas
, rect
, NULL
, btn
, btn
._id
==_selected_id
, false);
572 //InvalidateRect(_hwnd, &rect, FALSE);
573 //UpdateWindow(_hwnd);
582 // if (++idx < (int)_buttons.size())
583 // PostMessage(_hwnd, PM_UPDATE_ICONS, idx, 0);
587 int icons_extracted
= 0;
588 int icons_updated
= 0;
590 for(StartMenuShellDirs::iterator it
=_dirs
.begin(); it
!=_dirs
.end(); ++it
) {
591 ShellDirectory
& dir
= it
->_dir
;
593 icons_extracted
+= dir
.extract_icons();
596 if (icons_extracted
) {
597 for(ShellEntryMap::iterator it1
=_entries
.begin(); it1
!=_entries
.end(); ++it1
) {
598 StartMenuEntry
& sme
= it1
->second
;
601 sme
._hIcon
= (HICON
)-1;
603 for(ShellEntrySet::const_iterator it2
=sme
._entries
.begin(); it2
!=sme
._entries
.end(); ++it2
) {
604 const Entry
* sm_entry
= *it2
;
606 if (sm_entry
->_hIcon
) {
607 sme
._hIcon
= sm_entry
->_hIcon
;
614 for(SMBtnVector::iterator it
=_buttons
.begin(); it
!=_buttons
.end(); ++it
) {
615 SMBtnInfo
& info
= *it
;
617 if (info
._id
>0 && !info
._hIcon
) {
618 info
._hIcon
= _entries
[info
._id
]._hIcon
;
625 InvalidateRect(_hwnd
, NULL
, FALSE
);
633 // resize child button controls to accomodate for new window size
634 void StartMenu::ResizeButtons(int cx
)
636 HDWP hdwp
= BeginDeferWindowPos(10);
638 for(HWND ctrl
=GetWindow(_hwnd
,GW_CHILD
); ctrl
; ctrl
=GetNextWindow(ctrl
,GW_HWNDNEXT
)) {
641 if (rt
.right
!= cx
) {
642 int height
= rt
.bottom
- rt
.top
;
644 // special handling for separator controls
645 if (!height
&& (GetWindowStyle(ctrl
)&SS_TYPEMASK
)==SS_ETCHEDHORZ
)
648 hdwp
= DeferWindowPos(hdwp
, ctrl
, 0, 0, 0, cx
, height
, SWP_NOMOVE
|SWP_NOZORDER
|SWP_NOACTIVATE
);
652 EndDeferWindowPos(hdwp
);
656 int StartMenu::Command(int id
, int code
)
664 ShellEntryMap::iterator found
= _entries
.find(id
);
666 if (found
!= _entries
.end()) {
667 ActivateEntry(id
, found
->second
._entries
);
671 return super::Command(id
, code
);}
678 StartMenuEntry
& StartMenu::AddEntry(const String
& title
, ICON_ID icon_id
, Entry
* entry
)
680 // search for an already existing subdirectory entry with the same name
681 if (entry
->_data
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
682 for(ShellEntryMap::iterator it
=_entries
.begin(); it
!=_entries
.end(); ++it
) {
683 StartMenuEntry
& sme
= it
->second
;
685 if (sme
._title
== title
) ///@todo speed up by using a map indexed by name
686 for(ShellEntrySet::iterator it2
=sme
._entries
.begin(); it2
!=sme
._entries
.end(); ++it2
) {
687 if ((*it2
)->_data
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
688 // merge the new shell entry with the existing of the same name
689 sme
._entries
.insert(entry
);
695 StartMenuEntry
& sme
= AddEntry(title
, icon_id
);
697 sme
._entries
.insert(entry
);
702 StartMenuEntry
& StartMenu::AddEntry(const String
& title
, ICON_ID icon_id
, int id
)
707 StartMenuEntry
& sme
= _entries
[id
];
710 sme
._icon_id
= icon_id
;
715 StartMenuEntry
& StartMenu::AddEntry(const ShellFolder folder
, ShellEntry
* entry
)
719 if (entry
->_data
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
720 icon_id
= ICID_FOLDER
;
722 icon_id
= (ICON_ID
)/*@@*/ entry
->_icon_id
;
724 return AddEntry(folder
.get_name(entry
->_pidl
), icon_id
, entry
);
727 StartMenuEntry
& StartMenu::AddEntry(const ShellFolder folder
, Entry
* entry
)
731 if (entry
->_data
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
732 icon_id
= ICID_FOLDER
;
734 icon_id
= (ICON_ID
)/*@@*/ entry
->_icon_id
;
736 return AddEntry(entry
->_display_name
, icon_id
, entry
);
740 void StartMenu::AddButton(LPCTSTR title
, ICON_ID icon_id
, bool hasSubmenu
, int id
, bool enabled
)
742 #ifdef _LIGHT_STARTMENU
743 _buttons
.push_back(SMBtnInfo(title
, icon_id
, id
, hasSubmenu
, enabled
));
745 DWORD style
= enabled
? WS_VISIBLE
|WS_CHILD
|BS_OWNERDRAW
: WS_VISIBLE
|WS_CHILD
|BS_OWNERDRAW
|WS_DISABLED
;
747 WindowRect
rect(_hwnd
);
748 ClientRect
clnt(_hwnd
);
750 // increase window height to make room for the new button
751 rect
.top
-= STARTMENU_LINE_HEIGHT
;
753 // move down if we are too high now
755 rect
.top
+= STARTMENU_LINE_HEIGHT
;
756 rect
.bottom
+= STARTMENU_LINE_HEIGHT
;
759 WindowCanvas
canvas(_hwnd
);
760 FontSelection
font(canvas
, GetStockFont(DEFAULT_GUI_FONT
));
762 // widen window, if it is too small
763 int text_width
= GetStartMenuBtnTextWidth(canvas
, title
, _hwnd
) + 16/*icon*/ + 10/*placeholder*/ + 16/*arrow*/;
765 int cx
= clnt
.right
- _border_left
;
767 rect
.right
+= text_width
-cx
;
769 MoveWindow(_hwnd
, rect
.left
, rect
.top
, rect
.right
-rect
.left
, rect
.bottom
-rect
.top
, TRUE
);
771 StartMenuCtrl(_hwnd
, _border_left
, clnt
.bottom
, rect
.right
-rect
.left
-_border_left
,
772 title
, id
, g_Globals
._icon_cache
.get_icon(icon_id
)._hIcon
, hasSubmenu
, style
);
776 void StartMenu::AddSeparator()
778 #ifdef _LIGHT_STARTMENU
779 _buttons
.push_back(SMBtnInfo(NULL
, ICID_NONE
, -1, false));
781 WindowRect
rect(_hwnd
);
782 ClientRect
clnt(_hwnd
);
784 // increase window height to make room for the new separator
785 rect
.top
-= STARTMENU_SEP_HEIGHT
;
787 // move down if we are too high now
789 rect
.top
+= STARTMENU_LINE_HEIGHT
;
790 rect
.bottom
+= STARTMENU_LINE_HEIGHT
;
793 MoveWindow(_hwnd
, rect
.left
, rect
.top
, rect
.right
-rect
.left
, rect
.bottom
-rect
.top
, TRUE
);
795 StartMenuSeparator(_hwnd
, _border_left
, clnt
.bottom
, rect
.right
-rect
.left
-_border_left
);
800 bool StartMenu::CloseOtherSubmenus(int id
)
803 if (IsWindow(_submenu
)) {
804 if (_submenu_id
== id
)
808 DestroyWindow(_submenu
);
809 // _submenu should be reset automatically by PM_STARTMENU_CLOSED, but safety first...
820 void StartMenu::CreateSubmenu(int id
, LPCTSTR title
, CREATORFUNC creator
)
822 CreateSubmenu(id
, StartMenuFolders(), title
, creator
);
825 void StartMenu::CreateSubmenu(int id
, int folder_id
, LPCTSTR title
, CREATORFUNC creator
)
828 SpecialFolderPath
folder(folder_id
, _hwnd
);
830 StartMenuFolders new_folders
;
831 new_folders
.push_back(folder
);
833 CreateSubmenu(id
, new_folders
, title
, creator
);
834 } catch(COMException
&) {
835 // ignore Exception and don't display anything
839 void StartMenu::CreateSubmenu(int id
, int folder_id1
, int folder_id2
, LPCTSTR title
, CREATORFUNC creator
)
841 StartMenuFolders new_folders
;
844 new_folders
.push_back(SpecialFolderPath(folder_id1
, _hwnd
));
845 } catch(COMException
&) {
849 new_folders
.push_back(SpecialFolderPath(folder_id2
, _hwnd
));
850 } catch(COMException
&) {
853 if (!new_folders
.empty())
854 CreateSubmenu(id
, new_folders
, title
, creator
);
857 void StartMenu::CreateSubmenu(int id
, const StartMenuFolders
& new_folders
, LPCTSTR title
, CREATORFUNC creator
)
859 // Only open one submenu at a time.
860 if (!CloseOtherSubmenus(id
))
866 if (GetButtonRect(id
, &rect
)) {
867 ClientToScreen(_hwnd
, &rect
);
869 x
= rect
.right
; // Submenus should overlap their parent a bit.
870 y
= rect
.top
+STARTMENU_LINE_HEIGHT
-_border_top
;
872 WindowRect
pos(_hwnd
);
879 _submenu
= StartMenu::Create(x
, y
, new_folders
, _hwnd
, title
, creator
);
883 void StartMenu::ActivateEntry(int id
, const ShellEntrySet
& entries
)
885 StartMenuFolders new_folders
;
888 for(ShellEntrySet::const_iterator it
=entries
.begin(); it
!=entries
.end(); ++it
) {
889 Entry
* entry
= const_cast<Entry
*>(*it
);
891 if (entry
->_data
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
893 ///@todo If the user explicitely clicked on a submenu, display this folder as floating start menu.
895 if (entry
->_etype
== ET_SHELL
)
896 new_folders
.push_back(entry
->create_absolute_pidl());
898 TCHAR path
[MAX_PATH
];
900 if (entry
->get_path(path
))
901 new_folders
.push_back(path
);
905 title
= entry
->_display_name
;
907 // If the entry is no subdirectory, there can only be one shell entry.
908 assert(entries
.size()==1);
910 HWND hparent
= GetParent(_hwnd
);
911 ShellPath shell_path
= entry
->create_absolute_pidl();
913 // close start menus after launching the selected entry
916 ///@todo launch in the background; specify correct HWND for error message box titles
917 SHELLEXECUTEINFO shexinfo
;
919 shexinfo
.cbSize
= sizeof(SHELLEXECUTEINFO
);
920 shexinfo
.fMask
= SEE_MASK_INVOKEIDLIST
; // SEE_MASK_IDLIST is also possible.
921 shexinfo
.hwnd
= hparent
;
922 shexinfo
.lpVerb
= NULL
;
923 shexinfo
.lpFile
= NULL
;
924 shexinfo
.lpParameters
= NULL
;
925 shexinfo
.lpDirectory
= NULL
;
926 shexinfo
.nShow
= SW_SHOWNORMAL
;
928 shexinfo
.lpIDList
= &*shell_path
;
930 if (!ShellExecuteEx(&shexinfo
))
931 display_error(hparent
, GetLastError());
933 // we may have deleted 'this' - ensure we leave the loop and function
938 if (!new_folders
.empty()) {
939 // Only open one submenu at a time.
940 if (!CloseOtherSubmenus(id
))
943 CreateSubmenu(id
, new_folders
, title
);
948 /// close all windows of the start menu popup
949 void StartMenu::CloseStartMenu(int id
)
951 if (!(GetWindowStyle(_hwnd
) & WS_CAPTION
)) { // don't automatically close floating menus
952 if (!SendParent(PM_STARTENTRY_LAUNCHED
, id
, (LPARAM
)_hwnd
))
953 DestroyWindow(_hwnd
);
954 } else if (_submenu
) // instead close submenus of floating parent menus
959 int GetStartMenuBtnTextWidth(HDC hdc
, LPCTSTR title
, HWND hwnd
)
961 RECT rect
= {0, 0, 0, 0};
962 DrawText(hdc
, title
, -1, &rect
, DT_SINGLELINE
|DT_NOPREFIX
|DT_CALCRECT
);
964 return rect
.right
-rect
.left
;
967 #ifdef _LIGHT_STARTMENU
968 void DrawStartMenuButton(HDC hdc
, const RECT
& rect
, LPCTSTR title
, const SMBtnInfo
& btn
, bool has_focus
, bool pushed
)
970 void DrawStartMenuButton(HDC hdc
, const RECT
& rect
, LPCTSTR title
, HICON hIcon
,
971 bool hasSubmenu
, bool enabled
, bool has_focus
, bool pushed
);
974 UINT style
= DFCS_BUTTONPUSH
;
977 style
|= DFCS_INACTIVE
;
979 POINT iconPos
= {rect
.left
+2, (rect
.top
+rect
.bottom
-16)/2};
980 RECT textRect
= {rect
.left
+16+4, rect
.top
+2, rect
.right
-4, rect
.bottom
-4};
983 style
|= DFCS_PUSHED
;
984 ++iconPos
.x
; ++iconPos
.y
;
985 ++textRect
.left
; ++textRect
.top
;
986 ++textRect
.right
; ++textRect
.bottom
;
989 int bk_color
= COLOR_BTNFACE
;
990 int text_color
= COLOR_BTNTEXT
;
993 bk_color
= COLOR_HIGHLIGHT
;
994 text_color
= COLOR_HIGHLIGHTTEXT
;
997 HBRUSH bk_brush
= GetSysColorBrush(bk_color
);
1000 FillRect(hdc
, &rect
, bk_brush
);
1002 if (btn
._icon_id
> ICID_NONE
)
1003 DrawIconEx(hdc
, iconPos
.x
, iconPos
.y
, g_Globals
._icon_cache
.get_icon(btn
._icon_id
)._hIcon
, 16, 16, 0, bk_brush
, DI_NORMAL
);
1005 // draw submenu arrow at the right
1006 if (btn
._hasSubmenu
) {
1007 static SmallIcon
arrowIcon(IDI_ARROW
);
1008 static SmallIcon
selArrowIcon(IDI_ARROW_SELECTED
);
1010 DrawIconEx(hdc
, rect
.right
-16, iconPos
.y
,
1011 has_focus
? selArrowIcon
: arrowIcon
,
1012 16, 16, 0, bk_brush
, DI_NORMAL
);
1016 BkMode
bk_mode(hdc
, TRANSPARENT
);
1018 if (!btn
._enabled
) // dis->itemState & (ODS_DISABLED|ODS_GRAYED)
1019 DrawGrayText(hdc
, &textRect
, title
, DT_SINGLELINE
|DT_NOPREFIX
|DT_VCENTER
);
1021 TextColor
lcColor(hdc
, GetSysColor(text_color
));
1022 DrawText(hdc
, title
, -1, &textRect
, DT_SINGLELINE
|DT_NOPREFIX
|DT_VCENTER
);
1028 #ifdef _LIGHT_STARTMENU
1030 void StartMenu::ResizeToButtons()
1032 WindowRect
rect(_hwnd
);
1034 WindowCanvas
canvas(_hwnd
);
1035 FontSelection
font(canvas
, GetStockFont(DEFAULT_GUI_FONT
));
1037 int max_width
= STARTMENU_WIDTH_MIN
;
1040 for(SMBtnVector::const_iterator it
=_buttons
.begin(); it
!=_buttons
.end(); ++it
) {
1041 int w
= GetStartMenuBtnTextWidth(canvas
, it
->_title
, _hwnd
);
1047 height
+= STARTMENU_SEP_HEIGHT
;
1049 height
+= STARTMENU_LINE_HEIGHT
;
1052 // calculate new window size
1053 int text_width
= max_width
+ 16/*icon*/ + 10/*placeholder*/ + 16/*arrow*/;
1055 RECT rt_hgt
= {rect
.left
, rect
.bottom
-_border_top
-height
, rect
.left
+_border_left
+text_width
, rect
.bottom
};
1056 AdjustWindowRectEx(&rt_hgt
, GetWindowStyle(_hwnd
), FALSE
, GetWindowExStyle(_hwnd
));
1058 // ignore movement, only look at the size change
1059 rect
.right
= rect
.left
+ (rt_hgt
.right
-rt_hgt
.left
);
1060 rect
.top
= rect
.bottom
- (rt_hgt
.bottom
-rt_hgt
.top
);
1062 // move down if we are too high
1064 rect
.top
+= STARTMENU_LINE_HEIGHT
;
1065 rect
.bottom
+= STARTMENU_LINE_HEIGHT
;
1068 MoveWindow(_hwnd
, rect
.left
, rect
.top
, rect
.right
-rect
.left
, rect
.bottom
-rect
.top
, TRUE
);
1071 #else // _LIGHT_STARTMENU
1073 LRESULT
StartMenuButton::WndProc(UINT nmsg
, WPARAM wparam
, LPARAM lparam
)
1077 // automatically set the focus to startmenu entries when moving the mouse over them
1078 if (GetFocus()!=_hwnd
&& !(GetWindowStyle(_hwnd
)&WS_DISABLED
))
1083 PostParent(PM_STARTENTRY_FOCUSED
, _hasSubmenu
, (LPARAM
)_hwnd
);
1087 // route WM_CANCELMODE to the startmenu window
1088 return SendParent(nmsg
, wparam
, lparam
);
1091 return super::WndProc(nmsg
, wparam
, lparam
);
1097 void StartMenuButton::DrawItem(LPDRAWITEMSTRUCT dis
)
1099 TCHAR title
[BUFFER_LEN
];
1101 GetWindowText(_hwnd
, title
, BUFFER_LEN
);
1103 DrawStartMenuButton(dis
->hDC
, dis
->rcItem
, title
, _hIcon
,
1105 !(dis
->itemState
& ODS_DISABLED
),
1106 dis
->itemState
&ODS_FOCUS
? true: false,
1107 dis
->itemState
&ODS_SELECTED
? true: false);
1113 StartMenuRoot::StartMenuRoot(HWND hwnd
)
1116 #ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
1117 if (!g_Globals
._SHRestricted
|| !SHRestricted(REST_NOCOMMONGROUPS
))
1120 // insert directory "All Users\Start Menu"
1121 ShellDirectory
cmn_startmenu(Desktop(), SpecialFolderPath(CSIDL_COMMON_STARTMENU
, _hwnd
), _hwnd
);
1122 _dirs
.push_back(StartMenuDirectory(cmn_startmenu
, false)); // don't add subfolders
1123 } catch(COMException
&) {
1124 // ignore exception and don't show additional shortcuts
1128 // insert directory "<user name>\Start Menu"
1129 ShellDirectory
usr_startmenu(Desktop(), SpecialFolderPath(CSIDL_STARTMENU
, _hwnd
), _hwnd
);
1130 _dirs
.push_back(StartMenuDirectory(usr_startmenu
, false)); // don't add subfolders
1131 } catch(COMException
&) {
1132 // ignore exception and don't show additional shortcuts
1135 // read size of logo bitmap
1137 GetObject(ResBitmap(IDB_LOGOV
), sizeof(BITMAP
), &bmp_hdr
);
1138 _logo_size
.cx
= bmp_hdr
.bmWidth
;
1139 _logo_size
.cy
= bmp_hdr
.bmHeight
;
1141 _border_left
= _logo_size
.cx
;
1145 HWND
StartMenuRoot::Create(HWND hwndDesktopBar
)
1147 WindowRect
pos(hwndDesktopBar
);
1149 RECT rect
= {pos
.left
, pos
.top
-STARTMENU_LINE_HEIGHT
-4, pos
.left
+STARTMENU_WIDTH_MIN
, pos
.top
};
1151 #ifndef _LIGHT_STARTMENU
1152 rect
.top
+= STARTMENU_LINE_HEIGHT
;
1155 AdjustWindowRectEx(&rect
, WS_POPUP
|WS_THICKFRAME
|WS_CLIPCHILDREN
|WS_VISIBLE
, FALSE
, 0);
1157 return Window::Create(WINDOW_CREATOR(StartMenuRoot
), 0, GetWndClasss(), TITLE_STARTMENU
,
1158 WS_POPUP
|WS_THICKFRAME
|WS_CLIPCHILDREN
,
1159 rect
.left
, rect
.top
, rect
.right
-rect
.left
, rect
.bottom
-rect
.top
, hwndDesktopBar
);
1163 void StartMenuRoot::TrackStartmenu()
1168 #ifdef _LIGHT_STARTMENU
1172 // show previously hidden start menu
1173 ShowWindow(hwnd
, SW_SHOW
);
1175 while(IsWindow(hwnd
)) {
1176 if (!GetMessage(&msg
, 0, 0, 0)) {
1177 PostQuitMessage(msg
.wParam
);
1181 // Check for a mouse click on any window, which is not part of the start menu
1182 if (msg
.message
==WM_LBUTTONDOWN
|| msg
.message
==WM_MBUTTONDOWN
|| msg
.message
==WM_RBUTTONDOWN
) {
1183 StartMenu
* menu_wnd
= NULL
;
1185 for(HWND hwnd
=msg
.hwnd
; hwnd
; hwnd
=GetParent(hwnd
)) {
1186 menu_wnd
= WINDOW_DYNAMIC_CAST(StartMenu
, hwnd
);
1199 if (pretranslate_msg(&msg
))
1202 if (dispatch_dialog_msg(&msg
))
1205 TranslateMessage(&msg
);
1208 DispatchMessage(&msg
);
1209 } catch(COMException
& e
) {
1210 HandleException(e
, _hwnd
);
1212 } catch(COMException
& e
) {
1213 HandleException(e
, _hwnd
);
1219 LRESULT
StartMenuRoot::Init(LPCREATESTRUCT pcs
)
1221 // add buttons for entries in _entries
1222 if (super::Init(pcs
))
1232 if (RegOpenKey(HKEY_CURRENT_USER
, _T("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer"), &hkey
))
1235 if (RegOpenKey(HKEY_CURRENT_USER
, _T("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced"), &hkeyAdv
))
1238 #define IS_VALUE_ZERO(hk, name) \
1239 (!hk || (len=sizeof(value),RegQueryValueEx(hk, name, NULL, NULL, (LPBYTE)&value, &len) || !value))
1241 #define IS_VALUE_NOT_ZERO(hk, name) \
1242 (!hk || (len=sizeof(value),RegQueryValueEx(hk, name, NULL, NULL, (LPBYTE)&value, &len) || value>0))
1246 // insert hard coded start entries
1247 AddButton(ResString(IDS_PROGRAMS
), ICID_APPS
, true, IDC_PROGRAMS
);
1249 AddButton(ResString(IDS_DOCUMENTS
), ICID_DOCUMENTS
, true, IDC_DOCUMENTS
);
1251 #ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
1252 if (!g_Globals
._SHRestricted
|| !SHRestricted(REST_NORECENTDOCSMENU
))
1254 if (IS_VALUE_ZERO(hkey
, _T("NoRecentDocsMenu")))
1256 AddButton(ResString(IDS_RECENT
), ICID_DOCUMENTS
, true, IDC_RECENT
);
1258 AddButton(ResString(IDS_FAVORITES
), ICID_FAVORITES
, true, IDC_FAVORITES
);
1260 AddButton(ResString(IDS_SETTINGS
), ICID_CONFIG
, true, IDC_SETTINGS
);
1262 AddButton(ResString(IDS_BROWSE
), ICID_FOLDER
, true, IDC_BROWSE
);
1264 #ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
1265 if (!g_Globals
._SHRestricted
|| !SHRestricted(REST_NOFIND
))
1267 if (IS_VALUE_ZERO(hkey
, _T("NoFind")))
1269 AddButton(ResString(IDS_SEARCH
), ICID_SEARCH
, true, IDC_SEARCH
);
1271 AddButton(ResString(IDS_START_HELP
), ICID_INFO
, false, IDC_START_HELP
);
1273 #ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
1274 if (!g_Globals
._SHRestricted
|| !SHRestricted(REST_NORUN
))
1276 if (IS_VALUE_ZERO(hkey
, _T("NoRun")))
1278 AddButton(ResString(IDS_LAUNCH
), ICID_ACTION
, false, IDC_LAUNCH
);
1284 #ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
1285 if (!g_Globals
._SHRestricted
|| !SHRestricted(REST_NOCLOSE
))
1287 if (IS_VALUE_NOT_ZERO(hkeyAdv
, _T("StartMenuLogoff")))
1289 AddButton(ResString(IDS_LOGOFF
), ICID_LOGOFF
, false, IDC_LOGOFF
);
1292 #ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
1293 if (!g_Globals
._SHRestricted
|| SHRestricted(REST_STARTMENULOGOFF
) != 1)
1295 if (IS_VALUE_ZERO(hkey
, _T("NoClose")))
1297 AddButton(ResString(IDS_SHUTDOWN
), ICID_LOGOFF
, false, IDC_SHUTDOWN
);
1301 RegCloseKey(hkeyAdv
);
1306 #ifdef _LIGHT_STARTMENU
1307 // set the window size to fit all buttons
1315 void StartMenuRoot::AddEntries()
1317 super::AddEntries();
1319 AddButton(ResString(IDS_EXPLORE
), ICID_EXPLORER
, false, IDC_EXPLORE
);
1323 LRESULT
StartMenuRoot::WndProc(UINT nmsg
, WPARAM wparam
, LPARAM lparam
)
1327 PaintCanvas
canvas(_hwnd
);
1332 return super::WndProc(nmsg
, wparam
, lparam
);
1338 void StartMenuRoot::Paint(PaintCanvas
& canvas
)
1341 {WindowCanvas
dc(_hwnd
); clr_bits
=GetDeviceCaps(dc
, BITSPIXEL
);}
1342 bool logo256
= clr_bits
<=8;
1345 ResBitmap
bmp(logo256
? IDB_LOGOV256
: IDB_LOGOV
);
1346 BitmapSelection
sel(mem_dc
, bmp
);
1348 ClientRect
clnt(_hwnd
);
1349 int h
= min(_logo_size
.cy
, clnt
.bottom
);
1351 RECT rect
= {0, 0, _logo_size
.cx
-1, clnt
.bottom
-h
};
1352 HBRUSH hbr
= CreateSolidBrush(logo256
? RGB(166,202,240): RGB(255,255,255)); // same color as the background color in the logo bitmap
1353 FillRect(canvas
, &rect
, hbr
);
1355 //PatBlt(canvas, _logo_size.cx-1, 0, 1, clnt.bottom-h, WHITENESS);
1356 PatBlt(canvas
, _logo_size
.cx
-1, 0, 1, clnt
.bottom
-h
, WHITENESS
);
1358 BitBlt(canvas
, 0, clnt
.bottom
-h
, _logo_size
.cx
, h
, mem_dc
, 0, 0, SRCCOPY
);
1361 rect
.left
= rect
.right
++;
1362 rect
.bottom
= clnt
.bottom
;
1363 HBRUSH hbr_border
= GetStockBrush(GRAY_BRUSH
); //CreateSolidBrush(RGB(71,88,85));
1364 FillRect(canvas
, &rect
, hbr_border
);
1365 //DeleteObject(hbr_border);
1368 super::Paint(canvas
);
1372 void StartMenuRoot::CloseStartMenu(int id
)
1377 ShowWindow(_hwnd
, SW_HIDE
);
1381 int StartMenuHandler::Command(int id
, int code
)
1388 CreateSubmenu(id
, CSIDL_COMMON_PROGRAMS
, CSIDL_PROGRAMS
, ResString(IDS_PROGRAMS
));
1393 explorer_show_frame(_hwnd
, SW_SHOWNORMAL
);
1397 HWND hwndDesktopBar
= GetWindow(_hwnd
, GW_OWNER
);
1399 ShowLaunchDialog(hwndDesktopBar
);
1403 CreateSubmenu(id
, CSIDL_PERSONAL
, ResString(IDS_DOCUMENTS
));
1407 CreateSubmenu(id
, CSIDL_RECENT
, ResString(IDS_RECENT
), STARTMENU_CREATOR(RecentStartMenu
));
1411 CreateSubmenu(id
, CSIDL_FAVORITES
, ResString(IDS_FAVORITES
));
1415 CreateSubmenu(id
, ResString(IDS_BROWSE
), STARTMENU_CREATOR(BrowseMenu
));
1419 CreateSubmenu(id
, ResString(IDS_SETTINGS
), STARTMENU_CREATOR(SettingsMenu
));
1423 CreateSubmenu(id
, ResString(IDS_SEARCH
), STARTMENU_CREATOR(SearchMenu
));
1426 case IDC_START_HELP
: {
1427 HWND hwndDesktopBar
= GetWindow(_hwnd
, GW_OWNER
);
1429 MessageBox(hwndDesktopBar
, TEXT("Help not yet implemented"), ResString(IDS_TITLE
), MB_OK
);
1433 /* The shell32 Dialog prompts about some system setting change. This is not what we want to display here.
1434 HWND hwndDesktopBar = GetWindow(_hwnd, GW_OWNER);
1436 ShowRestartDialog(hwndDesktopBar, EWX_LOGOFF);*/
1437 DestroyWindow(GetParent(_hwnd
));
1440 case IDC_SHUTDOWN
: {
1441 HWND hwndDesktopBar
= GetWindow(_hwnd
, GW_OWNER
);
1443 ShowExitWindowsDialog(hwndDesktopBar
);
1449 case IDC_SETTINGS_MENU
:
1450 CreateSubmenu(id
, CSIDL_CONTROLS
, ResString(IDS_SETTINGS_MENU
));
1454 CreateSubmenu(id
, CSIDL_PRINTERS
, CSIDL_PRINTHOOD
, ResString(IDS_PRINTERS
));
1457 case IDC_CONTROL_PANEL
:
1459 MainFrame::Create(TEXT("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}"), FALSE
);
1463 CreateSubmenu(id
, CSIDL_COMMON_ADMINTOOLS
, CSIDL_ADMINTOOLS
, ResString(IDS_ADMIN
));
1466 case IDC_CONNECTIONS
:
1467 CreateSubmenu(id
, CSIDL_CONNECTIONS
, ResString(IDS_CONNECTIONS
));
1474 CreateSubmenu(id
, CSIDL_NETWORK
, ResString(IDS_NETWORK
));
1478 ///@todo exclude removeable drives
1479 CreateSubmenu(id
, CSIDL_DRIVES
, ResString(IDS_DRIVES
));
1485 case IDC_SEARCH_PROGRAM
:
1487 Dialog::DoModal(IDD_SEARCH_PROGRAM
, WINDOW_CREATOR(FindProgramDlg
));
1490 case IDC_SEARCH_FILES
:
1495 case IDC_SEARCH_COMPUTER
:
1497 ShowSearchComputer();
1502 return super::Command(id
, code
);
1509 void StartMenuHandler::ShowSearchDialog()
1511 static DynamicFct
<SHFINDFILES
> SHFindFiles(TEXT("SHELL32"), 90);
1514 (*SHFindFiles
)(NULL
, NULL
);
1516 MessageBox(0, TEXT("SHFindFiles() not yet implemented in SHELL32"), ResString(IDS_TITLE
), MB_OK
);
1519 void StartMenuHandler::ShowSearchComputer()
1521 static DynamicFct
<SHFINDCOMPUTER
> SHFindComputer(TEXT("SHELL32"), 91);
1524 (*SHFindComputer
)(NULL
, NULL
);
1526 MessageBox(0, TEXT("SHFindComputer() not yet implemented in SHELL32"), ResString(IDS_TITLE
), MB_OK
);
1529 void StartMenuHandler::ShowLaunchDialog(HWND hwndDesktopBar
)
1531 ///@todo All text phrases should be put into the resources.
1532 static LPCSTR szTitle
= "Create New Task";
1533 static LPCSTR szText
= "Type the name of a program, folder, document, or Internet resource, and Task Manager will open it for you.";
1535 static DynamicFct
<RUNFILEDLG
> RunFileDlg(TEXT("SHELL32"), 61);
1537 // Show "Run..." dialog
1540 if ((HIWORD(GetVersion())>>14) == W_VER_NT
) {
1541 WCHAR wTitle
[40], wText
[256];
1543 MultiByteToWideChar(CP_ACP
, 0, szTitle
, -1, wTitle
, 40);
1544 MultiByteToWideChar(CP_ACP
, 0, szText
, -1, wText
, 256);
1546 (*RunFileDlg
)(hwndDesktopBar
, 0, NULL
, (LPCSTR
)wTitle
, (LPCSTR
)wText
, RFF_CALCDIRECTORY
);
1549 (*RunFileDlg
)(hwndDesktopBar
, 0, NULL
, szTitle
, szText
, RFF_CALCDIRECTORY
);
1553 void StartMenuHandler::ShowRestartDialog(HWND hwndOwner
, UINT flags
)
1555 static DynamicFct
<RESTARTWINDOWSDLG
> RestartDlg(TEXT("SHELL32"), 59);
1558 (*RestartDlg
)(hwndOwner
, (LPWSTR
)L
"You selected <Log Off>.\n\n", flags
); ///@todo ANSI string conversion if needed
1560 MessageBox(hwndOwner
, TEXT("RestartDlg() not yet implemented in SHELL32"), ResString(IDS_TITLE
), MB_OK
);
1563 void ShowExitWindowsDialog(HWND hwndOwner
)
1565 static DynamicFct
<EXITWINDOWSDLG
> ExitWindowsDlg(TEXT("SHELL32"), 60);
1568 (*ExitWindowsDlg
)(hwndOwner
);
1570 MessageBox(hwndOwner
, TEXT("ExitWindowsDlg() not yet implemented in SHELL32"), ResString(IDS_TITLE
), MB_OK
);
1574 void SettingsMenu::AddEntries()
1576 super::AddEntries();
1578 #ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
1579 if (!g_Globals
._SHRestricted
|| !SHRestricted(REST_NOCONTROLPANEL
))
1581 AddButton(ResString(IDS_CONTROL_PANEL
), ICID_CONFIG
, false, IDC_CONTROL_PANEL
);
1583 AddButton(ResString(IDS_PRINTERS
), ICID_PRINTER
, true, IDC_PRINTERS
);
1584 AddButton(ResString(IDS_CONNECTIONS
), ICID_NETWORK
, true, IDC_CONNECTIONS
);
1585 AddButton(ResString(IDS_ADMIN
), ICID_CONFIG
, true, IDC_ADMIN
);
1587 #ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
1588 if (!g_Globals
._SHRestricted
|| !SHRestricted(REST_NOCONTROLPANEL
))
1590 AddButton(ResString(IDS_SETTINGS_MENU
), ICID_CONFIG
, true, IDC_SETTINGS_MENU
);
1593 void BrowseMenu::AddEntries()
1595 super::AddEntries();
1597 #ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
1598 if (!g_Globals
._SHRestricted
|| !SHRestricted(REST_NONETHOOD
)) // or REST_NOENTIRENETWORK ?
1600 AddButton(ResString(IDS_NETWORK
), ICID_NETWORK
, true, IDC_NETWORK
);
1602 AddButton(ResString(IDS_DRIVES
), ICID_FOLDER
, true, IDC_DRIVES
);
1605 void SearchMenu::AddEntries()
1607 super::AddEntries();
1609 AddButton(ResString(IDS_SEARCH_PRG
), ICID_APPS
, false, IDC_SEARCH_PROGRAM
);
1611 AddButton(ResString(IDS_SEARCH_FILES
), ICID_SEARCH_DOC
, false, IDC_SEARCH_FILES
);
1613 #ifndef __MINGW32__ // SHRestricted() missing in MinGW (as of 29.10.2003)
1614 if (!g_Globals
._SHRestricted
|| !SHRestricted(REST_HASFINDCOMPUTERS
))
1616 AddButton(ResString(IDS_SEARCH_COMPUTER
), ICID_COMPUTER
, false, IDC_SEARCH_COMPUTER
);
1620 void RecentStartMenu::AddEntries()
1622 for(StartMenuShellDirs::iterator it
=_dirs
.begin(); it
!=_dirs
.end(); ++it
) {
1623 StartMenuDirectory
& smd
= *it
;
1624 ShellDirectory
& dir
= smd
._dir
;
1626 if (!dir
._scanned
) {
1629 #ifdef _LAZY_ICONEXTRACT
1630 dir
.smart_scan(SCAN_FILESYSTEM
);
1632 dir
.smart_scan(SCAN_EXTRACT_ICONS
|SCAN_FILESYSTEM
);
1636 dir
.sort_directory(SORT_DATE
);
1637 AddShellEntries(dir
, 16, smd
._subfolders
); ///@todo read max. count of entries from registry