Преглед изворни кода

added group wnd, magnetic wnd

git-svn-id: svn://svn.code.sf.net/p/ditto-cp/code/trunk@395 595ec19a-5cb4-439b-94a8-42fb3063c22c
sabrogden пре 18 година
родитељ
комит
320a8ff025
21 измењених фајлова са 938 додато и 277 уклоњено
  1. 3 2
      CP_Main.cpp
  2. 1 0
      CP_Main.h
  3. 10 2
      CP_Main.rc
  4. 20 2
      CP_Main.vcproj
  5. 4 1
      Clip.cpp
  6. 212 62
      GroupTree.cpp
  7. 24 43
      GroupTree.h
  8. 211 0
      GroupWnd.cpp
  9. 55 0
      GroupWnd.h
  10. 169 0
      MagneticWnd.cpp
  11. 29 0
      MagneticWnd.h
  12. 3 3
      MoveToGroupDlg.cpp
  13. 33 21
      OleClipSource.cpp
  14. 52 0
      Options.cpp
  15. 13 0
      Options.h
  16. 65 111
      QPasteWnd.cpp
  17. 4 4
      QPasteWnd.h
  18. 6 8
      QuickPaste.cpp
  19. 8 3
      Resource.h
  20. 14 14
      WndEx.cpp
  21. 2 1
      WndEx.h

+ 3 - 2
CP_Main.cpp

@@ -125,6 +125,7 @@ CCP_MainApp::CCP_MainApp()
 	m_cfIgnoreClipboard = ::RegisterClipboardFormat(_T("Clipboard Viewer Ignore"));
 	m_cfDelaySavingData = ::RegisterClipboardFormat(_T("Ditto Delay Saving Data"));
 	m_RemoteCF_HDROP = ::RegisterClipboardFormat(_T("Ditto Remote CF_HDROP"));
+	m_DittoIdsFormat = ::RegisterClipboardFormat(_T("Ditto Clip Ids Format"));
 
 	m_QuickPasteMode = NONE_QUICK_PASTE;
 	m_pQuickPasteClip = NULL;
@@ -711,9 +712,9 @@ void CCP_MainApp::RefreshView()
 	if(pWnd)
 	{
 		if(m_bAsynchronousRefreshView)
-			pWnd->PostMessage(WM_REFRESH_VIEW);
+			pWnd->PostMessage(WM_REFRESH_VIEW, 0, 0);
 		else
-			pWnd->SendMessage(WM_REFRESH_VIEW);
+			pWnd->SendMessage(WM_REFRESH_VIEW, 0, 0);
 	}
 }
 

+ 1 - 0
CP_Main.h

@@ -175,6 +175,7 @@ public:
 	CLIPFORMAT m_HTML_Format;
 	CLIPFORMAT m_RemoteCF_HDROP;
 	CLIPFORMAT m_RTFFormat;
+	CLIPFORMAT m_DittoIdsFormat;
 
 	COleDateTime m_oldtStartUp;
 

+ 10 - 2
CP_Main.rc

@@ -87,6 +87,7 @@ IDB_BACK                BITMAP                  "res\\back.bmp"
 IDB_BACK_PRESSED        BITMAP                  "res\\back1.bmp"
 IDB_BACK_FOCUSED        BITMAP                  "res\\back2.bmp"
 IDR_EDIT_WND            BITMAP                  "res\\mainfram.bmp"
+IDR_TOOLBAR_GROUP       BITMAP                  "res\\toolbar1.bmp"
 
 /////////////////////////////////////////////////////////////////////////////
 //
@@ -120,6 +121,13 @@ BEGIN
     BUTTON      ID_BUTTON_CLOSE
 END
 
+IDR_TOOLBAR_GROUP TOOLBAR  16, 15
+BEGIN
+    BUTTON      ID_BUTTON_REFRESH_GROUP
+    BUTTON      ID_BUTTON_PIN
+    BUTTON      ID_BUTTON_NEW_GROUP
+END
+
 
 /////////////////////////////////////////////////////////////////////////////
 //
@@ -746,11 +754,11 @@ BEGIN
     LTEXT           "Quick Paste Text",IDC_STATIC,7,56,62,13,SS_CENTERIMAGE
 END
 
-IDD_ABOUT DIALOG  0, 0, 292, 153
+IDD_ABOUT DIALOGEX 0, 0, 292, 153
 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | 
     WS_SYSMENU
 CAPTION "About"
-FONT 8, "MS Shell Dlg"
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
 BEGIN
     LISTBOX         IDC_LIST,7,16,271,86,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | 
                     WS_TABSTOP

+ 20 - 2
CP_Main.vcproj

@@ -831,6 +831,9 @@
 						ObjectFile="$(IntDir)/$(InputName)1.obj"/>
 				</FileConfiguration>
 			</File>
+			<File
+				RelativePath=".\DittoDropTarget.cpp">
+			</File>
 			<File
 				RelativePath=".\DittoRulerRichEditCtrl.cpp">
 			</File>
@@ -1065,6 +1068,9 @@
 						BasicRuntimeChecks="3"/>
 				</FileConfiguration>
 			</File>
+			<File
+				RelativePath=".\GroupWnd.cpp">
+			</File>
 			<File
 				RelativePath=".\HTMLFormatAggregator.cpp">
 			</File>
@@ -1105,6 +1111,9 @@
 						BasicRuntimeChecks="3"/>
 				</FileConfiguration>
 			</File>
+			<File
+				RelativePath=".\MagneticWnd.cpp">
+			</File>
 			<File
 				RelativePath="MainFrm.cpp">
 				<FileConfiguration
@@ -2690,6 +2699,9 @@
 			<File
 				RelativePath=".\DittoCopyBuffer.h">
 			</File>
+			<File
+				RelativePath=".\DittoDropTarget.h">
+			</File>
 			<File
 				RelativePath=".\DittoRulerRichEditCtrl.h">
 			</File>
@@ -2720,6 +2732,9 @@
 			<File
 				RelativePath="GroupTree.h">
 			</File>
+			<File
+				RelativePath=".\GroupWnd.h">
+			</File>
 			<File
 				RelativePath=".\HTMLFormatAggregator.h">
 			</File>
@@ -2732,6 +2747,9 @@
 			<File
 				RelativePath="InternetUpdate.h">
 			</File>
+			<File
+				RelativePath=".\MagneticWnd.h">
+			</File>
 			<File
 				RelativePath="MainFrm.h">
 			</File>
@@ -2969,7 +2987,7 @@
 				</FileConfiguration>
 			</File>
 			<File
-				RelativePath="Release\focus.dll">
+				RelativePath="Debug\focus.dll">
 				<FileConfiguration
 					Name="Release|Win32"
 					ExcludedFromBuild="TRUE">
@@ -2996,7 +3014,7 @@
 				</FileConfiguration>
 			</File>
 			<File
-				RelativePath="Debug\focus.dll">
+				RelativePath="Release\focus.dll">
 				<FileConfiguration
 					Name="Release|Win32"
 					ExcludedFromBuild="TRUE">

+ 4 - 1
Clip.cpp

@@ -702,6 +702,7 @@ void CClip::MakeLatestTime()
 
 BOOL CClip::LoadMainTable(long lID)
 {
+	bool bRet = false;
 	try
 	{
 		CppSQLite3Query q = theApp.m_db.execQueryEx(_T("SELECT * FROM Main WHERE lID = %d"), lID);
@@ -718,11 +719,13 @@ BOOL CClip::LoadMainTable(long lID)
 			m_csQuickPaste = q.getStringField(_T("QuickPasteText"));
 
 			m_ID = lID;
+
+			bRet = true;
 		}
 	}
 	CATCH_SQLITE_EXCEPTION_AND_RETURN(FALSE)
 
-	return TRUE;
+	return bRet;
 }
 
 // STATICS

+ 212 - 62
GroupTree.cpp

@@ -4,6 +4,7 @@
 #include "stdafx.h"
 #include "cp_main.h"
 #include "GroupTree.h"
+#include ".\grouptree.h"
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
@@ -16,25 +17,24 @@ static char THIS_FILE[] = __FILE__;
 
 CGroupTree::CGroupTree()
 {
-	m_bHide = true;
 	m_lSelectedFolderID = -1;
-	m_bSendAllready = false;
+	m_bShowCounts = true;
 }
 
 CGroupTree::~CGroupTree()
 {
+	
 }
 
 
 BEGIN_MESSAGE_MAP(CGroupTree, CTreeCtrl)
 	//{{AFX_MSG_MAP(CGroupTree)
 	ON_WM_CREATE()
-	ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelchanged)
-	ON_WM_KILLFOCUS()
-	ON_WM_ACTIVATE()
 	ON_NOTIFY_REFLECT(NM_DBLCLK, OnDblclk)
 	ON_NOTIFY_REFLECT(TVN_KEYDOWN, OnKeydown)
 	//}}AFX_MSG_MAP
+	ON_NOTIFY_REFLECT(TVN_ENDLABELEDIT, OnTvnEndlabeledit)
+	ON_NOTIFY_REFLECT(TVN_BEGINLABELEDIT, OnTvnBeginlabeledit)
 END_MESSAGE_MAP()
 
 
@@ -44,6 +44,7 @@ END_MESSAGE_MAP()
 BOOL CGroupTree::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) 
 {
 	// TODO: Add your specialized code here and/or call the base class
+	dwStyle = dwStyle | TVS_EDITLABELS | TVS_SHOWSELALWAYS;
 	
 	return CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
 }
@@ -62,19 +63,23 @@ int CGroupTree::OnCreate(LPCREATESTRUCT lpCreateStruct)
 	m_bmOpenFolder.LoadBitmap(IDB_OPEN_FOLDER);
 	iml.Add(&m_bmOpenFolder, RGB(255, 0, 0));
 	
-
 	SetImageList(&iml, TVSIL_NORMAL);
 	iml.Detach();
-		
+	
+	m_DropTarget.Register(this);
+	m_DropTarget.SetDropTarget(this);
+	
 	return 0;
 }
 
 void CGroupTree::FillTree()
 {	
 	DeleteAllItems();
-	m_bSendAllready = false;
 
-	HTREEITEM hItem = InsertItem(_T("Root"), TVI_ROOT);
+	CString cs;
+	cs.Format(_T("Root (%d)"), GetGroupCount(-1));
+
+	HTREEITEM hItem = InsertItem(cs, TVI_ROOT);
 	SetItemData(hItem, -1);
 	SetItemState(hItem, TVIS_EXPANDED, TVIS_EXPANDED);
 
@@ -84,7 +89,6 @@ void CGroupTree::FillTree()
 	FillTree(-1, hItem);
 }
 
-
 void CGroupTree::FillTree(long lParentID, HTREEITEM hParent)
 {	
 	try
@@ -94,22 +98,33 @@ void CGroupTree::FillTree(long lParentID, HTREEITEM hParent)
 		if(q.eof() == false)
 		{
 			HTREEITEM hItem;
+			CString cs;
 
 			while(!q.eof())
 			{
-				if(q.getIntField(_T("lID")) == m_lSelectedFolderID)
+				int nGroupID = q.getIntField(_T("lID"));
+				if(m_bShowCounts)
 				{
-					hItem = InsertItem(q.getStringField(_T("mText")), 1, 1, hParent);
+					cs.Format(_T("%s (%d)"), q.getStringField(_T("mText")), GetGroupCount(nGroupID));
+				}
+				else
+				{
+					cs.Format(_T("%s"), q.getStringField(_T("mText")));
+				}
+
+				if(nGroupID == m_lSelectedFolderID)
+				{
+					hItem = InsertItem(cs, 1, 1, hParent);
 					SelectItem(hItem);
 				}
 				else
 				{				
-					hItem = InsertItem(q.getStringField(_T("mText")), 0, 0, hParent);
+					hItem = InsertItem(cs, 0, 0, hParent);
 				}
 
-				SetItemData(hItem, q.getIntField(_T("lID")));
+				SetItemData(hItem, nGroupID);
 				
-				FillTree(q.getIntField(_T("lID")), hItem);
+				FillTree(nGroupID, hItem);
 
 				q.nextRow();
 			}
@@ -118,47 +133,16 @@ void CGroupTree::FillTree(long lParentID, HTREEITEM hParent)
 	CATCH_SQLITE_EXCEPTION	
 }
 
-void CGroupTree::OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult) 
-{
-	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
-	// TODO: Add your control notification handler code here
-	
-//	if(m_bHide == true)
-//	{	
-//		::SendMessage(m_NotificationWnd, NM_GROUP_TREE_MESSAGE, GetItemData(pNMTreeView->itemNew.hItem), 0);
-//	}
-	
-	*pResult = 0;
-}
-
-void CGroupTree::OnKillFocus(CWnd* pNewWnd) 
-{
-	CTreeCtrl::OnKillFocus(pNewWnd);
-}
-
-void CGroupTree::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) 
-{
-	CTreeCtrl::OnActivate(nState, pWndOther, bMinimized);
-	
-	if(m_bHide)
-	{
-		if (nState == WA_INACTIVE)
-		{		
-			SendToParent(-1);
-		}
-	}
-}
-
 void CGroupTree::OnDblclk(NMHDR* pNMHDR, LRESULT* pResult) 
 {
 	HTREEITEM hItem =  GetNextItem(TVI_ROOT, TVGN_CARET);
 	if(hItem)
-		SendToParent(GetItemData(hItem));
+		SendToParent(hItem);
 			
 	*pResult = 1;
 }
 
-long CGroupTree::GetSelectedTree()
+long CGroupTree::GetSelectedGroup()
 {
 	HTREEITEM hItem =  GetNextItem(TVI_ROOT, TVGN_CARET);
 	if(hItem)
@@ -177,42 +161,208 @@ void CGroupTree::OnKeydown(NMHDR* pNMHDR, LRESULT* pResult)
 	{	
 		HTREEITEM hItem =  GetNextItem(TVI_ROOT, TVGN_CARET);
 		if(hItem)
-			SendToParent(GetItemData(hItem));
+			SendToParent(hItem);
 		
 		break;
 	}
-	case VK_ESCAPE:
-	{	
-		SendToParent(-1);
+	case VK_F2:
+		{
+			HTREEITEM hItem =  GetNextItem(TVI_ROOT, TVGN_CARET);
+			if(hItem)
+				EditLabel(hItem);
+		}
 		break;
-	}	
 	}
 	
 	*pResult = 1;
 }
 
 
-void CGroupTree::SendToParent(long lID)
+void CGroupTree::SendToParent(HTREEITEM Item)
 {
-	if(m_bSendAllready == false)
-	{
-		m_bSendAllready = true;
-		::PostMessage(m_NotificationWnd, NM_GROUP_TREE_MESSAGE, lID, 0);
-	}
+	long lID = -1;
+	if(Item != NULL)
+		lID = GetItemData(Item);
+
+	::PostMessage(m_NotificationWnd, NM_GROUP_TREE_MESSAGE, lID, 0);
+	RefreshTreeItem(Item);
 }
 
-bool CGroupTree::AddNode(CString csText, long lID)
+HTREEITEM CGroupTree::AddNode(CString csText, long lID)
 {
 	HTREEITEM hItem;
 
 	HTREEITEM hParent =  GetNextItem(TVI_ROOT, TVGN_CARET);
 	if(hParent == NULL)
-		return false;
+		return NULL;
 		
 	hItem = InsertItem(csText, 1, 1, hParent);
 	SelectItem(hItem);
 
 	SetItemData(hItem, lID);
 
-	return true;
+	return hItem;
+}
+
+int CGroupTree::GetGroupCount(long lGroupID)
+{
+	long lCount = 0;
+	try
+	{
+		lCount = theApp.m_db.execScalarEx(_T("SELECT COUNT(lID) FROM Main WHERE lParentID = %d"), lGroupID);
+	}
+	CATCH_SQLITE_EXCEPTION
+
+	return lCount;
+}
+
+void CGroupTree::OnTvnEndlabeledit(NMHDR *pNMHDR, LRESULT *pResult)
+{
+	LPNMTVDISPINFO pTVDispInfo = reinterpret_cast<LPNMTVDISPINFO>(pNMHDR);
+	*pResult = 0;
+
+	long lID = GetItemData(pTVDispInfo->item.hItem);
+	if((lID < 0 && lID != NEW_GROUP_ID) || pTVDispInfo->item.pszText == NULL)
+	{
+		if(lID == NEW_GROUP_ID)
+			DeleteItem(pTVDispInfo->item.hItem);
+
+		return;
+	}
+
+	if(lID == NEW_GROUP_ID)
+	{
+		HTREEITEM hParent = GetParentItem(pTVDispInfo->item.hItem);
+		long lParentID = -1;
+		if(hParent != NULL)
+			lParentID = GetItemData(hParent);
+
+		lID = NewGroupID(lParentID, pTVDispInfo->item.pszText);
+		if(lID >= 0)
+		{
+			SetItemData(pTVDispInfo->item.hItem, lID);
+		}
+		else
+		{
+			DeleteItem(pTVDispInfo->item.hItem);
+			return;
+		}
+	}
+
+	CClip clip;
+	if(clip.LoadMainTable(lID))
+	{
+		clip.m_Desc = pTVDispInfo->item.pszText;
+		if(clip.ModifyMainTable())
+		{
+			CString cs;
+			cs.Format(_T("%s (%d)"), pTVDispInfo->item.pszText, GetGroupCount(lID));
+			SetItemText(pTVDispInfo->item.hItem, cs);
+		}
+	}	
+}
+
+void CGroupTree::OnTvnBeginlabeledit(NMHDR *pNMHDR, LRESULT *pResult)
+{
+	LPNMTVDISPINFO pTVDispInfo = reinterpret_cast<LPNMTVDISPINFO>(pNMHDR);
+	long lID = GetItemData(pTVDispInfo->item.hItem);
+	if(lID < 0 && lID != NEW_GROUP_ID)
+	{
+		*pResult = 1;
+		return;
+	}
+
+	if(m_bShowCounts)
+	{
+		CString csText = GetItemText(pTVDispInfo->item.hItem);
+		if(csText.ReverseFind(')') == csText.GetLength()-1)
+		{
+			int nPos = csText.ReverseFind('(');
+			csText = csText.Left(nPos);
+			csText = csText.Trim();
+
+			CEdit* pEdit = GetEditControl();
+			if (pEdit != NULL)
+			{
+				pEdit->SetWindowText(csText);
+			}
+		}
+	}
+
+	// TODO: Add your control notification handler code here
+	*pResult = 0;
+}
+
+void CGroupTree::RefreshTreeItem(HTREEITEM Item)
+{
+	CString csText = GetItemText(Item);
+	if(csText.ReverseFind(')') == csText.GetLength()-1)
+	{
+		int nPos = csText.ReverseFind('(');
+		csText = csText.Left(nPos);
+		csText = csText.Trim();
+	}
+
+	CString csItemText;
+	long lGroupID = GetItemData(Item);
+	csItemText.Format(_T("%s (%d)"), csText, GetGroupCount(lGroupID));
+	SetItemText(Item, csItemText);
+}
+
+DROPEFFECT CGroupTree::DragEnter(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point) 
+{
+	return DragOver(pDataObject, dwKeyState, point);
+}
+
+DROPEFFECT CGroupTree::DragOver(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point) 
+{
+	if(pDataObject->IsDataAvailable(theApp.m_DittoIdsFormat) == false)
+		return DROPEFFECT_NONE;
+
+	HTREEITEM hItem = HitTest(point);
+	SelectDropTarget(hItem);
+
+	return DROPEFFECT_MOVE;
+}
+
+BOOL CGroupTree::Drop(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point) 
+{
+	
+	HTREEITEM hItem = HitTest(point);
+	long lGroupID = GetItemData(hItem);
+	
+	CClipIDs Clips;
+	HGLOBAL hData = pDataObject->GetGlobalData(theApp.m_DittoIdsFormat);
+	if(hData)
+	{
+		int *pData = (int*)GlobalLock(hData);
+		if(pData)
+		{
+			int nItems = GlobalSize(hData) / sizeof(int);
+
+			for(int nPos = 0; nPos < nItems; nPos++)
+			{
+				Clips.Add(pData[nPos]);
+			}
+
+			GlobalUnlock(hData);
+		}
+	}
+
+	if(Clips.GetCount() > 0)
+	{
+		Clips.MoveTo(lGroupID);
+		RefreshTreeItem(hItem);
+		::SendMessage(m_NotificationWnd, WM_REFRESH_VIEW, 1, 0);
+	}
+
+	SelectDropTarget(NULL);
+	SelectItem(hItem);
+
+	return FALSE;
+}
+
+void CGroupTree::DragLeave()
+{
+	SelectDropTarget(NULL);
 }

+ 24 - 43
GroupTree.h

@@ -1,16 +1,10 @@
-#if !defined(AFX_GROUPTREE_H__A1F01358_5440_45A8_B402_3F32F46FCAA5__INCLUDED_)
-#define AFX_GROUPTREE_H__A1F01358_5440_45A8_B402_3F32F46FCAA5__INCLUDED_
-
-#if _MSC_VER > 1000
 #pragma once
-#endif // _MSC_VER > 1000
-// GroupTree.h : header file
-//
 
-/////////////////////////////////////////////////////////////////////////////
-// CGroupTree window
+#include "DittoDropTarget.h"
+
+#define NEW_GROUP_ID -2
 
-class CGroupTree : public CTreeCtrl
+class CGroupTree : public CTreeCtrl, IDittoDropTarget
 {
 // Construction
 public:
@@ -23,52 +17,39 @@ public:
 public:
 	void FillTree();
 	void SetNotificationWndEx(HWND hWnd)	{ m_NotificationWnd = hWnd;	}
-	bool m_bHide;
-	long m_lSelectedFolderID;
-	long GetSelectedTree();
-	bool AddNode(CString csText, long lID);
+	long GetSelectedGroup();
+	void SetSelectedGroup(long lGroupID)	{ m_lSelectedFolderID = lGroupID; }
+	HTREEITEM AddNode(CString csText, long lID);
 
 protected:
 	void FillTree(long lParentID, HTREEITEM hParent);
-	void SendToParent(long lID);
+	void SendToParent(HTREEITEM Item);
+	int GetGroupCount(long lGroupID);
+	void RefreshTreeItem(HTREEITEM Item);
 
 	HWND m_NotificationWnd;
 	CBitmap m_bmOpenFolder;
 	CBitmap m_bmClosedFolder;
-	bool m_bSendAllready;
-
-// Overrides
-	// ClassWizard generated virtual function overrides
-	//{{AFX_VIRTUAL(CGroupTree)
-	public:
-	virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);
-	//}}AFX_VIRTUAL
+	CDittoDropTarget m_DropTarget;
+	long m_lSelectedFolderID;
+	bool m_bShowCounts;
 
-// Implementation
 public:
 	virtual ~CGroupTree();
 
 	// Generated message map functions
 protected:
-	//{{AFX_MSG(CGroupTree)
+
+	DECLARE_MESSAGE_MAP()
+public:
+	virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);
 	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
-	afx_msg void OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult);
-	afx_msg void OnKillFocus(CWnd* pNewWnd);
-	afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
 	afx_msg void OnDblclk(NMHDR* pNMHDR, LRESULT* pResult);
 	afx_msg void OnKeydown(NMHDR* pNMHDR, LRESULT* pResult);
-	//}}AFX_MSG
-
-	DECLARE_MESSAGE_MAP()
-	// Generated OLE dispatch map functions
-	//{{AFX_DISPATCH(CGroupTree)
-		// NOTE - the ClassWizard will add and remove member functions here.
-	//}}AFX_DISPATCH
-};
-
-/////////////////////////////////////////////////////////////////////////////
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_GROUPTREE_H__A1F01358_5440_45A8_B402_3F32F46FCAA5__INCLUDED_)
+	afx_msg void OnTvnEndlabeledit(NMHDR *pNMHDR, LRESULT *pResult);
+	afx_msg void OnTvnBeginlabeledit(NMHDR *pNMHDR, LRESULT *pResult);
+	virtual DROPEFFECT DragEnter(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point);
+	virtual DROPEFFECT DragOver(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point);
+	virtual void DragLeave();
+	virtual BOOL Drop(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point);
+};

+ 211 - 0
GroupWnd.cpp

@@ -0,0 +1,211 @@
+// GroupWnd.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "CP_Main.h"
+#include "GroupWnd.h"
+#include ".\groupwnd.h"
+
+
+// CGroupWnd
+#define ID_TRANPARENCY 100
+
+IMPLEMENT_DYNAMIC(CGroupWnd, CMagneticWnd)
+CGroupWnd::CGroupWnd()
+{
+	m_lSelectedGroup = -1;
+	m_hwndNotify = NULL;
+}
+
+CGroupWnd::~CGroupWnd()
+{
+}
+
+
+BEGIN_MESSAGE_MAP(CGroupWnd, CMagneticWnd)
+	ON_WM_SIZE()
+	ON_WM_CREATE()
+	ON_WM_NCCALCSIZE()
+	ON_WM_NCPAINT()
+	ON_WM_NCHITTEST()
+	ON_WM_NCLBUTTONDOWN()
+	ON_WM_NCLBUTTONUP()
+	ON_WM_NCMOUSEMOVE()
+	ON_COMMAND(ID_BUTTON_REFRESH_GROUP, OnRefresh)
+	ON_COMMAND(ID_BUTTON_PIN, OnPin)
+	ON_COMMAND(ID_BUTTON_NEW_GROUP, OnNewGroup)
+	ON_WM_CLOSE()
+	ON_WM_KEYDOWN()
+	ON_WM_DESTROY()
+	ON_WM_ACTIVATE()
+END_MESSAGE_MAP()
+
+int CGroupWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+	if (CMagneticWnd::OnCreate(lpCreateStruct) == -1)
+		return -1;
+
+	m_DittoWindow.DoCreate(this);
+	m_DittoWindow.m_bDrawChevron = false;
+	m_DittoWindow.m_bDrawMaximize = false;
+	m_DittoWindow.m_bDrawMinimize = false;
+	m_DittoWindow.SetCaptionColors(::GetSysColor(COLOR_ACTIVECAPTION), ::GetSysColor(COLOR_GRADIENTACTIVECAPTION));
+	m_DittoWindow.SetCaptionOn(this, CAPTION_TOP, true);
+
+	m_Tree.Create(_T("SysTreeView32"), NULL, WS_BORDER|WS_VISIBLE|WS_CHILD|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS, CRect(0,0,0,0), this, 1);
+
+	m_Tree.SetSelectedGroup(m_lSelectedGroup);
+	m_Tree.SetNotificationWndEx(m_hwndNotify);
+
+	m_ToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD|WS_VISIBLE|CBRS_TOP|CBRS_TOOLTIPS);
+	m_ToolBar.LoadToolBar(IDR_TOOLBAR_GROUP);
+
+	MoveControls();
+
+	return 0;
+}
+
+void CGroupWnd::OnSize(UINT nType, int cx, int cy)
+{
+	CMagneticWnd::OnSize(nType, cx, cy);
+
+	m_DittoWindow.DoSetRegion(this);
+
+	MoveControls();
+}
+
+void CGroupWnd::MoveControls()
+{
+	if(::IsWindow(m_Tree.GetSafeHwnd()))
+	{
+		CRect cr;
+		GetClientRect(cr);
+
+		m_Tree.MoveWindow(cr.left, cr.top, cr.Width(), cr.Height() - 30);
+		m_ToolBar.MoveWindow(cr.left, cr.bottom - 30, 70, 30, TRUE);
+	}
+}
+
+void CGroupWnd::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp) 
+{
+	CMagneticWnd::OnNcCalcSize(bCalcValidRects, lpncsp);
+
+	m_DittoWindow.DoNcCalcSize(bCalcValidRects, lpncsp);
+}
+
+void CGroupWnd::OnNcPaint()
+{
+	m_DittoWindow.DoNcPaint(this);	
+}
+
+UINT CGroupWnd::OnNcHitTest(CPoint point) 
+{
+	UINT Ret = m_DittoWindow.DoNcHitTest(this, point);
+	if(Ret == -1)
+		return CMagneticWnd::OnNcHitTest(point);
+
+	return Ret;
+}
+void CGroupWnd::OnNcLButtonDown(UINT nHitTest, CPoint point)
+{
+	m_DittoWindow.DoNcLButtonDown(this, nHitTest, point);
+
+	CMagneticWnd::OnNcLButtonDown(nHitTest, point);
+}
+
+void CGroupWnd::OnNcLButtonUp(UINT nHitTest, CPoint point)
+{
+	if(m_DittoWindow.DoNcLButtonUp(this, nHitTest, point) > 0)
+		return;
+
+	CMagneticWnd::OnNcLButtonUp(nHitTest, point);
+}
+
+void CGroupWnd::OnNcMouseMove(UINT nHitTest, CPoint point)
+{
+	m_DittoWindow.DoNcMouseMove(this, nHitTest, point);
+
+	CMagneticWnd::OnNcMouseMove(nHitTest, point);
+}
+
+BOOL CGroupWnd::PreTranslateMessage(MSG* pMsg)
+{
+	m_DittoWindow.DoPreTranslateMessage(pMsg);
+
+	if(pMsg->message == WM_KEYDOWN && pMsg->hwnd == m_Tree.m_hWnd)
+	{
+		if(pMsg->wParam == VK_ESCAPE)
+		{
+			OnClose();
+			return TRUE;
+		}
+	}
+
+	return CMagneticWnd::PreTranslateMessage(pMsg);
+}
+
+void CGroupWnd::OnRefresh()
+{
+	m_Tree.SetSelectedGroup(m_Tree.GetSelectedGroup());
+	m_Tree.FillTree();
+}
+
+void CGroupWnd::OnPin()
+{
+	g_Opt.SetGroupWndPinned(!g_Opt.m_bGroupWndPinned);
+}
+
+void CGroupWnd::OnNewGroup()
+{
+	HTREEITEM hItem = m_Tree.AddNode("", NEW_GROUP_ID);
+	if(hItem != NULL)
+		m_Tree.EditLabel(hItem);
+}
+
+void CGroupWnd::RefreshTree(long lSelectedGroup) 
+{ 
+	m_lSelectedGroup = lSelectedGroup; 
+	m_Tree.FillTree(); 
+}
+void CGroupWnd::OnClose()
+{
+	ShowWindow(SW_HIDE);
+	::SetFocus(m_hwndNotify);
+}
+
+void CGroupWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
+{
+	if(nChar == VK_ESCAPE)
+	{
+		OnClose();
+		return;
+	}
+
+	CMagneticWnd::OnKeyDown(nChar, nRepCnt, nFlags);
+}
+
+void CGroupWnd::OnDestroy()
+{
+	CMagneticWnd::OnDestroy();
+}
+
+void CGroupWnd::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) 
+{
+	CWnd::OnActivate(nState, pWndOther, bMinimized);
+
+	if (nState == WA_INACTIVE)
+	{
+		HWND hNew = ::GetForegroundWindow();
+		DWORD OtherThreadID = GetWindowThreadProcessId(hNew, NULL);
+		DWORD ThisThreadID = GetWindowThreadProcessId(m_hWnd, NULL);
+
+		if(OtherThreadID != ThisThreadID)
+		{
+			::PostMessage(m_hwndNotify, NM_GROUP_TREE_MESSAGE, -1, TRUE);
+		}
+		else if(OtherThreadID == ThisThreadID && g_Opt.m_bGroupWndPinned == false)
+		{
+			OnClose();
+		}
+	}
+}

+ 55 - 0
GroupWnd.h

@@ -0,0 +1,55 @@
+#pragma once
+
+
+#include "DittoWindow.h"
+#include "GroupTree.h"
+#include "MagneticWnd.h"
+#include "AlphaBlend.h"
+
+class CGroupWnd : public CMagneticWnd
+{
+	DECLARE_DYNAMIC(CGroupWnd)
+
+public:
+	CGroupWnd();
+	virtual ~CGroupWnd();
+
+protected:
+	CDittoWindow m_DittoWindow;
+	CGroupTree m_Tree;
+	long m_lSelectedGroup;
+	HWND m_hwndNotify;
+	CToolBar m_ToolBar;
+	CSliderCtrl m_Transparency;
+	CAlphaBlend	m_Alpha;
+
+	void MoveControls();
+
+public:
+	void SetNotifyWnd(HWND hWnd)		{ m_hwndNotify = hWnd; m_Tree.SetNotificationWndEx(hWnd); }
+	void SetSelectedGroup(long lGroup)	{ m_lSelectedGroup = lGroup; }
+	void RefreshTree(long lSelectedGroup);
+
+protected:
+	DECLARE_MESSAGE_MAP()
+public:
+	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+	afx_msg void OnNcLButtonDown(UINT nHitTest, CPoint point);
+	afx_msg void OnNcLButtonUp(UINT nHitTest, CPoint point);
+	afx_msg void OnNcMouseMove(UINT nHitTest, CPoint point);
+	virtual BOOL PreTranslateMessage(MSG* pMsg);
+	afx_msg void OnNcLButtonDblClk(UINT nHitTest, CPoint point);
+	afx_msg void OnNcPaint();
+	afx_msg void OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp);
+	afx_msg UINT OnNcHitTest(CPoint point);
+	afx_msg void OnSize(UINT nType, int cx, int cy);
+	void OnRefresh();
+	void OnPin();
+	void OnNewGroup();
+	afx_msg void OnClose();
+	afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
+	afx_msg void OnDestroy();
+	void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
+};
+
+

+ 169 - 0
MagneticWnd.cpp

@@ -0,0 +1,169 @@
+#include "stdafx.h"
+#include ".\magneticwnd.h"
+
+bool bDoChange = true;
+
+CMagneticWnd::CMagneticWnd()
+{
+	m_bMovedAttachedWnd = false;
+	m_crLastMove.SetRectEmpty();
+	m_bHandleWindowPosChanging = true;
+}
+
+CMagneticWnd::~CMagneticWnd()
+{
+}
+
+
+BEGIN_MESSAGE_MAP(CMagneticWnd, CWnd)
+	ON_WM_MOVE()
+	ON_WM_WINDOWPOSCHANGING()
+END_MESSAGE_MAP()
+
+void CMagneticWnd::OnMove(int x, int y) 
+{
+	CWnd::OnMove(x, y);
+
+	if(m_bMovedAttachedWnd)
+	{
+		CRect crThis;
+		CRect crAttached;
+		long lDiff = 0;
+
+		GetWindowRect(crThis);
+
+		for(std::vector<CMagneticWnd*>::iterator Iter = m_AttachedWnd.begin(); Iter != m_AttachedWnd.end(); Iter++)
+		{
+			CMagneticWnd *pAttachedWnd = *Iter;
+			if(pAttachedWnd)
+			{
+				if(m_crLastMove.IsRectEmpty() == FALSE)
+				{
+					pAttachedWnd->GetWindowRect(crAttached);
+
+					long lXDiff = crThis.left - m_crLastMove.left;
+					long lYDiff = crThis.bottom - m_crLastMove.bottom;
+
+					crAttached.left += lXDiff;
+					crAttached.right += lXDiff;
+					crAttached.top += lYDiff;
+					crAttached.bottom += lYDiff;
+
+					pAttachedWnd->MoveMagneticWWnd(crAttached);
+				}
+			}
+		}
+
+		m_crLastMove = crThis;
+	}
+}
+
+void CMagneticWnd::MoveMagneticWWnd(LPCRECT lpRect, BOOL bRepaint)
+{
+	m_bHandleWindowPosChanging = false;
+	MoveWindow(lpRect, bRepaint);
+	m_bHandleWindowPosChanging = true;
+}
+
+
+void CMagneticWnd::OnWindowPosChanging(WINDOWPOS* lpwndpos)
+{
+	CWnd::OnWindowPosChanging(lpwndpos);
+
+	if(m_bHandleWindowPosChanging == false)
+		return;
+
+	for(std::vector<CMagneticWnd*>::iterator Iter = m_SnapToWnds.begin(); Iter != m_SnapToWnds.end(); Iter++)
+	{
+		CMagneticWnd *pOtherWnd = *Iter;
+
+		if(pOtherWnd != NULL && 
+			this->IsWindowVisible() && 
+			pOtherWnd->IsWindowVisible() &&
+			lpwndpos->x != 0 && lpwndpos->y != 0 && lpwndpos->cx != 0 && lpwndpos->cy != 0)
+		{
+			if(m_bMovedAttachedWnd && (IsWindowAttached(pOtherWnd)))
+				continue;
+
+			CRect rectParent;
+			pOtherWnd->GetWindowRect(rectParent);
+			bool bAttached = false;
+
+			// Snap left edge
+			if(abs(lpwndpos->x - rectParent.right) <= 15)
+			{
+				lpwndpos->x = rectParent.right;
+				bAttached = true;
+			}
+
+			// Snap right edge
+			if (abs(lpwndpos->x + lpwndpos->cx - rectParent.left) <= 15)
+			{
+				lpwndpos->x = rectParent.left - lpwndpos->cx;
+				bAttached = true;
+			}
+
+			// Snap to the bottom
+			if (abs(lpwndpos->y + lpwndpos->cy - rectParent.top) <= 15)
+			{
+				lpwndpos->y = rectParent.top - lpwndpos->cy;
+				bAttached = true;
+			} 
+
+			// Snap the top
+			if (abs(lpwndpos->y - rectParent.bottom) <= 15)
+			{
+				lpwndpos->y = rectParent.bottom;
+				bAttached = true;
+			}
+
+			pOtherWnd->SetWindowAttached(this, bAttached);
+			SetWindowAttached(pOtherWnd, bAttached);
+
+			if(m_bMovedAttachedWnd)
+			{
+				m_crLastMove.left = lpwndpos->x;
+				m_crLastMove.top = lpwndpos->y;
+				m_crLastMove.right = lpwndpos->x + lpwndpos->cx;
+				m_crLastMove.bottom = lpwndpos->y + lpwndpos->cy;
+			}
+		}
+	}
+}
+
+void CMagneticWnd::SetWindowAttached(CMagneticWnd *pOtherWnd, bool bAttach)
+{
+	bool bFound = false;
+	for(std::vector<CMagneticWnd*>::iterator Iter = m_AttachedWnd.begin(); Iter != m_AttachedWnd.end(); Iter++)
+	{
+		CMagneticWnd *pAttachedWnd = *Iter;
+		if(pAttachedWnd == pOtherWnd)
+		{
+			bFound = true;
+			if(bAttach == false)
+			{
+				m_AttachedWnd.erase(Iter);
+			}
+			break;
+		}
+	}
+	
+	if(bAttach && bFound == false)
+	{
+		m_AttachedWnd.push_back(pOtherWnd);
+	}
+}
+
+bool CMagneticWnd::IsWindowAttached(CMagneticWnd *pWnd)
+{
+	for(std::vector<CMagneticWnd*>::iterator Iter = m_AttachedWnd.begin(); Iter != m_AttachedWnd.end(); Iter++)
+	{
+		CMagneticWnd *pAttachedWnd = *Iter;
+		if(pAttachedWnd == pWnd)
+		{
+			return true;
+		}
+	}
+
+	return false;
+}

+ 29 - 0
MagneticWnd.h

@@ -0,0 +1,29 @@
+#pragma once
+
+#include <vector>
+
+class CMagneticWnd : public CWnd
+{
+public:
+	CMagneticWnd(void);
+	~CMagneticWnd(void);
+
+protected:
+	DECLARE_MESSAGE_MAP()
+	afx_msg void OnWindowPosChanging(WINDOWPOS* lpwndpos);
+	afx_msg void OnMove(int x, int y);
+
+	std::vector<CMagneticWnd*> m_SnapToWnds;
+	std::vector<CMagneticWnd*> m_AttachedWnd;
+	bool m_bMovedAttachedWnd;
+	CRect m_crLastMove;
+	bool m_bHandleWindowPosChanging;
+
+public:
+	void AddWindowToSnapTo(CMagneticWnd *pWnd)	{ m_SnapToWnds.push_back(pWnd); }
+	void SetWindowAttached(CMagneticWnd *pOther, bool bAttache);
+	bool IsWindowAttached(CMagneticWnd *pWnd);
+	void MoveMagneticWWnd(LPCRECT lpRect, BOOL bRepaint = TRUE);
+
+	void SetMoveAttachedWnds(bool bMove)	{ m_bMovedAttachedWnd = bMove; }
+};

+ 3 - 3
MoveToGroupDlg.cpp

@@ -51,7 +51,7 @@ BOOL CMoveToGroupDlg::OnInitDialog()
 {
 	CDialog::OnInitDialog();
 	
-	m_Tree.m_lSelectedFolderID = m_nSelectedGroup;
+	m_Tree.SetSelectedGroup(m_nSelectedGroup);
 	m_Tree.SetNotificationWndEx(m_hWnd);
 	m_Tree.FillTree();
 
@@ -79,7 +79,7 @@ LRESULT CMoveToGroupDlg::OnTreeSelect(WPARAM wParam, LPARAM lParam)
 
 void CMoveToGroupDlg::OnOK() 
 {
-	m_nSelectedGroup = m_Tree.GetSelectedTree();
+	m_nSelectedGroup = m_Tree.GetSelectedGroup();
 	
 	CDialog::OnOK();
 }
@@ -100,7 +100,7 @@ void CMoveToGroupDlg::OnButtonNewGroup()
 		
 	CString csName = Name.m_csName;
 	
-	long lID = NewGroupID(m_Tree.GetSelectedTree(), csName);
+	long lID = NewGroupID(m_Tree.GetSelectedGroup(), csName);
 	if(lID >= 0)
 	{
 		m_Tree.AddNode(csName, lID);

+ 33 - 21
OleClipSource.cpp

@@ -32,6 +32,8 @@ BOOL COleClipSource::DoDelayRender()
 	int count = types.GetSize();
 	for(int i=0; i < count; i++)
 		DelayRenderData(types[i]);
+
+	DelayRenderData(theApp.m_DittoIdsFormat);
 	
 	return count;
 }
@@ -193,33 +195,43 @@ BOOL COleClipSource::OnRenderGlobalData(LPFORMATETC lpFormatEtc, HGLOBAL* phGlob
 	}
 	else
 	{
-		CClip clip;
-
-		clip.LoadFormats(m_ClipIDs[0]);
-
-		CClipFormat *pDittoDelayCF_HDROP = clip.m_Formats.FindFormat(theApp.m_RemoteCF_HDROP);
-		CClipFormat *pCF_HDROP = clip.m_Formats.FindFormat(CF_HDROP);
-
-		if(pDittoDelayCF_HDROP && pCF_HDROP)
+		if(lpFormatEtc->cfFormat == theApp.m_DittoIdsFormat)
 		{
-			CDittoCF_HDROP *pData = (CDittoCF_HDROP*)GlobalLock(pDittoDelayCF_HDROP->m_hgData);
-			if(pData)
+			if(m_ClipIDs.GetCount() > 0)
 			{
-				CString csComputerName;
-				CString csIP;
-
-				CTextConvert::ConvertFromUTF8(pData->m_cIP, csIP);
-				CTextConvert::ConvertFromUTF8(pData->m_cComputerName, csComputerName);
-				
-				GlobalUnlock(pDittoDelayCF_HDROP->m_hgData);
-
-				CClient cl;
-				hData = cl.RequestCopiedFiles(*pCF_HDROP, csIP, csComputerName);
+				hData = NewGlobalP(m_ClipIDs.GetData(), m_ClipIDs.GetCount()*sizeof(m_ClipIDs[0]));
 			}
 		}
 		else
 		{
-			hData = m_ClipIDs.Render(lpFormatEtc->cfFormat);
+			CClip clip;
+
+			clip.LoadFormats(m_ClipIDs[0]);
+
+			CClipFormat *pDittoDelayCF_HDROP = clip.m_Formats.FindFormat(theApp.m_RemoteCF_HDROP);
+			CClipFormat *pCF_HDROP = clip.m_Formats.FindFormat(CF_HDROP);
+
+			if(pDittoDelayCF_HDROP && pCF_HDROP)
+			{
+				CDittoCF_HDROP *pData = (CDittoCF_HDROP*)GlobalLock(pDittoDelayCF_HDROP->m_hgData);
+				if(pData)
+				{
+					CString csComputerName;
+					CString csIP;
+
+					CTextConvert::ConvertFromUTF8(pData->m_cIP, csIP);
+					CTextConvert::ConvertFromUTF8(pData->m_cComputerName, csComputerName);
+					
+					GlobalUnlock(pDittoDelayCF_HDROP->m_hgData);
+
+					CClient cl;
+					hData = cl.RequestCopiedFiles(*pCF_HDROP, csIP, csComputerName);
+				}
+			}
+			else
+			{
+				hData = m_ClipIDs.Render(lpFormatEtc->cfFormat);
+			}
 		}
 
 		//Add to a cache of already rendered data

+ 52 - 0
Options.cpp

@@ -61,6 +61,7 @@ bool CGetSetOptions::m_bInConversion = false;
 bool CGetSetOptions::m_bFromIni = false;
 CString CGetSetOptions::m_csIniFileName;
 __int64 CGetSetOptions::nLastDbWriteTime = 0;
+bool CGetSetOptions::m_bGroupWndPinned = true;
 
 CGetSetOptions g_Opt;
 
@@ -141,6 +142,7 @@ void CGetSetOptions::LoadSettings()
 	m_bEnableDebugLogging = GetEnableDebugLogging();
 	m_bEnsureConnectToClipboard = GetEnsureConnectToClipboard();
 	m_bOutputDebugString = false;
+	m_bGroupWndPinned = GetGroupWndPinned();
 
 	GetExtraNetworkPassword(true);
 
@@ -1725,4 +1727,54 @@ BOOL CGetSetOptions::GetEditWordWrap()
 void CGetSetOptions::SetEditWordWrap(BOOL bSet)
 {
 	SetProfileLong(_T("EditWordWrap"), bSet);
+}
+
+BOOL CGetSetOptions::SetGroupWndSize(CSize size)
+{
+	BOOL bRet = SetProfileLong("GroupWndCX", size.cx);
+	bRet = SetProfileLong("GroupWndCY", size.cy);
+
+	return bRet;
+}
+
+void CGetSetOptions::GetGroupWndSize(CSize &size)
+{
+	size.cx = GetProfileLong("GroupWndCX", 0);
+	size.cy = GetProfileLong("GroupWndCY", 0);
+}
+
+BOOL CGetSetOptions::SetGroupWndPoint(CPoint point)
+{
+	BOOL bRet = SetProfileLong("GroupWndX", point.x);
+	bRet = SetProfileLong("GroupWndY", point.y);
+
+	return bRet;
+}
+
+void CGetSetOptions::GetGroupWndPoint(CPoint &point)
+{
+	point.x = GetProfileLong("GroupWndX", 0);
+	point.y = GetProfileLong("GroupWndY", 0);	
+}
+
+int CGetSetOptions::GetGroupWndTransparency()
+{
+	return GetProfileLong("GroupWndTrans", 0);
+}
+
+void CGetSetOptions::SetGroupWndTransparency(int nTrans)
+{
+	SetProfileLong("GroupWndTrans", nTrans);
+}
+
+bool CGetSetOptions::GetGroupWndPinned()
+{
+	return (GetProfileLong("GroupWndPinned", TRUE) == TRUE);
+
+}
+void CGetSetOptions::SetGroupWndPinned(bool bSet)
+{
+	m_bGroupWndPinned = (bSet == TRUE);
+	SetProfileLong("GroupWndPinned", bSet);
+
 }

+ 13 - 0
Options.h

@@ -356,6 +356,19 @@ public:
 
 	static BOOL		GetEditWordWrap();
 	static void		SetEditWordWrap(BOOL bSet);
+
+	static BOOL SetGroupWndSize(CSize size);
+	static void GetGroupWndSize(CSize &size);
+
+	static BOOL SetGroupWndPoint(CPoint point);
+	static void GetGroupWndPoint(CPoint &point);
+
+	static int GetGroupWndTransparency();
+	static void SetGroupWndTransparency(int nTrans);
+
+	static bool m_bGroupWndPinned;
+	static bool GetGroupWndPinned();
+	static void SetGroupWndPinned(bool bSet);
 };
 
 // global for easy access and for initialization of fast access variables

+ 65 - 111
QPasteWnd.cpp

@@ -48,7 +48,6 @@ static char THIS_FILE[] = __FILE__;
 CQPasteWnd::CQPasteWnd()
 {	
 	m_Title = QPASTE_TITLE;
-	m_bHideWnd = true;
 	m_strSQLSearch = "";
 	m_bAllowRepaintImmediately = true;
 	m_bHandleSearchTextChange = true;
@@ -107,8 +106,7 @@ BEGIN_MESSAGE_MAP(CQPasteWnd, CWndEx)
 	ON_COMMAND(ID_MENU_QUICKOPTIONS_DOUBLECLICKINGONCAPTION_ROLLUPWINDOW, OnMenuQuickoptionsDoubleclickingoncaptionRollupwindow)
 	ON_COMMAND(ID_MENU_QUICKOPTIONS_DOUBLECLICKINGONCAPTION_TOGGLESALWAYSSHOWDESCRIPTION, OnMenuQuickoptionsDoubleclickingoncaptionTogglesshowdescription)
 	ON_COMMAND(ID_MENU_QUICKOPTIONS_PROMPTFORNEWGROUPNAMES, OnMenuQuickoptionsPromptfornewgroupnames)
-	ON_BN_CLICKED(ID_SHOW_GROUPS_BOTTOM, OnShowGroupsBottom)
-	ON_BN_CLICKED(ID_SHOW_GROUPS_TOP, OnShowGroupsTop)
+	ON_BN_CLICKED(ID_SHOW_GROUPS_BOTTOM, OnShowGroups)
 	ON_COMMAND(ID_MENU_VIEWGROUPS, OnMenuViewgroups)
 	ON_COMMAND(ID_MENU_QUICKPROPERTIES_SETTONEVERAUTODELETE, OnMenuQuickpropertiesSettoneverautodelete)
 	ON_COMMAND(ID_MENU_QUICKPROPERTIES_AUTODELETE, OnMenuQuickpropertiesAutodelete)
@@ -233,11 +231,14 @@ int CQPasteWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
 		return -1;
 	}
 
-	((CWnd *)&m_GroupTree)->CreateEx(NULL, _T("SysTreeView32"), NULL, WS_BORDER|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS, CRect(0, 0, 100, 100), this, 0);
-	m_GroupTree.ModifyStyle(WS_CAPTION, WS_BORDER);
-	
-	m_GroupTree.SetNotificationWndEx(m_hWnd);
-	m_GroupTree.ShowWindow(SW_HIDE);
+	m_GroupWnd.CreateEx(NULL, _T("SysTreeView32"), NULL, WS_POPUP, CRect(0, 0, 0, 0), this, 0);
+	m_GroupWnd.SetNotifyWnd(m_hWnd);
+
+	CPoint Point;
+	CSize Size;
+	CGetSetOptions::GetQuickPastePoint(Point);
+	CGetSetOptions::GetQuickPasteSize(Size);
+	m_GroupWnd.MoveWindow(Point.x, Point.y, Size.cx, Size.cy);
 	
 	m_ShowGroupsFolderBottom.Create(NULL, WS_CHILD | BS_OWNERDRAW | WS_TABSTOP, CRect(0, 0, 0, 0), this, ID_SHOW_GROUPS_BOTTOM);
 	m_ShowGroupsFolderBottom.LoadBitmaps(IDB_CLOSED_FOLDER, IDB_CLOSED_FOLDER_PRESSED, IDB_CLOSED_FOLDER_FOCUSED);
@@ -297,7 +298,11 @@ int CQPasteWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
 	m_SearchingEvent = CreateEvent(NULL, TRUE, FALSE, _T(""));
 
 	AfxBeginThread(StartThread, this);
-		
+
+	AddWindowToSnapTo(&m_GroupWnd);
+	SetMoveAttachedWnds(true);
+	m_GroupWnd.AddWindowToSnapTo(this);
+
 	return 0;
 }
 
@@ -365,7 +370,7 @@ void CQPasteWnd::OnSetFocus(CWnd* pOldWnd)
 {
 	CWndEx::OnSetFocus(pOldWnd);
 
-	::SetWindowPos(m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_SHOWWINDOW);
+	//::SetWindowPos(m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_SHOWWINDOW);
 	
 	// Set the focus to the list control
 	if(::IsWindow(m_lstHeader.m_hWnd))
@@ -375,22 +380,23 @@ void CQPasteWnd::OnSetFocus(CWnd* pOldWnd)
 void CQPasteWnd::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) 
 {
 	CWndEx::OnActivate(nState, pWndOther, bMinimized);
-	
-	if(m_bHideWnd == false || m_lstHeader.GetToolTipHWnd() == pWndOther->GetSafeHwnd())
-		return;
-	
+		
 	if (nState == WA_INACTIVE)
 	{
-		if(!g_Opt.m_bShowPersistent)
+		HWND hNew = ::GetForegroundWindow();
+		DWORD OtherThreadID = GetWindowThreadProcessId(hNew, NULL);
+		DWORD ThisThreadID = GetWindowThreadProcessId(m_hWnd, NULL);
+
+		if(OtherThreadID != ThisThreadID)
 		{
 			HideQPasteWindow();
-		}
-		
-		//re register the global hot keys for the last ten
-		if(theApp.m_bAppExiting == false)
-			g_HotKeys.RegisterAll();
+			
+			//re register the global hot keys for the last ten
+			if(theApp.m_bAppExiting == false)
+				g_HotKeys.RegisterAll();
 
-		m_lstHeader.HidePopup();
+			m_lstHeader.HidePopup();
+		}
 	}
 	else if (nState == WA_ACTIVE || nState == WA_CLICKACTIVE)
 	{
@@ -418,7 +424,6 @@ BOOL CQPasteWnd::HideQPasteWindow()
 	theApp.ReleaseFocus();
 	
 	SetEvent(m_Events[THREAD_DESTROY_ACCELERATORS]);
-//	m_lstHeader.DestroyAndCreateAccelerator(FALSE);
 	
 	KillTimer(TIMER_FILL_CACHE);
 	
@@ -428,8 +433,14 @@ BOOL CQPasteWnd::HideQPasteWindow()
 	CGetSetOptions::SetQuickPasteSize(rect.Size());
 	CGetSetOptions::SetQuickPastePoint(rect.TopLeft());
 
+	//Save the group wnd size
+	m_GroupWnd.GetWindowRect(&rect);
+	CGetSetOptions::SetGroupWndSize(rect.Size());
+	CGetSetOptions::SetGroupWndPoint(rect.TopLeft());
+
 	// Hide the window when the focus is lost
 	ShowWindow(SW_HIDE);
+	m_GroupWnd.ShowWindow(SW_HIDE);
 	
 	//Reset the selection in the search combo
 	m_bHandleSearchTextChange = false;
@@ -469,8 +480,6 @@ BOOL CQPasteWnd::ShowQPasteWindow(BOOL bFillList)
 	
 	SetEvent(m_Events[THREAD_FILL_ACCELERATORS]);
 	
-	m_bHideWnd = true;
-	
 #ifdef AFTER_98
 	//Set the transparency
 	if(CGetSetOptions::GetEnableTransparency())
@@ -503,11 +512,7 @@ BOOL CQPasteWnd::ShowQPasteWindow(BOOL bFillList)
 	
 	// from now on, for interactive use, we can repaint immediately
 	m_bAllowRepaintImmediately = true;
-	
-	// always on top... for persistent showing (g_Opt.m_bShowPersistent)
-	// SHOWWINDOW was also integrated into this function rather than calling it separately
-	::SetWindowPos( m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_SHOWWINDOW );
-	
+		
 	return TRUE;
 }
 
@@ -614,12 +619,8 @@ BOOL CQPasteWnd::NewGroup( bool bGroupSelection )
 	CString csName("");
 	
 	if(g_Opt.m_bPrompForNewGroupName)
-	{
-		m_bHideWnd = false;
-		
+	{	
 		int nRet = Name.DoModal();
-	
-		m_bHideWnd = true;
 		
 		if(nRet == IDOK)
 			csName = Name.m_csName;
@@ -711,6 +712,13 @@ LRESULT CQPasteWnd::OnRefreshView(WPARAM wParam, LPARAM lParam)
 
 	theApp.m_FocusID = -1;
 
+	if (((int)wParam) > 0)
+	{
+		int nCaretPos = m_lstHeader.GetCaret();
+		if(nCaretPos >= 0 && theApp.m_FocusID < 0)
+			theApp.m_FocusID = m_lstHeader.GetItemData(nCaretPos);
+	}
+
 	if(theApp.m_bShowingQuickPaste)
 	{
 		FillList();
@@ -1209,8 +1217,6 @@ void CQPasteWnd::OnMenuToggleConnectCV()
 
 void CQPasteWnd::OnMenuProperties() 
 {	
-	m_bHideWnd = false;
-	
 	ARRAY IDs, Indexes;
 	m_lstHeader.GetSelectionItemData(IDs);
 	m_lstHeader.GetSelectionIndexes(Indexes);
@@ -1263,8 +1269,6 @@ void CQPasteWnd::OnMenuProperties()
 		m_lstHeader.SetFocus();
 		m_lstHeader.SetListPos(nRow);
 	}
-	
-	m_bHideWnd = true;
 }
 
 void CQPasteWnd::UpdateFont()
@@ -1382,7 +1386,7 @@ void CQPasteWnd::OnMenuQuickoptionsPromptfornewgroupnames()
 
 void CQPasteWnd::OnMenuViewgroups() 
 {
-	OnShowGroupsTop();
+	OnShowGroups();
 }
 
 void CQPasteWnd::OnMenuQuickpropertiesSettoneverautodelete() 
@@ -1609,8 +1613,6 @@ void CQPasteWnd::OnMenuSenttoPromptforip()
 
 void CQPasteWnd::OnMenuGroupsMovetogroup() 
 {
-	m_bHideWnd = false;
-
 	CMoveToGroupDlg dlg;
 
 	int nRet = dlg.DoModal();
@@ -1626,8 +1628,6 @@ void CQPasteWnd::OnMenuGroupsMovetogroup()
 		}
 		FillList();
 	}
-
-	m_bHideWnd = true;
 }
 
 void CQPasteWnd::OnMenuPasteplaintextonly() 
@@ -1680,8 +1680,6 @@ void CQPasteWnd::OnMenuExport()
 	ofn.lpstrDefExt = _T("dto");
 	ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_OVERWRITEPROMPT;
 
-	m_bHideWnd = false;
-
 	if(GetSaveFileName(&ofn)) 
 	{
 		using namespace nsPath;
@@ -1692,15 +1690,11 @@ void CQPasteWnd::OnMenuExport()
 		CString csFile(ofn.lpstrFile);
 		IDs.Export(csFile);
 	}
-
-	m_bHideWnd = true;
 }
 
 void CQPasteWnd::OnMenuImport()
 {
-	m_bHideWnd = false;
 	theApp.ImportClips(m_hWnd);
-	m_bHideWnd = true;
 }
 
 void CQPasteWnd::OnMenuHelp() 
@@ -1713,8 +1707,6 @@ void CQPasteWnd::OnMenuHelp()
 
 void CQPasteWnd::OnMenuQuickoptionsFont() 
 {
-	m_bHideWnd = false;
-
 	CFont *pFont = m_lstHeader.GetFont();
 	LOGFONT lf;
 	pFont->GetLogFont(&lf);
@@ -1724,8 +1716,6 @@ void CQPasteWnd::OnMenuQuickoptionsFont()
 		CGetSetOptions::SetFont(*dlg.m_cf.lpLogFont);
 		m_lstHeader.SetLogFont(*dlg.m_cf.lpLogFont);
 	}
-	
-	m_bHideWnd = true;
 }
 
 void CQPasteWnd::OnMenuQuickoptionsShowthumbnails() 
@@ -1795,8 +1785,6 @@ BOOL CQPasteWnd::SendToFriendbyPos(int nPos)
 {
 	CWaitCursor wait;
 
-	m_bHideWnd = false;
-
 	CClipIDs IDs;
 	long lCount = m_lstHeader.GetSelectedCount();
 	if(lCount <= 0)
@@ -1847,8 +1835,6 @@ BOOL CQPasteWnd::SendToFriendbyPos(int nPos)
 	}
 	CATCH_SQLITE_EXCEPTION	
 
-	m_bHideWnd = true;
-
 	return bRet;
 }
 
@@ -1863,12 +1849,7 @@ void CQPasteWnd::DeleteSelectedRows()
 {
 	if(g_Opt.GetPromptWhenDeletingClips())
 	{
-		bool bStartValue = m_bHideWnd;
-		m_bHideWnd = false;
-
 		int nRet = MessageBox(theApp.m_Language.GetString("Delete_Clip", "Delete Selected Clips?"), _T("Ditto"), MB_YESNO);
-	
-		m_bHideWnd = bStartValue;
 
 		if(nRet == IDNO)
 			return;
@@ -1993,11 +1974,11 @@ BOOL CQPasteWnd::PreTranslateMessage(MSG* pMsg)
 					}
 					else
 					{	
-						if(m_GroupTree.IsWindowVisible() == FALSE)
+	/*					if(m_GroupTree.IsWindowVisible() == FALSE)
 						{
 							HideQPasteWindow();
 							return TRUE;
-						}
+						}*/
 					}
 				}
 				break;
@@ -2021,7 +2002,7 @@ BOOL CQPasteWnd::PreTranslateMessage(MSG* pMsg)
 		case 'G':
 			if(GetKeyState(VK_CONTROL) & 0x8000)
 			{
-				OnShowGroupsTop();
+				OnShowGroups();
 				return TRUE;
 			}
 		case 'N':
@@ -2307,6 +2288,8 @@ void CQPasteWnd::OnNcLButtonDblClk(UINT nHitTest, CPoint point)
 		{
 		case TOGGLES_ALLWAYS_ON_TOP:
 			theApp.ShowPersistent( !g_Opt.m_bShowPersistent );
+			::SetWindowPos(m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_SHOWWINDOW);
+			
 			break;
 		case TOGGLES_ALLWAYS_SHOW_DESCRIPTION:
 			CGetSetOptions::SetAllwaysShowDescription(!g_Opt.m_bAllwaysShowDescription);
@@ -2326,8 +2309,6 @@ void CQPasteWnd::OnWindowPosChanging(WINDOWPOS* lpwndpos)
 {
 	CWndEx::OnWindowPosChanging(lpwndpos);
 
-//	m_lstHeader.HidePopup();
-	
 	CRect rcScreen;
 	
 	CRect cr(lpwndpos->x, lpwndpos->y, lpwndpos->x + lpwndpos->cx, lpwndpos->y + lpwndpos->cy);
@@ -2360,55 +2341,30 @@ void CQPasteWnd::OnWindowPosChanging(WINDOWPOS* lpwndpos)
 	}
 }
 
-void CQPasteWnd::OnShowGroupsTop()
-{
-	OnShowGroupsBottom();
-	return;
-	m_GroupTree.m_bHide = false;
-	m_bHideWnd = false;
-	
-	CRect crList;
-	m_lstHeader.GetWindowRect(crList);
-	
-	CRect cr(crList.left, crList.top, crList.left + crList.Width(), crList.top + 200);
-	
-	m_GroupTree.MoveWindow(cr);
-	m_GroupTree.m_lSelectedFolderID = theApp.m_GroupID;
-	m_GroupTree.FillTree();
-	m_GroupTree.ShowWindow(SW_SHOW);
-	
-	m_GroupTree.m_bHide = true;
-	m_bHideWnd = true;
-}
-
-void CQPasteWnd::OnShowGroupsBottom()
+void CQPasteWnd::OnShowGroups()
 {
-	m_GroupTree.m_bHide = false;
-	m_bHideWnd = false;
-	
-	CRect crWindow, crList;
-	m_lstHeader.GetWindowRect(crList);
-	GetWindowRect(crWindow);
-	
-	CRect cr(crWindow.left, crWindow.bottom, crWindow.left + crWindow.Width(), crWindow.bottom + 200);
-	
-	m_GroupTree.MoveWindow(cr);
-	m_GroupTree.m_lSelectedFolderID = theApp.m_GroupID;
-	m_GroupTree.FillTree();
-	m_GroupTree.ShowWindow(SW_SHOW);
-	
-	m_GroupTree.m_bHide = true;
-	m_bHideWnd = true;
+	if(m_GroupWnd.IsWindowVisible())
+	{
+		m_GroupWnd.ShowWindow(SW_HIDE);
+		SetFocus();
+	}
+	else
+	{
+		m_GroupWnd.RefreshTree(-1);
+		m_GroupWnd.ShowWindow(SW_SHOW);
+	}
 }
 
 LRESULT CQPasteWnd::OnGroupTreeMessage(WPARAM wParam, LPARAM lParam)
 {
-	m_bHideWnd = false;
-	
+	if(lParam == TRUE)
+	{
+		HideQPasteWindow();
+		return TRUE;
+	}
+
 	long lID = (long)wParam;
 	
-	m_GroupTree.ShowWindow(SW_HIDE);
-	
 	m_bHandleSearchTextChange = false;
 	m_Search.SetWindowText(_T(""));
 	m_bHandleSearchTextChange = true;
@@ -2436,8 +2392,6 @@ LRESULT CQPasteWnd::OnGroupTreeMessage(WPARAM wParam, LPARAM lParam)
 		HideQPasteWindow();
 	}
 	
-	m_bHideWnd = true;
-	
 	return TRUE;
 }
 

+ 4 - 4
QPasteWnd.h

@@ -14,6 +14,8 @@
 #include "GroupTree.h"
 #include "AlphaBlend.h"
 #include "Sqlite\CppSQLite3.h"
+#include "GroupWnd.h"
+
 #include <vector>
 #include <afxmt.h>
 
@@ -76,12 +78,10 @@ public:
 	CSearchEditBox	m_Search;
 	CFont			m_SearchFont;
 	CButton			m_btCancel;
-	bool			m_bHideWnd;
 	CString			m_strSQLSearch;
 	CGroupStatic	m_stGroup;
 	CFont			GroupFont;
 	CString			m_Title;
-	CGroupTree		m_GroupTree;
 	CBitmapButton	m_ShowGroupsFolderBottom;
 	CBitmapButton	m_ShowGroupsFolderTop;
 	CBitmapButton	m_BackButton;
@@ -94,6 +94,7 @@ public:
 	bool			m_bHandleSearchTextChange;
 	bool			m_bFoundClipToSetFocusTo;
 	long			m_lItemsPerPage;
+	CGroupWnd		m_GroupWnd;
 
 	std::vector<CMainTable> m_Cache;
 
@@ -181,8 +182,7 @@ protected:
 	afx_msg void OnMenuQuickoptionsDoubleclickingoncaptionRollupwindow();
 	afx_msg void OnMenuQuickoptionsDoubleclickingoncaptionTogglesshowdescription();
 	afx_msg void OnMenuQuickoptionsPromptfornewgroupnames();
-	afx_msg void OnShowGroupsBottom();
-	afx_msg void OnShowGroupsTop();
+	afx_msg void OnShowGroups();
 	afx_msg void OnMenuViewgroups();
 	afx_msg void OnMenuQuickpropertiesSettoneverautodelete();
 	afx_msg void OnMenuQuickpropertiesAutodelete();

+ 6 - 8
QuickPaste.cpp

@@ -29,8 +29,7 @@ CQuickPaste::~CQuickPaste()
 	{
 		delete m_pwndPaste;
 		m_pwndPaste = NULL;
-	}
-	
+	}	
 }
 
 void CQuickPaste::Create(CWnd *pParent)
@@ -92,13 +91,11 @@ void CQuickPaste::ShowQPasteWnd(CWnd *pParent, bool bAtPrevPos, bool bFromKeyboa
 		return;
 	}
 
-	if(theApp.m_bShowingQuickPaste)
+	if(g_Opt.m_bShowPersistent && m_pwndPaste != NULL)
 	{
-		if(g_Opt.m_bShowPersistent)
-		{
-			m_pwndPaste->MinMaxWindow(FORCE_MAX);
-			m_pwndPaste->SetForegroundWindow();
-		}
+		m_pwndPaste->ShowWindow(SW_SHOW);
+		m_pwndPaste->MinMaxWindow(FORCE_MAX);
+		m_pwndPaste->SetForegroundWindow();
 		return;
 	}
 	
@@ -172,6 +169,7 @@ void CQuickPaste::ShowQPasteWnd(CWnd *pParent, bool bAtPrevPos, bool bFromKeyboa
 	}
 	
 	// Show the window
+	m_pwndPaste->ShowWindow(SW_SHOW);
 	m_pwndPaste->ShowQPasteWindow(bReFillList);
 	m_pwndPaste->SetForegroundWindow();
 }

+ 8 - 3
Resource.h

@@ -29,6 +29,7 @@
 #define IDD_DIALOG_REMOTE_FILE          157
 #define IDR_FILE_COPY                   158
 #define IDD_OPTIONS_COPY_BUFFERS        166
+#define IDR_TOOLBAR_GROUP               167
 #define IDC_PATH                        1000
 #define IDC_GET_PATH                    1001
 #define IDC_SELECT_SOUND                1002
@@ -323,15 +324,19 @@
 #define ID_FIRST_NEWCLIP                32868
 #define ID_BUTTON_SAVE_CLOSE_CLIPBOARD  32869
 #define ID_FIRST_COPYTODEVICE           32870
+#define ID_BUTTON_REFRESH_GROUP         32872
+#define ID_BUTTON_PIN                   32874
+#define ID_BUTTON32875                  32875
+#define ID_BUTTON_NEW_GROUP             32875
 
 // Next default values for new objects
 // 
 #ifdef APSTUDIO_INVOKED
 #ifndef APSTUDIO_READONLY_SYMBOLS
 #define _APS_3D_CONTROLS                     1
-#define _APS_NEXT_RESOURCE_VALUE        167
-#define _APS_NEXT_COMMAND_VALUE         32871
-#define _APS_NEXT_CONTROL_VALUE         2091
+#define _APS_NEXT_RESOURCE_VALUE        169
+#define _APS_NEXT_COMMAND_VALUE         32876
+#define _APS_NEXT_CONTROL_VALUE         2092
 #define _APS_NEXT_SYMED_VALUE           101
 #endif
 #endif

+ 14 - 14
WndEx.cpp

@@ -44,7 +44,7 @@ void CWndEx::GetWindowRectEx(LPRECT lpRect)
 		return;
 	}
 	
-	CWnd::GetWindowRect(lpRect);
+	CMagneticWnd::GetWindowRect(lpRect);
 }
 
 bool CWndEx::SetCaptionColors( COLORREF left, COLORREF right )
@@ -54,7 +54,7 @@ bool CWndEx::SetCaptionColors( COLORREF left, COLORREF right )
 	return true;
 }
 
-BEGIN_MESSAGE_MAP(CWndEx, CWnd)
+BEGIN_MESSAGE_MAP(CWndEx, CMagneticWnd)
 //{{AFX_MSG_MAP(CWndEx)
 	ON_WM_CREATE()
 	ON_WM_NCPAINT()
@@ -99,7 +99,7 @@ BOOL CWndEx::Create(const CRect& crStart, CWnd* pParentWnd)
 
 int CWndEx::OnCreate(LPCREATESTRUCT lpCreateStruct) 
 {
-	if (CWnd::OnCreate(lpCreateStruct) == -1)
+	if (CMagneticWnd::OnCreate(lpCreateStruct) == -1)
 		return -1;
 	
 	m_DittoWindow.DoCreate(this);
@@ -156,7 +156,7 @@ void CWndEx::OnNcPaint()
 
 void CWndEx::OnNcCalcSize(BOOL bCalcValidRects, NCCALCSIZE_PARAMS FAR* lpncsp) 
 {
-	CWnd::OnNcCalcSize(bCalcValidRects, lpncsp);
+	CMagneticWnd::OnNcCalcSize(bCalcValidRects, lpncsp);
 	
 	m_DittoWindow.DoNcCalcSize(bCalcValidRects, lpncsp);
 }
@@ -165,7 +165,7 @@ UINT CWndEx::OnNcHitTest(CPoint point)
 {
 	UINT Ret = m_DittoWindow.DoNcHitTest(this, point);
 	if(Ret == -1)
-		return CWnd::OnNcHitTest(point);
+		return CMagneticWnd::OnNcHitTest(point);
 
 	return Ret;
 }
@@ -174,7 +174,7 @@ void CWndEx::OnNcLButtonDown(UINT nHitTest, CPoint point)
 {
 	m_DittoWindow.DoNcLButtonDown(this, nHitTest, point);
 
-	CWnd::OnNcLButtonDown(nHitTest, point);
+	CMagneticWnd::OnNcLButtonDown(nHitTest, point);
 }
 
 void CWndEx::OnNcLButtonUp(UINT nHitTest, CPoint point) 
@@ -189,7 +189,7 @@ void CWndEx::OnNcLButtonUp(UINT nHitTest, CPoint point)
 		return;
 	}
 	
-	CWnd::OnNcLButtonUp(nHitTest, point);
+	CMagneticWnd::OnNcLButtonUp(nHitTest, point);
 }
 
 void CWndEx::MinMaxWindow(long lOption)
@@ -307,19 +307,19 @@ void CWndEx::OnNcMouseMove(UINT nHitTest, CPoint point)
 		m_bMaxSetTimer = true;
 	}
 	
-	CWnd::OnNcMouseMove(nHitTest, point);
+	CMagneticWnd::OnNcMouseMove(nHitTest, point);
 }
 
 BOOL CWndEx::PreTranslateMessage(MSG* pMsg) 
 {
 	m_DittoWindow.DoPreTranslateMessage(pMsg);
 	
-	return CWnd::PreTranslateMessage(pMsg);
+	return CMagneticWnd::PreTranslateMessage(pMsg);
 }
 
 BOOL CWndEx::OnEraseBkgnd(CDC* pDC) 
 {
-	return CWnd::OnEraseBkgnd(pDC);
+	return CMagneticWnd::OnEraseBkgnd(pDC);
 }
 
 void CWndEx::OnTimer(UINT nIDEvent)
@@ -374,12 +374,12 @@ void CWndEx::OnTimer(UINT nIDEvent)
 		}
 	}
 	
-	CWnd::OnTimer(nIDEvent);
+	CMagneticWnd::OnTimer(nIDEvent);
 }
 
 void CWndEx::OnWindowPosChanging(WINDOWPOS* lpwndpos)
 {
-	CWnd::OnWindowPosChanging(lpwndpos);
+	CMagneticWnd::OnWindowPosChanging(lpwndpos);
 	
 	if(m_bMaxSetTimer)
 	{
@@ -391,7 +391,7 @@ void CWndEx::OnWindowPosChanging(WINDOWPOS* lpwndpos)
 
 void CWndEx::OnSize(UINT nType, int cx, int cy)
 {
-	CWnd::OnSize(nType, cx, cy);
+	CMagneticWnd::OnSize(nType, cx, cy);
 	
 	m_DittoWindow.DoSetRegion(this);
 }
@@ -416,7 +416,7 @@ void CWndEx::OnInitMenuPopup(CMenu *pPopupMenu, UINT nIndex,BOOL bSysMenu)
 	}
     else if ((hParentMenu = ::GetMenu(m_hWnd)) != NULL)
     {
-        CWnd* pParent = this;
+        CMagneticWnd* pParent = this;
 		// Child windows don't have menus--need to go to the top!
         if (pParent != NULL &&
 			(hParentMenu = ::GetMenu(pParent->m_hWnd)) != NULL)

+ 2 - 1
WndEx.h

@@ -8,12 +8,13 @@
 //
 
 #include "DittoWindow.h"
+#include "MagneticWnd.h"
 
 #define	SWAP_MIN_MAX			1
 #define FORCE_MIN				2
 #define FORCE_MAX				3
 
-class CWndEx : public CWnd
+class CWndEx : public CMagneticWnd
 {
 // Construction
 public: