精华内容
下载资源
问答
  • 窗体管理WindowManager用来做什么的? 这真正给我们使用的窗体管理,我们想打开一个窗体,就调用它好了。比如: WindowManager.Instance.OpenWindow(WindowType.StoreWindow); 我们之前写了很多接口,...

    大家好,我是SKODE。

    小提示:选中左侧目录,可快速找到所需内容

    本系列博客地址:传送门

     

    一、本节目标

    窗体管理类WindowManager是用来做什么的?

    • 这是真正的给我们使用的窗体管理类,我们想打开一个窗体,就调用它好了。比如:
    WindowManager.Instance.OpenWindow(WindowType.StoreWindow);
    • 我们之前写了很多接口,但哪些窗体要用到这些接口脚本呢?所以这脚本还用于初始化我们要用到的窗体,即我们要将用到的窗体在这添加进去。

     

     

    二、窗体管理类:WindowManager

    在Assets/MVCLibrary下创建该脚本。内容如下:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using MVCLibrary.View;
    using UnityEditor.PackageManager.UI;
    using UnityEngine;
    
    public class WindowManager : MonoSingleton<WindowManager>
    {
        Dictionary<WindowType, BaseWindow> windowDic = new Dictionary<WindowType, BaseWindow>();
    
        /// <summary>
        /// 构造函数,完成窗体初始化
        /// </summary>
        public WindowManager()
        {
            //我们就在这,添加我们要用到的窗体
            //商城
            windowDic.Add(WindowType.StoreWindow, new StoreWindow());
        }
    
        public void Update()
        {
            //实现基类BaseWindow的Update不停执行
            foreach (var window in windowDic.Values)
            {
                if (window.IsVisable())
                {
                    window.Update(Time.deltaTime);
                }
            }
        }
    
        /// <summary>
        /// 打开窗口
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public BaseWindow OpenWindow(WindowType type)
        {
            BaseWindow window;
            if (windowDic.TryGetValue(type, out window))
            {
                window.Open();
                return window;
            }
            else
            {
                Debug.LogError($"Open Error:{type}");
                return null;
            }
        }
    
        /// <summary>
        /// 关闭窗口
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public void CloseWindow(WindowType type)
        {
            BaseWindow window;
            if (windowDic.TryGetValue(type, out window))
            {
                window.Close();
            }
            else
            {
                Debug.LogError($"Close Error:{type}");
            }
        }
    
        /// <summary>
        /// 预加载窗体(若当前场景跟该UI设置的场景类型相同,就可预加载该UI)
        /// </summary>
        /// <param name="type"></param>
        public void PreLoadWindow(SceneType type)
        {
            foreach (var item in windowDic.Values)
            {
                if (item.GetSceneType() == type)
                {
                    item.PreLoad();
                }
            }
        }
    
        /// <summary>
        /// 隐藏掉某个类型的所有窗口
        /// </summary>
        /// <param name="type">要被卸载(只是close了)的类型</param>
        /// <param name="isDestroy">是否强制卸载(销毁了)</param>
        public void HideAllWindow(SceneType type, bool isDestroy = false)
        {
            foreach (var item in windowDic.Values)
            {
                if (item.GetSceneType() == type)
                {
                    item.Close(isDestroy);
                }
            }
        }
    }

     

     

    一起进步

    我是SKODE

    展开全文
  • 窗体显示

    2017-07-10 15:27:00
    窗体在前面已经注冊。而且已经创建出来了。但这时这个窗体并不能出如今我们眼前,又是什么...另外创建窗体之后在系统看来窗体已经是可用。这时能够先在窗体上画图,当完毕时再一次性显示出来。也避免窗体不...

    窗体在前面已经注冊。而且已经创建出来了。但这时这个窗体并不能出如今我们的眼前,又是什么原因呢?哦,还不显示出来。原来是有原因的,就是窗体有多种状态,窗体能够隐藏、普通显示、最大化显示、最小化显示等。

    而且创建出来时,不马上显示。也是能够方便一性地创建非常多非常多窗体,最后才一次性地显示出来;另外创建窗体之后在系统看来窗体已经是可用的。这时能够先在窗体上画图,当完毕时再一次性显示出来。也避免窗体不断地刷新时窗体在闪动。看起来让人眼花缭乱。因而在这里就封装一个窗体显示类Window。这个类非常easy。它的代码例如以下:

    #开发者:蔡军生(QQ:9073204) 深圳  2014-8-24
    #窗体类
    class Window:
        def __init__(self, hWnd):
            self.hWnd = hWnd
        def Display(self, cmdShow):
            windll.user32.ShowWindow(self.hWnd, cmdShow)
            windll.user32.UpdateWindow(self.hWnd)

    在这个类里主要提供构造函数__init__和显示函数Display

    在构造函数里主要是创建保存窗体句柄的成员变量self.hWnd,用来保存相应的窗体与本类的关系。

    显示函数Display主要是调用系统的API函数ShowWindow把窗体显示出来,调用系统的API函数UpdateWindow把窗体的客户区进行更新。

    到这里已经把界面操作功能封装成三个类:WinClassMakerWinMakerWindow。这三个类的功能是各司其职,WinClassMaker是负责把窗体样式注冊,定制不同的窗体类型;WinMaker是负责样式定下来的窗体创建一个实体对象出来,站在开发者的角度就是分配内存给一个对象;Window是负责把窗体显示、隐藏或者相应的移动等操作。

    因为这三部分是全部窗体类的基本功能,以后再须要创建新的窗体,都能够继承这三个类来进行复用代码。

    把这三个类放在一起,就把前面的样例代码再重写一遍,就变成了以下这个样子:

    #windows应用程序
    #使用类来描写叙述
    from ctypes import *
    from ctypes.wintypes import *
    
    WS_EX_APPWINDOW = 0x40000
    WS_OVERLAPPEDWINDOW = 0xcf0000
    WS_CAPTION = 0xc00000
    SW_SHOWNORMAL = 1
    SW_SHOW = 5
    CS_HREDRAW = 2
    CS_VREDRAW = 1
    CW_USEDEFAULT = 0x80000000
    WM_DESTROY = 2
    WHITE_BRUSH = 0
    
    WNDPROCTYPE = WINFUNCTYPE(c_int, HWND, c_uint, WPARAM, LPARAM)
    #定义窗体类结构
    class WNDCLASSEX(Structure):
        _fields_ = [("cbSize", c_uint),
                    ("style", c_uint),
                    ("lpfnWndProc", WNDPROCTYPE),
                    ("cbClsExtra", c_int),
                    ("cbWndExtra", c_int),
                    ("hInstance", HANDLE),
                    ("hIcon", HANDLE),
                    ("hCursor", HANDLE),
                    ("hBrush", HANDLE),
                    ("lpszMenuName", LPCWSTR),
                    ("lpszClassName", LPCWSTR),
                    ("hIconSm", HANDLE)]
    
    
    
    #开发者:蔡军生(QQ:9073204) 深圳  2014-8-24
    #窗体类
    class Window:
        def __init__(self, hWnd):
            self.hWnd = hWnd
        def Display(self, cmdShow):
            windll.user32.ShowWindow(self.hWnd, cmdShow)
            windll.user32.UpdateWindow(self.hWnd)
       
    #窗体类型注冊类
    class WinClassMaker:
        def __init__(self, wndProc, className, hInst):
            self.wndClass = WNDCLASSEX()
            self.wndClass.cbSize = sizeof(WNDCLASSEX)
            self.wndClass.style = CS_HREDRAW | CS_VREDRAW
            self.wndClass.lpfnWndProc = wndProc
            self.wndClass.cbClsExtra = 0
            self.wndClass.cbWndExtra = 0
            self.wndClass.hInstance = hInst
            self.wndClass.hIcon = 0
            self.wndClass.hCursor = 0
            self.wndClass.hBrush = windll.gdi32.GetStockObject(WHITE_BRUSH)
            self.wndClass.lpszMenuName = 0
            self.wndClass.lpszClassName = className
            self.wndClass.hIconSm = 0
        def Register(self):
            return windll.user32.RegisterClassExW(byref(self.wndClass))
    
    #创建窗体
    class WinMaker:
        def __init__(self, className, hInst):
            self.className = className
            self.hInst = hInst
            self.style = WS_OVERLAPPEDWINDOW | WS_CAPTION
            self.exStyle = 0
            self.x = CW_USEDEFAULT
            self.y = 0
            self.width = CW_USEDEFAULT
            self.height = 0
            self.hWndParent = HWND(0)
            self.hMenu = HWND(0)
            self.wndCreatData = c_void_p(0)
        def Create(self, title):
            self.hWnd = windll.user32.CreateWindowExW(
                self.exStyle, self.className, title,
                self.style,
                self.x, self.y,
                self.width, self.height,
                self.hWndParent,
                self.hMenu, 
                self.hInst, 
                self.wndCreatData)
        
            if not self.hWnd:
                print('Failed to create window')
                exit(0)
            return self.hWnd
            
    #窗体消息处理回调函数
    def PyWndProc(hWnd, Msg, wParam, lParam):
        if Msg == WM_DESTROY:
            windll.user32.PostQuitMessage(0)
        else:
            return windll.user32.DefWindowProcW(hWnd, Msg, wParam, lParam)
        return 0
        
    #主函数入口    
    def main():	
        hInst = windll.kernel32.GetModuleHandleW(None)
        WndProc = WNDPROCTYPE(PyWndProc) 
        
        className = u'ShenzhenCai'
        wname = u'Hello World' 
        
        winClass = WinClassMaker(WndProc, className, hInst)
        winClass.Register()
        maker = WinMaker(className, hInst)
        win = Window(maker.Create(wname))
        win.Display(SW_SHOW)
        
        msg = MSG()
        lpmsg = pointer(msg)
        print('Entering message loop')
        while windll.user32.GetMessageW(lpmsg, 0, 0, 0) != 0:
            windll.user32.TranslateMessage(lpmsg)
            windll.user32.DispatchMessageW(lpmsg)
    
        print('done.')
        
        
    if __name__ == "__main__":
        print( "Win32 Application in python" )
        main()    
           
    


    展开全文
  • Windows SDK 创建窗体

    千次阅读 2009-03-02 11:12:00
    VC++ 6.0 调试通过。提供给想了解Windows窗体创建机制和讨厌MFC兄弟们。从一个支持文件拖拽例子抠出来代码,代码...创建窗体程序步骤等 #include "windows.h"int WINAPI WinMain( HINSTANCE hInstance,HINST

    VC++ 6.0 调试通过。

    提供给想了解Windows窗体创建机制和讨厌MFC的兄弟们。

    从一个支持文件拖拽的例子抠出来的代码,代码简单易懂。

    有空再加注释吧。了解Windows机制的淫应该很容易明白代码在干啥。比如什么是窗体类,窗体实力,消息处理等。创建窗体程序的步骤等

     

    展开全文
  • View类是android中非常重要一个类.view是应用程序界面直观体现,我们看到应用...那么我们应用程序界面是怎么创建的呢,也就是应用程序View是什么时候创建的? 在android中与界面直接相关就是Activity了....

    View类是android中非常重要的一个类.view是应用程序界面的直观体现,我们看到的应用程序界面就能够看作是View(视图)组成的.

    那么我们应用程序的界面是怎么创建的呢,也就是应用程序的View是什么时候创建的?

    在android中与界面直接相关的就是Activity了.

    我们平时在Activity的onCreate()函数中,通过调用它的setContentView()函数,将我们应用程序的界面资源设置进去.然后执行程序就能够看到我们布局文件里描写叙述的界面了.

    从我们调用setContentView()函数将界面资源设置进去,到执行完毕界面全然显示出来,当中经过了非常多过程.

    这里我主要是通过源代码来分析一下当中终于界面究竟是什么样的View? 然后分析一下View的measure,layout,draw过程.

    由于我们设置界面是setContentView()中设置的,所以就从该函数開始来分析.

     

    分析点击android桌面app图标启动应用程序的过程一文中我们知道Activity的onCreate()函数最先被调用.第五十步  

     private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
           ....
            Activity activity = null;
            try {
                java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
                activity = mInstrumentation.newActivity(
                        cl, component.getClassName(), r.intent);
                StrictMode.incrementExpectedActivityCount(activity.getClass());
                r.intent.setExtrasClassLoader(cl);
                if (r.state != null) {
                    r.state.setClassLoader(cl);
                }
            } catch (Exception e) {
          ....
            }
    
            try {
                Application app = r.packageInfo.makeApplication(false, mInstrumentation);
    ....
                if (activity != null) {
                    Context appContext = createBaseContextForActivity(r, activity);
                    CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                    Configuration config = new Configuration(mCompatConfiguration);
                  ...
                    activity.attach(appContext, this, getInstrumentation(), r.token,
                            r.ident, app, r.intent, r.activityInfo, title, r.parent,
                            r.embeddedID, r.lastNonConfigurationInstances, config);
    
                    if (customIntent != null) {
                        activity.mIntent = customIntent;
                    }
                    r.lastNonConfigurationInstances = null;
                    activity.mStartedActivity = false;
                    int theme = r.activityInfo.getThemeResource();
                    if (theme != 0) {
                        activity.setTheme(theme);
                    }
    
                    activity.mCalled = false;
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                 .....
        }
    这里首先创建Activity 的实例,然后mInstrumentation.callActivityOnCreate(activity, r.state)该函数终于就会调用Activity的onCreate()函数.

    好了,看setContentView()函数

    第一步:setContentView()

    在frameworks/base/core/java/android/app/Activity.java中

    public void setContentView(int layoutResID) {
            getWindow().setContentView(layoutResID);
            initActionBar();
        }
        public void setContentView(View view) {
            getWindow().setContentView(view);
            initActionBar();
        }
        public void setContentView(View view, ViewGroup.LayoutParams params) {
            getWindow().setContentView(view, params);
            initActionBar();
        }

    Activity中setContentView()函数有三个重载函数,一般用第一个比較多,这里就按第一个继续往下分析,事实上它们终于实现都一样.

    首先看getWindow()函数

    第二步:getWindow()

    frameworks/base/core/java/android/app/Activity.java中

    public Window getWindow() {
            return mWindow;
        }
    
    Activity的成员变量mWindow是Window类型,它是什么时候被赋值的呢?

    这里还是到分析点击android桌面app图标启动应用程序的过程一文中第五十步 看看

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
            ....
            Activity activity = null;
            try {
                java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
                activity = mInstrumentation.newActivity(
                        cl, component.getClassName(), r.intent);
                StrictMode.incrementExpectedActivityCount(activity.getClass());
                r.intent.setExtrasClassLoader(cl);
                if (r.state != null) {
                    r.state.setClassLoader(cl);
                }
            } catch (Exception e) {
           ...
            }
    
            try {
                Application app = r.packageInfo.makeApplication(false, mInstrumentation);
    ...
                if (activity != null) {
                    Context appContext = createBaseContextForActivity(r, activity);
                    CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                    Configuration config = new Configuration(mCompatConfiguration);
                ...
                    activity.attach(appContext, this, getInstrumentation(), r.token,
                            r.ident, app, r.intent, r.activityInfo, title, r.parent,
                            r.embeddedID, r.lastNonConfigurationInstances, config);
    
               ....
        }
    这里创建Activity的实例后,就通过activity.attach()函数给activity内部变量赋值,所以进attach()函数里面看看

    第三步:attach()

    在frameworks/base/core/java/android/app/Activity.java中

    final void attach(Context context, ActivityThread aThread,
                Instrumentation instr, IBinder token, int ident,
                Application application, Intent intent, ActivityInfo info,
                CharSequence title, Activity parent, String id,
                NonConfigurationInstances lastNonConfigurationInstances,
                Configuration config) {
           ...
            mWindow = PolicyManager.makeNewWindow(this);//
          ....
        }
    
    mWindow = PolicyManager.makeNewWindow(this);这里就是给activity中mWindow赋值.那继续看PolicyManager.makeNewWindow(this)这个函数

    第四步:makeNewWindow()

    在frameworks/base/core/java/com/android/internal/policyPolicyManager.java

     // The static methods to spawn new policy-specific objects
        public static Window makeNewWindow(Context context) {
            return sPolicy.makeNewWindow(context);
        }
    <pre name="code" class="java">
    
    
    public final class PolicyManager {
        private static final String POLICY_IMPL_CLASS_NAME =
            "com.android.internal.policy.impl.Policy";
        private static final IPolicy sPolicy;
        static {
            // Pull in the actual implementation of the policy at run-time
            try {
                Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);
                sPolicy = (IPolicy)policyClass.newInstance();
            } catch (ClassNotFoundException ex) {
             ....
        }
    这里继续调用sPolicy.makeNewWindow(context);由上面代码能够知道这里的sPolicy事实上是Policy类型

    第五步:makeNewWindow()

    在frameworks/base/policy/src/com/android/internal/policy/impl/Policy.java中

    public class Policy implements IPolicy {
       .
        public Window makeNewWindow(Context context) {
            return new PhoneWindow(context);
        }
    这里直接new PhoneWindow(context)返回,可知PhoneWindow类是Window类的子类,进入PhoneWindow类看看

    第六步:PhoneWindow()

    frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java

    public class PhoneWindow extends Window implements MenuBuilder.Callback {
    .
        public PhoneWindow(Context context) {
            super(context);
            mLayoutInflater = LayoutInflater.from(context);
        }
    来看一下PhoneWindow类的构造函数,首先是调用了其父类(Window)的构造函数,然后创建了一个LayoutInflater对象mLayoutInflater,这个对象依据它的名字大概能够知道它是渲染布局资源的

    Window类的构造函数看看

    第七步:Window()

    在frameworks/base/core/java/android/view/Window.java中

    public Window(Context context) {
            mContext = context;
        }
    回到第二步中,这是我们知道getWindow()返回事实上是一个PhoneWindow对象,即Activity的成员变量mWindow是PhoneWindow类型.

    然后回到第一步中,那么接着事实上是调用PhoneWindow.setContentView()了

    第八步:setContentView()

    在frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java中

     public void setContentView(int layoutResID) {
            if (mContentParent == null) {
                installDecor();
            } else {
                mContentParent.removeAllViews();
            }
            mLayoutInflater.inflate(layoutResID, mContentParent);
            final Callback cb = getCallback();
            if (cb != null && !isDestroyed()) {
                cb.onContentChanged();
            }
        }

    PhoneWindow的成员变量mContentParent是ViewGroup类型,第一次进来为null,所以调用installDecor()函数,那我们首先看看该函数

    第九步:installDecor()

    在frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java中

    private void installDecor() {
            if (mDecor == null) {
                mDecor = generateDecor();
                mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
              ...
            }
            if (mContentParent == null) {
                mContentParent = generateLayout(mDecor);
    
                // Set up decor part of UI to ignore fitsSystemWindows if appropriate.
                mDecor.makeOptionalFitsSystemWindows();
    
                mTitleView = (TextView)findViewById(com.android.internal.R.id.title);
                if (mTitleView != null) {
                    mTitleView.setLayoutDirection(mDecor.getLayoutDirection());
                    if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
                        View titleContainer = findViewById(com.android.internal.R.id.title_container);
                        if (titleContainer != null) {
                            titleContainer.setVisibility(View.GONE);
                        } else {
                            mTitleView.setVisibility(View.GONE);
                        }
                        if (mContentParent instanceof FrameLayout) {
                            ((FrameLayout)mContentParent).setForeground(null);
                        }
                    } else {
                        mTitleView.setText(mTitle);
                    }
                } else {
                    mActionBar = (ActionBarView) findViewById(com.android.internal.R.id.action_bar);
                    if (mActionBar != null) {
                        mActionBar.setWindowCallback(getCallback());
                        if (mActionBar.getTitle() == null) {
                            mActionBar.setWindowTitle(mTitle);
                        }
                        final int localFeatures = getLocalFeatures();
                        if ((localFeatures & (1 << FEATURE_PROGRESS)) != 0) {
                            mActionBar.initProgress();
                        }
                        if ((localFeatures & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) {
                            mActionBar.initIndeterminateProgress();
                        }
    
                        boolean splitActionBar = false;
                        final boolean splitWhenNarrow =
                                (mUiOptions & ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW) != 0;
                        if (splitWhenNarrow) {
                            splitActionBar = getContext().getResources().getBoolean(
                                    com.android.internal.R.bool.split_action_bar_is_narrow);
                        } else {
                            splitActionBar = getWindowStyle().getBoolean(
                                    com.android.internal.R.styleable.Window_windowSplitActionBar, false);
                        }
                        final ActionBarContainer splitView = (ActionBarContainer) findViewById(
                                com.android.internal.R.id.split_action_bar);
                        if (splitView != null) {
                            mActionBar.setSplitView(splitView);
                            mActionBar.setSplitActionBar(splitActionBar);
                            mActionBar.setSplitWhenNarrow(splitWhenNarrow);
    
                            final ActionBarContextView cab = (ActionBarContextView) findViewById(
                                    com.android.internal.R.id.action_context_bar);
                            cab.setSplitView(splitView);
                            cab.setSplitActionBar(splitActionBar);
                            cab.setSplitWhenNarrow(splitWhenNarrow);
                        } else if (splitActionBar) {
                            Log.e(TAG, "Requested split action bar with " +
                                    "incompatible window decor! Ignoring request.");
                        }
                      .
                    }
                }
            }
        }

    PhoneWindow的成员变量mDecor是DecorView类型,看一下DecorView的类图结构


    由上图可知,DecorView也是View,事实上这个DecorView也是应用程序窗体根View.

    第一次进来mDecor为null,所以会执行以下:

    mDecor = generateDecor();
                mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);//焦点先交给mDecor的子view处理,假设子View没有处理自己再处理
             
    首先来看一下generateDecor()这个函数

    第十步:generateDecor()

    在frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java中

    protected DecorView generateDecor() {
            return new DecorView(getContext(), -1);
        }
    这里就直接新建了DecorView实例

    回到第九步中,mContentParent == null成立,所以执行:

    mContentParent = generateLayout(mDecor);
    进入generateLayout(mDecor)函数看看,传进去的參数就是第十步创建的DecorView对象

    第十一步:generateLayout()

    在frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java中

    protected ViewGroup generateLayout(DecorView decor) {
         ....
            mDecor.startChanging();
    
            View in = mLayoutInflater.inflate(layoutResource, null);
            decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
    
            ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
         ...
            return contentParent;
        }
    这个函数内容还是挺多的,只是不难,首先收集在清单配置文件里,给该activity配置的theme属性值,然后依据这些属性值去载入系统的布局文件,设置这些theme属性值也能够在代码中设置,只是要setContentView()之前,只是就不起作用了.

    else {
                // Embedded, so no decoration is needed.
                layoutResource = com.android.internal.R.layout.screen_simple;
                // System.out.println("Simple!");
            }
    这里假设须要载入的布局文件id是com.android.internal.R.layout.screen_simple,系统的布局文件在frameworks/base/core/res/res/layout/文件夹下,

    进去screen_simple.xml看一下

    <?xml version="1.0" encoding="utf-8"?

    > <!-- /* //device/apps/common/assets/res/layout/screen_simple.xml ** ** Copyright 2006, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ This is an optimized layout for a screen, with the minimum set of features enabled. --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" android:orientation="vertical"> <ViewStub android:id="@+id/action_mode_bar_stub" android:inflatedId="@+id/action_mode_bar" android:layout="@layout/action_mode_bar" android:layout_width="match_parent" android:layout_height="wrap_content" /> <FrameLayout android:id="@android:id/content" android:layout_width="match_parent" android:layout_height="match_parent" android:foregroundInsidePadding="false" android:foregroundGravity="fill_horizontal|top" android:foreground="?

    android:attr/windowContentOverlay" /> </LinearLayout>

    有一个id为content的控件,这个非常关键.

    在确定好载入哪个系统布局文件后,接下来:

    View in = mLayoutInflater.inflate(layoutResource, null);
            decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
    mLayoutInflater在第六步创建的,这里将一个布局文件渲染成一个View,这个view的详细类型就是布局文件的根节点的对象类型,像上面的screen_simple.xml它的根节点就是LinearLayout.

    接着将这个渲染成的LinearLayout加入到decor中,由于DecorView是ViewGroup类型,能加入子view.

    接着往下看:

    ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);

    这里ID_ANDROID_CONTENT为com.android.internal.R.id.content,我们进到findViewById()函数进去看看

    第十二步:findViewById()

    在frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java中

    public View findViewById(int id) {
            return getDecorView().findViewById(id);
        }
      public final View getDecorView() {
            if (mDecor == null) {
                installDecor();
            }
            return mDecor;
        }
    这个函数就去查找decorView中id为com.android.internal.R.id.content的子view,在上面的布局文件里就是一个FrameLayout了,所以说系统布局文件要有一个id为content的控件.

    好了,回到第十一步,找到了这控件后就返回到第九步中,将它赋值给了mContentParent.

    如今整理一下思路,mDecor赋值了,mContentParent也赋值了,它们的关系是:


    回到第九步,继续往下分析:

    mTitleView = (TextView)findViewById(com.android.internal.R.id.title);
                if (mTitleView != null) {
                    mTitleView.setLayoutDirection(mDecor.getLayoutDirection());
                    if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
                        View titleContainer = findViewById(com.android.internal.R.id.title_container);
                        if (titleContainer != null) {
                            titleContainer.setVisibility(View.GONE);
                        } else {
                            mTitleView.setVisibility(View.GONE);
                        }
                        if (mContentParent instanceof FrameLayout) {
                            ((FrameLayout)mContentParent).setForeground(null);
                        }
                    } else {
                        mTitleView.setText(mTitle);
                    }
                } else {
                    mActionBar = (ActionBarView) findViewById(com.android.internal.R.id.action_bar);
                    if (mActionBar != null) {
                        mActionBar.setWindowCallback(getCallback());
                        if (mActionBar.getTitle() == null) {
                            mActionBar.setWindowTitle(mTitle);
                        }
                        final int localFeatures = getLocalFeatures();
                        if ((localFeatures & (1 << FEATURE_PROGRESS)) != 0) {
                            mActionBar.initProgress();
                        }
                        if ((localFeatures & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) {
                            mActionBar.initIndeterminateProgress();
                        }
    
                        boolean splitActionBar = false;
                        final boolean splitWhenNarrow =
                                (mUiOptions & ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW) != 0;
                        if (splitWhenNarrow) {
                            splitActionBar = getContext().getResources().getBoolean(
                                    com.android.internal.R.bool.split_action_bar_is_narrow);
                        } else {
                            splitActionBar = getWindowStyle().getBoolean(
                                    com.android.internal.R.styleable.Window_windowSplitActionBar, false);
                        }
                        final ActionBarContainer splitView = (ActionBarContainer) findViewById(
                                com.android.internal.R.id.split_action_bar);
                        if (splitView != null) {
                            mActionBar.setSplitView(splitView);
                            mActionBar.setSplitActionBar(splitActionBar);
                            mActionBar.setSplitWhenNarrow(splitWhenNarrow);
    
                            final ActionBarContextView cab = (ActionBarContextView) findViewById(
                                    com.android.internal.R.id.action_context_bar);
                            cab.setSplitView(splitView);
                            cab.setSplitActionBar(splitActionBar);
                            cab.setSplitWhenNarrow(splitWhenNarrow);
                        } else if (splitActionBar) {
                            Log.e(TAG, "Requested split action bar with " +
                                    "incompatible window decor! Ignoring request.");
                        }
    
                    

    PhoneWindow类的成员函数installDecor()还会检查前面载入的窗体布局文件是否包括有一个id值为“title”的TextView控件。假设包括有的话,就会将它保存在PhoneWindow类的成员变量mTitleView中,用来描写叙述当前应用程序窗体的标题栏。可是,假设当前应用程序窗体是没有标题栏的。即它的Feature位FEATURE_NO_TITLE的值等于1。那么PhoneWindow类的成员函数installDecor()就须要将前面得到的标题栏隐藏起来。注意,PhoneWindow类的成员变量mTitleView所描写叙述的标题栏有可能是包括在一个id值为“title_container”的容器里面的。在这样的情况下。就须要隐藏该标题栏容器。还有一方面,假设当前应用程序窗体是设置有标题栏的。那么PhoneWindow类的成员函数installDecor就会设置它的标题栏文字。应用程序窗体的标题栏文字保存在PhoneWindow类的成员变量mTitle中,我们能够调用PhoneWindow类的成员函数setTitle来设置.假设没有id值为“title”的TextView控件,就去检查前面载入的窗体布局文件是否包括有一个id值为“action_bar”的ActionBarView控件.以下就不分析了.

    回到第八步setContentView()函数里,

    往下接着到

     mLayoutInflater.inflate(layoutResID, mContentParent);
    这里的layoutResID,是在activity的onCreate()方法里面,通过setContentView()设置的应用程序的窗体布局资源id.

    这里mLayoutInflater.inflate()方法,将应用程序的窗体布局资源渲染成一个view,然后加入到mContentParent这个ViewGroup中.

    所以应用程序窗体的界面的View结构例如以下:



    平时我们写应用,仅仅须要写上图中setContentView()的布局就能够,其它android已经实现好了.

    好了,应用程序窗体的布局结构就分析完了.我们知道一个应用程序的窗体的显示区域,事实上就是DecorView及其包括的子view.

    设置好应用程序的布局文件后,就要将DecorView包括内容渲染显示到屏幕上了.

    至于怎样渲染不打算分析了.

    在显示出来之前,DecorView还要经过measure(測量),layout(布局),draw(绘制)三个过程.后面打算分析源代码,对这三个过程加一分析下.



























    转载于:https://www.cnblogs.com/llguanli/p/8580731.html

    展开全文
  • 写了登录窗体之后,测试看看能不能用,就出现了这个错误弹窗,仔细看上面ADO这里问题,引用-工程出现了问题,未引用相关库文件导致产生此类错误,查了一下说“在代码中引用了相关控件方法,但是之前并未...
  • 什么是"适配器",可以用简单代码做演示看出来,适配器事件监听接口实现,这些实现了相应事件监听器接口,并为接口中所有方法定义了空实现方法,就是声明了接口中定义所有方法,但是方法空体。...
  • 其实方法也挺简单在U层工具的工具类创建共有的方法但是从之前的方法你要知道你用到了什么,需要用什么. 1.需要获取本窗体的X和Y的值 2.判断鼠标按键 3.窗体的坐标跟随鼠标而移动 以下实现的代码: 窗体的拖动...
  • Swing窗体

    2018-04-12 14:42:39
    利用JFrame类创建窗体 通过SetTitle(String title)方法。》》》》》》设置关闭按钮 点击关闭按钮时候 进行什么操作,下面使用方法下面有个例子》》》》》》》》》》》》》》》》》》》》》》》》...
  •  在Windows编程中,我们已经习惯了一个窗体创建到显示并获得焦点。...可能我们并不关心焦点切换,由于从视觉角度来看,没有不论什么影响,可是键盘类的消息却在焦点变化时不断切换响应窗体。我...
  • MDI窗体设计

    2017-05-18 00:31:00
    1、MDI窗体是什么?  程序的用户界面一般分为两大:单文档界面和多文档界面。   MDI是Multiple Document Interface的缩写,就是文档窗体的意思。它是和单文档SDI相对的。   C#允许在单个容器窗体中创建...
  • 透明与窗体的设置

    2011-09-18 16:50:35
    PS2:其他创建Dialog方法:创建app.Dialog或者创建app.AlertDialog。 Next Study:能不能在Activity已经打开以后动态修改当前Activity风格? 在测试中发现,在onCreate()事件中增加setTheme(),必须在...
  • 仅仅为了显示一个消息或者做个窗体投影,这没必要用form窗体的,那么只需要一个创建出来没有额外功能的窗口最简洁的。 用什么方法才能不用form弹出窗口呢? 1.用control,当然form也派生至control,相对...
  • 一、首先新建一个Qt动态库工程(*.dll) ...创建完成之后默认文件目录是这样:包含四个文件,.pro文件就不多所了,都知道是什么,可以看到QtCreator默认给我们创建了一个,.h文件和.cpp文件都有,
  • 简单说,“”就是对象表示形式,一个可以用于创建对象多个副本。 尽管我们没有在代码中编写过,但实际上我们已经在使用了。例如,当我们将一个 TextBox 控件拖动到窗体上时,实际上就是在创建 Te
  • 一个支持 Widget 侧边栏或者说是窗体化(widgetized)侧边栏几乎 WordPress 主题标准。 首先,什么是窗体化(widgetizing)呢?简单说,窗体化就是能够通过拖拉就能够整理侧边栏模块。比如我们需要更改...
  • 我在网上查如何将JTable...但是这些好像都对在JFrame窗体的“设计”中拖拽在界面上的表格不太适用,因为不能自己定义MyTable然后绘制在界面上,也不能重新new已经生成的table。 那么请问还有什么别的方法吗?谢谢~~
  • 窗体上巧用单例模式

    千次阅读 热门讨论 2013-12-05 21:26:58
    最近在合作开发机房收费系统时候,想要避免出现子窗体被多次实例化问题,这个问题一直没有想通怎么解决,最近在网上查相关资料时候,找到... 其创建两个,一个窗体MdiParent,一个窗体FormChild,在
  • 自定义控件自己写一个控件,或者继承已有控件 复合控件封装在公共容器内 Windows 窗体控件集合。这种控件有时称为“用户控件”。包含控件称为“构成控件”。 用户控件 复合控件包含与每个包含 ...
  • vb中模块是什么意思?

    千次阅读 2013-02-03 23:02:46
    VB模块也称代码模块: Visual Basic 代码存储在模块中。...因为不希望在两个窗体中重复代码,所以要创建一个独立模块,它包含实现公共代码过程。独立模块应为标准模块。此后可以建立一个包含共享过程
  • VB工程文件扩展名是什么?VB工程文件扩展名是:.vbp(Visual Basic Project)Visual Basic在创建和编译工程时要产生许多文件。这些文件分类如下:设计时文件、杂项开发文件和运行时文件。设计时文件是工程建造块...
  • 特别开发信息管理系统之类的跟数据库比较密切程序时,在数据和界面层开发中会遇到不少常见问题,下面我们通过vs.net自带数据窗体向导来看看能它能帮我们决绝什么问题。 一.使用向导新建Windows 应用程序,...
  • 我想在 win32 控制台里使用 mfc 里的类,但是翻来覆去改项目配置都没有搞定,我觉得这一个坑,为什么不能创建一个 mfc 的程序让它像 win32 控制台那样去工作呢 ? 于是就有了下文: 在 OnWindowPosChanging 下...
  • 一、分部创建过Web窗体应用同学,应该都有 注意到在窗体类的前面默认加上了Partial 修饰符,这个就是我们今天要讨论问题 ,通俗来讲:Partial 目的就是把一个 分成两个或者多个来实现接下来 我们...
  • (20KB)<END><br>97,twopanes.zip 你有没有想过把通用对话框作为你窗口一个View是什么样子?看看这个例子吧。(9KB)<END><br>98,bcmenu21.zip 可以利用工具条资源,绘制图标菜单。(56KB)<END><br>99,MENU4...
  • 控件数组VB提供一个优秀设计解决方案,它能很方便快捷处理大批同类控件响应和时间处理,但不知为什么在C#中这个优秀特性没有传承下来,甚为可惜,本文将要探讨就是如何在C# WinForm程序实现它.首先请看界面在...

空空如也

空空如也

1 2 3 4 5 ... 17
收藏数 322
精华内容 128
关键字:

创建窗体的类是什么