Re: По мотивам SWL
От: Аноним  
Дата: 05.06.03 12:25
Оценка:
Здравствуйте, WolfHound, Вы писали:

А как в шаблон сообщения добавить char* параметр?, почему-то на этапе линковки проблемы возникают
Re[17]: По мотивам SWL
От: lboss Россия  
Дата: 06.06.03 03:26
Оценка:
Здравствуйте, 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);
        }
};
С уважением Вадим.
Re[2]: Можно сильнее извратиться....
От: Рома Мик Россия http://romamik.com
Дата: 30.06.03 00:06
Оценка:
Здравствуйте, lboss, Вы писали:

L>Но я не могу придумать как форсировать вызов конструктора Initializer'а... Пришлось придумывать MsgResult...

Я чегой-от никак не пойму: а какого лешего инстанциируются статические члены MsgResult, а конкретно m_Initializer?
По идее пока соответсвующая OnMsg не вызвана, он не нужен, а вызвана она будет только если ее предварительно зарегистрировать, что делает именно Initializer. Замкнутый круг.
Ничего не понимаю.

Копаясь с этим делом я пришел к такому коду ( этот работает ) :
 #include <map>

template < class Param, class Id, Id id >
struct Message 
{
    Param &param_;
    Message(Param &param) : 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 &param)
    {
        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 &param)
    {
        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 >>
Re[3]: Можно сильнее извратиться....
От: Рома Мик Россия http://romamik.com
Дата: 30.06.03 00:20
Оценка:
Здравствуйте, Рома Мик, Вы писали:

Кстати, а нельзя ли победить синатксис C++ и сделать аналог такой штуки
template < class Param, Param::Id id >
struct Message {...}

//А в качестве параметра использовать
struct MsgParam
{
    typedef UINT Id;
    ...
}


Такое конечно, не компилируется, но вот подобного результата как добиться?
... << RSDN@Home 1.1 alpha 1 >>
Re[4]: Можно сильнее извратиться....
От: WolfHound  
Дата: 30.06.03 05:01
Оценка:
Здравствуйте, Рома Мик, Вы писали:
хъ
РМ>Такое конечно, не компилируется, но вот подобного результата как добиться?
template < class Param, class Id=Param::Id >
struct Message {};

struct MsgParam
{
    typedef UINT Id;
};

Ы?
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[5]: Можно сильнее извратиться....
От: Рома Мик Россия http://romamik.com
Дата: 30.06.03 09:13
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>
WH>template < class Param, class Id=Param::Id >
WH>struct Message {};

WH>struct MsgParam
WH>{
WH>    typedef UINT Id;
WH>};
WH>

WH>Ы?
Кажется, не Ы.Как минимум так:
<class Param=Что-то, class Id=Param::Id, Id id>

И это никак не помогает.
Если посмотреть на то что я там понаписал, там все время приходится писать нечто такое:
Message<MsgParam, UINT, WM_CREATE>

Хотелось бы сократить до такого
Message<MsgParam, WM_CREATE>

чтобы UINT вытащился из MsgParam.

ЗЫ это, впрочем, фигня. Объясните про lboss'овский вариант, пожалуйста.
... << RSDN@Home 1.1 alpha 1 >>
Re[4]: Можно сильнее извратиться....
От: Рома Мик Россия http://romamik.com
Дата: 30.06.03 09:22
Оценка:
Здравствуйте, Рома Мик, Вы писали:

РМ>Кстати, а нельзя ли победить синатксис C++ и сделать аналог такой штуки

Оп, сам догадался.
template < class Param, typename Param::Id id >
... << RSDN@Home 1.1 alpha 1 >>
Re[3]: Можно сильнее извратиться....
От: WolfHound  
Дата: 30.06.03 15:59
Оценка:
Здравствуйте, Рома Мик, Вы писали:

РМ>Я чегой-от никак не пойму: а какого лешего инстанциируются статические члены MsgResult, а конкретно m_Initializer?

Мой вариант
template<class T, int ID>
struct MsgRes
{
    MsgRes(bool res)
        :res_(res)
    {
        (void)registrator;//А вот и леший :)
    }
    operator bool(){return res_;}
    struct Registrator
    {
        Registrator()
        {
            MessageProcessor<T>::AddHandler<ID>(&Call);
        }
        static bool Call(T* t, WndMsg* msg)
        {
            Msg<ID> msg_(msg);
            return t->OnMessage(msg_);
        }
    };
    static Registrator registrator;
private:
    bool res_;
};

А фокус тут в том что когда обработчик возвращает значение компилятор вынужден инстационировать конструктор который тянет за собой registrator. Как и все гениальное просто.
... << RSDN@Home 1.1 alpha 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[4]: Можно сильнее извратиться....
От: Рома Мик Россия http://romamik.com
Дата: 30.06.03 19:10
Оценка:
Здравствуйте, WolfHound, Вы писали:

Простите непонятливого.

WH>А фокус тут в том что когда обработчик возвращает значение компилятор вынужден инстационировать конструктор который тянет за собой registrator.

Только если обработчик не зарегистрировать, он не будет вызван, а следовательно не станет возвращать значение, и как следствие registartor может и не быть инстанциирован. И у меня именно так и происходит.
Вместо отладки в таком случае неплохо бы, что компилятор генерил отчет о проделанной работе: что он сделал и почему...

Если не сложно, гляньте на мой код: 3.5 кб
Там закомментарены конструкторы Window и Wnd ( файлы main.cpp и window.h ). Если их раскомментарить, то все работает как и должно, а в противном случае — нет. Мне же кажется, что трюк я повторил почти дословно...
... << RSDN@Home 1.1 alpha 1 >>
Re[5]: Можно сильнее извратиться....
От: Рома Мик Россия http://romamik.com
Дата: 01.07.03 12:33
Оценка:
Здравствуйте, Рома Мик, Вы писали:

РМ>Если не сложно, гляньте на мой код: 3.5 кб

РМ>Там закомментарены конструкторы Window и Wnd ( файлы main.cpp и window.h ). Если их раскомментарить, то все работает как и должно, а в противном случае — нет. Мне же кажется, что трюк я повторил почти дословно...
Частично заработало.
template < class Target, class Param, typename Param::Id id >
struct MsgResult
{
    struct Registrar
    {
        Registrar()
        {
            MessageMap< Target, Param >::Register<id>();
        }

        static bool ProxyFun(Target &target, Param &param)
        {
            return target.Handle(Message<Param, id>(param));
        }
    };
    static Registrar registrar_;
    bool result_;
    MsgResult(bool result) : result_(result)
    {
        (void)registrar_;
    }
    operator bool() 
    {
        return result_;
    }
};


template < class Target, class Param, typename Param::Id id >
typename MsgResult< Target, Param, id >::Registrar MsgResult< Target, Param, id >::registrar_;

А без выделенного все компилировалось, но regisrar_ не инстанциировался.
... << RSDN@Home 1.1 alpha 1 >>
Re[4]: По мотивам "Прощания Славянки"
От: iZEN СССР  
Дата: 22.08.04 14:20
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Я уже лет шесть по разными GUI подходами занимаюсь...

CS>И вот в результате вернулся к истокам: http://terra-informatica.org/j-smile
CS>Получил массу удовольствия имплементируя.

И где ЭТО сейчас? Напишите пожалуйста.
Re: По мотивам SWL
От: Аноним  
Дата: 25.08.04 11:24
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Сейчас наткнулся на SWL

идея там на 5+ но реализация на 3-


Я, кстати, ее малость развил — добавил контролов и немного переделал их
иерархию. Сейчас есть

SWL::Button
SWL::Edit
SWL::Label
SWL::Combo
SWL::ListBox
SWL::ScrollBar
SWL::CheckBox

надо кому ?
Re[2]: По мотивам SWL
От: _nn_  
Дата: 25.08.04 11:31
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, WolfHound, Вы писали:


WH>>Сейчас наткнулся на SWL

А>идея там на 5+ но реализация на 3-


А>Я, кстати, ее малость развил — добавил контролов и немного переделал их

А>иерархию. Сейчас есть

А> SWL::Button

А> SWL::Edit
А> SWL::Label
А> SWL::Combo
А> SWL::ListBox
А> SWL::ScrollBar
А> SWL::CheckBox

А>надо кому ?


Вы выложите ее, а потом люди скажут надо или нет
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: По мотивам SWL
От: Аноним  
Дата: 25.08.04 11:57
Оценка:
Здравствуйте, _nn_, Вы писали:


__>Вы выложите ее, а потом люди скажут надо или нет



Куда ?
Re[4]: По мотивам SWL
От: _nn_  
Дата: 25.08.04 11:59
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, _nn_, Вы писали:



__>>Вы выложите ее, а потом люди скажут надо или нет



А>Куда ?

На RSDN конечно.

Положите в разделе файлы и дайте ссылку.
И ждите комментариев
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[5]: По мотивам "Прощания Славянки"
От: vdimas Россия  
Дата: 01.09.04 23:07
Оценка:
Здравствуйте, limax, Вы писали:

CS>> Хотя в твоём варианте с on(mouse_event&) эта проблема вроде исчезает, однако, по-моему, появляется другая: при добавлении в дочернем классе одной новой функции on(death_for_all&) компилятор прячет все старые on(...).


Виртуальные ф-ии не спрячешь. Ничто не помешает их переопределять в последующих потомках,
или вызывать внутри либы из базового класса. А учитывая, что, по-хорошему, все эти ф-ии являются protected, так о чем, вообще, речь???

L>Любой монолитный код, каким бы удобным и хорошо спроектированным он не был по-началу, будет когда-нибудь нуждаться в переписывании. Монолитность — bad, это у некоторых уже в определениях, в том числе и у меня.

Кстати, твой подход абсолютно стольк же монолитен, только требует в 10 раз больше монолитного кода
При смене имени классов или сообщений тебе точно так же придется везде все поменять...

L>Давай закроем тему? Это бесполезный спор. Каждый останется при своём мнении и будет пользовать тем, что ему удобнее. Тем более, что я не хочу яростно защищать ни один из существующих методов обработки сообщений — у каждого своих недостатков предостаточно.

В принципе, области применения очевидны.
Если тебуется перехватывать маленькое число сообщений в миниатюрном приложении, то подход с шаблонами рулит,
если же идет "тяжелая артиллерия", с разработкой насыщенных контролов или множества форм прикладного уровня, то вариант с виртуальными ф-иями явно предпочтительней.
Re[2]: По мотивам SWL
От: Kluev  
Дата: 02.09.04 08:03
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, WolfHound, Вы писали:


WH>>Сейчас наткнулся на SWL

А>идея там на 5+ но реализация на 3-


А>Я, кстати, ее малость развил — добавил контролов и немного переделал их

А>иерархию. Сейчас есть

А> SWL::Button

А> SWL::Edit
А> SWL::Label
А> SWL::Combo
А> SWL::ListBox
А> SWL::ScrollBar
А> SWL::CheckBox

А>надо кому ?


Давайте выложим как добавку к основной статье. Напишите Odi$$ey-у на odissey [at] rsdn [dot]ru Он выкладывал SWL на сайт.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.