游戏开发论坛

 找回密码
 立即注册
搜索
查看: 8580|回复: 22

创建基于c++标准程序库的Windows + Directx通用库,寻找同好者

[复制链接]

20

主题

136

帖子

172

积分

注册会员

Rank: 2

积分
172
发表于 2008-1-20 03:38:00 | 显示全部楼层 |阅读模式
我一直认为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;
      };
    };
  };

35

主题

1735

帖子

1739

积分

金牌会员

Rank: 6Rank: 6

积分
1739
QQ
发表于 2008-1-20 09:52:00 | 显示全部楼层

Re:创建基于c++标准程序库的Windows + Directx通用库,寻找同

最对大工程,希望不要半途而废。

2

主题

683

帖子

687

积分

高级会员

Rank: 4

积分
687
发表于 2008-1-20 13:05:00 | 显示全部楼层

Re:创建基于c++标准程序库的Windows + Directx通用库,寻找同

设计过度也是灾难

9

主题

249

帖子

260

积分

中级会员

Rank: 3Rank: 3

积分
260
发表于 2008-1-20 14:30:00 | 显示全部楼层

Re:创建基于c++标准程序库的Windows + Directx通用库,寻找同

这种大工程,坚持到最后才是正果!
我也不太喜欢MFC,但又不得不用!

0

主题

243

帖子

357

积分

中级会员

Rank: 3Rank: 3

积分
357
发表于 2008-1-20 23:52:00 | 显示全部楼层

Re:创建基于c++标准程序库的Windows + Directx通用库,寻找同

不喜欢用MFC的强烈推荐wxWidget + dialogblocks哈,超好用的

20

主题

136

帖子

172

积分

注册会员

Rank: 2

积分
172
 楼主| 发表于 2008-1-23 22:44:00 | 显示全部楼层

Re:创建基于c++标准程序库的Windows + Directx通用库,寻找同

[LoserPower]实现基于非对话框的模态窗口:

主要实现环节:
1)消息循环的控制权
2)禁止/激活父窗口的鼠标/键盘等消息
3)处理WM_CLOSE,手动删除资源和执行状态管理,归还控制权等

外部调用
modalwindow w;
if (w.modal(this) == IDOK)
  message_box(t("程序被请求终止")), close();
return 0;

unsigned int modal(window* parent_)
{
  parent = parent_;
1)创建窗口,但不显示
  app_style(WS_VISIBLE, true /* remove_ */);
  create(parent);
2)对齐窗口
  center_window();
  display();
3)禁用父窗口
  parent->enablewindow(false);
  is_model = true;
4)保存消息循环状态
  app->save_loop_window();
5)由当前窗口执行消息循环
  app->do_loop(this);
6)恢复消息循环状态
  app->restore_loop_window();
7)返回状态码
  return id_feed_back;
}

截获关闭消息
virtual LRESULT on_close()
{
  if (capture_close())
    _Release();
  return 0;
}

析构
virtual ~window()
{
  _Release();
}

销毁过程
bool _Release()
{
1)检查窗口是否销毁
  if (!hwnd)
    return false;
2)激活模态父窗口
  if (is_model)
    parent->enablewindow(), parent->send_message(WM_ACTIVATE, WPARAM(WA_ACTIVE),LPARAM(0)) ;
3)销毁当前窗口
  while(IsWindow(hwnd))
    DestroyWindow(hwnd);

4)取消消息路由登记信息,必须在销毁方法后,以便接收WM_DESTROY等消息
判断消息路由登记表的大小以便在应用程序管理器被销毁时不会发生异常(如主窗口取消对消息循环的管理导致应用程序退出,子窗口不能及时完成取消登记动作,就已经由应用程序管理器自动放弃维护)
  if(app->windows_map.size())
    app->windows_map.erase(hwnd);

5)析构委托器
  for (map_type::iterator itr = message_map.begin(); itr != message_map.end(); ++itr)
    delete[] itr->second;

  for (map_type::iterator itr = command_map.begin(); itr != command_map.end(); ++itr)
    delete[] itr->second;

6)归还消息循环的控制权,对于主窗口,这导致没有有效的其他管理窗口的接收,而导致程序退出
  if (app->get_loop_window() == this)
    app->set_loop_window(0);

7)清除句柄,并通知派生类析构动作可以释放资源
  hwnd = 0;
  return true;
}

具体类的析构形式

virtual ~inherit_window()
{
  if (_Base::_Release())
  {
    /*...*/
  }
}

模态窗口类的命令响应

LRESULT onok(unsigned int, void*)
{
  feedback(ok.id());
  return 0;
}

LRESULT oncancel(unsigned int, void*)
{
  feedback(cancel.id());
  return 0;
}

5

主题

755

帖子

757

积分

高级会员

Rank: 4

积分
757
发表于 2008-1-24 14:42:00 | 显示全部楼层

Re:创建基于c++标准程序库的Windows + Directx通用库,寻找同

你不用mfc也可以啊。只要有一套可行的UI拿游戏引擎带动。一样的

3

主题

5

帖子

7

积分

新手上路

Rank: 1

积分
7
发表于 2008-1-26 11:12:00 | 显示全部楼层

Re: 创建基于c++标准程序库的Windows + Directx通用库,寻找同

太赞了,虽然我还处于抄书的阶段,我也想做个这样的东西来的......

119

主题

1367

帖子

1393

积分

金牌会员

Rank: 6Rank: 6

积分
1393
发表于 2008-1-26 13:13:00 | 显示全部楼层

Re:创建基于c++标准程序库的Windows + Directx通用库,寻找同

GUI引擎,已经有人发明过了,可能你能做的更好
但还是建议楼主不如拿别人的源码去改,这重复造轮子的事情意义不大

121

主题

2029

帖子

2034

积分

金牌会员

Rank: 6Rank: 6

积分
2034
QQ
发表于 2008-1-26 22:07:00 | 显示全部楼层

Re:创建基于c++标准程序库的Windows + Directx通用库,寻找同

CEGUI...
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-12-20 04:40

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表