summaryrefslogtreecommitdiff
path: root/src/mir_core/subclass.cpp
blob: a526aeb9bfe27e92e498808a350e8667c877309c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/*
Copyright (C) 2012-13 Miranda NG team (http://miranda-ng.org)

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation version 2
of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "commonheaders.h"

struct MSubclassData
{
	HWND     m_hWnd;

	int      m_iHooks;
	WNDPROC *m_hooks;
	WNDPROC  m_origWndProc;

	~MSubclassData()
	{
		free(m_hooks);
	}
};

static LIST<MSubclassData> arSubclass(10, LIST<MSubclassData>::FTSortFunc(HandleKeySortT));

static LRESULT CALLBACK MSubclassWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	MSubclassData *p = arSubclass.find((MSubclassData*)&hwnd);
	if (p != NULL) {
		for (int i=0; i < p->m_iHooks; i++) {
			LRESULT res = p->m_hooks[i](hwnd, uMsg, wParam, lParam);
			if (res != 0)
				return res;
		}

		if (uMsg == WM_DESTROY) {
			SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)p->m_origWndProc);
			arSubclass.remove(p);
			delete p;			
		}
	}		

	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

MIR_CORE_DLL(void) mir_subclassWindow(HWND hWnd, WNDPROC wndProc)
{
	MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd);
	if (p == NULL) {
		p = new MSubclassData;
		p->m_hWnd = hWnd;
		p->m_origWndProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)MSubclassWndProc);
		p->m_iHooks = 0;
		p->m_hooks = (WNDPROC*)malloc( sizeof(WNDPROC));
		arSubclass.insert(p);
	}
	else p->m_hooks = (WNDPROC*)realloc(p->m_hooks, (p->m_iHooks+1)*sizeof(WNDPROC));

	p->m_hooks[p->m_iHooks++] = wndProc;		
}

MIR_CORE_DLL(LRESULT) mir_callNextSubclass(HWND hWnd, WNDPROC wndProc, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	MSubclassData *p = arSubclass.find((MSubclassData*)&hWnd);
	if (p)
		for (int i=0; i < p->m_iHooks-1; i++)
			if (p->m_hooks[i] == wndProc)
				return p->m_hooks[i+1](hWnd, uMsg, wParam, lParam);

	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

MIR_CORE_DLL(void) KillModuleSubclassing(HMODULE hInst)
{
	for (int i=0; i < arSubclass.getCount(); i++) {
		MSubclassData *p = arSubclass[i];
		for (int j=0; j < p->m_iHooks; ) {
			if ( GetInstByAddress(p->m_hooks[j]) == hInst) {
				for (int k=j+1; k < p->m_iHooks; k++)
					p->m_hooks[k-1] = p->m_hooks[k];
				p->m_iHooks--;
			}
			else j++;
		}
	}
}