norains的专栏

只专注于WINCE开发

用户操作
[即时聊天] [发私信] [加为好友]
norainsID:norains
142917次访问,排名598,好友0人,关注者53人。
代码其实是一种乐趣
norains的文章
原创 189 篇
翻译 0 篇
转载 10 篇
评论 274 篇
norains的公告
联系方式请看置顶文章
最近评论
dfdf:讨厌MFC!我觉得MFC就是太乱了!看似无用的代码不要不行,MD微软啥都给我们做完了,原理性的东西我们却永远没法搞懂了!
ironox:有个地方 我觉得很别扭,不知道怎么办好

比如说 CReg reg(HKEY_CURRENT_USER,TEXT("ControlPanel\Volume"));
ControlPanel\Volume 有可能不存在呀,这个该怎么处理哦?对象虽然创建了,出错了也没提示
szterry:呵呵,果然工作狂技术狂,同感,一样的感觉……不过我才刚毕业一年……搞IT就是玩……
jinlking:这个botton的实现只是在主窗口画了一块区域,对于事件的处理还要放在主窗口的窗口处理函数之中,在对应的消息处理上调用CheckTap来判断是否是此“按钮”,问一下,这种方法与把按钮封装在子窗口中有什么区别,二者使用那个更好?
KUODY:博主真是好人
文章分类
收藏
    相册
    动漫
    文章图片
    程序交流
    xumercury的BLOG
    狗友们的博客
    清蒸石斑鱼
    美女如刀锋
    茁茁的BLOG
    魅力老姐的窝
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 四论在C++类中实现Windows窗口的创建收藏

    新一篇: COM宏小结 | 旧一篇: WinCE同步和硬盘模式的切换

    //========================================================================
    //TITLE:
    //    四论在C++类中实现Windows窗口的创建
    //AUTHOR:
    //    norains
    //DATE:
    //    Tuesday  23-October-2007
    //Environment:
    //        EVC4.0 + Windows CE 5.0 Standard SDK
    //========================================================================


        之前写过三篇关于在类中封装window窗口的文章,其中的代码无一例外都是只能有一个窗口实例.一般来说,在普通的单界面使用场合中是足够了,也不会有什么很大的问题,但如果是多界面的环境中则将无能为力,比如浏览器的多页面浏览,如果按照之前文章所封装的方法,那么多页面也只能是虚假----因为永远只有一个窗口实例.
       
        C++类中封装窗口的创建一个关键在于,WNDCLASS->lpfnWndProc这个窗口过程处理函数必须不属于任何对象,也就是说只能属于类,亦即必须是static类型.而如果函数为static,会带来一个问题,就是不能直接读取实例对象的变量.之前的文章为了解决这个问题,特意设置了一个static的实例对象指针m_pInstance,然后在WndProc()函数中通过m_pInstance->Function()方式来调用对象的函数和变量(具体可参见之前文章的WndProc()函数代码).由此可见,如果要实现同一个类能创建多个实例对象,就必须要解决这个static WndProc()函数读取实例对象的变量问题.
       
        在本文中,C++类中还是存在一个static的WndProc()函数(以下以示例代码的StaticWndProc()函数替代),不过此时这个函数功能和之前文章的截然不同,而是用来向不同的实例发送窗口消息.要实现这点,我们首先要知道这个消息需要传送给哪个窗口实例,这个就需要一点小技巧.

        在窗口创建完毕之后,我们将实例对象指针存储在窗口的GWL_USERDATA地址中:
    SetWindowLong(m_hWnd, GWL_USERDATA, (DWORD)this);

        然后在StaticWndProc通过GetWindowLong()函数获取该实例对象指针,并且使用该指针调用实例对象的WndProc()函数:
        //获取实例对象指针
        CSimpleWnd *pObject = (CSimpleWnd*)GetWindowLong(hWnd, GWL_USERDATA);
        
    //调用实例对象的窗口处理函数
        pObject->WndProc(hWnd,msg,wParam,lParam);

        OK,就是这么简单,简简单单的两个代码,就完成了静态窗口函数向对象窗口函数的联结,同时也解决了本文创建多个对象窗口的难题.
       
        我们来看看一个简单的封装好的窗口类代码:

    /////////////////////////////////////////////////////////////////////
    // SimpleWnd.h: interface for the CSimpleWnd class.
    //
    //////////////////////////////////////////////////////////////////////
    #ifndef SIMPLEWND_H
    #define SIMPLEWND_H

    class CSimpleWnd  
    {
    public:
        BOOL Create(HINSTANCE hInst,HWND hWndParent);
        BOOL ShowWindow(BOOL bShow);    
        CSimpleWnd();
        
    virtual ~CSimpleWnd();

    protected:
        BOOL RegisterWnd(HINSTANCE hInst,HWND hWndParent);
        LRESULT WndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
        
    static LRESULT StaticWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
        
        HWND m_hWnd;
        HWND m_hWndParent;
        HINSTANCE m_hInst;
    };

    #endif //#ifndef SIMPLEWND_H




    //////////////////////////////////////////////////////////////////////
    // SimpleWnd.cpp: implementation of the CSimpleWnd class.
    //
    //////////////////////////////////////////////////////////////////////

    #include 
    "stdafx.h"
    #include 
    "SimpleWnd.h"

    //=====================================================================
    //Macro define
    #define WND_NAME        TEXT("SimpleWnd_name")
    #define WND_CLASS        TEXT("SimpleWnd_cls")
    //=====================================================================
    //////////////////////////////////////////////////////////////////////
    // Construction/Destruction
    //////////////////////////////////////////////////////////////////////

    CSimpleWnd::CSimpleWnd():
    m_hWnd(NULL),
    m_hWndParent(NULL),
    m_hInst(NULL)
    {

    }

    CSimpleWnd::
    ~CSimpleWnd()
    {

    }

    //----------------------------------------------------------------------
    //Description:
    //    Initialize
    //----------------------------------------------------------------------
    BOOL CSimpleWnd::RegisterWnd(HINSTANCE hInst, HWND hWndParent)
    {

        
        
        
        
    static BOOL s_bRegistered = FALSE;
        WNDCLASS        wc;
        
    if(s_bRegistered == FALSE)
        {
            wc.style         
    = 0;
            wc.lpfnWndProc   
    = (WNDPROC)CSimpleWnd::StaticWndProc;
            wc.cbClsExtra    
    = 0;
            wc.cbWndExtra    
    = 0;
            wc.hInstance     
    = m_hInst;
            wc.hIcon         
    = NULL; 
            wc.hCursor       
    = LoadCursor(NULL, IDC_ARROW);
            wc.hbrBackground 
    = (HBRUSH)GetSysColorBrush(COLOR_WINDOW);
            wc.lpszMenuName  
    = NULL;
            wc.lpszClassName 
    = WND_CLASS;
            
            
    if (RegisterClass(&wc))
            {
                s_bRegistered 
    = TRUE;
            }
        }

        
    return s_bRegistered;

        
    /*
        WNDCLASS        wc;
        wc.style         = 0;
        wc.lpfnWndProc   = (WNDPROC)CSimpleWnd::StaticWndProc;
        wc.cbClsExtra    = 0;
        wc.cbWndExtra    = 0;
        wc.hInstance     = m_hInst;
        wc.hIcon         = NULL; 
        wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
        wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_WINDOW);
        wc.lpszMenuName  = NULL;
        wc.lpszClassName = WND_CLASS;
        
        if (RegisterClass(&wc) == FALSE)
        {
            return FALSE;
        }
        

        return TRUE;
        
    */
    }

    //----------------------------------------------------------------------
    //Description:
    //    Static WndProc wrapper and actual WndProc
    //
    //----------------------------------------------------------------------
    LRESULT CSimpleWnd::StaticWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        CSimpleWnd 
    *pObject = (CSimpleWnd*)GetWindowLong(hWnd, GWL_USERDATA);

        
    if(pObject)
        {
            
    return pObject->WndProc(hWnd,msg,wParam,lParam);
        }
        
    else
        {
            
    return DefWindowProc(hWnd,msg,wParam,lParam);
        }
    }


    //----------------------------------------------------------------------
    //Description:
    //    Actual WndProc
    //
    //----------------------------------------------------------------------
    LRESULT CSimpleWnd::WndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
    {
        
    return DefWindowProc(hWnd,wMsg,wParam,lParam);
    }


    //----------------------------------------------------------------------
    //Description:
    //    Show the window
    //
    //----------------------------------------------------------------------
    BOOL CSimpleWnd::ShowWindow(BOOL bShow)
    {
        
    if(m_hWnd == NULL)
        {
            
    return FALSE;
        }

        
    if(bShow == TRUE)
        {
            ::ShowWindow(m_hWnd,SW_SHOW);
            SetForegroundWindow(m_hWnd);

        }
        
    else
        {
            ::ShowWindow(m_hWnd,SW_HIDE);
        }
        


        
    return TRUE;
    }



    //----------------------------------------------------------------------
    //Description:
    //    Create the window
    //
    //----------------------------------------------------------------------
    BOOL CSimpleWnd::Create(HINSTANCE hInst,HWND hWndParent)
    {
        m_hInst 
    = hInst;
        m_hWndParent 
    = hWndParent;

        RegisterWnd(m_hInst,m_hWndParent);

        m_hWnd 
    = CreateWindowEx(0,
                    WND_CLASS,
                    WND_NAME,
                    WS_VISIBLE,
                    
    0,
                    
    0,
                    
    800,
                    
    480,
                    m_hWndParent, 
                    NULL, 
                    m_hInst, 
                    
    0);
        
        
    if (IsWindow(m_hWnd) == FALSE)
        {
            
    return FALSE;
        }

        
    // If the window is created successfully, store this object so the 
        
    //static wrapper can pass calls to the real WndProc.
        SetWindowLong(m_hWnd, GWL_USERDATA, (DWORD)this);

        
    return TRUE;
    }

        来看看调用类实例对象的代码:
        CSimpleWnd sWnd1,sWnd2;
        sWnd1.Create(hInstance,NULL);
        sWnd1.ShowWindow(TRUE);

        sWnd2.Create(hInstance,NULL);
        sWnd2.ShowWindow(TRUE);

        OK,就是这么简单创建了两个类窗口实例.虽然两个窗口名相同,但要更改也是一件很简单的事情,不是么?
       
       
        最后我们来看看在<三论在C++类中实现Windows窗口的创建>(http://blog.csdn.net/norains/archive/2007/01/16/1485063.aspx)一文中窗口的调用方法:
            //声明一个对象指针:
            CDrawWnd *pDrawWnd;
            
            
    //获取一个对象实例:
            pDrawWnd = CDrawWnd::GetInstance();
        
            
    //初始化窗口:
            if(pDrawWnd->Initialize(hInstance) == FALSE)
            {
                
    return 0x05;
            }

            
    //如果窗口初始化成功,我们就可以让它显示了
            if(pDrawWnd->ShowWindow(TRUE) == FALSE)
            {
                
    return 0x10;
            }

        相比之下,是不是本文的窗口调用方式更为简单明了?不用调用GetInstance()获取对象实例,然后再调用Initialize()进行初始化,而仅仅是通过Create()即可完成以上两步的功能.
       
        那么在<三论>中所提到的方式是否就无用武之地了呢?也不尽然.如果在程序代码中,在不同的类都需要调用相同的窗口代码实现特定的功能,并且要保存上一次窗口关闭时的参量,那么采用<三论>中的方法则可以免去频繁地在不同类中传递全局变量的痛苦,同时也使得同步变得更为简便.

    发表于 @ 2007年10月23日 23:34:00|评论(loading...)|编辑

    新一篇: COM宏小结 | 旧一篇: WinCE同步和硬盘模式的切换

    评论:没有评论。

    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © norains