`
dato0123
  • 浏览: 924492 次
文章分类
社区版块
存档分类
最新评论

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

 
阅读更多
//========================================================================
//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:interfacefortheCSimpleWndclass.
//
//////////////////////////////////////////////////////////////////////
#ifndefSIMPLEWND_H
#defineSIMPLEWND_H

classCSimpleWnd
{
public:
BOOLCreate(HINSTANCEhInst,HWNDhWndParent);
BOOLShowWindow(BOOLbShow);
CSimpleWnd();
virtual~CSimpleWnd();

protected:
BOOLRegisterWnd(HINSTANCEhInst,HWNDhWndParent);
LRESULTWndProc(HWNDhWnd,UINTwMsg,WPARAMwParam,LPARAMlParam);
staticLRESULTStaticWndProc(HWNDhWnd,UINTwMsg,WPARAMwParam,LPARAMlParam);

HWNDm_hWnd;
HWNDm_hWndParent;
HINSTANCEm_hInst;
};

#endif//#ifndefSIMPLEWND_H




//////////////////////////////////////////////////////////////////////
//SimpleWnd.cpp:implementationoftheCSimpleWndclass.
//
//////////////////////////////////////////////////////////////////////

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

//=====================================================================
//Macrodefine
#defineWND_NAMETEXT("SimpleWnd_name")
#defineWND_CLASSTEXT("SimpleWnd_cls")
//=====================================================================
//////////////////////////////////////////////////////////////////////
//Construction/Destruction
//////////////////////////////////////////////////////////////////////

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

}

CSimpleWnd::
~CSimpleWnd()
{

}

//----------------------------------------------------------------------
//Description:
//Initialize
//----------------------------------------------------------------------
BOOLCSimpleWnd::RegisterWnd(HINSTANCEhInst,HWNDhWndParent)
{




staticBOOLs_bRegistered=FALSE;
WNDCLASSwc;
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;
}
}

returns_bRegistered;

/*
WNDCLASSwc;
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)
{
returnFALSE;
}


returnTRUE;
*/
}

//----------------------------------------------------------------------
//Description:
//StaticWndProcwrapperandactualWndProc
//
//----------------------------------------------------------------------
LRESULTCSimpleWnd::StaticWndProc(HWNDhWnd,UINTmsg,WPARAMwParam,LPARAMlParam)
{
CSimpleWnd
*pObject=(CSimpleWnd*)GetWindowLong(hWnd,GWL_USERDATA);

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


//----------------------------------------------------------------------
//Description:
//ActualWndProc
//
//----------------------------------------------------------------------
LRESULTCSimpleWnd::WndProc(HWNDhWnd,UINTwMsg,WPARAMwParam,LPARAMlParam)
{
returnDefWindowProc(hWnd,wMsg,wParam,lParam);
}


//----------------------------------------------------------------------
//Description:
//Showthewindow
//
//----------------------------------------------------------------------
BOOLCSimpleWnd::ShowWindow(BOOLbShow)
{
if(m_hWnd==NULL)
{
returnFALSE;
}

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

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



returnTRUE;
}



//----------------------------------------------------------------------
//Description:
//Createthewindow
//
//----------------------------------------------------------------------
BOOLCSimpleWnd::Create(HINSTANCEhInst,HWNDhWndParent)
{
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)
{
returnFALSE;
}

//Ifthewindowiscreatedsuccessfully,storethisobjectsothe
//staticwrappercanpasscallstotherealWndProc.
SetWindowLong(m_hWnd,GWL_USERDATA,(DWORD)this);

returnTRUE;
}

来看看调用类实例对象的代码:
CSimpleWndsWnd1,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)
{
return0x05;
}

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

相比之下,是不是本文的窗口调用方式更为简单明了?不用调用GetInstance()获取对象实例,然后再调用Initialize()进行初始化,而仅仅是通过Create()即可完成以上两步的功能.

那么在<三论>中所提到的方式是否就无用武之地了呢?也不尽然.如果在程序代码中,在不同的类都需要调用相同的窗口代码实现特定的功能,并且要保存上一次窗口关闭时的参量,那么采用<三论>中的方法则可以免去频繁地在不同类中传递全局变量的痛苦,同时也使得同步变得更为简便.
分享到:
评论

相关推荐

    windows透明的无边框窗口

    用c++创建无边框窗口, 同时可以通过鼠标拖动改变窗口大小,可以设置窗口的透明度

    win32创建子窗口 同时实现子窗口与父窗口传递信息

    win32创建子窗口 同时实现子窗口与父窗口传递信息 同时有win32显示int类型的知识点

    C++创建简单窗口例程(Win32 API应用)

    C++创建简单窗口例程(Win32 API应用)-非MFC

    Windows创建窗体C++实现

    使用Windows API 创建窗体,简单的实现这一过程,主要是理解创建的流程。

    SDK窗口编程的C++封装实现

    基础的windows窗口类使用C++封装后的源码,点此下载,这是我的第一版本,还有很多功能没有实现。 代码实现效果如: TWnd* wnd; wnd-&gt;Create(IDD_DIALOG1,NULL,(LPARAM)wnd); //创建一个非模态窗口; TWnd* dlg; ...

    C++ 创建窗口

    C++ 创建窗口 Windows ************************************************************************ 登记自己的窗口类 ************************************************************************/ bool ...

    使用Windows C++ API创建普通窗口实例

    一个使用Windows C++ API创建普通窗口的实例

    VC++在线程中创建并显示窗口

    VC++在线程中创建并显示窗口,从线程函数开始全用windows API完成,让你不再受封装的困惑。每点一个按钮就创建一个线程,多个线程可显示多个窗口。好的话别忘了给个评论。

    win32窗口封装类_c++

    用C++实现自己的窗口封装类,有这个东西,不用每次都在写那些重复的代码了,可以文件使用这个类创建窗口,映射窗口消息。

    windows窗口绘制三角形

    创建windows窗口并结合opengl绘制三角形

    C++ 中 Windows 编程概述

    可以使用 C++ 创建各种类别的 Windows 应用程序。 每种应用程序都有自己的编程模型 和一组特定于 Windows 的库,但 C++ 标准库和第三方 C++ 库可用于任何应用程序。 本部分讨论如何使用 Visual Studio 和 MFC/ATL ...

    VS2008下C++开发Windows服务程序

    使用VS2008开发环境C++编写的Windows服务程序,安装、启动、暂停、恢复、停止、重新启动服务

    C++&CLR(VS2015)编写 Windows 窗体应用程序

    C++&CLR(VS2015)编写 Windows 窗体应用程序

    C++,win编程,获取当前选中win窗口输入数据

    C++,win编程,获取当前选中win窗口输入数据; 可做学习参考,完成初步获取,待后续更新 。

    如何创建自定义窗口类并响应自定义事件

    创建自定义窗口并支持响应WINDOWS系统消息,调用CreateWindow函数的时候,将类指针传入,利用SetWindowLong和GetWindowLong 可以将消息分发给类实例, 形成可响应WINDOWS消息的窗口类. 运行系统windows xp, 编译环境vc6.

    DLL动态加载 生成窗口的方法

    但是Windows程序经常有很多窗口,如何把窗口封装到dll中,并且能否动态加载。就不是MFC架构能解决了。 因为要用到扩展MFC导出dll类型,来导出窗口类,但是这样的话,必须用静态加载lib文件方式来实现。降低了灵活...

    VS2019创建C++窗体应用程序[归纳].pdf

    在本文中,我们将详细介绍如何使用 VS2019 创建 C++ 窗体应用程序,从创建新项目到设计用户界面,最后实现按钮的点击事件处理。 一、创建新项目 首先,我们需要启动 VS2019 并创建一个新的项目。在创建新项目...

    创建win窗口

    简单的创建windows窗口,左击获取消息事件弹出窗口,汉字窗口显示

    易语言创建Windows任务栏窗口缩略图按钮教程源码

     不过MSDN中提供了C++的调用方法,在C++中这三个API被封装在ITaskBarList3类中,ITaskBarList3类定义在“Shobjidl.h”头文件。所以我想想到个方法,利用微软提供的C++代码编写一个DLL库来实现这三个方法,让易语言...

    Windows编程新手乐园 CHM

    在开始之前,需要注意的是本教程中所有的例子都是在 Visual C++ 6.0 中调试通过,因此最好不要使用 Visual C++ 5.0 以下的版本。 第一篇:Windows 编程基础 第一章 第一天课程——从实践中学习 第二章 第二天...

Global site tag (gtag.js) - Google Analytics