封装windows的回调函数

封装windows的回调函数

windows的回调函数(CALLBACK)拥有严格的参数表。如果直接封装成类的成员函数,在调用的时候会带有this指针,与回调函数的参数表不一致,导致连编译都过不了。
有两种方式可以将这个this指针去掉:

1、将回调函数声明为静态的成员函数。
2、将回调函数声明为友元friend。

第一种:将回调函数声明为静态的成员函数。
静态的成员函数只能用静态的成员变量,如果将一个类所有成员都声明为静态的,那你为什么要封装? 对象都不用创建。几乎失去了类的大部分功能。
如何用静态成员函数使用非静态的成员?
可以参考这两篇文章
https://blog.csdn.net/jia_xiaoxin/article/details/2887352

https://blog.csdn.net/Arcsinsin/article/details/9771251

第二种:将回调函数声明为友元friend。
原理与上面一样,我就不多说了
代码附上:
Frame.h

#include <Windows.h>
class Frame{
private:
    HWND hwnd;
    WNDCLASSEX wndclass;
    MSG msg;
    HINSTANCE hInstance;
    int x, y;
    int width, height;
public:
    Frame(HINSTANCE hInstance, WNDPROC WndProc = NULL);
    ~Frame();
    void start();//在这里面手动调用一次回调函数
    void setSize(int, int);//设置窗口大小
    void setPos(int, int);//设置窗口的位置
    void setVisible(bool);//设置窗口显示与隐藏 同时创建窗口,消息循环
public:
    friend LRESULT CALLBACK lpfnWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
};

Frame.cpp

#include "Frame.h"
Frame::Frame(HINSTANCE hInstance, WNDPROC WndProc){	  
    x = 0;
    y = 0;
    width = 0;
    height = 0;
    hwnd = NULL;
    this->hInstance = hInstance;
    if (WndProc == NULL){
    	wndclass.lpfnWndProc = lpfnWndProc;
    }
    else{
  	wndclass.lpfnWndProc = WndProc;
    }
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.cbSize = sizeof(WNDCLASSEX);
    wndclass.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
    wndclass.hCursor = LoadCursor(hInstance, IDC_ARROW);
    wndclass.hInstance = hInstance;
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszClassName = L"mywin";
    wndclass.lpszMenuName = NULL;
    wndclass.hIconSm = LoadIcon(hInstance, IDI_APPLICATION);
    if (!RegisterClassEx(&wndclass)){
    	MessageBox(NULL, L"窗口注册失败!", L"提示", MB_OK);
  	exit(-1);
    }
 }
Frame::~Frame(){
}

void Frame::setSize(int width, int height){
    this->width = width;
    this->height = height;
}

void Frame::setPos(int x, int y){
    this->x = x;
    this->y = y;
}
/*
* 负责创建窗口,将窗口显示或者隐藏
*/
void Frame::setVisible(bool b){
    if (hwnd == NULL){
    	this->start();//只是在创建窗口时调用
    	hwnd = CreateWindowEx(
   	NULL, ClassName, L"hello world",
   	WS_OVERLAPPEDWINDOW,
   	x, y, width, height,
   	NULL, NULL, hInstance, NULL);
   	if (hwnd == NULL){
   		MessageBox(NULL, L"窗口创建失败!", L"提示", MB_OK);
   		exit(-1);
    	}
    	
  	ShowWindow(hwnd, SW_SHOWDEFAULT);
  	UpdateWindow(hwnd);
  	while (GetMessage(&msg, NULL, 0, 0)){
   		TranslateMessage(&msg);
   		DispatchMessage(&msg);
  	}
    }
    if (b){
 	ShowWindow(hwnd, SW_NORMAL);
    }
    else if(!b){
  	ShowWindow(hwnd, SW_HIDE);
    }
}

void Frame::start(){
    lpfnWndProc(NULL, NULL, NULL, (LPARAM)this);
}

LRESULT CALLBACK lpfnWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){
//将对象指针设置为静态,当操作系统调用回调函数时不会改变对象
    static Frame *frame;
    if (hwnd == NULL){
    	//第一次调用的时候是手动调用,传递的参数为NULL
  	frame = (Frame*)lParam;
    }
    HDC hdc;
    PAINTSTRUCT ps;
    switch (msg){
    	case WM_CREATE:
 		break;
    	case WM_PAINT:
  		hdc = BeginPaint(hwnd, &ps);
  		//这里就可以直接用对象的私有变量了
  		Rectangle(hdc, 0, 0, frame->width, frame->height);
  		EndPaint(hwnd, &ps);
  		break;
    	case WM_DESTROY:
  		PostQuitMessage(0);
    		break;
    }
 return DefWindowProcA(hwnd, msg, wParam, lParam);
}

test.cpp

#include <Windows.h>
#include "Frame.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, PCHAR iCmdLine, int iCmdShow){
   Frame frame(hInstance);
   frame.setPos(200, 150);
   frame.setSize(800, 400);
   frame.setVisible(TRUE);
   return 0;
}

编译器:VS2013
环境:windows10
因为学过Java,所以自己设计的时候函数的名字或者代码风格有点有点Java的倾向。然后就是正在学习windows程序设计,所以有什么不对的,欢迎指出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值