Здравствуйте, yaroslav_v, Вы писали:
L>>А зачем это? Просто у меня есть своя библиотека (vlib) там много кода (в том числе и эксперементального) — оформлять и вычищать это нет времени — а вам эта куча мало что даст... Основные принципы работы с сообщениями я уже в флейме указал — так, что зачем выгружать всё библиотеку?!
_>Достаточно пары файлов касающихся окон — не беда если это прямо не будет компилиться,
_>просто чем больше кода — тем понятнее, конечно у каждого накоплено много своего
_>кода и обычно в виде *.lib — файла, если ты не хочешь все публиковать — будет интересно
_>посмотреть часть, касаюэуюся SWL-modified.
Ну ладно — вот файл (он не компилится):
#ifndef __vwnd_h_
#define __wwnd_h_
#include <map>
#include <list>
#include "vbase.h"
#include "vmodule.h"
#include "vcontent.h"
#include "vgc.h"
struct VMsgData
{
HWND m_hWnd;
UINT m_msg;
WPARAM m_wParam;
LPARAM m_lParam;
VMsgData(const VMsgData & o)
: m_hWnd(o.m_hWnd), m_msg(o.m_msg), m_wParam(o.m_wParam), m_lParam(o.m_lParam)
{
}
VMsgData(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
: m_hWnd(hWnd), m_msg(msg), m_wParam(wParam), m_lParam(lParam)
{
}
};
template <UINT msgID>
struct VMsg : public VMsgData
{
VMsg(const VMsgData & o)
: VMsgData(o)
{
}
};
template <WPARAM ctrlID>
struct VCommandMsg : public VMsgData
{
VCommandMsg(const VMsgData & o)
: VMsgData(o)
{
}
HWND sender() const { return (HWND)m_lParam; }
WORD id() const { return LOWORD(m_wParam); }
WORD notificationCode() const { return HIWORD(m_wParam); }
};
template <WPARAM ctrlID>
struct VNotifyMsg : public VMsgData
{
VNotifyMsg(const VMsgData & o)
: VMsgData(o)
{
}
int sender() const { return (int)m_wParam; }
LPNMHDR addInfo() const { return (LPNMHDR)m_lParam; }
};
class VWnd;
class VMessageMapProcessor
{
public:
virtual LRESULT operator () (VWnd * obj, VMsgData & msgData, bool & bHandled) = 0;
private:
int m_order;
friend class VMessageMapBase;
};
class VMessageMapBase
{
public:
typedef std::list<VMessageMapProcessor *> TList;
typedef std::map<UINT, TList> TMap;
static void add(TMap & rMap, UINT msgID, VMessageMapProcessor * f, int order = 0)
{
TList & l = rMap[msgID];
for(TList::iterator p = l.end(); p != l.begin(); )
{
--p;
if((*p)->m_order <= order)
{
l.insert(p, f);
return;
}
}
l.push_front(f);
}
static void remove(TMap & rMap, UINT msgID, VMessageMapProcessor * f)
{
TList & l = rMap[msgID];
l.remove(f);
}
static LRESULT processWindowMessage(TMap & rMap, VWnd * obj, VMsgData & msgData, bool & bHandled)
{
TMap::iterator pList = rMap.find(msgData.m_msg);
if(pList != rMap.end())
{
TList & l = pList->second;
for(TList::iterator p = l.begin(); p != l.end(); ++p)
{
bHandled = true;
LRESULT ret = (**p)(obj, msgData, bHandled);
if(bHandled)
return ret;
}
}
bHandled = false;
return 0;
}
};
template <class TWnd>
class VMessageMap : public VMessageMapBase
{
public:
static void add(UINT msgID, VMessageMapProcessor * f, int order = 0)
{
VMessageMapBase::add(getMap(), msgID, f, order);
}
static LRESULT processWindowMessage(TWnd * obj, VMsgData & msgData, bool & bHandled)
{
return VMessageMapBase::processWindowMessage(getMap(), obj, msgData, bHandled);
}
protected:
static TMap & getMap()
{
static TMap m_map;
return m_map;
}
};
class VOnMessageBase
{
public:
VOnMessageBase(LRESULT _ret)
: m_ret(_ret)
{
}
operator LRESULT () const
{
return m_ret;
}
protected:
LRESULT m_ret;
};
template <class TRel, UINT msgID>
class VOnMessage : public VOnMessageBase
{
public:
VOnMessage(LRESULT _ret)
: VOnMessageBase(_ret)
{
m_Registrator.fake();
}
class Registrator : public VMessageMapProcessor
{
public:
Registrator()
{
VMessageMap<TRel>::add(msgID, this);
}
virtual LRESULT operator () (VWnd * obj, VMsgData & msgData, bool & bHandled)
{
return static_cast<TRel *>(obj)->onMessage(VMsg<msgID>(msgData), bHandled);
}
void fake() {}
};
static Registrator m_Registrator;
};
template <class TRel, UINT msgID>
typename VOnMessage<TRel, msgID>::Registrator VOnMessage<TRel, msgID>::m_Registrator;
template <class TRel, WPARAM contID>
class VOnCommand : public VOnMessageBase
{
public:
VOnCommand(LRESULT _ret)
: VOnMessageBase(_ret)
{
m_Registrator.fake();
}
class Registrator : public VMessageMapProcessor
{
public:
Registrator()
{
VMessageMap<TRel>::add(WM_COMMAND, this);
}
virtual LRESULT operator () (VWnd * obj, VMsgData & msgData, bool & bHandled)
{
if(msgData.m_wParam == contID)
return static_cast<TRel *>(obj)->onMessage(VCommandMsg<contID>(msgData), bHandled);
bHandled = false;
return 0;
}
void fake() {}
};
static Registrator m_Registrator;
};
template <class TRel, WPARAM contID>
typename VOnCommand<TRel, contID>::Registrator VOnCommand<TRel, contID>::m_Registrator;
template <class TRel, WPARAM contID>
class VOnNotify : public VOnMessageBase
{
public:
VOnNotify(LRESULT _ret)
: VOnMessageBase(_ret)
{
m_Registrator.fake();
}
class Registrator : public VMessageMapProcessor
{
public:
Registrator()
{
VMessageMap<TRel>::add(WM_NOTIFY, this);
}
virtual LRESULT operator () (VWnd * obj, VMsgData & msgData, bool & bHandled)
{
if(((LPNMHDR)msgData.m_lParam)->code == contID)
return static_cast<TRel *>(obj)->onMessage(VNotifyMsg<contID>(msgData), bHandled);
bHandled = false;
return 0;
}
void fake() {}
};
static Registrator m_Registrator;
};
template <class TRel, WPARAM contID>
typename VOnNotify<TRel, contID>::Registrator VOnNotify<TRel, contID>::m_Registrator;
//--------------------------- Messages -----------------------------
template <>
struct VMsg<WM_INITDIALOG> : public VMsgData
{
VMsg(const VMsgData & msg)
: VMsgData(msg)
{
}
HWND defControl() const { return (HWND)m_wParam; }
void * param() const { return (void *)m_lParam; }
};
template <>
struct VMsg<WM_COMMAND> : public VMsgData
{
VMsg(const VMsgData & msg)
: VMsgData(msg)
{
}
HWND sender() const { return (HWND)m_lParam; }
WORD id() const { return LOWORD(m_wParam); }
WORD notificationCode() const { return HIWORD(m_wParam); }
};
template <>
struct VMsg<WM_PAINT> : public VMsgData
{
VMsg(const VMsgData & msg)
: VMsgData(msg)
{
}
PAINTSTRUCT m_ps;
HDC begin(HWND hWnd = NULL)
{
return BeginPaint(hWnd ? hWnd : m_hWnd, &m_ps);
}
void end(HWND hWnd = NULL)
{
EndPaint(hWnd ? hWnd : m_hWnd, &m_ps);
}
};
#define VMESSAGE_MAP(ClassName, BaseClass)\
typedef ClassName ThisClass;\
virtual LRESULT processWindowMessage(VMsgData & msgData, bool & bHandled)\
{\
LRESULT ret = VMessageMap<ClassName>::processWindowMessage(this, msgData, bHandled);\
if(!bHandled)\
ret = BaseClass::processWindowMessage(msgData, bHandled);\
return ret;\
}
#define VON_MESSAGE(msgID)\
VOnMessage<ThisClass, msgID> onMessage(VMsg<msgID> & msg, bool & bHandled)
#define VON_COMMAND(cmdID)\
VOnCommand<ThisClass, cmdID> onMessage(VCommandMsg<cmdID> & msg, bool & bHandled)
#define VON_NOTIFY(msgID)\
VOnNotify<ThisClass, msgID> onMessage(VNotifyMsg<msgID> & msg, bool & bHandled)
class VWnd
{
public:
typedef VWnd ThisClass;
virtual LRESULT processWindowMessage(VMsgData & msgData, bool & bHandled)
{
return VMessageMap<VWnd>::processWindowMessage(this, msgData, bHandled);
}
static std::map<LPARAM, VWnd *> & hWnd2ObjMap()
{
static std::map<LPARAM, VWnd *> m_instance;
return m_instance;
}
HWND m_hWnd;
operator HWND () const { return m_hWnd; }
VRet<LONG> setWindowLong(int index, LONG newValue)
{
SetLastError(0);
LONG ret = SetWindowLong(m_hWnd, index, newValue);
return VRet<LONG>::errIfError(ret, !ret && GetLastError(), "error in SetWindowLong()");
}
VRet<BOOL> destroyWindow()
{
return VRet<BOOL>::errIfEqu(DestroyWindow(m_hWnd), FALSE, "Error on destroyWindow()");
}
BOOL isWindow() const
{
return IsWindow(m_hWnd);
}
BOOL show(bool bShow = true)
{
return ShowWindow(m_hWnd, bShow ? SW_SHOW : SW_HIDE);
}
//MessageMap
VON_MESSAGE(WM_NCDESTROY)
{
onNCDestroy();
return 0;
}
virtual void onNCDestroy()
{
m_hWnd = NULL;
}
RECT getRect() const
{
RECT rect;
VRTVERIFYE(GetWindowRect(m_hWnd, &rect));
return rect;
}
RECT getRect(HWND relativeTo) const
{
RECT rect;
VRTVERIFYE(GetWindowRect(m_hWnd, &rect));
VRTVERIFYE(MapWindowPoints(NULL, relativeTo, (LPPOINT)&rect, 2) != 0);
return rect;
}
static LRESULT CALLBACK wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if(msg == WM_CREATE)
{
LPCREATESTRUCT cs = reinterpret_cast<LPCREATESTRUCT>(lParam);
VWnd * win = reinterpret_cast<VWnd *>(cs->lpCreateParams);
win->m_hWnd = hWnd;
hWnd2ObjMap()[(LPARAM)hWnd] = win;
}
std::map<LPARAM, VWnd *>::const_iterator pWnd = hWnd2ObjMap().find((LPARAM)hWnd);
if(pWnd != hWnd2ObjMap().end())
{
VWnd * win = pWnd->second;
if(win)
{
bool bHandled = true;
LRESULT ret = win->processWindowMessage(VMsgData(hWnd, msg, wParam, lParam), bHandled);
if(bHandled)
return ret;
else
return win->defWndProc(hWnd, msg, wParam, lParam);
}
}
return ::DefWindowProc(hWnd, msg, wParam, lParam);
}
virtual LRESULT defWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
return ::DefWindowProc(hWnd, msg, wParam, lParam);
}
static ATOM registerClass()
{
WNDCLASSEX wcex;
memset(&wcex, 0, sizeof(wcex));
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = wndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = (HINSTANCE)_ThisModule.m_hModule;
wcex.hIcon = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "VWindowClass";
wcex.hIconSm = NULL;
return RegisterClassEx(&wcex);
}
virtual const SYSCHAR * getClassName()
{
static ATOM wndAtom = registerClass();
VASSERTE(wndAtom);
return (const SYSCHAR *)wndAtom;
}
virtual DWORD getDefStyle()
{
return WS_OVERLAPPEDWINDOW;
}
virtual DWORD getDefExStyle()
{
return 0;
}
virtual HWND create(HWND hParent, DWORD dwStyle, DWORD dwExStyle, int X, int Y, int nWidth, int nHeight)
{
m_hWnd = CreateWindowEx(
dwExStyle,
getClassName(),
NULL,
dwStyle,
X,
Y,
nWidth,
nHeight,
hParent,
NULL,
_ThisModule.m_hModule,
this
);
VASSERTE(m_hWnd);
return m_hWnd;
}
HWND create(int X, int Y, int nWidth, int nHeight)
{
return create(NULL, getDefStyle(), getDefExStyle(), X, Y, nWidth, nHeight);
}
HWND create(HWND hParent, DWORD dwStyle, DWORD dwExStyle)
{
return create(hParent, dwStyle, dwExStyle, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT);
}
void getWindowRect(LPRECT pRect)
{
VVERIFY(GetWindowRect(m_hWnd, pRect), "Error GetWindowRect");
}
RECT getWindowRect()
{
RECT rect;
getWindowRect(&rect);
return rect;
}
void screenToClient(POINT & pt)
{
ScreenToClient(m_hWnd, &pt);
}
void screenToClient(RECT & rect)
{
MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rect, 2);
}
void setPos(HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags)
{
SetWindowPos(m_hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
}
void setPos(HWND hWndInsertAfter, UINT uFlags = SWP_NOMOVE | SWP_NOSIZE)
{
setPos(hWndInsertAfter, 0, 0, 0, 0, uFlags);
}
void setPos(int X, int Y, UINT uFlags = SWP_NOZORDER | SWP_NOSIZE)
{
setPos(NULL, X, Y, X, Y, uFlags);
}
BOOL move(int x, int y, int dx, int dy, BOOL bRepaint = TRUE)
{
return MoveWindow(m_hWnd, x, y, dx, dy, bRepaint);
}
BOOL move(RECT & rect, BOOL bRepaint = TRUE)
{
return move(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, bRepaint);
}
VSysString windowText()
{
VSysString ret;
size_t len = (size_t)GetWindowTextLength(m_hWnd);
GetWindowText(m_hWnd, ret.getBuffer(len), (int)len + 1);
ret.releaseBuffer(len);
return ret;
}
void windowText(const SYSCHAR * pStr)
{
SetWindowText(m_hWnd, pStr);
}
};
class VDlgControl
{
public:
int m_id;
VDlgControl * m_layoutParent;
enum DockType
{
dtNone,
dtTop,
dtLeft,
dtBottom,
dtRight,
dfClient,
};
DockType m_dock;
bool m_anchorTop;
bool m_anchorLeft;
bool m_anchorBottom;
bool m_anchorRight;
RECT m_rect;
VDlgControl()
: m_id(-1), m_layoutParent(NULL),
m_dock(dtNone),
m_anchorTop(true), m_anchorLeft(true), m_anchorRight(false), m_anchorBottom(false)
{
}
VDlgControl(int id, VDlgControl * layoutParent = NULL)
: m_id(id), m_layoutParent(layoutParent),
m_dock(dtNone),
m_anchorTop(true), m_anchorLeft(true), m_anchorRight(false), m_anchorBottom(false)
{
}
VDlgControl(int id, DockType dockType, VDlgControl * layoutParent = NULL)
: m_id(id), m_layoutParent(layoutParent),
m_dock(dockType),
m_anchorTop(true), m_anchorLeft(true), m_anchorRight(false), m_anchorBottom(false)
{
}
VDlgControl(int id, bool anchorLeft, bool anchorTop, bool anchorRight, bool anchorBottom, VDlgControl * layoutParent = NULL)
: m_id(id), m_layoutParent(layoutParent),
m_dock(dtNone),
m_anchorTop(anchorTop), m_anchorLeft(anchorLeft), m_anchorRight(anchorRight), m_anchorBottom(anchorBottom)
{
}
virtual ~VDlgControl()
{
}
};
class VControlMap
{
public:
void add(int cntl, VDlgControl * wnd)
{
m_map[cntl] = wnd;
}
protected:
friend class VDialog;
std::map<int, VDlgControl *> m_map;
};
template <int ctrlId, class TCtrlClass = VWnd>
class VControl : public TCtrlClass, public VDlgControl
{
public:
VControl(VDlgControl * layoutParent = NULL)
: VDlgControl(ctrlId, layoutParent)
{
VContent::getInstance().curDialog()->m_controlMap.add(ctrlId, this);
}
VControl(DockType dockType, VDlgControl * layoutParent = NULL)
: VDlgControl(ctrlId, dockType, layoutParent)
{
VContent::getInstance().curDialog()->m_controlMap.add(ctrlId, this);
}
VControl(bool anchorLeft, bool anchorTop, bool anchorRight, bool anchorBottom, VDlgControl * layoutParent = NULL)
: VDlgControl(ctrlId, anchorLeft, anchorTop, anchorRight, anchorBottom, layoutParent)
{
VContent::getInstance().curDialog()->m_controlMap.add(ctrlId, this);
}
};
//
class VDialog : public VWnd
{
public:
VDialog()
: m_bModeless(false)
{
VContent::getInstance().curDialog(this);
}
VRet<HWND> createDialog(LPCTSTR lpTemplateName, HWND hWndParent = VContent::getInstance().currentHWND(), HINSTANCE hInstance = _ThisModule.m_hModule)
{
m_bModeless = true;
HWND hWnd = CreateDialogParam(hInstance, lpTemplateName, hWndParent, dlgProc, (LPARAM)this);
if(hWnd)
InitModeless::getInstance().addDialog(hWnd);
return VRet<HWND>::errIfEqu(hWnd, NULL, "Error create dialog");
}
VRet<HWND> createDialog(WORD idd, HWND hWndParent = VContent::getInstance().currentHWND(), HINSTANCE hInstance = _ThisModule.m_hModule)
{
m_bModeless = true;
HWND hWnd = CreateDialogParam(hInstance, MAKEINTRESOURCE(idd), hWndParent, dlgProc, (LPARAM)this);
if(hWnd)
InitModeless::getInstance().addDialog(hWnd);
return VRet<HWND>::errIfEqu(hWnd, NULL, "Error create dialog");
}
VRet<INT_PTR> doModal(LPCTSTR lpTemplateName, HWND hWndParent = VContent::getInstance().currentHWND(), HINSTANCE hInstance = _ThisModule.m_hModule)
{
m_bModeless = false;
return VRet<INT_PTR>::errIfEqu(DialogBoxParam(hInstance, lpTemplateName, hWndParent, dlgProc, (LPARAM)this), -1, "Error create dialog");
}
VRet<INT_PTR> doModal(WORD idd, HWND hWndParent = VContent::getInstance().currentHWND(), HINSTANCE hInstance = _ThisModule.m_hModule)
{
m_bModeless = false;
return VRet<INT_PTR>::errIfEqu(DialogBoxParam(hInstance, MAKEINTRESOURCE(idd), hWndParent, dlgProc, (LPARAM)this), -1, "Error create dialog");
}
VRet<BOOL> endDialog(int nResult)
{
if(isModeless())
return destroyWindow();
else
return VRet<BOOL>::errIfEqu(EndDialog(m_hWnd, nResult), FALSE, "Error in EndDialog");
}
bool isModeless() const
{
return m_bModeless;
}
virtual void onNCDestroy()
{
InitModeless::getInstance().removeDialog(m_hWnd);
VWnd::onNCDestroy();
}
virtual bool onOk()
{
return true;
}
virtual bool onCancel()
{
return true;
}
virtual bool onClose()
{
return true;
}
VMESSAGE_MAP(VDialog, VWnd);
VON_COMMAND(IDOK)
{
if(!onOk())
bHandled = false;
else
endDialog(IDOK);
return 0;
}
VON_COMMAND(IDCANCEL)
{
if(!onCancel())
bHandled = false;
else
endDialog(IDCANCEL);
return 0;
}
VON_MESSAGE(WM_CLOSE)
{
if(!onClose())
bHandled = false;
else
endDialog(IDCANCEL);
return 0;
}
virtual void updateLayout(int dx, int dy)
{
}
VON_MESSAGE(WM_SIZE)
{
RECT rect = getWindowRect();
updateLayout(
(rect.right - rect.left) - (m_startRect.right - m_startRect.left),
(rect.bottom - rect.top) - (m_startRect.bottom - m_startRect.top)
);
m_startRect = rect;
return 0;
}
void layout(VWnd & wnd, int dx, int dy, bool bLeft, bool bTop, bool bRight, bool bBottom)
{
RECT rect;
wnd.getWindowRect(&rect);
screenToClient(rect);
if(!bLeft)
rect.left += dx;
if(!bTop)
rect.top += dy;
if(bRight)
rect.right += dx;
if(bBottom)
rect.bottom += dy;
wnd.move(rect);
}
void layout(WORD id, int dx, int dy, bool bLeft, bool bTop, bool bRight, bool bBottom)
{
HWND hWnd = GetDlgItem(m_hWnd, id);
RECT rect;
GetWindowRect(hWnd, &rect);
MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rect, 2);
if(!bLeft)
rect.left += dx;
if(!bTop)
rect.top += dy;
if(bRight)
rect.right += dx;
if(bBottom)
rect.bottom += dy;
MoveWindow(hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, TRUE);
}
class iterator
{
public:
iterator(std::map<int, VDlgControl *> & _map, std::map<int, VDlgControl *>::iterator pos)
: m_map(_map), m_pos(pos)
{
}
iterator(const iterator & o)
: m_map(o.m_map), m_pos(o.m_pos)
{
}
bool operator == (iterator p) const { return m_pos == p.m_pos; }
bool operator != (iterator p) const { return m_pos != p.m_pos; }
iterator & operator ++ ()
{
VASSERTE(m_pos != m_map.end());
VDlgControl * pParent = m_pos->second;
while(++m_pos != m_map.end() && m_pos->second != pParent);
return *this;
}
iterator operator ++ (int)
{
iterator tmp = *this;
++*this;
return tmp;
}
protected:
std::map<int, VDlgControl *> & m_map;
std::map<int, VDlgControl *>::iterator m_pos;
};
iterator begin(VDlgControl * pParent = NULL)
{
std::map<int, VDlgControl *>::iterator p = m_controlMap.m_map.begin();
while(p != m_controlMap.m_map.end() && p->second != pParent)
++p;
return iterator(m_controlMap.m_map, p);
}
iterator end()
{
return iterator(m_controlMap.m_map, m_controlMap.m_map.end());
}
void preInitDialog()
{
for(std::map<int, VDlgControl *>::const_iterator p = m_controlMap.m_map.begin(); p != m_controlMap.m_map.end(); ++p)
{
if(p->first != -1)
{
VWnd * wnd = dynamic_cast<VWnd *>(p->second);
VRTVERIFYE(wnd);
VRTVERIFY(wnd->m_hWnd = GetDlgItem(m_hWnd, p->first), "Invalid resource file");
p->second->m_rect = wnd->getRect(m_hWnd);
}
else
VRTVERIFYE(SetRectEmpty(&p->second->m_rect));
}
}
virtual void onInitDialog()
{
m_startRect = getWindowRect();
}
virtual LRESULT defWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
return 0;
}
protected:
RECT m_startRect;
static BOOL CALLBACK dlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
VContent::ChangecurrentHWND saveCurrentHWND(hWnd);
if(msg == WM_INITDIALOG)
{
VDialog * dlg = (VDialog *)lParam;
hWnd2ObjMap()[(LPARAM)hWnd] = dlg;
dlg->m_hWnd = hWnd;
dlg->preInitDialog();
dlg->onInitDialog();
}
VWnd * win = hWnd2ObjMap()[(LPARAM)hWnd];
if(win)
{
bool bHandled = true;
LRESULT ret = win->processWindowMessage(VMsgData(hWnd, msg, wParam, lParam), bHandled);
if(bHandled)
win->setWindowLong(DWL_MSGRESULT, (LONG)ret).ignore();
return bHandled ? TRUE : FALSE;
}
return FALSE;
}
class InitModeless
{
public:
InitModeless()
{
m_hKeyboardFilterHook = SetWindowsHookEx(WH_KEYBOARD, keyboardFilterProc, NULL, GetCurrentThreadId());
VASSERTE(m_hKeyboardFilterHook);
}
~InitModeless()
{
UnhookWindowsHookEx(m_hKeyboardFilterHook);
}
static InitModeless & getInstance()
{
static InitModeless m_instance;
return m_instance;
}
void addDialog(HWND dlg)
{
m_dlgs.push_back(dlg);
}
void removeDialog(HWND dlg)
{
m_dlgs.remove(dlg);
}
protected:
HHOOK m_hKeyboardFilterHook;
std::list<HWND> m_dlgs;
static LRESULT CALLBACK keyboardFilterProc(int code, WPARAM wParam, LPARAM lParam)
{
switch (code)
{
case HC_ACTION:
{
MSG msg;
msg.message = (lParam & 0x80000000L) ? WM_KEYUP : WM_KEYDOWN;
msg.hwnd = ::GetFocus();
msg.wParam = wParam;
msg.lParam = lParam;
GetCursorPos(&msg.pt);
msg.time = 0;
for(std::list<HWND>::const_iterator p = getInstance().m_dlgs.begin(); p != getInstance().m_dlgs.end(); ++p)
{
static const TCHAR * IsVlibTmp = TEXT("{0B98B0C3-E0C1-41c4-8E20-528C395EAB6D}");
HWND hWnd = *p;
if(IsWindowEnabled(hWnd) && !GetProp(hWnd, IsVlibTmp))
{
SetProp(hWnd, IsVlibTmp, (HANDLE)1);
BOOL bRet = IsDialogMessage(hWnd, &msg);
SetProp(hWnd, IsVlibTmp, (HANDLE)0);
if(bRet)
return (LRESULT)TRUE;
}
}
}
break;
}
return ::CallNextHookEx(getInstance().m_hKeyboardFilterHook, code, wParam, lParam);
}
};
bool m_bModeless;
public:
VControlMap m_controlMap;
};
class VControlWnd : public VWnd
{
public:
virtual DWORD getDefStyle()
{
return WS_CHILD;
}
virtual HWND create(HWND hParent, DWORD dwStyle, DWORD dwExStyle, int X, int Y, int nWidth, int nHeight)
{
m_hWnd = CreateWindowEx(
dwExStyle,
getClassName(),
NULL,
dwStyle,
X,
Y,
nWidth,
nHeight,
hParent,
NULL,
_ThisModule.m_hModule,
NULL
);
VASSERTE(m_hWnd);
m_oldWndProc = GetWindowLongPtr(m_hWnd, GWL_WNDPROC);
SetWindowLongPtr(m_hWnd, GWL_WNDPROC, (LONG_PTR)wndProc);
hWnd2ObjMap()[(LPARAM)m_hWnd] = this;
return m_hWnd;
}
virtual LRESULT defWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
return ::CallWindowProc((WNDPROC)m_oldWndProc, hWnd, msg, wParam, lParam);
}
protected:
LONG_PTR m_oldWndProc;
};
#endif//__vwnd_h_
Пример использования:
#pragma once
#include <shlwapi.h>
#include "vwin.h"
#include "resource.h"
#include "vcontrols.h"
#include "vopensavedlg.h"
#include "veditapp.h"
#include "vshell.h"
#pragma comment(lib, "shlwapi.lib")
class voptionsdlg : public VDialog
{
public:
voptionsdlg(void);
~voptionsdlg(void);
enum { IDD = IDD_OPTIONDLG };
VControl<IDC_ALLLIST, VListView> m_allPrograms;
virtual void onInitDialog()
{
m_allPrograms.addColumn(0, TEXT("╚ь "), LVCFMT_LEFT, 100);
m_allPrograms.addColumn(1, TEXT("╧ЁюуЁрььр"), LVCFMT_LEFT, 400);
std::map<VSysString, VSysString> items;
load(items);
for(std::map<VSysString, VSysString>::const_iterator p = items.begin(); p != items.end(); ++p)
addApp(p->first, p->second);
VDialog::onInitDialog();
}
void save()
{
std::map<VSysString, VSysString> items;
int count = m_allPrograms.count();
for(int i = 0; i < count; ++i)
items[m_allPrograms.itemText(i, 0)] = m_allPrograms.itemText(i, 1);
save(items);
}
virtual void updateLayout(int dx, int dy)
{
layout(m_allPrograms, dx, dy, true, true, true, true);
layout(IDOK, dx, dy, false, true, true, false);
layout(IDCANCEL, dx, dy, false, true, true, false);
layout(IDC_ADDBUTTON, dx, dy, false, true, true, false);
layout(IDC_EDITBUTTON, dx, dy, false, true, true, false);
layout(IDC_DELBUTTON, dx, dy, false, true, true, false);
VDialog::updateLayout(dx, dy);
}
VMESSAGE_MAP(voptionsdlg, VDialog);
VON_COMMAND(IDC_ADDBUTTON)
{
veditapp dlg;
if(dlg.doModal(veditapp::IDD, m_hWnd) == IDOK)
addApp(dlg.m_NameStr, dlg.m_FileStr);
return 0;
}
VON_COMMAND(IDC_EDITBUTTON)
{
int index = m_allPrograms.cursel();
if(index >= 0)
{
veditapp dlg;
dlg.m_NameStr = m_allPrograms.itemText(index, 0);
dlg.m_FileStr = m_allPrograms.itemText(index, 1);
if(dlg.doModal(veditapp::IDD, m_hWnd) == IDOK)
{
m_allPrograms.remove(index);
addApp(dlg.m_NameStr, dlg.m_FileStr);
}
}
return 0;
}
VON_COMMAND(IDC_DELBUTTON)
{
int index = m_allPrograms.cursel();
if(index >= 0)
m_allPrograms.remove(index);
return 0;
}
VON_NOTIFY(PSN_APPLY)
{
save();
return 0;
}
void addApp(const VSysString & name, const VSysString & file)
{
HIMAGELIST hImageList;
int index = VShell::getIcon(file, hImageList, true);
if(!m_allPrograms.imageList(LVSIL_SMALL))
m_allPrograms.imageList(hImageList, LVSIL_SMALL);
int i = m_allPrograms.add(name, index);
m_allPrograms.itemText(i, 1, file);
}
static void rTrim(SYSCHAR * pStr)
{
size_t len = vstrlen(pStr);
while(len && visWhiteSpace(pStr[len - 1]))
pStr[len-- - 1] = 0;
}
static void load(std::map<VSysString, VSysString> & items)
{
SYSCHAR buf[MAX_PATH + 1];
GetModuleFileName(_ThisModule.m_hModule, buf, countof(buf));
PathRemoveFileSpec(buf);
PathCombine(buf, buf, TEXT("apps.ini"));
FILE * f = fopen(buf, "rt");
if(!f)
return;
while(!feof(f))
{
if(!fgets(buf, countof(buf), f))
break;
SYSCHAR buf1[MAX_PATH + 1];
if(!fgets(buf1, countof(buf1), f))
break;
rTrim(buf);
rTrim(buf1);
items[buf] = buf1;
}
fclose(f);
}
static void save(std::map<VSysString, VSysString> & items)
{
SYSCHAR buf[MAX_PATH + 1];
GetModuleFileName(_ThisModule.m_hModule, buf, countof(buf));
PathRemoveFileSpec(buf);
PathCombine(buf, buf, TEXT("apps.ini"));
FILE * f = fopen(buf, "wt");
if(!f)
return;
for(std::map<VSysString, VSysString>::const_iterator p = items.begin(); p != items.end(); ++p)
{
fprintf(f, "%s\n", p->first.c_str());
fprintf(f, "%s\n", p->second.c_str());
}
fclose(f);
}
};
Здравствуйте, lboss, Вы писали:
L>Но я не могу придумать как форсировать вызов конструктора Initializer'а... Пришлось придумывать MsgResult...
Я чегой-от никак не пойму: а какого лешего инстанциируются статические члены MsgResult, а конкретно m_Initializer?
По идее пока соответсвующая OnMsg не вызвана, он не нужен, а вызвана она будет только если ее предварительно зарегистрировать, что делает именно Initializer. Замкнутый круг.
Ничего не понимаю.
Копаясь с этим делом я пришел к такому коду ( этот работает ) :
#include <map>
template < class Param, class Id, Id id >
struct Message
{
Param ¶m_;
Message(Param ¶m) : param_(param) { }
};
template < class Target, class Param, class Id >
struct MessageMap
{
typedef bool (*ProxyFun)(Target&, Param&);
template < Id id >
static bool ConcreteProxyFun(Target &target, Param ¶m)
{
return target.Handle(Message<Param, Id, id>(param));
}
typedef std::map<Id, ProxyFun> Map;
static Map &GetMap()
{
static Map map_;
return map_;
}
template < Id id >
struct Registrar
{
Registrar()
{
static struct ActualRegistrar
{
ActualRegistrar()
{
GetMap()[id] = ConcreteProxyFun<id>;
}
} registrar;
}
};
static bool Handle(Target& target, Id id, Param ¶m)
{
Map::iterator iter = GetMap().find(id);
if(iter == GetMap().end())
return false;
else
return (*iter->second)(target, param);
}
};
Использование
#include <windows.h>
#include <iostream>
struct MsgParam
{
WPARAM wParam_;
LPARAM lParam_;
MsgParam(WPARAM wParam, LPARAM lParam) : wParam_(wParam), lParam_(lParam) {}
};
struct Wnd
{
/*Wnd() // можно так
{
MessageMap< Wnd, MsgParam, UINT >::Registrar< WM_CREATE >();
MessageMap< Wnd, MsgParam, UINT >::Registrar< WM_COMMAND >();
}
*/
MessageMap< Wnd, MsgParam, UINT >::Registrar< WM_CREATE > regCreate; // а можно так
bool Handle(Message<MsgParam, UINT, WM_CREATE> msg)
{
std::cout << "WM_CREATE " << msg.param_.wParam_ << " " << msg.param_.lParam_ << "\n";
return true;
}
MessageMap< Wnd, MsgParam, UINT >::Registrar< WM_COMMAND > regCommand;
bool Handle(Message<MsgParam, UINT, WM_COMMAND> msg)
{
std::cout << "WM_COMMAND " << msg.param_.wParam_ << " " << msg.param_.lParam_ << "\n";
return true;
}
};
int main()
{
Wnd wnd;
MessageMap<Wnd, MsgParam, UINT>::Handle(wnd, WM_CREATE, MsgParam(0, 1));
MessageMap<Wnd, MsgParam, UINT>::Handle(wnd, WM_COMMAND, MsgParam(2, 3));
MessageMap<Wnd, MsgParam, UINT>::Handle(wnd, WM_CREATE, MsgParam(4, 5));
std::cin.get();
return 0;
}
Есть ту фсякие косяки, ну да бог с ними, хочется автоматики. А потому пытаемся повторить подвиг lboss'а и... ничего не получается.
Registrar переименовываем в Result, добавляем ему чуть-чуть и первозим его в глобальное пространство имен:
template < class Target, class Param, class Id, Id id >
struct Result
{
bool result_;
Result(bool result) : result_(result)
{
static struct ActualRegistrar
{
ActualRegistrar()
{
MessageMap< Target, Param, Id >::GetMap()[id] = MessageMap< Target, Param, Id >::ConcreteProxyFun<id>;
}
} registrar;
}
operator bool() { return result_; }
};
Использование теперь такое:
struct Wnd
{
Result<Wnd, MsgParam, UINT, WM_CREATE> Handle(Message<MsgParam, UINT, WM_CREATE> msg)
{
std::cout << "WM_CREATE " << msg.param_.wParam_ << " " << msg.param_.lParam_ << "\n";
return true;
}
Result<Wnd, MsgParam, UINT, WM_COMMAND> Handle(Message<MsgParam, UINT, WM_COMMAND> msg)
{
std::cout << "WM_COMMAND " << msg.param_.wParam_ << " " << msg.param_.lParam_ << "\n";
return true;
}
};
Только вот Result::ActualRegistrar не инстанциируется. Да и не должен. Это просто я типа у lboss'а подсмотрел, только чего-то недостмотрел

Объясните пожалуйста чего я не догоняю?
... << RSDN@Home 1.1 alpha 1 >>