ncgutter.h

来自「管理项目进度工具的原代码」· C头文件 代码 · 共 249 行

H
249
字号
// NcGutter.h: interface for the CNcGutter class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_NCGUTTER_H__A356B1B6_1B4D_4013_8F39_8D9D2442E149__INCLUDED_)
#define AFX_NCGUTTER_H__A356B1B6_1B4D_4013_8F39_8D9D2442E149__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "subclass.h"
#include "hottracker.h"
#include <afxtempl.h>

// wParam == ctrl id
const UINT WM_NCG_GETFIRSTVISIBLETOPLEVELITEM = ::RegisterWindowMessage("WM_NCG_GETFIRSTVISIBLETOPLEVELITEM");
const UINT WM_NCG_GETNEXTITEM = ::RegisterWindowMessage("WM_NCG_GETNEXTITEM");
const UINT WM_NCG_POSTDRAWITEM = ::RegisterWindowMessage("WM_NCG_POSTDRAWITEM");
const UINT WM_NCG_DRAWITEM = ::RegisterWindowMessage("WM_NCG_DRAWITEM");
const UINT WM_NCG_RECALCCOLWIDTH = ::RegisterWindowMessage("WM_NCG_RECALCCOLWIDTH");
const UINT WM_NCG_WIDTHCHANGE = ::RegisterWindowMessage("WM_NCG_WIDTHCHANGE");
const UINT WM_NCG_POSTNCDRAW = ::RegisterWindowMessage("WM_NCG_POSTNCDRAW");
const UINT WM_NCG_GETITEMRECT = ::RegisterWindowMessage("WM_NCG_GETITEMRECT");
const UINT WM_NCG_GETFIRSTCHILDITEM = ::RegisterWindowMessage("WM_NCG_GETFIRSTCHILDITEM");
const UINT WM_NCG_GETPARENTITEM = ::RegisterWindowMessage("WM_NCG_GETPARENTITEM");
const UINT WM_NCG_HITTEST = ::RegisterWindowMessage("WM_NCG_HITTEST");
const UINT WM_NCG_ISITEMSELECTED = ::RegisterWindowMessage("WM_NCG_ISITEMSELECTED");
const UINT WM_NCG_GETSELECTEDCOUNT = ::RegisterWindowMessage("WM_NCG_GETSELECTEDCOUNT");
const UINT WM_NCG_NOTIFYITEMCLICK = ::RegisterWindowMessage("WM_NCG_NOTIFYITEMCLICK"); 
const UINT WM_NCG_NOTIFYHEADERCLICK = ::RegisterWindowMessage("WM_NCG_NOTIFYHEADERCLICK"); 
const UINT WM_NCG_GETCURSOR = ::RegisterWindowMessage("WM_NCG_GETCURSOR"); 
const UINT WM_NCG_WANTREDRAW = ::RegisterWindowMessage("WM_NCG_WANTREDRAW"); 
const UINT WM_NCG_WANTRECALC = ::RegisterWindowMessage("WM_NCG_WANTRECALC"); 

const int NCG_COLPADDING = 3;

enum 
{
	NCGS_RIGHTCOLUMNS		= 0x01,
	NCGS_DOUBLEBUFFERCLIENT = 0x02,
	NCGS_SHOWHEADER			= 0x04,
};

struct NCGDRAWITEM
{
	NCGDRAWITEM() { pDC = NULL; dwItem = dwParentItem = 0; nColID = 0; rItem = NULL; nLevel = 0; 
					nItemPos = 0; rWindow = NULL; bSelected = FALSE; nTextAlign = DT_LEFT; }

	CDC* pDC;
	DWORD dwItem;
	DWORD dwParentItem; // always zero unless control responds to WM_NCG_GETFIRSTCHILDITEM
	int nColID;
	const CRect* rItem;
	int nLevel;			// always zero unless control responds to WM_NCG_GETFIRSTCHILDITEM
	int nItemPos;
	const CRect* rWindow;
	BOOL bSelected;
	UINT nTextAlign;
};

struct NCGRECALCCOLUMN
{
	int nColID;
	CDC* pDC;
	UINT nWidth; // fill in on return
};

struct NCGITEMRECT
{
	NCGITEMRECT() { dwItem = 0; ::SetRectEmpty(&rItem); }

	DWORD dwItem;
	RECT rItem; // return client coords
};

struct NCGITEMCLICK
{
	DWORD dwItem;
	DWORD dwPrevItem; // set if this is a BUTTONUP msg
	int nColID; // NCG_CLIENTCOLUMNID if client click
	UINT nMsgID; // WM_...
	POINT ptClick;
};

struct NCGHDRCLICK
{
	int nColID; 
	UINT nMsgID; // WM_...
	BOOL bPressed; // notifyee can modify to indicate what the final state should be
};

struct NCGGETCURSOR
{
	int nColID;
	DWORD dwItem;
};

struct NCGITEMSELECTION
{
	DWORD dwItem;
	BOOL bSelected;
};

const UINT NCG_CLIENTCOLUMNID = 0xffff;

enum NCGSORT
{
	NCGSORT_UP = -1,
	NCGSORT_NONE = 0, // default
	NCGSORT_DOWN = 1,
};

class CThemed;

class CNcGutter : protected CSubclassWnd  
{
public:
	CNcGutter(DWORD dwStyles);
	virtual ~CNcGutter();

	BOOL Initialize(HWND hwnd);
	BOOL IsInitialized() const { return IsHooked(); }

	// add WM_ messages that should cause a recalc
	// use nNotification for 
	void AddRecalcMessage(UINT nMessage, UINT nNotification = 0); 
	void AddRedrawMessage(UINT nMessage, UINT nNotification = 0); // add WM_ messages that should cause a redraw

	void Redraw();
	void RedrawItem(DWORD dwItem);

	void RecalcGutter(BOOL bForceRedraw = TRUE);
	BOOL RecalcColumn(UINT nColID); // TRUE if the gutter changed width
	int GetGutterWidth() const;

	void EnableStyle(DWORD dwStyle, BOOL bEnable = TRUE);
	BOOL HasStyle(DWORD dwStyle) const { return ((m_dwStyles & dwStyle) == dwStyle); }
	
	int AddColumn(UINT nColID, LPCTSTR szTitle = NULL, UINT nWidth = 0, UINT nTextAlign = DT_LEFT); // returns the index of the added column
	void PressHeader(UINT nColID, BOOL bPress = TRUE);
	void SetHeaderTitle(UINT nColID, LPCTSTR szTitle, LPCTSTR szFont = NULL, BOOL bSymbolFont = TRUE);
	void EnableHeaderClicking(UINT nColID, BOOL bEnable = TRUE);
	void SetColumnSort(UINT nColID, NCGSORT nSortDir, BOOL bExclusive = TRUE);
	int GetColumnCount() const { return m_aColumns.GetSize() - 1; } // don't count the client column

	BOOL PtInHeader(CPoint ptScreen) const;
	void GetWindowClientRect(CRect& rClient, BOOL bScreen) const;

protected:
	CMap<DWORD, DWORD, char, char> m_mapRecalcMessages;
	CMap<DWORD, DWORD, char, char> m_mapRedrawMessages;
	BOOL m_bSetRedraw;
	CBitmap m_bmClient, m_bmNonClient;
	BOOL m_bFirstRecalc;
	CHotTracker m_hotTrack;
	int m_nHeaderColDown;
	DWORD m_dwButtonDownItem;
	DWORD m_dwStyles;

	struct COLUMNDESC
	{
		COLUMNDESC(UINT nID = 0) : nColID(nID), nWidth(0), bCalcWidth(TRUE), bPressed(FALSE), 
								nTextAlign(DT_LEFT), bClickable(TRUE), nSortDir(NCGSORT_NONE), 
								hFont(NULL), bSymbolFont(FALSE) {}
		~COLUMNDESC() { ::DeleteObject(hFont); }

		UINT nColID;
		CString sTitle;
		BOOL bCalcWidth;
		UINT nWidth;
		UINT nTextWidth;
		BOOL bPressed;
		UINT nTextAlign;
		BOOL bClickable;
		NCGSORT nSortDir;
		HFONT hFont;
		BOOL bSymbolFont;
	};

	CArray<COLUMNDESC*, COLUMNDESC*> m_aColumns;

protected:
	virtual LRESULT WindowProc(HWND hRealWnd, UINT msg, WPARAM wp, LPARAM lp);

	// specific message handlers
	void OnPrint(HDC hdc, UINT& nFlags);
	void OnNcPaint();
	void OnPaint();
	void OnHotChange(int nPrevHot, int nHot);
	void OnNcButtonDown(UINT nMsg, CPoint point);
	void OnNcButtonUp(UINT nMsg, CPoint point);
	void OnButtonDown(UINT nMsg, CPoint point);
	void OnButtonUp(UINT nMsg, CPoint point);
	LRESULT OnNcHitTest(CPoint point);
	BOOL OnSetCursor(); // returns TRUE if the cursor was set
	LRESULT OnNcCalcSize(LPNCCALCSIZE_PARAMS lpncsp);

	// these test for messages added with AddRecalcMessage/AddRedrawMessage
	BOOL ProcessRecalcMsg(UINT nMsg, WPARAM wp, LPARAM lp, LRESULT& lr);
	BOOL ProcessRedrawMsg(UINT nMsg, WPARAM wp, LPARAM lp, LRESULT& lr);

	BOOL ParentWantRecalc();
	BOOL ParentWantRedraw();

	void NcDrawItem(CDC* pDC, DWORD dwItem, DWORD dwParentItem, int nLevel, int nPos, 
					const CRect& rGutter, CRect& rItem, BOOL bDrawChildren);
	void PostNcDraw(CDC* pDC, const CRect& rWindow);
	void PostNcDrawItem(CDC* pDC, DWORD dwItem, const CRect& rItem, int nLevel, BOOL bParent);
	
	DWORD GetFirstVisibleTopLevelItem(int& nItem) const; // return 0 if no items
	DWORD GetNextItem(DWORD dwItem) const; // return 0 at end
	CRect GetWindowItemRect(DWORD dwItem) const;
	DWORD GetFirstChildItem(DWORD dwItem) const;
	BOOL IsItemSelected(DWORD dwItem) const;
	int GetSelectedCount() const;
	DWORD GetParentItem(DWORD dwItem) const;

	enum NCG_HITTEST { NCGHT_HEADER, NCGHT_ITEM, NCGHT_NOWHERE }; // private

	NCG_HITTEST HitTest(CPoint ptScreen, DWORD& dwItem, int& nColumn) const;
	NCG_HITTEST HitTest(CPoint ptScreen) const;
	DWORD ItemHitTest(CPoint ptClient) const;
	int ColumnHitTest(CPoint ptScreen) const;

	enum HCHDRPART { NONCLIENT, CLIENT }; // private

	void NcDrawHeader(CDC* pDC, const CRect& rHeader, HCHDRPART nPart, const LPPOINT pCursor);
	void NcDrawHeaderColumn(CDC* pDC, int nColumn, CRect rColumn, CThemed* pTheme, const LPPOINT pCursor);
	void UpdateHeaderHotRects();
	void UnpressAllColumnHeaders(int nExcludeCol = -1);
	int RecalcGutterWidth();
	int GetColumnIndex(UINT nColID) const; // can return -1

	inline BOOL IsClientColumn(int nCol) const { return (nCol == m_aColumns.GetSize() - 1); }

	BOOL PrepareBitmap(CDC* pDC, CBitmap* pBitmap, const CRect& rect, BOOL bClient);
	CFont* PrepareFont(CDC* pDC, BOOL bHeader, HFONT hFont = NULL); // returns 'old' font

	enum GHR_WHAT { GHR_NONCLIENT, GHR_CLIENT, GHR_ALL }; // private

	void GetHeaderRect(CRect& rHeader, GHR_WHAT nWhat, BOOL bScreen) const;
	void GetWindowRectEx(CRect& rWindow, BOOL bScreen) const;
	void GetGutterRect(CRect& rGutter, BOOL bScreen) const;
	void GetCursorPos(CPoint& ptCursor, BOOL bScreen) const;
};

#endif // !defined(AFX_NCGUTTER_H__A356B1B6_1B4D_4013_8F39_8D9D2442E149__INCLUDED_)

⌨️ 快捷键说明

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