From ed65784ceca1d0730817d89dbda4007efdd8bfc7 Mon Sep 17 00:00:00 2001 From: Martin Fuchs Date: Fri, 29 Aug 2003 10:35:37 +0000 Subject: [PATCH] multithreading for class Window; usage of window map insted of GWL_USERDATA svn path=/trunk/; revision=5915 --- reactos/subsys/system/explorer/explorer.cpp | 14 ++--- .../system/explorer/shell/mainframe.cpp | 25 ++++++++- .../subsys/system/explorer/shell/mainframe.h | 3 ++ .../system/explorer/taskbar/desktopbar.cpp | 2 +- .../system/explorer/taskbar/startmenu.cpp | 38 +++++++++++-- .../system/explorer/taskbar/startmenu.h | 1 + .../system/explorer/taskbar/traynotify.cpp | 2 +- .../subsys/system/explorer/utility/utility.h | 49 +++++++++++++++++ .../subsys/system/explorer/utility/window.cpp | 54 +++++++++++++++---- .../subsys/system/explorer/utility/window.h | 51 +++++++++--------- 10 files changed, 187 insertions(+), 52 deletions(-) diff --git a/reactos/subsys/system/explorer/explorer.cpp b/reactos/subsys/system/explorer/explorer.cpp index 1b573d0bdf2..277c6939396 100644 --- a/reactos/subsys/system/explorer/explorer.cpp +++ b/reactos/subsys/system/explorer/explorer.cpp @@ -88,15 +88,17 @@ void explorer_show_frame(HWND hwndDesktop, int cmdshow) g_Globals._prescan_nodes = false; // create main window - HWND hwndFrame = MainFrame::Create(); + HWND hMainFrame = MainFrame::Create(); - g_Globals._hMainWnd = hwndFrame; + if (hMainFrame) { + g_Globals._hMainWnd = hMainFrame; - ShowWindow(hwndFrame, cmdshow); - UpdateWindow(hwndFrame); + ShowWindow(hMainFrame, cmdshow); + UpdateWindow(hMainFrame); - // Open the first child window after initializing the whole application - PostMessage(hwndFrame, PM_OPEN_WINDOW, TRUE/*mode_explore*/, 0); + // Open the first child window after initializing the whole application + PostMessage(hMainFrame, PM_OPEN_WINDOW, TRUE/*mode_explore*/, 0); + } } diff --git a/reactos/subsys/system/explorer/shell/mainframe.cpp b/reactos/subsys/system/explorer/shell/mainframe.cpp index aee6903104d..4f2c3c8d74b 100644 --- a/reactos/subsys/system/explorer/shell/mainframe.cpp +++ b/reactos/subsys/system/explorer/shell/mainframe.cpp @@ -167,6 +167,28 @@ HWND MainFrame::Create() 0/*hwndDesktop*/, hMenuFrame); } +HWND MainFrame::Create(LPCTSTR path, BOOL mode_explore) +{ + HWND hMainFrame = Create(); + if (!hMainFrame) + return 0; + + ShowWindow(hMainFrame, SW_SHOW); + + MainFrame* pMainFrame = GET_WINDOW(MainFrame, hMainFrame); + + if (pMainFrame) + pMainFrame->CreateChild(path, mode_explore); + + return hMainFrame; +} + + +ChildWindow* MainFrame::CreateChild(LPCTSTR path, BOOL mode_explore) +{ + return reinterpret_cast(SendMessage(_hwnd, PM_OPEN_WINDOW, mode_explore, (LPARAM)path)); +} + LRESULT MainFrame::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) { @@ -237,8 +259,7 @@ LRESULT MainFrame::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) create_info._mode_explore = wparam? true: false; // FileChildWindow::create(_hmdiclient, create_info); - ShellBrowserChild::create(_hmdiclient, create_info); - break;} + return (LRESULT)ShellBrowserChild::create(_hmdiclient, create_info);} case PM_GET_CONTROLWINDOW: if (wparam == FCW_STATUS) diff --git a/reactos/subsys/system/explorer/shell/mainframe.h b/reactos/subsys/system/explorer/shell/mainframe.h index 2f54b1176ef..31abb208e63 100644 --- a/reactos/subsys/system/explorer/shell/mainframe.h +++ b/reactos/subsys/system/explorer/shell/mainframe.h @@ -34,6 +34,9 @@ struct MainFrame : public PreTranslateWindow ~MainFrame(); static HWND Create(); + static HWND Create(LPCTSTR path, BOOL mode_explore=TRUE); + + ChildWindow* CreateChild(LPCTSTR path=NULL, BOOL mode_explore=TRUE); protected: FullScreenParameters _fullscreen; diff --git a/reactos/subsys/system/explorer/taskbar/desktopbar.cpp b/reactos/subsys/system/explorer/taskbar/desktopbar.cpp index ec889e39d0b..ea8868f02d0 100644 --- a/reactos/subsys/system/explorer/taskbar/desktopbar.cpp +++ b/reactos/subsys/system/explorer/taskbar/desktopbar.cpp @@ -252,7 +252,7 @@ LRESULT DesktopBar::ProcessCopyData(COPYDATASTRUCT* pcd) //TODO: process the differnt versions of the NOTIFYICONDATA structure (look at cbSize to decide which one) - NotifyArea* notify_area = static_cast(get_window(_hwndNotify)); + NotifyArea* notify_area = GET_WINDOW(NotifyArea, _hwndNotify); if (notify_area) return notify_area->ProcessTrayNotification(ptr->notify_code, &ptr->nicon_data); diff --git a/reactos/subsys/system/explorer/taskbar/startmenu.cpp b/reactos/subsys/system/explorer/taskbar/startmenu.cpp index c1303f5208d..111a5602ba1 100644 --- a/reactos/subsys/system/explorer/taskbar/startmenu.cpp +++ b/reactos/subsys/system/explorer/taskbar/startmenu.cpp @@ -562,6 +562,36 @@ HWND StartMenuRoot::Create(HWND hwndDesktopBar) } +void StartMenuRoot::TrackStartmenu() +{ + //TODO + + MSG msg; + + while(GetMessage(&msg, 0, 0, 0)) { + try { + if (pretranslate_msg(&msg)) + continue; + + if (dispatch_dialog_msg(&msg)) + continue; + + TranslateMessage(&msg); + + try { + DispatchMessage(&msg); + } catch(COMException& e) { + HandleException(e, g_Globals._hMainWnd); + } + } catch(COMException& e) { + HandleException(e, g_Globals._hMainWnd); + } + } + + //@@return msg.wParam; +} + + LRESULT StartMenuRoot::Init(LPCREATESTRUCT pcs) { // add buttons for entries in _entries @@ -656,12 +686,10 @@ int StartMenuRoot::Command(int id, int code) CreateSubmenu(id, CSIDL_CONTROLS); break; - case IDC_SETTINGS_WND: { //TODO: make more object oriented, e.g introduce a class CabinetWindow + case IDC_SETTINGS_WND: CloseStartMenu(id); - HWND hwndFrame = MainFrame::Create(); - ShowWindow(hwndFrame, SW_SHOW); - SendMessage(hwndFrame, PM_OPEN_WINDOW, FALSE/*mode_explore*/, (LPARAM)_T("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}")); - break;} + MainFrame::Create(_T("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}"), FALSE); + break; case IDC_FAVORITES: CreateSubmenu(id, CSIDL_FAVORITES); diff --git a/reactos/subsys/system/explorer/taskbar/startmenu.h b/reactos/subsys/system/explorer/taskbar/startmenu.h index c71e24e04cd..49472fafec8 100644 --- a/reactos/subsys/system/explorer/taskbar/startmenu.h +++ b/reactos/subsys/system/explorer/taskbar/startmenu.h @@ -206,6 +206,7 @@ struct StartMenuRoot : public StartMenu StartMenuRoot(HWND hwnd); static HWND Create(HWND hwndDesktopBar); + void TrackStartmenu(); protected: LRESULT Init(LPCREATESTRUCT pcs); diff --git a/reactos/subsys/system/explorer/taskbar/traynotify.cpp b/reactos/subsys/system/explorer/taskbar/traynotify.cpp index 175a6848a2c..759df99f6d4 100644 --- a/reactos/subsys/system/explorer/taskbar/traynotify.cpp +++ b/reactos/subsys/system/explorer/taskbar/traynotify.cpp @@ -124,7 +124,7 @@ LRESULT NotifyArea::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) case WM_TIMER: { TimerTick(); - ClockWindow* clock_window = static_cast(get_window(_hwndClock)); + ClockWindow* clock_window = GET_WINDOW(ClockWindow, _hwndClock); if (clock_window) clock_window->TimerTick(); diff --git a/reactos/subsys/system/explorer/utility/utility.h b/reactos/subsys/system/explorer/utility/utility.h index 56088d679ac..3c19ffa06ea 100644 --- a/reactos/subsys/system/explorer/utility/utility.h +++ b/reactos/subsys/system/explorer/utility/utility.h @@ -124,6 +124,55 @@ protected: }; +struct WindowHandle +{ + WindowHandle(HWND hwnd=0) + : _hwnd(hwnd) {} + + operator HWND() const {return _hwnd;} + HWND* operator&() {return &_hwnd;} + +protected: + HWND _hwnd; +}; + + + /// critical section wrapper + +struct CritSect : public CRITICAL_SECTION +{ + CritSect() + { + InitializeCriticalSection(this); + } + + ~CritSect() + { + DeleteCriticalSection(this); + } +}; + + + /// Lock protects a code section utilizing a critical section + +struct Lock +{ + Lock(CritSect& crit_sect) + : _crit_sect(crit_sect) + { + EnterCriticalSection(&crit_sect); + } + + ~Lock() + { + LeaveCriticalSection(&_crit_sect); + } + +protected: + CritSect& _crit_sect; +}; + + // window utilities struct ClientRect : public RECT diff --git a/reactos/subsys/system/explorer/utility/window.cpp b/reactos/subsys/system/explorer/utility/window.cpp index 4720bff4fb4..0f72b1d4002 100644 --- a/reactos/subsys/system/explorer/utility/window.cpp +++ b/reactos/subsys/system/explorer/utility/window.cpp @@ -57,9 +57,30 @@ IconWindowClass::IconWindowClass(LPCTSTR classname, UINT nid, UINT style, WNDPRO } -HHOOK Window::s_hcbtHook = 0; -Window::CREATORFUNC Window::s_window_creator = NULL; -const void* Window::s_new_info = NULL; +HHOOK Window::s_hcbtHook = 0; + +Window::CREATORFUNC Window::s_window_creator = NULL; +const void* Window::s_new_info = NULL; +CritSect Window::s_create_crit_sect; + +Window::WindowMap Window::s_wnd_map; +CritSect Window::s_map_crit_sect; + + +Window::Window(HWND hwnd) + : WindowHandle(hwnd) +{ + Lock lock(s_map_crit_sect); // protect access to s_wnd_map + + s_wnd_map[_hwnd] = this; +} + +Window::~Window() +{ + Lock lock(s_map_crit_sect); // protect access to s_wnd_map + + s_wnd_map.erase(_hwnd); +} HWND Window::Create(CREATORFUNC creator, DWORD dwExStyle, @@ -67,6 +88,8 @@ HWND Window::Create(CREATORFUNC creator, DWORD dwExStyle, DWORD dwStyle, int x, int y, int w, int h, HWND hwndParent, HMENU hMenu, LPVOID lpParam) { + Lock lock(s_create_crit_sect); // protect access to s_window_creator and s_new_info + s_window_creator = creator; s_new_info = NULL; @@ -80,6 +103,8 @@ HWND Window::Create(CREATORFUNC creator, const void* info, DWORD dwExStyle, DWORD dwStyle, int x, int y, int w, int h, HWND hwndParent, HMENU hMenu, LPVOID lpParam) { + Lock lock(s_create_crit_sect); // protect access to s_window_creator and s_new_info + s_window_creator = creator; s_new_info = info; @@ -93,6 +118,8 @@ static Window* s_new_child_wnd = NULL; Window* Window::create_mdi_child(HWND hmdiclient, const MDICREATESTRUCT& mcs, CREATORFUNC creator, const void* info) { + Lock lock(s_create_crit_sect); // protect access to s_window_creator and s_new_info + s_window_creator = creator; s_new_info = info; s_new_child_wnd = NULL; @@ -132,12 +159,18 @@ LRESULT CALLBACK Window::CBTHookProc(int code, WPARAM wparam, LPARAM lparam) Window* Window::get_window(HWND hwnd) { - Window* wnd = (Window*) GetWindowLong(hwnd, GWL_USERDATA); + { + Lock lock(s_map_crit_sect); // protect access to s_wnd_map - if (wnd) - return wnd; + WindowMap::const_iterator found = s_wnd_map.find(hwnd); + + if (found!=s_wnd_map.end()) + return found->second; + } if (s_window_creator) { // protect for recursion + Lock lock(s_create_crit_sect); // protect access to s_window_creator and s_new_info + const void* info = s_new_info; s_new_info = NULL; @@ -145,12 +178,12 @@ Window* Window::get_window(HWND hwnd) s_window_creator = NULL; if (info) - wnd = window_creator(hwnd, info); + return window_creator(hwnd, info); else - wnd = CREATORFUNC_NO_INFO(window_creator)(hwnd); + return CREATORFUNC_NO_INFO(window_creator)(hwnd); } - return wnd; + return NULL; } @@ -191,11 +224,12 @@ LRESULT Window::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) { HWND hwnd = _hwnd; +/*@@TODO: replace 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) CancelModes((HWND)wparam); //@@ erronesly cancels desktop bar resize when switching from another process - +*/ return DefWindowProc(hwnd, nmsg, wparam, lparam); } diff --git a/reactos/subsys/system/explorer/utility/window.h b/reactos/subsys/system/explorer/utility/window.h index f17abd69fd0..e2be7e966dc 100644 --- a/reactos/subsys/system/explorer/utility/window.h +++ b/reactos/subsys/system/explorer/utility/window.h @@ -45,19 +45,6 @@ typedef set WindowSet; */ -struct WindowHandle -{ - WindowHandle(HWND hwnd=0) - : _hwnd(hwnd) {} - - operator HWND() const {return _hwnd;} - HWND* operator&() {return &_hwnd;} - -protected: - HWND _hwnd; -}; - - /** Class Window is the base class for several C++ window wrapper classes. Window objects are allocated from the heap. They are automatically freed @@ -65,19 +52,11 @@ protected: */ struct Window : public WindowHandle { - Window(HWND hwnd) - : WindowHandle(hwnd) - { - // store "this" pointer as user data - SetWindowLong(hwnd, GWL_USERDATA, (LONG)this); - } + Window(HWND hwnd); + virtual ~Window(); - virtual ~Window() - { - // empty user data field - SetWindowLong(_hwnd, GWL_USERDATA, 0); - } + typedef map WindowMap; typedef Window* (*CREATORFUNC)(HWND, const void*); typedef Window* (*CREATORFUNC_NO_INFO)(HWND); @@ -95,8 +74,12 @@ struct Window : public WindowHandle static Window* create_mdi_child(HWND hmdiclient, const MDICREATESTRUCT& mcs, CREATORFUNC creator, const void* info=NULL); static LRESULT CALLBACK WindowWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam); - static Window* get_window(HWND hwnd); + static Window* get_window(HWND hwnd); +#ifndef _MSC_VER + template static WNDCLASS* get_window(HWND hwnd) {return static_cast(get_window(hwnd));} +#define GET_WINDOW(WNDCLASS, hwnd) Window::get_window(hwnd) +#endif static void register_pretranslate(HWND hwnd); static void unregister_pretranslate(HWND hwnd); @@ -122,8 +105,12 @@ protected: virtual int Notify(int id, NMHDR* pnmh); // WM_NOTIFY processing - static const void* s_new_info; //TODO: protect for multithreaded access - static CREATORFUNC s_window_creator; //TODO: protect for multithreaded access + static WindowMap s_wnd_map; + static CritSect s_map_crit_sect; + + static const void* s_new_info; + static CREATORFUNC s_window_creator; + static CritSect s_create_crit_sect; // MDI child creation static HHOOK s_hcbtHook; @@ -134,6 +121,16 @@ protected: }; +#ifdef _MSC_VER +template struct GetWindowHelper { + static WNDCLASS* get_window(HWND hwnd) { + return static_cast(Window::get_window(hwnd)); + } +}; +#define GET_WINDOW(WNDCLASS, hwnd) GetWindowHelper::get_window(hwnd) +#endif + + /** SubclassedWindow is used to wrap already existing window handles into C++ Window objects. To construct a object, use the "new" operator