multithreading for class Window; usage of window map insted of GWL_USERDATA

svn path=/trunk/; revision=5915
This commit is contained in:
Martin Fuchs 2003-08-29 10:35:37 +00:00
parent 9665ee6bdb
commit ed65784cec
10 changed files with 187 additions and 52 deletions

View file

@ -88,15 +88,17 @@ void explorer_show_frame(HWND hwndDesktop, int cmdshow)
g_Globals._prescan_nodes = false; g_Globals._prescan_nodes = false;
// create main window // create main window
HWND hwndFrame = MainFrame::Create(); HWND hMainFrame = MainFrame::Create();
g_Globals._hMainWnd = hwndFrame; if (hMainFrame) {
g_Globals._hMainWnd = hMainFrame;
ShowWindow(hwndFrame, cmdshow); ShowWindow(hMainFrame, cmdshow);
UpdateWindow(hwndFrame); UpdateWindow(hMainFrame);
// Open the first child window after initializing the whole application // Open the first child window after initializing the whole application
PostMessage(hwndFrame, PM_OPEN_WINDOW, TRUE/*mode_explore*/, 0); PostMessage(hMainFrame, PM_OPEN_WINDOW, TRUE/*mode_explore*/, 0);
}
} }

View file

@ -167,6 +167,28 @@ HWND MainFrame::Create()
0/*hwndDesktop*/, hMenuFrame); 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<ChildWindow*>(SendMessage(_hwnd, PM_OPEN_WINDOW, mode_explore, (LPARAM)path));
}
LRESULT MainFrame::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) 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; create_info._mode_explore = wparam? true: false;
// FileChildWindow::create(_hmdiclient, create_info); // FileChildWindow::create(_hmdiclient, create_info);
ShellBrowserChild::create(_hmdiclient, create_info); return (LRESULT)ShellBrowserChild::create(_hmdiclient, create_info);}
break;}
case PM_GET_CONTROLWINDOW: case PM_GET_CONTROLWINDOW:
if (wparam == FCW_STATUS) if (wparam == FCW_STATUS)

View file

@ -34,6 +34,9 @@ struct MainFrame : public PreTranslateWindow
~MainFrame(); ~MainFrame();
static HWND Create(); static HWND Create();
static HWND Create(LPCTSTR path, BOOL mode_explore=TRUE);
ChildWindow* CreateChild(LPCTSTR path=NULL, BOOL mode_explore=TRUE);
protected: protected:
FullScreenParameters _fullscreen; FullScreenParameters _fullscreen;

View file

@ -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) //TODO: process the differnt versions of the NOTIFYICONDATA structure (look at cbSize to decide which one)
NotifyArea* notify_area = static_cast<NotifyArea*>(get_window(_hwndNotify)); NotifyArea* notify_area = GET_WINDOW(NotifyArea, _hwndNotify);
if (notify_area) if (notify_area)
return notify_area->ProcessTrayNotification(ptr->notify_code, &ptr->nicon_data); return notify_area->ProcessTrayNotification(ptr->notify_code, &ptr->nicon_data);

View file

@ -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) LRESULT StartMenuRoot::Init(LPCREATESTRUCT pcs)
{ {
// add buttons for entries in _entries // add buttons for entries in _entries
@ -656,12 +686,10 @@ int StartMenuRoot::Command(int id, int code)
CreateSubmenu(id, CSIDL_CONTROLS); CreateSubmenu(id, CSIDL_CONTROLS);
break; break;
case IDC_SETTINGS_WND: { //TODO: make more object oriented, e.g introduce a class CabinetWindow case IDC_SETTINGS_WND:
CloseStartMenu(id); CloseStartMenu(id);
HWND hwndFrame = MainFrame::Create(); MainFrame::Create(_T("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}"), FALSE);
ShowWindow(hwndFrame, SW_SHOW); break;
SendMessage(hwndFrame, PM_OPEN_WINDOW, FALSE/*mode_explore*/, (LPARAM)_T("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}"));
break;}
case IDC_FAVORITES: case IDC_FAVORITES:
CreateSubmenu(id, CSIDL_FAVORITES); CreateSubmenu(id, CSIDL_FAVORITES);

View file

@ -206,6 +206,7 @@ struct StartMenuRoot : public StartMenu
StartMenuRoot(HWND hwnd); StartMenuRoot(HWND hwnd);
static HWND Create(HWND hwndDesktopBar); static HWND Create(HWND hwndDesktopBar);
void TrackStartmenu();
protected: protected:
LRESULT Init(LPCREATESTRUCT pcs); LRESULT Init(LPCREATESTRUCT pcs);

View file

@ -124,7 +124,7 @@ LRESULT NotifyArea::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
case WM_TIMER: { case WM_TIMER: {
TimerTick(); TimerTick();
ClockWindow* clock_window = static_cast<ClockWindow*>(get_window(_hwndClock)); ClockWindow* clock_window = GET_WINDOW(ClockWindow, _hwndClock);
if (clock_window) if (clock_window)
clock_window->TimerTick(); clock_window->TimerTick();

View file

@ -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 // window utilities
struct ClientRect : public RECT struct ClientRect : public RECT

View file

@ -57,9 +57,30 @@ IconWindowClass::IconWindowClass(LPCTSTR classname, UINT nid, UINT style, WNDPRO
} }
HHOOK Window::s_hcbtHook = 0; HHOOK Window::s_hcbtHook = 0;
Window::CREATORFUNC Window::s_window_creator = NULL;
const void* Window::s_new_info = NULL; 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, 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, DWORD dwStyle, int x, int y, int w, int h,
HWND hwndParent, HMENU hMenu, LPVOID lpParam) 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_window_creator = creator;
s_new_info = NULL; 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, DWORD dwStyle, int x, int y, int w, int h,
HWND hwndParent, HMENU hMenu, LPVOID lpParam) 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_window_creator = creator;
s_new_info = info; 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) 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_window_creator = creator;
s_new_info = info; s_new_info = info;
s_new_child_wnd = NULL; 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* 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) WindowMap::const_iterator found = s_wnd_map.find(hwnd);
return wnd;
if (found!=s_wnd_map.end())
return found->second;
}
if (s_window_creator) { // protect for recursion 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; const void* info = s_new_info;
s_new_info = NULL; s_new_info = NULL;
@ -145,12 +178,12 @@ Window* Window::get_window(HWND hwnd)
s_window_creator = NULL; s_window_creator = NULL;
if (info) if (info)
wnd = window_creator(hwnd, info); return window_creator(hwnd, info);
else 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; HWND hwnd = _hwnd;
/*@@TODO: replace 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)
CancelModes((HWND)wparam); //@@ erronesly cancels desktop bar resize when switching from another process CancelModes((HWND)wparam); //@@ erronesly cancels desktop bar resize when switching from another process
*/
return DefWindowProc(hwnd, nmsg, wparam, lparam); return DefWindowProc(hwnd, nmsg, wparam, lparam);
} }

View file

@ -45,19 +45,6 @@ typedef set<HWND> 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. Class Window is the base class for several C++ window wrapper classes.
Window objects are allocated from the heap. They are automatically freed Window objects are allocated from the heap. They are automatically freed
@ -65,19 +52,11 @@ protected:
*/ */
struct Window : public WindowHandle struct Window : public WindowHandle
{ {
Window(HWND hwnd) Window(HWND hwnd);
: WindowHandle(hwnd) virtual ~Window();
{
// store "this" pointer as user data
SetWindowLong(hwnd, GWL_USERDATA, (LONG)this);
}
virtual ~Window()
{
// empty user data field
SetWindowLong(_hwnd, GWL_USERDATA, 0);
}
typedef map<HWND,Window*> WindowMap;
typedef Window* (*CREATORFUNC)(HWND, const void*); typedef Window* (*CREATORFUNC)(HWND, const void*);
typedef Window* (*CREATORFUNC_NO_INFO)(HWND); 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 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 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<typename WNDCLASS> static WNDCLASS* get_window(HWND hwnd) {return static_cast<WNDCLASS*>(get_window(hwnd));}
#define GET_WINDOW(WNDCLASS, hwnd) Window::get_window<WNDCLASS>(hwnd)
#endif
static void register_pretranslate(HWND hwnd); static void register_pretranslate(HWND hwnd);
static void unregister_pretranslate(HWND hwnd); static void unregister_pretranslate(HWND hwnd);
@ -122,8 +105,12 @@ protected:
virtual int Notify(int id, NMHDR* pnmh); // WM_NOTIFY processing virtual int Notify(int id, NMHDR* pnmh); // WM_NOTIFY processing
static const void* s_new_info; //TODO: protect for multithreaded access static WindowMap s_wnd_map;
static CREATORFUNC s_window_creator; //TODO: protect for multithreaded access 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 // MDI child creation
static HHOOK s_hcbtHook; static HHOOK s_hcbtHook;
@ -134,6 +121,16 @@ protected:
}; };
#ifdef _MSC_VER
template<typename WNDCLASS> struct GetWindowHelper {
static WNDCLASS* get_window(HWND hwnd) {
return static_cast<WNDCLASS*>(Window::get_window(hwnd));
}
};
#define GET_WINDOW(WNDCLASS, hwnd) GetWindowHelper<WNDCLASS>::get_window(hwnd)
#endif
/** /**
SubclassedWindow is used to wrap already existing window handles SubclassedWindow is used to wrap already existing window handles
into C++ Window objects. To construct a object, use the "new" operator into C++ Window objects. To construct a object, use the "new" operator