定义自己的窗口类,其实主要的障碍就是消息函数怎么获得窗口所属的对象。
如果不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);
}

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