⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dockingcont.cpp.svn-base

📁 Notepad++ is a generic source code editor (it tries to be anyway) and Notepad replacement written in
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
//this file is part of docking functionality for Notepad++
//Copyright (C)2006 Jens Lorenz <jens.plugin.npp@gmx.de>
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

#include "dockingResource.h"
#include "math.h"
#include "Docking.h"
#include "DockingCont.h"
#include "DropData.h"
#include "SplitterContainer.h"
#include "WindowInterface.h"
#include "SysMsg.h"
#include <Commctrl.h>
#include <shlobj.h>
#include "common_func.h"

#ifndef WH_MOUSE_LL
#define WH_MOUSE_LL 14
#endif

static HWND		hWndServer		= NULL;
static HHOOK	hookMouse		= NULL;

static LRESULT CALLBACK hookProcMouse(UINT nCode, WPARAM wParam, LPARAM lParam)
{
    if(nCode < 0)
    {
		::CallNextHookEx(hookMouse, nCode, wParam, lParam);
        return 0;
    }

    switch (wParam)
    {
		case WM_MOUSEMOVE:
		case WM_NCMOUSEMOVE:
			::PostMessage(hWndServer, wParam, 0, 0);
			break;
		case WM_LBUTTONUP:
		case WM_NCLBUTTONUP:
			::PostMessage(hWndServer, wParam, 0, 0);
			break;
        default: 
			break;
	}

	return ::CallNextHookEx(hookMouse, nCode, wParam, lParam);
}


DockingCont::DockingCont(void)
{
	_isMouseOver		= FALSE;
	_isMouseClose		= FALSE;
	_isMouseDown		= FALSE;
	_isFloating			= false;
	_isTopCaption		= CAPTION_TOP;
	_dragFromTab		= FALSE;
	_hContTab			= NULL;
	_hDefaultTabProc	= NULL;
	_beginDrag			= FALSE;
	_prevItem			= 0;
	_hFont				= NULL;
	_vTbData.clear();
}

DockingCont::~DockingCont()
{
	::DeleteObject(_hFont);
}


void DockingCont::doDialog(bool willBeShown, bool isFloating)
{
	if (!isCreated())
	{
		create(IDD_CONTAINER_DLG);

		_isFloating  = isFloating;

		if (_isFloating == true)
		{
			::SetWindowLong(_hSelf, GWL_STYLE, POPUP_STYLES);
			::SetWindowLong(_hSelf, GWL_EXSTYLE, POPUP_EXSTYLES);
			::ShowWindow(_hCaption, SW_HIDE);
		}
		else
		{
			::SetWindowLong(_hSelf, GWL_STYLE, CHILD_STYLES);
			::SetWindowLong(_hSelf, GWL_EXSTYLE, CHILD_EXSTYLES);
			::ShowWindow(_hCaption, SW_SHOW);
		}

		_hFont = ::CreateFont(14, 0, 0, 0,
				 FW_NORMAL, FALSE, FALSE, FALSE,
				 ANSI_CHARSET, OUT_DEFAULT_PRECIS,
				 CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
				 DEFAULT_PITCH | FF_ROMAN,
				 "MS Shell Dlg");
	}

	display(willBeShown);
}


tTbData* DockingCont::createToolbar(tTbData data, Window **ppWin)
{
	tTbData *pTbData = new tTbData;

	*pTbData = data;

	/* force window style of client window */
	::SetWindowLong(pTbData->hClient, GWL_STYLE, CHILD_STYLES);
	::SetWindowLong(pTbData->hClient, GWL_EXSTYLE, CHILD_EXSTYLES);

	/* restore position if plugin is in floating state */
	if ((_isFloating == true) && (::SendMessage(_hContTab, TCM_GETITEMCOUNT, 0, 0) == 0))
	{
		reSizeToWH(pTbData->rcFloat);
	}

	/* set attached child window */
    ::SetParent(pTbData->hClient, ::GetDlgItem(_hSelf, IDC_CLIENT_TAB));

	/* set names for captions and view toolbar */
	viewToolbar(pTbData);

	/* attach to list */
	_vTbData.push_back(pTbData);

	return pTbData;
}


tTbData DockingCont::destroyToolbar(tTbData TbData)
{
	int			iItemCnt	= 0;

	/* remove from list */
	for (size_t iTb = 0; iTb < _vTbData.size(); iTb++)
	{
		if (_vTbData[iTb]->hClient == TbData.hClient)
		{
			/* remove tab */
			hideToolbar(_vTbData[iTb]);

			/* release client from container */
			::SetParent(TbData.hClient, NULL);

			/* free resources */
			delete _vTbData[iTb];
			vector<tTbData*>::iterator itr = _vTbData.begin() + iTb;
			_vTbData.erase(itr);
		}
	}
	return TbData;
}


tTbData* DockingCont::findToolbarByWnd(HWND hClient)
{
	tTbData*	pTbData		= NULL;

	/* find entry by handle */
	for (size_t iTb = 0; iTb < _vTbData.size(); iTb++)
	{
		if (hClient == _vTbData[iTb]->hClient)
		{
			pTbData = _vTbData[iTb];
		}
	}
	return pTbData;
}

tTbData* DockingCont::findToolbarByName(char* pszName)
{
	tTbData*	pTbData		= NULL;

	/* find entry by handle */
	for (size_t iTb = 0; iTb < _vTbData.size(); iTb++)
	{
		if (strcmp(pszName, _vTbData[iTb]->pszName) == 0)
		{
			pTbData = _vTbData[iTb];
		}
	}
	return pTbData;
}

void DockingCont::setActiveTb(tTbData* pTbData)
{
	int iItem = SearchPosInTab(pTbData);
	setActiveTb(iItem);
}

void DockingCont::setActiveTb(int iItem)
{
	//if ((iItem != -1) && (iItem < ::SendMessage(_hContTab, TCM_GETITEMCOUNT, 0, 0)))
	if (iItem < ::SendMessage(_hContTab, TCM_GETITEMCOUNT, 0, 0))
	{
		SelectTab(iItem);
	}
}

int DockingCont::getActiveTb(void)
{
	return ::SendMessage(_hContTab, TCM_GETCURSEL, 0, 0);
}

tTbData* DockingCont::getDataOfActiveTb(void)
{
	tTbData*	pTbData	= NULL;
	int			iItem	= getActiveTb();

	if (iItem != -1)
	{
		TCITEM	tcItem	= {0};

		tcItem.mask		= TCIF_PARAM;
		::SendMessage(_hContTab, TCM_GETITEM, iItem, (LPARAM)&tcItem);
		pTbData = (tTbData*)tcItem.lParam;
	}

	return pTbData;
}

vector<tTbData*> DockingCont::getDataOfVisTb(void)
{
	vector<tTbData*>	vTbData;
	TCITEM				tcItem		= {0};
	int					iItemCnt	= ::SendMessage(_hContTab, TCM_GETITEMCOUNT, 0, 0);

	tcItem.mask	= TCIF_PARAM;

	for(int iItem = 0; iItem < iItemCnt; iItem++)
	{
		::SendMessage(_hContTab, TCM_GETITEM, iItem, (LPARAM)&tcItem);
		vTbData.push_back((tTbData*)tcItem.lParam);
	}
	return vTbData;
}

bool DockingCont::isTbVis(tTbData* data)
{
	bool				bRet		= false;
	TCITEM				tcItem		= {0};
	int					iItemCnt	= ::SendMessage(_hContTab, TCM_GETITEMCOUNT, 0, 0);

	tcItem.mask	= TCIF_PARAM;

	for(int iItem = 0; iItem < iItemCnt; iItem++)
	{
		::SendMessage(_hContTab, TCM_GETITEM, iItem, (LPARAM)&tcItem);
		if (((tTbData*)tcItem.lParam) == data)
		{
			bRet = true;
			break;
		}
	}
	return bRet;
}


/*********************************************************************************
 *    Process function of caption bar
 */
LRESULT DockingCont::runProcCaption(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
	switch (Message)
	{
		case WM_LBUTTONDOWN:
		{
			_isMouseDown = TRUE;

			if (isInRect(hwnd, LOWORD(lParam), HIWORD(lParam)) == posClose)
			{
				_isMouseClose	= TRUE;
				_isMouseOver	= TRUE;

				/* start hooking */
				hWndServer		= _hCaption;
				if (GetVersion() & 0x80000000)
				{
					hookMouse	= ::SetWindowsHookEx(WH_MOUSE, (HOOKPROC)hookProcMouse, _hInst, 0);
				}
				else
				{
					hookMouse	= ::SetWindowsHookEx(WH_MOUSE_LL, (HOOKPROC)hookProcMouse, _hInst, 0);
				}

				if (!hookMouse)
				{
					DWORD dwError = ::GetLastError();
					TCHAR  str[128];
					::wsprintf(str, "GetLastError() returned %lu", dwError);
					::MessageBox(NULL, str, "SetWindowsHookEx(MOUSE) failed", MB_OK | MB_ICONERROR);
				}
				::RedrawWindow(hwnd, NULL, NULL, TRUE);
			}

			focusClient();
			return TRUE;
		}
		case WM_LBUTTONUP:
		{
			_isMouseDown = FALSE;
			if (_isMouseClose == TRUE)
			{
				/* end hooking */
				::UnhookWindowsHookEx(hookMouse);

				if (_isMouseOver == TRUE)
				{
					doClose();
				}
				_isMouseClose	= FALSE;
				_isMouseOver	= FALSE;
			}
			
			focusClient();
			return TRUE;
		}
		case WM_LBUTTONDBLCLK:
		{
			if (isInRect(hwnd, LOWORD(lParam), HIWORD(lParam)) == posCaption)
				::SendMessage(_hParent, DMM_FLOATALL, 0, (LPARAM)this);

			focusClient();
			return TRUE;
		}
		case WM_MOUSEMOVE:
		{
			POINT	pt			= {0};

			/* get correct cursor position */
			::GetCursorPos(&pt);
			::ScreenToClient(_hCaption, &pt);

			if (_isMouseDown == TRUE)
			{
				if (_isMouseClose == FALSE)
				{
                    /* keep sure that button is still down and within caption */
                    if ((wParam == MK_LBUTTON) && (isInRect(hwnd, pt.x, pt.y) == posCaption))
                    {
    					_dragFromTab = FALSE;
    					NotifyParent(DMM_MOVE);
    					_isMouseDown = FALSE;
                    }
                    else
                    {
                        _isMouseDown = FALSE;
                    }
				}
				else
				{
					BOOL    isMouseOver	= _isMouseOver;
					_isMouseOver = (isInRect(hwnd, pt.x, pt.y) == posClose ? TRUE : FALSE);

					/* if state is changed draw new */
					if (_isMouseOver != isMouseOver)
					{
						::SetFocus(NULL);
						::RedrawWindow(hwnd, NULL, NULL, TRUE);
					}
				}
			}
			return TRUE;
		}
		case WM_SIZE:
		{
			::GetWindowRect(hwnd, &_rcCaption);
			ScreenToClient(hwnd, &_rcCaption);
			break;
		}
		case WM_SETTEXT:
		{
			::RedrawWindow(hwnd, NULL, NULL, TRUE);
			return TRUE;
		}
		default:
			break;
	}

	return ::CallWindowProc(_hDefaultCaptionProc, hwnd, Message, wParam, lParam);
}

void DockingCont::drawCaptionItem(DRAWITEMSTRUCT *pDrawItemStruct)
{
	RECT		rc		= pDrawItemStruct->rcItem;
	HDC			hDc		= pDrawItemStruct->hDC;
	HBRUSH		bgbrush	= ::CreateSolidBrush(::GetSysColor(COLOR_BTNFACE));
	HPEN		hPen	= ::CreatePen(PS_SOLID, 1, RGB(0xC0,0xC0,0xC0));
	BITMAP		bmp		= {0};
	HBITMAP		hBmpCur	= NULL;
	HBITMAP		hBmpOld = NULL;
	HBITMAP		hBmpNew	= NULL;
	UINT		length  = strlen(_pszCaption);

	int nSavedDC = ::SaveDC(hDc);

	/* begin with paint */
	::SetBkMode(hDc, TRANSPARENT);

	/* set text and/or caption grid */
	if (_isTopCaption == TRUE)
	{
		SIZE	size;

		/* fill background */
		rc.left		+= 1;
		rc.top		+= 2;
		rc.right	-= 16;
		::FillRect(hDc, &rc, bgbrush);

		/* draw text */
		::SelectObject(hDc, _hFont);
		::ExtTextOut(hDc, rc.left, 2, ETO_CLIPPED, &rc, _pszCaption, length, NULL);

		/* calculate beginning of grid lines */
		GetTextExtentPoint32(hDc, _pszCaption, length, &size);
		rc.left += (size.cx + 2);

		if (rc.left < rc.right)
		{
			/* draw grid lines */
			HPEN	hOldPen = (HPEN)::SelectObject(hDc, hPen);

			MoveToEx(hDc, rc.left , rc.top+1 , NULL);
			LineTo  (hDc, rc.right, rc.top+1 );
			MoveToEx(hDc, rc.left , rc.top+4 , NULL);
			LineTo  (hDc, rc.right, rc.top+4 );
			MoveToEx(hDc, rc.left , rc.top+7 , NULL);
			LineTo  (hDc, rc.right, rc.top+7 );
			MoveToEx(hDc, rc.left , rc.top+10, NULL);
			LineTo  (hDc, rc.right, rc.top+10);
		}
	}
	else
	{
		/* create local font for vertical draw */
		HFONT	hFont;
		SIZE	size;

		/* fill background */
		rc.left		+= 2;
		rc.top		+= 16;
		rc.bottom	-= 1;
		::FillRect(hDc, &rc, bgbrush);

		/* draw text */
		hFont = ::CreateFont(12, 0, 90 * 10, 0,
			 FW_NORMAL, FALSE, FALSE, FALSE,
			 ANSI_CHARSET, OUT_DEFAULT_PRECIS,
			 CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
			 DEFAULT_PITCH | FF_ROMAN,
			 "MS Shell Dlg");
		::SelectObject(hDc, hFont);
		::ExtTextOut(hDc, 3, rc.bottom, ETO_CLIPPED, &rc, _pszCaption, length, NULL);

		/* calculate beginning of grid lines */
		GetTextExtentPoint32(hDc, _pszCaption, length, &size);
		rc.bottom -= (size.cx + 2);

		::DeleteObject(hFont);

		if (rc.bottom < rc.top)
		{
			/* draw grid lines */
			HPEN	hOldPen = (HPEN)::SelectObject(hDc, hPen);
			MoveToEx(hDc, rc.left+1 , rc.top, NULL);
			LineTo  (hDc, rc.left+1 , rc.bottom);
			MoveToEx(hDc, rc.left+4 , rc.top, NULL);
			LineTo  (hDc, rc.left+4 , rc.bottom);
			MoveToEx(hDc, rc.left+7 , rc.top, NULL);
			LineTo  (hDc, rc.left+7 , rc.bottom);
			MoveToEx(hDc, rc.left+10, rc.top, NULL);
			LineTo  (hDc, rc.left+10, rc.bottom);
		}
	}
	::DeleteObject(hPen);
	::DeleteObject(bgbrush);

	/* draw button */
	HDC			dcMem		= ::CreateCompatibleDC(NULL);

	/* select correct bitmap */
	if ((_isMouseOver == TRUE) && (_isMouseDown == TRUE))
		hBmpCur = ::LoadBitmap(_hInst, MAKEINTRESOURCE(IDB_CLOSE_DOWN));
	else
		hBmpCur = ::LoadBitmap(_hInst, MAKEINTRESOURCE(IDB_CLOSE_UP));

	/* blit bitmap into the destination */
	::GetObject(hBmpCur, sizeof(bmp), &bmp);
	hBmpOld = (HBITMAP)::SelectObject(dcMem, hBmpCur);
	hBmpNew = ::CreateCompatibleBitmap(dcMem, bmp.bmWidth, bmp.bmHeight);

	rc = pDrawItemStruct->rcItem;
	::SelectObject(hDc, hBmpNew);

	if (_isTopCaption == TRUE)
		::BitBlt(hDc, rc.right-bmp.bmWidth-2, 2, bmp.bmWidth, bmp.bmHeight, dcMem, 0, 0, SRCCOPY);
	else
		::BitBlt(hDc, 2, 2, bmp.bmWidth, bmp.bmHeight, dcMem, 0, 0, SRCCOPY);

	::SelectObject(dcMem, hBmpOld);
	::DeleteObject(hBmpCur);
	::DeleteObject(hBmpNew);
	::DeleteDC(dcMem);

	::RestoreDC(hDc, nSavedDC);
}

eMousePos DockingCont::isInRect(HWND hwnd, int x, int y)
{
	RECT		rc;
	eMousePos	ret	= posOutside;

	::GetWindowRect(hwnd, &rc);
	ScreenToClient(hwnd, &rc);

	if (_isTopCaption == TRUE)
	{
		if ((x > rc.left) && (x < rc.right-16) && (y > rc.top) && (y < rc.bottom))
		{
			ret = posCaption;
		}
		else if ((x > rc.right-14) && (x < rc.right-2) && (y > rc.top+2) && (y < rc.bottom-2))
		{
			ret = posClose;
		}
	}
	else
	{
		if ((x > rc.left) && (x < rc.right) && (y > rc.top+16) && (y < rc.bottom))
		{
			ret = posCaption;
		}
		else if ((x > rc.left-2) && (x < rc.right-2) && (y > rc.top+2) && (y < rc.top+14))
		{
			ret = posClose;
		}
	}

	return ret;
}


/*********************************************************************************
 *    Process function of tab
 */
LRESULT DockingCont::runProcTab(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
{
	switch (Message)
	{
		case WM_LBUTTONDOWN:
		{
			_beginDrag	= TRUE;
			return TRUE;
		}
		case WM_LBUTTONUP:
		{
			int				iItem	= 0;
			TCHITTESTINFO	info	= {0};

			/* get selected sub item */
			info.pt.x = LOWORD(lParam);
			info.pt.y = HIWORD(lParam);
			iItem = ::SendMessage(hwnd, TCM_HITTEST, 0, (LPARAM)&info);

			SelectTab(iItem);
			_beginDrag = FALSE;
			return TRUE;
		}
		case WM_LBUTTONDBLCLK:
		{
			NotifyParent((_isFloating == true)?DMM_DOCK:DMM_FLOAT);
			return TRUE;
		}
		case WM_MBUTTONUP:
		{
			int				iItem	= 0;
			TCITEM			tcItem	= {0};
			TCHITTESTINFO	info	= {0};

			/* get selected sub item */
			info.pt.x = LOWORD(lParam);
			info.pt.y = HIWORD(lParam);
			iItem = ::SendMessage(hwnd, TCM_HITTEST, 0, (LPARAM)&info);

			SelectTab(iItem);

			/* get data and hide toolbar */
			tcItem.mask		= TCIF_PARAM;
			::SendMessage(hwnd, TCM_GETITEM, iItem, (LPARAM)&tcItem);

			/* notify child windows */
			if (NotifyParent(DMM_CLOSE) == 0)
			{
				hideToolbar((tTbData*)tcItem.lParam);
			}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -