From ecc0688f2f28cb263f056e177a08a498d1c35e33 Mon Sep 17 00:00:00 2001 From: Martin Fuchs Date: Wed, 31 Dec 2003 00:41:01 +0000 Subject: [PATCH] implemented Explorer About Dialog svn path=/trunk/; revision=7357 --- .../system/explorer/desktop/desktop.cpp | 49 +++- .../subsys/system/explorer/desktop/desktop.h | 1 + reactos/subsys/system/explorer/explorer.cpp | 76 ++++++- reactos/subsys/system/explorer/explorer.dsp | 4 + .../subsys/system/explorer/explorer_intres.h | 15 +- .../subsys/system/explorer/explorer_intres.rc | 72 ++++-- reactos/subsys/system/explorer/externals.h | 3 + .../subsys/system/explorer/res/ros-big.ico | Bin 0 -> 138414 bytes .../system/explorer/shell/mainframe.cpp | 7 +- .../system/explorer/taskbar/startmenu.cpp | 4 +- .../system/explorer/utility/shellclasses.cpp | 21 +- .../system/explorer/utility/utility.cpp | 14 +- .../subsys/system/explorer/utility/utility.h | 2 + .../subsys/system/explorer/utility/window.cpp | 215 ++++++++++++++++++ .../subsys/system/explorer/utility/window.h | 104 ++++++++- 15 files changed, 544 insertions(+), 43 deletions(-) create mode 100644 reactos/subsys/system/explorer/res/ros-big.ico diff --git a/reactos/subsys/system/explorer/desktop/desktop.cpp b/reactos/subsys/system/explorer/desktop/desktop.cpp index 7f5d8b9ffc2..075cc460eaf 100644 --- a/reactos/subsys/system/explorer/desktop/desktop.cpp +++ b/reactos/subsys/system/explorer/desktop/desktop.cpp @@ -35,6 +35,7 @@ #include "../taskbar/desktopbar.h" #include "../shell/mainframe.h" // for MainFrame::Create() +#include "../globals.h" #include "../externals.h" #include "../explorer_intres.h" @@ -289,10 +290,10 @@ LRESULT DesktopShellView::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) switch(nmsg) { case WM_CONTEXTMENU: if (!DoContextMenu(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam))) - goto def; ///@todo desktop context menu + DoDesktopContextMenu(GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)); break; - default: def: + default: return super::WndProc(nmsg, wparam, lparam); } @@ -347,3 +348,47 @@ bool DesktopShellView::DoContextMenu(int x, int y) return true; } + +HRESULT DesktopShellView::DoDesktopContextMenu(int x, int y) +{ + IContextMenu* pcm; + + HRESULT hr = DesktopFolder()->GetUIObjectOf(_hwnd, 0, NULL, IID_IContextMenu, NULL, (LPVOID*)&pcm); + + if (SUCCEEDED(hr)) { + HMENU hmenu = CreatePopupMenu(); + + if (hmenu) { + hr = pcm->QueryContextMenu(hmenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST-1, CMF_NORMAL|CMF_EXPLORE); + + if (SUCCEEDED(hr)) { + AppendMenu(hmenu, MF_SEPARATOR, 0, NULL); + AppendMenu(hmenu, 0, FCIDM_SHVIEWLAST-1, ResString(IDS_ABOUT_EXPLORER)); + + UINT idCmd = TrackPopupMenu(hmenu, TPM_LEFTALIGN|TPM_RETURNCMD|TPM_RIGHTBUTTON, x, y, 0, _hwnd, NULL); + + if (idCmd == FCIDM_SHVIEWLAST-1) { + explorer_about(_hwnd); + } else if (idCmd) { + CMINVOKECOMMANDINFO cmi; + + cmi.cbSize = sizeof(CMINVOKECOMMANDINFO); + cmi.fMask = 0; + cmi.hwnd = _hwnd; + cmi.lpVerb = (LPCSTR)(INT_PTR)(idCmd - FCIDM_SHVIEWFIRST); + cmi.lpParameters = NULL; + cmi.lpDirectory = NULL; + cmi.nShow = SW_SHOWNORMAL; + cmi.dwHotKey = 0; + cmi.hIcon = 0; + + hr = pcm->InvokeCommand(&cmi); + } + } + } + + pcm->Release(); + } + + return hr; +} diff --git a/reactos/subsys/system/explorer/desktop/desktop.h b/reactos/subsys/system/explorer/desktop/desktop.h index 26d02b65377..e4fe235a2de 100644 --- a/reactos/subsys/system/explorer/desktop/desktop.h +++ b/reactos/subsys/system/explorer/desktop/desktop.h @@ -97,4 +97,5 @@ protected: int Notify(int id, NMHDR* pnmh); bool DoContextMenu(int x, int y); + HRESULT DoDesktopContextMenu(int x, int y); }; diff --git a/reactos/subsys/system/explorer/explorer.cpp b/reactos/subsys/system/explorer/explorer.cpp index 7589f4cd0b2..3c818c46435 100644 --- a/reactos/subsys/system/explorer/explorer.cpp +++ b/reactos/subsys/system/explorer/explorer.cpp @@ -136,8 +136,19 @@ void explorer_show_frame(HWND hwndDesktop, int cmdshow, LPTSTR lpCmdLine) ShowWindow(hMainFrame, cmdshow); UpdateWindow(hMainFrame); + bool valid_dir = false; + + if (lpCmdLine) { + DWORD attribs = GetFileAttributes(lpCmdLine); + + if (attribs!=INVALID_FILE_ATTRIBUTES && (attribs&FILE_ATTRIBUTE_DIRECTORY)) + valid_dir = true; + else if (*lpCmdLine==':' || *lpCmdLine=='"') + valid_dir = true; + } + // Open the first child window after initializing the application - if (lpCmdLine) + if (valid_dir) PostMessage(hMainFrame, PM_OPEN_WINDOW, 0, (LPARAM)lpCmdLine); else PostMessage(hMainFrame, PM_OPEN_WINDOW, OWM_EXPLORE|OWM_DETAILS, 0); @@ -145,6 +156,69 @@ void explorer_show_frame(HWND hwndDesktop, int cmdshow, LPTSTR lpCmdLine) } + /// "About Explorer" Dialog +struct ExplorerAboutDlg : public + CtlColorParent< + OwnerDrawParent + > +{ + typedef CtlColorParent< + OwnerDrawParent + > super; + + ExplorerAboutDlg(HWND hwnd) + : super(hwnd) + { + SetWindowIcon(hwnd, IDI_REACTOS); + + new FlatButton(hwnd, IDOK); + + _hfont = CreateFont(20, 0, 0, 0, FW_BOLD, TRUE, 0, 0, 0, 0, 0, 0, 0, TEXT("Sans Serif")); + new ColorStatic(hwnd, IDC_ROS_EXPLORER, RGB(32,32,128), 0, _hfont); + + new HyperlinkCtrl(hwnd, IDC_WWW); + + CenterWindow(hwnd); + } + + ~ExplorerAboutDlg() + { + DeleteObject(_hfont); + } + + LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) + { + switch(nmsg) { + case WM_PAINT: + Paint(); + break; + + default: + return super::WndProc(nmsg, wparam, lparam); + } + + return 0; + } + + void Paint() + { + PaintCanvas canvas(_hwnd); + + HICON hicon = (HICON) LoadImage(g_Globals._hInstance, MAKEINTRESOURCE(IDI_REACTOS_BIG), IMAGE_ICON, 0, 0, LR_SHARED); + + DrawIconEx(canvas, 20, 10, hicon, 0, 0, 0, 0, DI_NORMAL); + } + +protected: + HFONT _hfont; +}; + +void explorer_about(HWND hwndParent) +{ + Dialog::DoModal(IDD_ABOUT_EXPLORER, WINDOW_CREATOR(ExplorerAboutDlg), hwndParent); +} + + static void InitInstance(HINSTANCE hInstance) { CONTEXT("InitInstance"); diff --git a/reactos/subsys/system/explorer/explorer.dsp b/reactos/subsys/system/explorer/explorer.dsp index a6305167805..f137aef0b85 100644 --- a/reactos/subsys/system/explorer/explorer.dsp +++ b/reactos/subsys/system/explorer/explorer.dsp @@ -727,5 +727,9 @@ SOURCE=.\globals.h SOURCE=".\i386-stub-win32.c" # End Source File +# Begin Source File + +SOURCE=".\res\ros-big.ico" +# End Source File # End Target # End Project diff --git a/reactos/subsys/system/explorer/explorer_intres.h b/reactos/subsys/system/explorer/explorer_intres.h index 1110b92b203..a6d159f0df1 100644 --- a/reactos/subsys/system/explorer/explorer_intres.h +++ b/reactos/subsys/system/explorer/explorer_intres.h @@ -28,6 +28,7 @@ #define IDS_SEARCH_PRG 24 #define IDS_ALL_USERS 25 #define IDS_SEARCH 26 +#define IDS_ABOUT_EXPLORER 27 #define IDI_REACTOS 100 #define IDI_EXPLORER 101 #define IDI_STARTMENU 102 @@ -51,16 +52,20 @@ #define IDA_SEARCH_PROGRAM 133 #define IDI_APPICON 134 #define IDI_FLOATING 135 +#define IDD_ABOUT_EXPLORER 135 +#define IDI_REACTOS_BIG 137 #define ID_VIEW_NAME 401 #define ID_VIEW_ALL_ATTRIBUTES 402 #define ID_VIEW_SELECTED_ATTRIBUTES 403 #define ID_VIEW_STATUSBAR 503 #define ID_VIEW_DRIVE_BAR 507 #define ID_VIEW_TOOL_BAR 508 +#define IDC_ROS_EXPLORER 1000 +#define IDC_WWW 1012 #define IDC_TOPIC 1017 #define IDC_MAILS_FOUND 1018 #define ID_REFRESH 1704 -#define ID_ABOUT 1803 +#define ID_ABOUT_WINEFILE 1705 #define IDC_FILETREE 10001 #define ID_EXPLORER_FAQ 10002 #define ID_WINDOW_AUTOSORT 0x8003 @@ -70,6 +75,8 @@ #define ID_DRIVE_SHELL_NS 0x9001 #define ID_DRIVE_UNIX_FS 0x9002 #define ID_DRIVE_FIRST 0x9003 +#define ID_ABOUT_WINDOWS 40002 +#define ID_ABOUT_EXPLORER 40003 #define ID_WINDOW_NEW 0xE130 #define ID_WINDOW_ARRANGE 0xE131 #define ID_WINDOW_CASCADE 0xE132 @@ -86,9 +93,9 @@ // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 135 -#define _APS_NEXT_COMMAND_VALUE 40002 -#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_RESOURCE_VALUE 138 +#define _APS_NEXT_COMMAND_VALUE 40004 +#define _APS_NEXT_CONTROL_VALUE 1001 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/reactos/subsys/system/explorer/explorer_intres.rc b/reactos/subsys/system/explorer/explorer_intres.rc index d2422b00017..cd16567ad68 100644 --- a/reactos/subsys/system/explorer/explorer_intres.rc +++ b/reactos/subsys/system/explorer/explorer_intres.rc @@ -50,7 +50,8 @@ BEGIN POPUP "&Ajutor" BEGIN MENUITEM "Explorer &FAQ...", ID_EXPLORER_FAQ - MENUITEM "&Despre Explorer...", ID_ABOUT + MENUITEM "&Despre Explorer...", ID_ABOUT_EXPLORER + MENUITEM "Despre &OS...", ID_ABOUT_WINDOWS END END @@ -99,7 +100,6 @@ BEGIN IDS_EMPTY "(Empty)" IDS_RECENT "Documente Recente" IDS_ADMIN "Administrare" - IDS_SEARCH "Căutare..." END STRINGTABLE DISCARDABLE @@ -114,6 +114,8 @@ BEGIN IDS_BROWSE "Browse Files" IDS_SEARCH_PRG "Search Programm..." IDS_ALL_USERS "All Users\\" + IDS_SEARCH "Căutare..." + IDS_ABOUT_EXPLORER "&Despre Explorer..." END #endif // Romanian resources @@ -280,7 +282,7 @@ BEGIN MENUITEM "&Suchen...\tF1", ID_HELP MENUITEM "Hilfe &verwenden\tF1", ID_HELP_USING MENUITEM SEPARATOR - MENUITEM "Info about &Winefile...", ID_ABOUT + MENUITEM "Info about &Winefile...", ID_ABOUT_WINEFILE END END @@ -306,6 +308,19 @@ BEGIN PUSHBUTTON "&Hilfe",254,158,43,47,14 END +IDD_ABOUT_EXPLORER DIALOG DISCARDABLE 0, 0, 196, 109 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "About ReactOS Explorer" +FONT 10, "MS Sans Serif" +BEGIN + LTEXT "ReactOS Explorer",IDC_ROS_EXPLORER,91,29,90,11 + LTEXT "(c) 2003 Martin Fuchs",IDC_STATIC,90,50,70,8 + LTEXT "http://www.sky.franken.de/explorer/",IDC_WWW,21,84,104, + 8 + CONTROL "OK",IDOK,"Button",BS_OWNERDRAW | BS_FLAT | WS_GROUP,151, + 90,38,12 +END + #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// @@ -348,6 +363,26 @@ IDI_ARROW ICON DISCARDABLE "res/arrow.ico" IDI_ARROW_SELECTED ICON DISCARDABLE "res/arrowsel.ico" IDI_APPICON ICON DISCARDABLE "res/appicon.ico" IDI_FLOATING ICON DISCARDABLE "res/floating.ico" +IDI_REACTOS_BIG ICON DISCARDABLE "res\\ros-big.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_ABOUT_EXPLORER, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 189 + TOPMARGIN, 7 + BOTTOMMARGIN, 102 + END +END +#endif // APSTUDIO_INVOKED + ///////////////////////////////////////////////////////////////////////////// // @@ -371,7 +406,6 @@ BEGIN IDS_EMPTY "(Empty)" IDS_RECENT "Aktuelle Dokumente" IDS_ADMIN "Verwaltung" - IDS_SEARCH "Suche" END STRINGTABLE DISCARDABLE @@ -386,6 +420,8 @@ BEGIN IDS_BROWSE "Dateien" IDS_SEARCH_PRG "Suche Programm..." IDS_ALL_USERS "Alle Benutzer\\" + IDS_SEARCH "Suche" + IDS_ABOUT_EXPLORER "&Über Explorer..." END #endif // German (Germany) resources @@ -430,7 +466,8 @@ BEGIN POPUP "&Help" BEGIN MENUITEM "Explorer &FAQ...", ID_EXPLORER_FAQ - MENUITEM "&About Explorer...", ID_ABOUT + MENUITEM "&About Explorer...", ID_ABOUT_EXPLORER + MENUITEM "About &OS...", ID_ABOUT_WINDOWS END END @@ -539,7 +576,7 @@ BEGIN MENUITEM "Help &Search...\tF1", ID_HELP MENUITEM "&Using Help\tF1", ID_HELP_USING MENUITEM SEPARATOR - MENUITEM "Info about &Winefile...", ID_ABOUT + MENUITEM "Info about &Winefile...", ID_ABOUT_WINEFILE END END @@ -621,7 +658,6 @@ BEGIN IDS_EMPTY "(Empty)" IDS_RECENT "Recent Documents" IDS_ADMIN "Administration" - IDS_SEARCH "Search" END STRINGTABLE DISCARDABLE @@ -636,6 +672,8 @@ BEGIN IDS_BROWSE "Browse Files" IDS_SEARCH_PRG "Search Programm..." IDS_ALL_USERS "All Users\\" + IDS_SEARCH "Search" + IDS_ABOUT_EXPLORER "&About Explorer..." END #endif // English (U.S.) resources @@ -658,14 +696,14 @@ LANGUAGE LANG_FRENCH, SUBLANG_FRENCH IDM_MAINFRAME MENU PRELOAD DISCARDABLE BEGIN - POPUP "Fichier" + POPUP "&Fichier" BEGIN - MENUITEM "Fermer", ID_FILE_EXIT + MENUITEM "&Fermer", ID_FILE_EXIT END - POPUP "Affichage" + POPUP "&Affichage" BEGIN - MENUITEM "Barre d'outils", ID_VIEW_TOOL_BAR - MENUITEM "Barre d'état", ID_VIEW_STATUSBAR + MENUITEM "Barre d'&outils", ID_VIEW_TOOL_BAR + MENUITEM "Barre d'&état", ID_VIEW_STATUSBAR END POPUP "&Window" BEGIN @@ -677,10 +715,11 @@ BEGIN MENUITEM "Arrange &Symbols", ID_WINDOW_ARRANGE MENUITEM "&Refresh\tF5", ID_REFRESH END - POPUP "Aide" + POPUP "A&ide" BEGIN - MENUITEM "FAQ Explorateur...", ID_EXPLORER_FAQ - MENUITEM "A propos de l'explorateur...", ID_ABOUT + MENUITEM "&FAQ Explorateur...", ID_EXPLORER_FAQ + MENUITEM "A propos de l'&explorateur...", ID_ABOUT_WINDOWS + MENUITEM "A propos de l'&OS...", ID_ABOUT_EXPLORER END END @@ -729,7 +768,6 @@ BEGIN IDS_EMPTY "(Vide)" IDS_RECENT "Documents récents" IDS_ADMIN "Administration" - IDS_SEARCH "Rechercher" END STRINGTABLE DISCARDABLE @@ -744,6 +782,8 @@ BEGIN IDS_BROWSE "Parcourir" IDS_SEARCH_PRG "Recherche Programme..." IDS_ALL_USERS "Tous les utilisateurs\\" + IDS_SEARCH "Rechercher" + IDS_ABOUT_EXPLORER "A propos de l'explorateur..." END #endif // French (France) resources diff --git a/reactos/subsys/system/explorer/externals.h b/reactos/subsys/system/explorer/externals.h index 81ca8d70b86..579a1941aa0 100644 --- a/reactos/subsys/system/explorer/externals.h +++ b/reactos/subsys/system/explorer/externals.h @@ -40,6 +40,9 @@ extern int explorer_main(HINSTANCE hinstance, HWND hwndDesktop, LPTSTR lpCmdLine // display explorer/file manager window extern void explorer_show_frame(HWND hwndDesktop, int cmdshow, LPTSTR lpCmdLine=NULL); + // display explorer "About" dialog +extern void explorer_about(HWND hwndParent); + // test for already running desktop instance extern BOOL IsAnyDesktopRunning(); diff --git a/reactos/subsys/system/explorer/res/ros-big.ico b/reactos/subsys/system/explorer/res/ros-big.ico new file mode 100644 index 0000000000000000000000000000000000000000..7721efe24bd4281438bad1f5d461cb059088e25d GIT binary patch literal 138414 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 AjsO4v literal 0 HcmV?d00001 diff --git a/reactos/subsys/system/explorer/shell/mainframe.cpp b/reactos/subsys/system/explorer/shell/mainframe.cpp index ee8bed88865..4d5783bfa1c 100644 --- a/reactos/subsys/system/explorer/shell/mainframe.cpp +++ b/reactos/subsys/system/explorer/shell/mainframe.cpp @@ -30,6 +30,7 @@ #include "../explorer.h" #include "../globals.h" +#include "../externals.h" #include "../explorer_intres.h" @@ -526,10 +527,14 @@ int MainFrame::Command(int id, int code) ///@todo There are even more menu items! - case ID_ABOUT: + case ID_ABOUT_WINDOWS: ShellAbout(_hwnd, ResString(IDS_TITLE), NULL, 0); break; + case ID_ABOUT_EXPLORER: + explorer_about(_hwnd); + break; + case ID_EXPLORER_FAQ: launch_file(_hwnd, TEXT("http://www.sky.franken.de/explorer/"), SW_SHOWNORMAL); break; diff --git a/reactos/subsys/system/explorer/taskbar/startmenu.cpp b/reactos/subsys/system/explorer/taskbar/startmenu.cpp index 4180a392b40..7c225aa0277 100644 --- a/reactos/subsys/system/explorer/taskbar/startmenu.cpp +++ b/reactos/subsys/system/explorer/taskbar/startmenu.cpp @@ -975,7 +975,7 @@ void StartMenuRoot::ShowLaunchDialog(HWND hwndDesktopBar) static LPCSTR szTitle = "Create New Task"; static LPCSTR szText = "Type the name of a program, folder, document, or Internet resource, and Task Manager will open it for you."; - static DynamicFct RunFileDlg(TEXT("SHELL32"), 61); + static DynamicFct RunFileDlg(TEXT("WSHELL32"), 61); // Show "Run..." dialog if (RunFileDlg) { @@ -1116,10 +1116,12 @@ int SearchMenu::Command(int id, int code) break; case IDC_SEARCH_FILES: + CloseStartMenu(id); ShowSearchDialog(); break; case IDC_SEARCH_COMPUTER: + CloseStartMenu(id); ShowSearchComputer(); break; diff --git a/reactos/subsys/system/explorer/utility/shellclasses.cpp b/reactos/subsys/system/explorer/utility/shellclasses.cpp index 3ab67c4bd91..d447f3e7173 100644 --- a/reactos/subsys/system/explorer/utility/shellclasses.cpp +++ b/reactos/subsys/system/explorer/utility/shellclasses.cpp @@ -434,25 +434,16 @@ HRESULT ShellFolderContextMenu(IShellFolder* shell_folder, HWND hwndParent, int // HRESULT hr = CDefFolderMenu_Create2(dir?dir->_pidl:DesktopFolder(), hwndParent, 1, &pidl, shell_folder, NULL, 0, NULL, &pcm); if (SUCCEEDED(hr)) { - HMENU hPopup = CreatePopupMenu(); + HMENU hmenu = CreatePopupMenu(); - if (hPopup) { - hr = pcm->QueryContextMenu(hPopup, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL|CMF_EXPLORE); + if (hmenu) { + hr = pcm->QueryContextMenu(hmenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL|CMF_EXPLORE); if (SUCCEEDED(hr)) { - IContextMenu2* pcm2; - - pcm->QueryInterface(IID_IContextMenu2, (LPVOID*)&pcm2); - - UINT idCmd = TrackPopupMenu(hPopup, TPM_LEFTALIGN|TPM_RETURNCMD|TPM_RIGHTBUTTON, x, y, 0, hwndParent, NULL); - - if (pcm2) { - pcm2->Release(); - pcm2 = NULL; - } + UINT idCmd = TrackPopupMenu(hmenu, TPM_LEFTALIGN|TPM_RETURNCMD|TPM_RIGHTBUTTON, x, y, 0, hwndParent, NULL); if (idCmd) { - CMINVOKECOMMANDINFO cmi; + CMINVOKECOMMANDINFO cmi; cmi.cbSize = sizeof(CMINVOKECOMMANDINFO); cmi.fMask = 0; @@ -462,7 +453,7 @@ HRESULT ShellFolderContextMenu(IShellFolder* shell_folder, HWND hwndParent, int cmi.lpDirectory = NULL; cmi.nShow = SW_SHOWNORMAL; cmi.dwHotKey = 0; - cmi.hIcon = NULL; + cmi.hIcon = 0; hr = pcm->InvokeCommand(&cmi); } diff --git a/reactos/subsys/system/explorer/utility/utility.cpp b/reactos/subsys/system/explorer/utility/utility.cpp index 9630b2d3ce0..444128fdc58 100644 --- a/reactos/subsys/system/explorer/utility/utility.cpp +++ b/reactos/subsys/system/explorer/utility/utility.cpp @@ -101,10 +101,22 @@ void display_error(HWND hwnd, DWORD error) //@@ CONTEXT mit ausgeben -> display_ if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, 0, error, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (PTSTR)&msg, 0, NULL)) { LOG(FmtString(TEXT("display_error(%#x): %s"), error, msg)); + + SetLastError(0); MessageBox(hwnd, msg, TEXT("ROS Explorer"), MB_OK); + + if (GetLastError() == ERROR_INVALID_WINDOW_HANDLE) + MessageBox(0, msg, TEXT("ROS Explorer"), MB_OK); } else { LOG(FmtString(TEXT("Unknown Error %#x"), error)); - MessageBox(hwnd, FmtString(TEXT("Unknown Error %#x"), error), TEXT("ROS Explorer"), MB_OK); + + FmtString msg(TEXT("Unknown Error %#x"), error); + + SetLastError(0); + MessageBox(hwnd, msg, TEXT("ROS Explorer"), MB_OK); + + if (GetLastError() == ERROR_INVALID_WINDOW_HANDLE) + MessageBox(0, msg, TEXT("ROS Explorer"), MB_OK); } LocalFree(msg); diff --git a/reactos/subsys/system/explorer/utility/utility.h b/reactos/subsys/system/explorer/utility/utility.h index 83b43499eb3..9482d341ee5 100644 --- a/reactos/subsys/system/explorer/utility/utility.h +++ b/reactos/subsys/system/explorer/utility/utility.h @@ -605,6 +605,8 @@ struct String String& operator=(LPCTSTR s) {if (s) super::assign(s); else erase(); return *this;} String& operator=(const super& s) {super::assign(s); return *this;} + void assign(LPCTSTR s) {super::assign(s);} + void assign(LPCTSTR s, int l) {super::assign(s, l);} operator LPCTSTR() const {return c_str();} diff --git a/reactos/subsys/system/explorer/utility/window.cpp b/reactos/subsys/system/explorer/utility/window.cpp index 623d2e1c845..4dd1922ac25 100644 --- a/reactos/subsys/system/explorer/utility/window.cpp +++ b/reactos/subsys/system/explorer/utility/window.cpp @@ -930,6 +930,221 @@ void PictureButton::DrawItem(LPDRAWITEMSTRUCT dis) } +void FlatButton::DrawItem(LPDRAWITEMSTRUCT dis) +{ + UINT style = DFCS_BUTTONPUSH; + + if (dis->itemState & ODS_DISABLED) + style |= DFCS_INACTIVE; + + RECT textRect = {dis->rcItem.left+2, dis->rcItem.top+2, dis->rcItem.right-4, dis->rcItem.bottom-4}; + + if (dis->itemState & ODS_SELECTED) { + style |= DFCS_PUSHED; + ++textRect.left; ++textRect.top; + ++textRect.right; ++textRect.bottom; + } + + FillRect(dis->hDC, &dis->rcItem, GetSysColorBrush(COLOR_BTNFACE)); + + // highlight the button? + if (_active) + DrawEdge(dis->hDC, &dis->rcItem, EDGE_ETCHED, BF_RECT); + else if (GetWindowStyle(_hwnd) & BS_FLAT) // Only with BS_FLAT there will be drawn a frame to show highlighting. + DrawEdge(dis->hDC, &dis->rcItem, EDGE_RAISED, BF_RECT|BF_FLAT); + + TCHAR txt[BUFFER_LEN]; + int txt_len = GetWindowText(_hwnd, txt, BUFFER_LEN); + + if (dis->itemState & (ODS_DISABLED|ODS_GRAYED)) { + COLORREF gray = GetSysColor(COLOR_GRAYTEXT); + + if (gray) { + { + TextColor lcColor(dis->hDC, GetSysColor(COLOR_BTNHIGHLIGHT)); + RECT shadowRect = {textRect.left+1, textRect.top+1, textRect.right+1, textRect.bottom+1}; + DrawText(dis->hDC, txt, txt_len, &shadowRect, DT_SINGLELINE|DT_VCENTER|DT_CENTER); + } + + BkMode mode(dis->hDC, TRANSPARENT); + TextColor lcColor(dis->hDC, gray); + DrawText(dis->hDC, txt, txt_len, &textRect, DT_SINGLELINE|DT_VCENTER|DT_CENTER); + } else { + int old_r = textRect.right; + int old_b = textRect.bottom; + DrawText(dis->hDC, txt, txt_len, &textRect, DT_SINGLELINE|DT_VCENTER|DT_CENTER|DT_CALCRECT); + int x = textRect.left + (old_r-textRect.right)/2; + int y = textRect.top + (old_b-textRect.bottom)/2; + int w = textRect.right-textRect.left; + int h = textRect.bottom-textRect.top; + s_MyDrawText_Rect.right = w; + s_MyDrawText_Rect.bottom = h; + GrayString(dis->hDC, GetSysColorBrush(COLOR_GRAYTEXT), MyDrawText, (LPARAM)txt, txt_len, x, y, w, h); + } + } else { + TextColor lcColor(dis->hDC, _active? _activeColor: _textColor); + DrawText(dis->hDC, txt, txt_len, &textRect, DT_SINGLELINE|DT_VCENTER|DT_CENTER); + } + + if (dis->itemState & ODS_FOCUS) { + RECT rect = { + dis->rcItem.left+3, dis->rcItem.top+3, + dis->rcItem.right-dis->rcItem.left-4, dis->rcItem.bottom-dis->rcItem.top-4 + }; + if (dis->itemState & ODS_SELECTED) { + ++rect.left; ++rect.top; + ++rect.right; ++rect.bottom; + } + DrawFocusRect(dis->hDC, &rect); + } +} + +LRESULT FlatButton::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) +{ + switch(nmsg) { + case WM_MOUSEMOVE: { + bool active = false; + + if (IsWindowEnabled(_hwnd)) { + DWORD pid_foreground; + HWND hwnd_foreground = GetForegroundWindow(); //@@ vielleicht besser über WM_ACTIVATEAPP-Abfrage + GetWindowThreadProcessId(hwnd_foreground, &pid_foreground); + + if (GetCurrentProcessId() == pid_foreground) { + POINT pt = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)}; + ClientRect clntRect(_hwnd); + + // highlight the button? + if (pt.x>=clntRect.left && pt.x=clntRect.top && pt.y=clntRect.right || pt.y=clntRect.bottom) + goto cancel_press; + + goto def;} + + case WM_CANCELMODE: + cancel_press: { + TRACKMOUSEEVENT tme = {sizeof(tme), /*TME_HOVER|*/TME_LEAVE|TME_CANCEL, _hwnd/*, HOVER_DEFAULT*/}; + _TrackMouseEvent(&tme); + _active = false; + ReleaseCapture();} + // fall through + + case WM_MOUSELEAVE: + if (_active) { + _active = false; + + InvalidateRect(_hwnd, NULL, TRUE); + } + + return 0; + + default: def: + return super::WndProc(nmsg, wparam, lparam); + } +} + + +HyperlinkCtrl::HyperlinkCtrl(HWND hwnd, COLORREF colorLink, COLORREF colorVisited) + : super(hwnd), + _textColor(colorLink), + _colorVisited(colorVisited), + _hfont(0), + _crsr_link(0), + _cmd(ResString(GetDlgCtrlID(hwnd))) +{ + init(); +} + +HyperlinkCtrl::HyperlinkCtrl(HWND owner, int id, COLORREF colorLink, COLORREF colorVisited) + : super(GetDlgItem(owner, id)), + _textColor(colorLink), + _colorVisited(colorVisited), + _hfont(0), + _crsr_link(0), + _cmd(ResString(id)) +{ + init(); +} + +void HyperlinkCtrl::init() +{ + if (_cmd.empty()) { + TCHAR txt[BUFFER_LEN]; + _cmd.assign(txt, GetWindowText(_hwnd, txt, BUFFER_LEN)); + } +} + +HyperlinkCtrl::~HyperlinkCtrl() +{ + if (_hfont) + DeleteObject(_hfont); +} + +LRESULT HyperlinkCtrl::WndProc(UINT message, WPARAM wparam, LPARAM lparam) +{ + switch(message) { + case PM_DISPATCH_CTLCOLOR: { + if (!_hfont) { + HFONT hfont = (HFONT) SendMessage(_hwnd, WM_GETFONT, 0, 0); + LOGFONT lf; GetObject(hfont, sizeof(lf), &lf); + lf.lfUnderline = TRUE; + _hfont = CreateFontIndirect(&lf); + } + + HDC hdc = (HDC) wparam; + SetTextColor(hdc, _textColor); //@@ + SelectFont(hdc, _hfont); + SetBkMode(hdc, TRANSPARENT); + return (LRESULT)GetStockObject(HOLLOW_BRUSH); + } + + case WM_SETCURSOR: + if (!_crsr_link) + _crsr_link = LoadCursor(0, IDC_HAND); + + if (_crsr_link) + SetCursor(_crsr_link); + return 0; + + case WM_NCHITTEST: + return HTCLIENT; // Aktivierung von Maus-Botschaften + + case WM_LBUTTONDOWN: + if (LaunchLink()) { + _textColor = _colorVisited; + InvalidateRect(_hwnd, NULL, FALSE); + } else + MessageBeep(0); + return 0; + + default: + return super::WndProc(message, wparam, lparam); + } +} + + ToolTip::ToolTip(HWND owner) : super(CreateWindowEx(WS_EX_TOPMOST|WS_EX_NOPARENTNOTIFY, TOOLTIPS_CLASS, 0, WS_POPUP|TTS_NOPREFIX|TTS_ALWAYSTIP, CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT, diff --git a/reactos/subsys/system/explorer/utility/window.h b/reactos/subsys/system/explorer/utility/window.h index 0d077debef0..443463d6cef 100644 --- a/reactos/subsys/system/explorer/utility/window.h +++ b/reactos/subsys/system/explorer/utility/window.h @@ -493,7 +493,6 @@ struct Static : public WindowHandle }; -/* // control color message routing for ColorStatic and HyperlinkCtrl #define PM_DISPATCH_CTLCOLOR (WM_APP+0x08) @@ -522,7 +521,6 @@ template struct CtlColorParent : public BASE } } }; -*/ #define PM_DISPATCH_DRAWITEM (WM_APP+0x09) @@ -596,6 +594,26 @@ protected: */ +struct FlatButton : public OwnerdrawnButton +{ + typedef OwnerdrawnButton super; + + FlatButton(HWND hwnd) + : super(hwnd), _active(false) {} + + FlatButton(HWND owner, int id) + : super(GetDlgItem(owner, IDOK)), _active(false) {} + +protected: + LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam); + virtual void DrawItem(LPDRAWITEMSTRUCT dis); + + COLORREF _textColor; + COLORREF _activeColor; + bool _active; +}; + + /** Subclass button controls to paint pictures left to the labels. The buttons should have set the style bit BS_OWNERDRAW. @@ -619,6 +637,88 @@ protected: }; +struct ColorStatic : public SubclassedWindow +{ + typedef SubclassedWindow super; + + ColorStatic(HWND hwnd, COLORREF textColor=RGB(255,0,0), HBRUSH hbrush_bkgnd=0, HFONT hfont=0) + : super(hwnd), + _textColor(textColor), + _hbrush_bkgnd(hbrush_bkgnd), + _hfont(hfont) + { + } + + ColorStatic(HWND owner, int id, COLORREF textColor=RGB(255,0,0), HBRUSH hbrush_bkgnd=0, HFONT hfont=0) + : super(GetDlgItem(owner, id)), + _textColor(textColor), + _hbrush_bkgnd(hbrush_bkgnd), + _hfont(hfont) + { + } + +protected: + LRESULT WndProc(UINT message, WPARAM wparam, LPARAM lparam) + { + if (message == PM_DISPATCH_CTLCOLOR) { + HDC hdc = (HDC) wparam; + + SetTextColor(hdc, _textColor); + + if (_hfont) + SelectFont(hdc, _hfont); + + if (_hbrush_bkgnd) + return (LRESULT)_hbrush_bkgnd; + else { + SetBkMode(hdc, TRANSPARENT); + return (LRESULT)GetStockBrush(HOLLOW_BRUSH); + } + } else + return super::WndProc(message, wparam, lparam); + } + + COLORREF _textColor; + HBRUSH _hbrush_bkgnd; + HFONT _hfont; +}; + + + /// Hyperlink Controls + +struct HyperlinkCtrl : public SubclassedWindow +{ + typedef SubclassedWindow super; + + HyperlinkCtrl(HWND hwnd, COLORREF colorLink=RGB(0,0,255), COLORREF colorVisited=RGB(128,0,128)); + HyperlinkCtrl(HWND owner, int id, COLORREF colorLink=RGB(0,0,255), COLORREF colorVisited=RGB(128,0,128)); + + ~HyperlinkCtrl(); + + String _cmd; + +protected: + COLORREF _textColor; + COLORREF _colorVisited; + HFONT _hfont; + HCURSOR _crsr_link; + + LRESULT WndProc(UINT message, WPARAM wparam, LPARAM lparam); + + void init(); + + bool LaunchLink() + { + if (!_cmd.empty()) { + HINSTANCE hinst = ShellExecute(GetParent(_hwnd), _T("open"), _cmd, 0, 0, SW_SHOWNORMAL); + return (int)hinst > HINSTANCE_ERROR; + } + + return true; + } +}; + + /// encapsulation of tool tip controls struct ToolTip : public WindowHandle {