Windows API一日一练 21 SetWindowLongPtr和GetWindowLongPtr函数
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Windows API一日一练 21 SetWindowLongPtr和GetWindowLongPtr函数,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含7294字,纯文字阅读大概需要11分钟。
内容图文
在软件开发里,大家一直对着这个问题是执着的,那是“复用”。总想自己写出来的代码,可以适应性很强,到那里都可以落地生根。因此,面向对象的语言就层出不穷,每个都坚称可以最大地复用代码。在面向对象里,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, WPARAM wParam, 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, 0, CW_USEDEFAULT, 0, NULL, 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, message, wParam, 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,10,strShow.c_str(),(int)strShow.length()); #051? #052?????????????? // #053?????????????? EndPaint(hWnd, &ps); #054???????? } #055???????? break; #056??case WM_DESTROY: #057???????? //设置窗口类指针为空。 #058???????? SetWindowLongPtr(hWnd, GWL_USERDATA,NULL); #059? #060???????? PostQuitMessage(0); #061???????? break; #062??default: #063???????? return DefWindowProc(hWnd, message, wParam, 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 int nIndex, ??? __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
内容总结
以上是互联网集市为您收集整理的Windows API一日一练 21 SetWindowLongPtr和GetWindowLongPtr函数全部内容,希望文章能够帮你解决Windows API一日一练 21 SetWindowLongPtr和GetWindowLongPtr函数所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。