diff --git a/reactos/subsys/system/explorer/Makefile b/reactos/subsys/system/explorer/Makefile index f2206470cf6..e8ccaca9494 100644 --- a/reactos/subsys/system/explorer/Makefile +++ b/reactos/subsys/system/explorer/Makefile @@ -45,10 +45,11 @@ TARGET_OBJECTS := \ shell/pane.o \ shell/regfs.o \ shell/shellbrowser.o \ - shell/startup.o \ shell/unixfs.o \ shell/webchild.o \ shell/winfs.o \ + services/startup.o \ + services/shellservices.o \ taskbar/desktopbar.o \ taskbar/taskbar.o \ taskbar/startmenu.o \ diff --git a/reactos/subsys/system/explorer/Makefile.MinGW b/reactos/subsys/system/explorer/Makefile.MinGW index 569efe10674..a75dc2de0e6 100644 --- a/reactos/subsys/system/explorer/Makefile.MinGW +++ b/reactos/subsys/system/explorer/Makefile.MinGW @@ -38,7 +38,7 @@ CXXFLAGS = $(CFLAGS) EXEC_SUFFIX = .exe RES_SUFFIX = .coff -VPATH = shell utility taskbar desktop dialogs +VPATH = shell utility taskbar desktop dialogs services PROGRAM = explorer @@ -51,6 +51,7 @@ OBJECTS = \ window.o \ dragdropimpl.o \ shellbrowserimpl.o \ + shellservices.o \ explorer.o \ entries.o \ winfs.o \ diff --git a/reactos/subsys/system/explorer/Makefile.PCH b/reactos/subsys/system/explorer/Makefile.PCH index 35c1a6dcfe2..496831bf539 100644 --- a/reactos/subsys/system/explorer/Makefile.PCH +++ b/reactos/subsys/system/explorer/Makefile.PCH @@ -39,7 +39,7 @@ CXXFLAGS = $(CFLAGS) EXEC_SUFFIX = .exe RES_SUFFIX = .coff -VPATH = shell utility taskbar desktop dialogs +VPATH = shell utility taskbar desktop dialogs services PROGRAM = explorer @@ -69,6 +69,7 @@ OBJECTS = \ desktopbar.o \ taskbar.o \ startmenu.o \ + shellservices.o \ traynotify.o \ quicklaunch.o \ favorites.o \ diff --git a/reactos/subsys/system/explorer/Makefile.Wine b/reactos/subsys/system/explorer/Makefile.Wine index 39d0deb4d48..70e36d058e6 100644 --- a/reactos/subsys/system/explorer/Makefile.Wine +++ b/reactos/subsys/system/explorer/Makefile.Wine @@ -10,7 +10,7 @@ EXTRA_OBJS = notifyhook.dll libexpat.dll EXTRALIBS = $(LIBUUID) C_SRCS = \ - shell/startup.c \ + services/startup.c \ utility/splitpath.c CPP_SRCS = \ @@ -34,6 +34,7 @@ CPP_SRCS = \ shell/regfs.cpp \ shell/fatfs.cpp \ shell/webchild.cpp \ + services/shellservices.cpp \ taskbar/desktopbar.cpp \ taskbar/taskbar.cpp \ taskbar/startmenu.cpp \ diff --git a/reactos/subsys/system/explorer/explorer.cpp b/reactos/subsys/system/explorer/explorer.cpp index fae5389cdd2..0398ff83c17 100644 --- a/reactos/subsys/system/explorer/explorer.cpp +++ b/reactos/subsys/system/explorer/explorer.cpp @@ -41,6 +41,8 @@ #include "dialogs/settings.h" // for MdiSdiDlg +#include "services/shellservices.h" + extern "C" int initialize_gdb_stub(); // start up GDB stub @@ -829,7 +831,9 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdL // another undocumented event: "Global\\msgina: ReturnToWelcome" if (!SetShellReadyEvent(TEXT("msgina: ShellReadyEvent"))) SetShellReadyEvent(TEXT("Global\\msgina: ShellReadyEvent")); + } + if (!any_desktop_running) { // launch the shell DDE server if (g_SHDOCVW_ShellDDEInit) (*g_SHDOCVW_ShellDDEInit)(TRUE); @@ -868,18 +872,31 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdL g_Globals.read_persistent(); if (startup_desktop) { + WaitCursor wait; + g_Globals._desktops.init(); g_Globals._hwndDesktop = DesktopWindow::Create(); #ifdef _USE_HDESK g_Globals._desktops.get_current_Desktop()->_hwndDesktop = g_Globals._hwndDesktop; #endif + } - /**TODO launching autostart programs can be moved into a background thread. */ - if (autostart) { - char* argv[] = {"", "s"}; // call startup routine in SESSION_START mode - startup(2, argv); - } + if (g_Globals._hwndDesktop) + g_Globals._desktop_mode = true; + + Thread* pSSOThread = NULL; + + if (startup_desktop) { + // launch SSO thread to allow message processing independent from the explorer main thread + pSSOThread = new SSOThread; + pSSOThread->Start(); + } + + /**TODO launching autostart programs can be moved into a background thread. */ + if (autostart) { + char* argv[] = {"", "s"}; // call startup routine in SESSION_START mode + startup(2, argv); } /**TODO fix command line handling */ @@ -888,17 +905,21 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdL lpCmdLine[_tcslen(lpCmdLine)-1] = '\0'; } - if (g_Globals._hwndDesktop) - g_Globals._desktop_mode = true; - int ret = explorer_main(hInstance, lpCmdLine, nShowCmd); // write configuration file g_Globals.write_persistent(); - // shutdown the shell DDE server - if (g_SHDOCVW_ShellDDEInit) - (*g_SHDOCVW_ShellDDEInit)(FALSE); + if (pSSOThread) { + pSSOThread->Stop(); + delete pSSOThread; + } + + if (!any_desktop_running) { + // shutdown the shell DDE server + if (g_SHDOCVW_ShellDDEInit) + (*g_SHDOCVW_ShellDDEInit)(FALSE); + } return ret; } diff --git a/reactos/subsys/system/explorer/explorer.dsp b/reactos/subsys/system/explorer/explorer.dsp index eb9763211db..8035c7f945e 100644 --- a/reactos/subsys/system/explorer/explorer.dsp +++ b/reactos/subsys/system/explorer/explorer.dsp @@ -702,11 +702,6 @@ SOURCE=.\shell\shellfs.h # End Source File # Begin Source File -SOURCE=.\shell\startup.c -# SUBTRACT CPP /YX /Yc /Yu -# End Source File -# Begin Source File - SOURCE=.\shell\unixfs.cpp # PROP Exclude_From_Build 1 # End Source File @@ -785,5 +780,22 @@ SOURCE=.\precomp.cpp SOURCE=.\precomp.h # End Source File # End Group +# Begin Group "services" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\services\shellservices.cpp +# End Source File +# Begin Source File + +SOURCE=.\services\shellservices.h +# End Source File +# Begin Source File + +SOURCE=.\services\startup.c +# SUBTRACT CPP /YX /Yc /Yu +# End Source File +# End Group # End Target # End Project diff --git a/reactos/subsys/system/explorer/externals.h b/reactos/subsys/system/explorer/externals.h index eee42742ece..50e7650868c 100644 --- a/reactos/subsys/system/explorer/externals.h +++ b/reactos/subsys/system/explorer/externals.h @@ -31,9 +31,6 @@ extern "C" { #endif - // launch start programs -extern int startup(int argc, char *argv[]); - // explorer main routine extern int explorer_main(HINSTANCE hinstance, LPTSTR lpCmdLine, int cmdshow); diff --git a/reactos/subsys/system/explorer/services/shellservices.cpp b/reactos/subsys/system/explorer/services/shellservices.cpp new file mode 100644 index 00000000000..f24ef636ca2 --- /dev/null +++ b/reactos/subsys/system/explorer/services/shellservices.cpp @@ -0,0 +1,95 @@ +/* + * Copyright 2005 Martin Fuchs + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + + // + // Explorer clone + // + // shellservices.cpp + // + // Martin Fuchs, 28.03.2005 + // + + +#include "precomp.h" + +#include "shellservices.h" + + +int SSOThread::Run() +{ + ComInit usingCOM(COINIT_APARTMENTTHREADED|COINIT_DISABLE_OLE1DDE|COINIT_SPEED_OVER_MEMORY); + + HKEY hkey; + CLSID clsid; + WCHAR name[MAX_PATH], value[MAX_PATH]; + + typedef vector*> SSOVector; + SSOVector sso_ptrs; + + if (!RegOpenKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ShellServiceObjectDelayLoad"), &hkey)) { + for(int idx=0; ; ++idx) { + DWORD name_len = MAX_PATH; + DWORD value_len = sizeof(value); + + if (RegEnumValueW(hkey, idx, name, &name_len, 0, NULL, (LPBYTE)&value, &value_len)) + break; + + if (!_alive) + break; + + SIfacePtr* sso_ptr = new SIfacePtr; + + if (CLSIDFromString(value, &clsid) == NOERROR) { + if (SUCCEEDED(sso_ptr->CreateInstance(clsid, IID_IOleCommandTarget))) { + if (SUCCEEDED((*sso_ptr)->Exec(&CGID_ShellServiceObject, OLECMDID_NEW, OLECMDEXECOPT_DODEFAULT, NULL, NULL))) + sso_ptrs.push_back(sso_ptr); + } + } + } + + RegCloseKey(hkey); + } + + MSG msg; + + while(_alive) { + if (MsgWaitForMultipleObjects(1, &_evtFinish, FALSE, INFINITE, QS_ALLINPUT) == WAIT_OBJECT_0+0) + break; // _evtFinish has been set. + + while(_alive) { + if (!PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) + break; + + if (msg.message == WM_QUIT) + break; + + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + // shutdown all running Shell Service Objects + for(SSOVector::iterator it=sso_ptrs.begin(); it!=sso_ptrs.end(); ++it) { + SIfacePtr* sso_ptr = *it; + (*sso_ptr)->Exec(&CGID_ShellServiceObject, OLECMDID_SAVE, OLECMDEXECOPT_DODEFAULT, NULL, NULL); + delete sso_ptr; + } + + return 0; +} diff --git a/reactos/subsys/system/explorer/services/shellservices.h b/reactos/subsys/system/explorer/services/shellservices.h new file mode 100644 index 00000000000..ecda2819069 --- /dev/null +++ b/reactos/subsys/system/explorer/services/shellservices.h @@ -0,0 +1,36 @@ +/* + * Copyright 2005 Martin Fuchs + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + + // + // Explorer clone + // + // shellservices.h + // + // Martin Fuchs, 28.03.2005 + // + + + // launch start programs +extern "C" int startup(int argc, char *argv[]); + + // load Shell Service Objects (volume control, printer/network icons, ...) +struct SSOThread : public Thread +{ + int Run(); +}; diff --git a/reactos/subsys/system/explorer/shell/startup.c b/reactos/subsys/system/explorer/services/startup.c similarity index 100% rename from reactos/subsys/system/explorer/shell/startup.c rename to reactos/subsys/system/explorer/services/startup.c diff --git a/reactos/subsys/system/explorer/shell/pane.cpp b/reactos/subsys/system/explorer/shell/pane.cpp index 975379939b5..ea72acbee3b 100644 --- a/reactos/subsys/system/explorer/shell/pane.cpp +++ b/reactos/subsys/system/explorer/shell/pane.cpp @@ -163,7 +163,7 @@ void Pane::init() HKEY hkeyExplorer = 0; DWORD len = sizeof(_clrCompressed); - if (RegOpenKey(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"), &hkeyExplorer) || + if (RegOpenKey(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer"), &hkeyExplorer) || RegQueryValueEx(hkeyExplorer, TEXT("AltColor"), 0, NULL, (LPBYTE)&_clrCompressed, &len) || len!=sizeof(_clrCompressed)) _clrCompressed = RGB(0,0,255); diff --git a/reactos/subsys/system/explorer/shell/regfs.cpp b/reactos/subsys/system/explorer/shell/regfs.cpp index e804dfdaaaa..1f6506d62f0 100644 --- a/reactos/subsys/system/explorer/shell/regfs.cpp +++ b/reactos/subsys/system/explorer/shell/regfs.cpp @@ -43,9 +43,9 @@ void RegDirectory::read_directory(int scan_flags) _tcscpy(buffer, (LPCTSTR)_path); LPTSTR pname = buffer + _tcslen(buffer); - HKEY hKey; + HKEY hkey; - if (!RegOpenKeyEx(_hKeyRoot, *buffer=='\\'?buffer+1:buffer, 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS, &hKey)) { + if (!RegOpenKeyEx(_hKeyRoot, *buffer=='\\'?buffer+1:buffer, 0, STANDARD_RIGHTS_READ|KEY_QUERY_VALUE|KEY_ENUMERATE_SUB_KEYS, &hkey)) { if (pname[-1] != '\\') *pname++ = '\\'; @@ -60,7 +60,7 @@ void RegDirectory::read_directory(int scan_flags) DWORD name_len = MAX_PATH; DWORD class_len = MAX_PATH; - if (RegEnumKeyEx(hKey, idx, name, &name_len, 0, class_name, &class_len, &w32fd.ftLastWriteTime)) + if (RegEnumKeyEx(hkey, idx, name, &name_len, 0, class_name, &class_len, &w32fd.ftLastWriteTime)) break; w32fd.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY; @@ -88,7 +88,7 @@ void RegDirectory::read_directory(int scan_flags) TCHAR value[MAX_PATH]; LONG value_len = sizeof(value); - if (!RegQueryValue(hKey, NULL, value, &value_len) && value_len>1) { + if (!RegQueryValue(hkey, NULL, value, &value_len) && value_len>1) { memset(&w32fd, 0, sizeof(WIN32_FIND_DATA)); lstrcpy(w32fd.cFileName, TEXT("(Default)")); @@ -114,7 +114,7 @@ void RegDirectory::read_directory(int scan_flags) for(int idx=0; ; ++idx) { DWORD name_len = MAX_PATH; - if (RegEnumValue(hKey, idx, name, &name_len, 0, &type, NULL, NULL)) + if (RegEnumValue(hkey, idx, name, &name_len, 0, &type, NULL, NULL)) break; memset(&w32fd, 0, sizeof(WIN32_FIND_DATA)); @@ -147,7 +147,7 @@ void RegDirectory::read_directory(int scan_flags) TCHAR value[MAX_PATH]; DWORD value_len = sizeof(value); - if (!RegQueryValueEx(hKey, name, NULL, NULL, (LPBYTE)value, &value_len)) { + if (!RegQueryValueEx(hkey, name, NULL, NULL, (LPBYTE)value, &value_len)) { if (type==REG_SZ || type==REG_EXPAND_SZ || type==REG_LINK) entry->_content = _tcsdup(value); else if (type == REG_DWORD) { @@ -171,7 +171,7 @@ void RegDirectory::read_directory(int scan_flags) if (last) last->_next = NULL; - RegCloseKey(hKey); + RegCloseKey(hkey); } _down = first_entry; diff --git a/reactos/subsys/system/explorer/taskbar/desktopbar.cpp b/reactos/subsys/system/explorer/taskbar/desktopbar.cpp index 651420d7401..413bb71a4e3 100644 --- a/reactos/subsys/system/explorer/taskbar/desktopbar.cpp +++ b/reactos/subsys/system/explorer/taskbar/desktopbar.cpp @@ -41,7 +41,11 @@ DesktopBar::DesktopBar(HWND hwnd) : super(hwnd), +#ifdef _ROS_ _trayIcon(hwnd, ID_TRAY_VOLUME) +#else + WM_TASKBARCREATED(RegisterWindowMessage(WINMSG_TASKBARCREATED)) +#endif { SetWindowIcon(hwnd, IDI_REACTOS/*IDI_SEARCH*/); // icon in for TrayNotifyDlg @@ -107,6 +111,12 @@ LRESULT DesktopBar::Init(LPCREATESTRUCT pcs) // create tray notification area _hwndNotify = NotifyArea::Create(_hwnd); + + // notify all top level windows about the successfully created desktop bar + //@@ Use SendMessage() instead of PostMessage() to avoid problems with delayed created shell service objects? + PostMessage(HWND_BROADCAST, WM_TASKBARCREATED, 0, 0); + + _hwndQuickLaunch = QuickLaunchBar::Create(_hwnd); // create rebar window to manage task and quick launch bar @@ -147,10 +157,8 @@ LRESULT DesktopBar::Init(LPCREATESTRUCT pcs) SendMessage(_hwndrebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand); #endif - RegisterHotkeys(); - // notify all top level windows about the successfully created desktop bar - PostMessage(HWND_BROADCAST, WM_TASKBARCREATED, 0, 0); + RegisterHotkeys(); // prepare Startmenu, but hide it for now _startMenuRoot = GET_WINDOW(StartMenuRoot, StartMenuRoot::Create(_hwnd)); @@ -332,6 +340,7 @@ int DesktopBar::Command(int id, int code) PostMessage(_hwndQuickLaunch, PM_UPDATE_DESKTOP, desktop_idx, 0); break;} +#ifdef _ROS_ case ID_TRAY_VOLUME: launch_file(_hwnd, TEXT("sndvol32.exe"), SW_SHOWNORMAL); // launch volume control application break; @@ -339,6 +348,7 @@ int DesktopBar::Command(int id, int code) case ID_VOLUME_PROPERTIES: launch_cpanel(_hwnd, TEXT("mmsys.cpl")); break; +#endif default: if (_hwndQuickLaunch) @@ -381,6 +391,8 @@ LRESULT DesktopBar::ProcessCopyData(COPYDATASTRUCT* pcd) } +#ifdef _ROS_ + void DesktopBar::AddTrayIcons() { _trayIcon.Add(SmallIcon(IDI_SPEAKER), ResString(IDS_VOLUME)); @@ -410,3 +422,5 @@ void DesktopBar::TrayDblClick(UINT id, int btn) break; } } + +#endif diff --git a/reactos/subsys/system/explorer/taskbar/desktopbar.h b/reactos/subsys/system/explorer/taskbar/desktopbar.h index beb8467ccce..d5c067c4afb 100644 --- a/reactos/subsys/system/explorer/taskbar/desktopbar.h +++ b/reactos/subsys/system/explorer/taskbar/desktopbar.h @@ -61,11 +61,20 @@ /// desktop bar window, also known as "system tray" -struct DesktopBar : public TrayIconControllerTemplate< - OwnerDrawParent > +struct DesktopBar : public +#ifdef _ROS_ + TrayIconControllerTemplate< + OwnerDrawParent > +#else + OwnerDrawParent +#endif { +#ifdef _ROS_ typedef TrayIconControllerTemplate< OwnerDrawParent > super; +#else + typedef OwnerDrawParent super; +#endif DesktopBar(HWND hwnd); ~DesktopBar(); @@ -93,9 +102,13 @@ protected: struct StartMenuRoot* _startMenuRoot; +#ifdef _ROS_ TrayIcon _trayIcon; void AddTrayIcons(); virtual void TrayClick(UINT id, int btn); virtual void TrayDblClick(UINT id, int btn); +#else + const UINT WM_TASKBARCREATED; +#endif }; diff --git a/reactos/subsys/system/explorer/taskbar/taskbar.cpp b/reactos/subsys/system/explorer/taskbar/taskbar.cpp index cb64e9bd84f..4cf42dde267 100644 --- a/reactos/subsys/system/explorer/taskbar/taskbar.cpp +++ b/reactos/subsys/system/explorer/taskbar/taskbar.cpp @@ -144,6 +144,7 @@ LRESULT TaskBar::Init(LPCREATESTRUCT pcs) (*g_RegisterShellHookWindow)(_hwnd); } else { LOG(TEXT("Shell hooks not available.")); + SetTimer(_hwnd, 0, 200, NULL); } @@ -188,8 +189,6 @@ LRESULT TaskBar::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) default: def: if (nmsg == WM_SHELLHOOK) { - LOG(FmtString(TEXT("SHELLHOOK %x"), wparam)); - switch(wparam) { case HSHELL_WINDOWCREATED: case HSHELL_WINDOWDESTROYED: diff --git a/reactos/subsys/system/explorer/taskbar/traynotify.cpp b/reactos/subsys/system/explorer/taskbar/traynotify.cpp index 8cca2f36525..03e10d1179c 100644 --- a/reactos/subsys/system/explorer/taskbar/traynotify.cpp +++ b/reactos/subsys/system/explorer/taskbar/traynotify.cpp @@ -104,13 +104,23 @@ NotifyInfo::NotifyInfo() #define NID_SIZE_A5 (sizeof(NOTIFYICONDATAA)-sizeof(GUID)) #define NID_SIZE_A3 (sizeof(NOTIFYICONDATAA)-sizeof(GUID)-(128-64)*sizeof(CHAR)) -NotifyInfo& NotifyInfo::operator=(NOTIFYICONDATA* pnid) +bool NotifyInfo::modify(NOTIFYICONDATA* pnid) { - _hWnd = pnid->hWnd; - _uID = pnid->uID; + bool changes = false; - if (pnid->uFlags & NIF_MESSAGE) - _uCallbackMessage = pnid->uCallbackMessage; + if (_hWnd!=pnid->hWnd || _uID!=pnid->uID) { + _hWnd = pnid->hWnd; + _uID = pnid->uID; + + changes = true; + } + + if (pnid->uFlags & NIF_MESSAGE) { + if (_uCallbackMessage != pnid->uCallbackMessage) { + _uCallbackMessage = pnid->uCallbackMessage; + changes = true; + } + } if (pnid->uFlags & NIF_ICON) { // Some applications destroy the icon immediatelly after completing the @@ -119,15 +129,25 @@ NotifyInfo& NotifyInfo::operator=(NOTIFYICONDATA* pnid) DestroyIcon(_hIcon); _hIcon = (HICON) CopyImage(pnid->hIcon, IMAGE_ICON, NOTIFYICON_SIZE, NOTIFYICON_SIZE, 0); + + changes = true; ///@todo compare icon } #ifdef NIF_STATE // as of 21.08.2003 missing in MinGW headers - if (pnid->uFlags & NIF_STATE) - _dwState = (_dwState&~pnid->dwStateMask) | (pnid->dwState&pnid->dwStateMask); + if (pnid->uFlags & NIF_STATE) { + DWORD new_state = (_dwState&~pnid->dwStateMask) | (pnid->dwState&pnid->dwStateMask); + + if (_dwState != new_state) { + _dwState = new_state; + changes = true; + } + } #endif // store tool tip text - if (pnid->uFlags & NIF_TIP) + if (pnid->uFlags & NIF_TIP) { + String new_text; + if (pnid->cbSize==NID_SIZE_W6 || pnid->cbSize==NID_SIZE_W5 || pnid->cbSize==NID_SIZE_W3) { // UNICODE version of NOTIFYICONDATA structure LPCWSTR txt = (LPCWSTR)pnid->szTip; @@ -139,7 +159,12 @@ NotifyInfo& NotifyInfo::operator=(NOTIFYICONDATA* pnid) if (!txt[l]) break; - _tipText.assign(txt, l); + new_text.assign(txt, l); + + if (new_text != _tipText) { + _tipText = new_text; + changes = true; + } } else if (pnid->cbSize==NID_SIZE_A6 || pnid->cbSize==NID_SIZE_A5 || pnid->cbSize==NID_SIZE_A3) { LPCSTR txt = (LPCSTR)pnid->szTip; int max_len = pnid->cbSize==NID_SIZE_A3? 64: 128; @@ -149,20 +174,35 @@ NotifyInfo& NotifyInfo::operator=(NOTIFYICONDATA* pnid) if (!txt[l]) break; - _tipText.assign(txt, l); + new_text.assign(txt, l); + + if (new_text != _tipText) { + _tipText = new_text; + changes = true; + } } + } TCHAR title[MAX_PATH]; - if (GetWindowText(_hWnd, title, MAX_PATH)) - _windowTitle = title; + DWORD pid; + GetWindowThreadProcessId(_hWnd, &pid); - create_name(); + // avoid to send WM_GETTEXT messages to the own process + if (pid != GetCurrentProcessId()) + if (GetWindowText(_hWnd, title, MAX_PATH)) { + if (_windowTitle != title) { + _windowTitle = title; + changes = true; + } + } - ///@todo test for real changes - _lastChange = GetTickCount(); + if (changes) { + create_name(); + _lastChange = GetTickCount(); + } - return *this; + return changes; } @@ -194,7 +234,7 @@ static bool get_hide_clock_from_registry() bool hide_clock = false; // check if the clock should be hidden - if (!RegOpenKey(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StuckRects2"), &hkeyStuckRects) && + if (!RegOpenKey(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StuckRects2"), &hkeyStuckRects) && !RegQueryValueEx(hkeyStuckRects, TEXT("Settings"), 0, NULL, (LPBYTE)buffer, &len) && len==sizeof(buffer) && buffer[0]==sizeof(buffer)) hide_clock = buffer[2] & 0x08? true: false; @@ -338,7 +378,7 @@ HWND NotifyArea::Create(HWND hwndParent) ClientRect clnt(hwndParent); return Window::Create(WINDOW_CREATOR(NotifyArea), WS_EX_STATICEDGE, - wcTrayNotify, TITLE_TRAYNOTIFY, WS_CHILD|WS_VISIBLE, + wcTrayNotify, TITLE_TRAYNOTIFY, WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN, clnt.right-(NOTIFYAREA_WIDTH_DEF+1), 1, NOTIFYAREA_WIDTH_DEF, clnt.bottom-2, hwndParent); } @@ -448,7 +488,11 @@ LRESULT NotifyArea::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) (*AllowSetForegroundWindow)(pid); } - SendMessage(entry._hWnd, entry._uCallbackMessage, entry._uID, nmsg); + // use PostMessage() for notifcation icons of Shell Service Objects in the own process + if (pid == GetCurrentProcessId()) + PostMessage(entry._hWnd, entry._uCallbackMessage, entry._uID, nmsg); + else + SendMessage(entry._hWnd, entry._uCallbackMessage, entry._uID, nmsg); } } else if (_icon_map.erase(entry)) // delete icons without valid owner window @@ -540,18 +584,35 @@ LRESULT NotifyArea::ProcessTrayNotification(int notify_code, NOTIFYICONDATA* pni case NIM_ADD: case NIM_MODIFY: if ((int)pnid->uID >= 0) { ///@todo This is a fix for Windows Task Manager. - NotifyInfo& entry = _icon_map[pnid] = pnid; + NotifyInfo& entry = _icon_map[pnid]; // a new entry? if (entry._idx == -1) entry._idx = ++_next_idx; + /* + NotifyIconMap::iterator found = _icon_map.find(pnid); + NotifyInfo* pentry; + // a new entry? + if (found == _icon_map.end()) { + pentry = &_icon_map[pnid]; + pentry->_idx = ++_next_idx; + } else { + pentry = &found->second; + *pentry = pnid; + } + NotifyInfo& entry = *pentry; + */ + bool changes = entry.modify(pnid); #if NOTIFYICON_VERSION>=3 // as of 21.08.2003 missing in MinGW headers - if (DetermineHideState(entry) && entry._mode==NIM_HIDE) + if (DetermineHideState(entry) && entry._mode==NIM_HIDE) { entry._dwState |= NIS_HIDDEN; + changes = true; + } #endif - UpdateIcons(); ///@todo call only if really changes occurred + if (changes) + UpdateIcons(); ///@todo call only if really changes occurred return TRUE; } @@ -1290,6 +1351,8 @@ void ClockWindow::Paint() { PaintCanvas canvas(_hwnd); + FillRect(canvas, &canvas.rcPaint, GetSysColorBrush(COLOR_BTNFACE)); + BkMode bkmode(canvas, TRANSPARENT); FontSelection font(canvas, GetStockFont(ANSI_VAR_FONT)); diff --git a/reactos/subsys/system/explorer/taskbar/traynotify.h b/reactos/subsys/system/explorer/taskbar/traynotify.h index 40dda6b4feb..b4aa4750631 100644 --- a/reactos/subsys/system/explorer/taskbar/traynotify.h +++ b/reactos/subsys/system/explorer/taskbar/traynotify.h @@ -98,7 +98,7 @@ struct NotifyInfo : public NotifyIconIndex, public NotifyIconConfig friend bool operator<(const NotifyInfo& a, const NotifyInfo& b) {return a._idx < b._idx;} - NotifyInfo& operator=(NOTIFYICONDATA* pnid); + bool modify(NOTIFYICONDATA* pnid); int _idx; // display index HICON _hIcon; diff --git a/reactos/subsys/system/explorer/utility/utility.cpp b/reactos/subsys/system/explorer/utility/utility.cpp index 4e95db4a004..8d6f9ab542f 100644 --- a/reactos/subsys/system/explorer/utility/utility.cpp +++ b/reactos/subsys/system/explorer/utility/utility.cpp @@ -281,11 +281,11 @@ String get_windows_version_str() } else { TCHAR type[80]; DWORD dwBufLen; - HKEY hKey; + HKEY hkey; - if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"), 0, KEY_QUERY_VALUE, &hKey)) { - RegQueryValueEx(hKey, TEXT("ProductType"), NULL, NULL, (LPBYTE)type, &dwBufLen); - RegCloseKey(hKey); + if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"), 0, KEY_QUERY_VALUE, &hkey)) { + RegQueryValueEx(hkey, TEXT("ProductType"), NULL, NULL, (LPBYTE)type, &dwBufLen); + RegCloseKey(hkey); if (!_tcsicmp(TEXT("WINNT"), type)) str += TEXT(" Workstation"); diff --git a/reactos/subsys/system/explorer/utility/utility.h b/reactos/subsys/system/explorer/utility/utility.h index 8a0e5c30e1e..db8af0f91bf 100644 --- a/reactos/subsys/system/explorer/utility/utility.h +++ b/reactos/subsys/system/explorer/utility/utility.h @@ -317,16 +317,22 @@ protected: struct Thread { Thread() - : _alive(false) + : _alive(false), + _destroy(false) { _hThread = INVALID_HANDLE_VALUE; + _evtFinish = CreateEvent(NULL, TRUE, FALSE, NULL); } virtual ~Thread() { Stop(); + CloseHandle(_evtFinish); CloseHandle(_hThread); + + if (_destroy) + delete this; } void Start() @@ -339,6 +345,8 @@ struct Thread void Stop() { + SetEvent(_evtFinish); + if (_alive) { { Lock lock(_crit_sect); @@ -360,7 +368,9 @@ protected: static DWORD WINAPI ThreadProc(void* para); HANDLE _hThread; + HANDLE _evtFinish; bool _alive; + bool _destroy; }; diff --git a/reactos/subsys/system/explorer/utility/window.cpp b/reactos/subsys/system/explorer/utility/window.cpp index f7cf1ae237e..11673f82707 100644 --- a/reactos/subsys/system/explorer/utility/window.cpp +++ b/reactos/subsys/system/explorer/utility/window.cpp @@ -277,7 +277,7 @@ LRESULT CALLBACK Window::WindowWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPAR LRESULT Window::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) { -/*@@TODO: replaced by StartMenu::TrackStartmenu() +/**@todo: replaced by StartMenu::TrackStartmenu() HWND hwnd = _hwnd; // close startup menu and other popup menus @@ -352,7 +352,7 @@ LRESULT CALLBACK SubclassedWindow::SubclassedWndProc(HWND hwnd, UINT nmsg, WPARA LRESULT SubclassedWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) { -/*@@TODO: replaced by StartMenu::TrackStartmenu() +/**@todo: replaced by StartMenu::TrackStartmenu() // close startup menu and other popup menus // This functionality is for tray notification icons missing in MS Windows. if (nmsg == WM_SETFOCUS)