i'm trying to incorporate a derived class from WDL_VWnd. (For those that don't know, WDL is a bit like JUCE it allows to developp easily audio plugins)
so inside WDL there is a library that allows the creation of Windows windows
i'm trying to just create 1 child modal window outside the main audio plugin window.
i got 3 strange errors:
error LNK2019: unresolved external symbol "public: __thiscall WDL_VWnd::WDL_VWnd(void)" (??0WDL_VWnd@@QAE@XZ) référenced in the function "public: __thiscall testWindows::testWindows(void)" (??0testWindows@@QAE@XZ) C:\wdl-ol2\IPlugExamples\TestWaveletsCenter2\testWindows.obj
error LNK2019: unresolved external symbol "public: int __thiscall WDL_VWnd_Painter::GSC(int)" (?GSC@WDL_VWnd_Painter@@QAEHH@Z) référenced in the function "public: virtual int __thiscall testWindows::GSC(int)" (?GSC@testWindows@@UAEHH@Z) C:\wdl-ol2\IPlugExamples\TestWaveletsCenter2\testWindows.obj
error LNK2019: unresolved external symbol "public: virtual __thiscall WDL_VWnd::~WDL_VWnd(void)" (??1WDL_VWnd@@UAE@XZ) référenced in the function __unwindfunclet$??0testWindows@@QAE@XZ$0 C:\wdl-ol2\IPlugExamples\TestWaveletsCenter2\testWindows.obj
but the errors are not about the class TestWindows. Also WDL is very simple to install, there is not libraries to link, only simple #includes (which makes it very nice to use)
so, in the file TestWindows.h, i derivated a class from WDL_VWnd :
#ifndef _TestWindows_
#define _TestWindows_
#ifdef _WIN32
#include <windows.h>
#include <windowsx.h>
#else
#include "../WDL/swell/swell.h"
#endif
#include "../WDL/wingui/virtwnd.h"
class TestWindows : public WDL_VWnd
{
public:
TestWindows(void);
~TestWindows(void);
virtual int OnMouseDown(int xpos, int ypos);
virtual bool OnMouseDblClick(int xpos, int ypos);
virtual void OnMouseMove(int xpos, int ypos);
virtual void OnMouseUp(int xpos, int ypos);
virtual int UpdateCursor(int xpos, int ypos);
virtual bool GetToolTipString(int xpos, int ypos, char *bufOut, int bufOutSz);
virtual bool IsDescendent(WDL_VWnd *w);
virtual bool OnMouseWheel(int xpos, int ypos, int amt);
virtual WDL_VWnd *VirtWndFromPoint(int xpos, int ypos, int maxdepth);
virtual void SetChildPosition(WDL_VWnd *ch, int pos);
virtual void AddChild(WDL_VWnd *wnd, int pos);
virtual WDL_VWnd *GetChildByID(int id);
virtual void RemoveChild(WDL_VWnd *wnd, bool dodel);
virtual void OnPaint(LICE_IBitmap *drawbm, int origin_x, int origin_y, RECT *cliprect);
virtual void OnPaintOver(LICE_IBitmap *drawbm, int origin_x, int origin_y, RECT *cliprect);
virtual int GetNumChildren();
virtual WDL_VWnd *EnumChildren(int x);
virtual void RemoveAllChildren(bool dodel);
virtual INT_PTR SendCommand(int command, INT_PTR parm1, INT_PTR parm2, WDL_VWnd *src);
virtual void GetPositionInTopVWnd(RECT *r);
virtual void RequestRedraw(RECT *r);
virtual void testWindows::OnCaptureLost();
virtual int GSC(int a);
protected:
WDL_VWnd *m_parent;
WDL_VWnd_IAccessibleBridge *m__iaccess;
bool m_visible;
int m_id;
RECT m_position;
INT_PTR m_userdata;
HWND m_realparent;
int m_captureidx;
int m_lastmouseidx;
WDL_PtrList<WDL_VWnd> *m_children;
const char *m__iaccess_desc;
WDL_VWnd_Painter *m_curPainter;
WDL_DestroyState m_destroystate;
};;
#endif
here is TestWindows.cpp
#include "testWindows.h"
testWindows::testWindows()
{
m__iaccess=0;
m__iaccess_desc=0;
m_visible=true; m_id=0;
m_position.left=0; m_position.top=0; m_position.right=0; m_position.bottom=0;
m_parent=0;
m_children=0;
m_realparent=0;
m_captureidx=-1;
m_lastmouseidx=-1;
m_userdata=0;
m_curPainter=0;
}
testWindows::~testWindows()
{
if (m_children)
{
m_children->Empty(true);
delete m_children;
}
if (m__iaccess) m__iaccess->Release();
}
int testWindows::GSC(int a)
{
return m_curPainter ? m_curPainter->GSC(a) : GetSysColor(a);
}
INT_PTR testWindows::SendCommand(int command, INT_PTR parm1, INT_PTR parm2, WDL_VWnd *src)
{
if (m_realparent)
{
return SendMessage(m_realparent,command,parm1,parm2);
}
else if (m_parent) return m_parent->SendCommand(command,parm1,parm2,src);
return 0;
}
void testWindows::RequestRedraw(RECT *r)
{
if (!IsVisible() ||
m_position.right <= m_position.left ||
m_position.bottom <= m_position.top) return;
RECT r2;
if (r)
{
r2=*r;
r2.left+=m_position.left; r2.right += m_position.left;
r2.top += m_position.top; r2.bottom += m_position.top;
}
else
{
GetPositionPaintExtent(&r2);
RECT r3;
if (WantsPaintOver())
{
GetPositionPaintOverExtent(&r3);
if (r3.left<r2.left)r2.left=r3.left;
if (r3.top<r2.top)r2.top=r3.top;
if (r3.right>r2.right)r2.right=r3.right;
if (r3.bottom>r2.bottom)r2.bottom=r3.bottom;
}
}
if (m_realparent)
{
#ifdef _WIN32
HWND hCh;
if ((hCh=GetWindow(m_realparent,GW_CHILD)))
{
HRGN rgn=CreateRectRgnIndirect(&r2);
int n=30; // limit to 30 children
while (n-- && hCh)
{
if (IsWindowVisible(hCh))
{
RECT r;
GetWindowRect(hCh,&r);
ScreenToClient(m_realparent,(LPPOINT)&r);
ScreenToClient(m_realparent,((LPPOINT)&r)+1);
HRGN tmprgn=CreateRectRgn(r.left,r.top,r.right,r.bottom);
CombineRgn(rgn,rgn,tmprgn,RGN_DIFF);
DeleteObject(tmprgn);
}
hCh=GetWindow(hCh,GW_HWNDNEXT);
}
InvalidateRgn(m_realparent,rgn,FALSE);
DeleteObject(rgn);
}
else
#else
// OS X, expand region up slightly
r2.top--;
#endif
InvalidateRect(m_realparent,&r2,FALSE);
}
else if (m_parent) m_parent->RequestRedraw(&r2);
}
bool testWindows::IsDescendent(WDL_VWnd *w)
{
if (!w || !m_children) return false;
int x,n=m_children->GetSize();
for(x=0;x<n;x++) if (m_children->Get(x) == w) return true;
for(x=0;x<n;x++)
{
WDL_VWnd *tmp = m_children->Get(x);
if (tmp && tmp->IsDescendent(w)) return true;
}
return false;
}
void testWindows::SetChildPosition(WDL_VWnd *ch, int pos)
{
if (!ch || !m_children) return;
int x;
for(x=0;x<m_children->GetSize();x++)
{
if (m_children->Get(x) == ch)
{
if (pos>x) pos--;
if (pos != x)
{
m_children->Delete(x);
m_children->Insert(pos,ch);
}
return;
}
}
}
void testWindows::AddChild(WDL_VWnd *wnd, int pos)
{
if (!wnd) return;
wnd->SetParent(this);
if (!m_children) m_children=new WDL_PtrList<WDL_VWnd>;
if (pos<0||pos>=m_children->GetSize()) m_children->Add(wnd);
else m_children->Insert(pos,wnd);
if (m__iaccess) m__iaccess->ClearCaches();
}
WDL_VWnd *testWindows::GetChildByID(int id)
{
if (m_children)
{
int x;
for (x = 0; x < m_children->GetSize(); x ++)
if (m_children->Get(x)->GetID()==id) return m_children->Get(x);
WDL_VWnd *r;
for (x = 0; x < m_children->GetSize(); x ++) if ((r=m_children->Get(x)->GetChildByID(id))) return r;
}
return 0;
}
void testWindows::RemoveChild(WDL_VWnd *wnd, bool dodel)
{
int idx=m_children ? m_children->Find(wnd) : -1;
if (idx>=0)
{
if (!dodel)
{
WDL_VWnd *ch = m_children->Get(idx);
if (ch) ch->SetParent(NULL);
}
m_children->Delete(idx,dodel);
}
if (m__iaccess) m__iaccess->ClearCaches();
}
void testWindows::OnPaint(LICE_IBitmap *drawbm, int origin_x, int origin_y, RECT *cliprect)
{
int x;
if (m_children) for (x = m_children->GetSize()-1; x >=0; x --)
{
WDL_VWnd *ch=m_children->Get(x);
if (ch->IsVisible())
{
RECT re;
ch->GetPosition(&re);
if (re.right>re.left&&re.bottom>re.top)
{
ch->GetPositionPaintExtent(&re);
re.left += origin_x + m_position.left;
re.right += origin_x + m_position.left;
re.top += origin_y + m_position.top;
re.bottom += origin_y + m_position.top;
RECT cr=*cliprect;
if (cr.left < re.left) cr.left=re.left;
if (cr.right > re.right) cr.right=re.right;
if (cr.top < re.top) cr.top=re.top;
if (cr.bottom > re.bottom) cr.bottom=re.bottom;
if (cr.left < cr.right && cr.top < cr.bottom)
{
ch->SetCurPainter(m_curPainter);
ch->OnPaint(drawbm,m_position.left+origin_x,m_position.top+origin_y,&cr);
ch->SetCurPainter(NULL);
}
}
}
}
}
void testWindows::OnPaintOver(LICE_IBitmap *drawbm, int origin_x, int origin_y, RECT *cliprect)
{
int x;
if (m_children) for (x = m_children->GetSize()-1; x >=0; x --)
{
WDL_VWnd *ch=m_children->Get(x);
if (ch->IsVisible() && ch->WantsPaintOver())
{
RECT re;
ch->GetPosition(&re);
if (re.right>re.left && re.bottom > re.top)
{
ch->GetPositionPaintOverExtent(&re);
re.left += origin_x + m_position.left;
re.right += origin_x + m_position.left;
re.top += origin_y + m_position.top;
re.bottom += origin_y + m_position.top;
RECT cr=*cliprect;
if (cr.left < re.left) cr.left=re.left;
if (cr.right > re.right) cr.right=re.right;
if (cr.top < re.top) cr.top=re.top;
if (cr.bottom > re.bottom) cr.bottom=re.bottom;
if (cr.left < cr.right && cr.top < cr.bottom)
{
ch->SetCurPainter(m_curPainter);
ch->OnPaintOver(drawbm,m_position.left+origin_x,m_position.top+origin_y,&cr);
ch->SetCurPainter(NULL);
}
}
}
}
}
int testWindows::GetNumChildren()
{
return m_children ? m_children->GetSize() : 0;
}
WDL_VWnd *testWindows::EnumChildren(int x)
{
return m_children ? m_children->Get(x) : 0;
}
void testWindows::RemoveAllChildren(bool dodel)
{
if (m_children)
{
if (!dodel) // update parent pointers
{
int x;
for (x = 0; x < m_children->GetSize(); x++)
{
WDL_VWnd *ch = m_children->Get(x);
if (ch) ch->SetParent(NULL);
}
}
m_children->Empty(dodel);
}
}
WDL_VWnd *testWindows::VirtWndFromPoint(int xpos, int ypos, int maxdepth)
{
int x;
if (m_children) for (x = 0; x < m_children->GetSize(); x++)
{
WDL_VWnd *wnd=m_children->Get(x);
if (wnd->IsVisible())
{
RECT r;
wnd->GetPosition(&r);
if (xpos >= r.left && xpos < r.right && ypos >= r.top && ypos < r.bottom)
{
if (maxdepth!=0)
{
WDL_VWnd *cwnd=wnd->VirtWndFromPoint(xpos-r.left,ypos-r.top,maxdepth > 0 ? (maxdepth-1) : -1);
if (cwnd) return cwnd;
}
return wnd;
}
}
}
return 0;
}
int testWindows::OnMouseDown(int xpos, int ypos) // returns TRUE if handled
{
if (!m_children) return 0;
WDL_VWnd *wnd=VirtWndFromPoint(xpos,ypos,0);
if (!wnd)
{
m_captureidx=-1;
return 0;
}
RECT r;
wnd->GetPosition(&r);
WDL_VWND_DCHK(chk);
int a;
if ((a=wnd->OnMouseDown(xpos-r.left,ypos-r.top)))
{
if (a<0) return -1;
if (chk.isOK()) m_captureidx=m_children->Find(wnd);
return 1;
}
return 0;
}
bool testWindows::OnMouseDblClick(int xpos, int ypos) // returns TRUE if handled
{
WDL_VWnd *wnd=VirtWndFromPoint(xpos,ypos,0);
if (!wnd) return false;
RECT r;
wnd->GetPosition(&r);
return wnd->OnMouseDblClick(xpos-r.left,ypos-r.top);
}
bool testWindows::OnMouseWheel(int xpos, int ypos, int amt)
{
WDL_VWnd *wnd=VirtWndFromPoint(xpos,ypos,0);
if (!wnd) return false;
RECT r;
wnd->GetPosition(&r);
return wnd->OnMouseWheel(xpos-r.left,ypos-r.top,amt);
}
bool testWindows::GetToolTipString(int xpos, int ypos, char *bufOut, int bufOutSz)
{
WDL_VWnd *wnd=VirtWndFromPoint(xpos,ypos,0);
if (!wnd) return false;
RECT r;
wnd->GetPosition(&r);
return wnd->GetToolTipString(xpos-r.left,ypos-r.top,bufOut,bufOutSz);
}
int testWindows::UpdateCursor(int xpos, int ypos)
{
WDL_VWnd *wnd=VirtWndFromPoint(xpos,ypos,0);
if (!wnd) return 0;
RECT r;
wnd->GetPosition(&r);
return wnd->UpdateCursor(xpos-r.left,ypos-r.top);
}
void testWindows::OnMouseMove(int xpos, int ypos)
{
if (!m_children) return;
WDL_VWnd *wnd=m_children->Get(m_captureidx);
WDL_VWND_DCHK(chk);
if (!wnd)
{
wnd=VirtWndFromPoint(xpos,ypos,0);
if (wnd) // todo: stuff so if the mouse goes out of the window completely, the virtualwnd gets notified
{
int idx=m_children->Find(wnd);
if (idx != m_lastmouseidx)
{
WDL_VWnd *t=m_children->Get(m_lastmouseidx);
if (t)
{
RECT r;
t->GetPosition(&r);
t->OnMouseMove(xpos-r.left,ypos-r.top);
}
if (chk.isOK()) m_lastmouseidx=idx;
}
}
else
{
WDL_VWnd *t=m_children->Get(m_lastmouseidx);
if (t)
{
RECT r;
t->GetPosition(&r);
t->OnMouseMove(xpos-r.left,ypos-r.top);
}
if (chk.isOK()) m_lastmouseidx=-1;
}
}
if (wnd && chk.isOK())
{
RECT r;
wnd->GetPosition(&r);
wnd->OnMouseMove(xpos-r.left,ypos-r.top);
}
}
void testWindows::OnCaptureLost()
{
int oldcap=m_captureidx;
m_captureidx=-1;
if (m_children)
{
WDL_VWnd *wnd=m_children->Get(oldcap);
if (wnd)
{
wnd->OnCaptureLost();
}
}
}
void testWindows::OnMouseUp(int xpos, int ypos)
{
int oldcap=m_captureidx;
m_captureidx=-1; // set this before passing to children, in case a child ends up destroying us
if (m_children)
{
WDL_VWnd *wnd=m_children->Get(oldcap);
if (!wnd)
{
wnd=VirtWndFromPoint(xpos,ypos,0);
}
if (wnd)
{
RECT r;
wnd->GetPosition(&r);
wnd->OnMouseUp(xpos-r.left,ypos-r.top);
}
}
}
void testWindows::GetPositionInTopVWnd(RECT *r)
{
GetPosition(r);
WDL_VWnd *par=GetParent();
while (par)
{
WDL_VWnd *tmp=par;
par=par->GetParent();
if (par)
{
RECT t;
tmp->GetPosition(&t);
r->left+=t.left;
r->right+=t.left;
r->top+=t.top;
r->bottom+=t.top;
}
};
}