GacUI Demo:标签页

GacUI Demo:标签页
    GacUI新增了一个Demo。这里模拟了一个简单到过头了的编辑程序。界面是一个标签页,第一页里面只有一个按钮:Add Page。点中了他之后,其它页包含一个用来关掉自己的按钮,和一个多行的文本框。

    这个Demo要展示的其中一个问题是,在按下关闭按钮的时候,由于那个Page会被移除并删除,会导致按钮自己也被删除。但是事件发生过后,实际上还有很多事情要做的。所以这里展示了如何使用GacUI进行“延迟执行”,在事件结束之后再删除自己。为了方便,这个Demo使用了C++11(但是库的实现并不依赖与C++11)。先上图:





    然后我们来看代码:

#include  " ..\..\Public\Source\GacUIIncludes.h "
#include 
< Windows.h >

int  CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,  int  CmdShow)
{
    
return  SetupWindowsDirect2DRenderer();
}

class  TextBoxPage :  public  GuiTabPage
{
private :
    
static   int  pageCounter;

    GuiButton
*                 closeButton;
    GuiMultilineTextBox
*     textBox;

    
void  closeButton_Clicked(GuiGraphicsComposition *  sender, GuiEventArgs &  arguments)
    {
        
//  deleteing the tab page will also delete the button, because the button is in the page
        
//  when an event is processing, the button is not going to be deleted
        
//  because there are many works to do after this event
        
//  and maybe someone has already added another event handler to this button
        
//  so it use GetApplication()->InvokeInMainThread to send a function to the queue
        
//  so that this function will be executed after this input message (an input message raises multiple events)
        
//  to the user, this page is closed after cliking this button
        GetApplication() -> InvokeInMainThread([ this ]()
        {
            
//  remove the page and delete it
             this -> GetOwnerTab() -> RemovePage( this );
            delete 
this ;
        });
    }

    
void  OnPageContainerReady(GuiGraphicsComposition *  sender, GuiEventArgs &  arguments)
    {
        
//  create a table to place a button and a text box
        GuiTableComposition *  table = new  GuiTableComposition;
        table
-> SetRowsAndColumns( 2 1 );
        table
-> SetRowOption( 0 , GuiCellOption::MinSizeOption());
        table
-> SetRowOption( 1 , GuiCellOption::PercentageOption( 1.0 ));
        table
-> SetColumnOption( 0 , GuiCellOption::PercentageOption( 1.0 ));
        table
-> SetAlignmentToParent(Margin( 0 0 0 0 ));
        table
-> SetCellPadding( 2 );

        {
            GuiCellComposition
*  cell = new  GuiCellComposition;
            table
-> AddChild(cell);
            cell
-> SetSite( 0 0 1 1 );
            
            closeButton
= g::NewButton();
            closeButton
-> SetText(L " Close Me! " );
            closeButton
-> Clicked.AttachMethod( this & TextBoxPage::closeButton_Clicked);
            cell
-> AddChild(closeButton -> GetBoundsComposition());
        }
        
        {
            GuiCellComposition
*  cell = new  GuiCellComposition;
            table
-> AddChild(cell);
            cell
-> SetSite( 1 0 1 1 );
            
            textBox
= g::NewMultilineTextBox();
            textBox
-> GetBoundsComposition() -> SetAlignmentToParent(Margin( 0 0 0 0 ));
            textBox
-> SetText(L " You can input several lines of text here.\r\nThis is a multiple line text box. " );
            cell
-> AddChild(textBox -> GetBoundsComposition());
        }

        
this -> GetContainer() -> GetContainerComposition() -> AddChild(table);
    }

public :
    TextBoxPage()
        :closeButton(
0 )
        ,textBox(
0 )
    {
        PageContainerReady.AttachMethod(
this & TextBoxPage::OnPageContainerReady);
        
this -> SetText(L " Page  " + itow( ++ pageCounter));
    }

    
~ TextBoxPage()
    {
    }
};

int  TextBoxPage::pageCounter = 0 ;

class  TextBoxPageWindow :  public  GuiWindow
{
private :
    GuiTab
*                         tabControl;
    GuiTabPage
*                     controlPanelPage;
    GuiButton
*                     buttonAddPage;

    
void  buttonAddPage_Clicked(GuiGraphicsComposition *  sender, GuiEventArgs &  arguments)
    {
        
//  when the button is clicked, it creates a new TextBoxPage and adds it to the tab control
        TextBoxPage *  page = new  TextBoxPage;
        tabControl
-> CreatePage(page);
        tabControl
-> SetSelectedPage(page);
    }
public :
    TextBoxPageWindow()
        :GuiWindow(GetCurrentTheme()
-> CreateWindowStyle())
    {
        
this -> SetText(L " Controls.Tab.TextBoxPage " );
        
this -> GetBoundsComposition() -> SetPreferredMinSize(Size( 640 480 ));

        
//  create a tab control
        tabControl = g::NewTab();
        tabControl
-> GetBoundsComposition() -> SetAlignmentToParent(Margin( 2 2 2 2 ));
        
this -> AddChild(tabControl);

        
//  the first page is a control panel
        controlPanelPage = tabControl -> CreatePage();
        controlPanelPage
-> SetText(L " Control Panel " );

        
//  add a button to the control panel
        buttonAddPage = g::NewButton();
        buttonAddPage
-> SetText(L " Add a tab page " );
        buttonAddPage
-> Clicked.AttachMethod( this & TextBoxPageWindow::buttonAddPage_Clicked);
        controlPanelPage
-> GetContainer() -> GetContainerComposition() -> SetInternalMargin(Margin( 2 2 2 2 ));
        controlPanelPage
-> GetContainer() -> AddChild(buttonAddPage);

        
this -> ForceCalculateSizeImmediately();
        
this -> MoveToScreenCenter();
    }

    
~ TextBoxPageWindow()
    {
    }
};

void  GuiMain()
{
    GuiWindow
*  window = new  TextBoxPageWindow();
    GetApplication()
-> Run(window);
    delete window;
}

    那一大段的注释,就是在讲延迟执行的事情。看过C++11的人都知道,lambda expression实际上就是一个functor。在旧C++里面,调用InvokeInMainThread的时候,要么可以传一个void(*)(void*)和void*,要么可以传一个带operator()()的struct。在新C++里面,直接把lambda expression写在里面就好了。

    如果不使用延迟执行,在事件发生的时候把自己删掉,会导致Access Violation的发生,因为接下来要访问的对象被你删掉了。如果使用延迟执行,就可以在input message处理完之后,执行删除的代码。这样一切都是好的。

    下一个Demo就是关于文本框的操作,再下一个Demo是关于如何做用来显示代码的高亮文本框的事情。敬请期待,啊哈哈哈。

你可能感兴趣的:(GacUI Demo:标签页)