今天为
GacUI写了一个新的Demo,展示了一些可以自动排版的按钮。主要的设想就是在窗口上放一个表格,分成两行两列。上面的按钮占满一整行,下面两个单元格放两个按钮。然后就可以设置每个行和列占整个表格的比例,在这个Demo里面都设置成50%。这样每当窗口缩放的时候,按钮的位置也会随之重新排版。然后设置表格充满整个窗口,这样窗口的最小值就会被表格的内容所限定,这样试图把窗口缩小的时候,就会有一个最小的尺寸限制着,至始至终保证所有的东西都可以显示出来,不会因为窗口太小而只显示一半。按钮也是同样,可以设置它必须显示所有的文字。所有的过程一旦配置好之后,计算尺寸的时候所有的操作都会自动做,程序员不需要为窗口的Resize事件写任何代码。
下面先放图。
第一个图是窗口刚刚打开的时候的样子。因为Demo里面没有设置窗口的尺寸,所以一上来就自动变成了最小的尺寸——并且刚好可以显示所有的内容。
第二个图是窗口放大之后的样子。Disable按钮被按下了,所以上面的按钮就变灰。
这个Demo使用了Direct2D渲染器,所有的绘制过程都十分高速。而且表格的尺寸计算也是经过优化的,在拖放窗口的时候十分流畅。事实上按钮的渐变啊、边框啊、文字等等也是借助表格排版的。由于尺寸计算过于复杂,除了表格之外整个框架都不保存控件的尺寸,所有的东西都在需要的时候——譬如说渲染的时候,譬如说计算鼠标点中的位置——的那一刻才开始算。因此无论是鼠标滑过,或者是窗口拖放,都拼命地执行很多虚函数。可见C++的虚函数的性能之高,几乎永远都不会成为程序的瓶颈。下面来看代码:
#include "..\..\Public\Source\GacUIIncludes.h"
#include <Windows.h>
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int CmdShow)
{
return SetupWindowsDirect2DRenderer();
}
class EnableDisableWindow : public GuiWindow
{
private:
GuiButton* buttonTarget;
GuiButton* buttonEnable;
GuiButton* buttonDisable;
void buttonEnable_OnClick(GuiGraphicsComposition* sender, GuiEventArgs& arguments)
{
buttonTarget->SetEnabled(true);
}
void buttonDisable_OnClick(GuiGraphicsComposition* sender, GuiEventArgs& arguments)
{
buttonTarget->SetEnabled(false);
}
public:
EnableDisableWindow()
:GuiWindow(GetCurrentTheme()->CreateWindowStyle())
{
this->SetText(L"Controls.Button.EnableDisable");
// limit the size that the window should always show the whole content without cliping it
this->GetContainerComposition()->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);
// create a table to layout the 3 buttons
GuiTableComposition* table=new GuiTableComposition;
// make the table to have 2 rows
table->SetRowsAndColumns(2, 2);
table->SetRowOption(0, GuiCellOption::PercentageOption(0.5));
table->SetRowOption(1, GuiCellOption::PercentageOption(0.5));
table->SetColumnOption(0, GuiCellOption::PercentageOption(0.5));
table->SetColumnOption(1, GuiCellOption::PercentageOption(0.5));
// dock the table to fill the window
table->SetAlignmentToParent(Margin(10, 10, 10, 10));
// add the table to the window;
this->GetContainerComposition()->AddChild(table);
// add the target button
{
GuiCellComposition* cell=new GuiCellComposition;
table->AddChild(cell);
// this cell is the top cell
cell->SetSite(0, 0, 1, 2);
buttonTarget=g::NewButton();
buttonTarget->SetText(L"Enable or disable me using the buttons below!");
// ensure that the buttonTarget display the whole text
buttonTarget->GetBoundsComposition()->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);
// dock the button to fill the cell
buttonTarget->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 3));
// add the button to the cell
cell->AddChild(buttonTarget->GetBoundsComposition());
}
// add the enable button
{
GuiCellComposition* cell=new GuiCellComposition;
table->AddChild(cell);
// this cell is the bottom left cell
cell->SetSite(1, 0, 1, 1);
buttonEnable=g::NewButton();
buttonEnable->SetText(L"Enable");
buttonEnable->GetBoundsComposition()->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);
buttonEnable->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 3, 3, 0));
buttonEnable->Clicked.AttachMethod(this, &EnableDisableWindow::buttonEnable_OnClick);
cell->AddChild(buttonEnable->GetBoundsComposition());
}
// add the disable button
{
GuiCellComposition* cell=new GuiCellComposition;
table->AddChild(cell);
// this cell is the bottom right cell
cell->SetSite(1, 1, 1, 1);
buttonDisable=g::NewButton();
buttonDisable->SetText(L"Disable");
buttonDisable->GetBoundsComposition()->SetMinSizeLimitation(GuiGraphicsComposition::LimitToElementAndChildren);
buttonDisable->GetBoundsComposition()->SetAlignmentToParent(Margin(3, 3, 0, 0));
buttonDisable->Clicked.AttachMethod(this, &EnableDisableWindow::buttonDisable_OnClick);
cell->AddChild(buttonDisable->GetBoundsComposition());
}
// change the button font
{
FontProperties font;
font=buttonTarget->GetFont();
font.size=20;
buttonTarget->SetFont(font);
buttonEnable->SetFont(font);
buttonDisable->SetFont(font);
}
// call this to calculate the size immediately if any indirect content in the table changes
// so that the window can calcaulte its correct size before calling the MoveToScreenCenter()
table->UpdateCellBounds();
// update the size
this->SetBounds(Rect());
// move to the screen center
this->MoveToScreenCenter();
}
~EnableDisableWindow()
{
}
};
void GuiMain()
{
GuiWindow* window=new EnableDisableWindow();
GetApplication()->Run(window);
delete window;
}
代码里面充满了注释,而且主要的内容也在上面介绍了,在这里我就不罗嗦了。所有的代码都可以在
http://gac.codeplex.com中,下载最新的代码,然后在Libraries\GacUI\GacUIDemo\GacUIDemo.sln下面找到。
posted on 2012-04-25 02:46
陈梓瀚(vczh) 阅读(2332)
评论(5) 编辑 收藏 引用 所属分类:
GacUI