-
Notifications
You must be signed in to change notification settings - Fork 36
/
Copy pathsubclass.h
106 lines (88 loc) · 2.8 KB
/
subclass.h
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
97
98
99
100
101
102
103
104
105
106
/**
* Part of WinLamb - Win32 API Lambda Library
* https://github.com/rodrigocfd/winlamb
* Copyright 2017-present Rodrigo Cesar de Freitas Dias
* This library is released under the MIT License
*/
#pragma once
#include "internals/base_msg_pubm.h"
#include "internals/base_thread_pubm.h"
#include "wnd.h"
#include <CommCtrl.h>
namespace wl {
// Manages window subclassing for a window.
class subclass final :
public wnd,
public _wli::base_msg_pubm<LRESULT>,
public _wli::base_thread_pubm<LRESULT, 0>
{
private:
HWND _hWnd = nullptr;
UINT _subclassId = -1;
_wli::base_msg<LRESULT> _baseMsg{_hWnd};
_wli::base_thread<LRESULT, 0> _baseThread{_baseMsg};
public:
~subclass() {
this->remove_subclass();
}
subclass() :
wnd(_hWnd), base_msg_pubm(_baseMsg), base_thread_pubm(_baseThread) { }
subclass(subclass&&) = default;
subclass& operator=(subclass&&) = default; // movable only
void remove_subclass() noexcept {
if (this->hwnd()) {
RemoveWindowSubclass(this->hwnd(), _subclass_proc, this->_subclassId);
this->_hWnd = nullptr; // clear HWND
}
}
void install_subclass(HWND hCtrl) {
if (this->hwnd()) {
throw std::logic_error("Trying to install subclass twice.");
} else if (!hCtrl) {
throw std::invalid_argument("Trying to install subclass on an empty control.");
}
this->_hWnd = hCtrl; // store HWND
if (hCtrl) {
this->_subclassId = _next_id();
SetWindowSubclass(hCtrl, _subclass_proc, this->_subclassId,
reinterpret_cast<DWORD_PTR>(this));
}
}
void install_subclass(HWND hParent, int ctrlId) {
this->install_subclass(GetDlgItem(hParent, ctrlId));
}
void install_subclass(const wnd& ctrl) {
this->install_subclass(ctrl.hwnd());
}
void install_subclass(const wnd& parent, int ctrlId) {
this->install_subclass(GetDlgItem(parent.hwnd(), ctrlId));
}
private:
static LRESULT CALLBACK _subclass_proc(HWND hWnd, UINT msg,
WPARAM wp, LPARAM lp, UINT_PTR idSubclass, DWORD_PTR refData) noexcept
{
subclass* pSelf = reinterpret_cast<subclass*>(refData);
if (pSelf) {
if (pSelf->hwnd()) {
std::pair<bool, LRESULT> procRet =
pSelf->_baseMsg.process_msg(msg, wp, lp); // catches all message exceptions internally
if (msg == WM_NCDESTROY) {
pSelf->remove_subclass();
}
if (procRet.first) {
return procRet.second; // message was processed
}
} else if (msg == WM_NCDESTROY) {
pSelf->remove_subclass();
}
} else if (msg == WM_NCDESTROY) {
RemoveWindowSubclass(hWnd, _subclass_proc, idSubclass);
}
return DefSubclassProc(hWnd, msg, wp, lp); // message was not processed
}
static UINT _next_id() noexcept {
static UINT firstId = 0;
return firstId++;
}
};
}//namespace wl