diff options
author | Oliver Schneider <oliver@assarbad.net> | 2012-10-14 18:09:57 +0400 |
---|---|---|
committer | Oliver Schneider <oliver@assarbad.net> | 2012-10-14 18:09:57 +0400 |
commit | 8e6bf65086ceb2e950d0f66c15a29ab1a3d43705 (patch) | |
tree | 70ef058cf7c24fde6142e81a73af625e83fafa69 /windirstat/Dialogs | |
parent | 3f2c80c4b2f8fdf2fe79f319d18a10b54403fdf9 (diff) |
- Renaming various files to make more obvious where they belong logically
- Updated premake4.lua to create proper filters in VS projects
Diffstat (limited to 'windirstat/Dialogs')
-rw-r--r-- | windirstat/Dialogs/AboutDlg.h | 82 | ||||
-rw-r--r-- | windirstat/Dialogs/DeleteWarningDlg.cpp | 71 | ||||
-rw-r--r-- | windirstat/Dialogs/DeleteWarningDlg.h | 49 | ||||
-rw-r--r-- | windirstat/Dialogs/SelectDrivesDlg.cpp | 936 | ||||
-rw-r--r-- | windirstat/Dialogs/SelectDrivesDlg.h | 195 | ||||
-rw-r--r-- | windirstat/Dialogs/aboutdlg.cpp | 329 |
6 files changed, 1662 insertions, 0 deletions
diff --git a/windirstat/Dialogs/AboutDlg.h b/windirstat/Dialogs/AboutDlg.h new file mode 100644 index 0000000..2e0f76e --- /dev/null +++ b/windirstat/Dialogs/AboutDlg.h @@ -0,0 +1,82 @@ +// aboutdlg.h - Declaration of StartAboutDialog(), CAboutThread and CAboutDlg +// +// WinDirStat - Directory Statistics +// Copyright (C) 2003-2005 Bernhard Seifert +// Copyright (C) 2004-2006, 2008 Oliver Schneider (assarbad.net) +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Author(s): - bseifert -> http://windirstat.info/contact/bernhard/ +// - assarbad -> http://windirstat.info/contact/oliver/ +// + +#ifndef __WDS_ABOUTDLG_H__ +#define __WDS_ABOUTDLG_H__ +#pragma once + +#include "layout.h" +#include <common/wds_constants.h> + + +void StartAboutDialog(); + + +class CAboutThread: public CWinThread +{ + DECLARE_DYNCREATE(CAboutThread); +protected: + virtual BOOL InitInstance(); +}; + + +class CAboutDlg : public CDialog +{ + enum { IDD = IDD_ABOUTBOX }; + + class CMyTabControl: public CTabCtrl + { + public: + void Initialize(); + void SetPageText(int tab); + + protected: + CRichEditCtrl m_text; + + DECLARE_MESSAGE_MAP() + afx_msg void OnEnLinkText(NMHDR *pNMHDR, LRESULT *pResult); + afx_msg void OnEnMsgFilter(NMHDR *pNMHDR, LRESULT *pResult); + afx_msg void OnSize(UINT nType, int cx, int cy); + }; + +public: + CAboutDlg(); + static CString GetAppVersion(); + +protected: + virtual BOOL OnInitDialog(); + virtual void DoDataExchange(CDataExchange* pDX); + + CStatic m_caption; + CMyTabControl m_tab; + CLayout m_layout; + + DECLARE_MESSAGE_MAP() + afx_msg void OnTcnSelchangeTab(NMHDR *pNMHDR, LRESULT *pResult); + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg void OnGetMinMaxInfo(MINMAXINFO* lpMMI); + afx_msg void OnDestroy(); +}; + +#endif // __WDS_ABOUTDLG_H__ diff --git a/windirstat/Dialogs/DeleteWarningDlg.cpp b/windirstat/Dialogs/DeleteWarningDlg.cpp new file mode 100644 index 0000000..d19880c --- /dev/null +++ b/windirstat/Dialogs/DeleteWarningDlg.cpp @@ -0,0 +1,71 @@ +// DeleteWarningDlg.cpp - implementation of CDeleteWarningDlg +// +// WinDirStat - Directory Statistics +// Copyright (C) 2003-2005 Bernhard Seifert +// Copyright (C) 2004-2006, 2008 Oliver Schneider (assarbad.net) +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Author(s): - bseifert -> http://windirstat.info/contact/bernhard/ +// - assarbad -> http://windirstat.info/contact/oliver/ +// + +#include "stdafx.h" +#include "windirstat.h" +#include "DeleteWarningDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + + +IMPLEMENT_DYNAMIC(CDeleteWarningDlg, CDialog) + +CDeleteWarningDlg::CDeleteWarningDlg(CWnd* pParent /*=NULL*/) + : CDialog(CDeleteWarningDlg::IDD, pParent) + , m_fileName(wds::strEmpty) + , m_dontShowAgain(false) +{ +} + +CDeleteWarningDlg::~CDeleteWarningDlg() +{ +} + +void CDeleteWarningDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + DDX_Check(pDX, IDC_DONTSHOWAGAIN, m_dontShowAgain); + DDX_Text(pDX, IDC_FILENAME, m_fileName); +} + + +BEGIN_MESSAGE_MAP(CDeleteWarningDlg, CDialog) + ON_BN_CLICKED(IDNO, OnBnClickedNo) + ON_BN_CLICKED(IDYES, OnBnClickedYes) +END_MESSAGE_MAP() + + +void CDeleteWarningDlg::OnBnClickedNo() +{ + UpdateData(); + EndDialog(IDNO); +} + +void CDeleteWarningDlg::OnBnClickedYes() +{ + UpdateData(); + EndDialog(IDYES); +} diff --git a/windirstat/Dialogs/DeleteWarningDlg.h b/windirstat/Dialogs/DeleteWarningDlg.h new file mode 100644 index 0000000..0885c6b --- /dev/null +++ b/windirstat/Dialogs/DeleteWarningDlg.h @@ -0,0 +1,49 @@ +// deletewarningdlg.h - Declaration of CDeleteWarningDlg +// +// WinDirStat - Directory Statistics +// Copyright (C) 2003-2005 Bernhard Seifert +// Copyright (C) 2004-2006, 2008 Oliver Schneider (assarbad.net) +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Author(s): - bseifert -> http://windirstat.info/contact/bernhard/ +// - assarbad -> http://windirstat.info/contact/oliver/ +// + +#pragma once + +// +// CDeleteWarningDlg. As WinDirStat can delete all files and folders, +// e.g. C:\Windows, we show an additional warning, when the user +// selects "Delete" (before the shell shows its warning). +// +class CDeleteWarningDlg : public CDialog +{ + DECLARE_DYNAMIC(CDeleteWarningDlg) + enum { IDD = IDD_DELETE_WARNING }; + +public: + CDeleteWarningDlg(CWnd* pParent = NULL); + virtual ~CDeleteWarningDlg(); + + CString m_fileName; // [in] file name for feedback + BOOL m_dontShowAgain; // [out] + +protected: + virtual void DoDataExchange(CDataExchange* pDX); + DECLARE_MESSAGE_MAP() + afx_msg void OnBnClickedNo(); + afx_msg void OnBnClickedYes(); +}; diff --git a/windirstat/Dialogs/SelectDrivesDlg.cpp b/windirstat/Dialogs/SelectDrivesDlg.cpp new file mode 100644 index 0000000..138482d --- /dev/null +++ b/windirstat/Dialogs/SelectDrivesDlg.cpp @@ -0,0 +1,936 @@ +// SelectDrivesDlg.cpp - Implementation of CDriveItem, CDrivesList and CSelectDrivesDlg +// +// WinDirStat - Directory Statistics +// Copyright (C) 2003-2005 Bernhard Seifert +// Copyright (C) 2004-2006, 2008 Oliver Schneider (assarbad.net) +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Author(s): - bseifert -> http://windirstat.info/contact/bernhard/ +// - assarbad -> http://windirstat.info/contact/oliver/ +// + +#include "stdafx.h" +#include "windirstat.h" +#include "SelectDrivesDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + +namespace +{ + enum + { + COL_NAME, + COL_TOTAL, + COL_FREE, + COL_GRAPH, + COL_PERCENTUSED, + COLUMN_COUNT + }; + + const UINT WMU_OK = WM_USER + 100; + + static UINT WMU_THREADFINISHED = ::RegisterWindowMessage(_T("{F03D3293-86E0-4c87-B559-5FD103F5AF58}")); + + // Return: false, if drive not accessible + bool RetrieveDriveInformation(LPCTSTR path, CString& name, ULONGLONG& total, ULONGLONG& free) + { + CString volumeName; + + if(!GetVolumeName(path, volumeName)) + { + return false; + } + + name = FormatVolumeName(path, volumeName); + + if(!CDirstatApp::getDiskFreeSpace(path, total, free)) + { + return false; + } + + // This condition *can* become true if quotas exist! + //ASSERT(free <= total); + + return true; + } +} + + + +///////////////////////////////////////////////////////////////////////////// + +CDriveItem::CDriveItem(CDrivesList *list, LPCTSTR pszPath) + : m_list(list) + , m_path(pszPath) + , m_success(false) + , m_name(m_path) + , m_totalBytes(0) + , m_freeBytes(0) + , m_used(0) + , m_isRemote(DRIVE_REMOTE == ::GetDriveType(m_path)) + , m_querying(true) +{ + + /* + For local drives we could do this synchronously: + if(!m_isRemote) + { + m_querying = false; + + CString name = m_name; + ULONGLONG total = 0; + ULONGLONG free = 0; + + bool success = RetrieveDriveInformation(m_path, name, total, free); + SetDriveInformation(success, name, total, free); + } + */ +} + +void CDriveItem::StartQuery(HWND dialog, UINT serial) +{ + ASSERT(dialog != NULL); + + ASSERT(m_querying); // The synchronous query in the constructor is commented out. + + if(m_querying) + { + new CDriveInformationThread(m_path, (LPARAM)this, dialog, serial); + // (will delete itself when finished.) + } +} + +void CDriveItem::SetDriveInformation(bool success, LPCTSTR name, ULONGLONG total, ULONGLONG free) +{ + m_querying = false; + m_success = success; + + if(m_success) + { + m_name = name; + m_totalBytes = total; + m_freeBytes = free; + + m_used = 0; + if(m_totalBytes > 0) + { + if(m_totalBytes < m_freeBytes) // can happen with quotas enabled + { + m_used = 0.0; // always return 0% in this case + } + else + { + m_used = (double)(m_totalBytes - m_freeBytes) / m_totalBytes; + } + } + } +} + +bool CDriveItem::IsRemote() const +{ + return m_isRemote; +} + +bool CDriveItem::IsSUBSTed() const +{ + return IsSUBSTedDrive(m_path); +} + +int CDriveItem::Compare(const CSortingListItem *baseOther, int subitem) const +{ + const CDriveItem *other = (CDriveItem *)baseOther; + + int r = 0; + + switch (subitem) + { + case COL_NAME: + { + r = signum(GetPath().CompareNoCase(other->GetPath())); + } + break; + case COL_TOTAL: + { + r = signum(m_totalBytes - other->m_totalBytes); + } + break; + case COL_FREE: + { + r = signum(m_freeBytes - other->m_freeBytes); + } + break; + case COL_GRAPH: + case COL_PERCENTUSED: + { + r = signum(m_used - other->m_used); + } + break; + default: + { + ASSERT(0); + } + } + + return r; +} + + +int CDriveItem::GetImage() const +{ + return GetMyImageList()->getFileImage(m_path); +} + +bool CDriveItem::DrawSubitem(int subitem, CDC *pdc, CRect rc, UINT state, int *width, int *focusLeft) const +{ + if(subitem == COL_NAME) + { + DrawLabel(m_list, GetMyImageList(), pdc, rc, state, width, focusLeft); + return true; + } + else if(subitem == COL_GRAPH) + { + if(!m_success) + { + return false; + } + + + if(width != NULL) + { + *width = 100; + return true; + } + + DrawSelection(m_list, pdc, rc, state); + + rc.DeflateRect(3, 5); + + DrawPercentage(pdc, rc, m_used, RGB(0,0,170)); + + return true; + } + else + { + return false; + } +} + +CString CDriveItem::GetText(int subitem) const +{ + CString s; + + switch (subitem) + { + case COL_NAME: + { + s = m_name; + } + break; + + case COL_TOTAL: + if(m_success) + { + s = FormatBytes(m_totalBytes); + } + break; + + case COL_FREE: + if(m_success) + { + s = FormatBytes(m_freeBytes); + } + break; + + case COL_GRAPH: + if(m_querying) + { + s.LoadString(IDS_QUERYING); + } + else if(!m_success) + { + s.LoadString(IDS_NOTACCESSIBLE); + } + break; + + case COL_PERCENTUSED: + if(m_success) + { + s = FormatDouble(m_used * 100) + _T("%"); + } + break; + + default: + ASSERT(0); + } + + return s; +} + +CString CDriveItem::GetPath() const +{ + return m_path; +} + +CString CDriveItem::GetDrive() const +{ + return m_path.Left(2); +} + + +///////////////////////////////////////////////////////////////////////////// + +CSet<CDriveInformationThread *, CDriveInformationThread *> CDriveInformationThread::_runningThreads; +CCriticalSection CDriveInformationThread::_csRunningThreads; + +void CDriveInformationThread::AddRunningThread() +{ + CSingleLock lock(&_csRunningThreads, true); + _runningThreads.SetKey(this); +} + +void CDriveInformationThread::RemoveRunningThread() +{ + CSingleLock lock(&_csRunningThreads, true); + _runningThreads.RemoveKey(this); +} + + +// This static method is called by the dialog when the dialog gets closed. +// We set the m_dialog members of all running threads to null, so that +// they don't send messages around to a no-more-existing window. +// +void CDriveInformationThread::InvalidateDialogHandle() +{ + CSingleLock lock(&_csRunningThreads, true); + + POSITION pos = _runningThreads.GetStartPosition(); + while(pos != NULL) + { + CDriveInformationThread *thread; + _runningThreads.GetNextAssoc(pos, thread); + + CSingleLock lockObj(&thread->m_cs, true); + thread->m_dialog = NULL; + } +} + +void CDriveInformationThread::OnAppExit() +{ + // We need not do anything here. +} + +// The constructor starts the thread. +// +CDriveInformationThread::CDriveInformationThread(LPCTSTR path, LPARAM driveItem, HWND dialog, UINT serial) + : m_path(path) + , m_driveItem(driveItem) + , m_serial(serial) + , m_dialog(dialog) + , m_totalBytes(0) + , m_freeBytes(0) + , m_success(false) +{ + ASSERT(m_bAutoDelete); + + AddRunningThread(); + + VERIFY(CreateThread()); +} + +BOOL CDriveInformationThread::InitInstance() +{ + m_success = RetrieveDriveInformation(m_path, m_name, m_totalBytes, m_freeBytes); + +#ifdef TESTTHREADS + srand(::GetTickCount()); + ::Sleep((rand() & 0x07) * 1000); +#endif + + HWND dialog = NULL; + + { + CSingleLock lock(&m_cs, true); + dialog = m_dialog; + // Of course, we must release m_cs here to avoid deadlocks. + } + + if(dialog != NULL) + { + // Theoretically the dialog may have been closed at this point. + // SendMessage() to a non-existing window simply fails immediately. + // If in the meantime the system recycled the window handle, + // (it may even belong to another process now?!), + // we are safe, because WMU_THREADFINISHED is a unique registered message. + // (Well if the other process crashes because of our message, there is nothing we can do about it.) + // If the window handle is recycled by a new Select drives dialog, + // its new serial will prevent it from reacting. + ::SendMessage(dialog, WMU_THREADFINISHED, m_serial, (LPARAM)this); + } + + RemoveRunningThread(); + + ASSERT(m_bAutoDelete); // Object will delete itself. + return false; // no Run(), please! +} + +// This method is only called by the gui thread, while we hang +// in SendMessage(dialog, WMU_THREADFINISHED, 0, this). +// So we need no synchronization. +// +LPARAM CDriveInformationThread::GetDriveInformation(bool& success, CString& name, ULONGLONG& total, ULONGLONG& free) +{ + name = m_name; + total = m_totalBytes; + free = m_freeBytes; + success = m_success; + + return m_driveItem; +} + + +///////////////////////////////////////////////////////////////////////////// + +IMPLEMENT_DYNAMIC(CDrivesList, COwnerDrawnListControl) + +CDrivesList::CDrivesList() + : COwnerDrawnListControl(_T("drives"), 20) +{ +} + +CDriveItem *CDrivesList::GetItem(int i) +{ + return (CDriveItem *)GetItemData(i); +} + +bool CDrivesList::HasImages() +{ + return true; +} + +void CDrivesList::SelectItem(CDriveItem *item) +{ + int i = FindListItem(item); + SetItemState(i, LVIS_SELECTED, LVIS_SELECTED); +} + +bool CDrivesList::IsItemSelected(int i) +{ + return (LVIS_SELECTED == GetItemState(i, LVIS_SELECTED)); +} + +void CDrivesList::OnLButtonDown(UINT /*nFlags*/, CPoint /*point*/) +{ + if(GetFocus() == this || GetSelectedCount() == 0) + { + // We simulate Ctrl-Key-Down here, so that the dialog + // can be driven with one hand (mouse) only. + const MSG *msg = GetCurrentMessage(); + DefWindowProc(msg->message, msg->wParam | MK_CONTROL, msg->lParam); + } + else + { + SetFocus(); + + // Send a LVN_ITEMCHANGED to the parent, so that it can + // update the radio button. + NMLISTVIEW lv; + ZeroMemory(&lv, sizeof(lv)); + lv.hdr.hwndFrom = m_hWnd; + lv.hdr.idFrom = GetDlgCtrlID(); + lv.hdr.code = LVN_ITEMCHANGED; + GetParent()->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&lv); + + // no further action + } +} + +void CDrivesList::OnNMDblclk(NMHDR * /*pNMHDR*/, LRESULT *pResult) +{ + *pResult = 0; + + CPoint point = GetCurrentMessage()->pt; + ScreenToClient(&point); + int i = HitTest(point); + if(i == -1) + { + return; + } + + for(int k = 0; k < GetItemCount(); k++) + { + SetItemState(k, k == i ? LVIS_SELECTED : 0, LVIS_SELECTED); + } + + GetParent()->SendMessage(WMU_OK); +} + +BEGIN_MESSAGE_MAP(CDrivesList, COwnerDrawnListControl) + ON_WM_LBUTTONDOWN() + ON_NOTIFY_REFLECT(LVN_DELETEITEM, OnLvnDeleteitem) + ON_WM_MEASUREITEM_REFLECT() + ON_NOTIFY_REFLECT(NM_DBLCLK, OnNMDblclk) +END_MESSAGE_MAP() + +void CDrivesList::OnLvnDeleteitem(NMHDR *pNMHDR, LRESULT *pResult) +{ + LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR); + delete GetItem(pNMLV->iItem); + *pResult = 0; +} + +void CDrivesList::MeasureItem(LPMEASUREITEMSTRUCT mis) +{ + mis->itemHeight = GetRowHeight(); +} + + +///////////////////////////////////////////////////////////////////////////// + +IMPLEMENT_DYNAMIC(CSelectDrivesDlg, CDialog) + +UINT CSelectDrivesDlg::_serial; + +CSelectDrivesDlg::CSelectDrivesDlg(CWnd* pParent /*=NULL*/) + : CDialog(CSelectDrivesDlg::IDD, pParent) + , m_layout(this, _T("sddlg")) +{ + _serial++; +} + +CSelectDrivesDlg::~CSelectDrivesDlg() +{ +} + +void CSelectDrivesDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + DDX_Control(pDX, IDC_DRIVES, m_list); + DDX_Radio(pDX, IDC_ALLDRIVES, m_radio); + DDX_Text(pDX, IDC_FOLDERNAME, m_folderName); + DDX_Control(pDX, IDOK, m_okButton); +} + + +BEGIN_MESSAGE_MAP(CSelectDrivesDlg, CDialog) + ON_BN_CLICKED(IDC_BROWSEFOLDER, OnBnClickedBrowsefolder) + ON_BN_CLICKED(IDC_AFOLDER, OnBnClickedAfolder) + ON_BN_CLICKED(IDC_SOMEDRIVES, OnBnClickedSomedrives) + ON_EN_CHANGE(IDC_FOLDERNAME, OnEnChangeFoldername) + ON_WM_MEASUREITEM() + ON_NOTIFY(LVN_ITEMCHANGED, IDC_DRIVES, OnLvnItemchangedDrives) + ON_BN_CLICKED(IDC_ALLLOCALDRIVES, OnBnClickedAlllocaldrives) + ON_WM_SIZE() + ON_WM_GETMINMAXINFO() + ON_WM_DESTROY() + ON_MESSAGE(WMU_OK, OnWmuOk) + ON_REGISTERED_MESSAGE(WMU_THREADFINISHED, OnWmuThreadFinished) + ON_WM_SYSCOLORCHANGE() +END_MESSAGE_MAP() + + +BOOL CSelectDrivesDlg::OnInitDialog() +{ + CWaitCursor wc; + + CDialog::OnInitDialog(); + + if(WMU_THREADFINISHED == 0) + { + TRACE("RegisterMessage() failed. Using WM_USER + 123\r\n"); + WMU_THREADFINISHED = WM_USER + 123; + } + + ModifyStyle(0, WS_CLIPCHILDREN); + + m_layout.AddControl(IDOK, 1, 0, 0, 0); + m_layout.AddControl(IDCANCEL, 1, 0, 0, 0); + m_layout.AddControl(IDC_DRIVES, 0, 0, 1, 1); + m_layout.AddControl(IDC_AFOLDER, 0, 1, 0, 0); + m_layout.AddControl(IDC_FOLDERNAME, 0, 1, 1, 0); + m_layout.AddControl(IDC_BROWSEFOLDER, 1, 1, 0, 0); + + m_layout.OnInitDialog(true); + + m_list.ShowGrid(GetOptions()->IsListGrid()); + m_list.ShowStripes(GetOptions()->IsListStripes()); + m_list.ShowFullRowSelection(GetOptions()->IsListFullRowSelection()); + + m_list.SetExtendedStyle(m_list.GetExtendedStyle() | LVS_EX_HEADERDRAGDROP); + // If we set an ImageList here, OnMeasureItem will have no effect ?! + + m_list.InsertColumn(COL_NAME, LoadString(IDS_DRIVECOL_NAME), LVCFMT_LEFT, 120, COL_NAME); + m_list.InsertColumn(COL_TOTAL, LoadString(IDS_DRIVECOL_TOTAL), LVCFMT_RIGHT, 55, COL_TOTAL); + m_list.InsertColumn(COL_FREE, LoadString(IDS_DRIVECOL_FREE), LVCFMT_RIGHT, 55, COL_FREE); + m_list.InsertColumn(COL_GRAPH, LoadString(IDS_DRIVECOL_GRAPH), LVCFMT_LEFT, 100, COL_GRAPH); + m_list.InsertColumn(COL_PERCENTUSED,LoadString(IDS_DRIVECOL_PERCENTUSED),LVCFMT_RIGHT, 55, COL_PERCENTUSED); + + m_list.OnColumnsInserted(); + + m_folderName = CPersistence::GetSelectDrivesFolder(); + CPersistence::GetSelectDrivesDrives(m_selectedDrives); + + ShowWindow(SW_SHOWNORMAL); + UpdateWindow(); + BringWindowToTop(); + SetForegroundWindow(); + + DWORD drives = ::GetLogicalDrives(); + int i; + DWORD mask = 0x00000001; + for(i = 0; i < wds::iNumDriveLetters; i++, mask <<= 1) + { + if((drives & mask) == 0) + { + continue; + } + + CString s; + s.Format(_T("%c:\\"), i + wds::chrCapA); + + UINT type = ::GetDriveType(s); + if(type == DRIVE_UNKNOWN || type == DRIVE_NO_ROOT_DIR) + { + continue; + } + + // The check of remote drives will be done in the background by the CDriveInformationThread. + if(type != DRIVE_REMOTE && !DriveExists(s)) + { + continue; + } + + CDriveItem *item = new CDriveItem(&m_list, s); + m_list.InsertListItem(m_list.GetItemCount(), item); + item->StartQuery(m_hWnd, _serial); + + for(int k = 0; k < m_selectedDrives.GetSize(); k++) + { + if(item->GetDrive() == m_selectedDrives[k]) + { + m_list.SelectItem(item); + break; + } + } + } + + m_list.SortItems(); + + m_radio = CPersistence::GetSelectDrivesRadio(); + UpdateData(false); + + switch (m_radio) + { + case RADIO_ALLLOCALDRIVES: + case RADIO_AFOLDER: + { + m_okButton.SetFocus(); + } + break; + case RADIO_SOMEDRIVES: + { + m_list.SetFocus(); + } + break; + } + + UpdateButtons(); + return false; // we have set the focus. +} + +void CSelectDrivesDlg::OnBnClickedBrowsefolder() +{ + // Buffer, because SHBrowseForFolder() wants a buffer + CString sDisplayName, sSelectedFolder = m_folderName; + BROWSEINFO bi; + ZeroMemory(&bi, sizeof(bi)); + + // Load a meaningful title for the browse dialog + CString title = LoadString(IDS_SELECTFOLDER); + bi.hwndOwner = m_hWnd; + // Use the CString as buffer (minimum is MAX_PATH as length) + bi.pszDisplayName = sDisplayName.GetBuffer(_MAX_PATH); + bi.lpszTitle = title; + // Set a callback function to pre-select a folder + bi.lpfn = BFFCALLBACK(BrowseCallbackProc); + bi.lParam = LPARAM(sSelectedFolder.GetBuffer()); + // Set the required flags + bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_EDITBOX | BIF_NEWDIALOGSTYLE | BIF_NONEWFOLDERBUTTON; + + CCoTaskMem<LPITEMIDLIST> pidl = ::SHBrowseForFolder(&bi); + // Release the actual buffer + sDisplayName.ReleaseBuffer(); + sSelectedFolder.ReleaseBuffer(); + + if(pidl != NULL) + { + CString sDir; + + CComPtr<IShellFolder> pshf; + HRESULT hr = ::SHGetDesktopFolder(&pshf); + ASSERT(SUCCEEDED(hr)); + + STRRET strret; + strret.uType = STRRET_CSTR; + hr = pshf->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &strret); + ASSERT(SUCCEEDED(hr)); + sDir = MyStrRetToString(pidl, &strret); + + m_folderName = sDir; + m_radio = RADIO_AFOLDER; + UpdateData(false); + UpdateButtons(); + } +} + +void CSelectDrivesDlg::OnOK() +{ + UpdateData(); + + m_drives.RemoveAll(); + m_selectedDrives.RemoveAll(); + if(m_radio == RADIO_AFOLDER) + { + m_folderName = getFullPathName_(m_folderName); + UpdateData(false); + } + + for(int i = 0; i < m_list.GetItemCount(); i++) + { + CDriveItem *item = m_list.GetItem(i); + + if(m_radio == RADIO_ALLLOCALDRIVES && !item->IsRemote() && !item->IsSUBSTed() + || m_radio == RADIO_SOMEDRIVES && m_list.IsItemSelected(i)) + { + m_drives.Add(item->GetDrive()); + } + if(m_list.IsItemSelected(i)) + { + m_selectedDrives.Add(item->GetDrive()); + } + } + + CPersistence::SetSelectDrivesRadio(m_radio); + CPersistence::SetSelectDrivesFolder(m_folderName); + CPersistence::SetSelectDrivesDrives(m_selectedDrives); + + CDialog::OnOK(); +} + +void CSelectDrivesDlg::UpdateButtons() +{ + UpdateData(); + bool enableOk = false; + switch (m_radio) + { + case RADIO_ALLLOCALDRIVES: + { + enableOk = true; + } + break; + case RADIO_SOMEDRIVES: + { + enableOk = (m_list.GetSelectedCount() > 0); + } + break; + case RADIO_AFOLDER: + if(!m_folderName.IsEmpty()) + { + if(m_folderName.GetLength() >= 2 && m_folderName.Left(2) == _T("\\\\")) + { + enableOk = true; + } + else + { + CString pattern = m_folderName; + if(pattern.Right(1) != _T("\\")) + { + pattern += _T("\\"); + } + pattern += _T("*.*"); + enableOk = FALSE != CFileFind().FindFile(pattern); + } + } + break; + default: + { + ASSERT(0); + } + } + m_okButton.EnableWindow(enableOk); +} + +void CSelectDrivesDlg::OnBnClickedAfolder() +{ + UpdateButtons(); +} + +void CSelectDrivesDlg::OnBnClickedSomedrives() +{ + m_list.SetFocus(); + UpdateButtons(); +} + +void CSelectDrivesDlg::OnEnChangeFoldername() +{ + UpdateButtons(); +} + +void CSelectDrivesDlg::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT mis) +{ + if(nIDCtl == IDC_DRIVES) + { + mis->itemHeight = 20; + } + else + { + CDialog::OnMeasureItem(nIDCtl, mis); + } +} + +void CSelectDrivesDlg::OnLvnItemchangedDrives(NMHDR * /*pNMHDR*/, LRESULT *pResult) +{ + // unused: LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR); + + m_radio = RADIO_SOMEDRIVES; + + UpdateData(false); + UpdateButtons(); + + *pResult = 0; +} + +void CSelectDrivesDlg::OnBnClickedAlllocaldrives() +{ + UpdateButtons(); +} + +void CSelectDrivesDlg::OnSize(UINT nType, int cx, int cy) +{ + CDialog::OnSize(nType, cx, cy); + m_layout.OnSize(); +} + +void CSelectDrivesDlg::OnGetMinMaxInfo(MINMAXINFO* mmi) +{ + m_layout.OnGetMinMaxInfo(mmi); + CDialog::OnGetMinMaxInfo(mmi); +} + +void CSelectDrivesDlg::OnDestroy() +{ + CDriveInformationThread::InvalidateDialogHandle(); + + m_layout.OnDestroy(); + CDialog::OnDestroy(); +} + +LRESULT CSelectDrivesDlg::OnWmuOk(WPARAM, LPARAM) +{ + OnOK(); + return 0; +} + +// This message is _sent_ by a CDriveInformationThread. +// +LRESULT CSelectDrivesDlg::OnWmuThreadFinished(WPARAM serial, LPARAM lparam) +{ + if(serial != _serial) + { + TRACE("OnWmuThreadFinished: invalid serial (window handle recycled?)\r\n"); + return 0; + } + + CDriveInformationThread *thread = (CDriveInformationThread *)lparam; + + bool success; + CString name; + ULONGLONG total; + ULONGLONG free; + + LPARAM driveItem = thread->GetDriveInformation(success, name, total, free); + + // For paranoia's sake we check, whether driveItem is in our list. + // (and we so find its index.) + LVFINDINFO fi; + ZeroMemory(&fi, sizeof(fi)); + fi.flags = LVFI_PARAM; + fi.lParam = driveItem; + + int i = m_list.FindItem(&fi); + if(i == -1) + { + TRACE("OnWmuThreadFinished: item not found!\r\n"); + return 0; + } + + CDriveItem *item = (CDriveItem *)driveItem; + + item->SetDriveInformation(success, name, total, free); + + m_list.RedrawItems(i, i); + + m_list.SortItems(); + + return 0; +} + +void CSelectDrivesDlg::OnSysColorChange() +{ + CDialog::OnSysColorChange(); + m_list.SysColorChanged(); +} + +// Callback function for the dialog shown by SHBrowseForFolder() +int CALLBACK CSelectDrivesDlg::BrowseCallbackProc(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData) +{ + UNREFERENCED_PARAMETER(lParam); + + switch( uMsg ) + { + case BFFM_INITIALIZED: + ::SendMessage(hWnd, BFFM_SETSELECTION, TRUE, lpData); + break; + } + return 0; +} + +CString CSelectDrivesDlg::getFullPathName_(LPCTSTR relativePath) +{ + LPTSTR dummy; + CString buffer; + + DWORD len = _MAX_PATH; + + DWORD dw = ::GetFullPathName(relativePath, len, buffer.GetBuffer(len), &dummy); + buffer.ReleaseBuffer(); + + while(dw >= len) + { + len += _MAX_PATH; + dw = ::GetFullPathName(relativePath, len, buffer.GetBuffer(len), &dummy); + buffer.ReleaseBuffer(); + } + + if(0 == dw) + { + TRACE("GetFullPathName(%s) failed: GetLastError returns %u\r\n", relativePath, ::GetLastError()); + return relativePath; + } + + return buffer; +} diff --git a/windirstat/Dialogs/SelectDrivesDlg.h b/windirstat/Dialogs/SelectDrivesDlg.h new file mode 100644 index 0000000..cff7926 --- /dev/null +++ b/windirstat/Dialogs/SelectDrivesDlg.h @@ -0,0 +1,195 @@ +// SelectDrivesDlg.h - Declaration of CDriveItem, CDrivesList and CSelectDrivesDlg +// +// WinDirStat - Directory Statistics +// Copyright (C) 2003-2005 Bernhard Seifert +// Copyright (C) 2004-2006, 2008 Oliver Schneider (assarbad.net) +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Author(s): - bseifert -> http://windirstat.info/contact/bernhard/ +// - assarbad -> http://windirstat.info/contact/oliver/ +// + +#ifndef __WDS_SELECTDRIVESDLG_H__ +#define __WDS_SELECTDRIVESDLG_H__ +#pragma once + +#include "ownerdrawnlistcontrol.h" +#include "layout.h" + +// +// The dialog has these three radio buttons. +// +enum RADIO +{ + RADIO_ALLLOCALDRIVES, + RADIO_SOMEDRIVES, + RADIO_AFOLDER +}; + + +class CDrivesList; + +// +// CDriveItem. An item in the CDrivesList Control. +// All methods are called by the gui thread. +// +class CDriveItem: public COwnerDrawnListItem +{ +public: + CDriveItem(CDrivesList *list, LPCTSTR pszPath); + void StartQuery(HWND dialog, UINT serial); + + void SetDriveInformation(bool success, LPCTSTR name, ULONGLONG total, ULONGLONG free); + + virtual int Compare(const CSortingListItem *other, int subitem) const; + + CString GetPath() const; + CString GetDrive() const; + bool IsRemote() const; + bool IsSUBSTed() const; + virtual bool DrawSubitem(int subitem, CDC *pdc, CRect rc, UINT state, int *width, int *focusLeft) const; + virtual CString GetText(int subitem) const; + int GetImage() const; + +private: + CDrivesList *m_list; // Backpointer + CString m_path; // e.g. "C:\" + bool m_isRemote; // Whether the drive type is DRIVE_REMOTE (network drive) + + bool m_querying; // Information thread is running. + bool m_success; // Drive is accessible. false while m_querying is true. + + CString m_name; // e.g. "BOOT (C:)" + ULONGLONG m_totalBytes; // Capacity + ULONGLONG m_freeBytes; // Free space + + double m_used; // used space / total space +}; + +// +// CDriveInformationThread. Does the GetVolumeInformation() call, which +// may hang for ca. 30 sec, it a network drive is not accessible. +// +class CDriveInformationThread: public CWinThread +{ + // Set of all running CDriveInformationThreads. + // Used by InvalidateDialogHandle(). + static CSet<CDriveInformationThread *, CDriveInformationThread *> _runningThreads; + static CCriticalSection _csRunningThreads; + + // The objects register and unregister themselves in _runningThreads + void AddRunningThread(); + void RemoveRunningThread(); + +public: + static void InvalidateDialogHandle(); + static void OnAppExit(); + + CDriveInformationThread(LPCTSTR path, LPARAM driveItem, HWND dialog, UINT serial); + virtual BOOL InitInstance(); + + LPARAM GetDriveInformation(bool& success, CString& name, ULONGLONG& total, ULONGLONG& free); + +private: + const CString m_path; // Path like "C:\" + const LPARAM m_driveItem; // The list item, we belong to + + CCriticalSection m_cs; // for m_dialog + HWND m_dialog; // synchronized by m_cs + const UINT m_serial; // serial number of m_dialog + + // "[out]"-parameters + CString m_name; // Result: name like "BOOT (C:)", valid if m_success + ULONGLONG m_totalBytes; // Result: capacity of the drive, valid if m_success + ULONGLONG m_freeBytes; // Result: free space on the drive, valid if m_success + bool m_success; // Result: false, iff drive is unaccessible. +}; + +// +// CDrivesList. +// +class CDrivesList: public COwnerDrawnListControl +{ + DECLARE_DYNAMIC(CDrivesList) +public: + CDrivesList(); + CDriveItem *GetItem(int i); + void SelectItem(CDriveItem *item); + bool IsItemSelected(int i); + + virtual bool HasImages(); + + DECLARE_MESSAGE_MAP() + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnLvnDeleteitem(NMHDR *pNMHDR, LRESULT *pResult); + afx_msg void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct); + afx_msg void OnNMDblclk(NMHDR *pNMHDR, LRESULT *pResult); +}; + + +// +// CSelectDrivesDlg. The initial dialog, where the user can select +// one or more drives or a folder for scanning. +// +class CSelectDrivesDlg : public CDialog +{ + DECLARE_DYNAMIC(CSelectDrivesDlg) + enum { IDD = IDD_SELECTDRIVES }; + static CString getFullPathName_(LPCTSTR relativePath); + +public: + CSelectDrivesDlg(CWnd* pParent = NULL); + virtual ~CSelectDrivesDlg(); + + // Dialog Data + int m_radio; // out. + CString m_folderName; // out. Valid if m_radio = RADIO_AFOLDER + CStringArray m_drives; // out. Valid if m_radio != RADIO_AFOLDER + +protected: + virtual void DoDataExchange(CDataExchange* pDX); + virtual BOOL OnInitDialog(); + virtual void OnOK(); + + void UpdateButtons(); + + static UINT _serial; // Each Instance of this dialog gets a serial number + CDrivesList m_list; + CButton m_okButton; + CStringArray m_selectedDrives; + CLayout m_layout; + // Callback function for the dialog shown by SHBrowseForFolder() + // MUST be static! + static int CALLBACK BrowseCallbackProc(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData); + + DECLARE_MESSAGE_MAP() + afx_msg void OnBnClickedBrowsefolder(); + afx_msg void OnLbnSelchangeDrives(); + afx_msg void OnBnClickedAlllocaldrives(); + afx_msg void OnBnClickedAfolder(); + afx_msg void OnBnClickedSomedrives(); + afx_msg void OnEnChangeFoldername(); + afx_msg void OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct); + afx_msg void OnLvnItemchangedDrives(NMHDR *pNMHDR, LRESULT *pResult); + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg void OnGetMinMaxInfo(MINMAXINFO* lpMMI); + afx_msg void OnDestroy(); + afx_msg LRESULT OnWmuOk(WPARAM, LPARAM); + afx_msg LRESULT OnWmuThreadFinished(WPARAM, LPARAM lparam); + afx_msg void OnSysColorChange(); +}; + +#endif // __WDS_SELECTDRIVESDLG_H__ diff --git a/windirstat/Dialogs/aboutdlg.cpp b/windirstat/Dialogs/aboutdlg.cpp new file mode 100644 index 0000000..debbd80 --- /dev/null +++ b/windirstat/Dialogs/aboutdlg.cpp @@ -0,0 +1,329 @@ +// aboutdlg.cpp - Implementation of the StartAboutDialog() function +// +// WinDirStat - Directory Statistics +// Copyright (C) 2003-2005 Bernhard Seifert +// Copyright (C) 2004-2006, 2008 Oliver Schneider (assarbad.net) +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Author(s): - bseifert -> http://windirstat.info/contact/bernhard/ +// - assarbad -> http://windirstat.info/contact/oliver/ +// + +#include "stdafx.h" +#include "windirstat.h" +#include <common/version.h> +#include "aboutdlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#endif + +namespace +{ + enum + { + RE_CONTROL = 4711 // Id of the RichEdit Control + }; + + // Tabs + enum + { + TAB_ABOUT, + TAB_AUTHORS, + TAB_THANKSTO, + TAB_LICENSE + }; + + // Retrieve the GPL text from our resources + CString GetTextResource(UINT id, HMODULE dll = AfxGetResourceHandle()) + { + CString s; + + HGLOBAL hresource = NULL; + try + { + HRSRC hrsrc = ::FindResource(dll, MAKEINTRESOURCE(id), _T("TEXT")); + if(NULL == hrsrc) + { + MdThrowLastWinerror(); + } + + DWORD dwSize = ::SizeofResource(dll, hrsrc); + if(0 == dwSize) + { + MdThrowLastWinerror(); + } + + hresource = ::LoadResource(dll, hrsrc); + const BYTE *pData = (const BYTE *)::LockResource(hresource); + + CComBSTR bstr(dwSize, (LPCSTR)pData); + + s = bstr; + } + catch (CException *pe) + { + pe->ReportError(); + pe->Delete(); + } + + if(hresource != NULL) + { + ::FreeResource(hresource); + } + + return s; + } +} + +///////////////////////////////////////////////////////////////////////////// + +void StartAboutDialog() +{ + AfxBeginThread(RUNTIME_CLASS(CAboutThread), NULL); +} + + +///////////////////////////////////////////////////////////////////////////// + +IMPLEMENT_DYNCREATE(CAboutThread, CWinThread); + +BOOL CAboutThread::InitInstance() +{ + CWinThread::InitInstance(); + + CAboutDlg dlg; + dlg.DoModal(); + return false; +} + +///////////////////////////////////////////////////////////////////////////// + +void CAboutDlg::CMyTabControl::Initialize() +{ + ModifyStyle(0, WS_CLIPCHILDREN); + + InsertItem(TAB_ABOUT, LPCTSTR(LoadString(IDS_ABOUT_ABOUT))); + InsertItem(TAB_AUTHORS, LPCTSTR(LoadString(IDS_ABOUT_AUTHORS))); + InsertItem(TAB_THANKSTO, LPCTSTR(LoadString(IDS_ABOUT_THANKSTO))); + InsertItem(TAB_LICENSE, LPCTSTR(LoadString(IDS_ABOUT_LICENSEAGREEMENT))); + + CRect rc; + GetClientRect(rc); + + CRect rcItem; + GetItemRect(0, rcItem); + + rc.top = rcItem.bottom; + + VERIFY(m_text.Create(WS_CHILD | WS_VISIBLE | WS_BORDER | ES_CENTER | ES_MULTILINE | ES_READONLY, rc, this, RE_CONTROL)); + SetPageText(TAB_ABOUT); +} + +void CAboutDlg::CMyTabControl::SetPageText(int tab) +{ + USES_CONVERSION; + + CString text, translators; + DWORD newStyle = ES_CENTER; + + switch (tab) + { + case TAB_ABOUT: + { + text.FormatMessage(IDS_ABOUT_ABOUTTEXTss, GetAuthorEmail(), GetWinDirStatHomepage()); + } + break; + case TAB_AUTHORS: + { + text.FormatMessage(IDS_ABOUT_AUTHORSTEXTs, GetAuthorEmail()); + translators.LoadString(IDS_TRANSLATORS); + text += translators; + // Anti-spam: avoid e-mail addresses in source-code: + text.Replace(wds::chrSharp, wds::chrAt); + } + break; + case TAB_THANKSTO: + { + text.LoadString(IDS_ABOUT_THANKSTOTEXT); + } + break; + case TAB_LICENSE: + { + text = GetTextResource(IDR_LICENSE, NULL); + newStyle = ES_LEFT; + } + break; + default: + { + ASSERT(0); + } + } + CRect rc; + m_text.GetWindowRect(rc); + ScreenToClient(rc); + + DWORD style = m_text.GetStyle(); + style &= ~ES_CENTER; + style |= newStyle | WS_VSCROLL; + + DWORD exstyle = m_text.GetExStyle(); + + m_text.DestroyWindow(); + + m_text.Create(style, rc, this, RE_CONTROL); + if(exstyle) + { + m_text.ModifyStyleEx(0, exstyle); + } + + m_text.SetAutoURLDetect(); + m_text.SetEventMask(ENM_LINK | ENM_KEYEVENTS); + m_text.SetFont(GetFont()); + + m_text.SetWindowText(text); + + m_text.HideCaret(); +} + +BEGIN_MESSAGE_MAP(CAboutDlg::CMyTabControl, CTabCtrl) + ON_NOTIFY(EN_LINK, RE_CONTROL, OnEnLinkText) + ON_NOTIFY(EN_MSGFILTER, RE_CONTROL, OnEnMsgFilter) + ON_WM_SIZE() +END_MESSAGE_MAP() + +void CAboutDlg::CMyTabControl::OnEnLinkText(NMHDR *pNMHDR, LRESULT *pResult) +{ + ENLINK *el = reinterpret_cast<ENLINK *>(pNMHDR); + *pResult = 0; + + if(WM_LBUTTONDOWN == el->msg) + { + CString link; + m_text.GetTextRange(el->chrg.cpMin, el->chrg.cpMax, link); + + // FIXME: should probably one of the helper variants of this function + ::ShellExecute(*this, NULL, link, NULL, wds::strEmpty, SW_SHOWNORMAL); + } +} + +void CAboutDlg::CMyTabControl::OnEnMsgFilter(NMHDR *pNMHDR, LRESULT *pResult) +{ + MSGFILTER *mf = reinterpret_cast<MSGFILTER *>(pNMHDR); + *pResult = 0; + + if(WM_KEYDOWN == mf->msg && (VK_ESCAPE == mf->wParam || VK_TAB == mf->wParam)) + { + // Move the focus back to the Tab control + SetFocus(); + + // If we didn't ignore VK_ESCAPE here, strange things happen: + // both m_text and the Tab control would disappear. + *pResult = 1; + } +} + +void CAboutDlg::CMyTabControl::OnSize(UINT nType, int cx, int cy) +{ + CTabCtrl::OnSize(nType, cx, cy); + + if(::IsWindow(m_text.m_hWnd)) + { + CRect rc; + GetClientRect(rc); + + CRect rcItem; + GetItemRect(0, rcItem); + + rc.top = rcItem.bottom; + + m_text.MoveWindow(rc); + } +} + + +//////////////////////////////////////////////////////////////////////////// + +CAboutDlg::CAboutDlg() + : CDialog(CAboutDlg::IDD) + , m_layout(this, _T("aboutdlg")) +{ +} + +CString CAboutDlg::GetAppVersion() +{ + USES_CONVERSION; + + CString s; + s.Format(_T("WinDirStat %s"), A2T(VN_STRING_EXE)); + return s; +} + +void CAboutDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + DDX_Control(pDX, IDC_CAPTION, m_caption); + DDX_Control(pDX, IDC_TAB, m_tab); +} + +BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) + ON_NOTIFY(TCN_SELCHANGE, IDC_TAB, OnTcnSelchangeTab) + ON_WM_SIZE() + ON_WM_GETMINMAXINFO() + ON_WM_DESTROY() +END_MESSAGE_MAP() + +BOOL CAboutDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + m_layout.AddControl(IDC_CAPTION, 0.5, 0, 0, 0); + m_layout.AddControl(IDC_TAB, 0, 0, 1, 1); + m_layout.AddControl(IDOK, 0.5, 1, 0, 0); + + m_layout.OnInitDialog(true); + + m_tab.Initialize(); + m_caption.SetWindowText(GetAppVersion()); + + return true; +} + +void CAboutDlg::OnTcnSelchangeTab(NMHDR * /* pNMHDR */, LRESULT *pResult) +{ + *pResult = 0; + m_tab.SetPageText(m_tab.GetCurSel()); +} + +void CAboutDlg::OnSize(UINT nType, int cx, int cy) +{ + CDialog::OnSize(nType, cx, cy); + m_layout.OnSize(); +} + + +void CAboutDlg::OnGetMinMaxInfo(MINMAXINFO* mmi) +{ + m_layout.OnGetMinMaxInfo(mmi); + CDialog::OnGetMinMaxInfo(mmi); + +} + +void CAboutDlg::OnDestroy() +{ + m_layout.OnDestroy(); + CDialog::OnDestroy(); +} |