[用UpdateLayeredWindow实现任意异形窗口]
前面提到,我们可以用SetWindowRgn或SetLayeredWindowAttributes实现不规则以及半透明的效果
对于SetWindowRgn,它通过一个Rgn来设置区域,这个Rgn一般可以从图片中读取,在这张图片中,将不需要显示的区域标记为一种特殊的颜色,这里有个问题,必须保证这种颜色没有被正常的区域使用,否则会被误伤。为了解决这个问题,可以考虑用两张图片,增加一张单色的掩码图,这种方案带来了额外的管理开销。SetWindowRgn的好处是效率较高,对于大部分自绘的皮肤,一般只有四个角落有一些不规则,所以用SetWindowRgn是最好的选择。
SetLayeredWindowAttributes可以将特定的窗口设置为某种透明度,也可以用它来过滤某种颜色,匹配的颜色会变成全透明。也就是类似于SetWindowRgn的效果。SetLayeredWindowAttributes直接从DC中获得颜色,所以你需要事先绘制DC。
SetLayeredWindowAttributes过滤颜色后,相关区域虽然不可见,但是不可见的区域可以放置子窗口,这点和SetWindowRgn有所区别。此外若子窗口刷新不及时或其他原因,那么父窗口因为SetLayeredWindowAttributes被隐藏的DC颜色将被浮出水面。
UpdateLayeredWindow直接根据DC中的Alpha通道来实现透明效果,它很好的处理了和背景的Alpha Blend的问题,所以完美的解决了SetWindowRgn的锯齿问题。
Sample
    template<typename T,bool DLG>
    class ImageFrameT{
    public:
        BEGIN_MSG_MAP(ImageFrameT)
            MESSAGE_HANDLER(WM_CREATE, OnCreate)
            MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
            MESSAGE_HANDLER(WM_PAINT, OnPaint)
            MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
            MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLBttonDown)
        END_MSG_MAP()
        ImageFrameT():m_res_(NULL),m_move_flag_(false){}
        virtual ~ImageFrameT(){}
        LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled){
            bHandled = FALSE;
            // 通过参数获得资源句柄
            LPCREATESTRUCT lpCreateStruct = (LPCREATESTRUCT)lParam;
            if(lpCreateStruct && lpCreateStruct->lpCreateParams)
                m_res_ = (CImage*)(lpCreateStruct->lpCreateParams);
            ATLASSERT(m_res_);
            if(!DLG)
                this->InitSelf();
            return 0;
        }
        LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled){
            bHandled = FALSE;
            if(lParam){
                // 通过参数获得资源句柄
                m_res_ = (CImage*)lParam;
            }
            if(DLG)
                this->InitSelf();
            return 0;
        }
        LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/){
            // OnPaint不作任何事,转到UpdateLayeredWindow处理
            T* pT = static_cast<T*>(this);
            CPaintDC dc_(pT->m_hWnd);
            return TRUE;
        }
        LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/){
            // 屏蔽背景绘制
            return TRUE;
        }
        LRESULT OnLBttonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled){
            // 是否支持整窗口拖动
            T* pT = static_cast<T*>(this);
            if(this->m_move_flag_)
                pT->PostMessage(WM_SYSCOMMAND,0xF012,0);
            else
                bHandled = FALSE;
            return 0;
        }
        void            SetRes(CImage* res){
            // 设置资源
            ATLASSERT(res);
            if(res)
                this->m_res_ = res;
        }
        void            SetMoveFlag(bool flag){
            // 设置是否可拖动
            this->m_move_flag_ = flag;
        }
    private:
        void            InitSelf(){
            ATLASSERT(m_res_);
            if(m_res_){
                T* pT = static_cast<T*>(this);
                // 设置属性WS_EX_LAYERED
                LONG lWindowLong = ::GetWindowLong(pT->m_hWnd, GWL_EXSTYLE) | WS_EX_LAYERED;
                ::SetWindowLong(pT->m_hWnd, GWL_EXSTYLE, lWindowLong);
                // 设置属性WS_POPUP
                lWindowLong = ::GetWindowLong(pT->m_hWnd, GWL_STYLE) | WS_POPUP;
                // 去掉一堆其他属性
                lWindowLong &= ~WS_CHILD;
                lWindowLong &= ~WS_BORDER;
                lWindowLong &= ~WS_CAPTION;
                lWindowLong &= ~WS_SYSMENU;
                ::SetWindowLong(pT->m_hWnd, GWL_STYLE, lWindowLong);
                pT->SetWindowPos(HWND_BOTTOM,0,0,
                        m_res_->GetWidth(),m_res_->GetHeight(),
                        SWP_NOMOVE | SWP_NOOWNERZORDER);
                CClientDC dc_(pT->m_hWnd);
                CDC mem_dc_;
                mem_dc_.CreateCompatibleDC(dc_);
                CBitmap mem_bitmap_;
                mem_bitmap_.CreateCompatibleBitmap(dc_,
                        m_res_->GetWidth(),
                        m_res_->GetHeight());
                mem_dc_.SelectBitmap(mem_bitmap_);
                m_res_->Draw(mem_dc_,0,0);
                BLENDFUNCTION pb_;
                pb_.AlphaFormat = 1;
                pb_.BlendOp = 0;
                pb_.BlendFlags =0;
                pb_.SourceConstantAlpha = 0xFF;
                CPoint  pt_(0,0);
                CSize   size_(m_res_->GetWidth(),m_res_->GetHeight());
                ::UpdateLayeredWindow(pT->m_hWnd,dc_,&pt_,&size_,mem_dc_,&pt_,0,&pb_,ULW_ALPHA );
                pT->CenterWindow(NULL);
            }
        }
    protected:
        CImage*         m_res_;
        bool            m_move_flag_;
    };
    class CAboutDlg :
        public CDialogImpl<CAboutDlg>,
        public ImageFrameT<CAboutDlg,true>
    {
        typedef ImageFrameT<CAboutDlg,true> BaseClass;
    public:
        enum { IDD = IDD_DIALOG1 };
        BEGIN_MSG_MAP(CAboutDlg)
            CHAIN_MSG_MAP(BaseClass)
            MESSAGE_HANDLER(WM_RBUTTONDOWN, OnClose)
        END_MSG_MAP()
        LRESULT OnClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
        {
            EndDialog(0);
            return 0;
        }
    };
    CImage      bitmap_bg_;
    BOOL ret_ = File2CImageAndImplAlpha(&bitmap_bg_,_T("res/bk.png"));
    ATLASSERT(ret_);
    CAboutDlg dlg_;
    dlg_.SetMoveFlag(true);
    dlg_.DoModal(this->m_hSubWindow_,(LPARAM)(&bitmap_bg_));
放置子控件
若只需要最一个简单的窗口,那么上面的代码可以完成要求。UpdateLayeredWindow有一个问题,那就是它上面不能放置任何子窗口,放置上去的任何窗口都不可见。为了解决这个问题,一种简单的办法是自绘,在单个窗口中模拟各种消息。
若不想搞复杂,有一种变通的办法,那就是在上面放置一个非子窗口,这种子窗口大小位置保持和它一致,同时这个子窗口用SetLayeredWindowAttributes搞成全透明,接下来我们将所有子控件放到这个全透明的子窗口即可。
Sample
    #define CHAIN_MSG_MAP_ALT_MEMBER_EX(theChainMember, msgMapID, msg) \
        { \
            if(uMsg == msg && \
                theChainMember &&\
                theChainMember->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, msgMapID)) \
                return TRUE; \
        }
    // 放置在ImageFrameT上的子窗口
    // 这个类主要处理消息的转发,通过WM_CREATE获得最顶层窗口的指针
    // 并存储在m_message_变量中,然后使用CHAIN_MSG_MAP_ALT_MEMBER_EX
    // 将它子窗口发给它的WM_COMMAND,WM_NOTIFY转发过去
    template<typename T,typename Y>
    class SubWindowT{
    public:
        BEGIN_MSG_MAP(SubWindowT)
            MESSAGE_HANDLER(WM_CREATE, OnCreate)
            MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
            // 将这个不可见的窗口的WM_COMMAND和WM_NOTIFY消息
            // 转发给最顶层的窗口
            CHAIN_MSG_MAP_ALT_MEMBER_EX(m_message_,1,WM_COMMAND)
            CHAIN_MSG_MAP_ALT_MEMBER_EX(m_message_,1,WM_NOTIFY)
        END_MSG_MAP()
        SubWindowT():m_message_(NULL){};
        LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled){
            bHandled = FALSE;
            T* pT = static_cast<T*>(this);
            LPCREATESTRUCT lpCreateStruct = (LPCREATESTRUCT)lParam;
            // 初始化m_message_
            if(lpCreateStruct && lpCreateStruct->lpCreateParams)
                m_message_ = (Y*)(lpCreateStruct->lpCreateParams);
            ATLASSERT(m_message_);
            // 设置属性WS_POPUP
            LONG lWindowLong = ::GetWindowLong(pT->m_hWnd, GWL_STYLE) | WS_POPUP;
            // 去掉一堆其他属性
            lWindowLong &= ~WS_CHILD;
            lWindowLong &= ~WS_BORDER;
            lWindowLong &= ~WS_CAPTION;
            lWindowLong &= ~WS_SYSMENU;
            ::SetWindowLong(pT->m_hWnd, GWL_STYLE, lWindowLong);
            return 0;
        }
        LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/){
            // 屏蔽背景消息
            return TRUE;
        }
        // 这个指针指向最顶层的窗口,用它来将紧贴这顶层窗口的不可见窗口的消息
        // 转发给m_message_
        // 注意宏CHAIN_MSG_MAP_ALT_MEMBER_EX
        Y*      m_message_;
    };
    // 这个类在SubWindowT的基础上实现了全透明的效果
    // 利用SetLayeredWindowAttributes可以对某种特定的颜色实现全透明过滤的特性
    template<typename Y>
    class SubWindow1 :
        public CWindowImpl<SubWindow1<Y>,CWindow>,
        public SubWindowT<SubWindow1<Y>,Y>{
        typedef SubWindowT<SubWindow1<Y>,Y> BaseClass;
    public:
        BEGIN_MSG_MAP(SubWindow1)
            CHAIN_MSG_MAP(BaseClass) //连接基类的消息处理逻辑,并优先处理
            MESSAGE_HANDLER(WM_CREATE, OnCreate)
            MESSAGE_HANDLER(WM_PAINT, OnPaint)
            REFLECT_NOTIFICATIONS()
        END_MSG_MAP()
        LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled){
            bHandled = FALSE;
            // 设置属性WS_EX_LAYERED
            LONG lWindowLong = ::GetWindowLong(this->m_hWnd, GWL_EXSTYLE) | WS_EX_LAYERED;
            lWindowLong &= ~WS_EX_TRANSPARENT;
            ::SetWindowLong(this->m_hWnd, GWL_EXSTYLE, lWindowLong);
            // 在OnPaint里面将整个窗口刷成RGB(255,0,255)
            // 在这里将此颜色过滤(编程全透明)
            ::SetLayeredWindowAttributes(this->m_hWnd,RGB(255,0,255),0,LWA_COLORKEY);
            return 0;
        }
        LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/){
            // 在OnPaint里面将整个窗口刷成RGB(255,0,255)
            // 以便让SetLayeredWindowAttributes过滤
            CPaintDC dc_(this->m_hWnd);
            CRect client_rect_;
            this->GetClientRect(client_rect_);
            dc_.FillSolidRect(client_rect_,RGB(255,0,255));
            return TRUE;
        }
    };
    template<typename T,bool DLG,template<typename X> class SUB_WINDOW >
    class ImageFrameExT : public ImageFrameT<T,DLG>{
        typedef ImageFrameT<T,DLG> BaseClass;
    public:
        BEGIN_MSG_MAP(ImageFrameExT)
            CHAIN_MSG_MAP(BaseClass)
            MESSAGE_HANDLER(WM_CREATE, OnCreate)
            MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
            MESSAGE_HANDLER(WM_MOVE, OnMove)
        END_MSG_MAP()
        ImageFrameExT(){
            m_sub_rect_.SetRect(0,0,0,0);
        }
        LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled){
            bHandled = FALSE;
            T* pT = static_cast<T*>(this);
            if(!DLG){
                // 一并创建子窗口
                // 注意它将pT传给了最后一个参数,这个在
                // OnCreate传给了SubWindowT
                m_hSubWindow_.Create(pT->m_hWnd,NULL,NULL,
                        WS_VISIBLE,0,0U,pT);
            }
            return 0;
        }
        LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled){
            bHandled = FALSE;
            T* pT = static_cast<T*>(this);
            if(DLG){
                // 一并创建子窗口
                // 注意这里没有WS_CHILD
                m_hSubWindow_.Create(pT->m_hWnd,NULL,NULL,
                        WS_VISIBLE,0,0U,pT);
            }
            return 0;
        }
        LRESULT OnMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled){
            // 动态更新子窗口
            bHandled = FALSE;
            T* pT = static_cast<T*>(this);
            if(m_hSubWindow_.IsWindow()){
                CRect win_rect_;
                pT->GetWindowRect(win_rect_);
                if(m_sub_rect_.IsRectNull()){
                    m_hSubWindow_.MoveWindow(win_rect_);
                }else{
                    CRect tmp_ = m_sub_rect_;
                    tmp_.OffsetRect(win_rect_.TopLeft());
                    m_hSubWindow_.MoveWindow(tmp_);
                }
            }
            return 0;
        }
        SUB_WINDOW<T>*      SubWindow(){
            // 获得子窗口
            return &m_hSubWindow_;
        }
        void                SetSubRect(const CRect& rect){
            // 可以设置让子窗口位于那块区域,而不一定要占满整屏
            m_sub_rect_ = rect;
        }
    protected:
        SUB_WINDOW<T>       m_hSubWindow_;
        CRect               m_sub_rect_;
    };
    class CMainFrame :
        public CFrameWindowImpl<CMainFrame>,
        public ImageFrameExT<CMainFrame,false,SubWindow1 >
    {
        typedef ImageFrameExT<CMainFrame,false,SubWindow1 > BaseClass;
    public:
        DECLARE_FRAME_WND_CLASS(NULL, IDR_MAINFRAME)
        BEGIN_MSG_MAP(CMainFrame)
            //REFLECT_NOTIFICATIONS()
            CHAIN_MSG_MAP(BaseClass)
            MESSAGE_HANDLER(WM_CREATE, OnCreate)
            MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
            CHAIN_MSG_MAP(CFrameWindowImpl<CMainFrame>)
            ALT_MSG_MAP(1)
            COMMAND_CODE_HANDLER(BN_CLICKED,OnClick)
        END_MSG_MAP()
        LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
        {
            m_close_.Create(this->m_hSubWindow_,
                    CRect(200,200,50 + 200,26 + 200),
                    _T("Close"),
                    WS_CHILD | WS_VISIBLE);
            m_help_.Create(this->m_hSubWindow_,
                    CRect(260,200,50 + 260,26 + 200),
                    _T("Help"),
                    WS_CHILD | WS_VISIBLE);
            m_help2_.Create(this->m_hSubWindow_,
                    CRect(320,200,50 + 320,26 + 200),
                    _T("Help2"),
                    WS_CHILD | WS_VISIBLE);
            return 0;
        }
        LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
        {
            // 解决wtl不能关闭ws_popup的bug
            PostQuitMessage(0);
            bHandled = FALSE;
            return 1;
        }
        LRESULT OnClick(WORD wNotifyCode, WORD wID, HWND hWndCtl,
              BOOL& bHandled){
            if(m_close_ == hWndCtl){
                this->PostMessage(WM_CLOSE);
            }else if(m_help_ == hWndCtl){
            }else if(m_help2_ == hWndCtl){
            }
            return 0;
        }
        CButton     m_close_;
        CButton     m_help_;
        CButton     m_help2_;
    };
其他问题
若上面放置普通的矩形控件,并且不支持透明,那么啥问题都没有,然后若要实现不规则或者透明控件,那么全透明窗口被过滤的颜色将被显示出来
一个变通的办法就是将需要填充子控件的区域抠出来,并交给这个子窗口来画(这就要求放置控件区域的地方没有半透明,大部分需求都只是希望能够处理简单的异形,并且消除锯齿)。
    // 将父窗口中间抠出来,交给子窗口来画
    template<typename Y>
    class SubWindow2 :
        public CWindowImpl<SubWindow2<Y>,CWindow>,
        public SubWindowT<SubWindow2<Y>,Y>{
        typedef SubWindowT<SubWindow2<Y>,Y> BaseClass;
    public:
        BEGIN_MSG_MAP(SubWindow2)
            CHAIN_MSG_MAP(BaseClass)
            MESSAGE_HANDLER(WM_PAINT, OnPaint)
            REFLECT_NOTIFICATIONS()
        END_MSG_MAP()
        LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/){
            CPaintDC dc_(this->m_hWnd);
            ATLASSERT(m_res_);
            if(m_res_)
                m_res_->Draw(dc_,0,0);
            return TRUE;
        }
        inline void SetRes(CImage* res){
            ATLASSERT(res);
            if(res)
                this->m_res_ = res;
        }
    private:
        CImage*     m_res_;
    };
    class CAboutDlgEx :
        public CDialogImpl<CAboutDlgEx>,
        public ImageFrameExT<CAboutDlgEx,true,SubWindow2>
    {
        typedef ImageFrameExT<CAboutDlgEx,true,SubWindow2> BaseClass;
    public:
        enum { IDD = IDD_DIALOG1 };
        BEGIN_MSG_MAP(CAboutDlgEx)
            CHAIN_MSG_MAP(BaseClass)
            MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
            MESSAGE_HANDLER(WM_RBUTTONDOWN, OnClose)
            ALT_MSG_MAP(1)
        END_MSG_MAP()
        LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/){
            bool ret_ = m_res_.InitFromFile(
                    _T("res/imgbtn.png"),
                    _T("res/imgbtn_h.png"),
                    _T("res/imgbtn_p.png"),
                    _T("res/imgbtn_d.png"));
            ATLASSERT(ret_);
            m_btn_.Create(this->m_hSubWindow_,NULL,NULL,0,0,0U,&m_res_);
            m_btn_.MoveWindow(120,120,0,0,TRUE);
            return 0;
        }
        LRESULT OnClose(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/){
            EndDialog(0);
            return 0;
        }
        ImageButton<ButtonRes,true>     m_btn_;
        ButtonRes       m_res_;
    };
经测试,这种方案在拖动时,两个窗口交接处有明显的刷新不一致存在。
Bug
在一些非32位图像模式下,该函数会有些问题,解决办法就是强制创建32位的Bitmap
CBitmap bitmap;
BITMAPINFOHEADER bmih;
bmih.biSize                  = sizeof (BITMAPINFOHEADER) ;
bmih.biWidth                 = 384 ;
bmih.biHeight                = 256 ;
bmih.biPlanes                = 1 ;
bmih.biBitCount              = 32 ;  //注意32位
bmih.biCompression           = BI_RGB ;
bmih.biSizeImage             = 0 ;
bmih.biXPelsPerMeter         = 0 ;
bmih.biYPelsPerMeter         = 0 ;
bmih.biClrUsed               = 0 ;
bmih.biClrImportant          = 0 ;
bitmap.CreateDIBitmap(dc,&bmih);
为了避免绘图汇到左上角,需要在调用UpdateLayeredWindow时,明确指定左上角坐标
CRect rect_;
GetWindowRect(rect_);
CPoint topleft(rect_.left,rect_.top);
CPoint  pt_(0,0);
CSize   size_(m_res_->GetWidth(),m_res_->GetHeight());
::UpdateLayeredWindow(pT->m_hWnd,dc_,&topleft,&size_,mem_dc_,&pt_,0,&pb_,ULW_ALPHA );
参考
[用UpdateLayeredWindow实现任意异形窗口]的更多相关文章
- 一个最简单的Delphi2010的PNG异形窗口方法
		
同事演示了一个.NET的的PNG异形窗口.挺漂亮.于是也想用Delphi显摆一个. 关于Delphi用PNG做异形窗口的资料有不少.都是用GDIPlus或者TPNGImage组件加载PNG图像做的.但 ...
 - Win32创建异形窗口
		
大家都见过在windows下各种气泡窗口.输入法窗口以及其他一些窗口,这些窗口看起来不像传统的windows窗那样,上面是标题栏,下面是窗口的客户区.这些窗口形状各异,可以是一个多边形,一幅图,甚至是 ...
 - 使用Unity3d做异形窗口
		
项目马上上线,因为之前的登录器是使用VS2010的MFC做的,在很多电脑上会提示缺失mfcXXXX.dll,中间找寻这种解决方案,最后确定将vcredist2010_x86和我的程序打包到安装包里面, ...
 - WPF Window异形窗口演示
		
我们先通过简单的效果展示,切换展示不同图片: 我们先定义图片资源文件,我们可以在window资源中定义,下面的在app.xaml文件来定义: <Application x:Class=" ...
 - QT中异形窗口的绘制(winEvent处理WM_NCHITTEST消息)
		
这里讨论的只是Windows平台上的实现. 在QT中绘制异形窗口,只要设定 windowFlag 为 CustomizeWindowHint,再结合setMask()就可以做出各种奇形怪状的窗口.相对 ...
 - Qt QSplitter任意拆分窗口
		
Qt拆分窗口可以使用QSplitter,也可以使用比较容易使用布局控件来完成,本文章给出使用QSplitter分割窗口的例子. QSplitter 继承自QFrame,而QFrame又继承自QWidg ...
 - c# UpdateLayeredWindow异形窗口
		
#region UpdateLayeredWindow #region 重写窗体的 CreateParams 属性 protected override CreateParams CreatePara ...
 - 窗口界面编程之一:VB实现简单异形窗口
		
一.运行效果图(在Win8里的运行效果,在XP里运行就不能体现出来,因为我使用的XP的界面效果) 二.编译环境:Visual Basic 6.0 (SP6) 三.实现原理:通过区域合并 四.使用API ...
 - Delphi异形窗口之PNG
		
//1.单元内容 unit UnitAlienForm; interface uses Windows, Forms, Classes, Graphics; //从文件加载PNG procedure ...
 
随机推荐
- IOS基础:深入理解Objective-c中@class的含义
			
objective-c中,当一个类使用到另一个类时,并且在类的头文件中需要创建被引用的指针时, 如下面代码: A.h文件 #import "B.h" @interface A : ...
 - linux install nginx error
			
1 2 3 4 5 6 7 8 9 10 11 [mahao01@127.0.0.1 nginx-1.2.9]$ make make -f objs/Makefile make[1]: Enterin ...
 - Servlet基础知识(三)—— 会话机制Session,Session和Cookie的异同
			
Servlet会话机制: Http是一种无状态协议,它是无记忆的.也就是说,服务器不会保存用户的任何信息,当同一用户再次去访问时,服务器是不认识你的,它还是会建立新的连接. 但有时候我们需要服务器保留 ...
 - mysql中判断表中是否存在某条记录
			
SELECT CASE WHEN EXISTS (SELECT * FROM usergroupmap WHERE groupId = groupIdIn AND userId = v_friendI ...
 - python strip()函数介绍
			
函数原型 声明:str为字符串,s为要删除的字符序列 str.strip(s) 删除str字符串中开头.结尾处,位于 s删除序列的字符 str.lstrip(s) 删除str ...
 - gmpy2安装使用方法
			
GMP(GNU Multiple Precision Arithmetic Library,即GNU高精度算术运算库),它是一个开源的高精度运算库,其中不但有普通的整数.实数.浮点数的高精度运算,还有 ...
 - Cortex-M3动态加载三(模块调用系统函数)
			
在我的arm动态加载实验中需要解决一个模块调用系统函数的问题,可以使用以下的一个方法.将系统函数固定在某一段地址空间,然后导出这一块的符号表到符号文件中,要记载的模块link的时候使用这个符号表文件, ...
 - jquery.validate 一些技巧
			
1.Validator.element() Validates a single element, returns true if it is valid, false otherwise. http ...
 - Android 在一个程序中启动另一个程序
			
Android 开发有时需要在一个应用中启动另一个应用,比如Launcher加载所有的已安装的程序的列表,当点击图标时可以启动另一个应用.一般我们知道了另一个应用的包名和MainActivity的名字 ...
 - 射频识别技术漫谈(29)——射频接口芯片TRF7960
			
TRF7960系列是TI推出的载波为13.56MHz.支持ISO15693.ISO14443A/B和FeliCa协议的射频接口芯片.许多人更关心它能不能读写MF1卡片,就我的理解及实际验证,由于MF1 ...