launch all registered Shell Service Objects (Systray, network icons, ...)

svn path=/trunk/; revision=14361
This commit is contained in:
Martin Fuchs 2005-03-28 09:16:50 +00:00
parent f9a85ac5fb
commit 9b8f8ea446
20 changed files with 332 additions and 68 deletions

View file

@ -45,10 +45,11 @@ TARGET_OBJECTS := \
shell/pane.o \ shell/pane.o \
shell/regfs.o \ shell/regfs.o \
shell/shellbrowser.o \ shell/shellbrowser.o \
shell/startup.o \
shell/unixfs.o \ shell/unixfs.o \
shell/webchild.o \ shell/webchild.o \
shell/winfs.o \ shell/winfs.o \
services/startup.o \
services/shellservices.o \
taskbar/desktopbar.o \ taskbar/desktopbar.o \
taskbar/taskbar.o \ taskbar/taskbar.o \
taskbar/startmenu.o \ taskbar/startmenu.o \

View file

@ -38,7 +38,7 @@ CXXFLAGS = $(CFLAGS)
EXEC_SUFFIX = .exe EXEC_SUFFIX = .exe
RES_SUFFIX = .coff RES_SUFFIX = .coff
VPATH = shell utility taskbar desktop dialogs VPATH = shell utility taskbar desktop dialogs services
PROGRAM = explorer PROGRAM = explorer
@ -51,6 +51,7 @@ OBJECTS = \
window.o \ window.o \
dragdropimpl.o \ dragdropimpl.o \
shellbrowserimpl.o \ shellbrowserimpl.o \
shellservices.o \
explorer.o \ explorer.o \
entries.o \ entries.o \
winfs.o \ winfs.o \

View file

@ -39,7 +39,7 @@ CXXFLAGS = $(CFLAGS)
EXEC_SUFFIX = .exe EXEC_SUFFIX = .exe
RES_SUFFIX = .coff RES_SUFFIX = .coff
VPATH = shell utility taskbar desktop dialogs VPATH = shell utility taskbar desktop dialogs services
PROGRAM = explorer PROGRAM = explorer
@ -69,6 +69,7 @@ OBJECTS = \
desktopbar.o \ desktopbar.o \
taskbar.o \ taskbar.o \
startmenu.o \ startmenu.o \
shellservices.o \
traynotify.o \ traynotify.o \
quicklaunch.o \ quicklaunch.o \
favorites.o \ favorites.o \

View file

@ -10,7 +10,7 @@ EXTRA_OBJS = notifyhook.dll libexpat.dll
EXTRALIBS = $(LIBUUID) EXTRALIBS = $(LIBUUID)
C_SRCS = \ C_SRCS = \
shell/startup.c \ services/startup.c \
utility/splitpath.c utility/splitpath.c
CPP_SRCS = \ CPP_SRCS = \
@ -34,6 +34,7 @@ CPP_SRCS = \
shell/regfs.cpp \ shell/regfs.cpp \
shell/fatfs.cpp \ shell/fatfs.cpp \
shell/webchild.cpp \ shell/webchild.cpp \
services/shellservices.cpp \
taskbar/desktopbar.cpp \ taskbar/desktopbar.cpp \
taskbar/taskbar.cpp \ taskbar/taskbar.cpp \
taskbar/startmenu.cpp \ taskbar/startmenu.cpp \

View file

@ -41,6 +41,8 @@
#include "dialogs/settings.h" // for MdiSdiDlg #include "dialogs/settings.h" // for MdiSdiDlg
#include "services/shellservices.h"
extern "C" int initialize_gdb_stub(); // start up GDB stub 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" // another undocumented event: "Global\\msgina: ReturnToWelcome"
if (!SetShellReadyEvent(TEXT("msgina: ShellReadyEvent"))) if (!SetShellReadyEvent(TEXT("msgina: ShellReadyEvent")))
SetShellReadyEvent(TEXT("Global\\msgina: ShellReadyEvent")); SetShellReadyEvent(TEXT("Global\\msgina: ShellReadyEvent"));
}
if (!any_desktop_running) {
// launch the shell DDE server // launch the shell DDE server
if (g_SHDOCVW_ShellDDEInit) if (g_SHDOCVW_ShellDDEInit)
(*g_SHDOCVW_ShellDDEInit)(TRUE); (*g_SHDOCVW_ShellDDEInit)(TRUE);
@ -868,18 +872,31 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdL
g_Globals.read_persistent(); g_Globals.read_persistent();
if (startup_desktop) { if (startup_desktop) {
WaitCursor wait;
g_Globals._desktops.init(); g_Globals._desktops.init();
g_Globals._hwndDesktop = DesktopWindow::Create(); g_Globals._hwndDesktop = DesktopWindow::Create();
#ifdef _USE_HDESK #ifdef _USE_HDESK
g_Globals._desktops.get_current_Desktop()->_hwndDesktop = g_Globals._hwndDesktop; g_Globals._desktops.get_current_Desktop()->_hwndDesktop = g_Globals._hwndDesktop;
#endif #endif
}
/**TODO launching autostart programs can be moved into a background thread. */ if (g_Globals._hwndDesktop)
if (autostart) { g_Globals._desktop_mode = true;
char* argv[] = {"", "s"}; // call startup routine in SESSION_START mode
startup(2, argv); 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 */ /**TODO fix command line handling */
@ -888,17 +905,21 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdL
lpCmdLine[_tcslen(lpCmdLine)-1] = '\0'; lpCmdLine[_tcslen(lpCmdLine)-1] = '\0';
} }
if (g_Globals._hwndDesktop)
g_Globals._desktop_mode = true;
int ret = explorer_main(hInstance, lpCmdLine, nShowCmd); int ret = explorer_main(hInstance, lpCmdLine, nShowCmd);
// write configuration file // write configuration file
g_Globals.write_persistent(); g_Globals.write_persistent();
// shutdown the shell DDE server if (pSSOThread) {
if (g_SHDOCVW_ShellDDEInit) pSSOThread->Stop();
(*g_SHDOCVW_ShellDDEInit)(FALSE); delete pSSOThread;
}
if (!any_desktop_running) {
// shutdown the shell DDE server
if (g_SHDOCVW_ShellDDEInit)
(*g_SHDOCVW_ShellDDEInit)(FALSE);
}
return ret; return ret;
} }

View file

@ -702,11 +702,6 @@ SOURCE=.\shell\shellfs.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\shell\startup.c
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
# Begin Source File
SOURCE=.\shell\unixfs.cpp SOURCE=.\shell\unixfs.cpp
# PROP Exclude_From_Build 1 # PROP Exclude_From_Build 1
# End Source File # End Source File
@ -785,5 +780,22 @@ SOURCE=.\precomp.cpp
SOURCE=.\precomp.h SOURCE=.\precomp.h
# End Source File # End Source File
# End Group # 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 Target
# End Project # End Project

View file

@ -31,9 +31,6 @@ extern "C" {
#endif #endif
// launch start programs
extern int startup(int argc, char *argv[]);
// explorer main routine // explorer main routine
extern int explorer_main(HINSTANCE hinstance, LPTSTR lpCmdLine, int cmdshow); extern int explorer_main(HINSTANCE hinstance, LPTSTR lpCmdLine, int cmdshow);

View file

@ -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<SIfacePtr<IOleCommandTarget>*> 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<IOleCommandTarget>* sso_ptr = new SIfacePtr<IOleCommandTarget>;
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<IOleCommandTarget>* sso_ptr = *it;
(*sso_ptr)->Exec(&CGID_ShellServiceObject, OLECMDID_SAVE, OLECMDEXECOPT_DODEFAULT, NULL, NULL);
delete sso_ptr;
}
return 0;
}

View file

@ -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();
};

View file

@ -163,7 +163,7 @@ void Pane::init()
HKEY hkeyExplorer = 0; HKEY hkeyExplorer = 0;
DWORD len = sizeof(_clrCompressed); 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)) RegQueryValueEx(hkeyExplorer, TEXT("AltColor"), 0, NULL, (LPBYTE)&_clrCompressed, &len) || len!=sizeof(_clrCompressed))
_clrCompressed = RGB(0,0,255); _clrCompressed = RGB(0,0,255);

View file

@ -43,9 +43,9 @@ void RegDirectory::read_directory(int scan_flags)
_tcscpy(buffer, (LPCTSTR)_path); _tcscpy(buffer, (LPCTSTR)_path);
LPTSTR pname = buffer + _tcslen(buffer); 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] != '\\') if (pname[-1] != '\\')
*pname++ = '\\'; *pname++ = '\\';
@ -60,7 +60,7 @@ void RegDirectory::read_directory(int scan_flags)
DWORD name_len = MAX_PATH; DWORD name_len = MAX_PATH;
DWORD class_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; break;
w32fd.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY; w32fd.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
@ -88,7 +88,7 @@ void RegDirectory::read_directory(int scan_flags)
TCHAR value[MAX_PATH]; TCHAR value[MAX_PATH];
LONG value_len = sizeof(value); 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)); memset(&w32fd, 0, sizeof(WIN32_FIND_DATA));
lstrcpy(w32fd.cFileName, TEXT("(Default)")); lstrcpy(w32fd.cFileName, TEXT("(Default)"));
@ -114,7 +114,7 @@ void RegDirectory::read_directory(int scan_flags)
for(int idx=0; ; ++idx) { for(int idx=0; ; ++idx) {
DWORD name_len = MAX_PATH; 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; break;
memset(&w32fd, 0, sizeof(WIN32_FIND_DATA)); memset(&w32fd, 0, sizeof(WIN32_FIND_DATA));
@ -147,7 +147,7 @@ void RegDirectory::read_directory(int scan_flags)
TCHAR value[MAX_PATH]; TCHAR value[MAX_PATH];
DWORD value_len = sizeof(value); 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) if (type==REG_SZ || type==REG_EXPAND_SZ || type==REG_LINK)
entry->_content = _tcsdup(value); entry->_content = _tcsdup(value);
else if (type == REG_DWORD) { else if (type == REG_DWORD) {
@ -171,7 +171,7 @@ void RegDirectory::read_directory(int scan_flags)
if (last) if (last)
last->_next = NULL; last->_next = NULL;
RegCloseKey(hKey); RegCloseKey(hkey);
} }
_down = first_entry; _down = first_entry;

View file

@ -41,7 +41,11 @@
DesktopBar::DesktopBar(HWND hwnd) DesktopBar::DesktopBar(HWND hwnd)
: super(hwnd), : super(hwnd),
#ifdef _ROS_
_trayIcon(hwnd, ID_TRAY_VOLUME) _trayIcon(hwnd, ID_TRAY_VOLUME)
#else
WM_TASKBARCREATED(RegisterWindowMessage(WINMSG_TASKBARCREATED))
#endif
{ {
SetWindowIcon(hwnd, IDI_REACTOS/*IDI_SEARCH*/); // icon in for TrayNotifyDlg SetWindowIcon(hwnd, IDI_REACTOS/*IDI_SEARCH*/); // icon in for TrayNotifyDlg
@ -107,6 +111,12 @@ LRESULT DesktopBar::Init(LPCREATESTRUCT pcs)
// create tray notification area // create tray notification area
_hwndNotify = NotifyArea::Create(_hwnd); _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); _hwndQuickLaunch = QuickLaunchBar::Create(_hwnd);
// create rebar window to manage task and quick launch bar // 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); SendMessage(_hwndrebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand);
#endif #endif
RegisterHotkeys();
// notify all top level windows about the successfully created desktop bar RegisterHotkeys();
PostMessage(HWND_BROADCAST, WM_TASKBARCREATED, 0, 0);
// prepare Startmenu, but hide it for now // prepare Startmenu, but hide it for now
_startMenuRoot = GET_WINDOW(StartMenuRoot, StartMenuRoot::Create(_hwnd)); _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); PostMessage(_hwndQuickLaunch, PM_UPDATE_DESKTOP, desktop_idx, 0);
break;} break;}
#ifdef _ROS_
case ID_TRAY_VOLUME: case ID_TRAY_VOLUME:
launch_file(_hwnd, TEXT("sndvol32.exe"), SW_SHOWNORMAL); // launch volume control application launch_file(_hwnd, TEXT("sndvol32.exe"), SW_SHOWNORMAL); // launch volume control application
break; break;
@ -339,6 +348,7 @@ int DesktopBar::Command(int id, int code)
case ID_VOLUME_PROPERTIES: case ID_VOLUME_PROPERTIES:
launch_cpanel(_hwnd, TEXT("mmsys.cpl")); launch_cpanel(_hwnd, TEXT("mmsys.cpl"));
break; break;
#endif
default: default:
if (_hwndQuickLaunch) if (_hwndQuickLaunch)
@ -381,6 +391,8 @@ LRESULT DesktopBar::ProcessCopyData(COPYDATASTRUCT* pcd)
} }
#ifdef _ROS_
void DesktopBar::AddTrayIcons() void DesktopBar::AddTrayIcons()
{ {
_trayIcon.Add(SmallIcon(IDI_SPEAKER), ResString(IDS_VOLUME)); _trayIcon.Add(SmallIcon(IDI_SPEAKER), ResString(IDS_VOLUME));
@ -410,3 +422,5 @@ void DesktopBar::TrayDblClick(UINT id, int btn)
break; break;
} }
} }
#endif

View file

@ -61,11 +61,20 @@
/// desktop bar window, also known as "system tray" /// desktop bar window, also known as "system tray"
struct DesktopBar : public TrayIconControllerTemplate< struct DesktopBar : public
OwnerDrawParent<Window> > #ifdef _ROS_
TrayIconControllerTemplate<
OwnerDrawParent<Window> >
#else
OwnerDrawParent<Window>
#endif
{ {
#ifdef _ROS_
typedef TrayIconControllerTemplate< typedef TrayIconControllerTemplate<
OwnerDrawParent<Window> > super; OwnerDrawParent<Window> > super;
#else
typedef OwnerDrawParent<Window> super;
#endif
DesktopBar(HWND hwnd); DesktopBar(HWND hwnd);
~DesktopBar(); ~DesktopBar();
@ -93,9 +102,13 @@ protected:
struct StartMenuRoot* _startMenuRoot; struct StartMenuRoot* _startMenuRoot;
#ifdef _ROS_
TrayIcon _trayIcon; TrayIcon _trayIcon;
void AddTrayIcons(); void AddTrayIcons();
virtual void TrayClick(UINT id, int btn); virtual void TrayClick(UINT id, int btn);
virtual void TrayDblClick(UINT id, int btn); virtual void TrayDblClick(UINT id, int btn);
#else
const UINT WM_TASKBARCREATED;
#endif
}; };

View file

@ -144,6 +144,7 @@ LRESULT TaskBar::Init(LPCREATESTRUCT pcs)
(*g_RegisterShellHookWindow)(_hwnd); (*g_RegisterShellHookWindow)(_hwnd);
} else { } else {
LOG(TEXT("Shell hooks not available.")); LOG(TEXT("Shell hooks not available."));
SetTimer(_hwnd, 0, 200, NULL); SetTimer(_hwnd, 0, 200, NULL);
} }
@ -188,8 +189,6 @@ LRESULT TaskBar::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
default: def: default: def:
if (nmsg == WM_SHELLHOOK) { if (nmsg == WM_SHELLHOOK) {
LOG(FmtString(TEXT("SHELLHOOK %x"), wparam));
switch(wparam) { switch(wparam) {
case HSHELL_WINDOWCREATED: case HSHELL_WINDOWCREATED:
case HSHELL_WINDOWDESTROYED: case HSHELL_WINDOWDESTROYED:

View file

@ -104,13 +104,23 @@ NotifyInfo::NotifyInfo()
#define NID_SIZE_A5 (sizeof(NOTIFYICONDATAA)-sizeof(GUID)) #define NID_SIZE_A5 (sizeof(NOTIFYICONDATAA)-sizeof(GUID))
#define NID_SIZE_A3 (sizeof(NOTIFYICONDATAA)-sizeof(GUID)-(128-64)*sizeof(CHAR)) #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; bool changes = false;
_uID = pnid->uID;
if (pnid->uFlags & NIF_MESSAGE) if (_hWnd!=pnid->hWnd || _uID!=pnid->uID) {
_uCallbackMessage = pnid->uCallbackMessage; _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) { if (pnid->uFlags & NIF_ICON) {
// Some applications destroy the icon immediatelly after completing the // Some applications destroy the icon immediatelly after completing the
@ -119,15 +129,25 @@ NotifyInfo& NotifyInfo::operator=(NOTIFYICONDATA* pnid)
DestroyIcon(_hIcon); DestroyIcon(_hIcon);
_hIcon = (HICON) CopyImage(pnid->hIcon, IMAGE_ICON, NOTIFYICON_SIZE, NOTIFYICON_SIZE, 0); _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 #ifdef NIF_STATE // as of 21.08.2003 missing in MinGW headers
if (pnid->uFlags & NIF_STATE) if (pnid->uFlags & NIF_STATE) {
_dwState = (_dwState&~pnid->dwStateMask) | (pnid->dwState&pnid->dwStateMask); DWORD new_state = (_dwState&~pnid->dwStateMask) | (pnid->dwState&pnid->dwStateMask);
if (_dwState != new_state) {
_dwState = new_state;
changes = true;
}
}
#endif #endif
// store tool tip text // 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) { if (pnid->cbSize==NID_SIZE_W6 || pnid->cbSize==NID_SIZE_W5 || pnid->cbSize==NID_SIZE_W3) {
// UNICODE version of NOTIFYICONDATA structure // UNICODE version of NOTIFYICONDATA structure
LPCWSTR txt = (LPCWSTR)pnid->szTip; LPCWSTR txt = (LPCWSTR)pnid->szTip;
@ -139,7 +159,12 @@ NotifyInfo& NotifyInfo::operator=(NOTIFYICONDATA* pnid)
if (!txt[l]) if (!txt[l])
break; 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) { } else if (pnid->cbSize==NID_SIZE_A6 || pnid->cbSize==NID_SIZE_A5 || pnid->cbSize==NID_SIZE_A3) {
LPCSTR txt = (LPCSTR)pnid->szTip; LPCSTR txt = (LPCSTR)pnid->szTip;
int max_len = pnid->cbSize==NID_SIZE_A3? 64: 128; int max_len = pnid->cbSize==NID_SIZE_A3? 64: 128;
@ -149,20 +174,35 @@ NotifyInfo& NotifyInfo::operator=(NOTIFYICONDATA* pnid)
if (!txt[l]) if (!txt[l])
break; break;
_tipText.assign(txt, l); new_text.assign(txt, l);
if (new_text != _tipText) {
_tipText = new_text;
changes = true;
}
} }
}
TCHAR title[MAX_PATH]; TCHAR title[MAX_PATH];
if (GetWindowText(_hWnd, title, MAX_PATH)) DWORD pid;
_windowTitle = title; 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 if (changes) {
_lastChange = GetTickCount(); create_name();
_lastChange = GetTickCount();
}
return *this; return changes;
} }
@ -194,7 +234,7 @@ static bool get_hide_clock_from_registry()
bool hide_clock = false; bool hide_clock = false;
// check if the clock should be hidden // 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) && !RegQueryValueEx(hkeyStuckRects, TEXT("Settings"), 0, NULL, (LPBYTE)buffer, &len) &&
len==sizeof(buffer) && buffer[0]==sizeof(buffer)) len==sizeof(buffer) && buffer[0]==sizeof(buffer))
hide_clock = buffer[2] & 0x08? true: false; hide_clock = buffer[2] & 0x08? true: false;
@ -338,7 +378,7 @@ HWND NotifyArea::Create(HWND hwndParent)
ClientRect clnt(hwndParent); ClientRect clnt(hwndParent);
return Window::Create(WINDOW_CREATOR(NotifyArea), WS_EX_STATICEDGE, 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); 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); (*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 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_ADD:
case NIM_MODIFY: case NIM_MODIFY:
if ((int)pnid->uID >= 0) { ///@todo This is a fix for Windows Task Manager. 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? // a new entry?
if (entry._idx == -1) if (entry._idx == -1)
entry._idx = ++_next_idx; 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 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; entry._dwState |= NIS_HIDDEN;
changes = true;
}
#endif #endif
UpdateIcons(); ///@todo call only if really changes occurred if (changes)
UpdateIcons(); ///@todo call only if really changes occurred
return TRUE; return TRUE;
} }
@ -1290,6 +1351,8 @@ void ClockWindow::Paint()
{ {
PaintCanvas canvas(_hwnd); PaintCanvas canvas(_hwnd);
FillRect(canvas, &canvas.rcPaint, GetSysColorBrush(COLOR_BTNFACE));
BkMode bkmode(canvas, TRANSPARENT); BkMode bkmode(canvas, TRANSPARENT);
FontSelection font(canvas, GetStockFont(ANSI_VAR_FONT)); FontSelection font(canvas, GetStockFont(ANSI_VAR_FONT));

View file

@ -98,7 +98,7 @@ struct NotifyInfo : public NotifyIconIndex, public NotifyIconConfig
friend bool operator<(const NotifyInfo& a, const NotifyInfo& b) friend bool operator<(const NotifyInfo& a, const NotifyInfo& b)
{return a._idx < b._idx;} {return a._idx < b._idx;}
NotifyInfo& operator=(NOTIFYICONDATA* pnid); bool modify(NOTIFYICONDATA* pnid);
int _idx; // display index int _idx; // display index
HICON _hIcon; HICON _hIcon;

View file

@ -281,11 +281,11 @@ String get_windows_version_str()
} else { } else {
TCHAR type[80]; TCHAR type[80];
DWORD dwBufLen; DWORD dwBufLen;
HKEY hKey; HKEY hkey;
if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"), 0, KEY_QUERY_VALUE, &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); RegQueryValueEx(hkey, TEXT("ProductType"), NULL, NULL, (LPBYTE)type, &dwBufLen);
RegCloseKey(hKey); RegCloseKey(hkey);
if (!_tcsicmp(TEXT("WINNT"), type)) if (!_tcsicmp(TEXT("WINNT"), type))
str += TEXT(" Workstation"); str += TEXT(" Workstation");

View file

@ -317,16 +317,22 @@ protected:
struct Thread struct Thread
{ {
Thread() Thread()
: _alive(false) : _alive(false),
_destroy(false)
{ {
_hThread = INVALID_HANDLE_VALUE; _hThread = INVALID_HANDLE_VALUE;
_evtFinish = CreateEvent(NULL, TRUE, FALSE, NULL);
} }
virtual ~Thread() virtual ~Thread()
{ {
Stop(); Stop();
CloseHandle(_evtFinish);
CloseHandle(_hThread); CloseHandle(_hThread);
if (_destroy)
delete this;
} }
void Start() void Start()
@ -339,6 +345,8 @@ struct Thread
void Stop() void Stop()
{ {
SetEvent(_evtFinish);
if (_alive) { if (_alive) {
{ {
Lock lock(_crit_sect); Lock lock(_crit_sect);
@ -360,7 +368,9 @@ protected:
static DWORD WINAPI ThreadProc(void* para); static DWORD WINAPI ThreadProc(void* para);
HANDLE _hThread; HANDLE _hThread;
HANDLE _evtFinish;
bool _alive; bool _alive;
bool _destroy;
}; };

View file

@ -277,7 +277,7 @@ LRESULT CALLBACK Window::WindowWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPAR
LRESULT Window::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) LRESULT Window::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
{ {
/*@@TODO: replaced by StartMenu::TrackStartmenu() /**@todo: replaced by StartMenu::TrackStartmenu()
HWND hwnd = _hwnd; HWND hwnd = _hwnd;
// close startup menu and other popup menus // 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) 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 // close startup menu and other popup menus
// This functionality is for tray notification icons missing in MS Windows. // This functionality is for tray notification icons missing in MS Windows.
if (nmsg == WM_SETFOCUS) if (nmsg == WM_SETFOCUS)