#include <map>
#include <functional>
#include <mutex>
#include <nana/gui.hpp>
#ifdef NANA_WINDOWS
#include <Windows.h>
#include <Winuser.h>
BOOL WINAPI AddClipboardFormatListener(
_In_ HWND hwnd
);
class subclass
{
struct msg_pro
{
};
public:
: native_(reinterpret_cast<HWND>(nana::API::
root(wd))),
old_proc_(nullptr)
{
}
~subclass()
{
clear();
}
void make_before(UINT msg,
std::function<
bool(UINT, WPARAM, LPARAM, LRESULT*)> fn)
{
_m_subclass(true);
}
void make_after(UINT msg,
std::function<
bool(UINT, WPARAM, LPARAM, LRESULT*)> fn)
{
_m_subclass(true);
}
void umake_before(UINT msg)
{
auto i = msg_table_.find(msg);
if(msg_table_.end() != i)
{
i->second.before = nullptr;
if(nullptr == i->second.after)
{
msg_table_.erase(msg);
if(msg_table_.empty())
_m_subclass(false);
}
}
}
void umake_after(UINT msg)
{
auto i = msg_table_.find(msg);
if(msg_table_.end() != i)
{
i->second.after = nullptr;
if(nullptr == i->second.before)
{
msg_table_.erase(msg);
if(msg_table_.empty())
_m_subclass(false);
}
}
}
void umake(UINT msg)
{
msg_table_.erase(msg);
if(msg_table_.empty())
_m_subclass(false);
}
void clear()
{
msg_table_.clear();
_m_subclass(false);
}
private:
void _m_subclass(bool enable)
{
if(enable)
{
if(native_ && (nullptr == old_proc_))
{
old_proc_ = (WNDPROC)::SetWindowLongPtr(native_, -4 , (LONG_PTR)_m_subclass_proc);
if(old_proc_)
table_[native_] = this;
}
}
else
{
if(old_proc_)
{
table_.erase(native_);
::SetWindowLongPtr(native_, -4 , (LONG_PTR)old_proc_);
old_proc_ = nullptr;
}
}
}
static bool _m_call_before(msg_pro& pro, UINT msg, WPARAM wp, LPARAM lp, LRESULT* res)
{
return (pro.before ? pro.before(msg, wp, lp, res) : true);
}
static bool _m_call_after(msg_pro& pro, UINT msg, WPARAM wp, LPARAM lp, LRESULT* res)
{
return (pro.after ? pro.after(msg, wp, lp, res) : true);
}
private:
static LRESULT CALLBACK _m_subclass_proc(HWND wd, UINT msg, WPARAM wp, LPARAM lp)
{
subclass * self = _m_find(wd);
if(nullptr == self || nullptr == self->old_proc_)
return 0;
auto i = self->msg_table_.find(msg);
if(self->msg_table_.end() == i)
return ::CallWindowProc(self->old_proc_, wd, msg, wp, lp);
LRESULT res = 0;
if(self->_m_call_before(i->second, msg, wp, lp, &res))
{
res = ::CallWindowProc(self->old_proc_, wd, msg, wp, lp);
self->_m_call_after(i->second, msg, wp, lp, &res);
}
if(WM_DESTROY == msg)
self->clear();
return res;
}
static subclass * _m_find(HWND wd)
{
return i->second;
return 0;
}
private:
HWND native_;
WNDPROC old_proc_;
};
int WINAPI WinMain(HINSTANCE, HINSTANCE, char*, int)
{
using namespace nana;
subclass sc(fm);
sc.make_before(WM_CLIPBOARDUPDATE, [](UINT, WPARAM, LPARAM, LRESULT*)
{
::OutputDebugStringA("WM_CLIPBOARDUPDATE Before\n");
return true;
});
sc.make_after(WM_CLIPBOARDUPDATE, [](UINT, WPARAM, LPARAM, LRESULT*)
{
::OutputDebugStringA("WM_CLIPBOARDUPDATE After\n");
return true;
});
HWND wd =
reinterpret_cast<HWND
>(
API::root(fm));
#if defined(_MSC_VER)
AddClipboardFormatListener(wd);
#else
::OutputDebugStringA("It seems that MinGW-w64 have problems with this: http://mingw-w64-public.narkive.com/1NqIVSS6/addclipboardformatlistener-missing-from-libuser32-a . Try uncommenting this.\n");
#endif
fm.show();
return 0;
}
#else
int main() {}
#endif // NANA_WINDOWS