|
|
我一直认为MFC是一个错误。凡是基于宏机制的实现都应该被摒弃。
我正在设计一个基于c++标准程序库的Windows + Directx通用库。构建于模板化委托器和多次重载注册符的消息映射机制,并为此创建了一个准开源项目(2008年1月17日)。
http://gforge.osdn.net.cn/plugins/scmsvn/viewcvs.php/?root=loserpower
欢迎同好者一起开展工作,或者指出改进或不足的地方,OICQ:158197295
初衷:替代Win32API和MFC,正确的面向对象、模板设计风格,并和包装dx的渲染库协同工作。
特色:
1)和STL构建思想一脉相承,绝大部分使用到的容器类均依赖于STL。
2)使用了自动字符串类型,可以在ansi/unicode编辑环境、ansi/unicode编译器、ansi/unicode目标系统正确工作,并且只需要编制一次代码。
3)仅仅设计和编写了若干天,大量的工作是对API概念的封装,子任务是:对象序列化、扩展Windows界面特性。接续任务是dx和演算库的构建。
基本实现概述:
1)基本窗口维护一个消息映射:
typedef invoke_root invoke_type;
typedef std::map<unsigned int, invoke_type*> map_type;
typedef std::pair<unsigned int, invoke_type*> sub_type;
map_type message_map;
map_type command_map;
2)应用于消息映射的委托器基类
//委托器
class invoke_root
{
public:
typedef void class_type;
invoke_root(class_type* This_)
:This(This_)
{
}
virtual LRESULT operator()(WPARAM, LPARAM) = 0;
protected:
class_type* This;
};
3)一个派生的委托器
//LRESULT (ClsTy::*)(unsigned int, int, int)
template<typename ClsTy> class invoke_ui_i_i
:public invoke_root
{
public:
typedef invoke_ui_i_i _Type;
typedef unsigned int arg_type_1;
typedef int arg_type_2;
typedef int arg_type_3;
typedef LRESULT(ClsTy::*method_type)(arg_type_1, arg_type_2, arg_type_3);
_Type(class_type* This_, method_type Met_)
:invoke_root(This_), Method(Met_)
{}
virtual LRESULT operator()(WPARAM wparam, LPARAM lparam)
{
arg_type_1 arg1 = arg_type_1(wparam);
arg_type_2 arg2 = arg_type_2(HIWORD(lparam));
arg_type_3 arg3 = arg_type_3(LOWORD(lparam));
return (reinterpret_cast<ClsTy*>(This)->*Method)(arg1, arg2, arg3);
}
private:
method_type Method;
};
4)消息类
//消息类
struct wm_null_tag
{
const static unsigned int wm_value = WM_NULL;
}wm_null;
struct wm_size_tag
:public wm_null_tag
{
static const unsigned int wm_value = WM_SIZE;
static const unsigned int maxhide = SIZE_MAXHIDE;
static const unsigned int maximized = SIZE_MAXIMIZED;
static const unsigned int maxshow = SIZE_MAXSHOW;
static const unsigned int minimized = SIZE_MINIMIZED;
static const unsigned int restored = SIZE_RESTORED;
}wm_size;
4)匹配符:
//=======================================================================
//WM_CREATE
//LRESULT (ClsTy::*)(unsigned int type, int x, int y)
//type 窗口状态
//x 宽度
//y 高度
//=======================================================================
template<typename ClsTy> void invoke(wm_size_tag, typename invoke_ui_i_i<ClsTy>::method_type met, ClsTy* this_val)
{
this_val->message_map[wm_size_tag::wm_value]
= static_cast<invoke_root*>(new invoke_ui_i_i<ClsTy>(this_val, met));
}
5)委托:
void window::_Invokes()
{
invoke(wm_command, on_command, this);
}
private:
virtual void window::invokes()
{
_Invokes();
}
6)派生窗口类委托:
private:
virtual void _Inherit::invokes()
{
invoke(wm_create, on_create, this);
invoke(wm_paint, on_paint, this);
invoke(btn.id(), on_btn, this);
invoke(btn1.id(), on_btn1, this);
_Base::_Invokes();
}
7)消息函数:
virtual LRESULT window: n_command(unsigned int code, unsigned int id, void* handle_)
{
map_type::iterator itr = command_map.find(map_type::key_type(id));
if(itr != command_map.end())
return (*itr->second)(WPARAM(code), LPARAM(handle_));
return -1;
}
8)消息分发器:
LRESULT __stdcall global_wndproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
window* ptr_target_window = app->windows_map[hwnd];
if (ptr_target_window)
return ptr_target_window->call_back(hwnd, message, wparam, lparam);
else if (ptr_target_window = _CreateLock::_CreateWindow)
return ptr_target_window->call_back(hwnd, message, wparam, lparam);
else if (std::find(catch_messages, catch_messages + sizeof(catch_messages) / sizeof(unsigned), message) != catch_messages + sizeof(catch_messages) / sizeof(unsigned))
{
message_package mp = {hwnd, message, wparam, lparam};
app->message_pump.push(mp);
}
return DefWindowProc(hwnd, message, wparam, lparam);
}
9)消息指派器:
virtual LRESULT window::call_back(HWND hwnd, unsigned int message, WPARAM wparam, LPARAM lparam)
{
if (message == WM_DESTROY && hwnd == app->get_main_window()->get_hwnd())
PostQuitMessage(0);
map_type::const_iterator itr = message_map.find(message);
if(itr != message_map.end())
return (*itr->second)(wparam, lparam);
else
return DefWindowProc(hwnd, message, wparam, lparam);
}
该指派器将依据消息索引和相关委托器对接。
10)全局管理器:
std::auto_ptr<framework::application> app(new framework::application);
template<typename AppTy>void set_application()
{
app.reset(new AppTy);
}
11)window派生类风格强制。
#include "window.h"
namespace los
{
namespace control
{
using namespace los::stringtypes;
using namespace los::control::messages;
class button
:public window
{
public:
typedef _Type _Base;
typedef button _Type;
_Type(int id_, const tchar* text_)
:_Base(t("Button"), text_)
,_Id(id_)
{
_Base::hmenu = (HMENU)_Id;
}
virtual void create(HWND hparent_)
{
_Create(hparent_);
}
unsigned int id()
{
return _Id;
}
protected:
void _Create(HWND hparent_)
{
set_style(WS_CHILD);
_Base::_Create(hparent_);
}
private:
unsigned int _Id;
};
};
};
|
|