Reputation: 25938
I have a funny error occurring at runtime where my HINSTANCE
and HWND
variables are getting corrupted. I have posted the debugging output below and the line of code where the runtime error occurs. *Note: even though the screen capture kindof shows the HWND isn't corrupted, it doesn't point to the right/valid window anymore
Why is this problem occurring and how can I fix it?
WindowTiler.exe!WindowLayoutComponent::init(const IEventArgs & evtArgs) Line 26 C++
[External Code]
WindowTiler.exe!EventDelegate::operator()(const IEventArgs & evtArgs) Line 21 C++
WindowTiler.exe!IApp::eventHandler(const int & evtId, const IEventArgs & evtArgs) Line 20 C++
WindowTiler.exe!Win32App::wndProc(HWND__ * hwnd, unsigned int message, unsigned int wParam, long lParam) Line 18 C++
[External Code]
[Frames below may be incorrect and/or missing, no symbols loaded for user32.dll]
WindowTiler.exe!Win32App::initInstance(const Win32AppInit & evtArgs) Line 154 C++
WindowTiler.exe!Win32App::init(const IEventArgs & evtArgs) Line 100 C++
WindowTiler.exe!App::init(const IEventArgs & evtArgs) Line 45 C++
WindowTiler.exe!WinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, char * lpCmdLine, int nCmdShow) Line 16 C++
[External Code]
Status WindowLayoutComponent::init(const IEventArgs& evtArgs)
{
auto args = (const WinEventArgs&)evtArgs;
HWND btn = CreateWindowEx(WS_EX_TRANSPARENT, _T("Button"), _T("Test"), WS_VISIBLE | WS_CHILD | WS_EX_TRANSPARENT,
30, 30, 50, 50, args.hwnd, NULL, args.hinstance, 0); // LINE 26
return S_SUCCESS;
}
Edit: There are 2 IEventArgs
objects involved. One passed to App::init(const IEventArgs & evtArgs)
and another different object created in Win32App::wndProc
and passed to IApp::eventHandler(const int & evtId, const IEventArgs & evtArgs)
.
LRESULT CALLBACK Win32App::wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
WinEventArgs args { hinstance, hwnd, wParam, lParam };
eventHandler(message, args);
...
Upvotes: 0
Views: 694
Reputation: 25938
After extensive debugging I have found the problem and solved it. I'm surprised the compiler didn't catch this error. It's actually quite interesting what went wrong. The problem was here...
struct IEventArgs
{
};
struct WinEventArgs : public IEventArgs
{
WinEventArgs() = delete;
WinEventArgs(const HINSTANCE& hinstance, const HWND& hwnd, const WPARAM& wParam, const LPARAM& lParam) :
hinstance(hinstance), hwnd(hwnd), wParam(wParam), lParam(lParam)
{}
const HINSTANCE& hinstance;
const HWND& hwnd;
const WPARAM& wParam;
const LPARAM& lParam;
};
class EventDelegate
{
public:
// the problem is here: the parameter should be 'const IEventArgs&'
typedef std::function<Status(IEventArgs)> EDelegate;
EventDelegate(EDelegate delegate, GUID gUidContext);
Status operator()(const IEventArgs& evtArgs)
{
return delegate(evtArgs);
}
private:
GUID gUidContext;
EDelegate delegate;
};
I've produced a simple example of the problem that people can reproduce. Whilst I've fixed it, what exactly was going wrong, was it that a copy was being made and I hadn't implemented a copy constructor?
struct IEventArgs { };
struct WinEventArgs : public IEventArgs
{
WinEventArgs(const int& a, const int& b) : a(a), b(b) { }
const int& a;
const int& b;
};
class Component
{
public:
void test(const IEventArgs& evtArgs)
{
const WinEventArgs& args = static_cast<const WinEventArgs&>(evtArgs);
printf("a=1 is: %d, b=2 is: %d\n", args.a, args.b);
}
};
int main()
{
WinEventArgs args(1,2);
Component cmp;
// Note Component::test's parameter is 'const IEventArgs&' and that the std::function parameter is just 'IEventArgs'
std::function<void(IEventArgs)> func = std::bind(&Component::test, cmp, std::placeholders::_1);
func(args);
// When std::function parameter is 'const IEventArgs&' the cast inside Component::test succeeds
std::function<void(const IEventArgs&)> func2 = std::bind(&Component::test, cmp, std::placeholders::_1);
func2(args);
return 0;
}
Upvotes: 0