使用C++和DirectX开发游戏GUI(五)

简介: 然后就是滚动条的问题了.我的列表框包含两个成员,m_horzscrollbar和m_vertscrollbar,他们都是GUI滚动条.当列表框的大小被改变时(wm_sizechanged()),他会看看数据的宽度和高度并决定是否显示滚动条.
// represents a column in our listbox 
class gui_listbox_column 

public: 
gui_listbox_column() { } 
virtual ~gui_listbox_column() { } 

virtual void draw(uti_rectangle &where); 

void setname(const char *name) { m_name = name; } 
uti_string getname(void) { return(m_name); } 

int getwidth(void) { return(m_width); } 
void setwidth(int w) { m_width = w; } 

private: 
uti_string m_name; 
int m_width; 
}; 

// an item in our listbox 
class gui_listbox_item 

public: 
gui_listbox_item() { m_isselected = 0; m_indent = 0; } 
virtual ~gui_listbox_item() { } 

virtual draw(int colnum, uti_rectangle &where); 

void clearallcolumns(void); // boring 
void setindent(int i) { m_indent = i; } 
int getindent(void) { return(m_indent); } 

void settext(int colnum, const char *text); // boring 
uti_string gettext(int colnum = 0); // boring 

void setitemdata(unsigned long itemdata) { m_itemdata = itemdata; } 
unsigned long getitemdata(void) { return(m_itemdata); } 

void setselected(int s = 1) { m_isselected = s; } 
int getselected(void) { return(m_isselected); } 

private: 
int m_isselected; 
int m_indent; // # of pixels to indent this item 
unsigned long m_itemdata; 
uti_pointerarray m_coltext; 
}; 

// the listbox itself 
class gui_fancylistbox : public gui_window 

public: 
gui_fancylistbox() { m_multiselect = 0; } 
virtual ~gui_fancylistbox() { clear(); } 

int getselected(int iter = 0); 

virtual int wm_command(gui_window *win, int cmd, int param); 
virtual int wm_paint(coord x, coord y); 
virtual int wm_lbuttondown(coord x, coord y); 

gui_scrollbar_horz &gethscroll(void) { return(m_hscroll); } 
gui_scrollbar_vert &getvscroll(void) { return(m_vscroll); } 

virtual int wm_sizechanged(void); // the window's size has changed somehow 

gui_listbox_item *getitemat(int index); // boring 
gui_listbox_item *additem(const char *text); // boring 
int delitem(int index); // boring 
int delallitems(void); // boring 
gui_listbox_column *getcolumn(int index); // boring 
int addcolumn(const char *name, int width); // boring 
gui_listbox_column *getcolumnat(int index); // boring 
int delcolumn(int index); // boring 
int delallcolumns(void); // boring 

int clear(void); // delete columns & items 

int getnumitems(void); 
int getnumcols(void); 

void deselectall(void); 
void selectitem(int item); 
void selecttoggleitem(int item); 

void deselitem(int item); 

private: 
int m_numdispobjsy; 
int m_vertgutterwidth; // # of pixels between items vertically 

gui_scrollbar_horz m_hscroll; 
gui_scrollbar_vert m_vscroll; 

bool m_multiselect; // is this multi-selectable? 
uti_pointerarray m_items; // array of gui_listbox_items 
uti_pointerarray m_columns; // array of gui_listbox_columns 
}; 

  列表框是到现在为止你做的最难的控件吧?但这仅仅是因为它是最通用的.一个能够处理多列、缩进、多重选择列表框控件将在实践中证明他对你的游戏是不可或缺的.停下来并想想在大多数游戏里用到列表框的地方,你就会很快发现这一点. 

  我把我的列表框控件分成两部分:一个多列的"报表风格"的列表控件和一个图标列表控件,它创建一个类似于当你在windows"我的电脑"里选择大图标察看方式的显示. 

  图表列表控件比较容易建立.它使用了一列静态图标(在一次代码重用),所有的具有相同的大小.我使用图标的宽度除列表框的宽,这让我知道有几列可用.(如果证明我的列表框比大图表小,我假设我只有一列,并让绘制系统剪裁图标以使他们不会超出我的绘制区域).一旦我有了列数,我通过图标的总数除以它计算出我所需要的行数.这样我就知道我该怎样设定要包括的滚动条. 

  注意当控件改变大小时必须重新计算这些值.为此我设定了一个wm_sizechanged()消息,calcall()将会在窗口绘制区域被改变的时候调用它. 

  报表风格列表控件要复杂一些.我先写了两个辅助类,gui_listbox_column和gui_listbox_item,它们包含了所有的关于列表中给定物件和列的信息. 

  gui_listbox_column是两者中较简单的.主要的列表框类有一个成员变量身份的gui_listbox_column的动态数组,这代表了目前列表框中的列.gui_listbox_column包含了在列表框中所需要的列的所有信息,包括列的名字,列的对齐,显示或隐藏,大小等等. 

  主要的列表框类也有一个gui_listbox_item的动态数.gui_listbox_item类包含了与我们的报表风格列表框中特定行(或物件)相关的所有信息.目前这个类最重要的数据成员是代表每列数据的字串数组.我也让每个物件通过m_itemdata成员存储一个附加的32位数据.这个技术类似于windows允许你通过位你的列表物件调用SetItemData()和GetItemData()来存储32位数据.这个细节很重要,因为它允许列表框的用户为每个物件存储一个指针-通常一个与该物件有关的特定类,以使它以后可用. 

  怎么绘制列和物件呢?我倾向于在要绘制的列表框中在每个单独的物件/列上有个绝对的控件.到最后,我决定让列表控件通过不断调用两个虚函数,gui_listbox_item::draw()和gui_listbox_column::draw()来绘制他的物件和列.每个函数使用一个代表列或者物件在屏幕上位置的矩形.默认的对这些draw()函数的开发仅仅分划出与矩形中特定列和子物件相关的文本;然而,我先在可以简单的为需要独特外观的物件或列派生和重载draw().这种技术目前工作的很好,但是我还不足以宣称这是最好的方法. 

  然而,绘制物件比行需要更多的工作.物件需要用高光绘制,这决定于他们是否被选择.这并不很难,但一定不能忘记. 

  然后就是滚动条的问题了.我的列表框包含两个成员,m_horzscrollbar和m_vertscrollbar,他们都是GUI滚动条.当列表框的大小被改变时(wm_sizechanged()),他会看看数据的宽度和高度并决定是否显示滚动条. 

总结 

  真是绕了一大圈子,但是幸运的是你对为GUI创建控件有了个大致的想法.这里我想强调的是"风格就是乐趣".在做你的GUI时不要害怕创新-做做你曾经梦想过的东西,和使你的游戏最酷的东西.如果你的游戏很依赖你的GUI的效能这一点尤其重要,比如你在作即时战略游戏. 

  还要记住当创建控件的时候,你需要为你的游戏的其他部分考虑平衡问题-细节表现力和开发时间是成正比的.尽量给你的玩家最易于上手的GUI,但同时不要花时间做50种不同的控件.你要在功能、好事、复杂性、坏事中做出平衡. 

  控件就到这吧.下一章也是最后一章中我们会看看资源编辑器,序列化窗口和创建对话框.祝愉快! 
目录
相关文章
|
3月前
|
人工智能 算法 BI
第十四届蓝桥杯省赛大学C组(C/C++)三国游戏
第十四届蓝桥杯省赛大学C组(C/C++)三国游戏
|
11天前
|
IDE 开发工具 C语言
C++一分钟之-嵌入式编程与裸机开发
通过这些内容的详细介绍和实例解析,希望能帮助您深入理解C++在嵌入式编程与裸机开发中的应用,提高开发效率和代码质量。
31 13
|
5天前
|
设计模式 IDE 编译器
【C++面向对象——类的多态性与虚函数】编写教学游戏:认识动物(头歌实践教学平台习题)【合集】
本项目旨在通过C++编程实现一个教学游戏,帮助小朋友认识动物。程序设计了一个动物园场景,包含Dog、Bird和Frog三种动物。每个动物都有move和shout行为,用于展示其特征。游戏随机挑选10个动物,前5个供学习,后5个用于测试。使用虚函数和多态实现不同动物的行为,确保代码灵活扩展。此外,通过typeid获取对象类型,并利用strstr辅助判断类型。相关头文件如<string>、<cstdlib>等确保程序正常运行。最终,根据小朋友的回答计算得分,提供互动学习体验。 - **任务描述**:编写教学游戏,随机挑选10个动物进行展示与测试。 - **类设计**:基类
18 3
WK
|
2月前
|
机器学习/深度学习 人工智能 算法
那C++适合开发哪些项目
C++ 是一种功能强大、应用广泛的编程语言,适合开发多种类型的项目。它在游戏开发、操作系统、嵌入式系统、科学计算、金融、图形图像处理、数据库管理、网络通信、人工智能、虚拟现实、航空航天等领域都有广泛应用。C++ 以其高性能、内存管理和跨平台兼容性等优势,成为众多开发者的选择。
WK
121 1
|
3月前
|
Rust 资源调度 安全
为什么使用 Rust over C++ 进行 IoT 解决方案开发
为什么使用 Rust over C++ 进行 IoT 解决方案开发
114 7
WK
|
2月前
|
开发框架 移动开发 Java
C++和Java哪个更适合开发移动应用
本文对比了C++和Java在移动应用开发中的优劣,从市场需求、学习难度、开发效率、跨平台性和应用领域等方面进行了详细分析。Java在Android开发中占据优势,而C++则适合对性能要求较高的场景。选择应根据具体需求和个人偏好综合考虑。
WK
78 0
WK
|
2月前
|
安全 Java 编译器
C++和Java哪个更适合开发web网站
在Web开发领域,C++和Java各具优势。C++以其高性能、低级控制和跨平台性著称,适用于需要高吞吐量和低延迟的场景,如实时交易系统和在线游戏服务器。Java则凭借其跨平台性、丰富的生态系统和强大的安全性,广泛应用于企业级Web开发,如企业管理系统和电子商务平台。选择时需根据项目需求和技术储备综合考虑。
WK
133 0
|
3月前
|
NoSQL API Redis
如何使用 C++ 开发 Redis 模块
如何使用 C++ 开发 Redis 模块
|
4天前
|
C++ 芯片
【C++面向对象——类与对象】Computer类(头歌实践教学平台习题)【合集】
声明一个简单的Computer类,含有数据成员芯片(cpu)、内存(ram)、光驱(cdrom)等等,以及两个公有成员函数run、stop。只能在类的内部访问。这是一种数据隐藏的机制,用于保护类的数据不被外部随意修改。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。成员可以在派生类(继承该类的子类)中访问。成员,在类的外部不能直接访问。可以在类的外部直接访问。为了完成本关任务,你需要掌握。
41 18
|
4天前
|
存储 编译器 数据安全/隐私保护
【C++面向对象——类与对象】CPU类(头歌实践教学平台习题)【合集】
声明一个CPU类,包含等级(rank)、频率(frequency)、电压(voltage)等属性,以及两个公有成员函数run、stop。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。​ 相关知识 类的声明和使用。 类的声明和对象的声明。 构造函数和析构函数的执行。 一、类的声明和使用 1.类的声明基础 在C++中,类是创建对象的蓝图。类的声明定义了类的成员,包括数据成员(变量)和成员函数(方法)。一个简单的类声明示例如下: classMyClass{ public: int
31 13