|
.h
#ifndef __REPORTCTRL_H__
#define __REPORTCTRL_H__
#define WM_ON_CHKBOX (WM_APP + 10000)
#define WM_ITEM_SORTED (WM_APP + 10001)
#define WM_EDIT_COMMITTED (WM_APP + 10002)
#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,
#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
#define RC_INVERT_SELECTION 0 // Invert item selection
#define RC_INVERT_CHECKMARK 1 // Invert item check mark
#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;
int m_OrgPosition;
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);
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;
};
class CReportCtrl : public CListCtrlColumnEx
{
public:
CReportCtrl();
virtual ~CReportCtrl();
virtual BOOL Create(CWnd* pParentWnd, UINT nID, LPCRECT lpRect = NULL, DWORD dwStyle = WS_BORDER | WS_TABSTOP);
int GetColumnCount();
void AdjustColumnWidth();
void CancelAllSelectedState();
int GetAllSelectedIndexs(CDWordArray &aryIndex);
BOOL SetColumnHeader(const CString& strHeadings);
int GetColumnCount() const;
BOOL DeleteAllColumns();
CString GetHeaderText(int nColumn) const;
BOOL SetHeaderText(int nColumn, LPCTSTR lpText);
BOOL HasColumnHeader() const;
const CHeaderCtrl* GetHeaderCtrl() const;
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);
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;
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;
void ResizeToFitParent();
void SetGridLines(BOOL bSet = TRUE);
void SetCheckboxeStyle(int nStyle = RC_CHKBOX_NORMAL);
int GetCheckboxStyle() const;
BOOL IsSortable() const;
BOOL SetSortable(BOOL bSet);
BOOL IsEditable() const;
void SetEditable(BOOL bSet = TRUE);
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);
int InsertItemEx(int nItem, LPCTSTR lpText, ...);
BOOL DeleteItem(int nItem, BOOL bSelectNextItem = FALSE);
int DeleteAllItems(DWORD dwStates = RC_ITEM_ALL);
int MoveUp(int nItem, int nCount = 1);
int MoveDown(int nItem, int nCount = 1);
int MoveToTop(int nItem);
int MoveToBottom(int nItem);
int MoveTo(int nItem, int nNewPosition);
BOOL SwapItems(int nItem1, int nItem2);
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);
BOOL IsSortAscending() const;
int GetSortedColumn() const;
void SortItems(int nColumn, BOOL bAscending);
void SetSortSeparator(LPCTSTR lpSortSeparator = NULL);
LPCTSTR GetSortSeparator() const;
virtual BOOL StartEdit(int nItem, int nSubItem);
virtual BOOL EndEdit(BOOL bCommit = TRUE);
CEdit* GetEditControl();
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);
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:
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);
CEdit* m_pWndEdit;
LPTSTR m_pszSeparator;
BOOL m_bAllowEdit;
POINT m_ptEditting;
int m_nChkStyle;
DWORD m_dwPrevEditFmt;
CImageList m_imgList;
CImageList m_headerImgList;
int m_nSortCol;
BOOL m_bSortAscending;
public:
virtual BOOL PreTranslateMessage(MSG* pMsg);
protected:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
virtual void PreSubclassWindow();
protected:
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);
DECLARE_MESSAGE_MAP()
};
#endif // __REPORTCTRL_H__
.cpp
#include "stdafx.h"
#include "ReportCtrl.h"
#include <afxtempl.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define MUST_STYLE (WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | LVS_REPORT)
#define MUST_EX_STYLE (LVS_EX_FULLROWSELECT | LVS_EX_SUBITEMIMAGES)
#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;
};
class CItemData
{
public:
CItemData() { dwData = 0; }
void InsertColumn(int nColumn);
void DeleteColumn(int nColumn);
DWORD dwData;
CArray<COLORREF, COLORREF> aTextColors;
CArray<COLORREF, COLORREF> aBkColors;
};
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);
}
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::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)
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)
END_MESSAGE_MAP()
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;
const int COL = pNMListView->iSubItem;
SortItems(COL, COL == m_nSortCol ? !m_bSortAscending : TRUE);
*pResult = 0;
}
void CReportCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
_MouseClkMonitor(WM_LBUTTONDOWN, nFlags, point, TRUE);
}
void CReportCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
{
_MouseClkMonitor(WM_LBUTTONDBLCLK, nFlags, point, TRUE);
}
void CReportCtrl::OnMButtonDown(UINT nFlags, CPoint point)
{
_MouseClkMonitor(WM_MBUTTONDOWN, nFlags, point, FALSE);
}
void CReportCtrl::OnMButtonDblClk(UINT nFlags, CPoint point)
{
_MouseClkMonitor(WM_MBUTTONDBLCLK, nFlags, point, FALSE);
}
void CReportCtrl::OnRButtonDown(UINT nFlags, CPoint point)
{
_MouseClkMonitor(WM_RBUTTONDOWN, nFlags, point, FALSE);
}
void CReportCtrl::OnRButtonDblClk(UINT nFlags, CPoint point)
{
_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;
SetExtendedStyle(GetExtendedStyle());
ASSERT(GetHeaderCtrl() != NULL);
return 0;
}
void CReportCtrl::OnDestroy()
{
DeleteAllItems();
m_pWndEdit->DestroyWindow();
m_imgList.DeleteImageList();
m_headerImgList.DeleteImageList();
CListCtrlColumnEx::OnDestroy();
}
BOOL CReportCtrl::_IsValidIndex(int nIndex) const
{
return nIndex >= 0 && nIndex < CListCtrlColumnEx::GetItemCount();
}
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)
{
for (int i = 0; i < nItemCount; i++)
_FreeItemMemory(i);
CListCtrlColumnEx::DeleteAllItems();
return nItemCount;
}
int nDelCount = 0;
for (int i = 0; i < nItemCount; i++)
{
if (ExamItemStates(i, dwStates))
{
DeleteItem(i--);
nItemCount--;
nDelCount++;
}
}
return nDelCount;
}
void CReportCtrl::SortItems(int nColumn, BOOL bAscending)
{
EndEdit(TRUE);
if (nColumn < 0 || nColumn >= GetColumnCount() || !IsSortable())
return;
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();
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);
}
CListCtrlColumnEx::DeleteItem(nItem);
const int IDX = CListCtrlColumnEx::InsertItem(nNewPosition, _T(""));
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();
const DWORD STATES1 = GetItemStates(nItem1);
const DWORD STATES2 = GetItemStates(nItem2);
const DWORD DATA1 = CListCtrlColumnEx::GetItemData(nItem1);
const DWORD DATA2 = CListCtrlColumnEx::GetItemData(nItem2);
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);
}
CListCtrlColumnEx::SetItemData(nItem1, DATA2);
CListCtrlColumnEx::SetItemData(nItem2, DATA1);
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)
{
if (!bBefore && bAfter)
{
SetAllItemStates(RC_ITEM_CHECKED, RC_ITEM_UNCHECKED);
SetItemStates(nIndex, RC_ITEM_CHECKED);
}
}
else if (m_nChkStyle == RC_CHKBOX_DISABLED)
{
SetItemStates(nIndex, bBefore ? RC_ITEM_CHECKED : RC_ITEM_UNCHECKED);
return TRUE;
}
SetAllItemStates(RC_ITEM_SELECTED, RC_ITEM_UNSELECTED);
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())
{
nEnd = str.Find(chDelimitior, nStart);
if( nEnd == -1 )
{
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)
{
cs.style &= ~MUST_NOT_STYLE;
cs.style |= MUST_STYLE;
return CListCtrlColumnEx::PreCreateWindow(cs);
}
BOOL CReportCtrl::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message == WM_KEYDOWN)
{
if (!_IsEditVisible())
{
if (pMsg->wParam == VK_SPACE)
return TRUE;
}
else
{
POINT pt = m_ptEditting;
switch (pMsg->wParam)
{
case VK_ESCAPE:
EndEdit(FALSE);
return TRUE;
case VK_RETURN:
EndEdit(TRUE);
return TRUE;
case VK_TAB:
if (pt.y == GetColumnCount() - 1)
pt.y = 0;
else
pt.y++;
EndEdit(TRUE);
StartEdit(pt.x, pt.y);
return TRUE;
case VK_UP:
if (pt.x > 0)
{
pt.x--;
EndEdit(TRUE);
StartEdit(pt.x, pt.y);
EnsureVisible(pt.x, FALSE);
return TRUE;
}
break;
case VK_DOWN:
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)
{
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()
{
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()
{
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)
{
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);
SetItemStates(m_ptEditting.x, RC_ITEM_SELECTED | RC_ITEM_FOCUSED);
const DWORD FMT = _GetHeaderTextFormat(nSubItem);
if (FMT != m_dwPrevEditFmt)
{
m_dwPrevEditFmt = FMT;
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);
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)
{
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;
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
{
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)
{
CItemData* p = (CItemData*)(CListCtrlColumnEx::GetItemData(nItem));
ASSERT(p != NULL);
p->aTextColors[nSubItem] = color;
}
else if (bRowValid && !bColValid)
{
CItemData* p = (CItemData*)(CListCtrlColumnEx::GetItemData(nItem));
ASSERT(p != NULL);
for (int i = 0; i < COLS; i++)
p->aTextColors[i] = color;
}
else if (!bRowValid && bColValid)
{
for (int i = 0; i < ROWS; i++)
{
CItemData* p = (CItemData*)(CListCtrlColumnEx::GetItemData(i));
ASSERT(p != NULL);
p->aTextColors[nSubItem] = color;
}
}
else
{
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)
{
CItemData* p = (CItemData*)(CListCtrlColumnEx::GetItemData(nItem));
ASSERT(p != NULL);
p->aBkColors[nSubItem] = color;
}
else if (bRowValid && !bColValid)
{
CItemData* p = (CItemData*)(CListCtrlColumnEx::GetItemData(nItem));
ASSERT(p != NULL);
for (int i = 0; i < COLS; i++)
p->aBkColors[i] = color;
}
else if (!bRowValid && bColValid)
{
for (int i = 0; i < ROWS; i++)
{
CItemData* p = (CItemData*)(CListCtrlColumnEx::GetItemData(i));
ASSERT(p != NULL);
p->aBkColors[nSubItem] = color;
}
}
else
{
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);
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);
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);
}
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;
if( pParent )
{
pNMHdr -> hdr.idFrom = GetDlgCtrlID();
*pResult = pParent -> SendNotifyMessage( WM_NOTIFY,
GetDlgCtrlID(), (LPARAM)pNMHdr );
}
return;
}
void CReportCtrl::OnFilterButtonClicked(NMHDR* pNMHDR, LRESULT* pResult)
{
NMHDFILTERBTNCLICK *pNMFButtonClick = (NMHDFILTERBTNCLICK*)pNMHDR;
NMHEADER *pNMHdr = (NMHEADER*)pNMHDR;
CWnd *pParent = GetParent();
*pResult = 0;
if( pParent )
{
pNMHdr -> hdr.idFrom = GetDlgCtrlID();
*pResult = pParent -> SendNotifyMessage( WM_NOTIFY,
GetDlgCtrlID(), (LPARAM)pNMHdr );
}
return;
}
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();
}
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()
ON_WM_KEYDOWN()
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)
{
columnState.m_Visible = true;
if ( columnState.m_OrgWidth == 0 )
{
columnState.m_OrgWidth = LVSCW_AUTOSIZE;
}
VERIFY( SetColumnWidth(nCol, columnState.m_OrgWidth) );
}
else
{
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())
{
m_ColumnStates.Add(columnState);
}
else
{
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)
{
}
else
{
CPoint pt = point;
ScreenToClient(&pt);
CRect headerRect;
GetHeaderCtrl()->GetClientRect(&headerRect);
if (headerRect.PtInRect(pt))
{
CMenu menu;
if (menu.CreatePopupMenu())
{
for( int i = GetColumnStateCount()-1 ; i >= 0; --i)
{
UINT uFlags = MF_BYPOSITION | MF_STRING | MF_ENABLED;
if (IsColumnVisible(i))
uFlags |= MF_CHECKED;
else
uFlags |= MF_UNCHECKED;
if(GetReadOnlyShowState(i))
uFlags |= MF_GRAYED;
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);
}
menu.TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y, this, 0);
}
}
}
}
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)
{
CListCtrl::OnKeyDown(nChar, nRepCnt, nFlags);
}
BOOL CListCtrlColumnEx::OnHeaderBeginResize(UINT id, NMHDR* pNMHDR, LRESULT* pResult)
{
NMHEADER* pNMH = (NMHEADER*)pNMHDR;
int nCol = (int)pNMH->iItem;
if (!IsColumnVisible(nCol))
{
*pResult = TRUE;
return TRUE;
}
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)
{
int nCol = (int)wParam;
if (!IsColumnVisible(nCol))
{
return FALSE;
}
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)
{
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;
}
LRESULT CListCtrlColumnEx::OnDeleteColumn(WPARAM wParam, LPARAM lParam)
{
LRESULT lRet = DefWindowProc(LVM_DELETECOLUMN, wParam, lParam);
if (lRet == FALSE)
return FALSE;
DeleteColumnState((int)wParam);
return lRet;
}
LRESULT CListCtrlColumnEx::OnInsertColumn(WPARAM wParam, LPARAM lParam)
{
LRESULT lRet = DefWindowProc(LVM_INSERTCOLUMN, wParam, lParam);
if (lRet == -1)
return -1;
int nCol = (int)lRet;
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);
}
}
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);
hinstDll = ::LoadLibrary(_T("UxTheme.dll"));
if (hinstDll)
{
(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)
{
HANDLE hTheme = pOpenThemeData(hwnd,classList);
if (hTheme!=NULL)
{
VERIFY(pCloseThemeData(hTheme)==S_OK);
lResult = pSetWindowTheme(hwnd, subApp, idlist);
}
}
}
::FreeLibrary(hinstDll);
}
return lResult;
}
}
void CListCtrlColumnEx::PreSubclassWindow()
{
CListCtrl::PreSubclassWindow();
#if (_WIN32_WINNT >= 0x501)
SetExtendedStyle(LVS_EX_DOUBLEBUFFER | GetExtendedStyle());
#endif
}
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)
{
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
{
LVHITTESTINFO lvhitTestInfo;
lvhitTestInfo.pt = point;
int nItem = ListView_SubItemHitTest(
this->m_hWnd,
&lvhitTestInfo);
int nSubItem = lvhitTestInfo.iSubItem;
UINT nFlags = lvhitTestInfo.flags;
if (nFlags & LVHT_ONITEMLABEL){
RECT rcClient;
GetClientRect( &rcClient );
pTI->hwnd = m_hWnd;
pTI->uId = (UINT) (nItem * 100 + nSubItem);
pTI->lpszText = LPSTR_TEXTCALLBACK;
pTI->rect = rcClient;
return pTI->uId;
}else{
return -1;
}
}
BOOL CListCtrlColumnEx::OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
{
TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
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;
const MSG* pMessage;
pMessage = GetCurrentMessage();
ASSERT ( pMessage );
CPoint pt;
pt = pMessage->pt;
ScreenToClient( &pt );
LVHITTESTINFO lvhitTestInfo;
lvhitTestInfo.pt = pt;
int nItem = SubItemHitTest(&lvhitTestInfo);
int nSubItem = lvhitTestInfo.iSubItem;
UINT nFlags = lvhitTestInfo.flags;
if( nFlags & LVHT_ONITEMLABEL )
{
strTipText = GetItemToolTipText(nItem, nSubItem);
if( !strTipText.IsEmpty() )
{
#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;
}
}
return FALSE;
}
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);
}
}
|
|
|
|
|
当Windows的Explorer进程意外终止重启后,程序的托盘图标就不见了。这是由于程序中没有对这种事件没有做处理的缘故。我们可以通过下面的方式解决此问题,在Explorer进程重启后,托盘图标任显示在状态栏。
在下面的虚函数中响应Explorer重启事件:
LRESULT CChatServerDlg::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
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.hIcon=LoadIcon(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDR_MAINFRAME));
strcpy(tnd.szTip, _T("托盘图标演示"));
Shell_NotifyIcon(NIM_ADD,&tnd);
}
return CDialog::DefWindowProc(message, wParam, lParam);
}
|
|
|
|
|
截图对话框源码:
.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
class CDlgTest1 : public CDialog
{
public:
CDlgTest1(CWnd* pParent = NULL);
enum { IDD = IDD_DIALOG1 };
static void CapScreenBitmap(CBitmap &memBitmap);
CBitmap m_Bitmap;
CBitmap m_ResultBitmap;
public:
virtual BOOL PreTranslateMessage(MSG* pMsg);
protected:
virtual void DoDataExchange(CDataExchange* pDX);
protected:
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);
DECLARE_MESSAGE_MAP()
private:
CPoint m_ptStart;
CPoint m_ptEnd;
BOOL m_bSelected;
BOOL m_bDoing;
HCURSOR m_hCursor;
};
#endif // !defined(AFX_DLGTEST1_H__CB58A726_ACFB_4A7D_ADE6_D81871CC5421__INCLUDED_)
.cpp
#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::CDlgTest1(CWnd* pParent )
: CDialog(CDlgTest1::IDD, pParent)
{
m_bSelected = FALSE;
m_bDoing = FALSE;
}
void CDlgTest1::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CDlgTest1, CDialog)
ON_WM_PAINT()
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONUP()
ON_WM_LBUTTONDOWN()
ON_WM_CREATE()
END_MESSAGE_MAP()
BOOL CDlgTest1::OnInitDialog()
{
CDialog::OnInitDialog();
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;
}
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);
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);
}
}
void CDlgTest1::OnMouseMove(UINT nFlags, CPoint point)
{
if ( m_bDoing )
{
m_ptEnd = point;
ClientToScreen(&m_ptEnd);
this->Invalidate(TRUE);
}
CDialog::OnMouseMove(nFlags, point);
}
void CDlgTest1::OnLButtonUp(UINT nFlags, CPoint point)
{
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)
{
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;
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)
{
if ( pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE )
{
CDialog::OnCancel();
}
if ( pMsg->message == WM_RBUTTONUP )
{
CDialog::OnCancel();
}
return CDialog::PreTranslateMessage(pMsg);
}
调用对话框源码:
.h
#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");
class CMyDlg : public CDialog
{
public:
CMyDlg(CWnd* pParent = NULL);
enum { IDD = IDD_MY_DIALOG };
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);
public:
virtual BOOL PreTranslateMessage(MSG* pMsg);
protected:
virtual void DoDataExchange(CDataExchange* pDX);
protected:
HICON m_hIcon;
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();
DECLARE_MESSAGE_MAP()
};
#endif // !defined(AFX_DLG_H__EFED66EB_A124_4791_B8D8_E64E6E1CF01F__INCLUDED_)
.cpp
#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
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX);
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
CMyDlg::CMyDlg(CWnd* pParent )
: CDialog(CMyDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CMyDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
ON_BN_CLICKED(IDC_BUTTON2, OnButton2)
ON_WM_CLOSE()
END_MESSAGE_MAP()
BOOL CMyDlg::OnInitDialog()
{
CDialog::OnInitDialog();
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);
}
}
SetIcon(m_hIcon, TRUE);
SetIcon(m_hIcon, FALSE);
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);
}
return TRUE;
}
void CMyDlg::OnClose()
{
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);
}
}
void CMyDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this);
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
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;
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
HCURSOR CMyDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CMyDlg::OnButton1()
{
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()
{
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)
{
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)
{
return CDialog::PreTranslateMessage(pMsg);
}
主程序实例源码:
.h
#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"
class CMyApp : public CWinApp
{
public:
CMyApp();
public:
virtual BOOL InitInstance();
DECLARE_MESSAGE_MAP()
};
#endif // !defined(AFX__H__B75C0466_F802_49D4_860E_274339DD06D5__INCLUDED_)
.cpp
#include "stdafx.h"
#include "截屏.h"
#include "截屏Dlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
BEGIN_MESSAGE_MAP(CMyApp, CWinApp)
ON_COMMAND(ID_HELP, CWinApp::OnHelp)
END_MESSAGE_MAP()
CMyApp::CMyApp()
{
}
CMyApp theApp;
BOOL CMyApp::InitInstance()
{
AfxEnableControlContainer();
#ifdef _AFXDLL
Enable3dControls();
#else
Enable3dControlsStatic();
#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)
{
}
else if (nResponse == IDCANCEL)
{
}
return FALSE;
}
资源文件源码:
.rc
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
#include "afxres.h"
#undef APSTUDIO_READONLY_SYMBOLS
#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
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
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
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
#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
IDC_CURSOR1 CURSOR DISCARDABLE "res\\arrow_m.cur"
IDR_MAINFRAME ICON DISCARDABLE "res\\截屏.ico"
STRINGTABLE DISCARDABLE
BEGIN
IDS_ABOUTBOX "关于 截屏(&A)..."
END
#endif // Chinese (P.R.C.) resources
#ifndef APSTUDIO_INVOKED
#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"
#include "l.chs\afxres.rc"
#endif
#endif // not APSTUDIO_INVOKED
Resource.h
#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
#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
|
|
|
|
|
实现方法:在CCombox的派生类中,添加CBN_DROPDOWN响应函数和获得下拉列表的自适应显示宽度函数,在CBN_DROPDOWN的响应函数OnDropDown()中重设下拉列表宽度。
具体可参考如下代码:
.h文件:
class CAutoAdjustWidthComboBox : public CComboBox
{
protected:
afx_msg void OnDropDown();
DECLARE_MESSAGE_MAP()
private:
int GetDropListWidth();
}
.cpp文件:
BEGIN_MESSAGE_MAP(CAutoAdjustWidthComboBox, CComboBox)
ON_CONTROL_REFLECT(CBN_DROPDOWN, OnDropDown)
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;
}
|
|
|
|
|
学友们,大家好:
在此之前,我做了很大的思想斗争,我怀疑我的所述能不能给大家带来帮助。如果您正在为找工作发愁,或者对勉强找到的工作不满意,您可以试着看完这封信。
先简单做个自我介绍哈。个人背景就不多做介绍了,就是个从农村走出来的娃。我上的是地处二线城市的一所师范学院,学的是计算机科学与技术专业,07年毕业,现在在北京做软件开发。
想做软件的,都想往一线城市跑,我也不例外,这也正是我现在在北京的原因。记得我是07年五一放假时来北京找工作的,我之前没有来过北京,所以我叫了个同学一起来的,不过他也没来过,幸好他有个同学在北京上学。这就解决了我俩初到北京住的问题。北京好大,这就是给我的第一感觉,决定一定要在北京工作。刚开始的一周,由于是五一长假,我俩没有找工作,而是好好的在北京逛,最先去的就是天安门了,站在那里,感觉好庆幸,好自豪。去了清华北大,又感觉好自卑,后悔自己当初没有好好读书。同时,也感觉到了压力,北京有这么多一流的大学,像我这样的在北京找工作太没有优势了。很快,五一长假就这么过去了,由于不能长期在同学的同学的学校住下去,我俩选择租了个地下室,同时开始在网上投简历,北京上网真贵,一小时五块,为了保证能吃饱我每天只能上一个小时。我的第一份简历写的很花绡,自我感觉像那样的简历找个工作还是很容易的事情。可在我很乐观,很积极的投了近一周的简历,没有接到一个面试通知的时候,我迷茫了,我开始怀疑我是不是太自信了,怀疑北京根本不是我这种人呆的地方。接下来有两天,我都没有去投简历,迷迷糊糊的。可能是上天看不下去让我这颗脆弱的心再受伤害,我得到了一位网友的指点与开导,照着他的描述,我修改了我的简历,内容不再花绡了,变的简单真实,多了对专业技术、自己经历的描述。刚刚改完我就迫不及待的投了好几份出去。心情又变得乐观了起来,高高兴兴的跑回地下室,进了被卧就睡了,虽然地下室很潮,可我今天却感觉很舒适。果不出网友所料,第二天就接到了好几个通知面试的电话。那个高兴,激动,是无法用主语能表达的。
回头看了下,好像说了很多不着边际的话哦。哈哈,还请多多包涵。说起难忘的经历就打不住了。
想做软件的都想进大公司,一流企业,我还是不例外。接下来,我每天都有面试,可是当我经历了几次面试之后,我又开始迷茫了,怎么都是一些小公司,就没多少人,和自己想的差距也太大了。待遇也很低,在北京可能勉强够生存。有了回老家教书都比这强的念头。可是我真得很想做编程,我该怎么办呢,我是回是留?我又去找了那位网友。是他再次给了我信心,他叫我务实点,面对残酷的就业压力,把自己摆在正确的位置上,能先找个工作就很不容易了,至于自己的大理想,可以在工作了以后再重新规划实现。待遇只要刚开始能保证基本的生活也是可以接受的,只要是金子都会发光,但一定要有发光的机会。听了他的话,我开始重新定位自己,我决定先找个差不多的公司。相对来说,我要找一个要求不太高的公司还是比较容易的,我的计算机基础知识,对C++的理解还算是可以的,常见的面试题基本都难不倒我。我真得不是炫耀,说这个只是想说,在学校虽然不能学到很多的实用技能,但一定要打下扎实的基础。没费多大周折,我就找了现在的公司定了下来。待遇不高,试用期一个月2K,呵呵,够低了吧。不过我还是接受了,我觉得那只是暂时的。进了公司,我好多好多东西都不会,我很努力,我不太喜欢什么问题都去问人,刚开始的一个月里,我基本都是在代码堆里度过的,可能阅读了有好几万行的代码,一个项目的代码让我差不多看完了。这为我后来很快融入项目打下了基础。
就到这吧,再写就跑题跑的更远了,向来文笔不行。 做个小结:
在遇到挫折的时候,能有个前辈指点开导,对自己是莫大的鼓舞。
面对现实,我们务实一点,会少去很多烦恼与不快。
是金子都会发光,但一定要有发光的机会。
空闲的时候不要只是娱乐,提升下自己生存的本领,不至于真正需要的时候,没什么可拿出来的。
困难只是暂时的,我们要有尽快战胜困难的信心。
偶尔委屈下自己,能换的更美好的明天。
愿学友们顺利找到自己喜欢的工作,身体健键康康,生活充实快乐!
onlinewan
写在09年愚人节前一天
|
|
|
|
|
计划为什么不能如期完成?
中国今年经济增长要保八,柳传志复出要在今年扭转联想亏损的局面,这周五开总结会,下周末出去玩,,小虎想今年年底使银行的存款从0变为10万,小花这个月想把体重从65KG减到45KG,等等。
大到国家,小到个人,这些都是计划。不对,上面所列真的都是计划吗?
准确的说,它们都不是计划,只能称的上是目标,是想达到的效果。当然,也不能排除它们都只是美梦,或者说是幻想。
计划,是指为了到达类似上面所列的目标所制订的行动方案。制订计划的目的很明确,就是为了达到目标,使美梦成真。
中国今年要保八,在经济寒冬设定这样的目标一定是经过深思熟虑的。是有了去年就悄然进行的全国各个地区的经济普查,社科院、工信部、保监会、银监会对全国公民消费理念,个人积蓄的考察,等等一系列的数据统计,才制定的目标。可见,制定这样的目标应该是可行的,是可以实现的。但是,光有能实现目标的潜力是远远不够的。更重要的是要制订合理的计划并执行,以保证实现保八的目标。实行减免税收、鼓励创业、放宽信贷、家电下乡等等惠民政策以提高就业、刺激消费拉到内需,可以看到,国家正在按照计划一步一步的走向目标,并且已经初见成效。希望中国能最终实现目标。
小虎想今年年底使银行的存款从0变为10万,我想这应该小虎是经过详细的分析规划后的决定。要想从0变为10万,对有些人来说是很容易的事情,对有些人来说,经过一定的努力是可以实现的,可对于有些人来说,那是根本不可能的。小虎一定是通过分析自己自身的能力,现有的收入,可提升的空间,日常基本消费水平等等后,得出自己到年底有希望使存款达到10万。小虎也根据自己分析的结果制订了符合自己的行动计划。从现在开始提高自身能力,以带动自己收入的提升,开始建立自己的小帐本,对日常开销进行记录,在一定的时间间隔下统计分析自己的日常开支情况,调整开支,减少开支,使开支合理化。等等行动,是小虎年底实现存款达到10万的保障。
可见,目标的制订是要有一定的依据的,目标的实现需要合理的计划,更需要计划的执行力。但是,往往有一部分人的目标都是不合理的,不现实的,或者没有执行力。
小花这个月想把体重从65KG减到45KG,这对于女孩子来说,是非常高效的减肥了。可是这个是不现实的,至少对于绝大多数人来说是不太可能的。可见小花有这样的美梦,一定是没有经过仔细分析的,是盲目的。
如果小花的目标是这个月把体重从65KG减到60KG,这个对于大部分减肥的人来说,不是一件很难的事,也是可以找出很多例子的。但是小花没有为自己制订减肥计划,只是成天嘴上说要减肥,成天还是大吃大喝,不加强锻炼,那本来可能的事,就变成不可能了。
如果小虎今年年底使银行的存款从0变为10万是可行的,是可以达到的,小虎也制订了自己的计划,但是,但是它对自己的计划没有长久坚持执行,或者说是三天打鱼两天晒网,甚至根本就没有行动,那他的目标实现就没有了保障,也是不太可能达到的。
可见目标不能实现的原因,主要有三个方面:制定的目标就是不现实的;没有对目标的实现制订合理的计划;有合理的计划但是没有执行力。那么,我们以后对待目标,是不是需要深思熟虑+周密计划+执行力呢? 当我们的目标不能实现的时候,是不是也应该从这三个方面,来分析原因,并有针对性的总结经验,在下次改进呢?
看到这大家有没有觉得本文的标题起得好像有点问题?应该改为“目标为怎么不能实现?”才合适点哦。
quote------------------------------------------------------------------
温总理说:经济寒冬我们最缺的不是钱,而是必胜的信心。
|
|
|
|
|
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->GetIDsOfNames ( IID_NULL ,
& ptName ,
1 ,
LOCALE_USER_DEFAULT ,
& 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 < cArgs; i++ )
{
pArgs [ i ] = va_arg ( marker , VARIANT );
}
dp.cArgs = cArgs;
dp.rgvarg = pArgs;
if ( autoType & DISPATCH_PROPERTYPUT )
{
dp.cNamedArgs = 1;
dp.rgdispidNamedArgs = & dispidNamed;
}
hr = pDisp->Invoke ( dispID ,
IID_NULL ,
LOCALE_SYSTEM_DEFAULT ,
autoType ,
& 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, &ADoc, acedGetAcadWinApp()->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, &ADoc, ADoc.pdispVal, L"Open", 2, vrOpenMode, vrFileName);
::VariantClear (&vrFileName);
bReturn = (FAILED(hr) ? FALSE : TRUE);
::VariantClear (&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, &ADoc, acedGetAcadWinApp()->GetIDispatch(TRUE), L"Documents", 0);
if ( FAILED(hr) )
{
break;
}
// 打开文件
hr = AutoWrap(DISPATCH_METHOD, &ADoc, ADoc.pdispVal, L"Add", 0);
bReturn = (FAILED(hr) ? FALSE : TRUE);
::VariantClear (&ADoc);
} while(0);
return bReturn;
}
catch (CException* e)
{
return FALSE;
}
}
|
|
|
|
|
|
大家都知道,西药见效快,可它治标不治本,中药见效慢,但它治根。究其原因,西药重在以药效强制杀死病菌,以解一时之痛;中药讲疗程,重在调养,见效慢,但可以从根本上铲除病魔。两者各有各的优点,也各有各的缺点,有人会问,为什么不两者一起用呢?这便有了现在中西药结合的时代。
当然,我不是从医的,上面描述的正确性有待查证。真正的意图,是想借此说出我对管理上自己的一点想法。
初级的管理靠的是制度,深一级的是深入人心的文化。它们两者和西药中药类似。
一个企业刚起步,靠的是文化,是创业人的激情,大家同舟共济。可随着规模的增大,新人的涌入,元老的隐退,起初的文化已经石沉大海,管理变得混乱。
因而,很多的企业制定了属于自己的企业制度,通过制度,阻止了随着规模的扩大而造成的管理混乱。但同时,往往忽略了文化的传播,早就没有了同舟共济的深厚友情,出现部门、员工急功近利,异口同声你我他。
当然,文化,虽其效用是深远的,但当企业规模越来越大,只有文化就不行了,没有明确合理的制度,企业的运营就会无章可循,职责混乱。光有激情,但缺乏执行力。
由此失败的企业比比皆是。
成功的企业一定是有个完善的制度体系,更重要的是有着上下一心的企业文化。是两者的结合。
阿里巴巴能成功,完善的制度体系是少不了的。可最令我佩服的是它们妖精化的团队。他们的魔力不仅影响者高层,更到最底层,甚至到员工家属。
一位因挫折极度消沉的女士来到阿里巴巴,三个月后姿态已焕然一新。尽管她3000左右的薪水在大部分白领看来毫无兴奋点,但她口气铿锵———“请不要再和我提自杀那些愚蠢的话题,我正在给中国的电子商务做贡献。”
马云习惯不定时邀请雇员的亲属到公司“视察”,大部分人在走出大门后,会对“枕边人”感慨———“加油干吧,以后就靠你了。”
曾有一位以抱怨“丈夫工作过于拼命”著称的妻子,最后在阿里巴巴员工大会时跌跌撞撞冲上了主席台:“我想感谢你们,我很荣幸将丈夫交给了阿里。”
马云会打扮成维吾尔族姑娘或江南小城的普通渔夫;而阿里巴巴的首席财务官蔡崇信,这个被业界认为不好说话、极其严肃的人,偶然也会穿上女人的丝袜、在众目睽睽下跳起缠绵的钢管舞。
尚且不论这些故事的真实性,但我相信大多数都是真的。这都说明一件事,那就是阿里巴巴有着深入人心的企业文化。
安利的成功,更是如此。它的发展是非常注重企业文化的传播的,它的直销模式类似传销,有人就拿洗脑来形容,洗脑可能过激,但说明,安利成功,除了有完善的奖金制度,更重要的是企业上下一心。
由此卓越的企业层出不穷。
总之,医药倡导中西药结合,企业也应该追求制度与文化的融合,只有这样,才能够走的更远。
|
|
|
|
|
题目描述:请编写程序,根据指定的对应关系,把一个文本中的字符串替换成另外的字符串。
输入数据:程序读入已被命名为 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;
}
|
|
|
|
|
题目描述:请编写程序,找出下面 “ 输入数据及格式 ” 中所描述的输入数据文件中最大重叠区间的大小。
对一个正整数 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>
|
|
|
|
|
题目描述:一个正整数有可能可以被表示为 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>
|
|
|
|
|
//功能:实现在Word中查找指定内容,将其替换为指定图片。
//参数:mapPicInfo 图片文件名称和全路径的map
//参数:strFileName 要操作的原文件
//参数:strOutputFileName 要输出的文件
BOOL COfficeSign::WordSign( map<CString, CString> &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<CString, CString>::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() < 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->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;
}
|
|
|
|
|
//功能:实现在Excel中查找指定内容,将其替换为指定图片。
//参数:mapPicInfo 图片文件名称和全路径的map
//参数:strFileName 要操作的原文件
//参数:strOutputFileName 要输出的文件
BOOL COfficeSign::ExcelSign( map<CString, CString> &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<CString, CString>::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 <= 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) <= 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->second;
oShapes.AddPicture((LPCTSTR)(strPicFile), 0, 1,
fPicLeft, fPicTop, fExcelPicWidth, fExcelPicHeight);
oRange.Clear();
}
}
COleVariant v;
V_VT(&v) = VT_DISPATCH;
V_DISPATCH(&v) = (IDispatch *)oRange.m_lpDispatch;
oRange.AttachDispatch(oUseRange.FindNext(v));
V_VT(&v) = VT_ERROR;
if ( oRange.m_lpDispatch == NULL )
{
break;
}
long lFinded_Column = oRange.GetColumn();
long lFinded_Row = oRange.GetRow();
if ( (lFinded_Column == lFirstFinded_Column
&& 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;
}
|
|
|
|
|
/****************************************************************************
题目要求 :编写函数,检查给定字符串是否整数,如果是,返回其整数值(注:不允许使用某种特定的库函数)。
用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 >= '0') && (*p <= '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 = &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->next = NULL;
pnode->str = substr;
plist->next = pnode;
plist = pnode;
loop = 0;
pos = ++p;
}
else
{
++p;
}
}
return l.next;
}
void print_list(node *l)
{
while ( l != NULL )
{
printf("%s|", l->str);
l = l->next;
}
}
void free_memory(node *l)
{
node *p = l;
if ( l == NULL )
{
return;
}
do
{
p = l->next;
free(l->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", &num);
printf("%d\n", num);
cout << endl << endl;
cout << strtest << 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
|
|
|
|
|
/****************************************************************************
题目要求 :一个整数数列,元素取值可能是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 < size; ++i )
{
if ( array[i] != 0 )
{
maxIndex = minIndex = i;
break;
}
}
/*试图确定随意取的数中的最大值和最小值*/
for ( ; i < size; ++i )
{
if ( array[i] > array[maxIndex] )
{
maxIndex = i;
}
else if ( array[i] < array[minIndex] )
{
minIndex = i;
}
}
/*如果最大值和最小值的差小于总个数,则可以判定它们是连续相邻的*/
return (array[maxIndex] - array[minIndex]) < 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) && 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->lchild);
}
if ( finded == 3 )
{
break;
}
else if ( parentnode != NULL )
{
while ( pop(s, p) && p == parentnode )
{
break;
}
push(s, p->rchild);
}
}
return finded == 3 ? parentnode : NULL;
}
/****************************************************************************
题目要求 :一棵排序二叉树,令 f=(最大值+最小值)/2,设计一个算法,找出距离f值最近、大于f值的结点。
复杂度如果是O(n2)则不得分。
用C描述的算法,注释略
****************************************************************************/
treenode* find_parentnode(tree, f)
{
tempnode = tree;
while ( tempnode )
{
if ( tempnode->data > f )
{
if ( NULL == tree->lchild
|| tree->lchild->data <= f )
{
break;
}
tempnode = tree->lchild;
}
else
{
if ( NULL == (tempnode = tempnode->right)
|| tempnode->data > 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 < size; ++i )
{
temp_index = array[i] < 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
|
|
|
|
|