ڼС
梦回起点
做你害怕做的事,你会发现:不过如此
本站基于WordPress—主题by 设计窝
冀ICP备15003737号
梦回起点
Copyright © 2015-2024 All rights reserved.

定义一个自己的窗口类

定义自己的窗口类,其实主要的障碍就是消息函数怎么获得窗口所属的对象。

如果不Hook窗口消息处理函数,那么我能想到的有两种方法:

1.是把每个对象指针存起来,用传到消息处理函数的窗口句柄去索引相应的对象;

2.找个和窗口相关的地儿,把对应的窗口类对象的指针放进去。

想来想去,同时参考了网上的一些代码,决定采用第二种方式。具体的代码如下:

 

#pragma once
#ifndef CREATEALPHAWINDOWABSTRACT_H
#define CREATEALPHAWINDOWABSTRACT_H

#include 
#include 

class CreateAlphaWindowAbstract
{
public:
	CreateAlphaWindowAbstract(HINSTANCE hInstance = NULL);
	virtual ~CreateAlphaWindowAbstract();

	HWND GetHWND();

	//动作:
	HWND Create(
		_In_opt_ LPCTSTR   lpWindowName = _T("AD"),
		_In_     int       x = 0,
		_In_     int       y = 0,
		_In_     int       nWidth = 0,
		_In_     int       nHeight = 0,	
		_In_     DWORD     dwStyle = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP/*无边框风格*/,
		_In_     DWORD     dwExStyle = WS_EX_LAYERED | WS_EX_TOOLWINDOW,
		_In_opt_ HWND      hWndParent = NULL,
		_In_opt_ HMENU     hMenu = NULL);
	BOOL Show(int nCmdShow = SW_SHOWNOACTIVATE);
	BOOL Update();
	VOID Exec();

protected:
	//消息处理函数,返回0表示没有被处理
	virtual BOOL HandleMessage(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam) = 0;
	BOOL SetWndClass(	int cbClsExtra = 0, 
				int cbWndExtra = 0,
				HICON hIcon = NULL,
				HCURSOR hCursor = NULL,
				HBRUSH hbrBackground = NULL,
				LPCWSTR lpszMenuName = NULL,
				HICON hIconSm = NULL);

private:
	static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
	static volatile LONG s_bReg;
	static volatile LONG s_InterLockReg;
	static CString s_strClassName;
	static WNDCLASSEX s_wndClass;

private:
	HWND m_hWnd;
	HINSTANCE m_hInstance;

};

#endif

下面是具体的实现:

#include "stdafx.h"

#include "InterLock.h"
#include "CreateAlphaWindowAbstract.h"

//初始化静态变量
volatile LONG CreateAlphaWindowAbstract::s_bReg = FALSE;
volatile LONG CreateAlphaWindowAbstract::s_InterLockReg = FALSE;
CString CreateAlphaWindowAbstract::s_strClassName = "";
WNDCLASSEX CreateAlphaWindowAbstract::s_wndClass = {};

CreateAlphaWindowAbstract::CreateAlphaWindowAbstract(HINSTANCE hInstance):m_hWnd(NULL), m_hInstance(hInstance)
{
	InterLock Lock(s_InterLockReg);
	//如果没有注册窗口类,那么注册窗口类
	if(!s_bReg){
		s_strClassName = _T("ThisIsAdWindow");
		s_wndClass.cbSize = sizeof(WNDCLASSEX);
		s_wndClass.cbClsExtra = 0;
		s_wndClass.cbWndExtra = 0;
		s_wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
		s_wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
		s_wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
		s_wndClass.hIconSm = NULL;
		s_wndClass.hInstance = NULL;
		s_wndClass.lpszClassName = s_strClassName;
		s_wndClass.lpszMenuName = NULL;
		s_wndClass.lpfnWndProc = CreateAlphaWindowAbstract::WndProc;
		s_wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_IME | CS_DBLCLKS;
		while(0 == RegisterClassEx(&s_wndClass)){//如果注册失败,那么更换窗口类名,继续尝试
			CString strTmp;
			strTmp.Format(L"%d", GetTickCount());
			s_strClassName = s_strClassName.Left(6)+strTmp;
			s_wndClass.lpszClassName = s_strClassName;
		}
		s_bReg = TRUE;
	}
}

CreateAlphaWindowAbstract::~CreateAlphaWindowAbstract()
{

}

HWND CreateAlphaWindowAbstract::GetHWND()
{
	return m_hWnd;
}

HWND CreateAlphaWindowAbstract::Create(
					_In_opt_ LPCTSTR   lpWindowName,
					_In_     int       x,
					_In_     int       y,
					_In_     int       nWidth,
					_In_     int       nHeight,
					_In_     DWORD     dwStyle,
					_In_     DWORD     dwExStyle,
					_In_opt_ HWND      hWndParent,
					_In_opt_ HMENU     hMenu)
{
	if(s_strClassName.GetLength() > 0 && NULL == m_hWnd){
		InterLock Lock(s_InterLockReg);
		HWND hWnd = CreateWindowEx(dwExStyle, s_strClassName.GetBuffer(), lpWindowName, dwStyle
			, x, y, nWidth, nHeight, hWndParent ,hMenu, m_hInstance, (LPVOID)this);
		INT n = GetLastError();
		
		return hWnd;
	}else if(NULL != m_hWnd){
		return m_hWnd;
	}
	return 0;
}
BOOL CreateAlphaWindowAbstract::Show(int nCmdShow)
{
	
	return NULL == m_hWnd ? FALSE : ::ShowWindow(m_hWnd, nCmdShow/*SW_SHOWNOACTIVATE*/);
}
BOOL CreateAlphaWindowAbstract::Update()
{
	return NULL == m_hWnd ? FALSE : ::UpdateWindow(m_hWnd);
}

VOID CreateAlphaWindowAbstract::Exec()
{
	MSG msg;
	while(GetMessage(&msg, m_hWnd, NULL, NULL)){
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
}

BOOL CreateAlphaWindowAbstract::HandleMessage(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	BOOL bRes = FALSE;
	
	return bRes;
}

BOOL CreateAlphaWindowAbstract::SetWndClass( int cbClsExtra, 
					int cbWndExtra,
					HICON hIcon,
					HCURSOR hCursor,
					HBRUSH hbrBackground,
					LPCWSTR lpszMenuName,
					HICON hIconSm)
{
	return FALSE;
}

//消息处理函数
LRESULT CALLBACK CreateAlphaWindowAbstract::WndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	CreateAlphaWindowAbstract* pThis = NULL;
	BOOL bRes = FALSE;

	//创建窗口的时候将对象和窗口关联起来
	if(WM_NCCREATE == nMsg){
		pThis = (CreateAlphaWindowAbstract*)((LPCREATESTRUCT(lParam))->lpCreateParams);
		if(!IsBadReadPtr((VOID*)pThis, sizeof(CreateAlphaWindowAbstract)) && NULL == pThis->m_hWnd){
			pThis->m_hWnd = hWnd;
			::SetProp(hWnd, s_strClassName, (HANDLE)pThis);
		}
	}

	//获取窗口对应的对象
	pThis = (CreateAlphaWindowAbstract*)::GetProp(hWnd, s_strClassName);
	
	//调用对应的消息处理函数
	if(!IsBadReadPtr((VOID*)pThis, sizeof(CreateAlphaWindowAbstract)) && pThis->m_hWnd == hWnd){
		switch(nMsg){
			case WM_DESTROY:
				pThis->m_hWnd = NULL;
				//这里故意没有写break,DESTROY删除hWnd句柄,然后继续调用消息处理函数
			default:
				//调用对应的消息处理函数
				bRes = (BOOL)pThis->HandleMessage(hWnd, nMsg, wParam, lParam);
				break;
		}
	}

	pThis = NULL;

	return bRes ? 0 : ::DefWindowProc(hWnd, nMsg, wParam, lParam);
}
2018-01-19
                         
  1. 哦引力

    也是厉害,我看多了,都头晕

发表回复