Windows API一日一练 21 SetWindowLongPtr和GetWindowLongPtr函
发布时间:2020-12-14 02:34:32 所属栏目:Windows 来源:网络整理
导读:在软件开发里,大家一直对着这个问题是执着的,那是“复用”。总想自己写出来的代码,可以适应性很强,到那里都可以落地生根。因此,面向对象的语言就层出不穷,每个都坚称可以最大地复用代码。在面向对象里, C ++是非常强大的。下面就来用 C ++把上面
在软件开发里,大家一直对着这个问题是执着的,那是“复用”。总想自己写出来的代码,可以适应性很强,到那里都可以落地生根。因此,面向对象的语言就层出不穷,每个都坚称可以最大地复用代码。在面向对象里,
C
++是非常强大的。下面就来用
C
++把上面介绍的程序封装起来,这样可以复用,或者说条理更加清晰。
#001?
#002?int APIENTRY _tWinMain(HINSTANCE hInstance,
#003?????????????????????? HINSTANCE hPrevInstance,
#004?????????????????????? LPTSTR??? lpCmdLine,
#005?????????????????????? int?????? nCmdShow)
#006?{
#007??UNREFERENCED_PARAMETER(hPrevInstance);
#008??UNREFERENCED_PARAMETER(lpCmdLine);
#009?
#010??CCaiWin caiWin;
#011?
#012??caiWin.MyRegisterClass(hInstance);
#013??if (!caiWin.InitInstance(hInstance,nCmdShow))
#014??{
#015???????? return 0;
#016??}
#017?
#018??return caiWin.RunMessage();???
#019?}
?
这段代码跟前面介绍的调用,就是不一样了。
第
10
行创建了一个
CCaiWin
的对象
caiWin
。
第
12
行调用对象
CCaiWin
里的注册函数
MyRegisterClass
来注册一个窗口。
第
13
行就是初始化一个窗口的创建。
第
18
行就是调用对象
caiWin
的消息处理函数
RunMessage
。
?
这样就制定了一个基本应用的框架,可以任意修改对象里的内容,都不会影响这个函数里的调用,也就是说,只要不改那几个函数就可以永远不用修改
WinMain
函数里的内容了。
?
接着下来,再来看看类
CCaiWin
是怎么样编写的。它的类定义如下:
#001?#include <string>
#002?
#003?//
#004?//
封装一个窗口类。
#005?//
蔡军生
?2007/07/27
#006?//
#007?class CCaiWin
#008?{
#009?public:
#010??CCaiWin(void);
#011??virtual ~CCaiWin(void);
#012?
#013??ATOM MyRegisterClass(HINSTANCE hInstance);
#014??bool InitInstance(HINSTANCE hInstance,int nCmdShow);??
#015??int RunMessage(void);
#016??HINSTANCE GetAppInstance(void)
#017 ??{
#018???????? return m_hInstance;
#019??}
#020?protected:
#021??static LRESULT CALLBACK WndProc(HWND hWnd,
#022???????? UINT message,WPARAM wParam,LPARAM lParam);
#023??static INT_PTR CALLBACK About(HWND hDlg,
#024???????? UINT message,LPARAM lParam);
#025?protected:
#026??HINSTANCE m_hInstance;
#027??HWND m_hWnd;
#028?
#029??std::wstring m_strWindowClass;
#030??std::wstring m_strTitle;
#031?};
第
7
行定义类
CCaiWin
。
第
13
行是声明
MyRegisterClass
注册函数。
第
14
行是声明
InitInstance
初始化窗口函数。
第
15
行是声明
RunMessage
消息处理函数。
第
16
行是定义
GetAppInstance
函数获取应用程序句柄。
第
21
行是声明窗口的消息处理函数。它是静态成员函数,所以它有全局的地址,因此它是没有
this
指针的,不能直接地访问这个类里的成员变量。需要使用其它方法给它传递。
第
23
行是关于对话框的消息处理函数。
第
26
行是保存应用程序句柄。
第
27
行是保存主窗口的句柄。
第
29
行是保存注册窗口名称。
第
30
行是保存窗口显示的标题。
?
下面再来仔细地查看类的实现文件。
#001?//
#002?//??
函数
: InitInstance(HINSTANCE,int)
#003?//
#004?//??
目的
:
保存程序实例句柄,并创建窗口显示。
#005?//
#006?//??
蔡军生
?2007/07/27 QQ:9073204
#007?//
#008?bool CCaiWin::InitInstance(HINSTANCE hInstance,int nCmdShow)
#009?{
#010??//
#011 ??m_hInstance = hInstance;
#012?
#013 ??m_hWnd = CreateWindow(m_strWindowClass.c_str(),m_strTitle.c_str(),
#014???????? WS_OVERLAPPEDWINDOW,
#015???????? CW_USEDEFAULT,CW_USEDEFAULT,NULL,hInstance,NULL);
#016?
#017??if (!m_hWnd)
#018??{
#019???????? return false;
#020??}
#021?
#022??//
保存类的指针到窗口
GWL_USERDATA
字段,
#023??//
以便消息函数里可以获取类指针。
#024??SetWindowLongPtr(m_hWnd,GWL_USERDATA,(LONG)(LONG_PTR)this);
#025?
#026??ShowWindow(m_hWnd,nCmdShow);
#027??UpdateWindow(m_hWnd);
#028?
#029??return true;
#030?}
这里创建窗口,跟以前创建窗口,只有一个地方不一样,那就是在第
24
行里调用
SetWindowLongPtr
函数保存对象指针到窗口用户自定义数据里,这样做就是让后面的静态成员函数
WndProc
可以访问类成员。如下:
#001?//
#002?//?
函数
: WndProc(HWND,UINT,WPARAM,LPARAM)
#003?//
#004?//?
目的
:?
处理主窗口的消息
.
#005?//
#006?//?
蔡军生
?2007/07/27?? QQ:9073204
#007?//
#008?LRESULT CALLBACK CCaiWin::WndProc(HWND hWnd,UINT message,
#009?????????????????????????????????????????? ??
#010?WPARAM wParam,LPARAM lParam)
#011?{
#012??//
获取窗口对应的类指针。
#013??LONG_PTR plptrWin = GetWindowLongPtr(hWnd,GWLP_USERDATA);
#014??if (plptrWin == NULL)
#015??{
#016??????? return DefWindowProc(hWnd,message,wParam,lParam);
#017??}
#018?
#019??//
#020??CCaiWin* pWin = reinterpret_cast<CCaiWin*>(plptrWin);
#021?
#022??int wmId,wmEvent;
#023??PAINTSTRUCT ps;
#024??HDC hdc;
#025?
#026??switch (message)
#027??{
#028??case WM_COMMAND:
#029???????? wmId??? = LOWORD(wParam);
#030???????? wmEvent = HIWORD(wParam);
#031???????? //
菜单选项命令响应
:
#032???????? switch (wmId)
#033???????? {
#034???????? case IDM_ABOUT:
#035?????????????? DialogBox(pWin->GetAppInstance(),MAKEINTRESOURCE(IDD_ABOUTBOX),
#036??????????????????? hWnd,CCaiWin::About);
#037?????????????? break;
#038???????? case IDM_EXIT:
#039?????????????? DestroyWindow(hWnd);
#040?????????????? break;
#041???????? default:
#042?????????????? return DefWindowProc(hWnd,lParam);
#043???????? }
#044???????? break;
#045??case WM_PAINT:
#046???????? {
#047?????????????? hdc = BeginPaint(hWnd,&ps);
#048?????????????? //
#049?????????????? std::wstring strShow(_T("C++
窗口类的实现
,2007-07-27"));
#050?????????????? TextOut(hdc,10,strShow.c_str(),(int)strShow.length());
#051?
#052?????????????? //
#053?????????????? EndPaint(hWnd,&ps);
#054???????? }
#055???????? break;
#056??case WM_DESTROY:
#057???????? //
设置窗口类指针为空。
#058???????? SetWindowLongPtr(hWnd,NULL);
#059?
#060???????? PostQuitMessage(0);
#061???????? break;
#062??default:
#063???????? return DefWindowProc(hWnd,lParam);
#064??}
#065??return 0;
#066?}
上面第
13
行就是获取窗口里保存的类对象指针,然后再作类型转换为窗口
CCaiWin
的指针,这样就可以使用类的成员了,比如在第
35
行里的调用
pWin->GetAppInstance()
。
?
其实在封装静态成员函数这里,就有三种方法传递类指针,上面介绍这种是最简单的。一种是
MFC
里使用的,它是采用一个窗口和类指针映射数组来实现的。一种是
WTL
里使用叫做
THUNK
代码实现窗口与静态函数的关联。像上面这种方法,在游戏
Second Life
的源程序就使用它,如果是一般的应用程序,而不是大框架,使用这种简单的方法,就是最好的。
?
函数
GetWindowLongPtr
和
SetWindowLongPtr
声明如下:
WINUSERAPI
LONG
WINAPI
GetWindowLongA(
??? __in HWND hWnd,
??? __in int nIndex);
WINUSERAPI
LONG
WINAPI
GetWindowLongW(
??? __in HWND hWnd,
??? __in int nIndex);
#ifdef UNICODE
#define GetWindowLong?GetWindowLongW
#else
#define GetWindowLong?GetWindowLongA
#endif // !UNICODE
?
WINUSERAPI
LONG
WINAPI
SetWindowLongA(
??? __in HWND hWnd,
??? __in int nIndex,
??? __in LONG dwNewLong);
WINUSERAPI
LONG
WINAPI
SetWindowLongW(
??? __in HWND hWnd,
??? __in LONG dwNewLong);
?
#ifdef UNICODE
#define SetWindowLong?SetWindowLongW
#else
#define SetWindowLong?SetWindowLongA
#endif // !UNICODE
#define GetWindowLongPtrA?? GetWindowLongA
#define GetWindowLongPtrW?? GetWindowLongW
#ifdef UNICODE
#define GetWindowLongPtr?GetWindowLongPtrW
#else
#define GetWindowLongPtr?GetWindowLongPtrA
#endif // !UNICODE
?
#define SetWindowLongPtrA?? SetWindowLongA
#define SetWindowLongPtrW?? SetWindowLongW
#ifdef UNICODE
#define SetWindowLongPtr?SetWindowLongPtrW
#else
#define SetWindowLongPtr?SetWindowLongPtrA
#endif // !UNICODE
?
hWnd
是窗口句柄。
nIndex
是访问窗口对象数据的索引值。比如像
GWLP_USERDATA
、
GWLP_WNDPROC
。
dwNewLong
是设置的新值。?
再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
推荐文章
站长推荐
热点阅读