📄 dockingwindow.h
字号:
// Copyright (c) 2002
// Sergey Klimov (kidd@ukr.net)
// WTL Docking windows
//
// This code is provided "as is", with absolutely no warranty expressed
// or implied. Any use is at your own risk.
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name is included. If
// the source code in this file is used in any commercial application
// then a simple email woulod be nice.
#ifndef __WTL_DW__DOCKINGWINDOW_H__
#define __WTL_DW__DOCKINGWINDOW_H__
#pragma once
#include "DDTracker.h"
namespace dockwins{
class CDocker : protected CWindow
{
public:
explicit CDocker(HWND hWnd=NULL) : CWindow(hWnd)
{
}
bool AdjustDragRect(DFDOCKRECT* pHdr) const
{
pHdr->hdr.code=DC_ADJUSTDRAGRECT;
return (::SendMessage(m_hWnd,WMDF_DOCK,NULL,reinterpret_cast<LPARAM>(pHdr))!=FALSE);
}
bool AcceptDock(DFDOCKRECT* pHdr) const
{
pHdr->hdr.code=DC_ACCEPT;
return (::SendMessage(m_hWnd,WMDF_DOCK,NULL,reinterpret_cast<LPARAM>(pHdr))!=FALSE);
}
bool Dock(DFDOCKRECT* pHdr) const
{
pHdr->hdr.code=DC_DOCK;
// return (::SendMessage(m_hWnd,WMDF_DOCK,NULL,reinterpret_cast<LPARAM>(pHdr))!=FALSE);
return (::SendMessage(pHdr->hdr.hBar,WMDF_DOCK,NULL,reinterpret_cast<LPARAM>(pHdr))!=FALSE);
}
bool Undock(DFMHDR* pHdr) const
{
pHdr->code=DC_UNDOCK;
return (::SendMessage(pHdr->hBar,WMDF_DOCK,NULL,reinterpret_cast<LPARAM>(pHdr))!=FALSE);
}
bool Replace(DFDOCKREPLACE* pHdr) const
{
pHdr->hdr.code=DC_REPLACE;
return (::SendMessage(pHdr->hdr.hBar,WMDF_DOCK,NULL,reinterpret_cast<LPARAM>(pHdr))!=FALSE);
}
bool GetDockingPosition(DFDOCKPOS* pHdr) const
{
pHdr->hdr.code=DC_GETDOCKPOSITION;
return (::SendMessage(m_hWnd,WMDF_DOCK,NULL,reinterpret_cast<LPARAM>(pHdr))!=FALSE);
}
bool SetDockingPosition(DFDOCKPOS* pHdr) const
{
pHdr->hdr.hBar=m_hWnd;
pHdr->hdr.code=DC_SETDOCKPOSITION;
return (::SendMessage(m_hWnd,WMDF_DOCK,NULL,reinterpret_cast<LPARAM>(pHdr))!=FALSE);
}
//#ifdef DF_AUTO_HIDE_FEATURES
bool PinUp(DFPINUP* pHdr) const
{
pHdr->hdr.code=DC_PINUP;
return (::SendMessage(m_hWnd,WMDF_DOCK,NULL,reinterpret_cast<LPARAM>(pHdr))!=FALSE);
}
bool IsPinned(DFMHDR* pHdr) const
{
pHdr->code=DC_ISPINNED;
return (::SendMessage(m_hWnd,WMDF_DOCK,NULL,reinterpret_cast<LPARAM>(pHdr))!=FALSE);
}
//#endif
operator HWND ()
{
return m_hWnd;
}
};
template < DWORD t_dwStyle = 0, DWORD t_dwExStyle = 0>
struct CDockingBarWinTraits : CWinTraits<t_dwStyle,t_dwExStyle>
{
typedef dockwins::CDocker CDocker;
};
typedef CDockingBarWinTraits<WS_OVERLAPPEDWINDOW| WS_POPUP/* WS_CHILD*/ | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,WS_EX_TOOLWINDOW/* WS_EX_CLIENTEDGE*/> CSimpleDockingBarWinTraits;
template <class T,
class TBase = CWindow,
class TWinTraits = CSimpleDockingBarWinTraits>
class ATL_NO_VTABLE CDockingWindowBaseImpl : public CWindowImpl< T, TBase, TWinTraits >
{
typedef CWindowImpl< T, TBase, TWinTraits > baseClass;
typedef CDockingWindowBaseImpl< T, TBase, TWinTraits > thisClass;
typedef typename TWinTraits::CDocker CDocker;
protected:
class CGhostMoveTracker : public CDDTrackerBaseT<CGhostMoveTracker>
{
//probably better use GetSystemMetrics
enum{GhostRectSideSize=3};
public:
CGhostMoveTracker(const CDocker& docker,const POINT& pt,DFDOCKRECT& dockHdr)
:m_docker(docker),m_dockHdr(dockHdr),m_dc(::GetWindowDC(NULL))
{
m_offset.cx=m_dockHdr.rect.left-pt.x;
m_offset.cy=m_dockHdr.rect.top-pt.y;
m_size.cx=m_dockHdr.rect.right-m_dockHdr.rect.left;
m_size.cy=m_dockHdr.rect.bottom-m_dockHdr.rect.top;
}
void DrawGhostRect(CDC& dc,RECT* pRect)
{
CBrush brush((HBRUSH)CDCHandle::GetHalftoneBrush());
if(!brush.IsNull())
{
HBRUSH hBrushOld = dc.SelectBrush(brush);
dc.PatBlt(pRect->left, pRect->top,
pRect->right-pRect->left,GhostRectSideSize, PATINVERT);
dc.PatBlt(pRect->left, pRect->bottom-GhostRectSideSize,
pRect->right-pRect->left,GhostRectSideSize, PATINVERT);
dc.PatBlt(pRect->left, pRect->top+GhostRectSideSize,
GhostRectSideSize,pRect->bottom-pRect->top-2*GhostRectSideSize, PATINVERT);
dc.PatBlt(pRect->right-GhostRectSideSize, pRect->top+GhostRectSideSize,
GhostRectSideSize,pRect->bottom-pRect->top-2*GhostRectSideSize, PATINVERT);
dc.SelectBrush(hBrushOld);
}
}
void CleanGhostRect(CDC& dc,RECT* pRect)
{
DrawGhostRect(dc,pRect);
}
void BeginDrag()
{
DrawGhostRect(m_dc,&m_dockHdr.rect);
}
void EndDrag(bool /*bCanceled*/)
{
CleanGhostRect(m_dc,&m_dockHdr.rect);
}
void OnMove(long x, long y)
{
CleanGhostRect(m_dc,&m_dockHdr.rect);
m_dockHdr.rect.left=x;
m_dockHdr.rect.top=y;
::ClientToScreen(m_dockHdr.hdr.hWnd,reinterpret_cast<POINT*>(&m_dockHdr.rect));
m_dockHdr.rect.right=m_dockHdr.rect.left+m_size.cx;
m_dockHdr.rect.bottom=m_dockHdr.rect.top+m_size.cy;
m_docker.AdjustDragRect(&m_dockHdr);
if((GetKeyState(VK_CONTROL) & 0x8000) || !m_docker.AcceptDock(&m_dockHdr))
{
m_dockHdr.hdr.hBar=HNONDOCKBAR;
m_dockHdr.rect.left=x+m_offset.cx;
m_dockHdr.rect.top=y+m_offset.cy;
m_dockHdr.rect.right=m_dockHdr.rect.left+m_size.cx;
m_dockHdr.rect.bottom=m_dockHdr.rect.top+m_size.cy;
}
DrawGhostRect(m_dc,&m_dockHdr.rect);
}
bool ProcessWindowMessage(MSG* pMsg)
{
bool bHandled=false;
switch(pMsg->message)
{
case WM_KEYDOWN:
case WM_KEYUP:
if(pMsg->wParam==VK_CONTROL)
{
CPoint point(pMsg->pt.x,pMsg->pt.y);
::ScreenToClient(m_dockHdr.hdr.hWnd,&point);
OnMove(point.x,point.y);
bHandled=true;
}
break;
}
return bHandled;
}
protected:
const CDocker& m_docker;
CDC m_dc;
DFDOCKRECT& m_dockHdr;
SIZE m_size;
SIZE m_offset;
};
public:
CDockingWindowBaseImpl()
:m_hBarOwner(HNONDOCKBAR)
{
m_rcUndock.SetRectEmpty();
}
HWND Create(HWND hDockingFrameWnd, RECT& rcPos, LPCTSTR szWindowName = NULL,
DWORD dwStyle = 0, DWORD dwExStyle = 0,
UINT nID = 0, LPVOID lpCreateParam = NULL)
{
m_docker=CDocker(hDockingFrameWnd);
return baseClass::Create(hDockingFrameWnd, rcPos, szWindowName ,
dwStyle , dwExStyle , nID , lpCreateParam);
}
#ifdef DF_AUTO_HIDE_FEATURES
BOOL IsWindowVisible() const
{
BOOL bRes=IsPinned();
if(!bRes)
bRes=baseClass::IsWindowVisible();
return bRes;
}
bool IsPinned() const
{
bool bRes=IsDocking();
if(bRes)
{
DFMHDR dockHdr;
// dockHdr.code=DC_ISPINNED;
dockHdr.hWnd=m_hWnd;
dockHdr.hBar=GetOwnerDockingBar();
bRes=m_docker.IsPinned(&dockHdr);
}
return bRes;
}
#endif
HDOCKBAR GetOwnerDockingBar() const
{
return m_hBarOwner;
}
bool GetDockingPosition(DFDOCKPOS* pHdr) const
{
assert(::IsWindow(m_hWnd));
bool bRes=true;
pHdr->hdr.hBar=GetOwnerDockingBar();
if(IsDocking())
{
pHdr->hdr.hWnd=m_hWnd;
// pHdr->hdr.code=DC_GETDOCKPOSITION;
bRes=m_docker.GetDockingPosition(pHdr);
}
return bRes;
}
bool GetDockingWindowPlacement(DFDOCKPOSEX* pHdr) const
{
bool bRes=true;
pHdr->bDocking=IsDocking();
if(pHdr->bDocking)
{
::CopyRect(&pHdr->rect,&m_rcUndock);
bRes=GetDockingPosition(&(pHdr->dockPos));
}
else
GetWindowRect(&pHdr->rect);
return bRes;
}
bool SetDockingPosition(DFDOCKPOS* pHdr)
{
assert(::IsWindow(m_hWnd));
if(IsDocking())
Undock();
pHdr->hdr.hWnd=m_hWnd;
// pHdr->hdr.code=DC_SETDOCKPOSITION;
return m_docker.SetDockingPosition(pHdr);
}
bool SetDockingWindowPlacement(DFDOCKPOSEX* pHdr)
{
bool bRes=true;
if(pHdr->bDocking)
{
bRes=SetDockingPosition(&(pHdr->dockPos));
::CopyRect(&m_rcUndock,&pHdr->rect);
}
else
{
if(IsDocking())
Undock();
bRes=(SetWindowPos(HWND_TOP,&(pHdr->rect),SWP_SHOWWINDOW | SWP_NOACTIVATE)!=FALSE);
}
return bRes;
}
bool IsDocking() const
{
return GetOwnerDockingBar()!=HNONDOCKBAR;
}
bool Float(LPCRECT pRc,UINT flags=SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_FRAMECHANGED,HWND hWndInsertAfter=HWND_TOP)
{
bool bRes=IsDocking();
if(bRes)
{
if(Undock())
bRes=(SetWindowPos(hWndInsertAfter,pRc,flags)!=FALSE);
}
return bRes;
}
bool Float()
{
bool bRes=!m_rcUndock.IsRectEmpty();
if(bRes)
bRes=Float(&m_rcUndock);
return bRes;
}
virtual bool Undock()
{
assert(IsDocking());
DFMHDR dockHdr;
// dockHdr.code=DC_UNDOCK;
dockHdr.hWnd=m_hWnd;
dockHdr.hBar=GetOwnerDockingBar();
return m_docker.Undock(&dockHdr);
}
bool OnClosing()
{
bool bRes=true;
if(IsDocking())
bRes=Undock();
return bRes;
}
virtual bool DockMe(DFDOCKRECT* pHdr)
{
return m_docker.Dock(pHdr);
}
bool BeginMoving(const POINT& point)
{
DFDOCKRECT dockHdr;
// dockHdr.hdr.code=DC_ACCEPT;
dockHdr.hdr.hWnd=m_hWnd;
dockHdr.hdr.hBar=HNONDOCKBAR;//GetOwnerDockingBar();
if(m_rcUndock.IsRectEmpty())
{
GetWindowRect(&dockHdr.rect);
// dockHdr.hdr.code=DC_ADJUSTDRAGRECT;
m_docker.AdjustDragRect(&dockHdr);
m_rcUndock.CopyRect(&dockHdr.rect);
}
GetWindowRect(&dockHdr.rect);
CPoint pt(point);
ClientToScreen(&pt);
float ratio=float(pt.x-dockHdr.rect.left)/(dockHdr.rect.right-dockHdr.rect.left);
dockHdr.rect.left=pt.x-long(ratio*m_rcUndock.Width());
ratio=float(pt.y-dockHdr.rect.top)/(dockHdr.rect.bottom-dockHdr.rect.top);
dockHdr.rect.top=pt.y-long(ratio*m_rcUndock.Height());
dockHdr.rect.right=dockHdr.rect.left+m_rcUndock.Width();
dockHdr.rect.bottom=dockHdr.rect.top+m_rcUndock.Height();
CGhostMoveTracker tracker(m_docker,point,dockHdr);
if(TrackDragAndDrop(tracker,m_hWnd))
{
CPoint ptCur;
::GetCursorPos(&ptCur);
if((dockHdr.hdr.hBar!=HNONDOCKBAR)
|| (ptCur.x!=pt.x) || (ptCur.y!=pt.y))
{
if(IsDocking())
Undock();
if(dockHdr.hdr.hBar!=HNONDOCKBAR)
// m_docker.Dock(&dockHdr);
DockMe(&dockHdr);
else
SetWindowPos(HWND_TOP,&(dockHdr.rect),SWP_SHOWWINDOW | SWP_FRAMECHANGED);
}
}
return true;
}
void OnDocked(HDOCKBAR hBar,bool /*bHorizontal*/)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -