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;
// 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);
}
}

View file

@ -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<ChildWindow*>(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)

View file

@ -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;

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)
NotifyArea* notify_area = static_cast<NotifyArea*>(get_window(_hwndNotify));
NotifyArea* notify_area = GET_WINDOW(NotifyArea, _hwndNotify);
if (notify_area)
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)
{
// 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);

View file

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

View file

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

View file

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

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.
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<HWND,Window*> 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<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 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<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
into C++ Window objects. To construct a object, use the "new" operator