Click here to Skip to main content

onlinewan - Professional Profile

Summary

10
Authority
15
Debator
72
Organiser
412
Participant
0
Author
0
Editor
0
Enquirer
No Biography provided
Member since Sunday, May 20, 2007 (6 years)

Contributions

Articles 0
Tech Blogs 0
Messages 21 (Lurker)
Q&A Questions 0
Q&A Answers 0
Tips/Tricks 0
Comments 0

Links

Reputation

For more information on Reputation please see the FAQ.

Privileges

Members need to achieve at least one of the given member levels in the given reputation categories in order to perform a given action. For example, to store personal files in your account area you will need to achieve Platinum level in either the Author or Authority category. The "If Owner" column means that owners of an item automatically have the privilege, and the given member types also gain the privilege regardless of their reputation level.

ActionAuthorAuthorityDebatorEditorEnquirerOrganiserParticipantIf OwnerMember Types
Have no restrictions on voting frequencysilversilversilversilverAdmin
Store personal files in your account areaplatinumplatinumSitebuilder, Subeditor, Supporter, Editor, Staff
Have live hyperlinks in your biographybronzebronzebronzebronzebronzebronzesilverSubeditor, Protector, Editor, Staff, Admin
Edit a Question in Q&AsilversilversilversilverYesSubeditor, Protector, Editor, Admin
Edit an Answer in Q&AsilversilversilversilverYesSubeditor, Protector, Editor, Admin
Delete a Question in Q&AYesSubeditor, Protector, Editor, Admin
Delete an Answer in Q&AYesSubeditor, Protector, Editor, Admin
Report an Articlesilversilversilversilver
Approve/Disapprove a pending ArticlegoldgoldgoldgoldSubeditor, Mentor, Protector, Editor, Staff, Admin
Edit other members' articlesSubeditor, Protector, Editor, Admin
Create an article without requiring moderationplatinumSubeditor, Mentor, Protector, Editor, Staff, Admin
Report a forum messagesilversilverbronzeProtector, Editor, Admin
Create a new tagsilversilversilversilverAdmin
Modify a tagsilversilversilversilverAdmin

Actions with a green tick can be performed by this member.


 
You must Sign In to use this message board.
Search this forum  
General带有扩展功能的ListCtrl Pin
Thursday, May 20, 2010 9:00 PM by onlinewan
.h
///////////////////////////////////////////////////////////////////////////////
// ReportCtrl.h
//
// CReportCtrl, a CListCtrl derived class that is specialized on "Report View"
// style. 
//
// Features:
//
// 1, Item sorting by clicking on column header.
// 2, Sub-item text edit.
// 3, Item repositioning.
// 4, Customizing checkbox styles, including "single" and "disabled".
// 5, Sending a message to parent window when user clicks on a checkbox.
// 6, Convenient item insertion, deletion, moving, and sub-item text changing.
// 7, Sub-item images and color
// 8, And much more... 
//
// 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 acknowledgement must be made to the author of this file .
//
// This file is provided "as is" with no expressed or implied warranty.
//
// Written by Bin Liu (abinn32@yahoo.com)
//
// History
//
// Nov. 26, 2003 - Initial release.
// Dec. 03, 2003 - Fixed a bug in "EndEdit" where item text were not preperly committed.
//                 Completed the implementation of the "Sort-Separator" feature.
// Jan. 01, 2004 - Fixed a bug in "SetItemData".
//               - Added message "WM_EDIT_COMMITTED" which is sent to the parent window
//                 when an item text editing is committed.
//               - Fixed a bug in "SetItemText"(double type).
//               - Fixed a bug where item sorting does not work properly when there
//                 are multiple CReportCtrl objects on same window.
//
///////////////////////////////////////////////////////////////////////////////

#ifndef __REPORTCTRL_H__
#define __REPORTCTRL_H__
 
// Sent to parent window when user clicked on the checkbox of an item:
// wParam: The item index in the list ctrl
// lParam: The mouse event type(WM_LBUTTONDOWN, WM_RBUTTONDOWN, etc) which generated this event. 
// Note: This message is not sent when the checkbox states were altered programmatically
//       by calling "SetItem", it is only sent when the user "physically" clicked the
//       checkbox using mouse or joystick etc.
#define WM_ON_CHKBOX	(WM_APP + 10000)
 
// Sent to parent window when a column of items were sorted
// wParam: The column index
// lParam: The sort method, either 0(descending) or 1(ascending)
#define WM_ITEM_SORTED	(WM_APP + 10001)
 
// Sent to parent window when an item text editing was committed
// wParam: The item index
// lParam: The column index
#define WM_EDIT_COMMITTED	(WM_APP + 10002)
 
// Checkbox styles.
#define RC_CHKBOX_NONE			0 // No checkbox displayed
#define	RC_CHKBOX_NORMAL		1 // Normal, multiple check allowed
#define	RC_CHKBOX_SINGLE		2 // Single check only
#define	RC_CHKBOX_DISABLED		3 // Disabled, cannot be checked/unchecked by user input,
								  // but can be by your code.

// Item state flags for selection, deletion, etc.
// Multiple flags can be combined together using the bit-or operator.
// Note: If RC_ITEM_ALL is set, all other flags are ignored
#define RC_ITEM_NONE		0x0000 // Void, indicates invalid items only
#define	RC_ITEM_ALL			0x0001 // All items regardless of states
#define	RC_ITEM_SELECTED	0x0002 // Selected items
#define	RC_ITEM_UNSELECTED	0x0004 // Unselected items
#define	RC_ITEM_CHECKED		0x0008 // Checked items
#define	RC_ITEM_UNCHECKED	0x0010 // Unchecked items
#define	RC_ITEM_FOCUSED		0x0020 // Focused item
#define	RC_ITEM_UNFOCUSED	0x0040 // Unfocused items

// Item inverting types
#define RC_INVERT_SELECTION	0 // Invert item selection
#define RC_INVERT_CHECKMARK	1 // Invert item check mark

// Removes any custom color from item text and item backgroun
#define COLOR_INVALID	0xffffffff
 
#include "atlbase.h"
#include <set>
#include <map>
 
//////////////////////////////////////////////////////////////////////////
class CListCtrlColumnEx : public CListCtrl
{
protected:	
	struct ColumnState
	{
		ColumnState()
			:m_Visible(false)
			,m_OrgWidth(0)
			,m_OrgPosition(-1)
			,m_strText(_T(""))
		{}
		bool m_Visible;
		int  m_OrgWidth;	// Width it had before being hidden
		int  m_OrgPosition;	// Position it had before being hidden
		CString m_strText;
	};
	CSimpleArray<ColumnState>	m_ColumnStates;
	int GetColumnStateCount();
	void InsertColumnState(int nCol, bool bVisible, int nOrgWidth, CString strText);
	void DeleteColumnState(int nCol);
	ColumnState& GetColumnState(int nCol);
 
	virtual afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
	virtual afx_msg LRESULT OnDeleteColumn(WPARAM wParam, LPARAM lParam);
	virtual afx_msg LRESULT OnInsertColumn(WPARAM wParam, LPARAM lParam);
	virtual afx_msg LRESULT OnSetColumnWidth(WPARAM wParam, LPARAM lParam);
	virtual afx_msg BOOL OnHeaderBeginResize(UINT id, NMHDR* pNmhdr, LRESULT* pResult);
	virtual afx_msg BOOL OnHeaderEndResize(UINT id, NMHDR* pNmhdr, LRESULT* pResult);
	virtual afx_msg BOOL OnHeaderEndDrag(UINT id, NMHDR* pNmhdr, LRESULT* pResult);
	virtual afx_msg BOOL OnHeaderDividerDblClick(UINT, NMHDR* pNMHDR, LRESULT* pResult);
	virtual afx_msg void OnContextMenu(CWnd*, CPoint point);
	virtual afx_msg void OnDestroy( );
	virtual afx_msg BOOL OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult ); 
 
	DECLARE_MESSAGE_MAP()
 
public:
	virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
	virtual void PreSubclassWindow();
 
public:
	CListCtrlColumnEx();
	virtual ~CListCtrlColumnEx();
 
	bool IsColumnVisible(int nCol);
	int GetFirstVisibleColumn();
	BOOL ShowColumn(int nCol, bool bShow);
	BOOL SetColumnWidthAuto(int nCol = -1, bool includeHeader = false);
 
	void AddReadOnlyShowState(LPCTSTR pszName);
 
	//bNoHideFirstColumn	标识是否设置第一列不可隐藏
	//strIdentifier			此ListCtrl的唯一标识
	virtual void ResetHeaderState(BOOL bNoHideFirstColumn = FALSE, CString strIdentifier = _T(""));
 
	void SetShowRightMenu(BOOL bShowRightMenu);
	BOOL IsShowRightMenu();
 
	virtual int OnToolHitTest(CPoint point, TOOLINFO * pTI) const;
	virtual CString GetItemToolTipText( int nItem, int nSubItem);
 
private:
	BOOL m_bShowRightMenu;
 
	BOOL SetRegister(LPCTSTR lpszName, LPCTSTR lpszValue, LPCTSTR lpszKeyName = _T("Software\\LiZheng\\CListCtrlHeader\\Settings"));
	CString GetRegister(LPCTSTR lpszName, LPCTSTR lpszPath = _T("Software\\LiZheng\\CListCtrlHeader\\Settings"));
	void SplitString(LPCTSTR sSource, CStringArray &sDestination, TCHAR cToken);
 
	BOOL m_bNoChangedFirstColumn;
	
	BOOL GetReadOnlyShowState(int i);
	std::set<CString> m_setReadOnlyShowState;
 
	CString m_strIdentifier;
	BOOL m_bNeedSaveStatus;
};
 

//////////////////////////////////////////////////////////////////////////
// The CReportCtrl Class Definition
//////////////////////////////////////////////////////////////////////////
class CReportCtrl : public CListCtrlColumnEx
{
public:		
		
	//////////////////////////////////////////////////////////////////////
	//		Constructor & Destructor
	//////////////////////////////////////////////////////////////////////
	CReportCtrl();
	virtual ~CReportCtrl();
 
	//////////////////////////////////////////////////////////////////////
	//		Run-time Creation
	//////////////////////////////////////////////////////////////////////
	virtual BOOL Create(CWnd* pParentWnd, UINT nID, LPCRECT lpRect = NULL, DWORD dwStyle = WS_BORDER | WS_TABSTOP);
 
	///////////////////////////////////////////////////////////////////////
	//		Column Header attributes
	///////////////////////////////////////////////////////////////////////
	//mlj added 081104
	int GetColumnCount();
	void AdjustColumnWidth();
	
	void CancelAllSelectedState();
	int GetAllSelectedIndexs(CDWordArray &aryIndex);
 
	BOOL SetColumnHeader(const CString& strHeadings); // Set columns and their formats.
	int GetColumnCount() const; // Get the column count.
	BOOL DeleteAllColumns();
	CString GetHeaderText(int nColumn) const;
	BOOL SetHeaderText(int nColumn, LPCTSTR lpText);	
	BOOL HasColumnHeader() const; // FALSE if the list control has LVS_NOCOLUMNHEADER flag
	const CHeaderCtrl* GetHeaderCtrl() const;
 
	///////////////////////////////////////////////////////////////////////
	//		Images & Color
	///////////////////////////////////////////////////////////////////////
	
	// Column header images
	BOOL SetHeaderImage(int nColumn, int nImageIndex, BOOL bLeftSide = TRUE);
	int GetHeaderImage(int nColumn) const;
	CImageList* SetHeaderImageList(UINT nBitmapID, COLORREF crMask = RGB(255, 0, 255));
	CImageList* SetHeaderImageList(CImageList* pImageList);
	
	// Sub-item images
	BOOL SetItemImage(int nItem, int nSubItem, int nImageIndex);
	int GetItemImage(int nItem, int nSubItem) const;
	CImageList* SetImageList(UINT nBitmapID, COLORREF crMask = RGB(255, 0, 255));
	CImageList* SetImageList(CImageList* pImageList);
	CImageList* GetImageList() const;
 
	// Sub-item Text & Background Color
	void SetItemTextColor(int nItem = -1, int nSubItem = -1, COLORREF color = COLOR_INVALID, BOOL bRedraw = TRUE);
	COLORREF GetItemTextColor(int nItem, int nSubItem) const;
	void SetItemBkColor(int nItem = -1, int nSubItem = -1, COLORREF color = COLOR_INVALID, BOOL bRedraw = TRUE);
	COLORREF GetItemBkColor(int nItem, int nSubItem) const;
 
	//////////////////////////////////////////////////////////////////////
	//		Control Styles & Attributes
	//////////////////////////////////////////////////////////////////////
	
	void ResizeToFitParent(); // Resize the list control to occupy parent's client area
	void SetGridLines(BOOL bSet = TRUE); // Show grid lines.
	void SetCheckboxeStyle(int nStyle = RC_CHKBOX_NORMAL); // Set checkbox styles.	
	int GetCheckboxStyle() const;	
	BOOL IsSortable() const; // Is sort allowed?
	BOOL SetSortable(BOOL bSet); // Allow/disallow sorting
	BOOL IsEditable() const; // Is Item text editable?
	void SetEditable(BOOL bSet = TRUE); // Allow item text editting
	
	///////////////////////////////////////////////////////////////////////
	//		Item attributes & operations
	///////////////////////////////////////////////////////////////////////	

	// Item states operation
	int GetFirstItem(DWORD dwStates = RC_ITEM_ALL, int nStartAfter = -1) const;
	int GetLastItem(DWORD dwStates = RC_ITEM_ALL, int nStartBefore = -1) const;
	int GetItemCount(DWORD dwStates = RC_ITEM_ALL) const;	
	DWORD GetItemStates(int nItem) const;
	BOOL ExamItemStates(int nItem, DWORD dwStates) const;
	BOOL SetItemStates(int nItem, DWORD dwNewStates);
	int SetAllItemStates(DWORD dwOldStates, DWORD dwNewStates);
	void InvertItems(int nType); // RC_INVERT_SELECTION or RC_INVERT_CHECKMARK

	// Item Insertion & Deletion	
	int InsertItemEx(int nItem, LPCTSTR lpText, ...); 	
	BOOL DeleteItem(int nItem, BOOL bSelectNextItem = FALSE); // Delete an item.
	int DeleteAllItems(DWORD dwStates = RC_ITEM_ALL); // Delete all qualified items.

	// Item positioning	
	int MoveUp(int nItem, int nCount = 1); // Move an item upwards by "nCount" positions.
	int MoveDown(int nItem, int nCount = 1); // Move an item downwards by "nCount" positions.
	int MoveToTop(int nItem); // Move an item up to the top.
	int MoveToBottom(int nItem); // Move an item down to the bottom.
	int MoveTo(int nItem, int nNewPosition); // Move an item to a particular position 
	BOOL SwapItems(int nItem1, int nItem2);	// Swap two items in the list, including all attributes.

	// Convenient versions of "CListCtrl::SetItemText"	
	BOOL SetItemText(int nItem, int nSubItem, INT val);
	BOOL SetItemText(int nItem, int nSubItem, UINT val);
	BOOL SetItemText(int nItem, int nSubItem, LONG val);
	BOOL SetItemText(int nItem, int nSubItem, ULONG val);
	BOOL SetItemText(int nItem, int nSubItem, TCHAR val);
	BOOL SetItemText(int nItem, int nSubItem, DOUBLE val, int nPrecision = -1);
	BOOL SetItemText(int nItem, int nSubItem, const COleDateTime& dateTime, DWORD dwFlags = 0);
 
	// Sorting	
	BOOL IsSortAscending() const;
	int GetSortedColumn() const;
	void SortItems(int nColumn, BOOL bAscending); // Sort a specified column.
	void SetSortSeparator(LPCTSTR lpSortSeparator = NULL); // Sort-separator, NULL=disabled
	LPCTSTR GetSortSeparator() const;
 
	// Item text edit	
	virtual BOOL StartEdit(int nItem, int nSubItem); // Display the editbox, previous edit are committed
	virtual BOOL EndEdit(BOOL bCommit = TRUE); // Commit/cancel text edit, hide the editbox
	CEdit* GetEditControl();	
 
	///////////////////////////////////////////////////////////////////////
	//		Necessary overloading but Irrelevant to Users
	///////////////////////////////////////////////////////////////////////
	
	int InsertColumn(int nCol, LPCTSTR lpColumnHeading, int nFormat = LVCFMT_LEFT, int nWidth = -1, int nSubItem = -1);
	int InsertColumn(int nCol, const LVCOLUMN* pColumn);
	BOOL DeleteColumn(int nCol);
	BOOL SetCheck(int nItem, BOOL bCheck = TRUE); // overloaded to guard the "single" checkbox style
	BOOL SetItem(int nItem, int nSubItem, UINT nMask, LPCTSTR lpszItem, int nImage, UINT nState, UINT nStateMask, LPARAM lParam);
	BOOL SetItem(const LVITEM* pItem);
	BOOL GetItem(LVITEM* pItem) const;
	DWORD GetItemData(int nItem) const;
	BOOL SetItemData(int nItem, DWORD dwData);
	DWORD SetExtendedStyle(DWORD dwNewStyle);
	BOOL ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0);
	BOOL ModifyStyleEx(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0);
	int InsertItem(UINT nMask, int nItem, LPCTSTR lpItem, UINT nState, UINT nStateMask, int nImage, LPARAM lParam);
	int InsertItem(int nItem, LPCTSTR lpItem, int nImage);
	int InsertItem(const LVITEM* pItem);
	int InsertItem(int nIndex, LPCTSTR lpText);
	BOOL SetItemText(int nItem, int nSubItem, LPCTSTR lpText);
 
	int GetCurSel();
	void ClearAllFilter();
 
protected:	
	
	// Helper functions for internal use
	BOOL _IsValidIndex(int nIndex) const;
	BOOL _ItemCheckMonitor(int nIndex, BOOL bBefore, BOOL bAfter, UINT nMsg);
	BOOL _IsEditVisible() const;
	void _MouseClkMonitor(UINT nMsg, UINT nFlags, CPoint point, BOOL bTriggerEdit);
	static void _StringSplit(const CString &str, CStringArray& arr, TCHAR chDelimitior);
	void _UnsetSortedColumn();
	BOOL _SetItemStatesNoVerify(int nItem, DWORD dwNewStates);
	void _EnsureSingleCheck(int nItem);
	DWORD _GetHeaderTextFormat(int nColumn) const;
	void _UpdateColumn(int nColumn, BOOL bInsert);
	void _AllocItemMemory(int nItem);
	void _FreeItemMemory(int nItem);
	BOOL _PartialSort(int nStart, int nEnd);
	int _FindSeparator(int nStartAfter, int nColumn) const;
	void _QuickSortRecursive(int* pArr, int nLow, int nHigh);
	int _CompareItems(int nItem1, int nItem2);
 
	// Member data	
	CEdit* m_pWndEdit; // Edit control, for subitem edit
	LPTSTR m_pszSeparator; // Sort separator
	BOOL m_bAllowEdit; // Is subitem edit allowed?
	POINT m_ptEditting; // Position of the subitem that is currently being edited
	int m_nChkStyle; // Checkbox style
	DWORD m_dwPrevEditFmt; // Format of previously edited subitem
	CImageList m_imgList; // Image list for items
	CImageList m_headerImgList; // Image list for the header control
	int m_nSortCol; // The sorted column, -1 if none
	BOOL m_bSortAscending; // Is sort ascending?

	//////////////////////////////////////////////////////////////////////
	// Wizard Generated Stuff
	//////////////////////////////////////////////////////////////////////

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CReportCtrl)
	public:
	virtual BOOL PreTranslateMessage(MSG* pMsg);
	protected:
	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
	virtual void PreSubclassWindow();
	//}}AFX_VIRTUAL

	// Generated message map functions

protected:	
 
	//{{AFX_MSG(CReportCtrl)
	afx_msg void OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult);
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	afx_msg void OnDestroy();
	afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
	afx_msg void OnMButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnMButtonDblClk(UINT nFlags, CPoint point);
	afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnRButtonDblClk(UINT nFlags, CPoint point);
	afx_msg void OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult);
	afx_msg void OnFilterChange(NMHDR* pNMHDR, LRESULT* pResult);
	afx_msg void OnFilterButtonClicked(NMHDR* pNMHDR, LRESULT* pResult);
	//}}AFX_MSG

	DECLARE_MESSAGE_MAP()
};
 
//////////////////////////////////////////////////////////////////////////
// End of CReportCtrl Class Definition
//////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // __REPORTCTRL_H__
 
.cpp
///////////////////////////////////////////////////////////////////////////////
// ReportCtrl.cpp
//
// CReportCtrl, a CListCtrlColumnEx derived class that is specialized on "Report View"
// style. 
//
// Features:
//
// 1, Item sorting by clicking on column header.
// 2, Sub-item text edit.
// 3, Item repositioning.
// 4, Customizing checkbox styles, including "single" and "disabled".
// 5, Sending a message to parent window when user clicks on a checkbox.
// 6, Convenient item insertion, deletion, moving, and sub-item text changing.
// 7, Sub-item images and color
// 8, And much more... 
//
// 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 acknowledgement must be made to the author of this file .
//
// This file is provided "as is" with no expressed or implied warranty.
//
// Written by Bin Liu (abinn32@yahoo.com)
//
// History
//
// Nov. 26, 2003 - Initial release.
// Dec. 03, 2003 - Fixed a bug in "EndEdit" where item text were not preperly committed.
//               - Completed the implementation of the "Sort-Separator" feature.
// Jan. 01, 2004 - Fixed a bug in "SetItemData".
//               - Added message "WM_EDIT_COMMITTED" which is sent to the parent window
//                 when an item text editing is committed.
//               - Fixed a bug in "SetItemText"(double type).
//               - Fixed a bug where item sorting does not work properly when there
//                 are multiple CReportCtrl objects on same window.
//
///////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ReportCtrl.h"
#include <afxtempl.h>
 
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
 
// Below styles MUST be present in a report ctrl
#define MUST_STYLE			(WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | LVS_REPORT)
#define MUST_EX_STYLE		(LVS_EX_FULLROWSELECT | LVS_EX_SUBITEMIMAGES)
 
// Below styles MUST NOT be present in a report ctrl
//#define MUST_NOT_STYLE		(LVS_EDITLABELS | LVS_ICON | LVS_SMALLICON | LVS_LIST | LVS_NOSCROLL)
#define MUST_NOT_STYLE		(LVS_ICON | LVS_SMALLICON | LVS_LIST | LVS_NOSCROLL)
#define MUST_NOT_EX_STYLE	(0)
 
struct ROWINFO
{
	DWORD dwData;
	DWORD dwStates;
	CArray<int, int> aImages;
	CStringArray aTexts;
};
 
//////////////////////////////////////////////////////////////////////////
// CItemData class is used for store extra information
//////////////////////////////////////////////////////////////////////////
class CItemData
{
public:
	CItemData() { dwData = 0; }
	void InsertColumn(int nColumn);
	void DeleteColumn(int nColumn);
	DWORD dwData; // The actual 32-bit user data stores here
	CArray<COLORREF, COLORREF> aTextColors; // Sub item text colors
	CArray<COLORREF, COLORREF> aBkColors; // Sub item backgroud colors
};
 
void CItemData::InsertColumn(int nColumn)
{
	aTextColors.InsertAt(nColumn, ::GetSysColor(COLOR_WINDOWTEXT));
	aBkColors.InsertAt(nColumn, ::GetSysColor(COLOR_WINDOW));
}
 
void CItemData::DeleteColumn(int nColumn)
{
	aTextColors.RemoveAt(nColumn);
	aBkColors.RemoveAt(nColumn);
}
 
///////////////////////////////////////////////////////////////////////
// A set of functions used for item text format determining
///////////////////////////////////////////////////////////////////////
namespace _ITEM_COMPARE_FUNCS
{
	BOOL _IsDecNumber(const CString& str, double& f);
	int _DecNumberCompare(double f1, double f2);
	BOOL _IsHexNumber(const CString& str, DWORD& dw);
	int _HexNumberCompare(DWORD dw1, DWORD dw2);
	BOOL _IsDate(const CString& str, COleDateTime& date);
	int _DateCompare(const COleDateTime& date1, const COleDateTime& date2);
};
 
BOOL _ITEM_COMPARE_FUNCS::_IsDecNumber(const CString& str, double& f)
{
	if (str.IsEmpty())
		return FALSE;
 
	LPTSTR p;
	f = _tcstod(str, &p);
	return (*p == _T('\0') || (*p == _T('%') && p[1] == _T('\0')));
}
 
int _ITEM_COMPARE_FUNCS::_DecNumberCompare(double f1, double f2)
{
	if(f1 < f2)
		return -1;
	
	if(f1 > f2)
		return 1;
 
	return 0;
}
 
BOOL _ITEM_COMPARE_FUNCS::_IsHexNumber(const CString& str, DWORD& dw)
{
	if (str.IsEmpty())
		return FALSE;
 
	LPTSTR p;
	dw = _tcstoul(str, &p, 16);
	return *p == _T('\0');
}
 
int _ITEM_COMPARE_FUNCS::_HexNumberCompare(DWORD dw1, DWORD dw2)
{
	if (dw1 > dw2)
		return 1;
 
	if (dw1 < dw2)
		return -1;
 
	return 0;
}
 
BOOL _ITEM_COMPARE_FUNCS::_IsDate(const CString& str, COleDateTime& date)
{
	return date.ParseDateTime(str);
}
 
int _ITEM_COMPARE_FUNCS::_DateCompare(const COleDateTime& date1, const COleDateTime& date2)
{
	if (date1 < date2)
		return -1;
 
	if (date1 > date2)
		return 1;
 
	return 0;
}
 
/////////////////////////////////////////////////////////////////////////////
// CReportCtrl Implementation
/////////////////////////////////////////////////////////////////////////////
CReportCtrl::CReportCtrl(): m_pWndEdit(NULL)
{
	m_pWndEdit = new CEdit;
	VERIFY(m_pWndEdit != NULL);
	m_pszSeparator = NULL;
	m_bAllowEdit = FALSE;
	m_ptEditting.x = -1;
	m_ptEditting.y = -1;
	m_nChkStyle = RC_CHKBOX_NORMAL;
	m_dwPrevEditFmt = ES_LEFT;
	m_nSortCol = -1;
	m_bSortAscending = TRUE;
}
 
CReportCtrl::~CReportCtrl()
{	
	if (m_pszSeparator != NULL)
		delete [] m_pszSeparator;
 
	if (m_pWndEdit != NULL)
		delete m_pWndEdit;
}
 

BEGIN_MESSAGE_MAP(CReportCtrl, CListCtrlColumnEx)
	//{{AFX_MSG_MAP(CReportCtrl)
	ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnclick)
	ON_WM_LBUTTONDOWN()
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_WM_LBUTTONDBLCLK()
	ON_WM_MBUTTONDOWN()
	ON_WM_MBUTTONDBLCLK()
	ON_WM_RBUTTONDOWN()
	ON_WM_RBUTTONDBLCLK()
	ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw)
	ON_NOTIFY(HDN_FILTERCHANGE, 0, OnFilterChange)
	ON_NOTIFY(HDN_FILTERBTNCLICK, 0, OnFilterButtonClicked)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()
 
/////////////////////////////////////////////////////////////////////////////
// CReportCtrl message handlers
void CReportCtrl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult) 
{
	LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)pNMHDR;
 
	if (lplvcd->nmcd.dwDrawStage == CDDS_PREPAINT)
	{
	    *pResult = CDRF_NOTIFYITEMDRAW;
	}
    else if (lplvcd->nmcd.dwDrawStage == CDDS_ITEMPREPAINT)
	{
	    *pResult = CDRF_NOTIFYSUBITEMDRAW;
	}
    else if (lplvcd->nmcd.dwDrawStage == (CDDS_ITEMPREPAINT | CDDS_SUBITEM))
    {
		CItemData* p = (CItemData*)(CListCtrlColumnEx::GetItemData(lplvcd->nmcd.dwItemSpec));
		ASSERT(p != NULL);
		ASSERT(lplvcd->iSubItem >= 0 && lplvcd->iSubItem < p->aTextColors.GetSize());
		lplvcd->clrText = p->aTextColors[lplvcd->iSubItem];
		lplvcd->clrTextBk = p->aBkColors[lplvcd->iSubItem];
		*pResult = CDRF_DODEFAULT;
	}
}
 
void CReportCtrl::OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here
	const int COL = pNMListView->iSubItem;
	SortItems(COL, COL == m_nSortCol ? !m_bSortAscending : TRUE);
	*pResult = 0;
}
 
void CReportCtrl::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	_MouseClkMonitor(WM_LBUTTONDOWN, nFlags, point, TRUE);
}
 
void CReportCtrl::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	_MouseClkMonitor(WM_LBUTTONDBLCLK, nFlags, point, TRUE);
}
 
void CReportCtrl::OnMButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	_MouseClkMonitor(WM_MBUTTONDOWN, nFlags, point, FALSE);
}
 
void CReportCtrl::OnMButtonDblClk(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	_MouseClkMonitor(WM_MBUTTONDBLCLK, nFlags, point, FALSE);
}
 
void CReportCtrl::OnRButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	_MouseClkMonitor(WM_RBUTTONDOWN, nFlags, point, FALSE);
}
 
void CReportCtrl::OnRButtonDblClk(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	_MouseClkMonitor(WM_RBUTTONDBLCLK, nFlags, point, FALSE);
}
 
int CReportCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	lpCreateStruct->style &= ~MUST_NOT_STYLE;
	lpCreateStruct->style |= MUST_STYLE;
	if (CListCtrlColumnEx::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// TODO: Add your specialized creation code here
	SetExtendedStyle(GetExtendedStyle());
	ASSERT(GetHeaderCtrl() != NULL);
	return 0;
}
 
void CReportCtrl::OnDestroy() 
{
	DeleteAllItems();
	m_pWndEdit->DestroyWindow();
	m_imgList.DeleteImageList();
	m_headerImgList.DeleteImageList();
	CListCtrlColumnEx::OnDestroy();
	// TODO: Add your message handler code here	
}
 
BOOL CReportCtrl::_IsValidIndex(int nIndex) const
{
	return nIndex >= 0 && nIndex < CListCtrlColumnEx::GetItemCount();
}
 
// the heading text is in the format of "text,width,format;text,width,format;..."
BOOL CReportCtrl::SetColumnHeader(const CString& strHeadings)
{
	DeleteAllItems();
	DeleteAllColumns();
	EndEdit(TRUE);
	BOOL bInserted = FALSE;
	CStringArray aLong, aShort;
	_StringSplit(strHeadings, aLong, _T(';'));
	for (int i = 0; i < aLong.GetSize(); i++)
	{
		_StringSplit(aLong[i], aShort, _T(','));
		if (aShort.GetSize() > 0)
		{
			const int WIDTH = aShort.GetSize() > 1 ? _ttoi(aShort[1]) : 100;
			int nFormat = aShort.GetSize() > 2 ? _ttoi(aShort[2]) : 0;
 
			if (nFormat == 1)
				nFormat = LVCFMT_CENTER;
			else if (nFormat == 2)
				nFormat = LVCFMT_RIGHT;
			else
				nFormat = LVCFMT_LEFT;
 
			bInserted |= (InsertColumn(GetColumnCount(), aShort[0], nFormat, WIDTH) >= 0);
		}
	}
	return bInserted;
}
 
int CReportCtrl::InsertItem(int nIndex, LPCTSTR lpText)
{	
	EndEdit(TRUE);
	_UnsetSortedColumn();
	const int IDX = CListCtrlColumnEx::InsertItem(nIndex, lpText);
	if (IDX >= 0)
		_AllocItemMemory(IDX);
	return IDX;
}
 
BOOL CReportCtrl::DeleteItem(int nItem, BOOL bSelectNextItem)
{
	EndEdit(m_ptEditting.x != nItem);
	
	if (bSelectNextItem)
		SetItemStates(nItem + 1, RC_ITEM_SELECTED);
 
	_FreeItemMemory(nItem);
	return CListCtrlColumnEx::DeleteItem(nItem);
}
 
int CReportCtrl::DeleteAllItems(DWORD dwStates)
{
	EndEdit(FALSE);
	int nItemCount = CListCtrlColumnEx::GetItemCount();
	if (dwStates & RC_ITEM_ALL)
	{
//		LockWindowUpdate();
		for (int i = 0; i < nItemCount; i++)
			_FreeItemMemory(i);
		CListCtrlColumnEx::DeleteAllItems();
//		UnlockWindowUpdate();
		return nItemCount;		
	}
	
	int nDelCount = 0;
//	LockWindowUpdate();

	for (int i = 0; i < nItemCount; i++)
	{
		if (ExamItemStates(i, dwStates))
		{
			DeleteItem(i--);
			nItemCount--;
			nDelCount++;
		}
	}	
//	UnlockWindowUpdate();
	return nDelCount;
}
 
void CReportCtrl::SortItems(int nColumn, BOOL bAscending)
{
	EndEdit(TRUE);
	if (nColumn < 0 || nColumn >= GetColumnCount() || !IsSortable())
		return;	
 
	// do the sorting	
	m_nSortCol = nColumn;
	m_bSortAscending = bAscending;
	
	BOOL bEnd = FALSE;
	int nSep1 = -1;
	int nSep2 = _FindSeparator(-1, nColumn);
	do
	{
		if (nSep2 < 0)
		{
			nSep2 = GetItemCount();
			bEnd = TRUE;
		}
		_PartialSort(nSep1 + 1, nSep2 - 1);
		nSep1 = _FindSeparator(nSep2 - 1, nColumn);
		nSep2 = _FindSeparator(nSep1, nColumn);
	} while (!bEnd && nSep1 >= 0);
 
	GetParent()->SendMessage(WM_ITEM_SORTED, (WPARAM)m_nSortCol, (LPARAM)m_bSortAscending);
}
 
BOOL CReportCtrl::SetItemText(int nItem, int nSubItem, LPCTSTR lpText)
{
	EndEdit(TRUE);
	_UnsetSortedColumn();
	return CListCtrlColumnEx::SetItemText(nItem, nSubItem, lpText);
}
 
int CReportCtrl::GetColumnCount() const
{
	return GetHeaderCtrl()->GetItemCount();
}
 
int CReportCtrl::InsertItem(const LVITEM *pItem)
{
	EndEdit(TRUE);
	_UnsetSortedColumn();
	const int IDX = CListCtrlColumnEx::InsertItem(pItem);
	if (IDX >= 0)
		_AllocItemMemory(IDX);
	return IDX;
}
 
int CReportCtrl::InsertItem(int nItem, LPCTSTR lpItem, int nImage)
{	
	EndEdit(TRUE);
	_UnsetSortedColumn();
	const int IDX = CListCtrlColumnEx::InsertItem(nItem, lpItem, nImage);
	if (IDX >= 0)
		_AllocItemMemory(IDX);
	return IDX;
}
 
int CReportCtrl::InsertItem(UINT nMask, int nItem, LPCTSTR lpItem, UINT nState, UINT nStateMask, int nImage, LPARAM lParam)
{
	EndEdit(TRUE);
	_UnsetSortedColumn();
	const int IDX = CListCtrlColumnEx::InsertItem(nMask, nItem, lpItem, nState, nStateMask, nImage, lParam);
	if (IDX >= 0)
		_AllocItemMemory(IDX);
	return IDX;
}
 
void CReportCtrl::SetGridLines(BOOL bSet)
{
	DWORD dwStype = GetExtendedStyle();
	if (bSet)
		dwStype |= LVS_EX_GRIDLINES;
	else
		dwStype &= ~LVS_EX_GRIDLINES;
 
	SetExtendedStyle(dwStype);	
}
 
int CReportCtrl::InsertColumn(int nCol, const LVCOLUMN *pColumn)
{
	EndEdit(TRUE);
	const int IDX = CListCtrlColumnEx::InsertColumn(nCol, pColumn);
	if (IDX >= 0)
		_UpdateColumn(IDX, TRUE);
	return IDX;
}
 
int CReportCtrl::InsertColumn(int nCol, LPCTSTR lpColumnHeading, int nFormat, int nWidth, int nSubItem)
{
	EndEdit(TRUE);
	const int IDX = CListCtrlColumnEx::InsertColumn(nCol, lpColumnHeading, nFormat, nWidth, nSubItem);
	if (IDX >= 0)
		_UpdateColumn(IDX, TRUE);
	return IDX;
}
 
BOOL CReportCtrl::DeleteColumn(int nCol)
{
	EndEdit(TRUE);
	const BOOL RES = CListCtrlColumnEx::DeleteColumn(nCol);
	if (RES)
		_UpdateColumn(nCol, FALSE);
	return RES;
}
 
void CReportCtrl::SetCheckboxeStyle(int nStyle)
{
	m_nChkStyle = nStyle;
	EndEdit(TRUE);
	DWORD dwStype = GetExtendedStyle();
	if (nStyle == 0)
	{
		dwStype &= ~LVS_EX_CHECKBOXES;		
	}
	else
	{
		dwStype |= LVS_EX_CHECKBOXES;
		_EnsureSingleCheck(-1);
	}
 
	SetExtendedStyle(dwStype);
}
 
int CReportCtrl::MoveTo(int nItem, int nNewPosition)
{
	if (!_IsValidIndex(nItem))
		return -1;
 
	EndEdit(TRUE);
	const int ITEMS = CListCtrlColumnEx::GetItemCount();
	nNewPosition = max(0, nNewPosition);
	nNewPosition  = min(ITEMS - 1, nNewPosition);
 
	if (nItem == nNewPosition)
		return nNewPosition;
 
	_UnsetSortedColumn();
 
	// Backup all states and attributes
	const int COLS = GetColumnCount();
	const DWORD STATES = GetItemStates(nItem);
	const DWORD DATA = CListCtrlColumnEx::GetItemData(nItem);
	CArray<int, int> aImages;
	CStringArray aTexts;
	aImages.SetSize(COLS);
	aTexts.SetSize(COLS);
	for (int i = 0; i < COLS; i++)
	{
		aImages[i] = GetItemImage(nItem, i);
		aTexts[i] = GetItemText(nItem, i);
	}	
 
	// Delete the item
	CListCtrlColumnEx::DeleteItem(nItem);
 
	// Insert a new item to the new position
	const int IDX = CListCtrlColumnEx::InsertItem(nNewPosition, _T(""));
 
	// Restore all states & attributes to the newly inserted item
	for (int j = 0; j < COLS; j++)
	{
		CListCtrlColumnEx::SetItemText(IDX, j, aTexts[j]);
		SetItemImage(IDX, j, aImages[j]);
	}
	CListCtrlColumnEx::SetItemData(IDX, DATA);
	SetItemStates(IDX, STATES);
	return IDX;
}
 
int CReportCtrl::MoveUp(int nItem, int nCount)
{	
	return MoveTo(nItem, nItem - nCount);
}
 
BOOL CReportCtrl::MoveDown(int nItem, int nCount)
{
	return MoveTo(nItem, nItem + nCount);
}
 
BOOL CReportCtrl::SwapItems(int nItem1, int nItem2)
{
	EndEdit(TRUE);
	if (!_IsValidIndex(nItem1) || !_IsValidIndex(nItem2))
		return FALSE;
 
	if (nItem1 == nItem2)
		return TRUE;
 
	_UnsetSortedColumn();
 
	// record previous states first
	const DWORD STATES1 = GetItemStates(nItem1);
	const DWORD STATES2 = GetItemStates(nItem2);
	const DWORD DATA1 = CListCtrlColumnEx::GetItemData(nItem1);
	const DWORD DATA2 = CListCtrlColumnEx::GetItemData(nItem2);
 
	// swap item texts and images
	for (int i = 0; i < GetColumnCount(); i++)
	{
		CString str = GetItemText(nItem1, i);
		CListCtrlColumnEx::SetItemText(nItem1, i, GetItemText(nItem2, i));
		CListCtrlColumnEx::SetItemText(nItem2, i, str);
		UINT nImg = GetItemImage(nItem1, i);
		SetItemImage(nItem1, i, GetItemImage(nItem2, i));
		SetItemImage(nItem2, i, nImg);
	}
	
	// swap item data
	CListCtrlColumnEx::SetItemData(nItem1, DATA2);
	CListCtrlColumnEx::SetItemData(nItem2, DATA1);
 
	// restore states
	SetItemStates(nItem1, STATES2);
	SetItemStates(nItem2, STATES1);
 
	return TRUE;
}
 
int CReportCtrl::MoveToTop(int nItem)
{
	return MoveTo(nItem, -1);
}
 
int CReportCtrl::MoveToBottom(int nItem)
{
	return MoveTo(nItem, INT_MAX);
}
 
BOOL CReportCtrl::SetItemText(int nItem, int nSubItem, TCHAR val)
{
	return SetItemText(nItem, nSubItem, CString(val));
}
 
BOOL CReportCtrl::SetItemText(int nItem, int nSubItem, INT val)
{	
	return SetItemText(nItem, nSubItem, (LONG)val);
}
 
BOOL CReportCtrl::SetItemText(int nItem, int nSubItem, UINT val)
{
	return SetItemText(nItem, nSubItem, (ULONG)val);
}
 
BOOL CReportCtrl::SetItemText(int nItem, int nSubItem, DOUBLE val, int nPrecision)
{
	CString sText, sFmt;
	
	if (nPrecision >= 0)
	{
		sFmt.Format(_T("%%.%df"), nPrecision);
		sText.Format(sFmt, val);
	}
	else
	{
		sText.Format(_T("%f"), val);
		sText.TrimRight(_T('0'));
		sText.TrimRight(_T('.'));
	}
	
	return SetItemText(nItem, nSubItem, sText);
}
 
BOOL CReportCtrl::SetItemText(int nItem, int nSubItem, const COleDateTime &dateTime, DWORD dwFlags)
{
	return SetItemText(nItem, nSubItem, dateTime.GetStatus() == COleDateTime::valid ? dateTime.Format(dwFlags) : _T(""));
}
 
BOOL CReportCtrl::SetItemText(int nItem, int nSubItem, LONG val)
{
	CString str;
	str.Format(_T("%d"), val);
	return SetItemText(nItem, nSubItem, str);
}
 
BOOL CReportCtrl::SetItemText(int nItem, int nSubItem, ULONG val)
{
	CString str;
	str.Format(_T("%u"), val);
	return SetItemText(nItem, nSubItem, str);
}
 
BOOL CReportCtrl::DeleteAllColumns()
{
	while (GetColumnCount() > 0)
		DeleteColumn(0);		
	return TRUE;
}
 
LPCTSTR CReportCtrl::GetSortSeparator() const
{
	return m_pszSeparator;
}
 
void CReportCtrl::SetSortSeparator(LPCTSTR lpSortSeparator)
{
	if (m_pszSeparator != NULL)
	{
		delete [] m_pszSeparator;
		m_pszSeparator = NULL;
	}
 
	if (lpSortSeparator != NULL)
		m_pszSeparator = _tcsdup(lpSortSeparator);
}
 
int CReportCtrl::InsertItemEx(int nItem, LPCTSTR lpText, ...)
{
	EndEdit(TRUE);
	_UnsetSortedColumn();
	const int IDX = CListCtrlColumnEx::InsertItem(nItem, lpText);
	if (IDX < 0)
		return -1;
 
 	va_list list;
	va_start(list, lpText);
 
	for(int iColumn = 1; iColumn < GetColumnCount(); iColumn++)
	{
		LPCTSTR lp = va_arg(list, LPCTSTR);
		if (lp != NULL)
		{
			CListCtrlColumnEx::SetItemText(IDX, iColumn, lp);
		}
		else
		{
			break;
		}
	}
 
	va_end(list);
 
	if (IDX >= 0)
		_AllocItemMemory(IDX);
 
	return IDX;
}
 
BOOL CReportCtrl::_IsEditVisible() const
{
	return m_bAllowEdit
		&& m_ptEditting.x >= 0 && m_ptEditting.x < CListCtrlColumnEx::GetItemCount()
		&& m_ptEditting.y >= 0 && m_ptEditting.y < GetColumnCount();
}
 
void CReportCtrl::SetEditable(BOOL bSet)
{	
	if (!bSet)
		EndEdit(TRUE);
	m_bAllowEdit = bSet;
 
	if ( m_bAllowEdit )
	{
		ModifyStyle(LVS_EDITLABELS, 0, 0);
	}
}
 
BOOL CReportCtrl::IsEditable() const
{
	return m_bAllowEdit;
}
 
BOOL CReportCtrl::_ItemCheckMonitor(int nIndex, BOOL bBefore, BOOL bAfter, UINT nMsg)
{
	if (!_IsValidIndex(nIndex)
		|| m_nChkStyle == RC_CHKBOX_NONE
		|| (bBefore && bAfter)
		|| (!bBefore && !bAfter))
	{
		return FALSE;
	}
 
	if (m_nChkStyle == RC_CHKBOX_SINGLE)
	{
		// Only one item can be checked
		if (!bBefore && bAfter)
		{
			SetAllItemStates(RC_ITEM_CHECKED, RC_ITEM_UNCHECKED); // uncheck all
			SetItemStates(nIndex, RC_ITEM_CHECKED);
		}		
	}
	else if (m_nChkStyle == RC_CHKBOX_DISABLED)
	{
		// Cannot change the item checked/unchecked states by mouse clicks
		SetItemStates(nIndex, bBefore ? RC_ITEM_CHECKED : RC_ITEM_UNCHECKED);
		return TRUE;
	}	
 
	SetAllItemStates(RC_ITEM_SELECTED, RC_ITEM_UNSELECTED); // unselect all
	SetItemStates(nIndex, RC_ITEM_SELECTED | RC_ITEM_FOCUSED);
	GetParent()->SendMessage(WM_ON_CHKBOX, (WPARAM)nIndex, (LPARAM)nMsg);
	return TRUE;
}
 
int CReportCtrl::GetCheckboxStyle() const
{
	return m_nChkStyle;
}
 
void CReportCtrl::_StringSplit(const CString &str, CStringArray &arr, TCHAR chDelimitior)
{
	int nStart = 0, nEnd = 0;
	arr.RemoveAll();
 
	while (nEnd < str.GetLength())
	{
		// determine the paragraph ("xxx,xxx,xxx;")
		nEnd = str.Find(chDelimitior, nStart);
		if( nEnd == -1 )
		{
			// reached the end of string
			nEnd = str.GetLength();
		}
 
		CString s = str.Mid(nStart, nEnd - nStart);
		if (!s.IsEmpty())
			arr.Add(s);
 
		nStart = nEnd + 1;
	}
}
 
BOOL CReportCtrl::SetSortable(BOOL bSet)
{
	if (!HasColumnHeader())
		return FALSE;
 
	LONG lStyle = ::GetWindowLong(GetHeaderCtrl()->GetSafeHwnd(), GWL_STYLE);
	if (bSet)
	{
		lStyle |= HDS_BUTTONS;
	}
	else
	{
		lStyle &= ~HDS_BUTTONS;
		_UnsetSortedColumn();
	}
	::SetWindowLong(GetHeaderCtrl()->GetSafeHwnd(), GWL_STYLE, lStyle);
	CListCtrlColumnEx::GetHeaderCtrl()->RedrawWindow();
	return TRUE;
}
 
DWORD CReportCtrl::SetExtendedStyle(DWORD dwNewStyle)
{
	dwNewStyle &= ~MUST_NOT_EX_STYLE;
	dwNewStyle |= MUST_EX_STYLE;
	return CListCtrlColumnEx::SetExtendedStyle(dwNewStyle);
}
 
BOOL CReportCtrl::PreCreateWindow(CREATESTRUCT& cs) 
{
	// TODO: Add your specialized code here and/or call the base class
	cs.style &= ~MUST_NOT_STYLE;
	cs.style |= MUST_STYLE;
	return CListCtrlColumnEx::PreCreateWindow(cs);
}
 
BOOL CReportCtrl::PreTranslateMessage(MSG* pMsg) 
{
	// TODO: Add your specialized code here and/or call the base class
	if (pMsg->message == WM_KEYDOWN)
	{
		if (!_IsEditVisible())
		{
			// disable user from check/uncheck the checkboxes using space key
			// things get nasty if the user is HOLDING the space bar down
			if (pMsg->wParam == VK_SPACE)
				return TRUE;
		}
		else
		{
			POINT pt = m_ptEditting;
			switch (pMsg->wParam)
			{
			case VK_ESCAPE: // Cancel edit
				EndEdit(FALSE);
				return TRUE;
 
			case VK_RETURN: // Commit edit
				EndEdit(TRUE);
				return TRUE;
 
			case VK_TAB: // switch edit sub items
				if (pt.y == GetColumnCount() - 1)
					pt.y = 0;
				else
					pt.y++;
				EndEdit(TRUE);
				StartEdit(pt.x, pt.y);
				return TRUE;
 
			case VK_UP: // edit upper item
				if (pt.x > 0)
				{
					pt.x--;
					EndEdit(TRUE);
					StartEdit(pt.x, pt.y);
					EnsureVisible(pt.x, FALSE);
					return TRUE;
				}
				break;
				
			case VK_DOWN: // edit lower item
				if (pt.x < CListCtrlColumnEx::GetItemCount() - 1)
				{
					pt.x++;
					EndEdit(TRUE);
					StartEdit(pt.x, pt.y);
					EnsureVisible(pt.x, FALSE);
					return TRUE;
				}
				break;			
 
			default:
				break;				
			}
		}
	}
 
	return CListCtrlColumnEx::PreTranslateMessage(pMsg);
}
 
CEdit* CReportCtrl::GetEditControl()
{
	if ( !m_bAllowEdit )
		return CListCtrlColumnEx::GetEditControl();
	return m_pWndEdit;
}
 
BOOL CReportCtrl::Create(CWnd* pParentWnd, UINT nID, LPCRECT lpRect, DWORD dwStyle) 
{
	// TODO: Add your specialized code here and/or call the base class
	ASSERT(pParentWnd != NULL);
 
	dwStyle &= ~MUST_NOT_STYLE;
	dwStyle |= MUST_STYLE;
 
	CRect rect;
	if (lpRect == NULL)
		pParentWnd->GetClientRect(&rect);
	else
		rect = *lpRect;
 
	return CListCtrlColumnEx::Create(dwStyle, rect, pParentWnd, nID);
}
 
void CReportCtrl::PreSubclassWindow() 
{
	// TODO: Add your specialized code here and/or call the base class
	LONG lStyle = ::GetWindowLong(GetSafeHwnd(), GWL_STYLE);
	lStyle &= ~MUST_NOT_STYLE;
	lStyle |= MUST_STYLE;
	::SetWindowLong(GetSafeHwnd(), GWL_STYLE, lStyle);
	SetExtendedStyle(0);
	ASSERT(GetHeaderCtrl() != NULL);
	CListCtrlColumnEx::PreSubclassWindow();
}
 
BOOL CReportCtrl::IsSortable() const
{
	if (!HasColumnHeader())
		return FALSE;
 
	LONG lStyle = ::GetWindowLong(GetHeaderCtrl()->GetSafeHwnd(), GWL_STYLE);
	return (lStyle & HDS_BUTTONS) != 0;
}
 
BOOL CReportCtrl::HasColumnHeader() const
{
	return (GetStyle() & LVS_NOCOLUMNHEADER) == 0;
}
 
void CReportCtrl::ResizeToFitParent()
{
	// resize the list ctrl to fit parent client area
	if (GetSafeHwnd() != NULL)
	{
		CRect rect;
		GetParent()->GetClientRect(&rect);
		MoveWindow(&rect);
	}
}
 
BOOL CReportCtrl::ModifyStyleEx(DWORD dwRemove, DWORD dwAdd, UINT nFlags)
{
	dwRemove &= ~MUST_EX_STYLE;
	dwRemove |= MUST_NOT_EX_STYLE;
	dwAdd &= ~MUST_NOT_EX_STYLE;
	dwAdd |= MUST_EX_STYLE;
	return CListCtrlColumnEx::ModifyStyleEx(dwRemove, dwAdd, nFlags);
}
 
BOOL CReportCtrl::ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags)
{
	dwRemove &= ~MUST_STYLE;
	dwRemove |= MUST_NOT_STYLE;
	dwAdd &= ~MUST_NOT_STYLE;
	dwAdd |= MUST_STYLE;
 
	return CListCtrlColumnEx::ModifyStyle(dwRemove, dwAdd, nFlags);
}
 
void CReportCtrl::_MouseClkMonitor(UINT nMsg, UINT nFlags, CPoint point, BOOL bTriggerEdit)
{
	LVHITTESTINFO hti;
	hti.pt = point;
	const int IDX = SubItemHitTest(&hti);
	const BOOL BEFORE = CListCtrlColumnEx::GetCheck(IDX) > 0;
	const BOOL WAS_EDIT = _IsEditVisible();
	EndEdit(TRUE);
	const BOOL WASACTIVE = bTriggerEdit ? ExamItemStates(IDX, RC_ITEM_FOCUSED | RC_ITEM_SELECTED) : FALSE;
 
	switch (nMsg)
	{
	case WM_LBUTTONDOWN:
		CListCtrlColumnEx::OnLButtonDown(nFlags, point);
		break;
 
	case WM_LBUTTONDBLCLK:
		CListCtrlColumnEx::OnLButtonDblClk(nFlags, point);
		break;
 
	case WM_MBUTTONDOWN:
		CListCtrlColumnEx::OnMButtonDown(nFlags, point);
		break;
 
	case WM_MBUTTONDBLCLK:
		CListCtrlColumnEx::OnMButtonDblClk(nFlags, point);
		break;
 
	case WM_RBUTTONDOWN:
		CListCtrlColumnEx::OnRButtonDown(nFlags, point);
		break;
 
	case WM_RBUTTONDBLCLK:
		CListCtrlColumnEx::OnRButtonDblClk(nFlags, point);
		break;
 
	default:
		break;		
	}
	
	const BOOL STATSCHANGED = _ItemCheckMonitor(IDX, BEFORE, CListCtrlColumnEx::GetCheck(IDX) > 0, nMsg);
 
	if (bTriggerEdit && m_bAllowEdit && !STATSCHANGED && !WAS_EDIT && WASACTIVE)
		StartEdit(IDX, hti.iSubItem);
}
 
BOOL CReportCtrl::SetItemImage(int nItem, int nSubItem, int nImageIndex)
{
	return CListCtrlColumnEx::SetItem(nItem, nSubItem, LVIF_IMAGE, NULL, nImageIndex, 0, 0, 0);
}
 
int CReportCtrl::GetItemImage(int nItem, int nSubItem) const
{
	LVITEM lvi;
	lvi.iItem = nItem;
	lvi.iSubItem = nSubItem;
	lvi.mask = LVIF_IMAGE;
	return CListCtrlColumnEx::GetItem(&lvi) ? lvi.iImage : -1;
}
 
CImageList* CReportCtrl::SetImageList(CImageList *pImageList)
{
	return CListCtrlColumnEx::SetImageList(pImageList, LVSIL_SMALL);
}
 
CImageList* CReportCtrl::GetImageList() const
{
	return CListCtrlColumnEx::GetImageList(LVSIL_SMALL);
}
 
CImageList* CReportCtrl::SetImageList(UINT nBitmapID, COLORREF crMask)
{
	m_imgList.DeleteImageList();
	m_imgList.Create(nBitmapID, 16, 4, crMask);	
	return CListCtrlColumnEx::SetImageList(&m_imgList, LVSIL_SMALL);
}
 
BOOL CReportCtrl::StartEdit(int nItem, int nSubItem)
{
	// Get the grid width and height
	if (!m_bAllowEdit || !_IsValidIndex(nItem) || nSubItem < 0 || nSubItem >= GetColumnCount())
		return FALSE;
	
	if (m_ptEditting.x == nItem && m_ptEditting.y == nSubItem)
		return TRUE;
 
	EndEdit(TRUE);
	m_ptEditting.x = nItem;
	m_ptEditting.y = nSubItem;
	SetAllItemStates(RC_ITEM_SELECTED, RC_ITEM_UNSELECTED); // unselect all
	SetItemStates(m_ptEditting.x, RC_ITEM_SELECTED | RC_ITEM_FOCUSED);
 
	// determine editbox font and alignment
	const DWORD FMT = _GetHeaderTextFormat(nSubItem);
	if (FMT != m_dwPrevEditFmt)
	{
		m_dwPrevEditFmt = FMT;
 
		// Funny thing:
		// Changing CEdit style among ES_LEFT, ES_CENTER, ES_RIGHT at runtime works
		// sometimes and fails other times. It just cannot guarantee to be succeed.
		// So I decided to destroy and recreate the CEdit every time when the text
		// format changes.
		if (m_pWndEdit->GetSafeHwnd() != NULL)
			m_pWndEdit->DestroyWindow();
 
		if (!m_pWndEdit->Create(ES_AUTOHSCROLL | ES_NOHIDESEL | WS_CHILD | WS_BORDER | FMT, CRect(0, 0, 1, 1), this, 0))
			return FALSE;
	}
	else
	{
		if (m_pWndEdit->GetSafeHwnd() == NULL
			&& !m_pWndEdit->Create(ES_AUTOHSCROLL | ES_NOHIDESEL | WS_CHILD | WS_BORDER | FMT, CRect(0, 0, 1, 1), this, 0))
		{
			return FALSE;
		}
	}
 
	m_pWndEdit->SetFont(GetFont());
 
	CRect rcEdit;
	ListView_GetSubItemRect(GetSafeHwnd(), m_ptEditting.x, m_ptEditting.y, LVIR_LABEL, &rcEdit);
	if (m_ptEditting.y > 0 && GetImageList() != NULL && GetItemImage(m_ptEditting.x, m_ptEditting.y) >= 0)
		rcEdit.DeflateRect(16, 0, 0, 0);
 
	// Move the editbox to that grid, obtain text from the grid, display the
	// editbox, and, finally, highlights all text in the editbox and set the
	// windows focus to the editbox.
	m_pWndEdit->MoveWindow(&rcEdit);
	m_pWndEdit->SetWindowText(GetItemText(m_ptEditting.x, m_ptEditting.y));
	m_pWndEdit->ShowWindow(SW_SHOW);
	m_pWndEdit->SetSel(0, -1);
	m_pWndEdit->SetFocus();
	return TRUE;
}
 
BOOL CReportCtrl::EndEdit(BOOL bCommit)
{
	if (!_IsEditVisible())
		return FALSE;
 
	CString str;
	m_pWndEdit->GetWindowText(str);
	BOOL bChanged = bCommit && str.Compare(GetItemText(m_ptEditting.x, m_ptEditting.y)) != 0;
	if (bChanged)
	{
		// update the list item
		CListCtrlColumnEx::SetItemText(m_ptEditting.x, m_ptEditting.y, str);
		_UnsetSortedColumn();
		GetParent()->SendMessage(WM_EDIT_COMMITTED, (WPARAM)m_ptEditting.x, (LPARAM)m_ptEditting.y);
	}
	m_pWndEdit->ShowWindow(SW_HIDE);
	m_ptEditting.x = -1;
	m_ptEditting.y = -1;
	return bChanged;
}
 
BOOL CReportCtrl::SetHeaderImage(int nColumn, int nImageIndex, BOOL bLeftSide)
{
	if (GetHeaderCtrl()->GetImageList() == NULL)
		CListCtrlColumnEx::GetHeaderCtrl()->SetImageList(GetImageList());
	
	HDITEM hi;
	::memset(&hi, 0, sizeof(HDITEM));
	hi.mask = HDI_FORMAT;
	if (!GetHeaderCtrl()->GetItem(nColumn, &hi))
		return FALSE;
	
	hi.mask |= HDI_IMAGE;		
	hi.fmt |= HDF_IMAGE;
 
	if (!bLeftSide)
		hi.fmt |= HDF_BITMAP_ON_RIGHT; // draw the image on right side of text

	hi.iImage = nImageIndex;
	return CListCtrlColumnEx::GetHeaderCtrl()->SetItem(nColumn, &hi);
}
 
int CReportCtrl::GetSortedColumn() const
{
	return m_nSortCol;
}
 
BOOL CReportCtrl::IsSortAscending() const
{
	return m_bSortAscending;
}
 
void CReportCtrl::_UnsetSortedColumn()
{
	m_nSortCol = -1;
	m_bSortAscending = TRUE;
}
 
DWORD CReportCtrl::_GetHeaderTextFormat(int nColumn) const
{
	if (!HasColumnHeader())
		return ES_LEFT;
 
	HDITEM hd;
	hd.mask = HDI_FORMAT;
	if (!GetHeaderCtrl()->GetItem(nColumn, &hd))
		return ES_LEFT;
 
	if (hd.fmt & HDF_CENTER)
	{	
		return ES_CENTER;
	}
	else if (hd.fmt & HDF_RIGHT)
	{
		return ES_RIGHT;
	}
	else
	{
		return ES_LEFT;
	}
}
 
int CReportCtrl::GetHeaderImage(int nColumn) const
{
	HDITEM hi;
	::memset(&hi, 0, sizeof(HDITEM));
	hi.mask = HDI_IMAGE;
	return !GetHeaderCtrl()->GetItem(nColumn, &hi) ? hi.iImage : -1;
}
 
CImageList* CReportCtrl::SetHeaderImageList(CImageList *pImageList)
{
	return CListCtrlColumnEx::GetHeaderCtrl()->SetImageList(pImageList);
}
 
CImageList* CReportCtrl::SetHeaderImageList(UINT nBitmapID, COLORREF crMask)
{
	m_headerImgList.Create(nBitmapID, 16, 4, crMask);
	return SetHeaderImageList(&m_headerImgList);
}
 
BOOL CReportCtrl::ExamItemStates(int nItem, DWORD dwStates) const
{
	if (dwStates == RC_ITEM_NONE)
		return FALSE;
 
	if (dwStates & RC_ITEM_ALL)
		return TRUE;
 
	return (GetItemStates(nItem) & dwStates) == dwStates;
}
 
int CReportCtrl::GetItemCount(DWORD dwStates) const
{
	const int ITEMS = CListCtrlColumnEx::GetItemCount();
	if (dwStates == RC_ITEM_ALL)
		return ITEMS;
 
	int nCount = 0;
	for (int i = 0; i <ITEMS; i++)
	{
		if (ExamItemStates(i, dwStates))
			nCount++;
	}
	return nCount;
}
 
int CReportCtrl::GetFirstItem(DWORD dwStates, int nStartAfter) const
{
	const int ITEMS = CListCtrlColumnEx::GetItemCount();
	nStartAfter = max(-1, nStartAfter);
	for (int i = nStartAfter + 1; i <ITEMS; i++)
	{
		if (ExamItemStates(i, dwStates))
			return i;
	}
	return -1;
}
 
int CReportCtrl::GetLastItem(DWORD dwStates, int nStartBefore) const
{
	const int ITEMS = CListCtrlColumnEx::GetItemCount();
	nStartBefore = nStartBefore < 0 ? ITEMS - 1 : min(ITEMS, nStartBefore);
	for (int i = nStartBefore - 1; i >= 0; i--)
	{
		if (ExamItemStates(i, dwStates))
			return i;
	}
	return -1;
}
 
void CReportCtrl::InvertItems(int nType)
{
	const int ITEMS = CListCtrlColumnEx::GetItemCount();
	if (nType == RC_INVERT_SELECTION)
	{
		for (int i = 0; i < ITEMS; i++)
			SetItemStates(i, ExamItemStates(i, RC_ITEM_SELECTED) ? RC_ITEM_UNSELECTED : RC_ITEM_SELECTED);
	}
	else if (nType == RC_INVERT_CHECKMARK)
	{
		for (int i = 0; i < ITEMS; i++)
			SetItemStates(i, ExamItemStates(i, RC_ITEM_CHECKED) ? RC_ITEM_UNCHECKED : RC_ITEM_CHECKED);
	}
}
 
DWORD CReportCtrl::GetItemStates(int nItem) const
{
	DWORD dwStates = 0;
 
	if (CListCtrlColumnEx::GetItemState(nItem, LVIS_SELECTED))
		dwStates |= RC_ITEM_SELECTED;
	else
		dwStates |= RC_ITEM_UNSELECTED;
 
	if (CListCtrlColumnEx::GetCheck(nItem) > 0)
		dwStates |= RC_ITEM_CHECKED;
	else
		dwStates |= RC_ITEM_UNCHECKED;
 
	if (CListCtrlColumnEx::GetItemState(nItem, LVIS_FOCUSED))
		dwStates |= RC_ITEM_FOCUSED;
	else
		dwStates |= RC_ITEM_UNFOCUSED;
 
	return dwStates;
}
 
BOOL CReportCtrl::SetItemStates(int nItem, DWORD dwNewStates)
{
	BOOL bResult = _SetItemStatesNoVerify(nItem, dwNewStates);
	if (dwNewStates & RC_ITEM_CHECKED)
		_EnsureSingleCheck(nItem);
	return bResult;
}
 
int CReportCtrl::SetAllItemStates(DWORD dwOldStates, DWORD dwNewStates)
{
	if (dwNewStates == RC_ITEM_NONE || dwOldStates == RC_ITEM_NONE)
		return 0;
 
	int nCount = 0;
	const int ITEMS = CListCtrlColumnEx::GetItemCount();
	for (int i = 0; i < ITEMS; i++)
	{
		if (dwOldStates == RC_ITEM_ALL || ExamItemStates(i, dwOldStates))
		{
			SetItemStates(i, dwNewStates);
			nCount++;
		}
	}
 
	if (dwNewStates & RC_ITEM_CHECKED)
		_EnsureSingleCheck(-1);
 
	return nCount;
}
 
void CReportCtrl::_EnsureSingleCheck(int nItem)
{
	if (m_nChkStyle == RC_CHKBOX_SINGLE)
	{
		const int FIRST = nItem < 0 ? GetFirstItem(RC_ITEM_CHECKED) : nItem;
		if (FIRST >= 0)
		{
			const int ITEMS = CListCtrlColumnEx::GetItemCount();
			for (int i = FIRST + 1; i < ITEMS; i++)
			{
				if (CListCtrlColumnEx::GetCheck(i))
					CListCtrlColumnEx::SetCheck(i, FALSE);
			}
		}		
	}
}
 
BOOL CReportCtrl::_SetItemStatesNoVerify(int nItem, DWORD dwNewStates)
{
	if (dwNewStates == RC_ITEM_NONE)
		return FALSE;
	
	BOOL bResult = TRUE;
	
	if (dwNewStates & RC_ITEM_SELECTED)
		bResult &= CListCtrlColumnEx::SetItemState(nItem, LVIS_SELECTED, LVIS_SELECTED);
 
	if (dwNewStates & RC_ITEM_UNSELECTED)
		bResult &= CListCtrlColumnEx::SetItemState(nItem, 0, LVIS_SELECTED);
 
	if (dwNewStates & RC_ITEM_CHECKED)
		bResult &= CListCtrlColumnEx::SetCheck(nItem, TRUE);
 
	if (dwNewStates & RC_ITEM_UNCHECKED)
		bResult &= CListCtrlColumnEx::SetCheck(nItem, FALSE);
 
	if (dwNewStates & RC_ITEM_FOCUSED)
		bResult &= CListCtrlColumnEx::SetItemState(nItem, LVIS_FOCUSED, LVIS_FOCUSED);
 
	if (dwNewStates & RC_ITEM_UNFOCUSED)
		bResult &= CListCtrlColumnEx::SetItemState(nItem, 0, LVIS_FOCUSED);
 
	return bResult;
}
 
BOOL CReportCtrl::SetCheck(int nItem, BOOL bCheck)
{
	const BOOL RES = CListCtrlColumnEx::SetCheck(nItem, bCheck);
	if (RES && bCheck)
		_EnsureSingleCheck(nItem);
	return RES;
}
 
CString CReportCtrl::GetHeaderText(int nColumn) const
{
	if (!HasColumnHeader())
		return _T("");
 
	HDITEM hd;
	TCHAR  szBuffer[256] = _T("");
	hd.mask = HDI_TEXT;
	hd.pszText = szBuffer;
	hd.cchTextMax = 255;
	return GetHeaderCtrl()->GetItem(nColumn, &hd) ? hd.pszText : _T("");
}
 
BOOL CReportCtrl::SetHeaderText(int nColumn, LPCTSTR lpText)
{
	if (!HasColumnHeader())
		return FALSE;
 
	LPTSTR psz = NULL;
	if (lpText == NULL)
	{
		psz = new TCHAR[1];
		*psz = _T('\0');
	}
	else
	{
		psz = _tcsdup(lpText);
	}
	HDITEM hd;
	hd.mask = HDI_TEXT;
	hd.pszText = psz;
	hd.cchTextMax = _tcslen(psz);
	const BOOL RES = CListCtrlColumnEx::GetHeaderCtrl()->SetItem(nColumn, &hd);
	delete [] psz;
	return RES;
}
 
const CHeaderCtrl* CReportCtrl::GetHeaderCtrl() const
{
	// Yes, CListCtrlColumnEx already provides "GetHeaderCtrl", but not const.	
	// I desperately need a "const" version of "GetHeaderCtrl" because that's the
	// only way to make "GetColumnCount" const, which, in turn, is being called by
	// A LOT of const member functions. So if "GetHeaderCtrl" is not const, there will
	// be almost no const member function at all in this class. Terrible.
	return (const CHeaderCtrl*)(CWnd::FromHandle(ListView_GetHeader(GetSafeHwnd())));
}
 
void CReportCtrl::_FreeItemMemory(int nItem)
{
	CItemData* p = (CItemData*)(CListCtrlColumnEx::GetItemData(nItem));
	if (p != NULL)
	{
		CListCtrlColumnEx::SetItemData(nItem, 0);
		delete p;
	}
}
 
void CReportCtrl::_AllocItemMemory(int nItem)
{
	ASSERT(_IsValidIndex(nItem));
	const int COLS = GetColumnCount();
	ASSERT(COLS > 0);
	CItemData* pData = new CItemData;	
	pData->dwData = CListCtrlColumnEx::GetItemData(nItem);
	pData->aTextColors.SetSize(COLS);
	pData->aBkColors.SetSize(COLS);
	for (int i = 0; i < COLS; i++)
	{
		pData->aTextColors[i] = ::GetSysColor(COLOR_WINDOWTEXT);
		pData->aBkColors[i] = ::GetSysColor(COLOR_WINDOW);
	}
	CListCtrlColumnEx::SetItemData(nItem, (DWORD)pData);
}
 
void CReportCtrl::_UpdateColumn(int nColumn, BOOL bInsert)
{
	const int ITEMS = GetItemCount();
	for (int i = 0; i < ITEMS; i++)
	{
		CItemData* p = (CItemData*)(CListCtrlColumnEx::GetItemData(i));
		ASSERT(p != NULL);
		if (bInsert)
			p->InsertColumn(nColumn);
		else
			p->DeleteColumn(nColumn);
	}
}
 
BOOL CReportCtrl::SetItemData(int nItem, DWORD dwData)
{
	CItemData* p = (CItemData*)(CListCtrlColumnEx::GetItemData(nItem));
	if (p == NULL)
		return FALSE;
	p->dwData = dwData;
	return CListCtrlColumnEx::SetItemData(nItem, (DWORD)p);
}
 
DWORD CReportCtrl::GetItemData(int nItem) const
{
	CItemData* p = (CItemData*)(CListCtrlColumnEx::GetItemData(nItem));
	return p == NULL ? 0 : p->dwData;
}
 
BOOL CReportCtrl::GetItem(LVITEM *pItem) const
{
	const BOOL RES = CListCtrlColumnEx::GetItem(pItem);
	if (RES && (pItem->mask & LVIF_PARAM) != 0)
	{
		CItemData* p = (CItemData*)(pItem->lParam);
		if (p != NULL)
			pItem->lParam = p->dwData;
	}
	return RES;
}
 
BOOL CReportCtrl::SetItem(const LVITEM *pItem)
{
	if (pItem == NULL)
		return FALSE;
	
	LVITEM li;
	memcpy(&li, pItem, sizeof(LVITEM));
	if ((li.mask & LVIF_PARAM) != 0)
	{
		CItemData* p = (CItemData*)(CListCtrlColumnEx::GetItemData(li.iItem));
		if (p != NULL)
		{
			p->dwData = li.lParam;
			li.lParam = (LPARAM)p;
		}		
	}
	return CListCtrlColumnEx::SetItem(&li);
}
 
BOOL CReportCtrl::SetItem(int nItem, int nSubItem, UINT nMask, LPCTSTR lpszItem, int nImage, UINT nState, UINT nStateMask, LPARAM lParam)
{
	if ((nMask & LVIF_PARAM) != 0)
	{
		CItemData* p = (CItemData*)(CListCtrlColumnEx::GetItemData(nItem));
		if (p != NULL)
		{
			p->dwData = lParam;
			lParam = (LPARAM)p;
		}		
	}
	return CListCtrlColumnEx::SetItem(nItem, nSubItem, nMask, lpszItem, nImage, nState, nStateMask, lParam);
}
 
void CReportCtrl::SetItemTextColor(int nItem, int nSubItem, COLORREF color, BOOL bRedraw)
{
	if (color == COLOR_INVALID)
		color = ::GetSysColor(COLOR_WINDOWTEXT);
	const int ROWS = GetItemCount();
	const int COLS = GetColumnCount();
	BOOL bRowValid = nItem >= 0 && nItem < ROWS;
	BOOL bColValid = nSubItem >= 0 && nSubItem < COLS;
 
	if (bRowValid && bColValid)
	{
		// apply to individual grid
		CItemData* p = (CItemData*)(CListCtrlColumnEx::GetItemData(nItem));
		ASSERT(p != NULL);
		p->aTextColors[nSubItem] = color;
	}
	else if (bRowValid && !bColValid)
	{
		// apply to whole row for the existing item
		CItemData* p = (CItemData*)(CListCtrlColumnEx::GetItemData(nItem));
		ASSERT(p != NULL);
		for (int i = 0; i < COLS; i++)
			p->aTextColors[i] = color;
	}
	else if (!bRowValid && bColValid)
	{
		// apply to whole column for all existing items
		for (int i = 0; i < ROWS; i++)
		{
			CItemData* p = (CItemData*)(CListCtrlColumnEx::GetItemData(i));
			ASSERT(p != NULL);
			p->aTextColors[nSubItem] = color;
		}
	}
	else
	{
		// apply to whole table for all existing items
		for (int i = 0; i < ROWS; i++)
		{
			CItemData* p = (CItemData*)(CListCtrlColumnEx::GetItemData(i));
			ASSERT(p != NULL);
			for (int j = 0; j < COLS; j++)
				p->aTextColors[j] = color;
		}
	}
 
	if (bRedraw)
		RedrawWindow();
}
 
void CReportCtrl::SetItemBkColor(int nItem, int nSubItem, COLORREF color, BOOL bRedraw)
{
	if (color == COLOR_INVALID)
		color = ::GetSysColor(COLOR_WINDOW);
	const int ROWS = GetItemCount();
	const int COLS = GetColumnCount();
	BOOL bRowValid = nItem >= 0 && nItem < ROWS;
	BOOL bColValid = nSubItem >= 0 && nSubItem < COLS;
 
	if (bRowValid && bColValid)
	{
		// apply to individual grid
		CItemData* p = (CItemData*)(CListCtrlColumnEx::GetItemData(nItem));
		ASSERT(p != NULL);
		p->aBkColors[nSubItem] = color;
	}
	else if (bRowValid && !bColValid)
	{
		// apply to whole row for the existing item
		CItemData* p = (CItemData*)(CListCtrlColumnEx::GetItemData(nItem));
		ASSERT(p != NULL);
		for (int i = 0; i < COLS; i++)
			p->aBkColors[i] = color;
	}
	else if (!bRowValid && bColValid)
	{
		// apply to whole column for all existing items
		for (int i = 0; i < ROWS; i++)
		{
			CItemData* p = (CItemData*)(CListCtrlColumnEx::GetItemData(i));
			ASSERT(p != NULL);
			p->aBkColors[nSubItem] = color;
		}
	}
	else
	{
		// apply to whole table for all existing items
		for (int i = 0; i < ROWS; i++)
		{
			CItemData* p = (CItemData*)(CListCtrlColumnEx::GetItemData(i));
			ASSERT(p != NULL);
			for (int j = 0; j < COLS; j++)
				p->aBkColors[j] = color;
		}
	}
 
	if (bRedraw)
		RedrawWindow();
}
 
COLORREF CReportCtrl::GetItemTextColor(int nItem, int nSubItem) const
{
	if (!_IsValidIndex(nItem) || nSubItem < 0 || nSubItem >= GetColumnCount())
		return COLOR_INVALID;
	CItemData* p = (CItemData*)(CListCtrlColumnEx::GetItemData(nItem));
	ASSERT(p != NULL);
	return p->aTextColors[nSubItem];
}
 
COLORREF CReportCtrl::GetItemBkColor(int nItem, int nSubItem) const
{
	if (!_IsValidIndex(nItem) || nSubItem < 0 || nSubItem >= GetColumnCount())
		return COLOR_INVALID;
	CItemData* p = (CItemData*)(CListCtrlColumnEx::GetItemData(nItem));
	ASSERT(p != NULL);
	return p->aBkColors[nSubItem];
}
 
BOOL CReportCtrl::_PartialSort(int nStart, int nEnd)
{
	if (nStart >= nEnd || !_IsValidIndex(nStart) || !_IsValidIndex(nEnd))
		return FALSE;
 
	const int COUNT = nEnd - nStart + 1;
	int i = 0;
	int* aIndices = new int[COUNT];
	for (i = 0; i < COUNT; i++)
		aIndices[i] = nStart + i;
	
	_QuickSortRecursive(aIndices, 0, COUNT - 1); 
 
	// rearrange items
	const int COLS = GetColumnCount();
	ROWINFO* aRows = new ROWINFO[COUNT];
	for (i = 0; i < COUNT; i++)
	{
		int n = aIndices[i];
		aRows[i].dwStates = GetItemStates(aIndices[i]);
		aRows[i].dwData = CListCtrlColumnEx::GetItemData(aIndices[i]);
		aRows[i].aImages.SetSize(COLS);
		aRows[i].aTexts.SetSize(COLS);
		for (int j = 0; j < COLS; j++)
		{
			aRows[i].aImages[j] = GetItemImage(aIndices[i], j);
			aRows[i].aTexts[j] = GetItemText(aIndices[i], j);
		}
	}
 
	for (i = 0; i < COUNT; i++)
	{
		SetItemStates(nStart + i, aRows[i].dwStates);
		CListCtrlColumnEx::SetItemData(nStart + i, aRows[i].dwData);
		for (int j = 0; j < COLS; j++)
		{
			SetItemImage(nStart + i, j, aRows[i].aImages[j]);			
			CListCtrlColumnEx::SetItemText(nStart + i, j, aRows[i].aTexts[j]);
		}
	}
	delete [] aRows;
	delete [] aIndices;
	return TRUE;
}
 
int CReportCtrl::_CompareItems(int nItem1, int nItem2)
{
	const CString s1 = GetItemText(nItem1, m_nSortCol);
	const CString s2 = GetItemText(nItem2, m_nSortCol);
 
	DWORD dw1, dw2;
	if(_ITEM_COMPARE_FUNCS::_IsHexNumber(s1, dw1) && _ITEM_COMPARE_FUNCS::_IsHexNumber(s2, dw2))
		return _ITEM_COMPARE_FUNCS::_HexNumberCompare(dw1, dw2);
 
	double f1, f2;
	if(_ITEM_COMPARE_FUNCS::_IsDecNumber(s1, f1) && _ITEM_COMPARE_FUNCS::_IsDecNumber(s2, f2))
		return _ITEM_COMPARE_FUNCS::_DecNumberCompare(f1, f2);
 
	// 修改 by wxg [10/20/2009 14:50:03] 当字符串中含有特殊字符时,下面的语句会有异常,故注掉
// 	COleDateTime date1, date2;
// 	if(_ITEM_COMPARE_FUNCS::_IsDate(s1, date1) && _ITEM_COMPARE_FUNCS::_IsDate(s2, date2))
// 		return _ITEM_COMPARE_FUNCS::_DateCompare(date1, date2);
	
	// plain text.
	return s1.CompareNoCase(s2);
}
 
int CReportCtrl::_FindSeparator(int nStartAfter, int nColumn) const
{
	if (m_pszSeparator == NULL)
		return -1;
 
	const int ITEMS = GetItemCount();
	for (int i = nStartAfter + 1; i < ITEMS; i++)
	{
		if (GetItemText(i, nColumn) == m_pszSeparator)
			return i;
	}
	return -1;
}
 
void CReportCtrl::_QuickSortRecursive(int* pArr, int nLow, int nHigh)
{
	int i = nHigh, j = nLow;
	int n = pArr[(nLow + nHigh) / 2];
	do
	{
		if (m_bSortAscending)
		{
			while (_CompareItems(pArr[j], n) < 0)
				j++;
 
			while (_CompareItems(pArr[i], n) > 0)
				i--;
		}
		else
		{
			while (_CompareItems(pArr[j], n) > 0)
				j++;
 
			while (_CompareItems(pArr[i], n) < 0)
				i--;
		}
 
		if ( i >= j )
		{
			if ( i != j )
			{
				int nTemp = pArr[i];
				pArr[i] = pArr[j];
				pArr[j] = nTemp;
			}
 
			i--;
			j++;
		}
		
	} while (j <= i);
 
	if (nLow < i)
		_QuickSortRecursive(pArr,nLow,i);
 
	if (j < nHigh)
		_QuickSortRecursive(pArr,j,nHigh);
}
 
//mlj added 081104
void CReportCtrl::AdjustColumnWidth()
{
	SetRedraw(FALSE);
	int nColumnCount = GetColumnCount();
 
	for(int i = 0; i < nColumnCount; i++)
	{
		SetColumnWidth(i, LVSCW_AUTOSIZE);
		int nColumnWidth = GetColumnWidth(i);
		SetColumnWidth(i, LVSCW_AUTOSIZE_USEHEADER);
		int nHeaderWidth = GetColumnWidth(i);
 
		SetColumnWidth(i, max(nColumnWidth, nHeaderWidth));
	}
	SetRedraw(TRUE);
}
 
int CReportCtrl::GetColumnCount()
{
	return(GetHeaderCtrl()->GetItemCount());
}
 
int CReportCtrl::GetCurSel()
{
    POSITION    pos             = GetFirstSelectedItemPosition ();
    int         nSelectedItem   = - 1;
    if ( pos != NULL )
    {
        nSelectedItem = GetNextSelectedItem ( pos );
    }
    return nSelectedItem;
}
 
void CReportCtrl::OnFilterChange(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NMHEADER	*pNMHdr = (NMHEADER*)pNMHDR;
	CWnd		*pParent = GetParent();
 
	*pResult = 0;											// Default RetCode
	if( pParent )											// If Parent Exists
	{
		pNMHdr -> hdr.idFrom = GetDlgCtrlID();				// Update Structure Data
		*pResult = pParent -> SendNotifyMessage( WM_NOTIFY, 
				GetDlgCtrlID(), (LPARAM)pNMHdr );			// Forward Message
	}
	return;													// Done!
}
 
void CReportCtrl::OnFilterButtonClicked(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NMHDFILTERBTNCLICK	*pNMFButtonClick = (NMHDFILTERBTNCLICK*)pNMHDR;
	NMHEADER			*pNMHdr = (NMHEADER*)pNMHDR;
	CWnd				*pParent = GetParent();
 
	*pResult = 0;											// Default RetCode
	if( pParent )											// If Parent Exists
	{
		pNMHdr -> hdr.idFrom = GetDlgCtrlID();				// Update Structure Data
		*pResult = pParent -> SendNotifyMessage( WM_NOTIFY, 
				GetDlgCtrlID(), (LPARAM)pNMHdr );			// Forward Message
	}
	return;													// Done!
}
 
void CReportCtrl::ClearAllFilter()
{
	CHeaderCtrl	*pHeader = (CHeaderCtrl	*)GetHeaderCtrl();
	if ( pHeader != NULL )
	{
		Header_ClearAllFilters( pHeader -> m_hWnd );		
	}
}
 
void CReportCtrl::CancelAllSelectedState()
{
	CDWordArray aryIndex;
	GetAllSelectedIndexs(aryIndex);
 
	for ( int i = 0; i < aryIndex.GetSize(); ++i )
	{
		SetItemState(aryIndex.GetAt(i), 0, LVIS_SELECTED);
	}
}
 
int CReportCtrl::GetAllSelectedIndexs(CDWordArray &aryIndex)
{
	aryIndex.RemoveAll();
	POSITION pos = GetFirstSelectedItemPosition();
	while (pos)
	{
		aryIndex.Add(GetNextSelectedItem(pos));
	}
 
	return aryIndex.GetSize();
}
//////////////////////////////////////////////////////////////////////////
//start CListCtrlColumnEx
CListCtrlColumnEx::CListCtrlColumnEx()
{
	m_bNoChangedFirstColumn = FALSE;	
	m_bShowRightMenu = FALSE;
 
	m_strIdentifier = _T("");
	m_bNeedSaveStatus = FALSE;
}
 
CListCtrlColumnEx::~CListCtrlColumnEx()
{
	
}
 
BEGIN_MESSAGE_MAP(CListCtrlColumnEx, CListCtrl)
	ON_MESSAGE(LVM_DELETECOLUMN, OnDeleteColumn)
	ON_MESSAGE(LVM_INSERTCOLUMN, OnInsertColumn)
	ON_MESSAGE(LVM_SETCOLUMNWIDTH, OnSetColumnWidth)
	ON_NOTIFY_EX(HDN_BEGINTRACKA, 0, OnHeaderBeginResize)
	ON_NOTIFY_EX(HDN_BEGINTRACKW, 0, OnHeaderBeginResize)
	ON_NOTIFY_EX(HDN_ENDTRACKA, 0, OnHeaderEndResize)
	ON_NOTIFY_EX(HDN_ENDTRACKW, 0, OnHeaderEndResize)
	ON_NOTIFY_EX(HDN_ENDDRAG, 0, OnHeaderEndDrag)
	ON_NOTIFY_EX(HDN_DIVIDERDBLCLICKA, 0, OnHeaderDividerDblClick)
	ON_NOTIFY_EX(HDN_DIVIDERDBLCLICKW, 0, OnHeaderDividerDblClick)
	ON_WM_CONTEXTMENU()	// OnContextMenu
	ON_WM_KEYDOWN()		// OnKeyDown
	ON_WM_DESTROY()
	ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
	ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
END_MESSAGE_MAP()
 
int CListCtrlColumnEx::GetFirstVisibleColumn()
{
	int nColCount = GetHeaderCtrl()->GetItemCount();
	for(int i = 0; i < nColCount; ++i)
	{
		int nCol = GetHeaderCtrl()->OrderToIndex(i);
		if (IsColumnVisible(nCol))
		{
			return nCol;
		}
	}
	return -1;
}
 
BOOL CListCtrlColumnEx::ShowColumn(int nCol, bool bShow)
{
	SetRedraw(FALSE);
 
	ColumnState& columnState = GetColumnState(nCol);
 
	if (bShow)
	{
		// Restore the column width
		columnState.m_Visible = true;
		if ( columnState.m_OrgWidth == 0 )
		{
			columnState.m_OrgWidth = LVSCW_AUTOSIZE;
		}
		VERIFY( SetColumnWidth(nCol, columnState.m_OrgWidth) );
	}
	else
	{
		// Backup the column width
		int orgWidth = GetColumnWidth(nCol);
		VERIFY( SetColumnWidth(nCol, 0) );
		columnState.m_Visible = false;
		columnState.m_OrgWidth = orgWidth;
	}
	SetRedraw(TRUE);
	Invalidate(FALSE);
	return TRUE;
}
 
BOOL CListCtrlColumnEx::SetColumnWidthAuto(int nCol, bool includeHeader)
{
	if (nCol == -1)
	{
		for(int i = 0; i < GetHeaderCtrl()->GetItemCount() ; ++i)
		{
			SetColumnWidthAuto(i, includeHeader);
		}
		return TRUE;
	}
	else
	{
		if (includeHeader)
			return SetColumnWidth(nCol, LVSCW_AUTOSIZE_USEHEADER);
		else
			return SetColumnWidth(nCol, LVSCW_AUTOSIZE);
	}
}
 
CListCtrlColumnEx::ColumnState& CListCtrlColumnEx::GetColumnState(int nCol)
{
	VERIFY( nCol >=0 && nCol < m_ColumnStates.GetSize() );
	return m_ColumnStates[nCol];
}
 
bool CListCtrlColumnEx::IsColumnVisible(int nCol)
{
	return GetColumnState(nCol).m_Visible;
}
 
int CListCtrlColumnEx::GetColumnStateCount()
{
	return m_ColumnStates.GetSize();
}
 
void CListCtrlColumnEx::InsertColumnState(int nCol, bool bVisible, int nOrgWidth, CString strText)
{
	VERIFY( nCol >=0 && nCol <= m_ColumnStates.GetSize() );
 
	ColumnState columnState;
	columnState.m_OrgWidth = nOrgWidth;
	columnState.m_Visible = bVisible;
	columnState.m_strText = strText;
	columnState.m_OrgPosition = nCol;
 
	if (nCol == m_ColumnStates.GetSize())
	{
		// Append column picker to the end of the array
		m_ColumnStates.Add(columnState);
	}
	else
	{
		// Insert column in the middle of the array
		CSimpleArray<ColumnState> newArray;
		for(int i=0 ; i < m_ColumnStates.GetSize(); ++i)
		{
			if (i == nCol)
				newArray.Add(columnState);
			newArray.Add(m_ColumnStates[i]);
		}
		m_ColumnStates = newArray;
	}
}
 
void CListCtrlColumnEx::DeleteColumnState(int nCol)
{
	VERIFY( nCol >=0 && nCol < m_ColumnStates.GetSize() );
	m_ColumnStates.RemoveAt(nCol);
}
 
void CListCtrlColumnEx::OnContextMenu(CWnd* pWnd, CPoint point)
{
	if ( !m_bShowRightMenu )
	{
		return;
	}
 
	if (point.x==-1 && point.y==-1)
	{
		// OBS! point is initialized to (-1,-1) if using SHIFT+F10 or VK_APPS
	}
	else
	{
		CPoint pt = point;
		ScreenToClient(&pt);
 
		CRect headerRect;
		GetHeaderCtrl()->GetClientRect(&headerRect);
		if (headerRect.PtInRect(pt))
		{
			// Show context-menu with the option to show hide columns
			CMenu menu;
			if (menu.CreatePopupMenu())
			{
				for( int i = GetColumnStateCount()-1 ; i >= 0; --i)
				{
					UINT uFlags = MF_BYPOSITION | MF_STRING | MF_ENABLED;
 
					// Put check-box on context-menu
					if (IsColumnVisible(i))
						uFlags |= MF_CHECKED;
					else
						uFlags |= MF_UNCHECKED;
 
					if(GetReadOnlyShowState(i))
						uFlags |= MF_GRAYED;
 
					// Retrieve column-title
					LVCOLUMN lvc = {0};
					lvc.mask = LVCF_TEXT;
					TCHAR sColText[256];
					lvc.pszText = sColText;
					lvc.cchTextMax = sizeof(sColText)-1;
					VERIFY( GetColumn(i, &lvc) );
 
					menu.InsertMenu(0, uFlags, i, lvc.pszText);
				}
 
/*
								if ( menu.GetMenuItemCount() > 0 && m_bNoChangedFirstColumn )
								{
									menu.EnableMenuItem(0, MF_BYCOMMAND | MF_GRAYED);
								}
 
				*/
//				menu.EnableMenuItem(i, MF_BYCOMMAND | GetReadOnlyShowState(i) ? MF_GRAYED : MF_ENABLED);
				menu.TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, this, 0);
			}
		}
	}
}
 
// Handle context-menu event for showing / hiding columns
BOOL CListCtrlColumnEx::OnCommand(WPARAM wParam, LPARAM lParam)
{
	if (HIWORD(wParam) == 0)
	{
		int nCol = LOWORD(wParam);
		if ( m_bShowRightMenu && nCol >= 0 && nCol < GetColumnStateCount() )
		{
			ShowColumn(nCol, !IsColumnVisible(nCol));
		}
	}
 
	return CListCtrl::OnCommand(wParam, lParam);
}
 
void CListCtrlColumnEx::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// 	switch(nChar)
// 	{
// 		case VK_ADD:	// CTRL + NumPlus (Auto size all columns)
// 		{
// 			if (GetKeyState(VK_CONTROL) < 0)
// 			{
// 				// Special handling to avoid showing "hidden" columns
// 				SetColumnWidthAuto(-1);
// 				return;
// 			}
// 		} break;
// 	}
	CListCtrl::OnKeyDown(nChar, nRepCnt, nFlags);
}
 
BOOL CListCtrlColumnEx::OnHeaderBeginResize(UINT id, NMHDR* pNMHDR, LRESULT* pResult)
{
	// Check that column is allowed to be resized
	NMHEADER* pNMH = (NMHEADER*)pNMHDR;
	int nCol = (int)pNMH->iItem;
	if (!IsColumnVisible(nCol))
	{
		*pResult = TRUE;	// Block resize
		return TRUE;		// Block event
	}
	return DefWindowProc(HDN_BEGINTRACK, (WPARAM)id, (LPARAM)pNMHDR);
}
 
BOOL CListCtrlColumnEx::OnHeaderEndResize( UINT id, NMHDR* pNmhdr, LRESULT* pResult )
{
	NMHEADER* pNMH = (NMHEADER*)pNmhdr;
	int nCol = (int)pNMH->iItem;
	
	m_ColumnStates[nCol].m_OrgWidth = pNMH->pitem->cxy;
	
	*pResult = TRUE;
	return DefWindowProc(HDN_ENDTRACK, (WPARAM)id, (LPARAM)pNmhdr);
}
 
LRESULT CListCtrlColumnEx::OnSetColumnWidth(WPARAM wParam, LPARAM lParam)
{
	// Check that column is allowed to be resized
	int nCol = (int)wParam;
	if (!IsColumnVisible(nCol))
	{
		return FALSE;
	}
	// Let the CListCtrl handle the event
	return DefWindowProc(LVM_SETCOLUMNWIDTH, wParam, lParam);
}
 
BOOL CListCtrlColumnEx::OnHeaderEndDrag(UINT id, NMHDR* pNMHDR, LRESULT* pResult)
{
	NMHEADER* pNMH = (NMHEADER*)pNMHDR;
	if (pNMH->pitem->mask & HDI_ORDER)
	{
		// Correct iOrder so it is just after the last hidden column
		int nColCount = GetHeaderCtrl()->GetItemCount();
		int* pOrderArray = new int[nColCount];
		VERIFY( GetColumnOrderArray(pOrderArray, nColCount) );
 
		for(int i = 0; i < nColCount ; ++i)
		{
			if (IsColumnVisible(pOrderArray[i]))
			{
                pNMH->pitem->iOrder = max(pNMH->pitem->iOrder,i);
				break;
			}
		}
		delete [] pOrderArray;
	}
	return DefWindowProc(HDN_ENDTRACK, (WPARAM)id, (LPARAM)pNMHDR);
}
 
BOOL CListCtrlColumnEx::OnHeaderDividerDblClick(UINT id, NMHDR* pNMHDR, LRESULT* pResult)
{
	NMHEADER* pNMH = (NMHEADER*)pNMHDR;
	SetColumnWidthAuto(pNMH->iItem);
	m_ColumnStates[pNMH->iItem].m_OrgWidth = GetColumnWidth(pNMH->iItem);
	return TRUE;	// Don't let parent handle the event
}
 
LRESULT CListCtrlColumnEx::OnDeleteColumn(WPARAM wParam, LPARAM lParam)
{
	// Let the CListCtrl handle the event
	LRESULT lRet = DefWindowProc(LVM_DELETECOLUMN, wParam, lParam);
	if (lRet == FALSE)
		return FALSE;
 
	// Book keeping of columns
	DeleteColumnState((int)wParam);
	return lRet;
}
 
LRESULT CListCtrlColumnEx::OnInsertColumn(WPARAM wParam, LPARAM lParam)
{
	// Let the CListCtrl handle the event
	LRESULT lRet = DefWindowProc(LVM_INSERTCOLUMN, wParam, lParam);
	if (lRet == -1)
		return -1;
 
	int nCol = (int)lRet;
 
	// Book keeping of columns
	if (GetColumnStateCount() < GetHeaderCtrl()->GetItemCount())
	{
		HDITEM hdi;
		TCHAR  lpBuffer[256];
		bool   fFound = false;
		
		hdi.mask = HDI_TEXT;
		hdi.pszText = lpBuffer;
		hdi.cchTextMax = 256;
		if ( GetHeaderCtrl()->GetItem(nCol, &hdi) )
		{
			InsertColumnState((int)nCol, true, GetColumnWidth(nCol), hdi.pszText);	// Insert as visible
		}
	}
 
	return lRet;
}
 

namespace {
	LRESULT EnableWindowTheme(HWND hwnd, LPCWSTR classList, LPCWSTR subApp, LPCWSTR idlist)
	{
		LRESULT lResult = S_FALSE;
		HMODULE hinstDll;
		BOOL (WINAPI *pIsThemeActive)();
		HRESULT (WINAPI *pSetWindowTheme)(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList);
		HANDLE (WINAPI *pOpenThemeData)(HWND hwnd, LPCWSTR pszClassList);
		HRESULT (WINAPI *pCloseThemeData)(HANDLE hTheme);
 
		// Check if running on Windows XP or newer
		hinstDll = ::LoadLibrary(_T("UxTheme.dll"));
		if (hinstDll)
		{
			// Check if theme service is running
			(FARPROC&)pIsThemeActive = ::GetProcAddress( hinstDll, "IsThemeActive" );
			if( pIsThemeActive && pIsThemeActive() )
			{
				(FARPROC&)pOpenThemeData = ::GetProcAddress(hinstDll, "OpenThemeData");
				(FARPROC&)pCloseThemeData = ::GetProcAddress(hinstDll, "CloseThemeData");
				(FARPROC&)pSetWindowTheme = ::GetProcAddress(hinstDll, "SetWindowTheme");
				if (pSetWindowTheme && pOpenThemeData && pCloseThemeData)			
				{
					// Check is themes is available for the application
					HANDLE hTheme = pOpenThemeData(hwnd,classList);
					if (hTheme!=NULL)
					{
						VERIFY(pCloseThemeData(hTheme)==S_OK);
						// Enable Windows Theme Style
						lResult = pSetWindowTheme(hwnd, subApp, idlist);
					}
				}
			}
			::FreeLibrary(hinstDll);
		}
		return lResult;
	}
}
 
void CListCtrlColumnEx::PreSubclassWindow()
{
	CListCtrl::PreSubclassWindow();
 
	// Focus retangle is not painted properly without double-buffering
#if (_WIN32_WINNT >= 0x501)
	SetExtendedStyle(LVS_EX_DOUBLEBUFFER | GetExtendedStyle());
#endif
//	SetExtendedStyle(GetExtendedStyle() | LVS_EX_FULLROWSELECT);
//	SetExtendedStyle(GetExtendedStyle() | LVS_EX_HEADERDRAGDROP);
//	SetExtendedStyle(GetExtendedStyle() | LVS_EX_GRIDLINES);

	// Enable Vista-look if possible
//	EnableWindowTheme(GetSafeHwnd(), L"ListView", L"Explorer", NULL);
}
 
void CListCtrlColumnEx::ResetHeaderState(BOOL bNoHideFirstColumn, CString strIdentifier)
{
	m_bNoChangedFirstColumn = bNoHideFirstColumn;
	m_strIdentifier = strIdentifier;
	m_bNeedSaveStatus = TRUE;
 
	TCHAR szName[1024];
	GetModuleFileName(NULL, szName, 1023);
	TCHAR *pFileName = _tcsrchr(szName, '\\') + 1;
 
	int nCtrlId = GetDlgCtrlID();
 
	CString strIdentifierInReg;
	strIdentifierInReg.Format(_T("%s_%d_%s"), pFileName, nCtrlId, m_strIdentifier);
 
	CString strRegValue = GetRegister(strIdentifierInReg);
 
	if ( strRegValue.IsEmpty() )
	{
		return;
	}
 
	std::map<CString, int> mapHeader;
	std::map<CString, int>::iterator mapIter;
	int nHeaderCount = GetHeaderCtrl()->GetItemCount();
 
	HDITEM hdi;
	TCHAR  lpBuffer[256];
	bool   fFound = false;
	
	hdi.mask = HDI_TEXT;
	hdi.pszText = lpBuffer;
	hdi.cchTextMax = 256;
 
	for ( int nIndexHeader = 0; nIndexHeader < nHeaderCount; ++nIndexHeader )
	{
		CString strHeaderText;
		if ( GetHeaderCtrl()->GetItem(nIndexHeader, &hdi) )
		{
			strHeaderText = hdi.pszText;
		}
 
		mapHeader.insert(std::make_pair(strHeaderText, nIndexHeader));
	}
 
	CStringArray sDestination;
	SplitString(strRegValue, sDestination, '\1');
 
	if ( sDestination.GetSize() != nHeaderCount )
	{
		return;
	}
 
	CSimpleArray<ColumnState> newArray;
	int i = 0;
	for ( i = 0; i < m_ColumnStates.GetSize(); ++i )
	{
		ColumnState columnState = m_ColumnStates[i];
		newArray.Add(columnState);
	}
 
	for ( i = 0; i < sDestination.GetSize(); ++i )
	{
		CStringArray sDestination2;
		SplitString(sDestination.GetAt(i), sDestination2, '\2');
		if ( sDestination2.GetSize() != 4 )
		{
			continue;
		}
 
		mapIter = mapHeader.find(sDestination2.GetAt(0));
		if ( mapIter != mapHeader.end() && mapIter->second < newArray.GetSize() )
		{
			newArray[mapIter->second].m_OrgPosition	 = _ttoi(sDestination2.GetAt(1));
			newArray[mapIter->second].m_OrgWidth	 = _ttoi(sDestination2.GetAt(2));
			newArray[mapIter->second].m_Visible		 = _ttoi(sDestination2.GetAt(3));
		}
		else
		{
			return;
		}
	}
 
	m_ColumnStates.RemoveAll();
	for ( i = 0; i < newArray.GetSize(); ++i )
	{
		ColumnState columnState = newArray[i];
		m_ColumnStates.Add(columnState);
	}
 
	int* pOrderArray = new int[nHeaderCount];
	int nIndexState = 0;
	for ( nIndexState = 0; nIndexState < m_ColumnStates.GetSize(); ++nIndexState )
	{
		pOrderArray[m_ColumnStates[nIndexState].m_OrgPosition] = nIndexState;
	}
 
	for ( nIndexState = 0; nIndexState < nHeaderCount; ++nIndexState )
	{
		if ( !m_ColumnStates[nIndexState].m_Visible )
		{
			m_ColumnStates[nIndexState].m_Visible = true;
			ShowColumn(nIndexState, false);
		}
		else
		{
			ShowColumn(nIndexState, true);
		}
	}
 
	SetColumnOrderArray(nHeaderCount, pOrderArray);
	delete []pOrderArray;
 
	if ( m_bNoChangedFirstColumn )
	{
		AddReadOnlyShowState(m_ColumnStates[0].m_strText);
	}
}
 
void CListCtrlColumnEx::OnDestroy()
{
	CListCtrl::OnDestroy();
 
	if ( !m_bNeedSaveStatus ) return;
	
	CString strText, strTemp;
	
	int nHeaderCount = m_ColumnStates.GetSize();
	int* pOrderArray = new int[nHeaderCount];
	
	if ( GetColumnOrderArray(pOrderArray, nHeaderCount) )
	{
		for ( int nIndexState = 0; nIndexState < nHeaderCount; ++nIndexState )
		{
			m_ColumnStates[pOrderArray[nIndexState]].m_OrgPosition = nIndexState;
		}
	}
	delete []pOrderArray;
	
	for( int i = 0 ; i < nHeaderCount; ++i )
	{
		strTemp.Format(_T("%s\2%d\2%d\2%d"), m_ColumnStates[i].m_strText, 
			m_ColumnStates[i].m_OrgPosition, 
			m_ColumnStates[i].m_OrgWidth, 
			m_ColumnStates[i].m_Visible);
		
		strText += strTemp;
		if ( i < (nHeaderCount - 1) )
		{
			strText += _T("\1");
		}
	}	
	
	TCHAR szName[1024];
	GetModuleFileName(NULL, szName, 1023);
	TCHAR *pFileName = _tcsrchr(szName, '\\') + 1;
	
	int nCtrlId = GetDlgCtrlID();
	
	CString strIdentifierInReg;
	strIdentifierInReg.Format(_T("%s_%d_%s"), pFileName, nCtrlId, m_strIdentifier);
	
	SetRegister(strIdentifierInReg, strText);
}
 
void CListCtrlColumnEx::SplitString(LPCTSTR sSource, CStringArray &sDestination, TCHAR cToken)
{
	int     nIndex  = 0;
	BOOL    ret;
	CString subStr;
	sDestination.RemoveAll ();
	while ( TRUE )
	{
		ret = AfxExtractSubString ( subStr , sSource , nIndex , cToken );
		if ( ! ret )
		{
			return;
		}
		if ( ! subStr.IsEmpty () )
		{
			sDestination.Add ( subStr );
		}
		nIndex++;
	}
}
 
// 功能描述:读取注册表信息
CString CListCtrlColumnEx::GetRegister(LPCTSTR lpszName,LPCTSTR lpszPath)
{
	CString strValue = _T("");
	CString strName = lpszName;
	if(strName.IsEmpty())
		return strValue;
	
	CRegKey regKey;
	try
	{
		if(regKey.Open(HKEY_CURRENT_USER,lpszPath) != ERROR_SUCCESS)
		{//如果不能打开,则退出
			return strValue;
		}
		TCHAR szValue[1024];
		DWORD sl = 1023;
		LONG lReturn = regKey.QueryValue(szValue,lpszName,&sl);
		if( lReturn == ERROR_SUCCESS)
		{
			strValue = szValue;
		}
		regKey.Close();
	}
	catch (...)
	{
		UINT unErro = GetLastError();
		return strValue;
	}
	return strValue;
}
 
// 功能描述:保存注册表信息
BOOL CListCtrlColumnEx::SetRegister(LPCTSTR lpszName, LPCTSTR lpszValue,LPCTSTR lpszKeyName)
{
	CString strName = lpszName;
	if(strName.IsEmpty())
		return FALSE;
	
	CRegKey regKey;
	try
	{
		if(regKey.Open(HKEY_CURRENT_USER,lpszKeyName) != ERROR_SUCCESS)
		{//如果不能打开,则新建一个
			if(regKey.Create(HKEY_CURRENT_USER,lpszKeyName) != ERROR_SUCCESS)
			{
				//如果建立不成功,返回FALSE
				return FALSE;
			}
		}
		if(regKey.SetValue(lpszValue,lpszName) != ERROR_SUCCESS)
		{
			return FALSE;
		}
		regKey.Close();
	}
	catch (...)
	{
		regKey.Close();
		return FALSE;
	}
	return TRUE;
}
 
void CListCtrlColumnEx::AddReadOnlyShowState(LPCTSTR pszColumnName)
{
	m_setReadOnlyShowState.insert(pszColumnName);
}
 
BOOL CListCtrlColumnEx::GetReadOnlyShowState(int i)
{
	std::set<CString>::iterator setIter = m_setReadOnlyShowState.find(GetColumnState(i).m_strText);
	return (setIter != m_setReadOnlyShowState.end());
}
 
void CListCtrlColumnEx::SetShowRightMenu( BOOL bShowRightMenu )
{
	m_bShowRightMenu = bShowRightMenu;
}
 
BOOL CListCtrlColumnEx::IsShowRightMenu()
{
	return 	m_bShowRightMenu;
}
 
int CListCtrlColumnEx::OnToolHitTest(CPoint point, TOOLINFO * pTI) const
{
 
   //See if the point falls onto a list item
	//UINT nFlags = 0;

	LVHITTESTINFO lvhitTestInfo;
 
	lvhitTestInfo.pt	= point;
 
	int nItem = ListView_SubItemHitTest(
			this->m_hWnd,
			&lvhitTestInfo);
	int nSubItem = lvhitTestInfo.iSubItem;
 
	UINT nFlags =   lvhitTestInfo.flags;
 
   //nFlags is 0 if the SubItemHitTest fails
   //Therefore, 0 & <anything> will equal false
   if (nFlags & LVHT_ONITEMLABEL){
      //If it did fall on a list item,
      //and it was also hit one of the
      //item specific sub-areas we wish to show tool tips for

      //Get the client (area occupied by this control
      RECT rcClient;
      GetClientRect( &rcClient );
 
      //Fill in the TOOLINFO structure
      pTI->hwnd = m_hWnd;
      pTI->uId = (UINT) (nItem * 100 + nSubItem);
      pTI->lpszText = LPSTR_TEXTCALLBACK;
      pTI->rect = rcClient;
 
      return pTI->uId; //By returning a unique value per listItem,
                       //we ensure that when the mouse moves over another list item,
                       //the tooltip will change
   }else{
      //Otherwise, we aren't interested, so let the message propagate
      return -1;
   }
}
 
BOOL CListCtrlColumnEx::OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
{
	//Handle both ANSI and UNICODE versions of the message
	TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
	TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
 
	//Ignore messages from the built in tooltip, we are processing them internally
	if( (pNMHDR->idFrom == (UINT)m_hWnd) &&
		 ( ((pNMHDR->code == TTN_NEEDTEXTA) && (pTTTA->uFlags & TTF_IDISHWND)) ||
         ((pNMHDR->code == TTN_NEEDTEXTW) && (pTTTW->uFlags & TTF_IDISHWND)) ) ){
      return FALSE;
   }
 

   *pResult = 0;
 
	CString strTipText;
 
	//Get the mouse position
	const MSG* pMessage;
   pMessage = GetCurrentMessage();
	ASSERT ( pMessage );
   CPoint pt;
   pt = pMessage->pt; //Get the point from the message
	ScreenToClient( &pt ); //Convert the point's coords to be relative to this control

   //See if the point falls onto a list item

	LVHITTESTINFO lvhitTestInfo;
 
	lvhitTestInfo.pt	= pt;
 
	int nItem = SubItemHitTest(&lvhitTestInfo);
	int nSubItem = lvhitTestInfo.iSubItem;
 
	UINT nFlags =   lvhitTestInfo.flags;
 
   //nFlags is 0 if the SubItemHitTest fails
   //Therefore, 0 & <anything> will equal false
	if( nFlags & LVHT_ONITEMLABEL )
	{
	  //If it did fall on a list item,
	  //and it was also hit one of the
	  //item specific sub-areas we wish to show tool tips for

		strTipText = GetItemToolTipText(nItem, nSubItem);
		if( !strTipText.IsEmpty() )
		{
		 //If there was a CString associated with the list item,
		 //copy it's text (up to 80 characters worth, limitation of the TOOLTIPTEXT structure)
		 //into the TOOLTIPTEXT structure's szText member

		 //Deal with UNICODE
			#ifndef _UNICODE
			if (pNMHDR->code == TTN_NEEDTEXTA)
				lstrcpyn(pTTTA->szText, strTipText, 80);
			else
				_mbstowcsz(pTTTW->szText, strTipText, 80);
			#else
			if (pNMHDR->code == TTN_NEEDTEXTA)
				_wcstombsz(pTTTA->szText, strTipText, 80);
			else
				lstrcpyn(pTTTW->szText, strTipText, 80);
			#endif
			return FALSE;    //We found a tool tip,
						 //tell the framework this message has been handled						
		}
	}
 
   return FALSE; //We didn't handle the message,
                 //let the framework continue propagating the message
}
 
CString CListCtrlColumnEx::GetItemToolTipText( int nItem, int nSubItem )
{
	if ( nItem < 0 || nSubItem < 0 )
	{
		return _T("");
	}
 
	return GetItemText(nItem, nSubItem);
}
 
列头检索功能实例:
BOOL C***::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) 
{
	CHeaderCtrl	*pHeader = NULL;
	NMHEADER	*pNMHdr = (NMHEADER*)lParam;
	int			iFC = HDN_FILTERCHANGE;
	int			iFBC = HDN_FILTERBTNCLICK;
 
	if( pNMHdr -> hdr.idFrom == IDC_LIST1 )	
	{
		if( pNMHdr -> hdr.code == HDN_FILTERCHANGE )
		{
			pHeader = (CHeaderCtrl *)m_cList.GetHeaderCtrl();
 
			if( pNMHdr -> iItem == -1 )
			{
				TRACE( _T( "FilterChanged On ALL Columns...\n" ) );
			}
			else											
			{
				TRACE1( _T( "FilterChanged On Column %d...  " ), pNMHdr -> iItem );
			}
			PopulateControlBasedOnFilter();				
		}
		else if( pNMHdr -> hdr.code == HDN_FILTERBTNCLICK )	
		{
			LPNMHDFILTERBTNCLICK	pNMBClick = (LPNMHDFILTERBTNCLICK)pNMHdr;
 
			TRACE1( _T( "FilterButtonClicked On Column %d...\n" ), pNMBClick -> iItem );
 
			return( TRUE );
		}
	}
	*pResult = 0;
 
	return CDialog::OnNotify(wParam, lParam, pResult);
}
 
void C***::PopulateControlBasedOnFilter()
{
	HDTEXTFILTER	hdTFilter;
	CWaitCursor		WAIT_CURSOR;
	CHeaderCtrl		*pHeader = (CHeaderCtrl *)m_cList.GetHeaderCtrl();
	HDITEM			hdItem;
	int				iColumns = 0;
 
	_ASSERTE( pHeader );								
	iColumns = pHeader -> GetItemCount();
	
	int nSortColumn = m_cList.GetSortedColumn();
	BOOL bIsAsc = m_cList.IsSortAscending();
 
	m_cList.SetRedraw( FALSE );
	UpdateListData();
 
	BOOL bIsAllSpace = TRUE;
	char cFilter[512];
	for( int iCol = 0; iCol < iColumns; iCol++ )		
	{
		hdItem.mask = ( HDI_FILTER );					
		ZeroMemory( cFilter, sizeof( cFilter ) );		
		hdTFilter.pszText = cFilter;					
		hdTFilter.cchTextMax = sizeof( cFilter );		
		hdItem.type = HDFT_ISSTRING;					
		hdItem.pvFilter = &hdTFilter;					
 
		pHeader -> GetItem( iCol, &hdItem );			
		if( strlen( cFilter ) )							
		{
			bIsAllSpace = FALSE;
			strupr(cFilter);
			for ( int loop = m_cList.GetItemCount() - 1; loop >= 0; --loop )
			{
				CString strValue = m_cList.GetItemText(loop, iCol);
				strValue.MakeUpper();
				
				CString strValuePinYin = strValue;
				CHzBarCode::ChangeHZBarCode(strValuePinYin);
				strValuePinYin.MakeUpper();
 
				if ( strValue.Find(cFilter) < 0 && strValuePinYin.Find(cFilter) < 0 )
				{
					m_cList.DeleteItem(loop);
				}
			}
		}
	}
 
	m_cList.SetRedraw( TRUE );
	m_cList.SortItems(nSortColumn, bIsAsc);
 
	if ( m_cList.GetItemCount() > 0 ) 
	{
		m_cList.SetItemState(0, LVIS_SELECTED, LVIS_SELECTED);
	}
}

 
General[MFC]当Explorer进程重启后,确保程序的托盘图标还正常显示在任务栏中 Pin
Monday, April 26, 2010 8:09 PM by onlinewan
当Windows的Explorer进程意外终止重启后,程序的托盘图标就不见了。这是由于程序中没有对这种事件没有做处理的缘故。我们可以通过下面的方式解决此问题,在Explorer进程重启后,托盘图标任显示在状态栏。
 
在下面的虚函数中响应Explorer重启事件:
LRESULT CChatServerDlg::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
	// TODO: 在此添加专用代码和/或调用基类
	static UINT s_uTaskbarRestart;     
	if (message == WM_CREATE)     
		s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));             
	if(message == s_uTaskbarRestart)     
	{     
		NOTIFYICONDATA tnd;     
		tnd.cbSize=sizeof(NOTIFYICONDATA);     
		tnd.hWnd=this->m_hWnd;     
		tnd.uID=IDR_MAINFRAME;     
		tnd.uFlags=NIF_MESSAGE|NIF_ICON|NIF_TIP;     
		//tnd.uCallbackMessage= ;     
		tnd.hIcon=LoadIcon(AfxGetInstanceHandle(),     
			MAKEINTRESOURCE(IDR_MAINFRAME));     
		strcpy(tnd.szTip, _T("托盘图标演示"));     
		Shell_NotifyIcon(NIM_ADD,&tnd);
	}
 
	return CDialog::DefWindowProc(message, wParam, lParam);
}

 
General用VC开发截图小工具 Pin
Tuesday, April 20, 2010 9:56 PM by onlinewan
截图对话框源码:
.h
#if !defined(AFX_DLGTEST1_H__CB58A726_ACFB_4A7D_ADE6_D81871CC5421__INCLUDED_)
#define AFX_DLGTEST1_H__CB58A726_ACFB_4A7D_ADE6_D81871CC5421__INCLUDED_
 
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// DlgTest1.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// CDlgTest1 dialog

class CDlgTest1 : public CDialog
{
// Construction
public:
	CDlgTest1(CWnd* pParent = NULL);   // standard constructor

// Dialog Data
	//{{AFX_DATA(CDlgTest1)
	enum { IDD = IDD_DIALOG1 };
		// NOTE: the ClassWizard will add data members here
	//}}AFX_DATA

	static void CapScreenBitmap(CBitmap &memBitmap);
 
	CBitmap m_Bitmap;		//桌面位图
	CBitmap m_ResultBitmap;	//结果位图

// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CDlgTest1)
	public:
	virtual BOOL PreTranslateMessage(MSG* pMsg);
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
 
	// Generated message map functions
	//{{AFX_MSG(CDlgTest1)
	virtual BOOL OnInitDialog();
	afx_msg void OnPaint();
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
 
private:
	CPoint m_ptStart;		//截取区域
	CPoint m_ptEnd;			//截取区域

	BOOL m_bSelected;		//是否已经选择了截取区域
	BOOL m_bDoing;
	HCURSOR m_hCursor;
};
 
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_DLGTEST1_H__CB58A726_ACFB_4A7D_ADE6_D81871CC5421__INCLUDED_)
 
.cpp
// DlgTest1.cpp : implementation file
//

#include "stdafx.h"
#include "截屏.h"
#include "DlgTest1.h"
#include <cmath>
 
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
 
/////////////////////////////////////////////////////////////////////////////
// CDlgTest1 dialog

 
CDlgTest1::CDlgTest1(CWnd* pParent /*=NULL*/)
	: CDialog(CDlgTest1::IDD, pParent)
{
	//{{AFX_DATA_INIT(CDlgTest1)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	m_bSelected = FALSE;
	m_bDoing = FALSE;
}
 

void CDlgTest1::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CDlgTest1)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}
 

BEGIN_MESSAGE_MAP(CDlgTest1, CDialog)
	//{{AFX_MSG_MAP(CDlgTest1)
	ON_WM_PAINT()
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONUP()
	ON_WM_LBUTTONDOWN()
	ON_WM_CREATE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()
 
/////////////////////////////////////////////////////////////////////////////
// CDlgTest1 message handlers

BOOL CDlgTest1::OnInitDialog() 
{
	CDialog::OnInitDialog();
	
	// TODO: Add extra initialization here
	Sleep(500);
	CapScreenBitmap(m_Bitmap);
 
	CRect rect;
	::GetWindowRect(GetDesktopWindow()->m_hWnd, &rect);
	SetWindowPos(&wndTopMost, 0, 0, rect.Width(), rect.Height(), SW_SHOWNA);
	::SetActiveWindow(this->m_hWnd);
	
	m_hCursor = AfxGetApp()->LoadCursor(IDC_CURSOR1);
	SetClassLong(m_hWnd, GCL_HCURSOR, (LONG)m_hCursor);
 
	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}
 
void CDlgTest1::CapScreenBitmap(CBitmap &memBitmap)
{
    CDC *pDC;
    pDC = CDC::FromHandle(::GetDC(GetDesktopWindow()->m_hWnd));
	if(pDC == NULL) return;
    int BitPerPixel = pDC->GetDeviceCaps(BITSPIXEL);
    int Width = pDC->GetDeviceCaps(HORZRES);
    int Height = pDC->GetDeviceCaps(VERTRES);
 
    CDC memDC;
    if(memDC.CreateCompatibleDC(pDC) == 0) return;
    
    CBitmap *oldmemBitmap;
    if(memBitmap.CreateCompatibleBitmap(pDC, Width, Height) == NULL)
	{
		return;
	}
 
   oldmemBitmap = memDC.SelectObject(&memBitmap);
	if(oldmemBitmap == NULL) return;
 
   if(memDC.BitBlt(0, 0, Width, Height, pDC, 0, 0, SRCCOPY) == 0) return;
   memDC.SelectObject(oldmemBitmap);
}
 
void CDlgTest1::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	
	// TODO: Add your message handler code here
	if ( m_bDoing )
	{
		CRect rect1(min(m_ptStart.x, m_ptEnd.x), min(m_ptStart.y, m_ptEnd.y), max(m_ptStart.x, m_ptEnd.x), max(m_ptStart.y, m_ptEnd.y));
		ScreenToClient(&rect1);
 
		CPen* pOldPen = NULL;
		CBrush* pOldBrush = NULL;
		pOldPen = dc.SelectObject(CPen::FromHandle(::CreatePen(PS_SOLID, 0, RGB(10,100,130))));
		pOldBrush = (CBrush*)dc.SelectStockObject(NULL_BRUSH);
 
		dc.Rectangle(&rect1);
 
		if (pOldPen != NULL)
			dc.SelectObject(pOldPen);
		if (pOldBrush != NULL)
			dc.SelectObject(pOldBrush);
 

		rect1.left += 2;
		rect1.top += 2;
		rect1.right -= 2;
		rect1.bottom -= 2;
		CDC   dcMem;   
		dcMem.CreateCompatibleDC(this->GetDC());   
		BITMAP   bitmap;
		m_Bitmap.GetBitmap(&bitmap);   
		CBitmap *pbmpOld = dcMem.SelectObject(&m_Bitmap);   
		this->GetDC()->StretchBlt(rect1.left, rect1.top, rect1.Width(), rect1.Height(), &dcMem, 
			rect1.left, rect1.top, rect1.Width(), rect1.Height(), SRCCOPY);
		dcMem.SelectObject(pbmpOld);
// 		this->GetDC()->StretchBlt(0, 0, rect1.Width(), rect1.Height(), &dcMem, 0, 0,   
// 				bitmap.bmWidth, bitmap.bmHeight, SRCCOPY);

	}
	// Do not call CDialog::OnPaint() for painting messages
}
 
void CDlgTest1::OnMouseMove(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	if ( m_bDoing )
	{
		m_ptEnd = point;
		ClientToScreen(&m_ptEnd);
		this->Invalidate(TRUE);
	}
 
	
	CDialog::OnMouseMove(nFlags, point);
}
 
void CDlgTest1::OnLButtonUp(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	m_bDoing = FALSE;
	m_ptEnd = point;
	ClientToScreen(&m_ptEnd);
 
	if ( fabs(m_ptStart.x - m_ptEnd.x) < 1 && fabs(m_ptStart.y - m_ptEnd.y) < 1 )
	{
		m_bSelected = FALSE;
		CDialog::OnLButtonUp(nFlags, point);
	}
 

	CDC *pDC = GetDC();
	CDC memDC;
	memDC.CreateCompatibleDC(pDC);
	CRect rect1(min(m_ptStart.x, m_ptEnd.x) + 2, min(m_ptStart.y, m_ptEnd.y) + 2, 
				max(m_ptStart.x, m_ptEnd.x) - 2, max(m_ptStart.y, m_ptEnd.y) - 2);
	CBitmap *oldmemBitmap;
	if(m_ResultBitmap.CreateCompatibleBitmap(pDC, rect1.Width(), rect1.Height()) == NULL)
	{
		return;
	}
 
	oldmemBitmap = memDC.SelectObject(&m_ResultBitmap);
	if( memDC.StretchBlt(0, 0, rect1.Width(), rect1.Height(), pDC,
		rect1.left, rect1.top, rect1.Width(), rect1.Height(), SRCCOPY) )
	{
 
	}
	memDC.SelectObject(oldmemBitmap);
 
	CDlgTest1::OnOK();	
}
 
void CDlgTest1::OnLButtonDown(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default
	if ( m_bSelected )
	{
		return;
	}
 
	m_ptStart = point;
	ClientToScreen(&m_ptStart);
	m_bDoing = TRUE;
	
	CDialog::OnLButtonDown(nFlags, point);
}
 
int CDlgTest1::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CDialog::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// TODO: Add your specialized creation code here
	SetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE,
                  GetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE)^0x80000);
	HINSTANCE hInst = LoadLibrary("User32.DLL"); 
	if ( hInst ) 
	{
		typedef BOOL (WINAPI *MYFUNC)(HWND,COLORREF,BYTE,DWORD);
		MYFUNC fun = NULL;
		fun = (MYFUNC)GetProcAddress(hInst, "SetLayeredWindowAttributes");
		if ( fun )
			fun(this->GetSafeHwnd(), 0, 150, 2);
		FreeLibrary(hInst); 
	}
 
	return 0;
}
 
BOOL CDlgTest1::PreTranslateMessage(MSG* pMsg) 
{
	// TODO: Add your specialized code here and/or call the base class
	if ( pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE )
	{
		CDialog::OnCancel();
	}
	if ( pMsg->message == WM_RBUTTONUP )
	{
		CDialog::OnCancel();
	}
	
	return CDialog::PreTranslateMessage(pMsg);
}
 
 

调用对话框源码:
.h
// 截屏Dlg.h : header file
//

#if !defined(AFX_DLG_H__EFED66EB_A124_4791_B8D8_E64E6E1CF01F__INCLUDED_)
#define AFX_DLG_H__EFED66EB_A124_4791_B8D8_E64E6E1CF01F__INCLUDED_
 
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "atlbase.h"
 
const TCHAR	REG_ROOT[]	= _T("Software\\wCutPicTool\\Settings");
 
/////////////////////////////////////////////////////////////////////////////
// CMyDlg dialog

class CMyDlg : public CDialog
{
// Construction
public:
	CMyDlg(CWnd* pParent = NULL);	// standard constructor

// Dialog Data
	//{{AFX_DATA(CMyDlg)
	enum { IDD = IDD_MY_DIALOG };
		// NOTE: the ClassWizard will add data members here
	//}}AFX_DATA

	static BOOL SetRegister(LPCTSTR lpszName, LPCTSTR lpszValue, LPCTSTR lpszKeyName = REG_ROOT);
	static CString GetRegister(LPCTSTR lpszName, LPCTSTR lpszPath = REG_ROOT);
	static void SplitString(LPCTSTR sSource, CStringArray &sDestination, TCHAR cToken);
 
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CMyDlg)
	public:
	virtual BOOL PreTranslateMessage(MSG* pMsg);
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	HICON m_hIcon;
 
	// Generated message map functions
	//{{AFX_MSG(CMyDlg)
	virtual BOOL OnInitDialog();
	afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	afx_msg void OnButton1();
	afx_msg void OnButton2();
	afx_msg void OnClose();
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};
 
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_DLG_H__EFED66EB_A124_4791_B8D8_E64E6E1CF01F__INCLUDED_)

.cpp
// 截屏Dlg.cpp : implementation file
//

#include "stdafx.h"
#include "截屏.h"
#include "截屏Dlg.h"
#include "DlgTest1.h"
 
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
 

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();
 
// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};
 
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}
 
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}
 
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()
 
/////////////////////////////////////////////////////////////////////////////
// CMyDlg dialog

CMyDlg::CMyDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CMyDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CMyDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
 
void CMyDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CMyDlg)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}
 
BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
	//{{AFX_MSG_MAP(CMyDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
	ON_BN_CLICKED(IDC_BUTTON2, OnButton2)
	ON_WM_CLOSE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()
 
/////////////////////////////////////////////////////////////////////////////
// CMyDlg message handlers

BOOL CMyDlg::OnInitDialog()
{
	CDialog::OnInitDialog();
 
	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);
 
	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}
 
	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	CString strAppHandle;
	strAppHandle.Format(_T("%d"), this->m_hWnd);
	SetRegister(_T("AppHandle"), strAppHandle);
 
	CRect desktopRect;
	::GetWindowRect(GetDesktopWindow()->m_hWnd, &desktopRect);
	
	CString strX = GetRegister(_T("WinPos_X"));
	CString strY = GetRegister(_T("WinPos_Y"));
 
	if ( strX.IsEmpty() || strY.IsEmpty() )
	{
		return TRUE;
	}
 
	int nX = atol(strX.IsEmpty() ? _T("10") : strX);
	int nY = atol(strY.IsEmpty() ? _T("10") : strY);
 
	CRect rect;
	this->GetWindowRect(&rect);
	if ( nX+rect.Width() < desktopRect.right && nY+rect.Height() < desktopRect.bottom )
	{
		rect.right = nX+rect.Width();
		rect.bottom = nY+rect.Height();
		rect.left = nX;
		rect.top = nY;
		MoveWindow(&rect);
	}
//	SetWindowPos(&wndTopMost, rect.left, rect.top, rect.Width(), rect.Height(), SW_SHOWNA);
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}
 
void CMyDlg::OnClose() 
{
	// TODO: Add your message handler code here and/or call default
	CRect rect;
	this->GetWindowRect(&rect);
 
	CString strX, strY;
	strX.Format(_T("%d"), rect.left);
	strY.Format(_T("%d"), rect.top);
 
	SetRegister(_T("WinPos_X"), strX);
	SetRegister(_T("WinPos_Y"), strY);	
 
	CDialog::OnClose();
}
 
void CMyDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}
 
// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CMyDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
 
		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;
 
		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}
 
// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CMyDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}
 
void CMyDlg::OnButton1() 
{
	// TODO: Add your control notification handler code here
	CDlgTest1 dlg(GetDesktopWindow());
 
	ShowWindow(SW_MINIMIZE);
 
	if ( dlg.DoModal() ==IDOK )
	{
		if (OpenClipboard()) 
		{
			//清空剪贴板
			EmptyClipboard();
			SetClipboardData(CF_BITMAP, dlg.m_ResultBitmap);
			//关闭剪贴板
			CloseClipboard();
		}
	}
 
	ShowWindow(SW_RESTORE);
}
 
void CMyDlg::OnButton2() 
{
	// TODO: Add your control notification handler code here
	CDlgTest1 dlg(GetDesktopWindow());
 
	ShowWindow(SW_MINIMIZE);
 
	if ( dlg.DoModal() ==IDOK )
	{
		CString strExt = _T("所有文件(*.bmp)|*.bmp|");
		CFileDialog dlgSave(FALSE, 
			_T ("xls"), 
			NULL,
			OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY,
			(LPCTSTR)strExt);
 
		CString strFileName;
		if(dlgSave.DoModal() == IDOK)
		{
			strFileName = dlgSave.GetPathName();
			
			FILE *fp = fopen(strFileName, "w+b");
 
			BITMAP bmp;
			dlg.m_ResultBitmap.GetBitmap(&bmp);
			BITMAPINFOHEADER bih = {0};
			bih.biBitCount = bmp.bmBitsPixel;
			bih.biCompression = BI_RGB;
			bih.biHeight = bmp.bmHeight;
			bih.biPlanes = 1;
			bih.biSize = sizeof(BITMAPINFOHEADER);
			bih.biSizeImage = bmp.bmWidthBytes * bmp.bmHeight;
			bih.biWidth = bmp.bmWidth;
			BITMAPFILEHEADER bfh = {0};
			bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
			bfh.bfSize = bfh.bfOffBits + bmp.bmWidthBytes * bmp.bmHeight;
			bfh.bfType = (WORD)0x4d42;
			fwrite(&bfh, 1, sizeof(BITMAPFILEHEADER), fp);
			fwrite(&bih, 1, sizeof(BITMAPINFOHEADER), fp);
			byte * p = new byte[bmp.bmWidthBytes * bmp.bmHeight];
			GetDIBits(this->GetDC()->m_hDC,
				(HBITMAP) dlg.m_ResultBitmap.m_hObject,
				0,
				bmp.bmHeight,
				p,
				(LPBITMAPINFO) &bih,
				DIB_RGB_COLORS);
			fwrite(p, 1, bmp.bmWidthBytes * bmp.bmHeight, fp);
			delete [] p;
			fclose(fp);
		}
	}
 
	ShowWindow(SW_RESTORE);
}
 
// 功能描述:读取注册表信息
CString CMyDlg::GetRegister(LPCTSTR lpszName,LPCTSTR lpszPath)
{
	CString strValue = _T("");
	CString strName = lpszName;
	if(strName.IsEmpty())
		return strValue;
	
	CRegKey regKey;
	try
	{
		if(regKey.Open(HKEY_CURRENT_USER,lpszPath) != ERROR_SUCCESS)
		{//如果不能打开,则退出
			return strValue;
		}
		TCHAR szValue[1024];
		DWORD sl = 1023;
		LONG lReturn = regKey.QueryValue(szValue,lpszName,&sl);
		if( lReturn == ERROR_SUCCESS)
		{
			strValue = szValue;
		}
		regKey.Close();
	}
	catch (...)
	{
		UINT unErro = GetLastError();
		return strValue;
	}
	return strValue;
}
 
// 功能描述:保存注册表信息
BOOL CMyDlg::SetRegister(LPCTSTR lpszName, LPCTSTR lpszValue,LPCTSTR lpszKeyName)
{
	CString strName = lpszName;
	if(strName.IsEmpty())
		return FALSE;
	
	CRegKey regKey;
	try
	{
		if(regKey.Open(HKEY_CURRENT_USER,lpszKeyName) != ERROR_SUCCESS)
		{//如果不能打开,则新建一个
			if(regKey.Create(HKEY_CURRENT_USER,lpszKeyName) != ERROR_SUCCESS)
			{
				//如果建立不成功,返回FALSE
				return FALSE;
			}
		}
		if(regKey.SetValue(lpszValue,lpszName) != ERROR_SUCCESS)
		{
			return FALSE;
		}
		regKey.Close();
	}
	catch (...)
	{
		regKey.Close();
		return FALSE;
	}
	return TRUE;
}
 
void CMyDlg::SplitString(LPCTSTR sSource, CStringArray &sDestination, TCHAR cToken)
{
	int     nIndex  = 0;
	BOOL    ret;
	CString subStr;
	sDestination.RemoveAll ();
	while ( TRUE )
	{
		ret = AfxExtractSubString ( subStr , sSource , nIndex , cToken );
		if ( ! ret )
		{
			return;
		}
		if ( ! subStr.IsEmpty () )
		{
			sDestination.Add ( subStr );
		}
		nIndex++;
	}
}
 
BOOL CMyDlg::PreTranslateMessage(MSG* pMsg) 
{
	// TODO: Add your specialized code here and/or call the base class

	return CDialog::PreTranslateMessage(pMsg);
}
 
 

主程序实例源码:
.h
// 截屏.h : main header file for the 截屏 application
//

#if !defined(AFX__H__B75C0466_F802_49D4_860E_274339DD06D5__INCLUDED_)
#define AFX__H__B75C0466_F802_49D4_860E_274339DD06D5__INCLUDED_
 
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#ifndef __AFXWIN_H__
	#error include 'stdafx.h' before including this file for PCH
#endif
 
#include "resource.h"		// main symbols

/////////////////////////////////////////////////////////////////////////////
// CMyApp:
// See 截屏.cpp for the implementation of this class
//

class CMyApp : public CWinApp
{
public:
	CMyApp();
 
// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CMyApp)
	public:
	virtual BOOL InitInstance();
	//}}AFX_VIRTUAL

// Implementation

	//{{AFX_MSG(CMyApp)
		// NOTE - the ClassWizard will add and remove member functions here.
		//    DO NOT EDIT what you see in these blocks of generated code !
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};
 

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX__H__B75C0466_F802_49D4_860E_274339DD06D5__INCLUDED_)

.cpp
// 截屏.cpp : Defines the class behaviors for the application.
//

#include "stdafx.h"
#include "截屏.h"
#include "截屏Dlg.h"
 
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
 
/////////////////////////////////////////////////////////////////////////////
// CMyApp

BEGIN_MESSAGE_MAP(CMyApp, CWinApp)
	//{{AFX_MSG_MAP(CMyApp)
		// NOTE - the ClassWizard will add and remove mapping macros here.
		//    DO NOT EDIT what you see in these blocks of generated code!
	//}}AFX_MSG
	ON_COMMAND(ID_HELP, CWinApp::OnHelp)
END_MESSAGE_MAP()
 
/////////////////////////////////////////////////////////////////////////////
// CMyApp construction

CMyApp::CMyApp()
{
	// TODO: add construction code here,
	// Place all significant initialization in InitInstance
}
 
/////////////////////////////////////////////////////////////////////////////
// The one and only CMyApp object

CMyApp theApp;
 
/////////////////////////////////////////////////////////////////////////////
// CMyApp initialization

BOOL CMyApp::InitInstance()
{
	AfxEnableControlContainer();
 
	// Standard initialization
	// If you are not using these features and wish to reduce the size
	//  of your final executable, you should remove from the following
	//  the specific initialization routines you do not need.

#ifdef _AFXDLL
	Enable3dControls();			// Call this when using MFC in a shared DLL
#else
	Enable3dControlsStatic();	// Call this when linking to MFC statically
#endif	
 
	CString strAppHandle;
	HANDLE hMutexHandle = ::CreateMutex(NULL, TRUE, _T("Wanxg_CutPicTool_V1.0"));
	if ( GetLastError() == ERROR_ALREADY_EXISTS )
	{
		strAppHandle = CMyDlg::GetRegister(_T("AppHandle"));
		int nTemp = atoi(strAppHandle);
		HWND hWnd = (HWND)nTemp;
		if ( hWnd != NULL )
		{
			::ShowWindow(hWnd, SW_RESTORE);
			::SetForegroundWindow(hWnd);
			return FALSE;
		}
	}
 
	CMyDlg dlg;
	m_pMainWnd = &dlg;
	int nResponse = dlg.DoModal();
	if (nResponse == IDOK)
	{
		// TODO: Place code here to handle when the dialog is
		//  dismissed with OK
	}
	else if (nResponse == IDCANCEL)
	{
		// TODO: Place code here to handle when the dialog is
		//  dismissed with Cancel
	}
 
	// Since the dialog has been closed, return FALSE so that we exit the
	//  application, rather than start the application's message pump.
	return FALSE;
}
 

资源文件源码:
.rc
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
 
/////////////////////////////////////////////////////////////////////////////
// Chinese (P.R.C.) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
#ifdef _WIN32
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
#pragma code_page(936)
#endif //_WIN32

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE DISCARDABLE 
BEGIN
    "resource.h\0"
END
 
2 TEXTINCLUDE DISCARDABLE 
BEGIN
    "#include ""afxres.h""\r\n"
    "\0"
END
 
3 TEXTINCLUDE DISCARDABLE 
BEGIN
    "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
    "#define _AFX_NO_OLE_RESOURCES\r\n"
    "#define _AFX_NO_TRACKER_RESOURCES\r\n"
    "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
    "\r\n"
    "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)\r\n"
    "#ifdef _WIN32\r\n"
    "LANGUAGE 4, 2\r\n"
    "#pragma code_page(936)\r\n"
    "#endif //_WIN32\r\n"
    "#include ""res\\截屏.rc2""  // non-Microsoft Visual C++ edited resources\r\n"
    "#include ""l.chs\\afxres.rc""          // Standard components\r\n"
    "#endif\r\n"
    "\0"
END
 
#endif    // APSTUDIO_INVOKED

 
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

IDD_ABOUTBOX DIALOG DISCARDABLE  0, 0, 235, 55
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "关于 截屏"
FONT 9, "宋体"
BEGIN
    ICON            IDR_MAINFRAME,IDC_STATIC,11,17,20,20
    LTEXT           "截屏 1.0 版",IDC_STATIC,40,10,119,8,SS_NOPREFIX
    LTEXT           "版权所有 (C) 2010",IDC_STATIC,40,25,119,8
    DEFPUSHBUTTON   "确定",IDOK,178,7,50,14,WS_GROUP
END
 
IDD_MY_DIALOG DIALOGEX 0, 0, 225, 57
STYLE DS_MODALFRAME | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | 
    WS_SYSMENU
EXSTYLE WS_EX_APPWINDOW
CAPTION "截图工具"
FONT 9, "宋体"
BEGIN
    PUSHBUTTON      "截图保存到剪切板",IDC_BUTTON1,7,7,90,24
    PUSHBUTTON      "截图保存到文件",IDC_BUTTON2,128,7,90,24
    LTEXT           "注:在截屏时,可以点击鼠标右键取消。",IDC_STATIC,7,42,
                    145,8
END
 
IDD_DIALOG1 DIALOGEX 0, 0, 187, 96
STYLE WS_CHILD
EXSTYLE WS_EX_TOOLWINDOW
FONT 10, "System"
BEGIN
END
 

#ifndef _MAC
/////////////////////////////////////////////////////////////////////////////
//
// Version
//

VS_VERSION_INFO VERSIONINFO
 FILEVERSION 1,0,0,1
 PRODUCTVERSION 1,0,0,1
 FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
 FILEFLAGS 0x1L
#else
 FILEFLAGS 0x0L
#endif
 FILEOS 0x4L
 FILETYPE 0x1L
 FILESUBTYPE 0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "080404B0"
        BEGIN
            VALUE "CompanyName", "\0"
            VALUE "FileDescription", "截屏 Microsoft 基础类应用程序\0"
            VALUE "FileVersion", "1, 0, 0, 1\0"
            VALUE "InternalName", "截屏\0"
            VALUE "LegalCopyright", "版权所有 (C) 2010\0"
            VALUE "LegalTrademarks", "\0"
            VALUE "OriginalFilename", "截屏.EXE\0"
            VALUE "ProductName", "截屏 应用程序\0"
            VALUE "ProductVersion", "1, 0, 0, 1\0"
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x804, 1200
    END
END
 
#endif    // !_MAC

 
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//

#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE 
BEGIN
    IDD_ABOUTBOX, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 228
        TOPMARGIN, 7
        BOTTOMMARGIN, 48
    END
 
    IDD_MY_DIALOG, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 218
        TOPMARGIN, 7
        BOTTOMMARGIN, 50
    END
 
    IDD_DIALOG1, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 180
        TOPMARGIN, 7
        BOTTOMMARGIN, 89
    END
END
#endif    // APSTUDIO_INVOKED

 
/////////////////////////////////////////////////////////////////////////////
//
// Cursor
//

IDC_CURSOR1             CURSOR  DISCARDABLE     "res\\arrow_m.cur"
 
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//

// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDR_MAINFRAME           ICON    DISCARDABLE     "res\\截屏.ico"
 
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//

STRINGTABLE DISCARDABLE 
BEGIN
    IDS_ABOUTBOX            "关于 截屏(&A)..."
END
 
#endif    // Chinese (P.R.C.) resources
/////////////////////////////////////////////////////////////////////////////

 

#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
#define _AFX_NO_SPLITTER_RESOURCES
#define _AFX_NO_OLE_RESOURCES
#define _AFX_NO_TRACKER_RESOURCES
#define _AFX_NO_PROPERTY_RESOURCES
 
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
#ifdef _WIN32
LANGUAGE 4, 2
#pragma code_page(936)
#endif //_WIN32
#include "res\截屏.rc2"  // non-Microsoft Visual C++ edited resources
#include "l.chs\afxres.rc"          // Standard components
#endif
 
/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED

Resource.h
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by 截屏.rc
//
#define IDM_ABOUTBOX                    0x0010
#define IDD_ABOUTBOX                    100
#define IDS_ABOUTBOX                    101
#define IDD_MY_DIALOG                   102
#define IDR_MAINFRAME                   128
#define IDD_DIALOG1                     129
#define IDC_CURSOR1                     135
#define IDC_BUTTON1                     1000
#define IDC_BUTTON2                     1001
 
// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        138
#define _APS_NEXT_COMMAND_VALUE         32771
#define _APS_NEXT_CONTROL_VALUE         1001
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

 
GeneralCComboBox的下拉列表实现自适应宽度 Pin
Tuesday, April 13, 2010 5:02 PM by onlinewan
实现方法:在CCombox的派生类中,添加CBN_DROPDOWN响应函数和获得下拉列表的自适应显示宽度函数,在CBN_DROPDOWN的响应函数OnDropDown()中重设下拉列表宽度。
 

具体可参考如下代码:
 
.h文件:
class CAutoAdjustWidthComboBox : public CComboBox
{
	// Generated message map functions
protected:
	//{{AFX_MSG(CSearchComboBox)
		// NOTE - the ClassWizard will add and remove member functions here.
	afx_msg void OnDropDown();
	//}}AFX_MSG

	DECLARE_MESSAGE_MAP()
 
private:
	int GetDropListWidth();
}
 

.cpp文件:
BEGIN_MESSAGE_MAP(CAutoAdjustWidthComboBox, CComboBox)
	//{{AFX_MSG_MAP(CSearchComboBox)
		// NOTE - the ClassWizard will add and remove mapping macros here.
	ON_CONTROL_REFLECT(CBN_DROPDOWN, OnDropDown)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()
 
void CAutoAdjustWidthComboBox::OnDropDown()
{
	SetDroppedWidth(GetDropListWidth());
}
 
int CAutoAdjustWidthComboBox::GetDropListWidth()
{
	CClientDC dc(this);
	int nSave = dc.SaveDC();
	dc.SelectObject( this->GetFont() );
 
	int nWidth = 0;
	CSize size;
	for ( int i = 0; i < this->GetCount(); ++i )
	{
		CString strText;
		this->GetLBText(i, strText);
		size = dc.GetTextExtent(strText);
		if ( nWidth < size.cx )
		{
			nWidth = size.cx;
		}
	}
	dc.RestoreDC(nSave);
 
	CRect rect;
	this->GetClientRect(&rect);
	if ( nWidth < rect.Width() )
	{
		return rect.Width();
	}
 
	return nWidth + 20;
}

 
General给刚刚毕业或即将毕业的同学一封信---从自身经历谈找工作 Pin
Monday, March 30, 2009 5:48 PM by onlinewan
学友们,大家好:
在此之前,我做了很大的思想斗争,我怀疑我的所述能不能给大家带来帮助。如果您正在为找工作发愁,或者对勉强找到的工作不满意,您可以试着看完这封信。
 
先简单做个自我介绍哈。个人背景就不多做介绍了,就是个从农村走出来的娃。我上的是地处二线城市的一所师范学院,学的是计算机科学与技术专业,07年毕业,现在在北京做软件开发。
 
想做软件的,都想往一线城市跑,我也不例外,这也正是我现在在北京的原因。记得我是07年五一放假时来北京找工作的,我之前没有来过北京,所以我叫了个同学一起来的,不过他也没来过,幸好他有个同学在北京上学。这就解决了我俩初到北京住的问题。北京好大,这就是给我的第一感觉,决定一定要在北京工作。刚开始的一周,由于是五一长假,我俩没有找工作,而是好好的在北京逛,最先去的就是天安门了,站在那里,感觉好庆幸,好自豪。去了清华北大,又感觉好自卑,后悔自己当初没有好好读书。同时,也感觉到了压力,北京有这么多一流的大学,像我这样的在北京找工作太没有优势了。很快,五一长假就这么过去了,由于不能长期在同学的同学的学校住下去,我俩选择租了个地下室,同时开始在网上投简历,北京上网真贵,一小时五块,为了保证能吃饱我每天只能上一个小时。我的第一份简历写的很花绡,自我感觉像那样的简历找个工作还是很容易的事情。可在我很乐观,很积极的投了近一周的简历,没有接到一个面试通知的时候,我迷茫了,我开始怀疑我是不是太自信了,怀疑北京根本不是我这种人呆的地方。接下来有两天,我都没有去投简历,迷迷糊糊的。可能是上天看不下去让我这颗脆弱的心再受伤害,我得到了一位网友的指点与开导,照着他的描述,我修改了我的简历,内容不再花绡了,变的简单真实,多了对专业技术、自己经历的描述。刚刚改完我就迫不及待的投了好几份出去。心情又变得乐观了起来,高高兴兴的跑回地下室,进了被卧就睡了,虽然地下室很潮,可我今天却感觉很舒适。果不出网友所料,第二天就接到了好几个通知面试的电话。那个高兴,激动,是无法用主语能表达的。
 
回头看了下,好像说了很多不着边际的话哦。哈哈,还请多多包涵。说起难忘的经历就打不住了。
 
想做软件的都想进大公司,一流企业,我还是不例外。接下来,我每天都有面试,可是当我经历了几次面试之后,我又开始迷茫了,怎么都是一些小公司,就没多少人,和自己想的差距也太大了。待遇也很低,在北京可能勉强够生存。有了回老家教书都比这强的念头。可是我真得很想做编程,我该怎么办呢,我是回是留?我又去找了那位网友。是他再次给了我信心,他叫我务实点,面对残酷的就业压力,把自己摆在正确的位置上,能先找个工作就很不容易了,至于自己的大理想,可以在工作了以后再重新规划实现。待遇只要刚开始能保证基本的生活也是可以接受的,只要是金子都会发光,但一定要有发光的机会。听了他的话,我开始重新定位自己,我决定先找个差不多的公司。相对来说,我要找一个要求不太高的公司还是比较容易的,我的计算机基础知识,对C++的理解还算是可以的,常见的面试题基本都难不倒我。我真得不是炫耀,说这个只是想说,在学校虽然不能学到很多的实用技能,但一定要打下扎实的基础。没费多大周折,我就找了现在的公司定了下来。待遇不高,试用期一个月2K,呵呵,够低了吧。不过我还是接受了,我觉得那只是暂时的。进了公司,我好多好多东西都不会,我很努力,我不太喜欢什么问题都去问人,刚开始的一个月里,我基本都是在代码堆里度过的,可能阅读了有好几万行的代码,一个项目的代码让我差不多看完了。这为我后来很快融入项目打下了基础。
 
就到这吧,再写就跑题跑的更远了,向来文笔不行。 做个小结:
在遇到挫折的时候,能有个前辈指点开导,对自己是莫大的鼓舞。
面对现实,我们务实一点,会少去很多烦恼与不快。
是金子都会发光,但一定要有发光的机会。
空闲的时候不要只是娱乐,提升下自己生存的本领,不至于真正需要的时候,没什么可拿出来的。
困难只是暂时的,我们要有尽快战胜困难的信心。
偶尔委屈下自己,能换的更美好的明天。
 
愿学友们顺利找到自己喜欢的工作,身体健键康康,生活充实快乐!
 
onlinewan
 
写在09年愚人节前一天
 
General计划为什么不能如期完成? Pin
Thursday, March 26, 2009 5:29 PM by onlinewan
计划为什么不能如期完成?
 
中国今年经济增长要保八,柳传志复出要在今年扭转联想亏损的局面,这周五开总结会,下周末出去玩,,小虎想今年年底使银行的存款从0变为10万,小花这个月想把体重从65KG减到45KG,等等。
大到国家,小到个人,这些都是计划。不对,上面所列真的都是计划吗?
 
准确的说,它们都不是计划,只能称的上是目标,是想达到的效果。当然,也不能排除它们都只是美梦,或者说是幻想。
 
计划,是指为了到达类似上面所列的目标所制订的行动方案。制订计划的目的很明确,就是为了达到目标,使美梦成真。
 
中国今年要保八,在经济寒冬设定这样的目标一定是经过深思熟虑的。是有了去年就悄然进行的全国各个地区的经济普查,社科院、工信部、保监会、银监会对全国公民消费理念,个人积蓄的考察,等等一系列的数据统计,才制定的目标。可见,制定这样的目标应该是可行的,是可以实现的。但是,光有能实现目标的潜力是远远不够的。更重要的是要制订合理的计划并执行,以保证实现保八的目标。实行减免税收、鼓励创业、放宽信贷、家电下乡等等惠民政策以提高就业、刺激消费拉到内需,可以看到,国家正在按照计划一步一步的走向目标,并且已经初见成效。希望中国能最终实现目标。
小虎想今年年底使银行的存款从0变为10万,我想这应该小虎是经过详细的分析规划后的决定。要想从0变为10万,对有些人来说是很容易的事情,对有些人来说,经过一定的努力是可以实现的,可对于有些人来说,那是根本不可能的。小虎一定是通过分析自己自身的能力,现有的收入,可提升的空间,日常基本消费水平等等后,得出自己到年底有希望使存款达到10万。小虎也根据自己分析的结果制订了符合自己的行动计划。从现在开始提高自身能力,以带动自己收入的提升,开始建立自己的小帐本,对日常开销进行记录,在一定的时间间隔下统计分析自己的日常开支情况,调整开支,减少开支,使开支合理化。等等行动,是小虎年底实现存款达到10万的保障。
 
可见,目标的制订是要有一定的依据的,目标的实现需要合理的计划,更需要计划的执行力。但是,往往有一部分人的目标都是不合理的,不现实的,或者没有执行力。
 
小花这个月想把体重从65KG减到45KG,这对于女孩子来说,是非常高效的减肥了。可是这个是不现实的,至少对于绝大多数人来说是不太可能的。可见小花有这样的美梦,一定是没有经过仔细分析的,是盲目的。
如果小花的目标是这个月把体重从65KG减到60KG,这个对于大部分减肥的人来说,不是一件很难的事,也是可以找出很多例子的。但是小花没有为自己制订减肥计划,只是成天嘴上说要减肥,成天还是大吃大喝,不加强锻炼,那本来可能的事,就变成不可能了。
如果小虎今年年底使银行的存款从0变为10万是可行的,是可以达到的,小虎也制订了自己的计划,但是,但是它对自己的计划没有长久坚持执行,或者说是三天打鱼两天晒网,甚至根本就没有行动,那他的目标实现就没有了保障,也是不太可能达到的。
 
可见目标不能实现的原因,主要有三个方面:制定的目标就是不现实的;没有对目标的实现制订合理的计划;有合理的计划但是没有执行力。那么,我们以后对待目标,是不是需要深思熟虑+周密计划+执行力呢? 当我们的目标不能实现的时候,是不是也应该从这三个方面,来分析原因,并有针对性的总结经验,在下次改进呢?
 
看到这大家有没有觉得本文的标题起得好像有点问题?应该改为“目标为怎么不能实现?”才合适点哦。
 

quote------------------------------------------------------------------
温总理说:经济寒冬我们最缺的不是钱,而是必胜的信心。
 
General在ARX中利于Automation打开、新建DWG文件 Pin
Sunday, March 22, 2009 3:33 PM by onlinewan
HRESULT AutoWrap ( int autoType ,   VARIANT * pvResult ,   IDispatch * pDisp ,   LPOLESTR ptName , int cArgs... )
{
     va_list marker;
     va_start ( marker , cArgs );
 
     if ( ! pDisp )
     {
          MessageBox ( NULL ,
                         _T("NULL IDispatch passed to AutoWrap()") ,
                         _T("Error") ,
                         0x10010 );
          _exit ( 0 );
     }
 
     DISPPARAMS   dp               =
     {
          NULL , NULL , 0 , 0
     };
     DISPID         dispidNamed = DISPID_PROPERTYPUT;
     DISPID         dispID;
     HRESULT      hr;
     char         buf [ 200 ];
     char         szName [ 200 ];
 
     WideCharToMultiByte ( CP_ACP ,
                                 0 ,
                                 ptName ,
                                 - 1 ,
                                 szName ,
                                 256 ,
                                 NULL ,
                                 NULL );
 
     hr = pDisp-&gt;GetIDsOfNames ( IID_NULL ,
                                        &amp; ptName ,
                                        1 ,
                                        LOCALE_USER_DEFAULT ,
                                        &amp; dispID );
 
     if ( FAILED ( hr ) )
     {
          sprintf ( buf ,
                       "IDispatch::GetIDsOfNames(\"%s\") failed w/err0x%08lx" ,
                       szName ,
                       hr );
          return hr;
     }
 
     VARIANT *   pArgs   = new VARIANT [ cArgs + 1 ];
 
     for ( int i = 0; i &lt; cArgs; i++ )
     {
          pArgs [ i ] = va_arg ( marker , VARIANT );
     }
 
     dp.cArgs = cArgs;
     dp.rgvarg = pArgs;
 
     if ( autoType &amp; DISPATCH_PROPERTYPUT )
     {
          dp.cNamedArgs = 1;
          dp.rgdispidNamedArgs = &amp; dispidNamed;
     }
 
     hr = pDisp-&gt;Invoke ( dispID ,
                              IID_NULL ,
                              LOCALE_SYSTEM_DEFAULT ,
                              autoType ,
                              &amp; dp ,
                              pvResult ,
                              NULL ,
                              NULL );
     if ( FAILED ( hr ))
     {
          sprintf ( buf ,
                       "IDispatch::Invoke(\"%s\"=%08lx) failed w/err 0x%08lx" ,
                       szName ,
                       dispID ,
                       hr );
          return hr;
     }
     va_end ( marker );
 
     delete [] pArgs;
 
     return hr;
}
 
//功能:打开一DWG文件 ,打开时不会弹出对话框
//参数:第一个是文件名称,第二个标识是否为只读打开
//返回:TRUE为打开成功,FALSE打开失败
BOOL OpenDwgFileByAutomation( CString strFile, BOOL bReadOnly )
{
     try
     {
          if ( strFile.IsEmpty() || !IsExistFile(strFile) || !IsVerCanOpen(strFile.GetBuffer(0)) )
          {
               return FALSE;
          }
 
          BOOL bReturn = FALSE;
          do
          {
               HRESULT hr = S_OK;
               VARIANT ADoc;
               hr = AutoWrap(DISPATCH_PROPERTYGET, &amp;ADoc, acedGetAcadWinApp()-&gt;GetIDispatch(TRUE), L"Documents", 0);
               if ( FAILED(hr) )
               {
                    break;
               }
              
               // 打开文件
               VARIANT vrFileName;
               vrFileName.vt=VT_BSTR;
               vrFileName.bstrVal= strFile.AllocSysString();
               VARIANT vrOpenMode;
               vrOpenMode.vt=VT_I2;
               vrOpenMode.iVal = bReadOnly ? 1 : 0;
 
               hr = AutoWrap(DISPATCH_METHOD, &amp;ADoc, ADoc.pdispVal, L"Open", 2, vrOpenMode, vrFileName);
               ::VariantClear (&amp;vrFileName);
               bReturn = (FAILED(hr) ? FALSE : TRUE);
               ::VariantClear (&amp;ADoc);
          } while(0);
         
          return bReturn;
     }
     catch (CException* e)
     {
          return FALSE;
     }
}
 
//功能:新建一DWG文件
//返回:TRUE为打开成功,FALSE打开失败
BOOL CLzPlatTool::NewDwgFileByAutomation()
{
     try
     {
          BOOL bReturn = FALSE;
          do
          {
               HRESULT hr = S_OK;
               VARIANT ADoc;
               hr = AutoWrap(DISPATCH_PROPERTYGET, &amp;ADoc, acedGetAcadWinApp()-&gt;GetIDispatch(TRUE), L"Documents", 0);
               if ( FAILED(hr) )
               {
                    break;
               }
              
               // 打开文件
               hr = AutoWrap(DISPATCH_METHOD, &amp;ADoc, ADoc.pdispVal, L"Add", 0);
               bReturn = (FAILED(hr) ? FALSE : TRUE);    
               ::VariantClear (&amp;ADoc);
          } while(0);
         
          return bReturn;
     }
     catch (CException* e)
     {
          return FALSE;
     }
}
 
General收藏 [modified] Pin
Sunday, March 15, 2009 4:19 PM by onlinewan
软件测试大讨论[^]
 
基于PHP开发WEB程序之工具推荐[^]
 
Haohappy的专栏--PHP5研究中心[^]
 
heiyeluren的blog(黑夜路人的开源世界)PHPCup.cn - 中国新锐LAMP论坛[^]
 
王泽宾 架构之家[^]
 
phphot php,linux,mysql,apache[^]
 
modified on Tuesday, March 24, 2009 1:38 AM

 
General企业制度与文化 Pin
Tuesday, March 10, 2009 11:06 PM by onlinewan
大家都知道,西药见效快,可它治标不治本,中药见效慢,但它治根。究其原因,西药重在以药效强制杀死病菌,以解一时之痛;中药讲疗程,重在调养,见效慢,但可以从根本上铲除病魔。两者各有各的优点,也各有各的缺点,有人会问,为什么不两者一起用呢?这便有了现在中西药结合的时代。
当然,我不是从医的,上面描述的正确性有待查证。真正的意图,是想借此说出我对管理上自己的一点想法。
 
初级的管理靠的是制度,深一级的是深入人心的文化。它们两者和西药中药类似。
 
一个企业刚起步,靠的是文化,是创业人的激情,大家同舟共济。可随着规模的增大,新人的涌入,元老的隐退,起初的文化已经石沉大海,管理变得混乱。
因而,很多的企业制定了属于自己的企业制度,通过制度,阻止了随着规模的扩大而造成的管理混乱。但同时,往往忽略了文化的传播,早就没有了同舟共济的深厚友情,出现部门、员工急功近利,异口同声你我他。
当然,文化,虽其效用是深远的,但当企业规模越来越大,只有文化就不行了,没有明确合理的制度,企业的运营就会无章可循,职责混乱。光有激情,但缺乏执行力。
由此失败的企业比比皆是。
 
成功的企业一定是有个完善的制度体系,更重要的是有着上下一心的企业文化。是两者的结合。
 
阿里巴巴能成功,完善的制度体系是少不了的。可最令我佩服的是它们妖精化的团队。他们的魔力不仅影响者高层,更到最底层,甚至到员工家属。
一位因挫折极度消沉的女士来到阿里巴巴,三个月后姿态已焕然一新。尽管她3000左右的薪水在大部分白领看来毫无兴奋点,但她口气铿锵———“请不要再和我提自杀那些愚蠢的话题,我正在给中国的电子商务做贡献。”
马云习惯不定时邀请雇员的亲属到公司“视察”,大部分人在走出大门后,会对“枕边人”感慨———“加油干吧,以后就靠你了。”
曾有一位以抱怨“丈夫工作过于拼命”著称的妻子,最后在阿里巴巴员工大会时跌跌撞撞冲上了主席台:“我想感谢你们,我很荣幸将丈夫交给了阿里。”
马云会打扮成维吾尔族姑娘或江南小城的普通渔夫;而阿里巴巴的首席财务官蔡崇信,这个被业界认为不好说话、极其严肃的人,偶然也会穿上女人的丝袜、在众目睽睽下跳起缠绵的钢管舞。
尚且不论这些故事的真实性,但我相信大多数都是真的。这都说明一件事,那就是阿里巴巴有着深入人心的企业文化。
安利的成功,更是如此。它的发展是非常注重企业文化的传播的,它的直销模式类似传销,有人就拿洗脑来形容,洗脑可能过激,但说明,安利成功,除了有完善的奖金制度,更重要的是企业上下一心。
由此卓越的企业层出不穷。
 
总之,医药倡导中西药结合,企业也应该追求制度与文化的融合,只有这样,才能够走的更远。
 
General2005年百度之星程序设计大赛试题初赛题目三 Pin
Monday, November 3, 2008 7:06 PM by onlinewan
题目描述:请编写程序,根据指定的对应关系,把一个文本中的字符串替换成另外的字符串。
输入数据:程序读入已被命名为 text.txt 和 dict.txt 的两个输入数据文本文件, text.txt 为一个包含大量字符串(含中文)的文本,以 whitespace 为分隔符; dict.txt 为表示字符串( s1 )与字符串( s2 )的对应关系的另一个文本(含中文),大约在 1 万行左右,每行两个字符串(即 s1 和 s2 ),用一个 \t 或空格分隔。 dict.txt 中各行的 s1 没有排序,并有可能有重复,这时以最后出现的那次 s1 所对应的 s2 为准。 text.txt 和 dict.txt 中的每个字符串都可能包含除 whitespace 之外的任何字符。 text.txt 中的字符串必须和 dict.txt 中的某 s1 完全匹配才能被替换。(为便于调试,您可下载测试 text.txt 和 dict.txt 文件,实际运行时我们会使用不同内容的输入文件。)
输出数据:在标准输出上打印 text.txt 被 dict.txt 替换后了的整个文本。
评分标准:程序输出结果必须正确,内存使用越少越好,程序的执行时间越快越好。
 

程序代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <ctime>
#include <map>
#include <string>
 
using namespace std;
 
int main()
{
     map<string, string> dictmap;
     string linestring;
     FILE *fp1 = fopen("text.txt", "r");
     if ( fp1 == NULL )
     {
          cout << "open text.txt file failed!\n";
          return 0;
     }
    
     FILE *fp2 = fopen("dict.txt", "r");
     if ( fp1 == NULL )
     {
          cout << "open dict.txt file failed!\n";
          fclose(fp1);
          return 0;
     }
 
     FILE *fp3 = fopen("output.txt", "w");
     if ( fp1 == NULL )
     {
          cout << "creat output.txt file failed!\n";
          fclose(fp1);
          fclose(fp2);
          return 0;
     }
 
     char szBuffer[1024];
     char szBufferTemp[1024];
     char *ppos = NULL;
     string str1, str2;
     while ( fgets(szBuffer, 1024, fp2) != NULL )
     {
         
          if ( (ppos = strchr(szBuffer, ' ')) == NULL
               && (ppos = strchr(szBuffer, '\t')) == NULL )
          {
               continue;
          }
          *ppos++ = '\0';
 
          if ( ppos[strlen(ppos) - 1] = '\n' )
          {
               ppos[strlen(ppos) - 1] = '\0';
          }
          str1 = szBuffer;
          str2 = ppos;
          dictmap.insert(make_pair(str1, str2));
     }
 
     map<string, string>::iterator mapIter;
     string strText;
 
     char ch;
     int i = 0;
     bool bFind = false;
     while ( (ch = getc(fp1)) != EOF )
     {
          if ( ch == ' ' )
          {
               putc(ch, fp3);
              
               szBuffer[i] = '\0';
 
               if ( i > 0 )
               {
                    strText = szBuffer;
                    if ( (mapIter = dictmap.find(strText)) != dictmap.end() )
                    {
                         fputs(mapIter->second.c_str(), fp3);
                    }
                    else
                    {
                         fputs(strText.c_str(), fp3);
                    }
               }
 
               while ( (ch = getc(fp1)) != EOF && ch == ' ' ) putc(ch, fp3);
 
               i = 0;
               if ( ch != EOF )
               {
                    szBuffer[i++] = ch;
               }
          }
          else
          {
               szBuffer[i++] = ch;
          }
     }
 
     if ( i > 0 )
     {
          szBuffer[i] = '\0';
          strText = szBuffer;
          if ( (mapIter = dictmap.find(strText)) != dictmap.end() )
          {
               fputs(mapIter->second.c_str(), fp3);
          }
          else
          {
               fputs(strText.c_str(), fp3);
          }
     }    
 
     fclose(fp1);
     fclose(fp2);
     fclose(fp3);
 
     cout << "success!\n";
 
     return 1;
}
 
General2005年百度之星程序设计大赛试题初赛题目二 Pin
Monday, November 3, 2008 7:02 PM by onlinewan
题目描述:请编写程序,找出下面 “ 输入数据及格式 ” 中所描述的输入数据文件中最大重叠区间的大小。
对一个正整数 n ,如果 n 在数据文件中某行的两个正整数(假设为 A 和 B )之间,即 A<=n<=B 或 A>=n>=B ,则 n 属于该行;如果 n 同时属于行 i 和 j ,则 i 和 j 有重叠区间;重叠区间的大小是同时属于行 i 和 j 的整数个数。
例如,行( 10 20 )和( 12 25 )的重叠区间为 [12 20] ,其大小为 9 ;行( 20 10 )和( 12 18 )的重叠区间为 [10 12] ,其大小为 3 ;行 (20 10) 和( 20 30 )的重叠区间大小为 1 。
输入数据:程序读入已被命名为 input.txt 的输入数据文本文件,该文件的行数在 1 到 1,000,000 之间,每行有用一个空格分隔的 2 个正整数,这 2 个正整数的大小次序随机,每个数都在 1 和 2^32-1 之间。(为便于调试,您可下载测试 input.txt 文件,实际运行时我们会使用不同内容的输入文件。)
输出数据:在标准输出上打印出输入数据文件中最大重叠区间的大小,如果所有行都没有重叠区间,则输出 0 。
评分标准:程序输出结果必须正确,内存使用必须不超过 256MB ,程序的执行时间越快越好。
 
<pre>#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <ctime>
 
using namespace std;
 
struct number_pair {
     unsigned long num1;
     unsigned long num2;
     unsigned long lineindex;
};
 
unsigned long get_area(number_pair *pair1, number_pair *pair2, number_pair *area)
{
     unsigned long areasize = 0;
    
     unsigned long pair1_1 = __min(pair1->num1, pair1->num2);
     unsigned long pair1_2 = __max(pair1->num1, pair1->num2);
    
     unsigned long pair2_1 = __min(pair2->num1, pair2->num2);
     unsigned long pair2_2 = __max(pair2->num1, pair2->num2);
    
     do
     {
          if ( pair1_1 > pair2_2 || pair2_1 > pair1_2 )
          {
               break;
          }
         
          if ( pair1_1 < pair2_1 )
          {
               if ( pair1_2 < pair2_2 )
               {
                    areasize = pair1_2 - pair2_1 + 1;
                    area->num1 = pair2_1;
                    area->num2 = pair1_2;
               }
               else
               {
                    areasize = pair2_2 - pair2_1 + 1;
                    area->num1 = pair2_1;
                    area->num2 = pair2_2;
               }
          }
          else
          {
               if ( pair1_2 > pair2_2 )
               {
                    areasize = pair2_2 - pair1_1 + 1;
                    area->num1 = pair1_1;
                    area->num2 = pair2_2;
               }
               else
               {
                    areasize = pair1_2 - pair1_1 + 1;
                    area->num1 = pair1_1;
                    area->num2 = pair1_2;
               }
          }         
     } while( false );
    
     return areasize;
}
 
int main()
{
     bool breturn = false;
     do
     {
          cout << "\n";
          cout << "\n请选择下列一项后回车:\n";
          cout << "      1、生成测试数据文件input.txt(在当前目录生成,如果存在,将覆盖)\n";
          cout << "      2、运行测试程序。(输入数据为当前目录下的input.txt文件)\n";
          cout << "      3、退出。\n";
          cout << "请选择:";
 
         
          int sel = 0;
          cin >> sel;
 
          switch ( sel )
          {
          case 1:
               {
                    bool bMakeSuccess = false;
                    FILE *fp = fopen("input.txt", "w+");
                    if ( fp != NULL )
                    {
                         unsigned long linecount = 0;
                         cout << "\n请输入行数(1~~~1,000,000): ";
                         cin >> linecount;
 
                         char szbuffer[1024] = "\0";
                         srand( (unsigned)time( NULL ) );                        
                         for( unsigned long i = 0; i < linecount; ++i )
                              fprintf(fp, "%ld %ld\n", (unsigned int)rand(), (unsigned int)rand());
 
                         fclose(fp);
 
                         bMakeSuccess = true;
                    }
                   
                    cout << "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
                    if ( bMakeSuccess )
                    {
                         cout << "\n测试数据文件input.txt生成成功!\n";
                    }
                    else
                    {
                         cout << "\n测试数据文件input.txt生成失败!\n";
                    }
                    cout << "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
                    break;
               }
          case 2:
               {                   
                    unsigned long arysize = 1000000;                   
                    number_pair *pnumber_pair = new number_pair[arysize];
                    unsigned long cursize = 0;
 
                    bool bMakeSuccess = false;
                    unsigned long maxareasize = 0;
                    unsigned long tempareasize = 0;
                    unsigned long line1 = 0;
                    unsigned long line2 = 0;
                    unsigned long lineindex = 0;
                    number_pair area, temparea;
 
                    FILE *fp = fopen("input.txt", "r");
                    if ( fp != NULL )
                    {
                         if ( pnumber_pair == NULL )
                         {
                              bMakeSuccess = false;
                         }
                         else
                         {                             
                              char szbuffer[1024] = "\0";    
                              do
                              {
                                   if ( fgets(szbuffer, 1023, fp) == NULL )
                                   {
                                        break;
                                   }
                                   ++lineindex;
 
                                   sscanf(szbuffer, "%ld %ld\n", &pnumber_pair[cursize].num1, &pnumber_pair[cursize].num2);
 
                                   pnumber_pair[cursize].lineindex = lineindex;
 
                                   if ( (__max(pnumber_pair[cursize].num1, pnumber_pair[cursize].num2) -
                                        __min(pnumber_pair[cursize].num1, pnumber_pair[cursize].num2)) <= maxareasize )
                                   {
                                        continue;
                                   }
 
                                   for ( unsigned long i = 0; i < cursize; ++i )
                                   {
                                        tempareasize = get_area(&pnumber_pair[i], &pnumber_pair[cursize], &temparea);
                                        if ( tempareasize > maxareasize )
                                        {
                                             maxareasize = tempareasize;
                                            
                                             line1 = i;
                                             line2 = cursize;
 
                                             area = temparea;
                                        }
                                   }
                                  
                                   ++cursize;
                              } while( cursize < arysize );
                         }
                        
                         fclose(fp);
                        
                         bMakeSuccess = true;
                    }
 
                    cout << "\n*****************************************************************\n";
                    if ( bMakeSuccess )
                    {
                         if ( maxareasize < 1 )
                         {
                              cout << "最大重叠区间的大小是:0\n";
                         }
                         else
                         {
                              cout << "\n最大重叠区间[" << area.num1 << " " << area.num2 << "]的大小是:" << maxareasize << "\n"
                                   << "由第 [" << pnumber_pair[line1].lineindex << "] 行 ("
                                   << pnumber_pair[line1].num1 << " " << pnumber_pair[line1].num2 << ") 和第 ["
                                   << pnumber_pair[line2].lineindex << "] 行 ("
                                   << pnumber_pair[line2].num1 << " " << pnumber_pair[line2].num2 << ") 得到。\n";
                         }
                    }
                    else
                    {
                         cout << "\n文件格式错误或文件input.txt不存在!\n";
                    }
                    cout << "\n*****************************************************************\n\n\n";
 
                    if ( pnumber_pair != NULL )
                    {
                         delete []pnumber_pair;
                         pnumber_pair = NULL;
                    }
 
                    break;
               }
          case 3:
               {
                    breturn = true;
                    break;
               }
          default:
               {
                    cout << "\n您输入有误, 请输入1---3之间的数。\n";
                    break;
               }
          }
 
          if ( breturn )
          {
               break;
          }
     } while( 1 );
 
     return 1;
}</pre>
 
General2005年百度之星程序设计大赛试题初赛题目一 Pin
Monday, November 3, 2008 6:47 PM by onlinewan
题目描述:一个正整数有可能可以被表示为 n(n>=2) 个连续正整数之和,如:
15=1+2+3+4+5
15=4+5+6
15=7+8
请编写程序,根据输入的任何一个正整数,找出符合这种要求的所有连续正整数序列。
输入数据:一个正整数,以命令行参数的形式提供给程序。
输出数据:在标准输出上打印出符合题目描述的全部正整数序列,每行一个序列,每个序列都从该序列的最小正整数开始、以从小到大的顺序打印。如果结果有多个序列,按各序列的最小正整数的大小从小到大打印各序列。此外,序列不允许重复,序列内的整数用一个空格分隔。如果没有符合要求的序列,输出 “NONE” 。
例如,对于 15 ,其输出结果是:
1 2 3 4 5
4 5 6
7 8
对于 16 ,其输出结果是:
NONE
评分标准:程序输出结果是否正确。
 

 
程序代码:
<pre>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
 
int main()
{
     bool bFinded = false;
     int n = 0;
     int min = 0;
     int temp = 0;
     int i = 0, j = 0;
     char ch;
     do
     {
          printf("请输入一个正整数: n=");
          scanf("%d", &n);
         
          min = sqrt(n * 2);         
         
          for ( i = min; i > 1; --i )
          {
               temp = n / i;
               if ( i % 2 == 1 )
               {
                    if ( (temp * i) == n )
                    {
                         for ( j = - i / 2; j < i / 2 + 1; ++j )
                         {
                              printf("%d ", temp + j);
                         }
                         printf("\n");
                        
                         bFinded = true;
                    }
               }
               else
               {
                    if ( (temp * i + (i / 2)) == n )
                    {
                         for ( j = - i / 2 + 1; j < i / 2 + 1; ++j )
                         {
                              printf("%d ", temp + j);
                         }
                         printf("\n");
                        
                         bFinded = true;
                    }
               }
          }
         
          if ( !bFinded )
          {
               printf("NONE\n");
          }
         
          printf("要继续吗?(y/n): ");
          scanf("%c", &ch);
 
          if ( ch != 'y' && ch != 'Y' )
          {
               break;
          }
     }while ( 1 );
 
     return 1;
}</pre>
 
General实现在Word中查找指定内容,将其替换为指定图片 Pin
Thursday, October 23, 2008 3:12 PM by onlinewan
//功能:实现在Word中查找指定内容,将其替换为指定图片。
//参数:mapPicInfo          图片文件名称和全路径的map
//参数:strFileName          要操作的原文件
//参数:strOutputFileName     要输出的文件
BOOL COfficeSign::WordSign( map&lt;CString, CString&gt; &amp;mapPicInfo, CString strFileName, CString strOutputFileName )
{
     float fWordPicHeight     = 30.0;
     float fWordPicWidth          = 60.0;
    
     ::CoInitialize(NULL);
 
     MsOfficeWordOle::_Application oWordApp;
     MsOfficeWordOle::_Document     oWordDoc;
     MsOfficeWordOle::Documents     oWordDocs;
     MsOfficeWordOle::Selection     oSel;
     MsOfficeWordOle::Find          oFind;
     MsOfficeWordOle::Replacement     oRep;
     MsOfficeWordOle::Range          oRange;
     MsOfficeWordOle::InlineShapes oInlineShapes;
     MsOfficeWordOle::InlineShape   oInlineShape;
 
     map&lt;CString, CString&gt;::iterator mapIter;
    
     LPDISPATCH   lpDisp;
 
     if(!oWordApp.CreateDispatch("Word.Application"))
     {
          AfxMessageBox("无法启动Word服务器, 请确保您已成功安装Word软件.");
          return FALSE;
     }
    
     oWordApp.SetDisplayAlerts(FALSE); //不显示警告框
     oWordApp.SetVisible(FALSE);
    
     COleVariant avar((long)DISP_E_PARAMNOTFOUND, VT_ERROR);    
     COleVariant vTrue((short)TRUE), vFalse((short)FALSE);
 
     try
     {
          oWordDocs.AttachDispatch(oWordApp.GetDocuments());
          lpDisp = oWordDocs.Open(COleVariant((LPCTSTR)strFileName), avar, avar, avar, avar,
               avar, avar, avar, avar, avar, avar, avar, avar, avar, avar, avar);
          oWordDoc.AttachDispatch(lpDisp);
          oSel.AttachDispatch(oWordApp.GetSelection());
          oFind.AttachDispatch(oSel.GetFind());
          oRep.AttachDispatch(oFind.GetReplacement());
          oRep.SetText(_T(""));
          oFind.SetText(_T("[[]*[]]"));
          oFind.SetForward(TRUE);
          oFind.SetWrap(1);        // wdFindStop = 0, wdFindContinue = 1, wdFindAsk = 2
          oFind.SetFormat(FALSE);
          oFind.SetMatchCase(FALSE);
          oFind.SetMatchWholeWord(FALSE);
          oFind.SetMatchByte(FALSE);
          oFind.SetMatchAllWordForms(FALSE);
          oFind.SetMatchSoundsLike(FALSE);
          oFind.SetMatchWildcards(TRUE);
 
          CString strFindName(_T(""));
          while ( oFind.Execute(avar, avar, avar, avar, avar, avar, COleVariant((long)1), avar, avar, avar,
               avar, avar, avar, avar, avar) )
          {
               oRange.AttachDispatch(oSel.GetRange());
                   
               strFindName = oRange.GetText();
               if ( strFindName.GetLength() &lt; 3 )
               {
                    oRange.ReleaseDispatch();
                    continue;
               }
 
               int iLen = strFindName.GetLength();
               strFindName = strFindName.Mid(1, strFindName.GetLength() - 2);
               strFindName.TrimLeft();
               strFindName.TrimRight();
               strFindName.MakeUpper();
 
               mapIter = mapPicInfo.find(strFindName);
               if ( mapIter == mapPicInfo.end() )
               {
                    oRange.ReleaseDispatch();
                    continue;
               }
 
               oRange.Delete(COleVariant((long)1), COleVariant((long)1));
 
               CString strPicFileName = mapIter-&gt;second;
               oInlineShapes.AttachDispatch(oRange.GetInlineShapes());
               lpDisp = oInlineShapes.AddPicture((LPCTSTR)strPicFileName, avar, avar, avar);
               oInlineShape.AttachDispatch(lpDisp);
               oInlineShape.SetHeight(fWordPicHeight);
               oInlineShape.SetWidth(fWordPicWidth);
 

               oInlineShapes.ReleaseDispatch();
               oInlineShape.ReleaseDispatch();
               oRange.ReleaseDispatch();
          }
         
          oSel.ReleaseDispatch();
          oFind.ReleaseDispatch();
          oRep.ReleaseDispatch();
 
          //oWordDoc.Save();
          oWordDoc.SaveAs(COleVariant(strOutputFileName.GetBuffer(0)), avar, avar, avar, avar, avar, avar,
               avar, avar, avar ,avar, avar, avar, avar, avar, avar);
          oWordDoc.Close(vFalse, avar, avar);
          oWordApp.Quit(vFalse, avar, avar);
     }
     catch (...)
     {
          oWordDoc.Close(vFalse, avar, avar);
          oWordApp.Quit(vFalse, avar, avar);
 
          CString strMsg;
          strMsg.Format(_T("文件 %s 可能正在被使用,出错!"), (LPCTSTR)strFileName);
          AfxMessageBox(strMsg, MB_OK | MB_ICONINFORMATION);
          return FALSE;
     }
 
     return TRUE;    
}
 
General实现在Excel中查找指定内容,将其替换为指定图片 Pin
Thursday, October 23, 2008 3:04 PM by onlinewan
//功能:实现在Excel中查找指定内容,将其替换为指定图片。
//参数:mapPicInfo          图片文件名称和全路径的map
//参数:strFileName          要操作的原文件
//参数:strOutputFileName     要输出的文件
BOOL COfficeSign::ExcelSign( map&lt;CString, CString&gt; &amp;mapPicInfo, CString strFileName, CString strOutputFileName )
{
     ::CoInitialize(NULL);
 
     float fExcelPicHeight     = 30.0;
     float fExcelPicWidth     = 60.0;
 
     MsOfficeExcelOle::_Application     oExcelApp;
     MsOfficeExcelOle::_Workbook          oWorkBook;
     MsOfficeExcelOle::Workbooks          oWorkBooks;
     MsOfficeExcelOle::_Worksheet     oWorkSheet;
     MsOfficeExcelOle::Worksheets     oWorkSheets;
     MsOfficeExcelOle::Shapes          oShapes;
     MsOfficeExcelOle::Range               oRange;
     MsOfficeExcelOle::Range               oUseRange;
     MsOfficeExcelOle::Range               oMergeRange;
     LPDISPATCH          lpDisp;    
 
     map&lt;CString, CString&gt;::iterator mapIter;
 
     if(!oExcelApp.CreateDispatch(_T("Excel.Application")))
     {
          AfxMessageBox(_T("无法启动Excel服务器, 请确保您已成功安装Excel软件."));
          return FALSE;
     }
    
     oExcelApp.SetDisplayAlerts(FALSE); //不显示警告框
    
     COleVariant avar((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
     COleVariant vTrue((short)TRUE), vFalse((short)FALSE);
 
     oExcelApp.SetVisible(FALSE);
     oExcelApp.SetUserControl(TRUE);
 
     try
     {
          oWorkBooks.AttachDispatch(oExcelApp.GetWorkbooks());
          lpDisp = oWorkBooks.Open((LPCTSTR)strFileName, avar, avar, avar, avar,
                    avar, avar, avar, avar, avar, avar, avar, avar, avar, avar);
          oWorkBook.AttachDispatch(lpDisp);
 
          if ( oWorkBook.GetReadOnly() )
          {
               AfxMessageBox(strFileName + _T("文件可能已打开,出错!"), MB_OK | MB_ICONINFORMATION);
               oWorkBook.Close(vFalse, avar, avar);
               oWorkBooks.Close();
               oExcelApp.Quit();
 
               oWorkBook.ReleaseDispatch();
               oWorkBooks.ReleaseDispatch();
               oExcelApp.ReleaseDispatch();
               return FALSE;
          }
 
          oWorkSheets.AttachDispatch(oWorkBook.GetSheets());
         
          int iSheetCount = oWorkSheets.GetCount();
 
          CString strName(_T(""));
          CString strFindText = _T("[*]");
          for ( int i = 1; i &lt;= iSheetCount; ++i )
          {
               lpDisp = oWorkSheets.GetItem(COleVariant((long)i));
               oWorkSheet.AttachDispatch(lpDisp);
               oUseRange.AttachDispatch(oWorkSheet.GetUsedRange());
 
               oShapes.AttachDispatch(oWorkSheet.GetShapes());
              
               lpDisp = oUseRange.Find(COleVariant((LPCTSTR)strFindText), avar, avar, avar ,avar, 1,
                    avar, avar ,avar);         
              
               if ( lpDisp != NULL )
               {
                    oRange.AttachDispatch(lpDisp);
                   
                    long lFirstFinded_Column = oRange.GetColumn();
                    long lFirstFinded_Row     = oRange.GetRow();
 
                    do
                    {
                         if ( oRange.GetMergeCells().boolVal )
                         {
                              oMergeRange.AttachDispatch(oRange.GetMergeArea());
                             
                              fExcelPicHeight          = oMergeRange.GetHeight().dblVal - 1.0;
                              fExcelPicWidth          = oMergeRange.GetWidth().dblVal -1.0;
 
                              oMergeRange.ReleaseDispatch();
                         }
                         else
                         {
                              fExcelPicHeight = oRange.GetHeight().dblVal - 1.0;
                              fExcelPicWidth     = oRange.GetWidth().dblVal - 1.0;                             
                         }
 
                         if( (fExcelPicHeight * 3.0 / 2.0) &lt;= fExcelPicWidth )
                         {
                              fExcelPicWidth = fExcelPicHeight * 3.0 / 2.0;
                         }
                         else
                         {
                              fExcelPicHeight = fExcelPicWidth * 2.0 / 3.0;
                         }
 
                         strName = oRange.GetText().bstrVal;
                         int pos1 = strName.Find('[') + 1;
                         int pos2 = strName.Find(']', pos1);
                         if ( pos2 != -1 )
                         {
                              strName = strName.Mid(pos1, pos2 - pos1);
                              strName.TrimLeft();
                              strName.TrimRight();
                              strName.MakeUpper();
                             
                              mapIter = mapPicInfo.find(strName);
                              if ( mapIter != mapPicInfo.end() )
                              {
                                   float fPicLeft   = oRange.GetLeft().dblVal + (oRange.GetWidth().dblVal - fExcelPicWidth) / 2;
                                   float fPicTop     = oRange.GetTop().dblVal + 1.0;
                                  
                                   CString strPicFile = mapIter-&gt;second;
                                   oShapes.AddPicture((LPCTSTR)(strPicFile), 0, 1,
                                        fPicLeft, fPicTop, fExcelPicWidth, fExcelPicHeight);
 
                                   oRange.Clear();
                              }
                         }
 
                         COleVariant v;
                         V_VT(&amp;v) = VT_DISPATCH;
                         V_DISPATCH(&amp;v) = (IDispatch *)oRange.m_lpDispatch;
                         oRange.AttachDispatch(oUseRange.FindNext(v));
                         V_VT(&amp;v) = VT_ERROR;
                         if ( oRange.m_lpDispatch == NULL )
                         {
                              break;
                         }
 
                         long lFinded_Column = oRange.GetColumn();
                         long lFinded_Row     = oRange.GetRow();
                         if ( (lFinded_Column == lFirstFinded_Column
                              &amp;&amp; lFinded_Row == lFirstFinded_Row) )
                         {
                              break;
                         }
                    } while ( TRUE );
               }
 
               oShapes.ReleaseDispatch();
               oUseRange.ReleaseDispatch();
               oWorkSheet.ReleaseDispatch();
          }
 
          oWorkBook.SaveAs(COleVariant(strOutputFileName.GetBuffer(0)), avar, avar, avar, avar, avar, 1, avar, avar, avar ,avar, avar);
 
          oWorkBook.Close(vFalse, avar, avar);
          oWorkBooks.Close();
          oExcelApp.Quit();
     }
     catch (...)
     {
          oWorkBook.Close(vFalse, avar, avar);
          oWorkBooks.Close();
          oExcelApp.Quit();
 
          CString strMsg;
          strMsg.Format(_T("文件 %s 可能正在被使用,出错!"), (LPCTSTR)strFileName);
          AfxMessageBox(strMsg, MB_OK | MB_ICONINFORMATION);
          return FALSE;         
     }
 
     return TRUE;    
}
 
General【某公司C++笔试题】 [modified] Pin
Sunday, October 12, 2008 10:57 PM by onlinewan
/****************************************************************************
题目要求 :编写函数,检查给定字符串是否整数,如果是,返回其整数值(注:不允许使用某种特定的库函数)。
 
用C描述的算法,注释略
****************************************************************************/
int is_int(const char *str, int *num)
{
     char *p = (char *)str;
     int temp = 0;
     char sign = '+';
    
     if ( !str )
     {
          assert(0);
          return 0;
     }
 
     do
     {
          if ( *p == ' ' )
          {
               p++;
          }
          else
          {
               break;
          }
     } while( *p != '\0' );
    
     if ( *p == '-' || *p == '+' )
     {
          sign = *p++;
     }
 
     while ( *p != '\0' )    
     {
          if ( (*p &gt;= '0') &amp;&amp; (*p &lt;= '9') )
          {
               temp = temp * 10 + (*p - '0');
          }
          else
          {
               return 0;
          }
         
          p++;
     }
 
     *num = sign == '-' ? -temp : temp;
    
     return 1;
}
 

 
/****************************************************************************
题目要求 :编写函数实现字符串分割。SourceStr为源串,splitStr为分割字符串,SplitStr中的每一个字符在SourceStr被看作是分  
   割符。函数需要返回被分割符分割好的字符串链表。
   例如: 如果
         SourceStr为“this is pen ,that is a ball.”。
         SplitStr   为“, .”
 
用C描述的算法,注释略
****************************************************************************/
struct node{
     char *str;
     struct node *next;
};
 
node* split_string(const char *str, const char *token)
{
     char *p = (char *)str;
     char *ch = (char *)token;
 
     char map[128];
     char *pos = p;
     char *substr = NULL;
     node l;
     node *plist = &amp;l;
     node *pnode = NULL;
     int loop = 0;
 
     if ( str == NULL || token == NULL )
     {
          assert(0);
          return NULL;
     }
    
     l.next = NULL;
 
     while ( *ch != '\0' )
     {
          map[*ch] = *ch++;
     }
 
     while ( *p != '\0' )
     {
          if ( map[*p] == *p )
          {
               pnode = (node *)malloc(sizeof(node));
               substr = (char *)malloc(sizeof(char) * (p - pos + 1));
               while ( pos != p )
               {
                    substr[loop++] = *pos++;
               }
               substr[loop] = '\0';
               pnode-&gt;next = NULL;
               pnode-&gt;str = substr;
               plist-&gt;next = pnode;
               plist = pnode;
               loop = 0;              
               pos = ++p;
          }
          else
          {
               ++p;
          }
     }
 
     return l.next;         
}
 
void print_list(node *l)
{
     while ( l != NULL )
     {
          printf("%s|", l-&gt;str);
          l = l-&gt;next;
     }
}
 
void free_memory(node *l)
{
     node *p = l;
 
     if ( l == NULL )
     {
          return;
     }
 
     do
     {
          p = l-&gt;next;
          free(l-&gt;str);
          free(l);
          l = p;
     } while( l != NULL );
}
 
int main(int argc, char* argv[])
{
     int num = 0;
     char *strtest = " this   is   pen , that   is   a   bal. ";
     node *l = NULL;
    
     is_int("   +51111", &amp;num);
     printf("%d\n", num);
 

     cout &lt;&lt; endl &lt;&lt; endl;
     cout &lt;&lt; strtest &lt;&lt; endl;    
     l = split_string(strtest, ", .");
     print_list(l);
     free_memory(l);
     l = NULL;    
    
     system("pause");
     return 0;
}
 
modified on Thursday, October 23, 2008 9:14 PM
 
General四道微软面试算法题 [modified] Pin
Sunday, October 12, 2008 4:28 PM by onlinewan
/****************************************************************************
题目要求 :一个整数数列,元素取值可能是0~65535中的任意一个数,相同数值不会重复出现。0是例外,可以反复出现。
请设计一个算法,当你从该数列中随意选取5个数值,判断这5个数值是否连续相邻。
注意:
- 5个数值允许是乱序的。比如: 8 7 5 0 6
- 0可以通配任意数值。比如:8 7 5 0 6 中的0可以通配成9或者4
- 0可以多次出现。
- 复杂度如果是O(n2)则不得分。
 
用C描述的算法
功能          :判断随意取的数值是否连续相邻,相邻返回1,否则返回0
参数array     :存储随意取的数
参数size     :随意取的数的个数    
****************************************************************************/
int is_progression(array, size)
{
     /*最大值的索引和最小值的索引*/
     maxIndex = 0;    
     minIndex   = 0;
    
     i = 0;
     /*试图找到第一个不为0的元素,初始化maxIndex和minIndex*/
     for ( ; i &lt; size; ++i )
     {
          if ( array[i] != 0 )
          {
               maxIndex = minIndex = i;
               break;
          }
     }
 
     /*试图确定随意取的数中的最大值和最小值*/
     for ( ; i &lt; size; ++i )
     {
          if ( array[i] &gt; array[maxIndex] )
          {
               maxIndex = i;
          }
          else if ( array[i] &lt; array[minIndex] )
          {
               minIndex = i;
          }
     }
 
     /*如果最大值和最小值的差小于总个数,则可以判定它们是连续相邻的*/
     return (array[maxIndex] - array[minIndex]) &lt; size ? 1 : 0;
}    
 

/****************************************************************************
题目要求 :设计一个算法,找出二叉树上任意两个结点的最近共同父结点。
复杂度如果是O(n2)则不得分。  
 
用C描述的算法,注释略
****************************************************************************/
typedef int datatype
typedef struct tree_node{
datatype data;
struct tree_node *lchild;
struct teee_node *rchild;
}treenode, *lptreenode;
treenode* find_parentnode(tree, node1, node2)
{
     initstack(s);
     push(s, tree);
     finded = 0;
     parentnode = tree;
 
     while ( !stackempty(s) )
     {
          while ( gettop(s, p) &amp;&amp; p )
          {
               if ( p == node1 )
               {
                    finded += 1;
               }
               if ( p == node2 )
               {
                    finded += 1;
               }
 
               if ( finded == 0 )
               {
                    parentnode = p;
                    break;
               }
               else if ( finded == 2 )
               {
                    break;
               }
 
               push(s, p-&gt;lchild);
          }
 
          if ( finded == 3 )
          {
               break;
          }
          else if ( parentnode != NULL )
          {
               while ( pop(s, p) &amp;&amp; p == parentnode )
               {
                    break;
               }
 
               push(s, p-&gt;rchild);
          }
     }
 
     return finded == 3 ? parentnode : NULL;
}
 

/****************************************************************************
题目要求 :一棵排序二叉树,令 f=(最大值+最小值)/2,设计一个算法,找出距离f值最近、大于f值的结点。
复杂度如果是O(n2)则不得分。  
 
用C描述的算法,注释略
****************************************************************************/
treenode* find_parentnode(tree, f)
{
     tempnode = tree;
     while ( tempnode   )
     {
          if ( tempnode-&gt;data &gt; f )
          {
               if ( NULL == tree-&gt;lchild
               || tree-&gt;lchild-&gt;data &lt;= f )
               {
                    break;
               }
 
               tempnode = tree-&gt;lchild;
          }
          else
          {
               if ( NULL == (tempnode = tempnode-&gt;right)
               || tempnode-&gt;data &gt; f )
               {
                    break;
               }
          }
     }
 
     return tempnode;
}
 

/****************************************************************************
题目要求 :一个整数数列,元素取值可能是1~N(N是一个较大的正整数)中的任意一个数,相同数值不会重复出现。
设计一个算法,找出数列中符合条件的数对的个数,满足数对中两数的和等于N+1。
复杂度最好是O(n),如果是O(n2)则不得分。
 
用C描述的算法
****************************************************************************/
int get_numberpair_count(array, size, N)
{
     count = 0;
     temp_array_size = N / 2 + 1;
     temp_index = 0;
 
     temp_array[temp_array_size];
 
     for ( i = 0; i &lt; size; ++i )
     {
          temp_index = array[i] &lt; temp_array_size ? array[i] : (N-array[i]);
          if ( temp_array[temp_index] == 1 )
          {
               ++count;
          }
          else
          {
               temp_array[temp_index] = 1;
          }
     }
 
     return count;
}
 
modified on Thursday, October 23, 2008 9:13 PM

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   


Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 26 May 2013
Copyright © CodeProject, 1999-2013
All Rights Reserved. Terms of Use
Layout: fixed | fluid