zoukankan      html  css  js  c++  java
  • 自己画WinForm 皮肤包括默认控件

    好久没来博客园,今天捣鼓到现在就是为了把之前的皮肤控件完善好,

    之前也看了很多技术文章,大多数都是自己重写系统控件实现换肤,几乎没有像东日的(IrisSkin)控件一样 添加一个组件 把系统的皮肤全换掉,我曾经也是重写系统的控件,但我就喜欢瞎捣鼓,于是就开始找这方面的资料,苦于没学过底层,对windows窗口 以及消息循环机制不了解,找资料也基本上白搭了许久,但最后以为自己能想到的最笨的方法实现 了继承了自己写的父窗口,那么窗口添加的控件就是自己画的 而不是系统画的,

    先上传一张效果图:

    整天效果应该也还算勉强吧,目前我也就写了这几个控件的美化,虽然这破代码捣鼓好几天了,但代码依旧混乱不堪,加上反编译了微软的部分东西,因为想尽快出来,代码都没看,直接复制过来修改成编译不报错就完事了,

    现在我来说说我实现的思路:

    前题条件继承的是自己写的FormBase
    然后重写了系统的OnControlAdded 方法,在这里为每个控件添加美化的类,

    可怎么添加了? 找了好久,找到了一个可拦截Control消息的接口:IWindowTarget 接口(具体请参考 MSDN 微软不建议直接使用的一个类)

    Control 公开并允许修改这个接口的信息,

    IWindowTarget 接口有两个方法,一个是更换控件句柄的(也许应该叫设置控件句柄) 还有一个就是处理 Windows 消息的OnMessage
     我要做的就是拦截Windows 消息的重画消息,拦截下来 然后自己画,其它的还是丢个控件处理,(后来发现貌似实现IMessageFilter接口也可以实现)

    好了屁话不多说了 上代码 上demo 没写完  希望大神能帮忙完善下就最好了-.-!

    对了 就是问个2B问题,怎么拦截所有的Form创建或者Form创建句柄时?我用IMessageFilter好像拦截不到,

    唉 代码有点乱,各位将就着看吧

    部分代码:

    using DotNet.Windows.Forms.Internal;
    using System;
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Drawing.Imaging;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    
    namespace DotNet.Windows.Forms
    {
        public abstract class WindowTarget<T> : IWindowTarget
            where T : Control
        {
            private static readonly ControlStyles UserControlStyles;
            private static readonly MethodInfo SetStyleMethod;
            private static readonly MethodInfo SetStateMethod;
            private static readonly PropertyInfo CacheTextInternalProperty;
            private static readonly FieldInfo windowField;
    
            static WindowTarget()
            {
                UserControlStyles = ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.Selectable | ControlStyles.ContainerControl | ControlStyles.UserPaint;
                SetStyleMethod = typeof(Control).GetMethod("SetStyle",BindingFlags.Instance |BindingFlags.NonPublic);
                SetStateMethod = typeof(Control).GetMethod("SetState", BindingFlags.Instance | BindingFlags.NonPublic);
                windowField = typeof(Control).GetField("window", BindingFlags.Instance | BindingFlags.NonPublic);
                CacheTextInternalProperty = typeof(Control).GetProperty("CacheTextInternal", BindingFlags.Instance | BindingFlags.NonPublic);
            }
            private T m_Control;
            private IWindowTarget m_WindowTarget;
            private MouseState m_MouseState = MouseState.Normal;
            protected WindowTarget(T control)
            {
                m_Control = control;
                m_WindowTarget = m_Control.WindowTarget;
                m_Control.MouseUp += (o, e) => { this.MouseState = MouseState.Up; };
                m_Control.MouseEnter += (o, e) => { this.MouseState = MouseState.Move; };
                m_Control.MouseLeave += (o, e) => { this.MouseState = MouseState.Leave; };
                m_Control.MouseDown += (o, e) => { this.MouseState = MouseState.Down; };
            }
            protected virtual void SetStyle(ControlStyles styles, bool value)
            {
                SetStyleMethod.Invoke(Control, new object[] { styles, value });
            }
            private object window
            {
                get
                {
                    return windowField.GetValue(Control);
                }
            }
            private bool CacheTextInternal
            {
                get
                {
                    return (bool)CacheTextInternalProperty.GetValue(Control, null);
                }
                set
                {
                    CacheTextInternalProperty.SetValue(Control, value, null);
                }
            }
            protected virtual void SetState(int flag, bool value)
            {
                SetStyleMethod.Invoke(Control, new object[] { flag, value });
            }
            protected T Control { get { return m_Control; } }
            protected IWindowTarget Target { get { return m_WindowTarget; } }
            protected abstract void OnPaint(DotNet.Windows.Forms.Internal.PaintEventArgs e);
            protected MouseState MouseState
            {
                get
                {
                    return m_MouseState;
                }
                set
                {
                    if (m_MouseState != value)
                    {
                        m_MouseState = value;
                        Control.Invalidate();
                    }
                }
            }
            protected virtual Image GetImage()
            {
                switch (MouseState)
                {
                    case MouseState.Leave:
                    case MouseState.Normal:
                        return GetNormalImage();
                    case MouseState.Up:
                    case MouseState.Move:
                        return GetMoveImage();
                    case MouseState.Down:
                        return GetDownImage();
                    default:
                        return null;
                }
            }
            protected abstract Image GetNormalImage();
            protected abstract Image GetMoveImage();
            protected abstract Image GetDownImage();
            protected void RendererBackground(Graphics g, Rectangle rect, Image backgroundImage, bool method)
            {
                if (!method)
                {
                    g.DrawImage(backgroundImage, new Rectangle(rect.X + 0, rect.Y, 5, rect.Height), 0, 0, 5, backgroundImage.Height, GraphicsUnit.Pixel);
                    g.DrawImage(backgroundImage, new Rectangle(rect.X + 5, rect.Y, rect.Width - 10, rect.Height), 5, 0, backgroundImage.Width - 10, backgroundImage.Height, GraphicsUnit.Pixel);
                    g.DrawImage(backgroundImage, new Rectangle(rect.X + rect.Width - 5, rect.Y, 5, rect.Height), backgroundImage.Width - 5, 0, 5, backgroundImage.Height, GraphicsUnit.Pixel);
                }
                else
                {
                    RendererBackground(g, rect, 5, backgroundImage);
                }
            }
            /// <summary>
            /// 渲染背景图片,使背景图片不失真
            /// </summary>
            /// <param name="g"></param>
            /// <param name="rect"></param>
            /// <param name="cut"></param>
            /// <param name="backgroundImage"></param>
            protected void RendererBackground(Graphics g, Rectangle rect, int cut, Image backgroundImage)
            {
                //左上角
                g.DrawImage(backgroundImage, new Rectangle(rect.X, rect.Y, cut, cut), 0, 0, cut, cut, GraphicsUnit.Pixel);
                //上边
                g.DrawImage(backgroundImage, new Rectangle(rect.X + cut, rect.Y, rect.Width - cut * 2, cut), cut, 0, backgroundImage.Width - cut * 2, cut, GraphicsUnit.Pixel);
                //右上角
                g.DrawImage(backgroundImage, new Rectangle(rect.X + rect.Width - cut, rect.Y, cut, cut), backgroundImage.Width - cut, 0, cut, cut, GraphicsUnit.Pixel);
                //左边
                g.DrawImage(backgroundImage, new Rectangle(rect.X, rect.Y + cut, cut, rect.Height - cut * 2), 0, cut, cut, backgroundImage.Height - cut * 2, GraphicsUnit.Pixel);
                //左下角
                g.DrawImage(backgroundImage, new Rectangle(rect.X, rect.Y + rect.Height - cut, cut, cut), 0, backgroundImage.Height - cut, cut, cut, GraphicsUnit.Pixel);
                //右边
                g.DrawImage(backgroundImage, new Rectangle(rect.X + rect.Width - cut, rect.Y + cut, cut, rect.Height - cut * 2), backgroundImage.Width - cut, cut, cut, backgroundImage.Height - cut * 2, GraphicsUnit.Pixel);
                //右下角
                g.DrawImage(backgroundImage, new Rectangle(rect.X + rect.Width - cut, rect.Y + rect.Height - cut, cut, cut), backgroundImage.Width - cut, backgroundImage.Height - cut, cut, cut, GraphicsUnit.Pixel);
                //下边
                g.DrawImage(backgroundImage, new Rectangle(rect.X + cut, rect.Y + rect.Height - cut, rect.Width - cut * 2, cut), cut, backgroundImage.Height - cut, backgroundImage.Width - cut * 2, cut, GraphicsUnit.Pixel);
                //平铺中间
                g.DrawImage(backgroundImage, new Rectangle(rect.X + cut, rect.Y + cut, rect.Width - cut * 2, rect.Height - cut * 2), cut, cut, backgroundImage.Width - cut * 2, backgroundImage.Height - cut * 2, GraphicsUnit.Pixel);
            }
            #region IWindowTarget 成员
            void IWindowTarget.OnHandleChange(IntPtr newHandle)
            {
                Target.OnHandleChange(newHandle);
            }
            private BufferedGraphicsContext BufferContext
            {
                get
                {
                    return BufferedGraphicsManager.Current;
                }
            }
            internal static IntPtr SetUpPalette(IntPtr dc, bool force, bool realizePalette)
            {
                IntPtr halftonePalette = Graphics.GetHalftonePalette();
                IntPtr ptr2 = SafeNativeMethods.SelectPalette(new HandleRef(null, dc), new HandleRef(null, halftonePalette), force ? 0 : 1);
                if ((ptr2 != IntPtr.Zero) && realizePalette)
                {
                    SafeNativeMethods.RealizePalette(new HandleRef(null, dc));
                }
                return ptr2;
            }
            private void WmPaint(ref  Message m)
            {
                bool flag = true;
                IntPtr zero = IntPtr.Zero;
                NativeMethods.PAINTSTRUCT lpPaint = new NativeMethods.PAINTSTRUCT();
                bool flag2 = false;
                try
                {
                    IntPtr wParam;
                    Rectangle clientRectangle;
                    if (m.WParam == IntPtr.Zero)
                    {
                        zero = Control.Handle;
                        wParam = UnsafeNativeMethods.BeginPaint(new HandleRef(this, zero), ref lpPaint);
                        flag2 = true;
                        clientRectangle = new Rectangle(lpPaint.rcPaint_left, lpPaint.rcPaint_top, lpPaint.rcPaint_right - lpPaint.rcPaint_left, lpPaint.rcPaint_bottom - lpPaint.rcPaint_top);
                    }
                    else
                    {
                        wParam = m.WParam;
                        clientRectangle = Control.ClientRectangle;
                    }
                    if (!flag || ((clientRectangle.Width > 0) && (clientRectangle.Height > 0)))
                    {
                        IntPtr handle = IntPtr.Zero;
                        BufferedGraphics graphics = null;
                        DotNet.Windows.Forms.Internal.PaintEventArgs e = null;
                        System.Drawing.Drawing2D.GraphicsState gstate = null;
                        try
                        {
                            if (flag || (m.WParam == IntPtr.Zero))
                            {
                                handle = SetUpPalette(wParam, false, false);
                            }
                            if (flag)
                            {
                                try
                                {
                                    graphics = this.BufferContext.Allocate(wParam, Control.ClientRectangle);
                                }
                                catch (Exception exception)
                                {
                                    if (ClientUtils.IsCriticalException(exception))
                                    {
                                        throw;
                                    }
                                    flag = false;
                                }
                            }
                            if (graphics != null)
                            {
                                graphics.Graphics.SetClip(clientRectangle);
                                e = new DotNet.Windows.Forms.Internal.PaintEventArgs(graphics.Graphics, clientRectangle);
                                gstate = e.Graphics.Save();
                            }
                            else
                            {
                                e = new DotNet.Windows.Forms.Internal.PaintEventArgs(wParam, clientRectangle);
                            }
                            using (e)
                            {
                                try
                                {
                                    if (((m.WParam == IntPtr.Zero) && true) || flag)
                                    {
                                        this.PaintWithErrorHandling(e, 1);
                                    }
                                }
                                finally
                                {
                                    if (gstate != null)
                                    {
                                        e.Graphics.Restore(gstate);
                                    }
                                    else
                                    {
                                        e.ResetGraphics();
                                    }
                                }
                                this.PaintWithErrorHandling(e, 2);
                                if (graphics != null)
                                {
                                    graphics.Render();
                                }
                            }
                        }
                        finally
                        {
                            if (handle != IntPtr.Zero)
                            {
                                SafeNativeMethods.SelectPalette(new HandleRef(null, wParam), new HandleRef(null, handle), 0);
                            }
                            if (graphics != null)
                            {
                                graphics.Dispose();
                            }
                        }
                    }
                }
                finally
                {
                    if (flag2)
                    {
                        UnsafeNativeMethods.EndPaint(new HandleRef(this, zero), ref lpPaint);
                    }
                }
            }
            protected virtual void OnPaintBackground(DotNet.Windows.Forms.Internal.PaintEventArgs pevent)
            {
                NativeMethods.RECT rect = new NativeMethods.RECT();
                UnsafeNativeMethods.GetClientRect(new HandleRef(this.window, Control.Handle), ref rect);
                this.PaintBackground(pevent, new Rectangle(rect.left, rect.top, rect.right, rect.bottom));
            }
            internal void PaintBackground(DotNet.Windows.Forms.Internal.PaintEventArgs e, Rectangle rectangle)
            {
                this.PaintBackground(e, rectangle, Control.BackColor, Point.Empty);
            }
    
            internal void PaintBackground(DotNet.Windows.Forms.Internal.PaintEventArgs e, Rectangle rectangle, System.Drawing.Color backColor)
            {
                this.PaintBackground(e, rectangle, backColor, Point.Empty);
            }
            private bool RenderColorTransparent(System.Drawing.Color c)
            {
                return ((c.A < 0xff));
            }
            internal void PaintTransparentBackground(DotNet.Windows.Forms.Internal.PaintEventArgs e, Rectangle rectangle)
            {
                this.PaintTransparentBackground(e, rectangle, null);
            }
            internal static bool IsImageTransparent(Image backgroundImage)
            {
                return ((backgroundImage != null) && ((backgroundImage.Flags & 2) > 0));
            }
            internal static Rectangle CalculateBackgroundImageRectangle(Rectangle bounds, Image backgroundImage, ImageLayout imageLayout)
            {
                Rectangle rectangle = bounds;
                if (backgroundImage != null)
                {
                    switch (imageLayout)
                    {
                        case ImageLayout.None:
                            rectangle.Size = backgroundImage.Size;
                            return rectangle;
    
                        case ImageLayout.Tile:
                            return rectangle;
    
                        case ImageLayout.Center:
                            {
                                rectangle.Size = backgroundImage.Size;
                                Size size = bounds.Size;
                                if (size.Width > rectangle.Width)
                                {
                                    rectangle.X = (size.Width - rectangle.Width) / 2;
                                }
                                if (size.Height > rectangle.Height)
                                {
                                    rectangle.Y = (size.Height - rectangle.Height) / 2;
                                }
                                return rectangle;
                            }
                        case ImageLayout.Stretch:
                            rectangle.Size = bounds.Size;
                            return rectangle;
    
                        case ImageLayout.Zoom:
                            {
                                Size size2 = backgroundImage.Size;
                                float num = ((float)bounds.Width) / ((float)size2.Width);
                                float num2 = ((float)bounds.Height) / ((float)size2.Height);
                                if (num >= num2)
                                {
                                    rectangle.Height = bounds.Height;
                                    rectangle.Width = (int)((size2.Width * num2) + 0.5);
                                    if (bounds.X >= 0)
                                    {
                                        rectangle.X = (bounds.Width - rectangle.Width) / 2;
                                    }
                                    return rectangle;
                                }
                                rectangle.Width = bounds.Width;
                                rectangle.Height = (int)((size2.Height * num) + 0.5);
                                if (bounds.Y >= 0)
                                {
                                    rectangle.Y = (bounds.Height - rectangle.Height) / 2;
                                }
                                return rectangle;
                            }
                    }
                }
                return rectangle;
            }
            internal static void DrawBackgroundImage(Graphics g, Image backgroundImage, Color backColor, ImageLayout backgroundImageLayout, Rectangle bounds, Rectangle clipRect, Point scrollOffset, RightToLeft rightToLeft)
            {
                if (g == null)
                {
                    throw new ArgumentNullException("g");
                }
                if (backgroundImageLayout == ImageLayout.Tile)
                {
                    using (TextureBrush brush = new TextureBrush(backgroundImage, WrapMode.Tile))
                    {
                        if (scrollOffset != Point.Empty)
                        {
                            Matrix transform = brush.Transform;
                            transform.Translate((float)scrollOffset.X, (float)scrollOffset.Y);
                            brush.Transform = transform;
                        }
                        g.FillRectangle(brush, clipRect);
                        return;
                    }
                }
                Rectangle rect = CalculateBackgroundImageRectangle(bounds, backgroundImage, backgroundImageLayout);
                if ((rightToLeft == RightToLeft.Yes) && (backgroundImageLayout == ImageLayout.None))
                {
                    rect.X += clipRect.Width - rect.Width;
                }
                using (SolidBrush brush2 = new SolidBrush(backColor))
                {
                    g.FillRectangle(brush2, clipRect);
                }
                if (!clipRect.Contains(rect))
                {
                    if ((backgroundImageLayout == ImageLayout.Stretch) || (backgroundImageLayout == ImageLayout.Zoom))
                    {
                        rect.Intersect(clipRect);
                        g.DrawImage(backgroundImage, rect);
                    }
                    else if (backgroundImageLayout == ImageLayout.None)
                    {
                        rect.Offset(clipRect.Location);
                        Rectangle destRect = rect;
                        destRect.Intersect(clipRect);
                        Rectangle rectangle3 = new Rectangle(Point.Empty, destRect.Size);
                        g.DrawImage(backgroundImage, destRect, rectangle3.X, rectangle3.Y, rectangle3.Width, rectangle3.Height, GraphicsUnit.Pixel);
                    }
                    else
                    {
                        Rectangle rectangle4 = rect;
                        rectangle4.Intersect(clipRect);
                        Rectangle rectangle5 = new Rectangle(new Point(rectangle4.X - rect.X, rectangle4.Y - rect.Y), rectangle4.Size);
                        g.DrawImage(backgroundImage, rectangle4, rectangle5.X, rectangle5.Y, rectangle5.Width, rectangle5.Height, GraphicsUnit.Pixel);
                    }
                }
                else
                {
                    ImageAttributes imageAttr = new ImageAttributes();
                    imageAttr.SetWrapMode(WrapMode.TileFlipXY);
                    g.DrawImage(backgroundImage, rect, 0, 0, backgroundImage.Width, backgroundImage.Height, GraphicsUnit.Pixel, imageAttr);
                    imageAttr.Dispose();
                }
            }
            internal void PaintTransparentBackground(DotNet.Windows.Forms.Internal.PaintEventArgs e, Rectangle rectangle, System.Drawing.Region transparentRegion)
            {
                Graphics g = e.Graphics;
                Control parentInternal = Control.Parent;
                if (parentInternal != null)
                {
                    if (Application.RenderWithVisualStyles) // parentInternal.RenderTransparencyWithVisualStyles)
                    {
                        System.Drawing.Drawing2D.GraphicsState gstate = null;
                        if (transparentRegion != null)
                        {
                            gstate = g.Save();
                        }
                        try
                        {
                            if (transparentRegion != null)
                            {
                                g.Clip = transparentRegion;
                            }
                            ButtonRenderer.DrawParentBackground(g, rectangle, Control);
                            return;
                        }
                        finally
                        {
                            if (gstate != null)
                            {
                                g.Restore(gstate);
                            }
                        }
                    }
                    Rectangle rectangle2 = new Rectangle(-Control.Left, -Control.Top, parentInternal.Width, parentInternal.Height);
                    Rectangle clipRect = new Rectangle(rectangle.Left + Control.Left, rectangle.Top + Control.Top, rectangle.Width, rectangle.Height);
                    using (WindowsGraphics graphics2 = WindowsGraphics.FromGraphics(g))
                    {
                        graphics2.DeviceContext.TranslateTransform(-Control.Left, -Control.Top);
                        using (DotNet.Windows.Forms.Internal.PaintEventArgs args = new DotNet.Windows.Forms.Internal.PaintEventArgs(graphics2.GetHdc(), clipRect))
                        {
                            if (transparentRegion != null)
                            {
                                args.Graphics.Clip = transparentRegion;
                                args.Graphics.TranslateClip(-rectangle2.X, -rectangle2.Y);
                            }
                            try
                            {
                                //this.InvokePaintBackground(parentInternal, args);
                                //this.InvokePaint(parentInternal, args);
                            }
                            finally
                            {
                                if (transparentRegion != null)
                                {
                                    args.Graphics.TranslateClip(rectangle2.X, rectangle2.Y);
                                }
                            }
                        }
                        return;
                    }
                }
                g.FillRectangle(SystemBrushes.Control, rectangle);
            }
            internal void PaintBackground(DotNet.Windows.Forms.Internal.PaintEventArgs e, Rectangle rectangle, System.Drawing.Color backColor, Point scrollOffset)
            {
                backColor = Color.Transparent;
                //ControlStyles.SupportsTransparentBackColor;
                this.PaintTransparentBackground(e, rectangle);
                //if (this.RenderColorTransparent(backColor))
                //{
                //    this.PaintTransparentBackground(e, rectangle);
                //}
                bool flag = ((Control is FormBase) || (this is MdiClient)) && Control.IsMirrored;
                if (((Control.BackgroundImage != null) && !SystemInformation.HighContrast) && !flag)
                {
                    if ((Control.BackgroundImageLayout == ImageLayout.Tile) && IsImageTransparent(Control.BackgroundImage))
                    {
                        PaintTransparentBackground(e, rectangle);
                    }
                    Point autoScrollPosition = scrollOffset;
                    if ((Control is ScrollableControl) && (autoScrollPosition != Point.Empty))
                    {
                        autoScrollPosition = ((ScrollableControl)(Control)Control).AutoScrollPosition;
                    }
                    if (IsImageTransparent(Control.BackgroundImage))
                    {
                        PaintBackColor(e, rectangle, backColor);
                    }
                    DrawBackgroundImage(e.Graphics, Control.BackgroundImage, backColor, Control.BackgroundImageLayout, Control.ClientRectangle, rectangle, autoScrollPosition, Control.RightToLeft);
                }
                else
                {
                    PaintBackColor(e, rectangle, backColor);
                }
            }
            private static void PaintBackColor(DotNet.Windows.Forms.Internal.PaintEventArgs e, Rectangle rectangle, System.Drawing.Color backColor)
            {
                System.Drawing.Color nearestColor = backColor;
                if (nearestColor.A == 0xff)
                {
                    using (WindowsGraphics graphics = ((e.HDC != IntPtr.Zero) && ((short)Screen.PrimaryScreen.BitsPerPixel > 8)) ? WindowsGraphics.FromHdc(e.HDC) : WindowsGraphics.FromGraphics(e.Graphics))
                    {
                        nearestColor = graphics.GetNearestColor(nearestColor);
                        using (WindowsBrush brush = new WindowsSolidBrush(graphics.DeviceContext, nearestColor))
                        {
                            graphics.FillRectangle(brush, rectangle);
                        }
                        return;
                    }
                }
                if (nearestColor.A > 0)
                {
                    using (Brush brush2 = new SolidBrush(nearestColor))
                    {
                        e.Graphics.FillRectangle(brush2, rectangle);
                    }
                }
            }
            private void PaintWithErrorHandling(DotNet.Windows.Forms.Internal.PaintEventArgs e, short layer)
            {
                try
                {
                    this.CacheTextInternal = true;
                    bool flag = true;
                    try
                    {
                        switch (layer)
                        {
                            case 1:
                                this.OnPaintBackground(e);
                                break;
                            case 2:
                                this.OnPaint(e);
                                break;
                        }
                        flag = false;
                    }
                    finally
                    {
                        if (flag)
                        {
                            this.SetState(0x400000, true);
                            Control.Invalidate();
                        }
                    }
                }
                finally
                {
                    this.CacheTextInternal = false;
                }
            }
            void IWindowTarget.OnMessage(ref Message m)
            {
                if (m.Msg == 15)
                {
                    WmPaint(ref m);
                    return;
                }
                Target.OnMessage(ref m);
            }
    
            #endregion
        }
    }
    View Code

    http://files.cnblogs.com/dotnet-org-cn/DotNet.Framework.rar

    最后打个小广告:中国.NET协会(http://www.dotnet.org.cn
    腾讯企鹅群:45132984中国.NET协会
    博客园地址:http://http://www.cnblogs.com/dotnet-org-cn
         国内唯一一个以非盈利的.NET协会,致力打造国内具有权威性、价值性的.NET协会。

  • 相关阅读:
    android创建自定义对话框
    激光裁剪的商务名片
    60个响应式的Web设计教程–能够手机访问!
    前端性能优化:使用Data URI代替图片SRC
    40个最好的Tumblr主题
    40个超酷的jQuery动画效果教程
    15个最好的jQuery timeline插件
    60+富有创意的宣传册设计
    Eclipse安装SVN
    EXPLAIN 关键字可以 查看 sql执行 的详细过程
  • 原文地址:https://www.cnblogs.com/dotnet-org-cn/p/4166250.html
Copyright © 2011-2022 走看看