Dx11 UI 设计草案(一) 框架及 简单窗体 【附带源码】

这篇 笔记 是在 上一篇 《键盘控制 显示静态文本【已完成】【附带源码】(只能处理 大写英文字母)》 代码上修改过来的, 其中添加了一些还处于 设计阶段的代码,但不影响本随笔的 主要方向, 设计基于 Dx11 的简单UI, 设计参考自 《DirectX9 User Interface Design and Implementation》。先来张类关系图吧( 不是正规的UML 表示图):

新添加 的 UI 子框架 与 原先系统的结合除主要在 SystemClass 的 OnRender() 渲染函数中:

void SystemClass::Render()
{
    if( d3dContext_ == 0 )
        return;

    float clearColor[ 4] = { 0.2f, 0.22f, 0.24f, 1.0f};
    d3dContext_->ClearRenderTargetView( backBufferTarget_, clearColor);
    
        
    std::vector< SentenceType>::iterator iter;
    for( iter = m_sentenceList.begin(); iter != m_sentenceList.end(); ++ iter )
    {
        m_TextSystem->UpdateAndDrawSentence( d3dContext_, width_, height_, 
            iter->sentence.c_str(),
            iter->left, 
            iter->top );
    }

    m_Destop->PostMessageDown( WM_RENDER, 0, 0, 0);

    swapChain_->Present( 0, 0);
}
红色加黑 代码m_Destop->PostMessageDown( WM_RENDER, 0, 0, 0); 即是渲染 UI 控件的开始部分; 首先 SystemClass 中有两个 全局UI 窗体控件: m_Destop 和 (内注)母窗体:

无论 是CXWindow 还是其他诸如 CXButton, CXCheckBox, CXLabel 等 都是继承自 基类 CXControl 的子类, 代码逻辑上是:


这个 UI 由一个 “桌面”的主窗体引领, 该“桌面” 上布满各种 “窗体”, “窗体”上有各种控件, 控件又可以由各种其他控件组成, 这种设计方式参考自 《DirectX9 User Interface Design and Implementation》:

Class CXWindow as a Parent[1]

There are two window stypes disscussed here, the first window style to consider is analogous to the destop, the parent window. Generally, it is the top frame, or top window, in an application of which all other windows are children -- much like an MDI program. Thus, our Direct3D applications only have one parent window. To UILIB, this is hierarchically the topmost control where all messages are posted and then dispatched downward through child chontrols. Parctically, the parent window will be invisible and sized to match the client area of the application window. Figures 9.2 and 9.3 illustrate the parent window in terms of being like a destop.


These are the most important features of the parent window:
  • The parent window if the topmost control in a hierarchy. It has no parent itself, except for the screen.
  • As a window, it cannot be dragged, moved, minimized, or resized. It must remain static and in one place, like a permanently fixed frame.
  • Its canvas respresents the greatest extents of an interface in terms of width and height. Every control exists within its boundaries and nothing can pass through them.
  • It is essentially the representative of an interface. All messages and events should be posted here only, using the PostMessage(注:在代码中,被修改为 PostMessageDown, 因为和 系统的 PsotMessage 忌讳) method of CXControl. From here, the desktop will implicitly handle how messages are then dispatched to children in the form of events.
  • Being the topmost control in a hierarchy, the parent window effectively controls the lifetime of every object in an interface. When the parent is removed from memory, all children will be too.

 

Implementing the Parent Window

Considering the power the parent has and its importance for an interface, CXWindow in terms of the parent window is actually relatively simple to implement. This is primarily because most of the parent's functionality has been already been implemented into CXControl. It can already become part of a hierarchy, already pass messages downward as events, and already has width and height. In fact, there is nothing further that needs to this class to make it a suitable parent frame. Of course, you caould add a function to load an image onto its canvas to use a kind of desktop background. However, image loading is something we will consider soon as we examine CXWindow in terms of a standard child window. This is something that requires more thought, and it is to this subject that we must now turn.

 

CXWindow as a Child Window

The second form of window that CXwindow encapsulates is a child window. This is more prevalent and in keeping with our understanding of a window. It is a Direct3D version of the typical frame that can be dragged and minimized, and applications can have as many instances of it as they want. It will be like all the child windows of an MDI application. Figures 9.4 and 9.5 illustrate a child window.

These are some of the most important properties of child windows:

  • Child windows, as all controls, are children of the parent window or ultimately trace their ancestry to this control. In other words, child windows are descendants of the parent but can be children to other child windows too.
  • Child windows define the greatest geometrical extents in terms of width and height beyond which its children cannot exist. In other words, controls can move freely within their window's boundaries but not beyond them. To this extent, windows are a container for controls.
  • Unless invisible, hild windows always paint upon their canvas. They might show images loaded from files or elsewhere. Ultimately, this image acts as a window background.
  • Child windows can be dragged around the screen. Because its child controls are dependent upon the window for their position and size, as a window is dragged all contrined controls should logically follow.
  • Like the parent window, controls depend upon a child window for subsistence. Effectively, this means controls cannot exist if their parent is destroyed. If a window is removed from memory, its children will follow.

Implementing Child Windows

Child windows require more work to implement than parent windows.This is because we must code specific behaviors like painting, dragging, and minimizing. Consequently, the following functions and properties have been added to class CXWindow, and details of these features are discussed in following subsections.

class CXControl{
private:
protected:
    DWORD m_Width;    // width of canvas
    DWORD m_Height;    // height of canvas
    bool  m_Visible;    // visibility of canvas
    
    CXTexture*    m_Canvas;    // the canvas itself
    CXSprite*    m_Sprite;

    CXControl* m_ChildControls;
    CXControl* m_Parent;
    CXControl* m_NextSibling;
    CXControl* m_PreviousSibling;
    
    XMFLOAT2    m_Position;

    bool m_Focus;
    CXControl* m_FocusControl;

    bool m_Depressed ;

public:
    CXControl( void);
    ~CXControl( void);

    CXSprite* GetSpirite( void) const;
    void SetSpirite( CXSprite* Spirite);

    CXTexture* GetCanvas( void) const;
    void SetCanvas( CXTexture* canvas);
    
    bool GetVisible( void) const;
    void SetVisible( bool visible);


    float GetWidth( void) const;
    void SetWidth( DWORD width);

    float GetHeight( void) const;
    void SetHeight( DWORD height);
    void SetWidthHeight( DWORD width, DWORD height);

    CXControl* AddChildControl( CXControl* Control);
    CXControl* GetFirstChild( void) const;
    void SetFirstChild( CXControl* Control);

    CXControl* GetParentControl( void) const;
    void SetParentControl( CXControl* Control);

    CXControl* GetNextSibling( void) const;
    void SetNextSibling( CXControl* Control);

    CXControl* GetPreviousSibling( void) const;
    void SetPreviousSibling( CXControl* Control);

    CXControl* RemoveChildControl( CXControl* Control);
    void RemoveAllChildren( void);
    int GetChildCont( void) const;

    void SetXYPos( float x, float y);
    void SetPosition( float x, float y);
    void SetPosition( const XMFLOAT2& Position);
    void SetPosition( const XMFLOAT2* Position);
    XMFLOAT2* GetPosition( void);
    const XMFLOAT2& GetConstPosition( void) const;
    const XMFLOAT2* GetConstPositionPtr( void) const;

    float GetXPos( void ) const;
    void SetXPos( float x);

    float GetYPos( void ) const;
    void SetYPos( float y);

    void GetAbsolutePosition( XMFLOAT2& Position) const;
    void GetAbsolutePosition( XMFLOAT2* Position) const;

    virtual void OnMouseDown( int Button, int X, int Y) = 0;
    virtual void OnMouseMove( int X, int Y) = 0;
    virtual void OnMouseUp( int Button, int X, int Y) = 0;
    bool PostMessageDown( UINT msg, WPARAM wParam, LPARAM lParam, void* Data );
    bool IsCursorIntersect( float X, float Y);
    
    CXControl* PostToAll( UINT msg, WPARAM wParam, LPARAM lParam, void* Data);

    virtual void OnKeyDown( WPARAM Key, LPARAM Extended ) = 0;
    virtual void OnKeyUp( WPARAM Key, LPARAM Extended ) = 0;
    CXControl* GetFocusControl( void) const;
    void SetFocusControl( CXControl* Control);

    virtual bool  OnRender() = 0;

    CXControl* CXControl::PostToAllReverse( CXControl* Control, UINT msg, WPARAM wParam, LPARAM lParam, void* Data);
    void CXControl::MoveToFront( CXControl* Control);


};

 

 下图是 运行后的 效果, 有一个窗体(其背景是一张图片), 暂未考虑 多窗体及其他控件的情况。

接下来是 源代码: D3DTextDemo_UI_window.rar


参考文献:

[1]. Alan.《DirectX9 User Interface Design and Implementation》.Wordware Publishing,Inc. 2004 : 9.4section
posted @ 2013-01-23 23:10  Wilson-Loo  阅读(1874)  评论(0编辑  收藏  举报