随笔-341  评论-2670  文章-0  trackbacks-0
    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(21);
        table
->SetRowOption(0, GuiCellOption::MinSizeOption());
        table
->SetRowOption(1, GuiCellOption::PercentageOption(1.0));
        table
->SetColumnOption(0, GuiCellOption::PercentageOption(1.0));
        table
->SetAlignmentToParent(Margin(0000));
        table
->SetCellPadding(2);

        {
            GuiCellComposition
* cell=new GuiCellComposition;
            table
->AddChild(cell);
            cell
->SetSite(0011);
            
            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(1011);
            
            textBox
=g::NewMultilineTextBox();
            textBox
->GetBoundsComposition()->SetAlignmentToParent(Margin(0000));
            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(640480));

        
// create a tab control
        tabControl=g::NewTab();
        tabControl
->GetBoundsComposition()->SetAlignmentToParent(Margin(2222));
        
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(2222));
        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是关于如何做用来显示代码的高亮文本框的事情。敬请期待,啊哈哈哈。
posted on 2012-04-30 23:28 陈梓瀚(vczh) 阅读(1998) 评论(2)  编辑 收藏 引用 所属分类: GacUI

评论:
# re: GacUI Demo:标签页 2012-05-01 06:31 | CY
AttachMethod如果是只有一个响应或者最后一个响应里面delete自己,应该能侥幸没事不?  回复  更多评论
  
# re: GacUI Demo:标签页 2012-05-01 09:55 | 陈梓瀚(vczh)
@CY
不能  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理