今天為
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) 閱讀(2346)
評論(5) 編輯 收藏 引用 所屬分類:
GacUI