diff options
author | Sean Werkema <sean@werkema.com> | 2020-06-23 09:43:05 -0400 |
---|---|---|
committer | Sean Werkema <sean@werkema.com> | 2020-06-23 09:43:05 -0400 |
commit | 4d0596a2530134383f231b2c7d22be6fa8c6a846 (patch) | |
tree | 538482a55afb3ee2bf4623a1ede59b7bbbcecd3f |
Initial import into version control.v1.4
-rw-r--r-- | AboutDialog.cpp | 34 | ||||
-rw-r--r-- | AboutDialog.h | 15 | ||||
-rw-r--r-- | DriveDialog.cpp | 136 | ||||
-rw-r--r-- | DriveDialog.h | 34 | ||||
-rw-r--r-- | E.H | 30 | ||||
-rw-r--r-- | FolderTree.cpp | 644 | ||||
-rw-r--r-- | FolderTree.h | 122 | ||||
-rw-r--r-- | FolderView.cpp | 1131 | ||||
-rw-r--r-- | FolderView.h | 101 | ||||
-rw-r--r-- | Freedoc.cpp | 122 | ||||
-rw-r--r-- | Freeview.cpp | 74 | ||||
-rw-r--r-- | Mainfrm.cpp | 281 | ||||
-rw-r--r-- | Mainfrm.h | 59 | ||||
-rw-r--r-- | README.TXT | 185 | ||||
-rw-r--r-- | SetupDlg.cpp | 310 | ||||
-rw-r--r-- | SetupDlg.h | 32 | ||||
-rw-r--r-- | SpaceMonger.cpp | 527 | ||||
-rw-r--r-- | SpaceMonger.dsp | 249 | ||||
-rw-r--r-- | SpaceMonger.dsw | 29 | ||||
-rw-r--r-- | SpaceMonger.h | 90 | ||||
-rw-r--r-- | SpaceMonger.ncb | bin | 0 -> 99328 bytes | |||
-rw-r--r-- | SpaceMonger.opt | bin | 0 -> 48640 bytes | |||
-rw-r--r-- | SpaceMonger.rc | 330 | ||||
-rw-r--r-- | StdAfx.cpp | 5 | ||||
-rw-r--r-- | Stdafx.h | 25 | ||||
-rw-r--r-- | TipWnd.cpp | 789 | ||||
-rw-r--r-- | TipWnd.h | 203 | ||||
-rw-r--r-- | lang.h | 51 | ||||
-rw-r--r-- | lang_en.cpp | 109 | ||||
-rw-r--r-- | lang_fr.cpp | 58 | ||||
-rw-r--r-- | res/SpaceMonger.ico | bin | 0 -> 1398 bytes | |||
-rw-r--r-- | res/scan1.bmp | bin | 0 -> 3190 bytes | |||
-rw-r--r-- | res/scan2.bmp | bin | 0 -> 3190 bytes | |||
-rw-r--r-- | res/scan3.bmp | bin | 0 -> 3190 bytes | |||
-rw-r--r-- | res/scan4.bmp | bin | 0 -> 3190 bytes | |||
-rw-r--r-- | res/toolbar_en.bmp | bin | 0 -> 3418 bytes | |||
-rw-r--r-- | res/toolbar_fr.bmp | bin | 0 -> 3418 bytes | |||
-rw-r--r-- | resource.h | 99 | ||||
-rw-r--r-- | xapp.h | 248 |
39 files changed, 6122 insertions, 0 deletions
diff --git a/AboutDialog.cpp b/AboutDialog.cpp new file mode 100644 index 0000000..d180f61 --- /dev/null +++ b/AboutDialog.cpp | |||
@@ -0,0 +1,34 @@ | |||
1 | |||
2 | #include "stdafx.h" | ||
3 | #include "spacemonger.h" | ||
4 | #include "AboutDialog.h" | ||
5 | #include "Lang.h" | ||
6 | |||
7 | #ifdef _DEBUG | ||
8 | #define new DEBUG_NEW | ||
9 | #undef THIS_FILE | ||
10 | static char THIS_FILE[] = __FILE__; | ||
11 | #endif | ||
12 | |||
13 | CAboutDialog::CAboutDialog(CWnd* pParent) | ||
14 | : CDialog(IDD_ABOUT, pParent) | ||
15 | { | ||
16 | } | ||
17 | |||
18 | BEGIN_MESSAGE_MAP(CAboutDialog, CDialog) | ||
19 | //{{AFX_MSG_MAP(CAboutDialog) | ||
20 | //}}AFX_MSG_MAP | ||
21 | END_MESSAGE_MAP() | ||
22 | |||
23 | BOOL CAboutDialog::OnInitDialog() | ||
24 | { | ||
25 | CDialog::OnInitDialog(); | ||
26 | |||
27 | SetWindowText(CurLang->about_spacemonger); | ||
28 | SetDlgItemText(IDC_STATIC_FREEWARE, CurLang->freeware); | ||
29 | SetDlgItemText(IDC_STATIC_WARRANTY, CurLang->warranty); | ||
30 | SetDlgItemText(IDC_STATIC_EMAIL, CurLang->email); | ||
31 | SetDlgItemText(IDOK, CurLang->ok); | ||
32 | |||
33 | return TRUE; | ||
34 | } | ||
diff --git a/AboutDialog.h b/AboutDialog.h new file mode 100644 index 0000000..f1f9e59 --- /dev/null +++ b/AboutDialog.h | |||
@@ -0,0 +1,15 @@ | |||
1 | #ifndef ABOUTDIALOG_H | ||
2 | #define ABOUTDIALOG_H | ||
3 | |||
4 | class CAboutDialog : public CDialog { | ||
5 | public: | ||
6 | CAboutDialog(CWnd* pParent = NULL); | ||
7 | |||
8 | protected: | ||
9 | //{{AFX_MSG(CAboutDialog) | ||
10 | virtual BOOL OnInitDialog(); | ||
11 | //}}AFX_MSG | ||
12 | DECLARE_MESSAGE_MAP() | ||
13 | }; | ||
14 | |||
15 | #endif | ||
diff --git a/DriveDialog.cpp b/DriveDialog.cpp new file mode 100644 index 0000000..8d1132d --- /dev/null +++ b/DriveDialog.cpp | |||
@@ -0,0 +1,136 @@ | |||
1 | #include "stdafx.h" | ||
2 | #include "spacemonger.h" | ||
3 | #include "DriveDialog.h" | ||
4 | #include "Lang.h" | ||
5 | |||
6 | CDriveDialog::CDriveDialog(CWnd* pParent) | ||
7 | : CDialog(IDD_OPEN_DIALOG, pParent) | ||
8 | { | ||
9 | } | ||
10 | |||
11 | BEGIN_MESSAGE_MAP(CDriveDialog, CDialog) | ||
12 | //{{AFX_MSG_MAP(CDriveDialog) | ||
13 | ON_NOTIFY(NM_DBLCLK, IDC_DRIVE_LIST, OnDriveDblClk) | ||
14 | //}}AFX_MSG_MAP | ||
15 | END_MESSAGE_MAP() | ||
16 | |||
17 | void CDriveDialog::OnDriveDblClk(NMHDR *pNotifyStruct, LRESULT *result) | ||
18 | { | ||
19 | CListCtrl *lc = (CListCtrl *)GetDlgItem(IDC_DRIVE_LIST); | ||
20 | if (lc == NULL) return; | ||
21 | if (lc->GetSelectedCount() != 1) return; | ||
22 | |||
23 | int i, max = lc->GetItemCount(); | ||
24 | for (i = 0; i < max; i++) { | ||
25 | if (lc->GetItemState(i, LVIS_SELECTED)) { | ||
26 | EndDialog(lc->GetItemData(i)); | ||
27 | } | ||
28 | } | ||
29 | } | ||
30 | |||
31 | void CDriveDialog::OnOK() | ||
32 | { | ||
33 | CListCtrl *lc = (CListCtrl *)GetDlgItem(IDC_DRIVE_LIST); | ||
34 | if (lc == NULL) EndDialog(-1); | ||
35 | if (lc->GetSelectedCount() != 1) return; | ||
36 | |||
37 | int i, max = lc->GetItemCount(); | ||
38 | for (i = 0; i < max; i++) { | ||
39 | if (lc->GetItemState(i, LVIS_SELECTED)) { | ||
40 | EndDialog(lc->GetItemData(i)); | ||
41 | } | ||
42 | } | ||
43 | } | ||
44 | |||
45 | void CDriveDialog::OnCancel() | ||
46 | { | ||
47 | EndDialog(-1); | ||
48 | } | ||
49 | |||
50 | BOOL CDriveDialog::OnInitDialog() | ||
51 | { | ||
52 | CWaitCursor wait; | ||
53 | |||
54 | CDialog::OnInitDialog(); | ||
55 | |||
56 | CDriveInfo driveinfo[26]; | ||
57 | HIMAGELIST imagelist; | ||
58 | int i, index; | ||
59 | LV_ITEM item; | ||
60 | |||
61 | imagelist = ImageList_Create(32, 32, TRUE, 0, 26); | ||
62 | |||
63 | CListCtrl *lc = (CListCtrl *)GetDlgItem(IDC_DRIVE_LIST); | ||
64 | ::SendMessage(lc->m_hWnd, LVM_SETIMAGELIST, (WPARAM)LVSIL_NORMAL, (LPARAM)(HIMAGELIST)imagelist); | ||
65 | |||
66 | SetWindowText(CurLang->selectdrive); | ||
67 | SetDlgItemText(IDOK, CurLang->ok); | ||
68 | SetDlgItemText(IDCANCEL, CurLang->cancel); | ||
69 | |||
70 | lc->InsertColumn(0, "Name"); | ||
71 | if (lc != NULL) { | ||
72 | lc->SetItemCount(26); | ||
73 | index = 0; | ||
74 | for (i = 'A'; i <= 'Z'; i++) { | ||
75 | driveinfo[i-'A'].LoadDriveInfo(i); | ||
76 | if (driveinfo[i-'A'].avail) { | ||
77 | ImageList_AddIcon(imagelist, driveinfo[i-'A'].icon); | ||
78 | item.mask = LVIF_STATE|LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM; | ||
79 | item.iItem = index; | ||
80 | item.iSubItem = 0; | ||
81 | item.state = 0; | ||
82 | item.stateMask = LVIS_SELECTED; | ||
83 | item.pszText = driveinfo[i-'A'].longname; | ||
84 | item.cchTextMax = strlen(driveinfo[i-'A'].longname); | ||
85 | item.iImage = index; | ||
86 | item.lParam = i - 'A'; | ||
87 | ::SendMessage(lc->m_hWnd, LVM_INSERTITEM, (WPARAM)0, (LPARAM)(&item)); | ||
88 | index++; | ||
89 | } | ||
90 | driveinfo[i-'A'].Free(); | ||
91 | } | ||
92 | } | ||
93 | |||
94 | return TRUE; | ||
95 | } | ||
96 | |||
97 | ////////////////////////////////////////////////////////////////////////////// | ||
98 | |||
99 | void CDriveInfo::Free(void) | ||
100 | { | ||
101 | if (longname != NULL) delete[] longname; | ||
102 | } | ||
103 | |||
104 | void CDriveInfo::LoadDriveInfo(char let) | ||
105 | { | ||
106 | char name[8]; | ||
107 | UINT type; | ||
108 | |||
109 | if (let >= 'a' && let <= 'z') let -= 32; | ||
110 | name[0] = let; | ||
111 | name[1] = ':'; | ||
112 | name[2] = '\\'; | ||
113 | name[3] = '\0'; | ||
114 | |||
115 | type = GetDriveType(name); | ||
116 | |||
117 | if (type != 0 && type != 1) { | ||
118 | SHFILEINFO fileinfo; | ||
119 | memset(&fileinfo, sizeof(SHFILEINFO), 0); | ||
120 | |||
121 | SHGetFileInfo(name, 0, &fileinfo, sizeof(SHFILEINFO), | ||
122 | SHGFI_DISPLAYNAME|SHGFI_ICON); | ||
123 | |||
124 | avail = 1; | ||
125 | letter = let; | ||
126 | icon = fileinfo.hIcon; | ||
127 | longname = new char[strlen(fileinfo.szDisplayName)+1]; | ||
128 | strcpy(longname, fileinfo.szDisplayName); | ||
129 | } | ||
130 | else { | ||
131 | avail = 0; | ||
132 | letter = let; | ||
133 | icon = NULL; | ||
134 | longname = NULL; | ||
135 | } | ||
136 | } | ||
diff --git a/DriveDialog.h b/DriveDialog.h new file mode 100644 index 0000000..088d3a3 --- /dev/null +++ b/DriveDialog.h | |||
@@ -0,0 +1,34 @@ | |||
1 | |||
2 | #ifndef DRIVEDIALOG_H | ||
3 | #define DRIVEDIALOG_H | ||
4 | |||
5 | struct CDriveInfo { | ||
6 | void Free(void); | ||
7 | void LoadDriveInfo(char letter); | ||
8 | |||
9 | char letter; | ||
10 | BOOL avail; | ||
11 | HICON icon; | ||
12 | char *longname; | ||
13 | }; | ||
14 | |||
15 | class CDriveDialog : public CDialog { | ||
16 | public: | ||
17 | CDriveDialog(CWnd* pParent = NULL); | ||
18 | |||
19 | //{{AFX_VIRTUAL(CDriveDialog) | ||
20 | virtual void OnOK(); | ||
21 | virtual void OnCancel(); | ||
22 | //}}AFX_VIRTUAL | ||
23 | |||
24 | protected: | ||
25 | //{{AFX_MSG(CDriveDialog) | ||
26 | afx_msg BOOL OnInitDialog(); | ||
27 | afx_msg void OnDriveDblClk(NMHDR *pNotifyStruct, LRESULT *result); | ||
28 | //}}AFX_MSG | ||
29 | DECLARE_MESSAGE_MAP() | ||
30 | |||
31 | CDriveInfo *driveinfo; | ||
32 | }; | ||
33 | |||
34 | #endif | ||
@@ -0,0 +1,30 @@ | |||
1 | |||
2 | #ifndef E_H | ||
3 | #define E_H | ||
4 | |||
5 | #define ui64 unsigned __int64 | ||
6 | #define si64 signed __int64 | ||
7 | #define ui32 unsigned long int | ||
8 | #define si32 signed long int | ||
9 | #define ui16 unsigned short int | ||
10 | #define si16 signed short int | ||
11 | #define ui8 unsigned char | ||
12 | #define si8 signed char | ||
13 | |||
14 | #define real32 float | ||
15 | #define real64 double | ||
16 | |||
17 | typedef short int sym; | ||
18 | |||
19 | #define until(n) while (!(n)) | ||
20 | #define unless(n) if (!(n)) | ||
21 | |||
22 | #define true 1 | ||
23 | #define TRUE 1 | ||
24 | #define True 1 | ||
25 | #define false 0 | ||
26 | #define FALSE 0 | ||
27 | #define False 0 | ||
28 | |||
29 | #endif | ||
30 | |||
diff --git a/FolderTree.cpp b/FolderTree.cpp new file mode 100644 index 0000000..93c6254 --- /dev/null +++ b/FolderTree.cpp | |||
@@ -0,0 +1,644 @@ | |||
1 | |||
2 | #include "stdafx.h" | ||
3 | #include "spacemonger.h" | ||
4 | #include "FolderTree.h" | ||
5 | #include "Lang.h" | ||
6 | |||
7 | #include <io.h> | ||
8 | #include <sys/types.h> | ||
9 | #include <sys/stat.h> | ||
10 | #include <errno.h> | ||
11 | #include <winioctl.h> | ||
12 | |||
13 | ////////////////////////////////////////////////////////////////////////////// | ||
14 | // Reparse points are utterly undocumented in Win2K, but can wreak havoc | ||
15 | // in SpaceMonger. We try hard to deal with them anyway. | ||
16 | |||
17 | #if (_WIN32_WINNT < 0x500) | ||
18 | |||
19 | // Maximum reparse buffer info size. The max user defined reparse | ||
20 | // data is 16KB, plus there's a header. | ||
21 | // | ||
22 | #define MAX_REPARSE_SIZE 17000 | ||
23 | |||
24 | // Undocumented FSCTL_SET_REPARSE_POINT structure definition | ||
25 | #define REPARSE_MOUNTPOINT_HEADER_SIZE 8 | ||
26 | typedef struct { | ||
27 | DWORD ReparseTag; | ||
28 | DWORD ReparseDataLength; | ||
29 | WORD Reserved; | ||
30 | WORD ReparseTargetLength; | ||
31 | WORD ReparseTargetMaximumLength; | ||
32 | WORD Reserved1; | ||
33 | WCHAR ReparseTarget[1]; | ||
34 | } REPARSE_MOUNTPOINT_DATA_BUFFER, *PREPARSE_MOUNTPOINT_DATA_BUFFER; | ||
35 | |||
36 | #define FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) // , REPARSE_DATA_BUFFER | ||
37 | |||
38 | #endif | ||
39 | |||
40 | ////////////////////////////////////////////////////////////////////////////// | ||
41 | |||
42 | CFolderTree::CFolderTree() | ||
43 | { | ||
44 | root = cur = NULL; | ||
45 | freespace = usedspace = totalspace = 0; | ||
46 | m_path = ""; | ||
47 | } | ||
48 | |||
49 | CFolderTree::~CFolderTree() | ||
50 | { | ||
51 | if (root != NULL) delete root; | ||
52 | } | ||
53 | |||
54 | static void PseudoSleep(ui32 time) | ||
55 | { | ||
56 | ui32 starttime = GetTickCount(); | ||
57 | MSG msg; | ||
58 | while (GetTickCount() - starttime < time) { | ||
59 | while (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { | ||
60 | ::TranslateMessage(&msg); | ||
61 | ::DispatchMessage(&msg); | ||
62 | } | ||
63 | } | ||
64 | } | ||
65 | |||
66 | BOOL CFolderTree::LoadTree(const CString &path, BOOL includespace, CWnd *modalwin) | ||
67 | { | ||
68 | CFolderDialog dialog; | ||
69 | |||
70 | if (path == "") return 1; | ||
71 | |||
72 | dialog.Create(IDD_SCAN_DIALOG, modalwin); | ||
73 | dialog.Reset(); | ||
74 | |||
75 | m_path = path; | ||
76 | GetSpace(path); | ||
77 | if (root != NULL) delete root; | ||
78 | root = new CFolder; | ||
79 | cur = root; | ||
80 | filespace = 0; | ||
81 | |||
82 | if (!root->LoadFolderInitial(this, path, clustersize, &dialog)) { | ||
83 | root->Finalize(); | ||
84 | if (root != NULL) delete root; | ||
85 | root = cur = NULL; | ||
86 | freespace = usedspace = totalspace = 0; | ||
87 | m_path = ""; | ||
88 | return 0; | ||
89 | } | ||
90 | else { | ||
91 | dialog.ForcedUpdate(this); | ||
92 | numfiles = dialog.numfiles; | ||
93 | numfolders = dialog.numfolders; | ||
94 | if (includespace) | ||
95 | root->AddFile(this, "<<<<<<<<<<<<<<<<<<<<", 1, freespace, freespace, 0); | ||
96 | root->Finalize(); | ||
97 | ::PseudoSleep(1000); | ||
98 | modalwin->SetWindowPos(&CWnd::wndTop, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); | ||
99 | return 1; | ||
100 | } | ||
101 | } | ||
102 | |||
103 | void CFolderTree::GetSpace(const CString &path) | ||
104 | { | ||
105 | DWORD SecPerClus, BytesPerSec, ClusPerDisk, FreeClus; | ||
106 | ui64 oddfree, total, totalfree; | ||
107 | |||
108 | typedef BOOL (WINAPI *GetFreeDiskSpaceExFunc)(LPCTSTR pathname, | ||
109 | ui64 *oddfree, ui64 *total, ui64 *totalfree); | ||
110 | |||
111 | // First, compute the cluster size (which will be needed later) | ||
112 | GetDiskFreeSpace(path, &SecPerClus, &BytesPerSec, &FreeClus, &ClusPerDisk); | ||
113 | clustersize = (ui64)BytesPerSec * (ui64)SecPerClus; | ||
114 | |||
115 | // Next, load in Kernel32 and use GetDiskFreeSpaceEx to find out | ||
116 | // the size of the disk. If GetDiskFreeSpaceEx doesn't exist, then | ||
117 | // fall back on the values from GetDiskFreeSpace. | ||
118 | HINSTANCE hLibrary = LoadLibrary("KERNEL32.DLL"); | ||
119 | GetFreeDiskSpaceExFunc getfreediskspaceex = | ||
120 | (GetFreeDiskSpaceExFunc)GetProcAddress(hLibrary, "GetDiskFreeSpaceExA"); | ||
121 | if (hLibrary != NULL && getfreediskspaceex != NULL) { | ||
122 | getfreediskspaceex(path, &oddfree, &total, &totalfree); | ||
123 | freespace = totalfree; | ||
124 | totalspace = total; | ||
125 | } | ||
126 | else { | ||
127 | freespace = clustersize * (ui64)FreeClus; | ||
128 | totalspace = clustersize * (ui64)ClusPerDisk; | ||
129 | } | ||
130 | FreeLibrary(hLibrary); | ||
131 | |||
132 | usedspace = totalspace - freespace; | ||
133 | } | ||
134 | |||
135 | CFolder *CFolderTree::GetRoot(void) | ||
136 | { | ||
137 | return(root); | ||
138 | } | ||
139 | |||
140 | CFolder *CFolderTree::SetCur(const CString &path) | ||
141 | { | ||
142 | return(cur); | ||
143 | } | ||
144 | |||
145 | CFolder *CFolderTree::GetCur(void) | ||
146 | { | ||
147 | return(cur); | ||
148 | } | ||
149 | |||
150 | CFolder *CFolderTree::Down(unsigned int index) | ||
151 | { | ||
152 | if (index < cur->cur) { | ||
153 | CFolder *newfolder = cur->children[index]; | ||
154 | if (newfolder != NULL) { | ||
155 | cur = newfolder; | ||
156 | return(cur); | ||
157 | } | ||
158 | } | ||
159 | return(NULL); | ||
160 | } | ||
161 | |||
162 | CFolder *CFolderTree::Up(void) | ||
163 | { | ||
164 | if (cur != root) { | ||
165 | cur = cur->parent; | ||
166 | return(cur); | ||
167 | } | ||
168 | return(NULL); | ||
169 | } | ||
170 | |||
171 | ////////////////////////////////////////////////////////////////////////////// | ||
172 | |||
173 | static char *cpp_strdup(const char *string, int stringlen) | ||
174 | { | ||
175 | char *newstr = (char *)malloc(stringlen+1 * sizeof(char)); | ||
176 | if (newstr == NULL) return(NULL); | ||
177 | |||
178 | char *src; | ||
179 | char c; | ||
180 | BOOL allupper = 1; | ||
181 | src = newstr; | ||
182 | while (stringlen--) { | ||
183 | c = *src++ = *string++; | ||
184 | if (c >= 'a' && c <= 'z') allupper = 0; | ||
185 | } | ||
186 | *src = '\0'; | ||
187 | if (allupper && src != newstr) { | ||
188 | src = newstr+1; | ||
189 | while ((c = *src) != '\0') { | ||
190 | if (c >= 'A' && c <= 'Z') *src += 32; | ||
191 | src++; | ||
192 | } | ||
193 | } | ||
194 | |||
195 | return(newstr); | ||
196 | } | ||
197 | |||
198 | CFolder::CFolder() | ||
199 | { | ||
200 | cur = 0; | ||
201 | max = 2; | ||
202 | names = (char **)malloc(sizeof(char *) * max); | ||
203 | sizes = (ui64 *)malloc(sizeof(ui64) * max); | ||
204 | actualsizes = (ui64 *)malloc(sizeof(ui64) * max); | ||
205 | children = (CFolder **)malloc(sizeof(CFolder *) * max); | ||
206 | times = (ui64 *)malloc(sizeof(ui64) * max); | ||
207 | size_self = size_children = 0; | ||
208 | parent = NULL; | ||
209 | parentindex = 0; | ||
210 | } | ||
211 | |||
212 | CFolder::~CFolder() | ||
213 | { | ||
214 | unsigned int i; | ||
215 | |||
216 | for (i = 0; i < cur; i++) { | ||
217 | if (names[i] != NULL) free(names[i]); | ||
218 | if (children[i] != NULL) delete children[i]; | ||
219 | } | ||
220 | |||
221 | free(names); | ||
222 | free(children); | ||
223 | free(sizes); | ||
224 | free(actualsizes); | ||
225 | free(times); | ||
226 | |||
227 | cur = max = 0; | ||
228 | size_self = size_children = 0; | ||
229 | parent = NULL; | ||
230 | parentindex = 0; | ||
231 | } | ||
232 | |||
233 | void CFolder::MoreEntries(void) | ||
234 | { | ||
235 | int newmax = max * 2; | ||
236 | char **newnames = (char **)malloc(sizeof(char *) * newmax); | ||
237 | ui64 *newsizes = (ui64 *)malloc(sizeof(ui64) * newmax); | ||
238 | ui64 *newactualsizes = (ui64 *)malloc(sizeof(ui64) * newmax); | ||
239 | ui64 *newtimes = (ui64 *)malloc(sizeof(ui64) * newmax); | ||
240 | CFolder **newkids = (CFolder **)malloc(sizeof(CFolder *) * newmax); | ||
241 | |||
242 | memcpy(newnames, names, max * sizeof(char *)); | ||
243 | memcpy(newsizes, sizes, max * sizeof(ui64)); | ||
244 | memcpy(newtimes, times, max * sizeof(ui64)); | ||
245 | memcpy(newactualsizes, actualsizes, max * sizeof(ui64)); | ||
246 | memcpy(newkids, children, max * sizeof(CFolder *)); | ||
247 | free(names); | ||
248 | free(sizes); | ||
249 | free(times); | ||
250 | free(actualsizes); | ||
251 | free(children); | ||
252 | names = newnames; | ||
253 | sizes = newsizes; | ||
254 | times = newtimes; | ||
255 | actualsizes = newactualsizes; | ||
256 | children = newkids; | ||
257 | |||
258 | max = newmax; | ||
259 | } | ||
260 | |||
261 | void CFolder::AddFile(CFolderTree *tree, const char *name, ui32 namelen, ui64 size, | ||
262 | ui64 actual_size, ui64 time) | ||
263 | { | ||
264 | if (cur >= max) MoreEntries(); | ||
265 | |||
266 | names[cur] = cpp_strdup(name, namelen); | ||
267 | actualsizes[cur] = actual_size; | ||
268 | times[cur] = time; | ||
269 | size_self += (sizes[cur] = size); | ||
270 | children[cur] = NULL; | ||
271 | cur++; | ||
272 | tree->filespace += size; | ||
273 | } | ||
274 | |||
275 | void CFolder::AddFolder(CFolderTree *tree, const char *name, ui32 namelen, CFolder *folder, | ||
276 | ui64 time) | ||
277 | { | ||
278 | if (cur >= max) MoreEntries(); | ||
279 | |||
280 | names[cur] = cpp_strdup(name, namelen); | ||
281 | size_children += (sizes[cur] = folder->SizeTotal()); | ||
282 | actualsizes[cur] = sizes[cur]; | ||
283 | times[cur] = time; | ||
284 | children[cur] = folder; | ||
285 | folder->parent = this; | ||
286 | folder->parentindex = cur; | ||
287 | cur++; | ||
288 | } | ||
289 | |||
290 | // EightBitCountingSort | ||
291 | // Performs an 8-bit counting sort on the given data. O(n). | ||
292 | |||
293 | void CFolder::EightBitCountingSort(ui64 *dsize, ui64 *ssize, ui32 count, ui32 bitpos, | ||
294 | char **dnames, char **snames, CFolder **dkids, CFolder **skids, | ||
295 | ui64 *dasize, ui64 *sasize, ui64 *dtimes, ui64 *stimes) | ||
296 | { | ||
297 | ui32 countarray[257]; | ||
298 | ui32 i, dest; | ||
299 | |||
300 | #define VALUE(size) (0xFF - (ui32)((size) >> bitpos) & 0xFF) | ||
301 | |||
302 | // Initially, zero offsets for each | ||
303 | for (i = 0; i < 256; i++) | ||
304 | countarray[i] = 0; | ||
305 | |||
306 | // Count how many of each value we have | ||
307 | for (i = 0; i < count; i++) | ||
308 | countarray[VALUE(ssize[i]) + 1]++; | ||
309 | |||
310 | // Create array offsets for each | ||
311 | for (i = 1; i < 256; i++) | ||
312 | countarray[i] += countarray[i-1]; | ||
313 | |||
314 | // Now move them into place | ||
315 | for (i = 0; i < count; i++) { | ||
316 | dest = countarray[VALUE(ssize[i])]++; | ||
317 | dsize[dest] = ssize[i]; | ||
318 | dnames[dest] = snames[i]; | ||
319 | dkids[dest] = skids[i]; | ||
320 | dasize[dest] = sasize[i]; | ||
321 | dtimes[dest] = stimes[i]; | ||
322 | if (dkids[dest] != NULL) dkids[dest]->parentindex = i; | ||
323 | } | ||
324 | } | ||
325 | |||
326 | // Finalize | ||
327 | // Sorts the directory by file size. O(n)! | ||
328 | |||
329 | void CFolder::Finalize(void) | ||
330 | { | ||
331 | if (cur <= 1) return; | ||
332 | |||
333 | char **newnames = (char **)malloc(sizeof(char *) * cur); | ||
334 | ui64 *newsizes = (ui64 *)malloc(sizeof(ui64) * cur); | ||
335 | ui64 *newactualsizes = (ui64 *)malloc(sizeof(ui64) * cur); | ||
336 | CFolder **newkids = (CFolder **)malloc(sizeof(CFolder *) * cur); | ||
337 | ui64 *newtimes = (ui64 *)malloc(sizeof(ui64) * cur); | ||
338 | |||
339 | // We do a radix sort with internal counting sort. This means | ||
340 | // that we pass over the source data exactly 16*cur times to sort it. | ||
341 | EightBitCountingSort(newsizes, sizes, cur, 0, newnames, names, newkids, children, newactualsizes, actualsizes, newtimes, times); | ||
342 | EightBitCountingSort(sizes, newsizes, cur, 8, names, newnames, children, newkids, actualsizes, newactualsizes, times, newtimes); | ||
343 | EightBitCountingSort(newsizes, sizes, cur, 16, newnames, names, newkids, children, newactualsizes, actualsizes, newtimes, times); | ||
344 | EightBitCountingSort(sizes, newsizes, cur, 24, names, newnames, children, newkids, actualsizes, newactualsizes, times, newtimes); | ||
345 | EightBitCountingSort(newsizes, sizes, cur, 32, newnames, names, newkids, children, newactualsizes, actualsizes, newtimes, times); | ||
346 | EightBitCountingSort(sizes, newsizes, cur, 40, names, newnames, children, newkids, actualsizes, newactualsizes, times, newtimes); | ||
347 | EightBitCountingSort(newsizes, sizes, cur, 48, newnames, names, newkids, children, newactualsizes, actualsizes, newtimes, times); | ||
348 | EightBitCountingSort(sizes, newsizes, cur, 56, names, newnames, children, newkids, actualsizes, newactualsizes, times, newtimes); | ||
349 | |||
350 | free(newtimes); | ||
351 | free(newnames); | ||
352 | free(newsizes); | ||
353 | free(newactualsizes); | ||
354 | free(newkids); | ||
355 | } | ||
356 | |||
357 | static ui32 strxcpy(char *dest, const char *src) | ||
358 | { | ||
359 | ui32 len = 0; | ||
360 | while ((*dest++ = *src++) != '\0') len++; | ||
361 | return len; | ||
362 | } | ||
363 | |||
364 | BOOL CFolder::LoadFolderInitial(CFolderTree *tree, const char *name, ui64 clustersize, CFolderDialog *dialog) | ||
365 | { | ||
366 | // First, fix up the pathname so that it's canonical and complete. | ||
367 | int len; | ||
368 | char path[MAX_PATH+270]; | ||
369 | _fullpath(path, name, MAX_PATH); | ||
370 | if (dialog != NULL) | ||
371 | dialog->SetPath(tree, path, this); | ||
372 | if ((len = strlen(path)) < 1 || path[len-1] != '\\') | ||
373 | path[len++] = '\\'; | ||
374 | |||
375 | // Next, compute a bit-field to use when computing the cluster size. This | ||
376 | // saves us the work of having to do a real modulus later on. | ||
377 | int clusterbits; | ||
378 | ui64 clustermod; | ||
379 | ui64 temp = clustersize; | ||
380 | BOOL aligned; | ||
381 | clusterbits = 0; | ||
382 | while (temp != 0) { | ||
383 | temp >>= 1; | ||
384 | clusterbits++; | ||
385 | } | ||
386 | clustermod = 1; | ||
387 | while (clusterbits--) clustermod <<= 1; | ||
388 | aligned = (clustermod == clustersize); | ||
389 | |||
390 | // Thus aligned will be set to TRUE if clustersize is a power of two, | ||
391 | // which, if it is, it saves a lot of computation work by letting us use | ||
392 | // bitwise-and instead of true modulus. We also subtract 1 from the | ||
393 | // cluster size here because it saves extra work in the recursive part. | ||
394 | |||
395 | return LoadFolder(tree, path, len, clustersize-1, aligned, dialog); | ||
396 | } | ||
397 | |||
398 | BOOL CFolder::LoadFolder(CFolderTree *tree, char *name, ui32 namelen, ui64 clustersize, BOOL aligned, CFolderDialog *dialog) | ||
399 | { | ||
400 | WIN32_FIND_DATA finddata; | ||
401 | BOOL gotfile; | ||
402 | HANDLE handle; | ||
403 | ui64 size; | ||
404 | static DWORD last_tick = 0; | ||
405 | ui32 newlen; | ||
406 | |||
407 | name[namelen] = '*'; | ||
408 | name[namelen+1] = '.'; | ||
409 | name[namelen+2] = '*'; | ||
410 | name[namelen+3] = '\0'; | ||
411 | |||
412 | // "name" now contains something like "C:\Windows\System\*.*" | ||
413 | |||
414 | handle = FindFirstFile(name, &finddata); | ||
415 | gotfile = (handle != INVALID_HANDLE_VALUE); | ||
416 | while (gotfile && !dialog->cancelled) { | ||
417 | newlen = namelen + strxcpy(name+namelen, finddata.cFileName); | ||
418 | |||
419 | // Handle (i.e., IGNORE) any junction points, mount points, or symbolic links. | ||
420 | // This is a lot messier than it would be with Unix soft-links, but a lot | ||
421 | // simpler than Unix mount points. | ||
422 | if (finddata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { | ||
423 | |||
424 | // Open a handle to the object. This should never be able to fail. | ||
425 | HANDLE fileHandle = CreateFile(name, 0, FILE_SHARE_READ, NULL, | ||
426 | OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT, 0); | ||
427 | |||
428 | // Retrieve the reparse information for the object. | ||
429 | BYTE reparseBuffer[MAX_REPARSE_SIZE]; | ||
430 | PREPARSE_GUID_DATA_BUFFER reparseInfo = (PREPARSE_GUID_DATA_BUFFER)reparseBuffer; | ||
431 | DWORD returnedLength; | ||
432 | DWORD result = DeviceIoControl(fileHandle, FSCTL_GET_REPARSE_POINT, | ||
433 | NULL, 0, reparseInfo, sizeof(reparseBuffer), | ||
434 | &returnedLength, NULL); | ||
435 | |||
436 | if (result) { | ||
437 | // If the reparse information indicated this was a mount point, junction | ||
438 | // point, or symbolic link, skip the file. Its size will be small enough | ||
439 | // that failing to factor it into the overall size computations will not | ||
440 | // yield invalid results. | ||
441 | ULONG msresult = IsReparseTagMicrosoft(reparseInfo->ReparseTag); | ||
442 | if (msresult) { | ||
443 | switch (reparseInfo->ReparseTag) { | ||
444 | case 0x80000000|IO_REPARSE_TAG_SYMBOLIC_LINK: | ||
445 | case IO_REPARSE_TAG_MOUNT_POINT: | ||
446 | CloseHandle(fileHandle); | ||
447 | goto nextfile; | ||
448 | } | ||
449 | } | ||
450 | } | ||
451 | CloseHandle(fileHandle); | ||
452 | } | ||
453 | |||
454 | // Process directories, except for the ".." directory. | ||
455 | if (finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { | ||
456 | if (!(finddata.cFileName[0] == '.' && (finddata.cFileName[1] == '\0' | ||
457 | || (finddata.cFileName[1] == '.' && finddata.cFileName[2] == '\0')))) { | ||
458 | if (dialog != NULL) | ||
459 | dialog->IncFolders(); | ||
460 | name[newlen++] = '\\'; | ||
461 | name[newlen] = '\0'; | ||
462 | CFolder *newfolder = new CFolder; | ||
463 | newfolder->LoadFolder(tree, name, newlen, clustersize, aligned, dialog); | ||
464 | AddFolder(tree, finddata.cFileName, newlen-namelen-1, newfolder, | ||
465 | *(ui64 *)&finddata.ftLastWriteTime); | ||
466 | } | ||
467 | } | ||
468 | else { | ||
469 | // Process files. | ||
470 | if (dialog != NULL) dialog->IncFiles(); | ||
471 | // We round up to the cluster size because that's the | ||
472 | // smallest the file can get | ||
473 | ui64 actualsize = (ui64)finddata.nFileSizeLow + ((ui64)finddata.nFileSizeHigh << 32); | ||
474 | if (aligned) size = (actualsize+clustersize) & clustersize; | ||
475 | else size = actualsize - (actualsize % (clustersize+1)); | ||
476 | AddFile(tree, finddata.cFileName, newlen-namelen, size, actualsize, | ||
477 | *(ui64 *)&finddata.ftLastWriteTime); | ||
478 | } | ||
479 | |||
480 | nextfile: | ||
481 | gotfile = FindNextFile(handle, &finddata); | ||
482 | |||
483 | // Only poll the system event queue every 1/5 of a second or so. | ||
484 | // That's enough to ensure quick response, but it won't bog | ||
485 | // down the scan. | ||
486 | DWORD tick = ::GetTickCount(); | ||
487 | if (tick > last_tick + 200) { | ||
488 | last_tick = tick; | ||
489 | MSG msg; | ||
490 | if (dialog != NULL) { | ||
491 | name[namelen] = '\0'; | ||
492 | dialog->SetPath(tree, name, this); | ||
493 | } | ||
494 | while (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { | ||
495 | ::TranslateMessage(&msg); | ||
496 | ::DispatchMessage(&msg); | ||
497 | } | ||
498 | } | ||
499 | } | ||
500 | FindClose(handle); | ||
501 | Finalize(); | ||
502 | |||
503 | return !dialog->cancelled; | ||
504 | } | ||
505 | |||
506 | void CFolder::DelFile(unsigned int index) | ||
507 | { | ||
508 | } | ||
509 | |||
510 | void CFolder::RenameFile(unsigned int index, const CString &name) | ||
511 | { | ||
512 | } | ||
513 | |||
514 | unsigned int CFolder::FindFile(const CString &name) | ||
515 | { | ||
516 | return((unsigned int)-1); | ||
517 | } | ||
518 | |||
519 | ////////////////////////////////////////////////////////////////////////////// | ||
520 | |||
521 | IMPLEMENT_DYNCREATE(CFolderDialog, CDialog) | ||
522 | |||
523 | BEGIN_MESSAGE_MAP(CFolderDialog, CDialog) | ||
524 | //{{AFX_MSG_MAP(CFolderDialog) | ||
525 | //}}AFX_MSG_MAP | ||
526 | END_MESSAGE_MAP() | ||
527 | |||
528 | CFolderDialog::CFolderDialog() | ||
529 | { | ||
530 | last_tick = last_redraw = 0; | ||
531 | path = ""; | ||
532 | numfiles = 0; | ||
533 | numfolders = 0; | ||
534 | chg_path = chg_numfiles = chg_numfolders = 0; | ||
535 | cur_frame = 0; | ||
536 | |||
537 | cancelled = 0; | ||
538 | } | ||
539 | |||
540 | CFolderDialog::~CFolderDialog() | ||
541 | { | ||
542 | } | ||
543 | |||
544 | void CFolderDialog::OnCancel(void) | ||
545 | { | ||
546 | cancelled = 1; | ||
547 | CDialog::OnCancel(); | ||
548 | } | ||
549 | |||
550 | void CFolderDialog::Reset(void) | ||
551 | { | ||
552 | if (!IsWindow(m_hWnd)) return; | ||
553 | |||
554 | last_tick = last_redraw = 0; | ||
555 | path = ""; | ||
556 | numfiles = 0; | ||
557 | numfolders = 0; | ||
558 | chg_path = chg_numfiles = chg_numfolders = 0; | ||
559 | cur_frame = 0; | ||
560 | |||
561 | cancelled = 0; | ||
562 | |||
563 | SetWindowText(CurLang->scanning); | ||
564 | SetDlgItemText(IDC_STATIC_FILESFOUND, CurLang->files_found); | ||
565 | SetDlgItemText(IDC_STATIC_FOLDERSFOUND, CurLang->folders_found); | ||
566 | SetDlgItemText(IDCANCEL, CurLang->cancel); | ||
567 | SetDlgItemText(IDC_PATH, path); | ||
568 | SetDlgItemInt(IDC_FILES, numfiles); | ||
569 | SetDlgItemInt(IDC_FOLDERS, numfolders); | ||
570 | CProgressCtrl *progress = (CProgressCtrl *)GetDlgItem(IDC_LOAD_PROGRESS); | ||
571 | if (progress != NULL) { | ||
572 | progress->SetRange(0, 4096); | ||
573 | progress->SetPos(0); | ||
574 | } | ||
575 | |||
576 | CClientDC dc(this); | ||
577 | CDC srcdc; | ||
578 | srcdc.CreateCompatibleDC(&dc); | ||
579 | ::SelectObject(srcdc.m_hDC, theApp.m_scan_animation[0]); | ||
580 | CRect rect; | ||
581 | GetClientRect(&rect); | ||
582 | dc.BitBlt(8, rect.bottom - rect.top - (48 + 8) - 12, 128, 48, &srcdc, 0, 0, SRCCOPY); | ||
583 | } | ||
584 | |||
585 | void CFolderDialog::UpdateDisplay(CFolderTree *tree, CFolder *folder) | ||
586 | { | ||
587 | // Guarantee that we don't update more often than 1/5 of a second | ||
588 | DWORD tick = ::GetTickCount(); | ||
589 | if (tick > last_tick + 200) { | ||
590 | last_tick = tick; | ||
591 | |||
592 | if (!IsWindow(m_hWnd)) return; | ||
593 | |||
594 | if (chg_path) SetDlgItemText(IDC_PATH, path); | ||
595 | if (chg_numfiles) SetDlgItemInt(IDC_FILES, numfiles); | ||
596 | if (chg_numfolders) SetDlgItemInt(IDC_FOLDERS, numfolders); | ||
597 | CProgressCtrl *progress = (CProgressCtrl *)GetDlgItem(IDC_LOAD_PROGRESS); | ||
598 | if (progress != NULL) { | ||
599 | ui64 filespace = tree->filespace/16384; | ||
600 | ui64 usedspace = tree->usedspace/16384; | ||
601 | if (usedspace <= 0) usedspace = 1; | ||
602 | progress->SetRange(0, 4096); | ||
603 | progress->SetPos((int)(filespace*4096/usedspace)); | ||
604 | } | ||
605 | chg_path = chg_numfiles = chg_numfolders = 0; | ||
606 | |||
607 | cur_frame = (cur_frame + 1) & 7; | ||
608 | if (!(cur_frame & 1)) { | ||
609 | CClientDC dc(this); | ||
610 | CDC srcdc; | ||
611 | srcdc.CreateCompatibleDC(&dc); | ||
612 | ::SelectObject(srcdc.m_hDC, theApp.m_scan_animation[cur_frame >> 1]); | ||
613 | CRect rect; | ||
614 | GetClientRect(&rect); | ||
615 | dc.BitBlt(8, rect.bottom - rect.top - (48 + 8) - 12, 128, 48, &srcdc, 0, 0, SRCCOPY); | ||
616 | } | ||
617 | } | ||
618 | #if 0 | ||
619 | // Redraws the display during the scan. Very ugly-looking. | ||
620 | if (tick > last_redraw + 1000) { | ||
621 | last_redraw = tick; | ||
622 | while (folder != NULL) { | ||
623 | folder->Finalize(); | ||
624 | folder = folder->parent; | ||
625 | } | ||
626 | tree->UpdateAllViews(); | ||
627 | } | ||
628 | #endif | ||
629 | } | ||
630 | |||
631 | void CFolderDialog::ForcedUpdate(CFolderTree *tree) | ||
632 | { | ||
633 | if (!IsWindow(m_hWnd)) return; | ||
634 | |||
635 | SetDlgItemText(IDC_PATH, path); | ||
636 | SetDlgItemInt(IDC_FILES, numfiles); | ||
637 | SetDlgItemInt(IDC_FOLDERS, numfolders); | ||
638 | CProgressCtrl *progress = (CProgressCtrl *)GetDlgItem(IDC_LOAD_PROGRESS); | ||
639 | if (progress != NULL) { | ||
640 | progress->SetRange(0, 4096); | ||
641 | progress->SetPos(4096); | ||
642 | } | ||
643 | } | ||
644 | |||
diff --git a/FolderTree.h b/FolderTree.h new file mode 100644 index 0000000..cd2df79 --- /dev/null +++ b/FolderTree.h | |||
@@ -0,0 +1,122 @@ | |||
1 | |||
2 | #ifndef FOLDERTREE_H | ||
3 | #define FOLDERTREE_H | ||
4 | |||
5 | class CFolderTree; | ||
6 | class CFolderDialog; | ||
7 | struct CFolder; | ||
8 | |||
9 | struct CFolder { | ||
10 | public: | ||
11 | CFolder(); | ||
12 | ~CFolder(); | ||
13 | |||
14 | void AddFile(CFolderTree *tree, const char *name, ui32 namelen, ui64 size, ui64 actual_size, ui64 time); | ||
15 | void AddFolder(CFolderTree *tree, const char *name, ui32 namelen, CFolder *folder, ui64 time); | ||
16 | void Finalize(void); | ||
17 | void DelFile(unsigned int index); | ||
18 | void RenameFile(unsigned int index, const CString &name); | ||
19 | unsigned int FindFile(const CString &name); | ||
20 | BOOL LoadFolderInitial(CFolderTree *tree, const char *name, ui64 clustersize, CFolderDialog *dialog); | ||
21 | inline ui64 SizeFiles() { return(size_self); } | ||
22 | inline ui64 SizeSub() { return(size_children); } | ||
23 | inline ui64 SizeTotal() { return(size_self + size_children); } | ||
24 | |||
25 | private: | ||
26 | void MoreEntries(void); | ||
27 | void EightBitCountingSort(ui64 *dsize, ui64 *ssize, ui32 count, ui32 bitpos, | ||
28 | char **dnames, char **snames, CFolder **dkids, CFolder **skids, | ||
29 | ui64 *dasize, ui64 *sasize, ui64 *dtimes, ui64 *stimes); | ||
30 | BOOL LoadFolder(CFolderTree *tree, char *name, ui32 namelen, ui64 clustersize, BOOL aligned, CFolderDialog *dialog); | ||
31 | |||
32 | public: | ||
33 | CFolder *parent; | ||
34 | unsigned int parentindex; | ||
35 | |||
36 | char **names; | ||
37 | CFolder **children; | ||
38 | ui64 *sizes; | ||
39 | ui64 *actualsizes; | ||
40 | ui64 *times; | ||
41 | ui64 size_self, size_children; | ||
42 | |||
43 | unsigned int cur, max; | ||
44 | }; | ||
45 | |||
46 | class CFolderTree : public CFreeDoc { | ||
47 | public: | ||
48 | CFolderTree(); | ||
49 | virtual ~CFolderTree(); | ||
50 | |||
51 | BOOL LoadTree(const CString &path, BOOL includespace, CWnd *modalwin); | ||
52 | void GetSpace(const CString &path); | ||
53 | CFolder *GetRoot(void); | ||
54 | |||
55 | CFolder *SetCur(const CString &path); | ||
56 | CFolder *GetCur(void); | ||
57 | CFolder *Down(unsigned int index); | ||
58 | CFolder *Up(void); | ||
59 | |||
60 | protected: | ||
61 | CFolder *root, *cur; | ||
62 | |||
63 | public: | ||
64 | CString m_path; | ||
65 | ui64 freespace, usedspace, totalspace, clustersize; | ||
66 | ui64 numfiles, numfolders; | ||
67 | ui64 filespace; | ||
68 | }; | ||
69 | |||
70 | class CFolderDialog : public CDialog { | ||
71 | public: | ||
72 | CFolderDialog(); | ||
73 | DECLARE_DYNCREATE(CFolderDialog) | ||
74 | virtual ~CFolderDialog(); | ||
75 | |||
76 | virtual void Reset(void); | ||
77 | virtual void UpdateDisplay(CFolderTree *tree, CFolder *folder); | ||
78 | virtual void ForcedUpdate(CFolderTree *tree); | ||
79 | |||
80 | void IncFiles(void); | ||
81 | void IncFolders(void); | ||
82 | void SetPath(CFolderTree *tree, const CString &string, CFolder *folder); | ||
83 | |||
84 | virtual void OnCancel(void); | ||
85 | |||
86 | protected: | ||
87 | //{{AFX_MSG(CFolderDialog) | ||
88 | //}}AFX_MSG | ||
89 | DECLARE_MESSAGE_MAP() | ||
90 | |||
91 | public: | ||
92 | ui32 numfiles, numfolders; | ||
93 | CString path; | ||
94 | |||
95 | BOOL cancelled; | ||
96 | |||
97 | protected: | ||
98 | BOOL chg_numfiles, chg_numfolders, chg_path; | ||
99 | DWORD last_tick, last_redraw; | ||
100 | ui32 cur_frame; | ||
101 | }; | ||
102 | |||
103 | inline void CFolderDialog::IncFiles(void) | ||
104 | { | ||
105 | numfiles++; | ||
106 | chg_numfiles = 1; | ||
107 | } | ||
108 | |||
109 | inline void CFolderDialog::IncFolders(void) | ||
110 | { | ||
111 | numfolders++; | ||
112 | chg_numfolders = 1; | ||
113 | } | ||
114 | |||
115 | inline void CFolderDialog::SetPath(CFolderTree *tree, const CString &string, CFolder *folder) | ||
116 | { | ||
117 | path = string; | ||
118 | chg_path = 1; | ||
119 | UpdateDisplay(tree, folder); | ||
120 | } | ||
121 | |||
122 | #endif | ||
diff --git a/FolderView.cpp b/FolderView.cpp new file mode 100644 index 0000000..b70c187 --- /dev/null +++ b/FolderView.cpp | |||
@@ -0,0 +1,1131 @@ | |||
1 | #include "stdafx.h" | ||
2 | #include "spacemonger.h" | ||
3 | #include "FolderView.h" | ||
4 | #include "MainFrm.h" | ||
5 | #include "TipWnd.h" | ||
6 | #include "Lang.h" | ||
7 | |||
8 | IMPLEMENT_DYNCREATE(CFolderView, CFreeView) | ||
9 | |||
10 | static COLORREF BoxColors[] = { | ||
11 | PALETTERGB(0xFF, 0x7F, 0x7F), | ||
12 | PALETTERGB(0xFF, 0xBF, 0x7F), | ||
13 | PALETTERGB(0xFF, 0xFF, 0x00), | ||
14 | PALETTERGB(0x7F, 0xFF, 0x7F), | ||
15 | PALETTERGB(0x7F, 0xFF, 0xFF), | ||
16 | PALETTERGB(0xBF, 0xBF, 0xFF), | ||
17 | PALETTERGB(0xBF, 0xBF, 0xBF), | ||
18 | PALETTERGB(0xFF, 0x7F, 0xFF), | ||
19 | |||
20 | PALETTERGB(0xFF, 0xBF, 0xBF), | ||
21 | PALETTERGB(0xFF, 0xDF, 0xBF), | ||
22 | PALETTERGB(0xFF, 0xFF, 0xBF), | ||
23 | PALETTERGB(0xBF, 0xFF, 0xBF), | ||
24 | PALETTERGB(0xDF, 0xFF, 0xFF), | ||
25 | PALETTERGB(0xDF, 0xDF, 0xFF), | ||
26 | PALETTERGB(0xDF, 0xDF, 0xDF), | ||
27 | PALETTERGB(0xFF, 0xBF, 0xFF), | ||
28 | |||
29 | PALETTERGB(0xBF, 0x7F, 0x7F), | ||
30 | PALETTERGB(0xBF, 0x9F, 0x5F), | ||
31 | PALETTERGB(0xBF, 0xBF, 0x3F), | ||
32 | PALETTERGB(0x7F, 0xBF, 0x7F), | ||
33 | PALETTERGB(0x7F, 0xBF, 0xBF), | ||
34 | PALETTERGB(0x9F, 0x9F, 0xFF), | ||
35 | PALETTERGB(0x9F, 0x9F, 0x9F), | ||
36 | PALETTERGB(0xBF, 0x7F, 0xBF), | ||
37 | |||
38 | PALETTERGB(0x00, 0x00, 0x00), | ||
39 | PALETTERGB(0xFF, 0xFF, 0xFF), | ||
40 | }; | ||
41 | |||
42 | // These colors are used for specifically-chosen folder colors. | ||
43 | static COLORREF FixedColors[] = { | ||
44 | PALETTERGB(0xFF, 0xFF, 0xFF), | ||
45 | PALETTERGB(0xBF, 0xBF, 0xBF), | ||
46 | PALETTERGB(0x7F, 0x7F, 0x7F), | ||
47 | |||
48 | PALETTERGB(0xFF, 0x7F, 0x7F), | ||
49 | PALETTERGB(0xFF, 0xBF, 0x7F), | ||
50 | PALETTERGB(0xFF, 0xFF, 0x00), | ||
51 | PALETTERGB(0x7F, 0xFF, 0x7F), | ||
52 | PALETTERGB(0x7F, 0xFF, 0xFF), | ||
53 | PALETTERGB(0xBF, 0xBF, 0xFF), | ||
54 | PALETTERGB(0xFF, 0x7F, 0xFF), | ||
55 | |||
56 | PALETTERGB(0xFF, 0xFF, 0xFF), | ||
57 | PALETTERGB(0xFF, 0xFF, 0xFF), | ||
58 | PALETTERGB(0xBF, 0xBF, 0xBF), | ||
59 | |||
60 | PALETTERGB(0xFF, 0x9F, 0x9F), | ||
61 | PALETTERGB(0xFF, 0xDF, 0xBF), | ||
62 | PALETTERGB(0xFF, 0xFF, 0xBF), | ||
63 | PALETTERGB(0xBF, 0xFF, 0xBF), | ||
64 | PALETTERGB(0xDF, 0xFF, 0xFF), | ||
65 | PALETTERGB(0xDF, 0xDF, 0xFF), | ||
66 | PALETTERGB(0xFF, 0xBF, 0xFF), | ||
67 | |||
68 | PALETTERGB(0xBF, 0xBF, 0xBF), | ||
69 | PALETTERGB(0x7F, 0x7F, 0x7F), | ||
70 | PALETTERGB(0x3F, 0x3F, 0x3F), | ||
71 | |||
72 | PALETTERGB(0xBF, 0x7F, 0x7F), | ||
73 | PALETTERGB(0xBF, 0x9F, 0x9F), | ||
74 | PALETTERGB(0xBF, 0xBF, 0x3F), | ||
75 | PALETTERGB(0x7F, 0xBF, 0x7F), | ||
76 | PALETTERGB(0x7F, 0xBF, 0xBF), | ||
77 | PALETTERGB(0x9F, 0x9F, 0xFF), | ||
78 | PALETTERGB(0xBF, 0x7F, 0xBF), | ||
79 | }; | ||
80 | |||
81 | CFolderView::CFolderView() | ||
82 | { | ||
83 | rootfolder = NULL; | ||
84 | selected = NULL; | ||
85 | displayfolders = displayend = NULL; | ||
86 | zoomlevel = 0; | ||
87 | showfreespace = 1; | ||
88 | lastcur = NULL; | ||
89 | } | ||
90 | |||
91 | CFolderView::~CFolderView() | ||
92 | { | ||
93 | ClearDisplayFolders(); | ||
94 | } | ||
95 | |||
96 | BEGIN_MESSAGE_MAP(CFolderView, CFreeView) | ||
97 | //{{AFX_MSG_MAP(CFolderView) | ||
98 | ON_WM_SIZE() | ||
99 | ON_WM_LBUTTONDOWN() | ||
100 | ON_WM_LBUTTONDBLCLK() | ||
101 | ON_WM_RBUTTONUP() | ||
102 | ON_WM_CREATE() | ||
103 | ON_WM_DESTROY() | ||
104 | ON_WM_MOUSEMOVE() | ||
105 | //}}AFX_MSG_MAP | ||
106 | ON_UPDATE_COMMAND_UI_RANGE(100, 41000, OnIgnoreUpdate) | ||
107 | END_MESSAGE_MAP() | ||
108 | |||
109 | BOOL CFolderView::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT *pResult) | ||
110 | { | ||
111 | if (::IsWindow(m_infotipwnd.m_hWnd)) { | ||
112 | MSG msg; | ||
113 | msg.message = message; | ||
114 | msg.wParam = wParam; | ||
115 | msg.lParam = lParam; | ||
116 | msg.hwnd = m_hWnd; | ||
117 | m_infotipwnd.ReflectMessage(&msg); | ||
118 | } | ||
119 | if (::IsWindow(m_nametipwnd.m_hWnd)) { | ||
120 | MSG msg; | ||
121 | msg.message = message; | ||
122 | msg.wParam = wParam; | ||
123 | msg.lParam = lParam; | ||
124 | msg.hwnd = m_hWnd; | ||
125 | m_nametipwnd.ReflectMessage(&msg); | ||
126 | } | ||
127 | return CFreeView::OnWndMsg(message, wParam, lParam, pResult); | ||
128 | } | ||
129 | |||
130 | int CFolderView::OnCreate(LPCREATESTRUCT lpCreateStruct) | ||
131 | { | ||
132 | if (CFreeView::OnCreate(lpCreateStruct) == -1) | ||
133 | return -1; | ||
134 | if (!m_infotipwnd.CreateEz(this, 64, 64)) return -1; | ||
135 | if (!m_nametipwnd.CreateEz(this, 64, 64)) return -1; | ||
136 | |||
137 | int i; | ||
138 | LOGPALETTE *logpalette = (LOGPALETTE *)malloc(sizeof(LOGPALETTE) + 26 * sizeof(PALETTEENTRY)); | ||
139 | logpalette->palVersion = 0x300; | ||
140 | logpalette->palNumEntries = 26; | ||
141 | for (i = 0; i < 26; i++) { | ||
142 | logpalette->palPalEntry[i].peFlags = 0; | ||
143 | logpalette->palPalEntry[i].peRed = GetRValue(BoxColors[i]); | ||
144 | logpalette->palPalEntry[i].peGreen = GetGValue(BoxColors[i]); | ||
145 | logpalette->palPalEntry[i].peBlue = GetBValue(BoxColors[i]); | ||
146 | } | ||
147 | m_palette.CreatePalette(logpalette); | ||
148 | delete logpalette; | ||
149 | |||
150 | black.CreateSolidBrush(RGB(0x00, 0x00, 0x00)); | ||
151 | white.CreateSolidBrush(RGB(0xFF, 0xFF, 0xFF)); | ||
152 | |||
153 | minifont.CreateFont(-9, 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET, | ||
154 | OUT_RASTER_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, | ||
155 | VARIABLE_PITCH|FF_SWISS, "Small Fonts"); | ||
156 | |||
157 | m_infotipwnd.SetAutoShow(1); | ||
158 | m_infotipwnd.SetAutoPos(1); | ||
159 | m_infotipwnd.SetShowDelay(theApp.m_settings.infotip_delay); | ||
160 | m_infotipwnd.EnableWindow(0); | ||
161 | |||
162 | HFONT nametipfont = ::CreateFont(-9, 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET, | ||
163 | OUT_RASTER_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, | ||
164 | VARIABLE_PITCH|FF_SWISS, "Small Fonts"); | ||
165 | ::SendMessage(m_nametipwnd.m_hWnd, WM_SETFONT, (WPARAM)nametipfont, 0); | ||
166 | m_nametipwnd.SetAutoShow(1); | ||
167 | m_nametipwnd.SetShowDelay(theApp.m_settings.nametip_delay); | ||
168 | m_nametipwnd.SetVPadding(0); | ||
169 | m_nametipwnd.SetHPadding(1); | ||
170 | m_nametipwnd.EnableWindow(0); | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | void CFolderView::OnDestroy() | ||
176 | { | ||
177 | m_palette.DeleteObject(); | ||
178 | black.DeleteObject(); | ||
179 | white.DeleteObject(); | ||
180 | minifont.DeleteObject(); | ||
181 | |||
182 | m_infotipwnd.DestroyWindow(); | ||
183 | m_nametipwnd.DestroyWindow(); | ||
184 | |||
185 | CFreeView::OnDestroy(); | ||
186 | } | ||
187 | |||
188 | CDisplayFolder *CFolderView::GetDisplayFolderFromPoint(const CPoint &point) | ||
189 | { | ||
190 | CDisplayFolder *cur = displayfolders; | ||
191 | |||
192 | while (cur != NULL) { | ||
193 | if (point.x > cur->x && point.y > cur->y | ||
194 | && point.x < cur->x + cur->w && point.y < cur->y + cur->h) { | ||
195 | if (cur->flags & 1) { | ||
196 | if (point.x < cur->x+3 || point.y < cur->y+12 | ||
197 | || point.x > cur->x+cur->w-3 || point.y > cur->y+cur->h-3) | ||
198 | break; | ||
199 | } | ||
200 | else break; | ||
201 | } | ||
202 | cur = cur->next; | ||
203 | } | ||
204 | |||
205 | if (cur != NULL && cur->name == NULL) | ||
206 | cur = NULL; | ||
207 | if (cur != NULL && cur->name[0] == '<') | ||
208 | cur = NULL; | ||
209 | |||
210 | return cur; | ||
211 | } | ||
212 | |||
213 | CDisplayFolder *CFolderView::GetContainerDisplayFolderFromPoint(const CPoint &point) | ||
214 | { | ||
215 | CDisplayFolder *cur = displayfolders, *best = NULL; | ||
216 | CRect minrect(-32768,-32768,32767,32767); | ||
217 | |||
218 | while (cur != NULL) { | ||
219 | if (cur->flags & 1 | ||
220 | && point.x > cur->x && point.y > cur->y | ||
221 | && point.x < cur->x + cur->w && point.y < cur->y + cur->h | ||
222 | && cur->x >= minrect.left && cur->y >= minrect.top | ||
223 | && cur->x+cur->w <= minrect.right && cur->y+cur->h <= minrect.bottom) { | ||
224 | // Found a tighter folder, so use it. | ||
225 | minrect.left = cur->x; | ||
226 | minrect.top = cur->y; | ||
227 | minrect.right = cur->x+cur->w; | ||
228 | minrect.bottom = cur->y+cur->h; | ||
229 | best = cur; | ||
230 | } | ||
231 | cur = cur->next; | ||
232 | } | ||
233 | |||
234 | return best; | ||
235 | } | ||
236 | |||
237 | void CFolderView::HighlightPathAtPoint(const CPoint &point) | ||
238 | { | ||
239 | CDisplayFolder *cur = displayfolders; | ||
240 | |||
241 | CDC *pDC = GetDC(); | ||
242 | pDC->SelectObject(&minifont); | ||
243 | pDC->SetBkMode(TRANSPARENT); | ||
244 | pDC->SetTextAlign(TA_LEFT | TA_TOP | TA_NOUPDATECP); | ||
245 | pDC->SelectPalette(&m_palette, 0); | ||
246 | while (cur != NULL) { | ||
247 | if (cur->name != NULL && cur->name[0] != '<') { | ||
248 | if (point.x > cur->x && point.y > cur->y | ||
249 | && point.x < cur->x + cur->w && point.y < cur->y + cur->h) { | ||
250 | if (!(cur->flags & 4)) { | ||
251 | cur->flags |= 4; | ||
252 | MinimalDrawDisplayFolder(pDC, cur, selected == cur); | ||
253 | } | ||
254 | } | ||
255 | else { | ||
256 | if (cur->flags & 4) { | ||
257 | cur->flags &= ~4; | ||
258 | MinimalDrawDisplayFolder(pDC, cur, selected == cur); | ||
259 | } | ||
260 | } | ||
261 | } | ||
262 | cur = cur->next; | ||
263 | } | ||
264 | ReleaseDC(pDC); | ||
265 | } | ||
266 | |||
267 | void CFolderView::OnLButtonDown(UINT flags, CPoint point) | ||
268 | { | ||
269 | SelectFolder(GetDisplayFolderFromPoint(point)); | ||
270 | lastcur = NULL; | ||
271 | OnMouseMove(flags, point); | ||
272 | } | ||
273 | |||
274 | void CFolderView::OnLButtonDblClk(UINT flags, CPoint point) | ||
275 | { | ||
276 | CDisplayFolder *cur = GetDisplayFolderFromPoint(point); | ||
277 | SelectFolder(cur); | ||
278 | |||
279 | if (cur != NULL) { | ||
280 | if (cur->flags & 1) ZoomIn(cur); | ||
281 | else { | ||
282 | CString title, path; | ||
283 | title += ((CFolderTree *)GetDocument())->m_path; | ||
284 | BuildTitleReverse(selected->source, title); | ||
285 | path = title; | ||
286 | title += selected->source->names[selected->index]; | ||
287 | ShellExecute(NULL, NULL, title, NULL, path, SW_SHOWDEFAULT); | ||
288 | } | ||
289 | } | ||
290 | lastcur = NULL; | ||
291 | OnMouseMove(flags, point); | ||
292 | } | ||
293 | |||
294 | void CFolderView::OnMouseMove(UINT nFlags, CPoint point) | ||
295 | { | ||
296 | CDisplayFolder *cur = GetDisplayFolderFromPoint(point); | ||
297 | |||
298 | if (theApp.m_settings.rollover_box) HighlightPathAtPoint(point); | ||
299 | else HighlightPathAtPoint(CPoint(-1,-1)); | ||
300 | |||
301 | if (theApp.m_settings.show_info_tips) { | ||
302 | if (cur == NULL) | ||
303 | m_infotipwnd.EnableWindow(0); | ||
304 | else if (lastcur != cur) | ||
305 | SetupInfoTip(cur); | ||
306 | } | ||
307 | else m_infotipwnd.EnableWindow(0); | ||
308 | |||
309 | if (theApp.m_settings.show_name_tips) { | ||
310 | if (cur == NULL) | ||
311 | m_nametipwnd.EnableWindow(0); | ||
312 | else if (lastcur != cur) | ||
313 | SetupNameTip(cur); | ||
314 | } | ||
315 | else m_nametipwnd.EnableWindow(0); | ||
316 | |||
317 | lastcur = cur; | ||
318 | } | ||
319 | |||
320 | static void PrintFileSize(CString &string, ui64 size) | ||
321 | { | ||
322 | char sizebuf[256]; | ||
323 | char *dest = sizebuf+255; | ||
324 | int ctr = 0; | ||
325 | sizebuf[255] = '\0'; | ||
326 | while (size != 0) { | ||
327 | if (++ctr == 4) *--dest = CurLang->digitcomma, ctr = 1; | ||
328 | *--dest = (char)(size % 10) + '0'; | ||
329 | size /= 10; | ||
330 | } | ||
331 | string += dest; | ||
332 | string += " "; | ||
333 | string += CurLang->bytes; | ||
334 | } | ||
335 | |||
336 | static void PrintDate(CString &string, ui64 date) | ||
337 | { | ||
338 | CString tempstring; | ||
339 | SYSTEMTIME mtime; | ||
340 | FileTimeToSystemTime((FILETIME *)&date, &mtime); | ||
341 | if (mtime.wMonth < 1 || mtime.wMonth > 12) mtime.wMonth = 1; | ||
342 | if (mtime.wDayOfWeek < 0 || mtime.wDayOfWeek > 6) mtime.wDayOfWeek = 0; | ||
343 | tempstring.Format("%02d %s %04d %d:%02d:%02d", | ||
344 | mtime.wDay, CurLang->monthnames[mtime.wMonth-1], mtime.wYear, | ||
345 | mtime.wHour, mtime.wMinute, mtime.wSecond); | ||
346 | string += tempstring; | ||
347 | } | ||
348 | |||
349 | void CFolderView::SetupInfoTip(CDisplayFolder *cur) | ||
350 | { | ||
351 | if (cur == NULL) { | ||
352 | m_infotipwnd.EnableWindow(0); | ||
353 | return; | ||
354 | } | ||
355 | |||
356 | CString path; | ||
357 | CString string, tempstring; | ||
358 | |||
359 | // Get the full pathname to the file. | ||
360 | CFolderTree *ft = (CFolderTree *)GetDocument(); | ||
361 | path += ft->m_path; | ||
362 | BuildTitleReverse(cur->source, tempstring); | ||
363 | path += tempstring; | ||
364 | |||
365 | // Load in the file's information using FindFirstFile. | ||
366 | WIN32_FIND_DATA info; | ||
367 | HANDLE handle = FindFirstFile(path+cur->source->names[cur->index], &info); | ||
368 | FindClose(handle); | ||
369 | |||
370 | if (theApp.m_settings.infotip_flags & TIP_PATH) | ||
371 | string += path; | ||
372 | if (theApp.m_settings.infotip_flags & TIP_NAME) | ||
373 | string += cur->source->names[cur->index]; | ||
374 | if (theApp.m_settings.infotip_flags & (TIP_NAME|TIP_PATH)) | ||
375 | string += '\n'; | ||
376 | if (theApp.m_settings.infotip_flags & TIP_SIZE) | ||
377 | PrintFileSize(string, cur->source->actualsizes[cur->index]); | ||
378 | if (theApp.m_settings.infotip_flags & TIP_ATTRIB) { | ||
379 | if ((theApp.m_settings.infotip_flags & TIP_SIZE) | ||
380 | && info.dwFileAttributes != 0) string += " / "; | ||
381 | if (info.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) string += " ", string += CurLang->attribnames[0]; | ||
382 | if (info.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) string += " ", string += CurLang->attribnames[1]; | ||
383 | if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) string += " ", string += CurLang->attribnames[2]; | ||
384 | if (info.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) string += " ", string += CurLang->attribnames[3]; | ||
385 | if (info.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) string += " ", string += CurLang->attribnames[4]; | ||
386 | if (info.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) string += " ", string += CurLang->attribnames[5]; | ||
387 | if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) string += " ", string += CurLang->attribnames[6]; | ||
388 | if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) string += " ", string += CurLang->attribnames[7]; | ||
389 | if (info.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) string += " ", string += CurLang->attribnames[8]; | ||
390 | if (info.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) string += " ", string += CurLang->attribnames[9]; | ||
391 | if (info.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) string += " ", string += CurLang->attribnames[10]; | ||
392 | } | ||
393 | if (theApp.m_settings.infotip_flags & (TIP_ATTRIB|TIP_SIZE)) | ||
394 | string += '\n'; | ||
395 | if (theApp.m_settings.infotip_flags & TIP_DATE) { | ||
396 | PrintDate(string, cur->source->times[cur->index]); | ||
397 | string += '\n'; | ||
398 | } | ||
399 | if (theApp.m_settings.infotip_flags & TIP_ICON) { | ||
400 | SHFILEINFO fileinfo; | ||
401 | memset(&fileinfo, sizeof(SHFILEINFO), 0); | ||
402 | SHGetFileInfo(path+cur->source->names[cur->index], 0, | ||
403 | &fileinfo, sizeof(SHFILEINFO), SHGFI_DISPLAYNAME|SHGFI_ICON); | ||
404 | m_infotipwnd.SetIcon(fileinfo.hIcon, 1); | ||
405 | m_infotipwnd.SetIconPos(TW_LEFT); | ||
406 | } | ||
407 | |||
408 | m_infotipwnd.SetWindowText(string); | ||
409 | m_infotipwnd.AutoSize(); | ||
410 | m_infotipwnd.EnableWindow(1); | ||
411 | m_infotipwnd.RedrawWindow(); | ||
412 | } | ||
413 | |||
414 | void CFolderView::SetupNameTip(CDisplayFolder *cur) | ||
415 | { | ||
416 | m_nametipwnd.EnableWindow(0); | ||
417 | |||
418 | if (cur == NULL) return; | ||
419 | |||
420 | CDC *pDC = GetDC(); | ||
421 | pDC->SelectObject(&minifont); | ||
422 | pDC->SetBkMode(TRANSPARENT); | ||
423 | pDC->SetTextAlign(TA_LEFT | TA_TOP | TA_NOUPDATECP); | ||
424 | pDC->SelectPalette(&m_palette, 0); | ||
425 | |||
426 | int tx, ty, failed = 0; | ||
427 | CSize size = pDC->GetTextExtent(cur->name, strlen(cur->name)); | ||
428 | int x = cur->x, y = cur->y, w = cur->w + 1, h = cur->h + 1; | ||
429 | if (size.cx > w - 2) tx = x + 2; | ||
430 | else if (cur->flags & 1) tx = x + 2, failed++; | ||
431 | else tx = x + (w - size.cx) / 2, failed++; | ||
432 | if (size.cy > h - 2) ty = y + 1; | ||
433 | else if (cur->flags & 1) ty = y + 1, failed++; | ||
434 | else ty = y + (h - size.cy) / 2, failed++; | ||
435 | if (failed == 2) return; | ||
436 | |||
437 | if (!(cur->flags & 1) && h >= 36 && w >= 48) | ||
438 | ty -= 12; | ||
439 | |||
440 | if (selected == cur) { | ||
441 | m_nametipwnd.SetBgColor(RGB(0,0,0)); | ||
442 | m_nametipwnd.SetTextColor(RGB(255,255,255)); | ||
443 | } | ||
444 | else if (cur->flags & 4) { | ||
445 | m_nametipwnd.SetBgColor(BoxColors[(cur->depth & 7) + 8]); | ||
446 | m_nametipwnd.SetTextColor(RGB(0,0,0)); | ||
447 | } | ||
448 | else { | ||
449 | m_nametipwnd.SetBgColor(BoxColors[cur->depth & 7]); | ||
450 | m_nametipwnd.SetTextColor(RGB(0,0,0)); | ||
451 | } | ||
452 | m_nametipwnd.SetWindowText(cur->name); | ||
453 | m_nametipwnd.AutoSize(); | ||
454 | m_nametipwnd.MoveWindow(this, tx-2, ty-1); | ||
455 | m_nametipwnd.PushOnScreen(); | ||
456 | |||
457 | ReleaseDC(pDC); | ||
458 | m_nametipwnd.EnableWindow(1); | ||
459 | m_nametipwnd.RedrawWindow(); | ||
460 | } | ||
461 | |||
462 | static void AddMenuEntry(HMENU menu, UINT cmd = 0, const char *string = NULL, | ||
463 | BOOL checked = 0, BOOL disabled = 0, BOOL bold = 0) | ||
464 | { | ||
465 | MENUITEMINFO mii; | ||
466 | mii.cbSize = sizeof(MENUITEMINFO); | ||
467 | mii.fMask = MIIM_CHECKMARKS|MIIM_ID|MIIM_STATE|MIIM_TYPE; | ||
468 | mii.fType = ((string != NULL) ? MFT_STRING : MFT_SEPARATOR); | ||
469 | mii.fState = 0; | ||
470 | if (bold) mii.fState |= MFS_DEFAULT; | ||
471 | if (checked) mii.fState |= MFS_CHECKED; | ||
472 | if (disabled) mii.fState |= MFS_GRAYED|MFS_DISABLED; | ||
473 | mii.wID = cmd; | ||
474 | mii.hSubMenu = NULL; | ||
475 | mii.hbmpChecked = NULL; | ||
476 | mii.hbmpUnchecked = NULL; | ||
477 | mii.dwTypeData = (char *)string; | ||
478 | if (string != NULL) mii.cch = strlen(string); | ||
479 | else mii.cch = 0; | ||
480 | |||
481 | ::InsertMenuItem(menu, GetMenuItemCount(menu), TRUE, &mii); | ||
482 | } | ||
483 | |||
484 | void CFolderView::OnRButtonUp(UINT flags, CPoint point) | ||
485 | { | ||
486 | CDisplayFolder *cur = GetDisplayFolderFromPoint(point); | ||
487 | SelectFolder(cur); | ||
488 | ClientToScreen(&point); | ||
489 | |||
490 | bool showinfo = m_infotipwnd.IsWindowEnabled(); | ||
491 | bool showname = m_nametipwnd.IsWindowEnabled(); | ||
492 | m_infotipwnd.EnableWindow(0); | ||
493 | m_nametipwnd.EnableWindow(0); | ||
494 | |||
495 | CSpaceMonger *app = (CSpaceMonger *)AfxGetApp(); | ||
496 | HMENU menu = ::CreatePopupMenu(); | ||
497 | ::AddMenuEntry(menu, ID_VIEW_ZOOM_IN, CurLang->zoomin, 0, cur == NULL, (cur != NULL) && (cur->flags & 1) != 0); | ||
498 | ::AddMenuEntry(menu, ID_VIEW_ZOOM_OUT, CurLang->zoomout, 0, cur == NULL, 0); | ||
499 | ::AddMenuEntry(menu, ID_VIEW_ZOOM_FULL, CurLang->zoomfull, 0, cur == NULL, 0); | ||
500 | ::AddMenuEntry(menu); | ||
501 | ::AddMenuEntry(menu, ID_FILE_RUN, CurLang->run, 0, cur == NULL, (cur != NULL) && (cur->flags & 1) == 0); | ||
502 | ::AddMenuEntry(menu, ID_FILE_DELETE, CurLang->del, 0, | ||
503 | !app->m_settings.disable_delete && cur == NULL, 0); | ||
504 | ::AddMenuEntry(menu); | ||
505 | ::AddMenuEntry(menu, ID_FILE_OPEN, CurLang->opendrive, 0, 0, 0); | ||
506 | ::AddMenuEntry(menu, ID_FILE_REFRESH, CurLang->rescandrive, 0, 0, 0); | ||
507 | ::AddMenuEntry(menu, ID_VIEW_FREE, CurLang->showfreespace, showfreespace, 0, 0); | ||
508 | ::AddMenuEntry(menu); | ||
509 | ::AddMenuEntry(menu, ID_FILE_PROPERTIES, CurLang->properties, 0, 0, 0); | ||
510 | ::TrackPopupMenuEx(menu, TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON, | ||
511 | point.x, point.y, theApp.m_mainframe->m_hWnd, NULL); | ||
512 | ::DestroyMenu(menu); | ||
513 | |||
514 | if (showname) m_nametipwnd.EnableWindow(1); | ||
515 | if (showinfo) m_infotipwnd.EnableWindow(1); | ||
516 | } | ||
517 | |||
518 | void CFolderView::SelectFolder(CDisplayFolder *cur) | ||
519 | { | ||
520 | if (cur == selected) return; | ||
521 | |||
522 | CDC *dc = GetDC(); | ||
523 | |||
524 | if (selected != NULL) { | ||
525 | DrawDisplayFolder(dc, selected, 0); | ||
526 | selected = NULL; | ||
527 | } | ||
528 | |||
529 | selected = cur; | ||
530 | if (selected != NULL) | ||
531 | DrawDisplayFolder(dc, selected, 1); | ||
532 | |||
533 | ReleaseDC(dc); | ||
534 | UpdateTitleBar(); | ||
535 | } | ||
536 | |||
537 | static CString GetSizeString(ui64 size, ui64 totalspace, BOOL percent) | ||
538 | { | ||
539 | CString result; | ||
540 | |||
541 | if (totalspace == 0) totalspace = (ui64)(-1); | ||
542 | |||
543 | if (percent) { | ||
544 | size = (size * (ui64)1000) / totalspace; | ||
545 | result.Format(CurLang->percent_format, (ui32)size / 10, (ui32)size % 10); | ||
546 | } | ||
547 | else { | ||
548 | ui32 displayfull, displayfractional; | ||
549 | const char *displaytype; | ||
550 | |||
551 | if (size < (ui64)(1024)) { | ||
552 | displayfull = (ui32)size; | ||
553 | displayfractional = 0; | ||
554 | displaytype = CurLang->bytes; | ||
555 | } | ||
556 | else if (size < (ui64)(1024*1024)) { | ||
557 | displayfull = (ui32)(size / (ui64)(1024)); | ||
558 | displayfractional = (ui32)(10 * (size % (ui64)(1024)) / (ui64)(1024)); | ||
559 | displaytype = CurLang->kb; | ||
560 | } | ||
561 | else if (size < (ui64)(1024*1024*1024)) { | ||
562 | displayfull = (ui32)(size / (ui64)(1024*1024)); | ||
563 | displayfractional = (ui32)(10 * (size % (ui64)(1024*1024)) / (ui64)(1024*1024)); | ||
564 | displaytype = CurLang->mb; | ||
565 | } | ||
566 | else { | ||
567 | displayfull = (ui32)(size / (ui64)(1024*1024*1024)); | ||
568 | displayfractional = (ui32)(10 * (size % (ui64)(1024*1024*1024)) / (ui64)(1024*1024*1024)); | ||
569 | displaytype = CurLang->gb; | ||
570 | } | ||
571 | result.Format(CurLang->size_format, displayfull, displayfractional, displaytype); | ||
572 | } | ||
573 | |||
574 | return result; | ||
575 | } | ||
576 | |||
577 | void CFolderView::UpdateTitleBar(void) | ||
578 | { | ||
579 | CMainFrame *mainfrm = (CMainFrame *)GetTopLevelFrame(); | ||
580 | CFolderTree *ft = (CFolderTree *)GetDocument(); | ||
581 | CString title = ""; | ||
582 | ui64 size; | ||
583 | |||
584 | mainfrm->m_toolbar.UpdateButtonsForView(this); | ||
585 | |||
586 | if (mainfrm == NULL) return; | ||
587 | if (ft == NULL) { | ||
588 | mainfrm->SetWindowText(title); | ||
589 | return; | ||
590 | } | ||
591 | |||
592 | if (selected != NULL && selected->name != NULL) { | ||
593 | if (ft != NULL) title += ft->m_path; | ||
594 | BuildTitleReverse(selected->source, title); | ||
595 | title += selected->source->names[selected->index]; | ||
596 | size = selected->source->sizes[selected->index]; | ||
597 | title += " - " + GetSizeString(size, ft->totalspace, 1) | ||
598 | + " - " + GetSizeString(size, ft->totalspace, 0) + " - "; | ||
599 | } | ||
600 | else if (rootfolder != NULL && ft != NULL) { | ||
601 | if (ft != NULL) title += ft->m_path; | ||
602 | BuildTitleReverse(rootfolder, title); | ||
603 | if (rootfolder->parent == NULL) size = ft->totalspace; // Kludge | ||
604 | else size = rootfolder->SizeTotal(); | ||
605 | title += " - " + GetSizeString(size, ft->totalspace, 0) | ||
606 | + " " + CurLang->total + " - " + GetSizeString(ft->freespace, ft->freespace, 0) | ||
607 | + " " + CurLang->free + " - "; | ||
608 | } | ||
609 | |||
610 | title += "SpaceMonger"; | ||
611 | |||
612 | mainfrm->SetWindowText(title); | ||
613 | } | ||
614 | |||
615 | void CFolderView::BuildTitleReverse(CFolder *folder, CString &string) | ||
616 | { | ||
617 | if (folder->parent != NULL) | ||
618 | BuildTitleReverse(folder->parent, string); | ||
619 | if (folder->parent == NULL) return; | ||
620 | |||
621 | string += folder->parent->names[folder->parentindex]; | ||
622 | string += "\\"; | ||
623 | } | ||
624 | |||
625 | void CFolderView::OnDraw(CDC *pDC) | ||
626 | { | ||
627 | pDC->SelectObject(&minifont); | ||
628 | pDC->SetBkMode(TRANSPARENT); | ||
629 | pDC->SetTextAlign(TA_LEFT | TA_TOP | TA_NOUPDATECP); | ||
630 | pDC->SelectPalette(&m_palette, 0); | ||
631 | pDC->RealizePalette(); | ||
632 | |||
633 | CDisplayFolder *cur = displayfolders; | ||
634 | |||
635 | DrawBox(pDC->m_hDC, ColorFlat, 0, 0, m_width, m_height); | ||
636 | if (cur == NULL) | ||
637 | FillBox(pDC->m_hDC, ColorFlat, 1, 1, m_width-2, m_height-2); | ||
638 | |||
639 | while (cur != NULL) { | ||
640 | MinimalDrawDisplayFolder(pDC, cur, selected == cur); | ||
641 | cur = cur->next; | ||
642 | } | ||
643 | } | ||
644 | |||
645 | void CFolderView::DrawDisplayFolder(CDC *pDC, CDisplayFolder *cur, BOOL sel) | ||
646 | { | ||
647 | pDC->SelectObject(&minifont); | ||
648 | pDC->SetBkMode(TRANSPARENT); | ||
649 | pDC->SetTextAlign(TA_LEFT | TA_TOP | TA_NOUPDATECP); | ||
650 | pDC->SelectPalette(&m_palette, 0); | ||
651 | |||
652 | MinimalDrawDisplayFolder(pDC, cur, sel); | ||
653 | } | ||
654 | |||
655 | void CFolderView::MinimalDrawDisplayFolder(CDC *pDC, CDisplayFolder *cur, BOOL sel) | ||
656 | { | ||
657 | int x, y, w, h; | ||
658 | |||
659 | x = cur->x, y = cur->y, w = cur->w + 1, h = cur->h + 1; | ||
660 | |||
661 | if (cur->depth != -1) | ||
662 | DrawBox(pDC->m_hDC, black, x, y, w, h); | ||
663 | |||
664 | if (w > 2 && h > 2) { | ||
665 | COLORREF color, bright, dark; | ||
666 | CBrush brush, bbrush, dbrush; | ||
667 | int colortype = (cur->flags & 1) ? theApp.m_settings.folder_color | ||
668 | : theApp.m_settings.file_color; | ||
669 | |||
670 | if (sel && !(cur->flags & 2)) | ||
671 | color = bright = dark = RGB(0,0,0); | ||
672 | else if (cur->depth != -1) { | ||
673 | if (colortype == 0) { | ||
674 | color = BoxColors[cur->depth & 7]; | ||
675 | bright = BoxColors[(cur->depth & 7) + 8]; | ||
676 | dark = BoxColors[(cur->depth & 7) + 16]; | ||
677 | } | ||
678 | else if (colortype == 1) { | ||
679 | color = GetSysColor(COLOR_3DFACE); | ||
680 | bright = GetSysColor(COLOR_3DHILIGHT); | ||
681 | dark = GetSysColor(COLOR_3DSHADOW); | ||
682 | } | ||
683 | else { | ||
684 | color = FixedColors[colortype-2]; | ||
685 | bright = FixedColors[colortype-2 + 10]; | ||
686 | dark = FixedColors[colortype-2 + 20]; | ||
687 | } | ||
688 | if (theApp.m_settings.rollover_box) { | ||
689 | if (cur->flags & 4) dark = color, color = bright, bright = RGB(255,255,255); | ||
690 | else bright = color, color = dark; | ||
691 | } | ||
692 | } | ||
693 | else color = bright = dark = GetSysColor(COLOR_3DFACE); | ||
694 | |||
695 | brush.CreateSolidBrush(color); | ||
696 | bbrush.CreateSolidBrush(bright); | ||
697 | dbrush.CreateSolidBrush(dark); | ||
698 | |||
699 | DrawDualBox(pDC->m_hDC, bbrush, dbrush, x + 1, y + 1, w - 2, h - 2); | ||
700 | if (cur->flags & 1) { | ||
701 | DrawBox(pDC->m_hDC, brush, x + 2, y + 2, w - 4, h - 4); | ||
702 | FillBox(pDC->m_hDC, brush, x + 3, y + 3, w - 6, 9); | ||
703 | } | ||
704 | else FillBox(pDC->m_hDC, brush, x + 2, y + 2, w - 4, h - 4); | ||
705 | } | ||
706 | |||
707 | if (cur->name != NULL) { | ||
708 | CRgn rgn; | ||
709 | rgn.CreateRectRgn(x, y, x + w, y + h); | ||
710 | pDC->SelectClipRgn(&rgn); | ||
711 | |||
712 | int len = strlen(cur->name); | ||
713 | CSize size; | ||
714 | int tx, ty; | ||
715 | |||
716 | size = pDC->GetTextExtent(cur->name, len); | ||
717 | if (size.cx > w - 2 || (cur->flags & 1)) tx = x + 2; | ||
718 | else tx = x + (w - size.cx) / 2; | ||
719 | if (size.cy > h - 2 || (cur->flags & 1)) ty = y + 1; | ||
720 | else ty = y + (h - size.cy) / 2; | ||
721 | |||
722 | if (cur->flags & 2) { | ||
723 | // There's only one free-space block, so we can afford to | ||
724 | // be a little less efficient with it. | ||
725 | CFolderTree *ft = (CFolderTree *)GetDocument(); | ||
726 | char buffer[256]; | ||
727 | CString string; | ||
728 | ui64 ts = ft->totalspace; | ||
729 | if (ts <= 1) ts = 1; | ||
730 | si32 freepercent = (si32)(ft->freespace * (ui64)1000 / ts); | ||
731 | string.Format(CurLang->freespace_format, freepercent / 10, freepercent % 10); | ||
732 | size = pDC->GetTextExtent(string); | ||
733 | if (size.cx > w-2) tx = x + 2; | ||
734 | else tx = x + (w - size.cx) / 2; | ||
735 | pDC->TextOut(tx, ty-18, string); | ||
736 | strcpy(buffer, GetSizeString(ft->freespace, ft->totalspace, 0)+" "+CurLang->free); | ||
737 | pDC->TextOut(tx, ty-6, buffer, strlen(buffer)); | ||
738 | sprintf(buffer, CString(CurLang->files_total)+" %u", ft->numfiles); | ||
739 | pDC->TextOut(tx, ty+6, buffer, strlen(buffer)); | ||
740 | sprintf(buffer, CString(CurLang->folders_total)+" %u", ft->numfolders); | ||
741 | pDC->TextOut(tx, ty+15, buffer, strlen(buffer)); | ||
742 | } | ||
743 | else { | ||
744 | if (sel) pDC->SetTextColor(RGB(0xFF,0xFF,0xFF)); | ||
745 | if (!(cur->flags & 1) && h >= 36 && w >= 48) { | ||
746 | // Enough room (probably) for the date and file size | ||
747 | CString string; | ||
748 | CSize size; | ||
749 | string.Empty(); | ||
750 | PrintFileSize(string, cur->source->actualsizes[cur->index]); | ||
751 | size = pDC->GetTextExtent(string); | ||
752 | if (size.cx > w-2) | ||
753 | pDC->TextOut(x+2, ty+1, string); | ||
754 | else pDC->TextOut(x+(w-size.cx)/2, ty+1, string); | ||
755 | string.Empty(); | ||
756 | PrintDate(string, cur->source->times[cur->index]); | ||
757 | size = pDC->GetTextExtent(string); | ||
758 | if (size.cx > w-2) | ||
759 | pDC->TextOut(x+2, ty+11, string); | ||
760 | else pDC->TextOut(x+(w-size.cx)/2, ty+11, string); | ||
761 | ty -= 12; | ||
762 | } | ||
763 | pDC->TextOut(tx, ty, cur->name, len); | ||
764 | if (sel) pDC->SetTextColor(RGB(0,0,0)); | ||
765 | } | ||
766 | pDC->SelectClipRgn(NULL); | ||
767 | } | ||
768 | } | ||
769 | |||
770 | void CFolderView::SetDocument(CFreeDoc *doc) | ||
771 | { | ||
772 | CFreeView::SetDocument(doc); | ||
773 | |||
774 | if (doc != NULL) | ||
775 | rootfolder = ((CFolderTree *)doc)->GetRoot(); | ||
776 | else rootfolder = NULL; | ||
777 | zoomlevel = 0; | ||
778 | |||
779 | UpdateTitleBar(); | ||
780 | OnSize(0, m_width, m_height); | ||
781 | CDC *dc = GetDC(); | ||
782 | OnDraw(dc); | ||
783 | ReleaseDC(dc); | ||
784 | } | ||
785 | |||
786 | void CFolderView::OnActivate(UINT nState, CWnd *pWndOther, BOOL bMinimized) | ||
787 | { | ||
788 | if (nState == WA_ACTIVE || nState == WA_CLICKACTIVE) | ||
789 | SetPalette(); | ||
790 | } | ||
791 | |||
792 | void CFolderView::SetPalette(void) | ||
793 | { | ||
794 | CDC *dc = GetDC(); | ||
795 | dc->SelectPalette(&m_palette, 0); | ||
796 | dc->RealizePalette(); | ||
797 | ReleaseDC(dc); | ||
798 | } | ||
799 | |||
800 | void CFolderView::OnUpdate(CFreeDoc *doc) | ||
801 | { | ||
802 | UpdateTitleBar(); | ||
803 | |||
804 | OnSize(0, m_width, m_height); | ||
805 | |||
806 | CDC *dc = GetDC(); | ||
807 | OnDraw(dc); | ||
808 | ReleaseDC(dc); | ||
809 | |||
810 | m_infotipwnd.SetShowDelay(theApp.m_settings.infotip_delay); | ||
811 | m_nametipwnd.SetShowDelay(theApp.m_settings.nametip_delay); | ||
812 | } | ||
813 | |||
814 | void CFolderView::OnSize(UINT nType, int cx, int cy) | ||
815 | { | ||
816 | CRect rect; | ||
817 | GetClientRect(&rect); | ||
818 | m_width = cx = rect.right - rect.left; | ||
819 | m_height = cy = rect.bottom - rect.top; | ||
820 | |||
821 | ClearDisplayFolders(); | ||
822 | |||
823 | if (rootfolder == NULL) { | ||
824 | if (GetDocument() == NULL) return; | ||
825 | rootfolder = ((CFolderTree *)GetDocument())->GetRoot(); | ||
826 | zoomlevel = 0; | ||
827 | if (rootfolder == NULL) return; | ||
828 | } | ||
829 | |||
830 | BuildFolderLayout(0, 0, cx - 1, cy - 1, rootfolder, zoomlevel); | ||
831 | } | ||
832 | |||
833 | CDisplayFolder *CFolderView::AddDisplayFolder(CFolder *source, ui32 index, | ||
834 | si32 depth, si16 x, si16 y, si16 w, si16 h, ui32 flags) | ||
835 | { | ||
836 | CDisplayFolder *newfolder = new CDisplayFolder; | ||
837 | char c; | ||
838 | |||
839 | if (source != NULL && index != (ui32)-1) { | ||
840 | newfolder->name = source->names[index]; | ||
841 | c = newfolder->name[0]; | ||
842 | } | ||
843 | else newfolder->name = NULL, c = 0; | ||
844 | |||
845 | if (c == '*' || c == '<' || c == '>' || c == '?' || c == '|') | ||
846 | newfolder->depth = -1, flags |= 2; | ||
847 | else newfolder->depth = depth; | ||
848 | |||
849 | newfolder->flags = flags; | ||
850 | newfolder->source = source; | ||
851 | newfolder->index = index; | ||
852 | newfolder->x = x, newfolder->y = y; | ||
853 | newfolder->w = w, newfolder->h = h; | ||
854 | newfolder->next = NULL; | ||
855 | |||
856 | if (displayend == NULL) | ||
857 | displayfolders = displayend = newfolder; | ||
858 | else | ||
859 | displayend = (displayend->next = newfolder); | ||
860 | |||
861 | return(newfolder); | ||
862 | } | ||
863 | |||
864 | void CFolderView::ClearDisplayFolders(void) | ||
865 | { | ||
866 | CDisplayFolder *cur = displayfolders, *temp; | ||
867 | while (cur != NULL) { | ||
868 | temp = cur->next; | ||
869 | delete cur; | ||
870 | cur = temp; | ||
871 | } | ||
872 | displayfolders = NULL; | ||
873 | displayend = NULL; | ||
874 | selected = NULL; | ||
875 | } | ||
876 | |||
877 | void CFolderView::BuildFolderLayout(int x, int y, int w, int h, CFolder *folder, int depth) | ||
878 | { | ||
879 | unsigned int i; | ||
880 | |||
881 | if (folder == NULL) return; | ||
882 | |||
883 | int *indices = new int[folder->cur]; | ||
884 | for (i = 0; i < folder->cur; i++) indices[i] = i; | ||
885 | |||
886 | static const int minsizes[][2] = { | ||
887 | { 96, 64, }, | ||
888 | { 64, 48, }, | ||
889 | { 48, 32, }, | ||
890 | { 32, 24, }, | ||
891 | { 24, 16, }, | ||
892 | { 16, 12, }, | ||
893 | { 8, 6, }, | ||
894 | }; | ||
895 | hmin = minsizes[theApp.m_settings.density + 3][0]; | ||
896 | vmin = minsizes[theApp.m_settings.density + 3][1]; | ||
897 | |||
898 | SizeFolders(x, y, w, h, folder, indices, (int)folder->cur, depth); | ||
899 | |||
900 | delete indices; | ||
901 | } | ||
902 | |||
903 | void CFolderView::SizeFolders(int x, int y, int w, int h, CFolder *folder, int *index, int numindices, int depth) | ||
904 | { | ||
905 | if (folder == NULL) return; | ||
906 | |||
907 | ui64 totalspace = folder->SizeTotal(); | ||
908 | |||
909 | int *list1 = new int[numindices]; | ||
910 | int *list2 = new int[numindices]; | ||
911 | int numlist1, numlist2, largest; | ||
912 | si64 list1sum, list2sum, bignum; | ||
913 | int x1, y1, w1, h1; | ||
914 | int x2, y2, w2, h2; | ||
915 | int split; | ||
916 | |||
917 | // Split the lists evenly. We assume the sizes are sorted | ||
918 | // in descending order. Overall, this is a greedy algorithm, | ||
919 | // so it should produce fairly good results. | ||
920 | |||
921 | numlist1 = numlist2 = 0; | ||
922 | list1sum = list2sum = 0; | ||
923 | |||
924 | for (largest = 0; largest < numindices; largest++) { | ||
925 | bignum = (si64)folder->sizes[index[largest]]; | ||
926 | if (folder->names[index[largest]][0] == '<' && !showfreespace) | ||
927 | bignum = 0; | ||
928 | if (bignum != 0) { | ||
929 | if (list1sum <= list2sum) { | ||
930 | list1[numlist1++] = index[largest]; | ||
931 | list1sum += bignum; | ||
932 | } | ||
933 | else { | ||
934 | list2[numlist2++] = index[largest]; | ||
935 | list2sum += bignum; | ||
936 | } | ||
937 | } | ||
938 | } | ||
939 | |||
940 | // Don't bother if the files have no space | ||
941 | if (list1sum + list2sum <= 0) { | ||
942 | delete list1; | ||
943 | delete list2; | ||
944 | return; | ||
945 | } | ||
946 | |||
947 | // Okay, we're now as even as we can safely get. Now we know how to | ||
948 | // split up the space. | ||
949 | int wbias, hbias; | ||
950 | if (theApp.m_settings.bias > 0) | ||
951 | wbias = theApp.m_settings.bias + 8, hbias = 8; | ||
952 | else if (theApp.m_settings.bias < 0) | ||
953 | hbias = -theApp.m_settings.bias + 8, wbias = 8; | ||
954 | else wbias = 8, hbias = 8; | ||
955 | if (((w * wbias) / 8) > ((h * hbias) / 8)) { | ||
956 | split = (int)(((si64)w * list1sum) / (list1sum + list2sum)); | ||
957 | x1 = x, y1 = y, w1 = split, h1 = h; | ||
958 | x2 = x + split, y2 = y, w2 = w - split, h2 = h; | ||
959 | } | ||
960 | else { | ||
961 | split = (int)(((si64)h * list1sum) / (list1sum + list2sum)); | ||
962 | x1 = x, y1 = y, w1 = w, h1 = split; | ||
963 | x2 = x, y2 = y + split, w2 = w, h2 = h - split; | ||
964 | } | ||
965 | // Now if a given rectangle has more than one file and is | ||
966 | // large enough to be subdivided again, subdivide again | ||
967 | if (numlist1 > 1 && w1 > hmin && h1 > vmin) | ||
968 | SizeFolders(x1, y1, w1, h1, folder, list1, numlist1, depth); | ||
969 | else if (numlist1 > 0) { | ||
970 | if (w1 > hmin && h1 > vmin) { | ||
971 | AddDisplayFolder(folder, list1[0], | ||
972 | depth, x1, y1, w1, h1, | ||
973 | (folder->children[list1[0]] != NULL)); | ||
974 | if (folder->children[list1[0]] != NULL) { | ||
975 | if (w1 > hmin && h1 > vmin) { | ||
976 | BuildFolderLayout(x1 + 3, y1 + 12, w1 - 6, h1 - 15, | ||
977 | folder->children[list1[0]], depth+1); | ||
978 | } | ||
979 | else AddDisplayFolder(folder, (ui32)-1, depth + 1, | ||
980 | x2 + 3, y2 + 12, w2 - 6, h2 - 15, 0); | ||
981 | } | ||
982 | } | ||
983 | else AddDisplayFolder(folder, (ui32)-1, depth, x1, y1, w1, h1, 0); | ||
984 | } | ||
985 | if (numlist2 > 1 && w2 > hmin && h2 > vmin) | ||
986 | SizeFolders(x2, y2, w2, h2, folder, list2, numlist2, depth); | ||
987 | else if (numlist2 > 0) { | ||
988 | if (w2 > hmin && h2 > vmin) { | ||
989 | AddDisplayFolder(folder, list2[0], | ||
990 | depth, x2, y2, w2, h2, | ||
991 | (folder->children[list2[0]] != NULL)); | ||
992 | if (folder->children[list2[0]] != NULL) { | ||
993 | if (w2 > hmin && h2 > vmin) { | ||
994 | BuildFolderLayout(x2 + 3, y2 + 12, w2 - 6, h2 - 15, | ||
995 | folder->children[list2[0]], depth+1); | ||
996 | } | ||
997 | else AddDisplayFolder(folder, (ui32)-1, depth + 1, | ||
998 | x2 + 3, y2 + 12, w2 - 6, h2 - 15, 0); | ||
999 | } | ||
1000 | } | ||
1001 | else AddDisplayFolder(folder, (ui32)-1, depth, x2, y2, w2, h2, 0); | ||
1002 | } | ||
1003 | |||
1004 | delete list1; | ||
1005 | delete list2; | ||
1006 | } | ||
1007 | |||
1008 | void CFolderView::ZoomIn(CDisplayFolder *folder) | ||
1009 | { | ||
1010 | CFolderTree *doc = (CFolderTree *)GetDocument(); | ||
1011 | CFolder *oldroot = rootfolder; | ||
1012 | |||
1013 | if (folder != NULL && folder->source->children[folder->index] != NULL) | ||
1014 | rootfolder = folder->source->children[folder->index]; | ||
1015 | |||
1016 | if (rootfolder == oldroot) return; | ||
1017 | |||
1018 | CRect start(folder->x, folder->y, | ||
1019 | folder->x+folder->w, folder->y+folder->h); | ||
1020 | CRect end; | ||
1021 | GetClientRect(&end); | ||
1022 | end.OffsetRect(-end.left, -end.top); | ||
1023 | if (theApp.m_settings.animated_zoom) AnimateBox(start, end); | ||
1024 | |||
1025 | CFolder *parent = rootfolder->parent; | ||
1026 | zoomlevel = 0; | ||
1027 | while (parent != NULL) zoomlevel++, parent = parent->parent; | ||
1028 | OnUpdate(doc); | ||
1029 | UpdateTitleBar(); | ||
1030 | } | ||
1031 | |||
1032 | void CFolderView::ZoomOut(void) | ||
1033 | { | ||
1034 | CFolderTree *doc = (CFolderTree *)GetDocument(); | ||
1035 | CFolder *oldroot = rootfolder; | ||
1036 | |||
1037 | if (rootfolder != NULL && rootfolder->parent != NULL) | ||
1038 | rootfolder = rootfolder->parent; | ||
1039 | |||
1040 | if (rootfolder == oldroot) return; | ||
1041 | |||
1042 | CRect start; | ||
1043 | GetClientRect(&start); | ||
1044 | start.OffsetRect(-start.left, -start.top); | ||
1045 | CRect end; | ||
1046 | end.left = end.right = start.right / 2; | ||
1047 | end.top = end.bottom = start.bottom / 2; | ||
1048 | if (theApp.m_settings.animated_zoom) AnimateBox(start, end); | ||
1049 | |||
1050 | zoomlevel--; | ||
1051 | OnUpdate(doc); | ||
1052 | UpdateTitleBar(); | ||
1053 | } | ||
1054 | |||
1055 | void CFolderView::ZoomFull(void) | ||
1056 | { | ||
1057 | CFolderTree *doc = (CFolderTree *)GetDocument(); | ||
1058 | CFolder *oldroot = rootfolder; | ||
1059 | |||
1060 | if (doc != NULL) | ||
1061 | rootfolder = ((CFolderTree *)doc)->GetRoot(); | ||
1062 | else rootfolder = NULL; | ||
1063 | |||
1064 | if (rootfolder == oldroot) return; | ||
1065 | |||
1066 | CRect start; | ||
1067 | GetClientRect(&start); | ||
1068 | start.OffsetRect(-start.left, -start.top); | ||
1069 | CRect end; | ||
1070 | end.left = end.right = start.right / 2; | ||
1071 | end.top = end.bottom = start.bottom / 2; | ||
1072 | if (theApp.m_settings.animated_zoom) AnimateBox(start, end); | ||
1073 | |||
1074 | zoomlevel = 0; | ||
1075 | OnUpdate(doc); | ||
1076 | UpdateTitleBar(); | ||
1077 | } | ||
1078 | |||
1079 | void CFolderView::ShowFreeSpace(BOOL shown) | ||
1080 | { | ||
1081 | if (showfreespace == shown) return; | ||
1082 | showfreespace = shown; | ||
1083 | OnUpdate(GetDocument()); | ||
1084 | } | ||
1085 | |||
1086 | static void ComputeNewRect(CRect &result, const CRect &start, const CRect &end, ui32 max, ui32 step) | ||
1087 | { | ||
1088 | if (max <= 0) max = 1; | ||
1089 | result.left = ((start.left * (max - step)) + (end.left * step)) / max; | ||
1090 | result.top = ((start.top * (max - step)) + (end.top * step)) / max; | ||
1091 | result.right = ((start.right * (max - step)) + (end.right * step)) / max; | ||
1092 | result.bottom = ((start.bottom * (max - step)) + (end.bottom * step)) / max; | ||
1093 | } | ||
1094 | |||
1095 | static void MinimalRect(CDC *dc, const CRect &rect) | ||
1096 | { | ||
1097 | dc->MoveTo(rect.left, rect.top); | ||
1098 | dc->LineTo(rect.right, rect.top); | ||
1099 | dc->LineTo(rect.right, rect.bottom); | ||
1100 | dc->LineTo(rect.left, rect.bottom); | ||
1101 | dc->LineTo(rect.left, rect.top); | ||
1102 | } | ||
1103 | |||
1104 | void CFolderView::AnimateBox(const CRect &start, const CRect &end) | ||
1105 | { | ||
1106 | // Total time of animation: 400 milliseconds + render time, or | ||
1107 | // about a half a second. | ||
1108 | |||
1109 | ui32 step; | ||
1110 | CRect rect = start; | ||
1111 | CDC *dc = GetDC(); | ||
1112 | dc->SetROP2(R2_NOT); | ||
1113 | for (step = 0; step < 8; step++) { | ||
1114 | ComputeNewRect(rect, start, end, 8, step); | ||
1115 | MinimalRect(dc, rect); | ||
1116 | Sleep(25); | ||
1117 | } | ||
1118 | for (step = 0; step < 8; step++) { | ||
1119 | ComputeNewRect(rect, start, end, 8, step); | ||
1120 | MinimalRect(dc, rect); | ||
1121 | Sleep(25); | ||
1122 | } | ||
1123 | dc->SetROP2(R2_COPYPEN); | ||
1124 | ReleaseDC(dc); | ||
1125 | } | ||
1126 | |||
1127 | void CFolderView::OnIgnoreUpdate(CCmdUI *ui) | ||
1128 | { | ||
1129 | GeneralIgnoreUpdate(ui); | ||
1130 | } | ||
1131 | |||
diff --git a/FolderView.h b/FolderView.h new file mode 100644 index 0000000..5c5e901 --- /dev/null +++ b/FolderView.h | |||
@@ -0,0 +1,101 @@ | |||
1 | #ifndef FOLDERVIEW_H | ||
2 | #define FOLDERVIEW_H | ||
3 | |||
4 | #include "FolderTree.h" | ||
5 | #include "TipWnd.h" | ||
6 | |||
7 | struct CDisplayFolder { | ||
8 | char *name; | ||
9 | si32 depth; | ||
10 | ui32 flags; // 1=folder | ||
11 | CFolder *source; | ||
12 | ui32 index; | ||
13 | si16 x, y, w, h; | ||
14 | CDisplayFolder *next; | ||
15 | }; | ||
16 | |||
17 | class CFolderView : public CFreeView { | ||
18 | public: | ||
19 | CFolderView(); | ||
20 | DECLARE_DYNCREATE(CFolderView) | ||
21 | virtual ~CFolderView(); | ||
22 | |||
23 | virtual void SetDocument(CFreeDoc *doc = NULL); | ||
24 | virtual void SetPalette(void); | ||
25 | |||
26 | void BuildTitleReverse(CFolder *folder, CString &string); | ||
27 | CDisplayFolder *GetDisplayFolderFromPoint(const CPoint &point); | ||
28 | CDisplayFolder *GetContainerDisplayFolderFromPoint(const CPoint &point); | ||
29 | void HighlightPathAtPoint(const CPoint &point); | ||
30 | |||
31 | void ZoomIn(CDisplayFolder *folder); | ||
32 | void ZoomOut(void); | ||
33 | void ZoomFull(void); | ||
34 | void ShowFreeSpace(BOOL show); | ||
35 | |||
36 | inline bool IsAnythingOpen(void) | ||
37 | { return rootfolder != NULL; } | ||
38 | inline bool IsAnythingSelected(void) | ||
39 | { return selected != NULL; } | ||
40 | inline bool IsSelectedAFolder(void) | ||
41 | { return selected != NULL && (selected->flags & 1) != 0; } | ||
42 | inline bool IsZoomFull(void) | ||
43 | { return zoomlevel == 0; } | ||
44 | |||
45 | void UpdateTitleBar(void); | ||
46 | |||
47 | void SelectFolder(CDisplayFolder *cur); | ||
48 | |||
49 | //{{AFX_VIRTUAL(CFolderView) | ||
50 | protected: | ||
51 | virtual void OnDraw(CDC *pDC); | ||
52 | //}}AFX_VIRTUAL | ||
53 | |||
54 | protected: | ||
55 | //{{AFX_MSG(CFolderView) | ||
56 | afx_msg void OnSize(UINT nType, int cx, int cy); | ||
57 | afx_msg void OnLButtonDown(UINT flags, CPoint point); | ||
58 | afx_msg void OnLButtonDblClk(UINT flags, CPoint point); | ||
59 | afx_msg void OnRButtonUp(UINT flags, CPoint point); | ||
60 | afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); | ||
61 | afx_msg void OnDestroy(); | ||
62 | afx_msg void OnMouseMove(UINT nFlags, CPoint point); | ||
63 | //}}AFX_MSG | ||
64 | afx_msg void OnIgnoreUpdate(CCmdUI *ui); | ||
65 | BOOL OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT *pResult); | ||
66 | afx_msg void OnActivate(UINT nState, CWnd *pWndOther, BOOL bMinimized); | ||
67 | DECLARE_MESSAGE_MAP() | ||
68 | |||
69 | public: | ||
70 | virtual void OnUpdate(CFreeDoc *doc); | ||
71 | |||
72 | protected: | ||
73 | void BuildFolderLayout(int x, int y, int w, int h, CFolder *folder, int depth); | ||
74 | void SizeFolders(int x, int y, int w, int h, CFolder *folder, int *index, int numindices, int depth); | ||
75 | CDisplayFolder *AddDisplayFolder(CFolder *source, ui32 index, | ||
76 | si32 depth, si16 x, si16 y, si16 w, si16 h, ui32 flags); | ||
77 | void ClearDisplayFolders(void); | ||
78 | void DrawDisplayFolder(CDC *pDC, CDisplayFolder *cur, BOOL selected); | ||
79 | void MinimalDrawDisplayFolder(CDC *pDC, CDisplayFolder *cur, BOOL selected); | ||
80 | void AnimateBox(const CRect &start, const CRect &end); | ||
81 | void SetupInfoTip(CDisplayFolder *cur); | ||
82 | void SetupNameTip(CDisplayFolder *cur); | ||
83 | |||
84 | protected: | ||
85 | CPalette m_palette; | ||
86 | CBrush black, white; | ||
87 | CFont minifont; | ||
88 | CFolder *rootfolder; | ||
89 | CDisplayFolder *displayfolders, *displayend; | ||
90 | int vmin, hmin; | ||
91 | CTipWnd m_infotipwnd; | ||
92 | CTipWnd m_nametipwnd; | ||
93 | CDisplayFolder *lastcur; | ||
94 | |||
95 | public: | ||
96 | int zoomlevel; | ||
97 | CDisplayFolder *selected; | ||
98 | BOOL showfreespace; | ||
99 | }; | ||
100 | |||
101 | #endif | ||
diff --git a/Freedoc.cpp b/Freedoc.cpp new file mode 100644 index 0000000..b7c42b9 --- /dev/null +++ b/Freedoc.cpp | |||
@@ -0,0 +1,122 @@ | |||
1 | |||
2 | #include "stdafx.h" | ||
3 | |||
4 | CFreeDoc::CFreeDoc() | ||
5 | { | ||
6 | m_strTitle = ""; | ||
7 | m_strPathName = ""; | ||
8 | m_bModified = 0; | ||
9 | m_bCreated = 0; | ||
10 | } | ||
11 | |||
12 | CFreeDoc::~CFreeDoc() | ||
13 | { | ||
14 | if (m_bCreated) OnDestroy(); | ||
15 | |||
16 | m_bCreated = 0; | ||
17 | m_bModified = 0; | ||
18 | m_strPathName = ""; | ||
19 | m_strTitle = ""; | ||
20 | } | ||
21 | |||
22 | BOOL CFreeDoc::Create(void) | ||
23 | { | ||
24 | BOOL createresult; | ||
25 | |||
26 | m_bModified = 0; | ||
27 | m_bCreated = 0; | ||
28 | m_strTitle = ""; | ||
29 | m_strPathName = ""; | ||
30 | |||
31 | createresult = OnCreate(); | ||
32 | |||
33 | m_bCreated = 1; | ||
34 | |||
35 | return(createresult); | ||
36 | } | ||
37 | |||
38 | BOOL CFreeDoc::IsModified(void) const | ||
39 | { | ||
40 | return(m_bModified); | ||
41 | } | ||
42 | |||
43 | void CFreeDoc::SetModifiedFlag(const BOOL modified) | ||
44 | { | ||
45 | m_bModified = modified; | ||
46 | } | ||
47 | |||
48 | void CFreeDoc::SetTitle(const CString &string) | ||
49 | { | ||
50 | m_strTitle = string; | ||
51 | } | ||
52 | |||
53 | void CFreeDoc::SetPathName(const CString &string) | ||
54 | { | ||
55 | m_strPathName = string; | ||
56 | } | ||
57 | |||
58 | UINT CFreeDoc::GetViewCount(void) const | ||
59 | { | ||
60 | return(m_viewList.GetCount()); | ||
61 | } | ||
62 | |||
63 | void CFreeDoc::AddView(CFreeView *view) | ||
64 | { | ||
65 | if (view != NULL) { | ||
66 | m_viewList.AddTail((void *)view); | ||
67 | OnChangedViewList(view, 1); | ||
68 | view->m_document = this; | ||
69 | } | ||
70 | } | ||
71 | |||
72 | void CFreeDoc::RemoveView(CFreeView *view) | ||
73 | { | ||
74 | if (view != NULL) { | ||
75 | POSITION pos = m_viewList.Find(view); | ||
76 | if (pos != NULL) { | ||
77 | m_viewList.RemoveAt(pos); | ||
78 | OnChangedViewList(view, 0); | ||
79 | } | ||
80 | view->m_document = NULL; | ||
81 | } | ||
82 | } | ||
83 | |||
84 | POSITION CFreeDoc::GetFirstViewPosition(void) const | ||
85 | { | ||
86 | return(m_viewList.GetHeadPosition()); | ||
87 | } | ||
88 | |||
89 | CFreeView *CFreeDoc::GetNextView(POSITION &position) const | ||
90 | { | ||
91 | CFreeView *view = (CFreeView *)m_viewList.GetNext(position); | ||
92 | return(view); | ||
93 | } | ||
94 | |||
95 | void CFreeDoc::UpdateAllViews(void) | ||
96 | { | ||
97 | POSITION pos = m_viewList.GetHeadPosition(); | ||
98 | CFreeView *view; | ||
99 | |||
100 | while (pos != NULL) { | ||
101 | view = (CFreeView *)m_viewList.GetNext(pos); | ||
102 | UpdateView(view); | ||
103 | } | ||
104 | } | ||
105 | |||
106 | void CFreeDoc::UpdateView(CFreeView *view) | ||
107 | { | ||
108 | view->OnUpdate(this); | ||
109 | } | ||
110 | |||
111 | void CFreeDoc::OnChangedViewList(CFreeView *view, BOOL added) | ||
112 | { | ||
113 | } | ||
114 | |||
115 | BOOL CFreeDoc::OnCreate(void) | ||
116 | { | ||
117 | return(TRUE); | ||
118 | } | ||
119 | |||
120 | void CFreeDoc::OnDestroy(void) | ||
121 | { | ||
122 | } | ||
diff --git a/Freeview.cpp b/Freeview.cpp new file mode 100644 index 0000000..1a0c3c5 --- /dev/null +++ b/Freeview.cpp | |||
@@ -0,0 +1,74 @@ | |||
1 | |||
2 | #include "stdafx.h" | ||
3 | |||
4 | IMPLEMENT_DYNCREATE(CFreeView, CWnd) | ||
5 | |||
6 | CFreeView::CFreeView() | ||
7 | { | ||
8 | m_document = NULL; | ||
9 | } | ||
10 | |||
11 | CFreeView::~CFreeView() | ||
12 | { | ||
13 | if (m_document != NULL) | ||
14 | m_document->RemoveView(this); | ||
15 | } | ||
16 | |||
17 | BEGIN_MESSAGE_MAP(CFreeView, CWnd) | ||
18 | //{{AFX_MSG_MAP(CFreeView) | ||
19 | ON_WM_SIZE() | ||
20 | ON_WM_PAINT() | ||
21 | //}}AFX_MSG_MAP | ||
22 | END_MESSAGE_MAP() | ||
23 | |||
24 | BOOL CFreeView::Create(CWnd *parent, BOOL show) | ||
25 | { | ||
26 | CRect rect; | ||
27 | |||
28 | if (parent != NULL) | ||
29 | parent->GetClientRect(&rect); | ||
30 | else { | ||
31 | rect.left = 0, rect.right = 16; | ||
32 | rect.top = 0, rect.bottom = 16; | ||
33 | } | ||
34 | |||
35 | if (!CWnd::Create(NULL, NULL, WS_CHILD, | ||
36 | rect, parent, 0)) return(FALSE); | ||
37 | if (show) { | ||
38 | ShowWindow(SW_SHOWNORMAL); | ||
39 | UpdateWindow(); | ||
40 | } | ||
41 | |||
42 | return(TRUE); | ||
43 | } | ||
44 | |||
45 | void CFreeView::SetDocument(CFreeDoc *document) | ||
46 | { | ||
47 | if (m_document != NULL) m_document->RemoveView(this); | ||
48 | if (document != NULL) document->AddView(this); | ||
49 | } | ||
50 | |||
51 | CFreeDoc *CFreeView::GetDocument(void) | ||
52 | { | ||
53 | return(m_document); | ||
54 | } | ||
55 | |||
56 | void CFreeView::OnSize(UINT nType, int cx, int cy) | ||
57 | { | ||
58 | CWnd::OnSize(nType, cx, cy); | ||
59 | m_width = cx, m_height = cy; | ||
60 | } | ||
61 | |||
62 | void CFreeView::OnDraw(CDC* pDC) | ||
63 | { | ||
64 | } | ||
65 | |||
66 | void CFreeView::OnUpdate(CFreeDoc *doc) | ||
67 | { | ||
68 | } | ||
69 | |||
70 | void CFreeView::OnPaint() | ||
71 | { | ||
72 | CPaintDC dc(this); | ||
73 | OnDraw(&dc); | ||
74 | } | ||
diff --git a/Mainfrm.cpp b/Mainfrm.cpp new file mode 100644 index 0000000..fd86441 --- /dev/null +++ b/Mainfrm.cpp | |||
@@ -0,0 +1,281 @@ | |||
1 | |||
2 | #include "StdAfx.h" | ||
3 | #include "SpaceMonger.h" | ||
4 | #include "FolderView.h" | ||
5 | #include "AboutDialog.h" | ||
6 | #include "Lang.h" | ||
7 | |||
8 | ///////////////////////////////////////////////////////////////////////////// | ||
9 | // CMainFrame | ||
10 | |||
11 | IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd) | ||
12 | |||
13 | BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) | ||
14 | //{{AFX_MSG_MAP(CMainFrame) | ||
15 | ON_WM_CREATE() | ||
16 | ON_WM_DESTROY() | ||
17 | ON_WM_SYSCOMMAND() | ||
18 | ON_WM_ERASEBKGND() | ||
19 | ON_WM_ACTIVATEAPP() | ||
20 | ON_WM_CLOSE() | ||
21 | ON_WM_WINDOWPOSCHANGED() | ||
22 | ON_WM_SHOWWINDOW() | ||
23 | //}}AFX_MSG_MAP | ||
24 | ON_UPDATE_COMMAND_UI_RANGE(100, 41000, OnIgnoreUpdate) | ||
25 | END_MESSAGE_MAP() | ||
26 | |||
27 | CMainFrame::CMainFrame() | ||
28 | { | ||
29 | } | ||
30 | |||
31 | CMainFrame::~CMainFrame() | ||
32 | { | ||
33 | } | ||
34 | |||
35 | BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) | ||
36 | { | ||
37 | CFrameWnd::PreCreateWindow(cs); | ||
38 | |||
39 | cs.dwExStyle &= ~WS_EX_CLIENTEDGE; | ||
40 | |||
41 | return(1); | ||
42 | } | ||
43 | |||
44 | int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) | ||
45 | { | ||
46 | if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return(-1); | ||
47 | |||
48 | HINSTANCE hinst = AfxFindResourceHandle(MAKEINTRESOURCE(ID_SPACEMONGER), RT_ICON); | ||
49 | HICON hicon = ::LoadIcon(hinst, MAKEINTRESOURCE(ID_SPACEMONGER)); | ||
50 | SetIcon(hicon, 1); | ||
51 | //SetIcon(hicon, 0); | ||
52 | |||
53 | if (!m_toolbar.Create(this)) return(-1); | ||
54 | |||
55 | CMenu *menu = GetSystemMenu(FALSE); | ||
56 | menu->AppendMenu(MF_SEPARATOR); | ||
57 | menu->AppendMenu(MF_STRING, ID_APP_ABOUT, CString("&") | ||
58 | + CurLang->about_spacemonger + "..."); | ||
59 | |||
60 | WINDOWPLACEMENT w; | ||
61 | w.length = sizeof(WINDOWPLACEMENT); | ||
62 | ::GetWindowPlacement(m_hWnd, &w); | ||
63 | theApp.m_settings.rect.left = w.rcNormalPosition.left; | ||
64 | theApp.m_settings.rect.top = w.rcNormalPosition.top; | ||
65 | theApp.m_settings.rect.right = w.rcNormalPosition.right; | ||
66 | theApp.m_settings.rect.bottom = w.rcNormalPosition.bottom; | ||
67 | theApp.m_settings.showcmd = w.showCmd; | ||
68 | |||
69 | RecalcLayout(0); | ||
70 | |||
71 | return(0); | ||
72 | } | ||
73 | |||
74 | void CMainFrame::OnDestroy(void) | ||
75 | { | ||
76 | WINDOWPLACEMENT w; | ||
77 | w.length = sizeof(WINDOWPLACEMENT); | ||
78 | ::GetWindowPlacement(m_hWnd, &w); | ||
79 | theApp.m_settings.rect.left = w.rcNormalPosition.left; | ||
80 | theApp.m_settings.rect.top = w.rcNormalPosition.top; | ||
81 | theApp.m_settings.rect.right = w.rcNormalPosition.right; | ||
82 | theApp.m_settings.rect.bottom = w.rcNormalPosition.bottom; | ||
83 | theApp.m_settings.showcmd = w.showCmd; | ||
84 | } | ||
85 | |||
86 | void CMainFrame::OnActivateApp(BOOL bActive, HTASK hTask) | ||
87 | { | ||
88 | if (bActive) { | ||
89 | CSpaceMonger *monger = (CSpaceMonger *)AfxGetApp(); | ||
90 | if (monger != NULL && monger->m_view != NULL) { | ||
91 | CFolderView *view = (CFolderView *)monger->m_view; | ||
92 | view->OnUpdate(monger->m_document); | ||
93 | } | ||
94 | } | ||
95 | else { | ||
96 | CSpaceMonger *monger = (CSpaceMonger *)AfxGetApp(); | ||
97 | if (monger != NULL && monger->m_view != NULL) { | ||
98 | CFolderView *view = (CFolderView *)monger->m_view; | ||
99 | view->SelectFolder(NULL); | ||
100 | } | ||
101 | } | ||
102 | } | ||
103 | |||
104 | void CMainFrame::RecalcLayout(BOOL bNotify) | ||
105 | { | ||
106 | CRect rectBorder; | ||
107 | int numwnds, wndnum, width; | ||
108 | CWnd *wnd, *first, *last; | ||
109 | |||
110 | if (m_bInRecalcLayout || !IsWindow(m_hWnd) | ||
111 | || (wnd = GetWindow(GW_CHILD)) == NULL) return; | ||
112 | |||
113 | m_bInRecalcLayout = TRUE; | ||
114 | |||
115 | first = wnd->GetWindow(GW_HWNDFIRST); | ||
116 | last = wnd->GetWindow(GW_HWNDLAST); | ||
117 | |||
118 | GetClientRect(&rectBorder); | ||
119 | rectBorder.OffsetRect(-rectBorder.left, -rectBorder.top); | ||
120 | width = rectBorder.right - rectBorder.left; | ||
121 | |||
122 | // Position our two toolbars | ||
123 | m_toolbar.SetWindowPos(NULL, 0, -2, width, 30, | ||
124 | SWP_NOZORDER|SWP_NOACTIVATE); | ||
125 | rectBorder.top += 28; | ||
126 | |||
127 | // First count how many windows need to be rearranged | ||
128 | numwnds = 0; | ||
129 | if (first != NULL) { | ||
130 | wnd = first; | ||
131 | while (1) { | ||
132 | if (wnd->m_hWnd != m_toolbar.m_hWnd) | ||
133 | numwnds++; | ||
134 | if (wnd == last) break; | ||
135 | wnd = wnd->GetWindow(GW_HWNDNEXT); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | // Now lay them all out in a horizontal band (cheap & easy) | ||
140 | if (first != NULL && numwnds > 0) { | ||
141 | wndnum = 0, wnd = first; | ||
142 | while (1) { | ||
143 | if (wnd->m_hWnd != m_toolbar.m_hWnd) { | ||
144 | wnd->SetWindowPos(NULL, rectBorder.left + (width * wndnum) / numwnds, rectBorder.top, | ||
145 | (width * (wndnum+1)) / numwnds - (width * wndnum) / numwnds, | ||
146 | rectBorder.bottom - rectBorder.top, | ||
147 | SWP_NOZORDER); | ||
148 | if (++wndnum == numwnds) break; | ||
149 | } | ||
150 | wnd = wnd->GetWindow(GW_HWNDNEXT); | ||
151 | } | ||
152 | } | ||
153 | |||
154 | m_bInRecalcLayout = FALSE; | ||
155 | } | ||
156 | |||
157 | void CMainFrame::OnSysCommand(UINT nid, LPARAM lparam) | ||
158 | { | ||
159 | if (nid == ID_APP_ABOUT) { | ||
160 | CAboutDialog about; | ||
161 | about.DoModal(); | ||
162 | } | ||
163 | else CFrameWnd::OnSysCommand(nid, lparam); | ||
164 | } | ||
165 | |||
166 | BOOL CMainFrame::OnEraseBkgnd(CDC* pDC) | ||
167 | { | ||
168 | #if 0 | ||
169 | CRect rect; | ||
170 | GetClientRect(&rect); | ||
171 | FillBox(pDC->m_hDC, ColorFlat, 0, 0, | ||
172 | rect.right - rect.left, rect.bottom - rect.top); | ||
173 | #endif | ||
174 | return(-1); | ||
175 | } | ||
176 | |||
177 | void CMainFrame::OnClose() | ||
178 | { | ||
179 | CFrameWnd::OnClose(); | ||
180 | } | ||
181 | |||
182 | void CMainFrame::OnIgnoreUpdate(CCmdUI *ui) | ||
183 | { | ||
184 | GeneralIgnoreUpdate(ui); | ||
185 | } | ||
186 | |||
187 | void CMainFrame::OnWindowPosChanged(WINDOWPOS *wp) | ||
188 | { | ||
189 | CFrameWnd::OnWindowPosChanged(wp); | ||
190 | |||
191 | WINDOWPLACEMENT w; | ||
192 | w.length = sizeof(WINDOWPLACEMENT); | ||
193 | ::GetWindowPlacement(m_hWnd, &w); | ||
194 | theApp.m_settings.rect.left = w.rcNormalPosition.left; | ||
195 | theApp.m_settings.rect.top = w.rcNormalPosition.top; | ||
196 | theApp.m_settings.rect.right = w.rcNormalPosition.right; | ||
197 | theApp.m_settings.rect.bottom = w.rcNormalPosition.bottom; | ||
198 | theApp.m_settings.showcmd = w.showCmd; | ||
199 | } | ||
200 | |||
201 | void CMainFrame::OnShowWindow(BOOL bShow, UINT status) | ||
202 | { | ||
203 | CFrameWnd::OnShowWindow(bShow, status); | ||
204 | |||
205 | WINDOWPLACEMENT w; | ||
206 | w.length = sizeof(WINDOWPLACEMENT); | ||
207 | ::GetWindowPlacement(m_hWnd, &w); | ||
208 | theApp.m_settings.rect.left = w.rcNormalPosition.left; | ||
209 | theApp.m_settings.rect.top = w.rcNormalPosition.top; | ||
210 | theApp.m_settings.rect.right = w.rcNormalPosition.right; | ||
211 | theApp.m_settings.rect.bottom = w.rcNormalPosition.bottom; | ||
212 | theApp.m_settings.showcmd = w.showCmd; | ||
213 | } | ||
214 | |||
215 | ///////////////////////////////////////////////////////////////////////////// | ||
216 | |||
217 | IMPLEMENT_DYNCREATE(CMainToolBar, CToolBar) | ||
218 | |||
219 | BEGIN_MESSAGE_MAP(CMainToolBar, CToolBar) | ||
220 | //{{AFX_MSG_MAP(CMainToolBar) | ||
221 | //}}AFX_MSG_MAP | ||
222 | ON_UPDATE_COMMAND_UI_RANGE(100, 41000, OnIgnoreUpdate) | ||
223 | END_MESSAGE_MAP() | ||
224 | |||
225 | CMainToolBar::CMainToolBar() | ||
226 | { | ||
227 | } | ||
228 | |||
229 | CMainToolBar::~CMainToolBar() | ||
230 | { | ||
231 | } | ||
232 | |||
233 | int CMainToolBar::Create(CWnd *parent) | ||
234 | { | ||
235 | if (!CToolBar::Create(parent, WS_CHILD|WS_VISIBLE|CBRS_TOP, IDR_TOOLBAR_EN)) return 0; | ||
236 | if (!LoadToolBar(CurLang->toolbar_bitmap_id)) return 0; | ||
237 | |||
238 | EnableState(ViewFree, 1); | ||
239 | |||
240 | return 1; | ||
241 | } | ||
242 | |||
243 | void CMainToolBar::EnableState(int state, BOOL enabled) | ||
244 | { | ||
245 | switch (state) { | ||
246 | case CMainToolBar::ViewFree: | ||
247 | SetButtonStyle(CommandToIndex(ID_VIEW_FREE), enabled ? TBBS_BUTTON|TBBS_PRESSED : TBBS_BUTTON); | ||
248 | break; | ||
249 | default: | ||
250 | break; | ||
251 | } | ||
252 | } | ||
253 | |||
254 | void CMainToolBar::UpdateButtonsForView(CFolderView *view) | ||
255 | { | ||
256 | CSpaceMonger *app = (CSpaceMonger *)AfxGetApp(); | ||
257 | CToolBarCtrl &ctrl = this->GetToolBarCtrl(); | ||
258 | ctrl.EnableButton(ID_FILE_RUN, view->IsAnythingOpen() && view->IsAnythingSelected()); | ||
259 | ctrl.EnableButton(ID_FILE_DELETE, !app->m_settings.disable_delete | ||
260 | && view->IsAnythingOpen() && view->IsAnythingSelected()); | ||
261 | ctrl.EnableButton(ID_FILE_OPEN, 1); | ||
262 | ctrl.EnableButton(ID_FILE_REFRESH, view->IsAnythingOpen()); | ||
263 | ctrl.EnableButton(ID_VIEW_ZOOM_FULL, view->IsAnythingOpen() && !view->IsZoomFull()); | ||
264 | ctrl.EnableButton(ID_VIEW_ZOOM_OUT, view->IsAnythingOpen() && !view->IsZoomFull()); | ||
265 | ctrl.EnableButton(ID_VIEW_ZOOM_IN, view->IsAnythingOpen() && view->IsAnythingSelected() | ||
266 | && view->IsSelectedAFolder()); | ||
267 | ctrl.EnableButton(ID_VIEW_FREE, view->IsAnythingOpen()); | ||
268 | ctrl.EnableButton(ID_SETTINGS, 1); | ||
269 | ctrl.EnableButton(ID_APP_ABOUT, 1); | ||
270 | } | ||
271 | |||
272 | void CMainToolBar::OnIgnoreUpdate(CCmdUI *ui) | ||
273 | { | ||
274 | GeneralIgnoreUpdate(ui); | ||
275 | } | ||
276 | |||
277 | void CMainToolBar::Reload(void) | ||
278 | { | ||
279 | LoadToolBar(CurLang->toolbar_bitmap_id); | ||
280 | RedrawWindow(); | ||
281 | } | ||
diff --git a/Mainfrm.h b/Mainfrm.h new file mode 100644 index 0000000..899326a --- /dev/null +++ b/Mainfrm.h | |||
@@ -0,0 +1,59 @@ | |||
1 | |||
2 | #ifndef CMAINFRAME_H | ||
3 | #define CMAINFRAME_H | ||
4 | |||
5 | class CMainToolBar : public CToolBar { | ||
6 | public: | ||
7 | CMainToolBar(); | ||
8 | virtual ~CMainToolBar(); | ||
9 | DECLARE_DYNCREATE(CMainToolBar) | ||
10 | |||
11 | virtual int Create(CWnd *parent); | ||
12 | |||
13 | enum { | ||
14 | NoState = 0, | ||
15 | ViewFree, | ||
16 | }; | ||
17 | |||
18 | virtual void EnableState(int state, BOOL enabled); | ||
19 | void UpdateButtonsForView(class CFolderView *view); | ||
20 | |||
21 | void Reload(void); | ||
22 | |||
23 | protected: | ||
24 | //{{AFX_MSG(CMainToolBar) | ||
25 | afx_msg void OnIgnoreUpdate(CCmdUI *ui); | ||
26 | //}}AFX_MSG | ||
27 | DECLARE_MESSAGE_MAP() | ||
28 | |||
29 | }; | ||
30 | |||
31 | class CMainFrame : public CFrameWnd { | ||
32 | public: | ||
33 | CMainFrame(); | ||
34 | virtual ~CMainFrame(); | ||
35 | DECLARE_DYNCREATE(CMainFrame) | ||
36 | BOOL PreCreateWindow(CREATESTRUCT& cs); | ||
37 | |||
38 | virtual void RecalcLayout(BOOL bNotify); | ||
39 | |||
40 | protected: | ||
41 | //{{AFX_MSG(CMainFrame) | ||
42 | afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); | ||
43 | afx_msg void OnDestroy(void); | ||
44 | afx_msg void OnSysCommand(UINT nid, LPARAM lparam); | ||
45 | afx_msg void OnClose(); | ||
46 | afx_msg void OnActivateApp(BOOL bActive, HTASK hTask); | ||
47 | afx_msg BOOL OnEraseBkgnd(CDC* pDC); | ||
48 | afx_msg void OnWindowPosChanged(WINDOWPOS *wp); | ||
49 | afx_msg void OnShowWindow(BOOL bShow, UINT status); | ||
50 | //}}AFX_MSG | ||
51 | afx_msg void OnIgnoreUpdate(CCmdUI *ui); | ||
52 | DECLARE_MESSAGE_MAP() | ||
53 | |||
54 | public: | ||
55 | CMainToolBar m_toolbar; | ||
56 | }; | ||
57 | |||
58 | #endif | ||
59 | |||
diff --git a/README.TXT b/README.TXT new file mode 100644 index 0000000..4001b0a --- /dev/null +++ b/README.TXT | |||
@@ -0,0 +1,185 @@ | |||
1 | |||
2 | SpaceMonger Version 1.4.0 | ||
3 | ------------------------- | ||
4 | |||
5 | |||
6 | INTRODUCTION | ||
7 | ------------ | ||
8 | |||
9 | SpaceMonger is a free tool for keeping track of the disk space on your | ||
10 | computer. Instead of viewing your disk as unhelpful little icons or | ||
11 | pie charts, you see a single picture that shows you at a glance how | ||
12 | much space every file and folder are using. | ||
13 | |||
14 | The latest version of SpaceMonger is always available at its web page: | ||
15 | |||
16 | http://www.werkema.com/software/spacemonger.html | ||
17 | |||
18 | |||
19 | SYSTEM REQUIREMENTS | ||
20 | ------------------- | ||
21 | |||
22 | SpaceMonger should run on any version of Windows 95, 98, or NT. It has | ||
23 | been tested on all three. It will probably run fine on Windows 2000, but | ||
24 | has not been officially tested on Windows 2000. It should be able to run | ||
25 | on any computer that can run Windows 95, 98, or NT; there are no | ||
26 | additional space or memory requirements, although we do recommend you have | ||
27 | at least 4 megabytes of memory installed in your computer if you want it | ||
28 | to run efficiently. | ||
29 | |||
30 | |||
31 | INSTALLATION | ||
32 | ------------ | ||
33 | |||
34 | Unpack the .ZIP archive. A single Windows executable will be produced, | ||
35 | named "SpaceMonger.exe", along with "README.TXT", which is what you're | ||
36 | reading now. The "SpaceMonger.exe" file is the complete program, and it | ||
37 | can be moved into any folder you like. (We recommend "C:\Program Files", | ||
38 | but you don't have to put it there.) | ||
39 | |||
40 | Double-click on it to run it. | ||
41 | |||
42 | |||
43 | NOTE TO WINDOWS 2000 USERS: | ||
44 | --------------------------- | ||
45 | |||
46 | SpaceMonger will run on Windows 2000. However, version 1.4.0 will NOT | ||
47 | correctly report space used by hard links, junction points, or sparse | ||
48 | files. So if you use Windows 2000, here is what you should expect: | ||
49 | |||
50 | * Hard linked files will exist in both places: There will appear | ||
51 | to be a full copy of the file everywhere a hard link exists, | ||
52 | so these files will get over-counted. | ||
53 | * Junction points and mount points will be treated as though they | ||
54 | are real folders, so their contents will be over-counted as well. | ||
55 | * Sparse files will not be treated as sparse: If you have a | ||
56 | 10-megabyte sparse file that really only uses one megabyte of | ||
57 | disk space, it will still be counted as 10 megabytes. | ||
58 | |||
59 | Our crack research team is investigating these problems and should be | ||
60 | able to resolve some of them soon. | ||
61 | |||
62 | |||
63 | FIRST-TIME INSTRUCTIONS | ||
64 | ----------------------- | ||
65 | |||
66 | SpaceMonger is not a hard program to use. In fact, you probably won't | ||
67 | need any instructions. But for those of you who like to read, here are | ||
68 | some first-time instructions: | ||
69 | |||
70 | When you first open SpaceMonger, you will initially be presented with a | ||
71 | blank window. Click "Open". Click on a drive, like drive "C", and hit | ||
72 | "OK". Wait patiently while the program collects statistics on your | ||
73 | drive. My, don't you have a lot of files! | ||
74 | |||
75 | SpaceMonger will show you the contents of your drive as little | ||
76 | rectangles. The larger the rectangle, the more space something is taking | ||
77 | up. Rectangles that have other rectangles in them are folders. | ||
78 | Rectangles with no other rectangles in them are files. Colors are used | ||
79 | to show how deeply the files and folders are nested. | ||
80 | |||
81 | You can get more information on a given folder by clicking on its title | ||
82 | and then clicking "Zoom In" (or by double-clicking on its title). The | ||
83 | window will change to show a larger, more detailed view of the folder | ||
84 | and its files. You can zoom in as many times as you want. "Zoom Out" | ||
85 | will take you back out (up) by one folder. "Zoom Full" will take you | ||
86 | all the way back to show the whole drive. | ||
87 | |||
88 | If you see a file or folder you want to delete, click it to select it | ||
89 | and hit "Delete". It will be moved to the Recycle Bin. If you want to | ||
90 | see what it is first, click on it and hit "Run or Open", which will try | ||
91 | to run it if is a program or open it if it is a file. | ||
92 | |||
93 | DISCLAIMER: If you don't know what something is, DON'T DELETE IT. | ||
94 | Deleting things at random is a good way to break your programs or | ||
95 | Windows itself or worse. 'Nuff said. | ||
96 | |||
97 | If you click the "Setup" button, you can change some aesthetic things | ||
98 | about the program. You can't damage anything with the Setup dialog box, | ||
99 | so feel free to try various options until you like how SpaceMonger looks | ||
100 | and feels. | ||
101 | |||
102 | In addition, you can right-click on a folder or a file to bring up a | ||
103 | context-sensitive menu of options that are identical to those on the | ||
104 | toolbar. This may be more efficient for some users. | ||
105 | |||
106 | If you double-click on a folder, SpaceMonger will zoom in on it. If you | ||
107 | double-click on a file (either a program or a document), SpaceMonger | ||
108 | will attempt to run it or open it, whichever is suitable. | ||
109 | |||
110 | |||
111 | DISTRIBUTION | ||
112 | ------------ | ||
113 | |||
114 | SpaceMonger is freeware, not crippled or time-limited in any way. You | ||
115 | can distribute it any way you like. You can even sell it, but the latest | ||
116 | copy will always be available for free download at SpaceMonger's web page, | ||
117 | so you probably won't be able to get much money for it. We encourage | ||
118 | users of the program to give away copies to their friends. | ||
119 | |||
120 | |||
121 | WHAT'S NEW | ||
122 | ---------- | ||
123 | |||
124 | Between 1.3.5 and 1.4.0 | ||
125 | * Internals rewritten to support multiple foreign langauges. | ||
126 | Currently foreign language support exists for British English, | ||
127 | American English, and French (possibly with grammar errors). | ||
128 | * Supports popup info-tips that can display the full filename, the | ||
129 | icon, the date, size, and attributes of any file or folder. | ||
130 | * Supports popup name-tips that prevent names from being obscured | ||
131 | by not having enough space to display them. | ||
132 | * Open dialog box now uses large icons. | ||
133 | * Includes rollover boxes that highlight the current folder. | ||
134 | * Files display their sizes and dates if there is enough room. | ||
135 | * Option to save the current window position. | ||
136 | * Fixed zero-size bug that caused divide-by-zero errors with some | ||
137 | Audio CD disks. | ||
138 | * Minor changes to color palette to handle rollover boxes. | ||
139 | * Support for Windows Property dialog box. | ||
140 | * Numerous other bug fixes. | ||
141 | * Support for Windows NT junction points. | ||
142 | |||
143 | Between 1.3.4 and 1.3.5 | ||
144 | * Toolbar buttons gray out when you can't use them. | ||
145 | * Setup option to disable the "Delete" button. | ||
146 | * Fixed size-computation routine that was oversizing | ||
147 | files on some systems. | ||
148 | * Double-clicking on files runs or opens them; double-clicking | ||
149 | on folders zooms in on them. | ||
150 | * Scanning now includes a percent bar so you can tell how | ||
151 | long it's taking. | ||
152 | |||
153 | Between 1.3.0 and 1.3.4 | ||
154 | * Major speed improvements using new memory manager subsystem. | ||
155 | Runs twice as fast and uses half the memory of 1.3.0. | ||
156 | * Better display of free space information. | ||
157 | * Right-click opens a pop-up menu of options. | ||
158 | * Double-click zooms in on a folder. | ||
159 | * Few minor bug-fixes. | ||
160 | * Replaced old "Scanning..." window with a better one. | ||
161 | |||
162 | Between 1.2.0 and 1.3.0 | ||
163 | * Added the Setup button with a whole bunch of new options. | ||
164 | * Internal bug-fixes to scanning routine. | ||
165 | |||
166 | Between 1.0.2 and 1.2.0 | ||
167 | * Lots of stuff. 1.1.0 was never released. New buttons, | ||
168 | new look, better code. Replaced most of what's under | ||
169 | the hood. | ||
170 | * 1.2.0 was released for private use only. | ||
171 | |||
172 | Between 1.0.0 and 1.0.2 | ||
173 | * Miscellaneous bug fixes. | ||
174 | * Added "Zoom In" and "Zoom Out" buttons. | ||
175 | * Added "Run or Open" and "Delete" buttons. | ||
176 | |||
177 | |||
178 | COPYRIGHT AND CONTACT INFORMATION | ||
179 | --------------------------------- | ||
180 | |||
181 | SpaceMonger is Copyright (C) 1998, 1999, and 2000 by Sean Werkema. | ||
182 | Have questions? Found a bug? Want a feature? Compose your thoughts in | ||
183 | an e-mail and send them to sean@werkema.com. I should be able to respond | ||
184 | within a few days of your message. | ||
185 | |||
diff --git a/SetupDlg.cpp b/SetupDlg.cpp new file mode 100644 index 0000000..eb44ab7 --- /dev/null +++ b/SetupDlg.cpp | |||
@@ -0,0 +1,310 @@ | |||
1 | |||
2 | #include "stdafx.h" | ||
3 | #include "spacemonger.h" | ||
4 | #include "Lang.h" | ||
5 | #include "SetupDlg.h" | ||
6 | |||
7 | IMPLEMENT_DYNCREATE(CSettingsDialog, CDialog) | ||
8 | |||
9 | BEGIN_MESSAGE_MAP(CSettingsDialog, CDialog) | ||
10 | //{{AFX_MSG_MAP(CSettingsDialog) | ||
11 | ON_BN_CLICKED(IDC_SHOW_NAME_TIPS, OnShowNameTips) | ||
12 | ON_BN_CLICKED(IDC_SHOW_INFO_TIPS, OnShowInfoTips) | ||
13 | ON_CBN_SELENDOK(IDC_LANG, OnLang) | ||
14 | //}}AFX_MSG_MAP | ||
15 | END_MESSAGE_MAP() | ||
16 | |||
17 | CSettingsDialog::CSettingsDialog(CWnd *parent) | ||
18 | : CDialog(IDD_SETTINGS, parent) | ||
19 | { | ||
20 | } | ||
21 | |||
22 | CSettingsDialog::~CSettingsDialog() | ||
23 | { | ||
24 | } | ||
25 | |||
26 | void CSettingsDialog::OnCancel(void) | ||
27 | { | ||
28 | theApp.m_settings.lang[0] = oldlang[0]; | ||
29 | theApp.m_settings.lang[1] = oldlang[1]; | ||
30 | theApp.m_settings.lang[2] = oldlang[2]; | ||
31 | theApp.m_settings.lang[3] = oldlang[3]; | ||
32 | CurLang = oldlangptr; | ||
33 | |||
34 | CDialog::OnCancel(); | ||
35 | } | ||
36 | |||
37 | void CSettingsDialog::OnOK(void) | ||
38 | { | ||
39 | CComboBox *density = (CComboBox *)GetDlgItem(IDC_DENSITY); | ||
40 | if (density != NULL) | ||
41 | theApp.m_settings.density = density->GetCurSel()-3; | ||
42 | CComboBox *file_color = (CComboBox *)GetDlgItem(IDC_FILE_COLOR); | ||
43 | if (file_color != NULL) | ||
44 | theApp.m_settings.file_color = file_color->GetCurSel(); | ||
45 | CComboBox *folder_color = (CComboBox *)GetDlgItem(IDC_FOLDER_COLOR); | ||
46 | if (folder_color != NULL) | ||
47 | theApp.m_settings.folder_color = folder_color->GetCurSel(); | ||
48 | CButton *auto_rescan = (CButton *)GetDlgItem(IDC_AUTO_RESCAN); | ||
49 | if (auto_rescan != NULL) | ||
50 | theApp.m_settings.auto_rescan = auto_rescan->GetCheck(); | ||
51 | CButton *animated = (CButton *)GetDlgItem(IDC_ANIMATED); | ||
52 | if (animated != NULL) | ||
53 | theApp.m_settings.animated_zoom = animated->GetCheck(); | ||
54 | CButton *disable_delete = (CButton *)GetDlgItem(IDC_DISABLE_DELETE); | ||
55 | if (disable_delete != NULL) | ||
56 | theApp.m_settings.disable_delete = disable_delete->GetCheck(); | ||
57 | CSliderCtrl *bias = (CSliderCtrl *)GetDlgItem(IDC_BIAS); | ||
58 | if (bias != NULL) | ||
59 | theApp.m_settings.bias = bias->GetPos()-20; | ||
60 | CButton *save_pos = (CButton *)GetDlgItem(IDC_SAVE_POS); | ||
61 | if (save_pos != NULL) | ||
62 | theApp.m_settings.save_pos = save_pos->GetCheck(); | ||
63 | |||
64 | CButton *show_tips = (CButton *)GetDlgItem(IDC_SHOW_NAME_TIPS); | ||
65 | if (show_tips != NULL) | ||
66 | theApp.m_settings.show_name_tips = show_tips->GetCheck(); | ||
67 | show_tips = (CButton *)GetDlgItem(IDC_SHOW_ROLLOVER_BOX); | ||
68 | if (show_tips != NULL) | ||
69 | theApp.m_settings.rollover_box = show_tips->GetCheck(); | ||
70 | show_tips = (CButton *)GetDlgItem(IDC_SHOW_INFO_TIPS); | ||
71 | if (show_tips != NULL) | ||
72 | theApp.m_settings.show_info_tips = show_tips->GetCheck(); | ||
73 | |||
74 | CButton *tip; | ||
75 | theApp.m_settings.infotip_flags = 0; | ||
76 | CEdit *nametipdelay = (CEdit *)GetDlgItem(IDC_NAMETIP_DELAY); | ||
77 | if (nametipdelay != NULL) { | ||
78 | CString string; | ||
79 | nametipdelay->GetWindowText(string); | ||
80 | theApp.m_settings.nametip_delay = atoi(string); | ||
81 | } | ||
82 | |||
83 | if ((tip = (CButton *)GetDlgItem(IDC_INFOTIP_PATH)) != NULL && tip->GetCheck()) | ||
84 | theApp.m_settings.infotip_flags |= TIP_PATH; | ||
85 | if ((tip = (CButton *)GetDlgItem(IDC_INFOTIP_NAME)) != NULL && tip->GetCheck()) | ||
86 | theApp.m_settings.infotip_flags |= TIP_NAME; | ||
87 | if ((tip = (CButton *)GetDlgItem(IDC_INFOTIP_SIZE)) != NULL && tip->GetCheck()) | ||
88 | theApp.m_settings.infotip_flags |= TIP_SIZE; | ||
89 | if ((tip = (CButton *)GetDlgItem(IDC_INFOTIP_DATE)) != NULL && tip->GetCheck()) | ||
90 | theApp.m_settings.infotip_flags |= TIP_DATE; | ||
91 | if ((tip = (CButton *)GetDlgItem(IDC_INFOTIP_ATTRIB)) != NULL && tip->GetCheck()) | ||
92 | theApp.m_settings.infotip_flags |= TIP_ATTRIB; | ||
93 | if ((tip = (CButton *)GetDlgItem(IDC_INFOTIP_ICON)) != NULL && tip->GetCheck()) | ||
94 | theApp.m_settings.infotip_flags |= TIP_ICON; | ||
95 | CEdit *infotipdelay = (CEdit *)GetDlgItem(IDC_INFOTIP_DELAY); | ||
96 | if (infotipdelay != NULL) { | ||
97 | CString string; | ||
98 | infotipdelay->GetWindowText(string); | ||
99 | theApp.m_settings.infotip_delay = atoi(string); | ||
100 | } | ||
101 | |||
102 | CDialog::OnOK(); | ||
103 | } | ||
104 | |||
105 | void CSettingsDialog::OnShowNameTips(void) | ||
106 | { | ||
107 | CButton *show_tips = (CButton *)GetDlgItem(IDC_SHOW_NAME_TIPS); | ||
108 | if (show_tips != NULL) | ||
109 | EnableNameTipButtons(show_tips->GetCheck()); | ||
110 | } | ||
111 | |||
112 | void CSettingsDialog::OnShowInfoTips(void) | ||
113 | { | ||
114 | CButton *show_tips = (CButton *)GetDlgItem(IDC_SHOW_INFO_TIPS); | ||
115 | if (show_tips != NULL) | ||
116 | EnableInfoTipButtons(show_tips->GetCheck()); | ||
117 | } | ||
118 | |||
119 | void CSettingsDialog::EnableNameTipButtons(BOOL bEnable) | ||
120 | { | ||
121 | CWnd *wnd; | ||
122 | if ((wnd = GetDlgItem(IDC_STATIC_NAMETIP1)) != NULL) | ||
123 | wnd->EnableWindow(bEnable); | ||
124 | if ((wnd = GetDlgItem(IDC_NAMETIP_DELAY)) != NULL) | ||
125 | wnd->EnableWindow(bEnable); | ||
126 | if ((wnd = GetDlgItem(IDC_STATIC_NAMETIP2)) != NULL) | ||
127 | wnd->EnableWindow(bEnable); | ||
128 | } | ||
129 | |||
130 | void CSettingsDialog::EnableInfoTipButtons(BOOL bEnable) | ||
131 | { | ||
132 | CWnd *wnd; | ||
133 | if ((wnd = GetDlgItem(IDC_INFOTIP_PATH)) != NULL) | ||
134 | wnd->EnableWindow(bEnable); | ||
135 | if ((wnd = GetDlgItem(IDC_INFOTIP_NAME)) != NULL) | ||
136 | wnd->EnableWindow(bEnable); | ||
137 | if ((wnd = GetDlgItem(IDC_INFOTIP_DATE)) != NULL) | ||
138 | wnd->EnableWindow(bEnable); | ||
139 | if ((wnd = GetDlgItem(IDC_INFOTIP_SIZE)) != NULL) | ||
140 | wnd->EnableWindow(bEnable); | ||
141 | if ((wnd = GetDlgItem(IDC_INFOTIP_ATTRIB)) != NULL) | ||
142 | wnd->EnableWindow(bEnable); | ||
143 | if ((wnd = GetDlgItem(IDC_INFOTIP_ICON)) != NULL) | ||
144 | wnd->EnableWindow(bEnable); | ||
145 | if ((wnd = GetDlgItem(IDC_STATIC_INFOTIP1)) != NULL) | ||
146 | wnd->EnableWindow(bEnable); | ||
147 | if ((wnd = GetDlgItem(IDC_INFOTIP_DELAY)) != NULL) | ||
148 | wnd->EnableWindow(bEnable); | ||
149 | if ((wnd = GetDlgItem(IDC_STATIC_INFOTIP2)) != NULL) | ||
150 | wnd->EnableWindow(bEnable); | ||
151 | } | ||
152 | |||
153 | void CSettingsDialog::OnLang(void) | ||
154 | { | ||
155 | CComboBox *lang = (CComboBox *)GetDlgItem(IDC_LANG); | ||
156 | if (lang == NULL) return; | ||
157 | int index = lang->GetCurSel(); | ||
158 | theApp.m_settings.lang[0] = Langs[index].abbrev[0]; | ||
159 | theApp.m_settings.lang[1] = Langs[index].abbrev[1]; | ||
160 | theApp.m_settings.lang[2] = '\0'; | ||
161 | theApp.m_settings.lang[3] = '\0'; | ||
162 | CurLang = Langs[index].text; | ||
163 | UpdateDialogForNewLanguage(); | ||
164 | } | ||
165 | |||
166 | void CSettingsDialog::UpdateDialogForNewLanguage(void) | ||
167 | { | ||
168 | CComboBox *lang = (CComboBox *)GetDlgItem(IDC_LANG); | ||
169 | if (lang != NULL) lang->ResetContent(); | ||
170 | CComboBox *density = (CComboBox *)GetDlgItem(IDC_DENSITY); | ||
171 | if (density != NULL) density->ResetContent(); | ||
172 | CComboBox *file_color = (CComboBox *)GetDlgItem(IDC_FILE_COLOR); | ||
173 | if (file_color != NULL) file_color->ResetContent(); | ||
174 | CComboBox *folder_color = (CComboBox *)GetDlgItem(IDC_FOLDER_COLOR); | ||
175 | if (folder_color != NULL) folder_color->ResetContent(); | ||
176 | |||
177 | int i; | ||
178 | |||
179 | SetWindowText(CurLang->settings); | ||
180 | SetDlgItemText(IDOK, CurLang->ok); | ||
181 | SetDlgItemText(IDCANCEL, CurLang->cancel); | ||
182 | |||
183 | SetDlgItemText(IDC_STATIC_LAYOUT, CurLang->layout); | ||
184 | SetDlgItemText(IDC_STATIC_DENSITY, CurLang->density); | ||
185 | SetDlgItemText(IDC_STATIC_BIAS, CurLang->bias); | ||
186 | SetDlgItemText(IDC_STATIC_HORZ, CurLang->horz); | ||
187 | SetDlgItemText(IDC_STATIC_EQUAL, CurLang->equal); | ||
188 | SetDlgItemText(IDC_STATIC_VERT, CurLang->vert); | ||
189 | SetDlgItemText(IDC_STATIC_DISPLAYCOLORS, CurLang->displaycolors); | ||
190 | SetDlgItemText(IDC_STATIC_FILES, CurLang->files); | ||
191 | SetDlgItemText(IDC_STATIC_FOLDERS, CurLang->folders); | ||
192 | SetDlgItemText(IDC_STATIC_TOOLTIPS, CurLang->tooltips); | ||
193 | SetDlgItemText(IDC_STATIC_MISCOPTIONS, CurLang->miscoptions); | ||
194 | SetDlgItemText(IDC_SHOW_NAME_TIPS, CurLang->shownametips); | ||
195 | SetDlgItemText(IDC_SHOW_ROLLOVER_BOX, CurLang->showrolloverbox); | ||
196 | SetDlgItemText(IDC_SHOW_INFO_TIPS, CurLang->showinfotips); | ||
197 | SetDlgItemText(IDC_INFOTIP_PATH, CurLang->fullpath); | ||
198 | SetDlgItemText(IDC_INFOTIP_NAME, CurLang->filename); | ||
199 | SetDlgItemText(IDC_INFOTIP_ICON, CurLang->icon); | ||
200 | SetDlgItemText(IDC_INFOTIP_DATE, CurLang->datetime); | ||
201 | SetDlgItemText(IDC_INFOTIP_SIZE, CurLang->filesize); | ||
202 | SetDlgItemText(IDC_INFOTIP_ATTRIB, CurLang->attrib); | ||
203 | SetDlgItemText(IDC_STATIC_NAMETIP1, CurLang->delay); | ||
204 | SetDlgItemText(IDC_STATIC_NAMETIP2, CurLang->msec); | ||
205 | SetDlgItemText(IDC_STATIC_INFOTIP1, CurLang->delay); | ||
206 | SetDlgItemText(IDC_STATIC_INFOTIP2, CurLang->msec); | ||
207 | SetDlgItemText(IDC_AUTO_RESCAN, CurLang->autorescan); | ||
208 | SetDlgItemText(IDC_DISABLE_DELETE, CurLang->disabledelete); | ||
209 | SetDlgItemText(IDC_ANIMATED, CurLang->animatedzoom); | ||
210 | SetDlgItemText(IDC_SAVE_POS, CurLang->savepos); | ||
211 | |||
212 | if (lang != NULL) { | ||
213 | for (i = 0; Langs[i].name != NULL; i++) { | ||
214 | lang->AddString(Langs[i].name); | ||
215 | if (Langs[i].abbrev[0] == theApp.m_settings.lang[0] | ||
216 | && Langs[i].abbrev[1] == theApp.m_settings.lang[1]) | ||
217 | lang->SetCurSel(i); | ||
218 | } | ||
219 | } | ||
220 | |||
221 | if (density != NULL) { | ||
222 | for (i = 0; i < 6; i++) | ||
223 | density->AddString(CurLang->densitynames[i]); | ||
224 | density->SetCurSel(theApp.m_settings.density+3); | ||
225 | } | ||
226 | if (file_color != NULL) { | ||
227 | for (i = 0; i < 12; i++) | ||
228 | file_color->AddString(CurLang->colornames[i]); | ||
229 | file_color->SetCurSel(theApp.m_settings.file_color); | ||
230 | } | ||
231 | if (folder_color != NULL) { | ||
232 | for (i = 0; i < 12; i++) | ||
233 | folder_color->AddString(CurLang->colornames[i]); | ||
234 | folder_color->SetCurSel(theApp.m_settings.folder_color); | ||
235 | } | ||
236 | CButton *auto_rescan = (CButton *)GetDlgItem(IDC_AUTO_RESCAN); | ||
237 | if (auto_rescan != NULL) | ||
238 | auto_rescan->SetCheck(theApp.m_settings.auto_rescan); | ||
239 | CButton *animated = (CButton *)GetDlgItem(IDC_ANIMATED); | ||
240 | if (animated != NULL) | ||
241 | animated->SetCheck(theApp.m_settings.animated_zoom); | ||
242 | CButton *disable_delete = (CButton *)GetDlgItem(IDC_DISABLE_DELETE); | ||
243 | if (disable_delete != NULL) | ||
244 | disable_delete->SetCheck(theApp.m_settings.disable_delete); | ||
245 | CButton *save_pos = (CButton *)GetDlgItem(IDC_SAVE_POS); | ||
246 | if (save_pos != NULL) | ||
247 | save_pos->SetCheck(theApp.m_settings.save_pos); | ||
248 | |||
249 | CButton *show_name_tips = (CButton *)GetDlgItem(IDC_SHOW_NAME_TIPS); | ||
250 | if (show_name_tips != NULL) | ||
251 | show_name_tips->SetCheck(theApp.m_settings.show_name_tips); | ||
252 | show_name_tips = (CButton *)GetDlgItem(IDC_SHOW_ROLLOVER_BOX); | ||
253 | if (show_name_tips != NULL) | ||
254 | show_name_tips->SetCheck(theApp.m_settings.rollover_box); | ||
255 | |||
256 | CButton *tip; | ||
257 | CButton *show_info_tips = (CButton *)GetDlgItem(IDC_SHOW_INFO_TIPS); | ||
258 | if (show_info_tips != NULL) | ||
259 | show_info_tips->SetCheck(theApp.m_settings.show_info_tips); | ||
260 | if ((tip = (CButton *)GetDlgItem(IDC_INFOTIP_PATH)) != NULL) | ||
261 | tip->SetCheck((theApp.m_settings.infotip_flags & TIP_PATH) != 0); | ||
262 | if ((tip = (CButton *)GetDlgItem(IDC_INFOTIP_NAME)) != NULL) | ||
263 | tip->SetCheck((theApp.m_settings.infotip_flags & TIP_NAME) != 0); | ||
264 | if ((tip = (CButton *)GetDlgItem(IDC_INFOTIP_DATE)) != NULL) | ||
265 | tip->SetCheck((theApp.m_settings.infotip_flags & TIP_DATE) != 0); | ||
266 | if ((tip = (CButton *)GetDlgItem(IDC_INFOTIP_SIZE)) != NULL) | ||
267 | tip->SetCheck((theApp.m_settings.infotip_flags & TIP_SIZE) != 0); | ||
268 | if ((tip = (CButton *)GetDlgItem(IDC_INFOTIP_ATTRIB)) != NULL) | ||
269 | tip->SetCheck((theApp.m_settings.infotip_flags & TIP_ATTRIB) != 0); | ||
270 | if ((tip = (CButton *)GetDlgItem(IDC_INFOTIP_ICON)) != NULL) | ||
271 | tip->SetCheck((theApp.m_settings.infotip_flags & TIP_ICON) != 0); | ||
272 | |||
273 | CEdit *tipdelay = (CEdit *)GetDlgItem(IDC_NAMETIP_DELAY); | ||
274 | if (tipdelay != NULL) { | ||
275 | CString string; | ||
276 | string.Format("%u", theApp.m_settings.nametip_delay); | ||
277 | tipdelay->SetWindowText(string); | ||
278 | } | ||
279 | tipdelay = (CEdit *)GetDlgItem(IDC_INFOTIP_DELAY); | ||
280 | if (tipdelay != NULL) { | ||
281 | CString string; | ||
282 | string.Format("%u", theApp.m_settings.infotip_delay); | ||
283 | tipdelay->SetWindowText(string); | ||
284 | } | ||
285 | EnableNameTipButtons(theApp.m_settings.show_name_tips); | ||
286 | EnableInfoTipButtons(theApp.m_settings.show_info_tips); | ||
287 | |||
288 | CSliderCtrl *bias = (CSliderCtrl *)GetDlgItem(IDC_BIAS); | ||
289 | if (bias != NULL) { | ||
290 | bias->SetRange(0, 40, 0); | ||
291 | bias->SetPos(theApp.m_settings.bias+20); | ||
292 | bias->SetTicFreq(5); | ||
293 | } | ||
294 | } | ||
295 | |||
296 | BOOL CSettingsDialog::OnInitDialog() | ||
297 | { | ||
298 | oldlang[0] = theApp.m_settings.lang[0]; | ||
299 | oldlang[1] = theApp.m_settings.lang[1]; | ||
300 | oldlang[2] = theApp.m_settings.lang[2]; | ||
301 | oldlang[3] = theApp.m_settings.lang[3]; | ||
302 | oldlangptr = CurLang; | ||
303 | |||
304 | UpdateDialogForNewLanguage(); | ||
305 | |||
306 | CDialog::OnInitDialog(); | ||
307 | |||
308 | return TRUE; | ||
309 | } | ||
310 | |||
diff --git a/SetupDlg.h b/SetupDlg.h new file mode 100644 index 0000000..f181d21 --- /dev/null +++ b/SetupDlg.h | |||
@@ -0,0 +1,32 @@ | |||
1 | |||
2 | #ifndef SETTINGSDIALOG_H | ||
3 | #define SETTINGSDIALOG_H | ||
4 | |||
5 | class CSettingsDialog : public CDialog { | ||
6 | public: | ||
7 | CSettingsDialog(CWnd *parent = NULL); | ||
8 | DECLARE_DYNCREATE(CSettingsDialog) | ||
9 | virtual ~CSettingsDialog(); | ||
10 | |||
11 | protected: | ||
12 | //{{AFX_MSG(CSettingsDialog) | ||
13 | virtual void OnOK(); | ||
14 | virtual void OnCancel(); | ||
15 | virtual void OnShowNameTips(); | ||
16 | virtual void OnShowInfoTips(); | ||
17 | virtual void OnLang(); | ||
18 | //}}AFX_MSG | ||
19 | DECLARE_MESSAGE_MAP() | ||
20 | |||
21 | void UpdateDialogForNewLanguage(void); | ||
22 | |||
23 | virtual BOOL OnInitDialog(); | ||
24 | void EnableNameTipButtons(BOOL bEnable); | ||
25 | void EnableInfoTipButtons(BOOL bEnable); | ||
26 | |||
27 | protected: | ||
28 | char oldlang[4]; | ||
29 | Lang *oldlangptr; | ||
30 | }; | ||
31 | |||
32 | #endif | ||
diff --git a/SpaceMonger.cpp b/SpaceMonger.cpp new file mode 100644 index 0000000..e3df885 --- /dev/null +++ b/SpaceMonger.cpp | |||
@@ -0,0 +1,527 @@ | |||
1 | |||
2 | #include "StdAfx.h" | ||
3 | #include "SpaceMonger.h" | ||
4 | #include "Lang.h" | ||
5 | #include "MainFrm.h" | ||
6 | #include "FolderTree.h" | ||
7 | #include "FolderView.h" | ||
8 | #include "DriveDialog.h" | ||
9 | #include "SetupDlg.h" | ||
10 | #include "TipWnd.h" | ||
11 | #include "AboutDialog.h" | ||
12 | |||
13 | ///////////////////////////////////////////////////////////////////////////// | ||
14 | // The primary CSpaceMonger object | ||
15 | |||
16 | CSpaceMonger theApp; | ||
17 | |||
18 | ///////////////////////////////////////////////////////////////////////////// | ||
19 | // CApp | ||
20 | |||
21 | BEGIN_MESSAGE_MAP(CSpaceMonger, CWinApp) | ||
22 | //{{AFX_MSG_MAP(CSpaceMonger) | ||
23 | ON_COMMAND(ID_APP_ABOUT, OnAbout) | ||
24 | ON_COMMAND(ID_APP_EXIT, OnAppExit) | ||
25 | ON_COMMAND(ID_FILE_OPEN, OnFileOpen) | ||
26 | ON_COMMAND(ID_FILE_REFRESH, OnFileRefresh) | ||
27 | ON_COMMAND(ID_FILE_RUN, OnFileRun) | ||
28 | ON_COMMAND(ID_FILE_DELETE, OnFileDelete) | ||
29 | ON_COMMAND(ID_FILE_PROPERTIES, OnFileProperties) | ||
30 | ON_COMMAND(ID_VIEW_ZOOM_FULL, OnZoomFull) | ||
31 | ON_COMMAND(ID_VIEW_ZOOM_IN, OnZoomIn) | ||
32 | ON_COMMAND(ID_VIEW_ZOOM_OUT, OnZoomOut) | ||
33 | ON_COMMAND(ID_VIEW_FREE, OnShowFree) | ||
34 | ON_COMMAND(ID_SETTINGS, OnSettings) | ||
35 | //}}AFX_MSG_MAP | ||
36 | ON_UPDATE_COMMAND_UI_RANGE(100, 41000, OnIgnoreUpdate) | ||
37 | END_MESSAGE_MAP() | ||
38 | |||
39 | CSpaceMonger::CSpaceMonger() | ||
40 | { | ||
41 | m_document = NULL; | ||
42 | } | ||
43 | |||
44 | CSpaceMonger::~CSpaceMonger() | ||
45 | { | ||
46 | } | ||
47 | |||
48 | BOOL CSpaceMonger::InitInstance() | ||
49 | { | ||
50 | int i; | ||
51 | |||
52 | InitTipWnd(AfxGetInstanceHandle()); | ||
53 | |||
54 | // Load in the settings from the Registry. If there were no settings, | ||
55 | // we load defaults. Once we've got them, save them back, which sounds | ||
56 | // odd, but it will end up creating the necessary entries if they don't | ||
57 | // exist. | ||
58 | m_settings.Load(); | ||
59 | m_settings.Save(); | ||
60 | |||
61 | int showcmd = m_settings.showcmd; | ||
62 | RECT rect = m_settings.rect; | ||
63 | if (!m_settings.save_pos) { | ||
64 | showcmd = SW_SHOWNORMAL; | ||
65 | rect.top = rect.left = CW_USEDEFAULT; | ||
66 | rect.right = rect.bottom = 0; // This is actually CW_USEDEFAULT because of a bug | ||
67 | // in CFrameWnd::Create() | ||
68 | } | ||
69 | |||
70 | // Create the main window | ||
71 | m_mainframe = new CMainFrame; | ||
72 | m_mainframe->CFrameWnd::Create(NULL, "SpaceMonger", WS_OVERLAPPEDWINDOW, rect); | ||
73 | m_pMainWnd = m_mainframe; | ||
74 | |||
75 | // Create the one and only document | ||
76 | m_document = new CFolderTree; | ||
77 | m_document->Create(); | ||
78 | |||
79 | // Create the main document view | ||
80 | m_view = new CFolderView; | ||
81 | m_view->Create(m_mainframe, 1); | ||
82 | m_view->SetDocument(m_document); | ||
83 | m_view->SetFocus(); | ||
84 | |||
85 | // Load in the animations | ||
86 | static int anim_name[4] = { | ||
87 | IDB_SCAN1, IDB_SCAN2, IDB_SCAN3, IDB_SCAN4, | ||
88 | }; | ||
89 | for (i = 0; i < 4; i++) | ||
90 | m_scan_animation[i] = (HBITMAP)LoadImage(m_hInstance, | ||
91 | MAKEINTRESOURCE(anim_name[i]), IMAGE_BITMAP, 128, 48, | ||
92 | LR_LOADTRANSPARENT|LR_LOADMAP3DCOLORS); | ||
93 | |||
94 | m_mainframe->ShowWindow(showcmd); | ||
95 | m_mainframe->UpdateWindow(); | ||
96 | m_mainframe->RecalcLayout(); | ||
97 | |||
98 | return(TRUE); | ||
99 | } | ||
100 | |||
101 | int CSpaceMonger::ExitInstance() | ||
102 | { | ||
103 | m_settings.Save(); | ||
104 | |||
105 | // m_pMainWnd is auto-deleted by the framework | ||
106 | delete m_view; | ||
107 | delete m_document; | ||
108 | |||
109 | return(0); | ||
110 | } | ||
111 | |||
112 | void CSpaceMonger::OnAppExit(void) | ||
113 | { | ||
114 | CWinApp::OnAppExit(); | ||
115 | } | ||
116 | |||
117 | void CSpaceMonger::OnFileOpen(void) | ||
118 | { | ||
119 | CDriveDialog drvdialog; | ||
120 | int drive = drvdialog.DoModal(); | ||
121 | if (drive == -1) return; | ||
122 | |||
123 | CFolderTree *ft = (CFolderTree *)m_document; | ||
124 | ft->m_path.Format("%c:\\", (char)(drive + 'A')); | ||
125 | OnFileRefresh(); | ||
126 | } | ||
127 | |||
128 | void CSpaceMonger::OnFileRefresh(void) | ||
129 | { | ||
130 | CFolderTree *ft = (CFolderTree *)m_document; | ||
131 | |||
132 | m_mainframe->EnableWindow(0); | ||
133 | m_view->SetDocument(NULL); | ||
134 | m_view->UpdateWindow(); | ||
135 | |||
136 | ((CFolderView *)m_view)->zoomlevel = 0; | ||
137 | ft->LoadTree(ft->m_path, 1, m_mainframe); | ||
138 | m_view->SetDocument(m_document); | ||
139 | ft->UpdateAllViews(); | ||
140 | m_mainframe->EnableWindow(1); | ||
141 | } | ||
142 | |||
143 | void CSpaceMonger::OnFileRun(void) | ||
144 | { | ||
145 | CFolderView *fv = (CFolderView *)m_view; | ||
146 | CFolderTree *ft = (CFolderTree *)m_document; | ||
147 | |||
148 | if (fv == NULL || ft == NULL || fv->selected == NULL) return; | ||
149 | |||
150 | CString title, path; | ||
151 | if (ft != NULL) title += ft->m_path; | ||
152 | fv->BuildTitleReverse(fv->selected->source, title); | ||
153 | path = title; | ||
154 | title += fv->selected->source->names[fv->selected->index]; | ||
155 | |||
156 | ShellExecute(NULL, NULL, title, NULL, path, SW_SHOWDEFAULT); | ||
157 | } | ||
158 | |||
159 | void CSpaceMonger::OnFileDelete(void) | ||
160 | { | ||
161 | CFolderView *fv = (CFolderView *)m_view; | ||
162 | CFolderTree *ft = (CFolderTree *)m_document; | ||
163 | |||
164 | if (fv == NULL || ft == NULL || fv->selected == NULL) return; | ||
165 | |||
166 | CString title; | ||
167 | if (ft != NULL) title += ft->m_path; | ||
168 | fv->BuildTitleReverse(fv->selected->source, title); | ||
169 | title += fv->selected->source->names[fv->selected->index]; | ||
170 | BOOL isfolder; | ||
171 | if (fv->selected->source->children[fv->selected->index] != NULL) | ||
172 | isfolder = 1; | ||
173 | else isfolder = 0; | ||
174 | |||
175 | char source[MAX_PATH+8]; | ||
176 | int len; | ||
177 | |||
178 | strcpy(source, title); | ||
179 | len = strlen(source); | ||
180 | source[len] = '\0'; | ||
181 | source[len+1] = '\0'; | ||
182 | |||
183 | SHFILEOPSTRUCT fop; | ||
184 | fop.hwnd = m_mainframe->m_hWnd; | ||
185 | fop.wFunc = FO_DELETE; | ||
186 | fop.pFrom = source; | ||
187 | fop.pTo = NULL; | ||
188 | fop.fFlags = FOF_SIMPLEPROGRESS|FOF_ALLOWUNDO|FOF_NOCONFIRMATION; | ||
189 | fop.fAnyOperationsAborted = 0; | ||
190 | fop.hNameMappings = NULL; | ||
191 | fop.lpszProgressTitle = CurLang->deleting; | ||
192 | |||
193 | if (SHFileOperation(&fop) != 0 || fop.fAnyOperationsAborted) { | ||
194 | AfxMessageBox("Windows failed to delete file."); | ||
195 | return; | ||
196 | } | ||
197 | |||
198 | if (isfolder) { | ||
199 | delete fv->selected->source->children[fv->selected->index]; | ||
200 | fv->selected->source->children[fv->selected->index] = NULL; | ||
201 | } | ||
202 | ui64 subsize = fv->selected->source->sizes[fv->selected->index]; | ||
203 | CFolder *folder = fv->selected->source; | ||
204 | if (isfolder) folder->size_children -= subsize; | ||
205 | else folder->size_self -= subsize; | ||
206 | folder = folder->parent; | ||
207 | while (folder != NULL) { | ||
208 | folder->size_children -= subsize; | ||
209 | folder = folder->parent; | ||
210 | } | ||
211 | fv->selected->source->sizes[fv->selected->index] = 0; | ||
212 | |||
213 | if (m_settings.auto_rescan) | ||
214 | OnFileRefresh(); | ||
215 | else | ||
216 | fv->OnUpdate(m_document); | ||
217 | } | ||
218 | |||
219 | void CSpaceMonger::OnZoomIn(void) | ||
220 | { | ||
221 | ((CFolderView *)m_view)->ZoomIn(((CFolderView *)m_view)->selected); | ||
222 | } | ||
223 | |||
224 | void CSpaceMonger::OnZoomOut(void) | ||
225 | { | ||
226 | ((CFolderView *)m_view)->ZoomOut(); | ||
227 | } | ||
228 | |||
229 | void CSpaceMonger::OnZoomFull(void) | ||
230 | { | ||
231 | ((CFolderView *)m_view)->ZoomFull(); | ||
232 | } | ||
233 | |||
234 | void CSpaceMonger::OnShowFree(void) | ||
235 | { | ||
236 | CFolderView *fv = (CFolderView *)m_view; | ||
237 | CMainFrame *mf = (CMainFrame *)m_mainframe; | ||
238 | if (fv == NULL || mf == NULL) return; | ||
239 | |||
240 | BOOL showfreespace = !fv->showfreespace; | ||
241 | mf->m_toolbar.EnableState(CMainToolBar::ViewFree, showfreespace); | ||
242 | fv->ShowFreeSpace(showfreespace); | ||
243 | } | ||
244 | |||
245 | void CSpaceMonger::OnSettings(void) | ||
246 | { | ||
247 | CSettingsDialog settingsdialog; | ||
248 | if (settingsdialog.DoModal() == IDOK) { | ||
249 | m_settings.Save(); | ||
250 | if (m_view != NULL && m_document != NULL) { | ||
251 | m_view->OnUpdate(m_document); | ||
252 | ((CFolderView *)m_view)->UpdateTitleBar(); | ||
253 | } | ||
254 | ((CMainFrame *)m_mainframe)->m_toolbar.Reload(); | ||
255 | } | ||
256 | } | ||
257 | |||
258 | void CSpaceMonger::OnFileProperties(void) | ||
259 | { | ||
260 | CFolderView *fv = (CFolderView *)m_view; | ||
261 | CFolderTree *ft = (CFolderTree *)m_document; | ||
262 | |||
263 | if (fv == NULL || ft == NULL || fv->selected == NULL) return; | ||
264 | |||
265 | CString path = ft->m_path; | ||
266 | fv->BuildTitleReverse(fv->selected->source, path); | ||
267 | path += fv->selected->source->names[fv->selected->index]; | ||
268 | |||
269 | SHELLEXECUTEINFO si; | ||
270 | ZeroMemory(&si, sizeof(si)); | ||
271 | si.cbSize = sizeof(si); | ||
272 | si.hwnd = fv->GetSafeHwnd(); | ||
273 | si.nShow = SW_SHOW; | ||
274 | si.fMask = SEE_MASK_INVOKEIDLIST; | ||
275 | si.lpVerb = _T("properties"); | ||
276 | si.lpFile = (LPCTSTR)path; | ||
277 | ShellExecuteEx(&si); | ||
278 | } | ||
279 | |||
280 | void CSpaceMonger::OnAbout() | ||
281 | { | ||
282 | CAboutDialog about; | ||
283 | about.DoModal(); | ||
284 | } | ||
285 | |||
286 | void CSpaceMonger::OnIgnoreUpdate(CCmdUI *ui) | ||
287 | { | ||
288 | GeneralIgnoreUpdate(ui); | ||
289 | } | ||
290 | |||
291 | void GeneralIgnoreUpdate(CCmdUI *ui) | ||
292 | { | ||
293 | CFolderView *fv = (CFolderView *)theApp.m_view; | ||
294 | CDisplayFolder *cur = fv->selected; | ||
295 | int zoom = fv->zoomlevel; | ||
296 | |||
297 | if (ui->m_nID == ID_FILE_DELETE) { | ||
298 | if (theApp.m_settings.disable_delete || cur == NULL) | ||
299 | ui->Enable(0); | ||
300 | } | ||
301 | else if (ui->m_nID == ID_FILE_RUN) { | ||
302 | if (cur == NULL) ui->Enable(0); | ||
303 | } | ||
304 | else if (ui->m_nID == ID_FILE_PROPERTIES) { | ||
305 | if (cur == NULL) ui->Enable(0); | ||
306 | } | ||
307 | else if (ui->m_nID == ID_FILE_REFRESH) { | ||
308 | CFolderTree *ft = (CFolderTree *)theApp.m_document; | ||
309 | if (ft == NULL || ft->GetRoot() == NULL) ui->Enable(0); | ||
310 | } | ||
311 | else if (ui->m_nID == ID_VIEW_FREE) { | ||
312 | CFolderTree *ft = (CFolderTree *)theApp.m_document; | ||
313 | ui->SetCheck(fv->showfreespace); | ||
314 | if (ft == NULL || ft->GetRoot() == NULL) ui->Enable(0); | ||
315 | } | ||
316 | else if (ui->m_nID == ID_VIEW_ZOOM_IN) { | ||
317 | if (cur == NULL || (cur->flags & 1) == 0) | ||
318 | ui->Enable(0); | ||
319 | } | ||
320 | else if (ui->m_nID == ID_VIEW_ZOOM_OUT || ui->m_nID == ID_VIEW_ZOOM_FULL) { | ||
321 | if (zoom == 0) ui->Enable(0); | ||
322 | } | ||
323 | } | ||
324 | |||
325 | ///////////////////////////////////////////////////////////////////////////// | ||
326 | // Application Settings | ||
327 | // | ||
328 | |||
329 | void CCurrentSettings::Reset(void) | ||
330 | { | ||
331 | density = 0; | ||
332 | file_color = 0; | ||
333 | folder_color = 0; | ||
334 | auto_rescan = 0; | ||
335 | animated_zoom = 1; | ||
336 | disable_delete = 0; | ||
337 | bias = 0; | ||
338 | show_name_tips = 1; | ||
339 | nametip_delay = 125; | ||
340 | show_info_tips = 1; | ||
341 | rollover_box = 0; | ||
342 | infotip_flags = TIP_DATE|TIP_SIZE|TIP_ICON; | ||
343 | infotip_delay = 250; | ||
344 | rect.left = rect.right = rect.top = rect.bottom = CW_USEDEFAULT; | ||
345 | showcmd = SW_SHOWNORMAL; | ||
346 | save_pos = 0; | ||
347 | lang[0] = 'u'; | ||
348 | lang[1] = 's'; | ||
349 | lang[2] = '\0'; | ||
350 | lang[3] = '\0'; | ||
351 | } | ||
352 | |||
353 | void CCurrentSettings::Load(void) | ||
354 | { | ||
355 | HKEY key; | ||
356 | Reset(); | ||
357 | if (RegOpenKey(HKEY_CURRENT_USER, "Software\\65\\SpaceMonger\\1.3", &key) != ERROR_SUCCESS) | ||
358 | return; | ||
359 | |||
360 | DWORD size = sizeof(density); | ||
361 | DWORD type; | ||
362 | RegQueryValueEx(key, "density", NULL, &type, (unsigned char *)&density, &size); | ||
363 | size = sizeof(file_color); | ||
364 | RegQueryValueEx(key, "file_color", NULL, &type, (unsigned char *)&file_color, &size); | ||
365 | size = sizeof(folder_color); | ||
366 | RegQueryValueEx(key, "folder_color", NULL, &type, (unsigned char *)&folder_color, &size); | ||
367 | size = sizeof(auto_rescan); | ||
368 | RegQueryValueEx(key, "auto_rescan", NULL, &type, (unsigned char *)&auto_rescan, &size); | ||
369 | size = sizeof(animated_zoom); | ||
370 | RegQueryValueEx(key, "animated_zoom", NULL, &type, (unsigned char *)&animated_zoom, &size); | ||
371 | size = sizeof(disable_delete); | ||
372 | RegQueryValueEx(key, "disable_delete", NULL, &type, (unsigned char *)&disable_delete, &size); | ||
373 | size = sizeof(save_pos); | ||
374 | RegQueryValueEx(key, "save_pos", NULL, &type, (unsigned char *)&save_pos, &size); | ||
375 | size = sizeof(bias); | ||
376 | RegQueryValueEx(key, "bias", NULL, &type, (unsigned char *)&bias, &size); | ||
377 | size = sizeof(show_name_tips); | ||
378 | RegQueryValueEx(key, "show_name_tips", NULL, &type, (unsigned char *)&show_name_tips, &size); | ||
379 | size = sizeof(rollover_box); | ||
380 | RegQueryValueEx(key, "show_rollover_box", NULL, &type, (unsigned char *)&rollover_box, &size); | ||
381 | size = sizeof(show_info_tips); | ||
382 | RegQueryValueEx(key, "show_info_tips", NULL, &type, (unsigned char *)&show_info_tips, &size); | ||
383 | size = sizeof(nametip_delay); | ||
384 | RegQueryValueEx(key, "nametip_delay", NULL, &type, (unsigned char *)&nametip_delay, &size); | ||
385 | size = sizeof(infotip_flags); | ||
386 | RegQueryValueEx(key, "infotip_flags", NULL, &type, (unsigned char *)&infotip_flags, &size); | ||
387 | size = sizeof(infotip_delay); | ||
388 | RegQueryValueEx(key, "infotip_delay", NULL, &type, (unsigned char *)&infotip_delay, &size); | ||
389 | size = sizeof(rect.left); | ||
390 | RegQueryValueEx(key, "window_rect.left", NULL, &type, (unsigned char *)&rect.left, &size); | ||
391 | size = sizeof(rect.top); | ||
392 | RegQueryValueEx(key, "window_rect.top", NULL, &type, (unsigned char *)&rect.top, &size); | ||
393 | size = sizeof(rect.right); | ||
394 | RegQueryValueEx(key, "window_rect.right", NULL, &type, (unsigned char *)&rect.right, &size); | ||
395 | size = sizeof(rect.bottom); | ||
396 | RegQueryValueEx(key, "window_rect.bottom", NULL, &type, (unsigned char *)&rect.bottom, &size); | ||
397 | size = sizeof(showcmd); | ||
398 | RegQueryValueEx(key, "window_showcmd", NULL, &type, (unsigned char *)&showcmd, &size); | ||
399 | size = sizeof(lang); | ||
400 | RegQueryValueEx(key, "lang", NULL, &type, (unsigned char *)&lang, &size); | ||
401 | RegCloseKey(key); | ||
402 | |||
403 | if (density < -3) density = -3; | ||
404 | if (density > 3) density = 3; | ||
405 | |||
406 | if (file_color < 0 || file_color > 12) file_color = 0; | ||
407 | if (folder_color < 0 || folder_color > 12) folder_color = 0; | ||
408 | |||
409 | auto_rescan = !!auto_rescan; | ||
410 | animated_zoom = !!animated_zoom; | ||
411 | disable_delete = !!disable_delete; | ||
412 | save_pos = !!save_pos; | ||
413 | |||
414 | rollover_box = !!rollover_box; | ||
415 | |||
416 | show_name_tips = !!show_name_tips; | ||
417 | if (nametip_delay < 0) nametip_delay = 0; | ||
418 | if (nametip_delay > 99999) nametip_delay = 99999; | ||
419 | |||
420 | show_info_tips = !!show_info_tips; | ||
421 | infotip_flags &= TIP_PATH|TIP_NAME|TIP_ICON|TIP_DATE|TIP_SIZE|TIP_ATTRIB; | ||
422 | if (infotip_delay < 0) infotip_delay = 0; | ||
423 | if (infotip_delay > 99999) infotip_delay = 99999; | ||
424 | |||
425 | if (bias < -20) bias = -20; | ||
426 | if (bias > 20) bias = 20; | ||
427 | |||
428 | // Ensure that the window's provided rectangle has at least a little of | ||
429 | // its area visible to the end-user. | ||
430 | int scrnwidth = GetSystemMetrics(SM_CXSCREEN), scrnheight = GetSystemMetrics(SM_CYSCREEN); | ||
431 | if (rect.top > rect.bottom) { | ||
432 | int temp = rect.top; | ||
433 | rect.top = rect.bottom; | ||
434 | rect.bottom = temp; | ||
435 | } | ||
436 | if (rect.left > rect.right) { | ||
437 | int temp = rect.left; | ||
438 | rect.left = rect.right; | ||
439 | rect.right = temp; | ||
440 | } | ||
441 | if (rect.right - rect.left > scrnwidth) rect.right = rect.left + scrnwidth; | ||
442 | if (rect.bottom - rect.top > scrnheight) rect.bottom = rect.top + scrnheight; | ||
443 | if (rect.top > scrnheight-8) | ||
444 | rect.bottom -= (rect.top - (scrnheight-8)), rect.top = scrnheight-8; | ||
445 | if (rect.left > scrnwidth-8) | ||
446 | rect.right -= (rect.left - (scrnwidth-8)), rect.left = scrnwidth-8; | ||
447 | if (rect.right < 8) | ||
448 | rect.left += (8-rect.right), rect.right = 8; | ||
449 | if (rect.bottom < 8) | ||
450 | rect.top += (8-rect.bottom), rect.bottom = 8; | ||
451 | |||
452 | // Ensure that the window's placement is comprehensible. | ||
453 | if (showcmd != SW_SHOWMINIMIZED && showcmd != SW_SHOWMAXIMIZED | ||
454 | && showcmd != SW_SHOWNORMAL) | ||
455 | showcmd = SW_SHOWNORMAL; | ||
456 | |||
457 | // Find the language in the list of languages. If it's not found, | ||
458 | // try US English. | ||
459 | lang[0] = tolower(lang[0]); | ||
460 | lang[1] = tolower(lang[1]); | ||
461 | lang[2] = '\0'; | ||
462 | lang[3] = '\0'; | ||
463 | int i; | ||
464 | CurLang = NULL; | ||
465 | for (i = 0; Langs[i].name != NULL; i++) { | ||
466 | if (lang[0] == Langs[i].abbrev[0] && lang[1] == Langs[i].abbrev[1]) { | ||
467 | CurLang = Langs[i].text; | ||
468 | break; | ||
469 | } | ||
470 | } | ||
471 | if (CurLang == NULL) { | ||
472 | CurLang = Langs[0].text; | ||
473 | lang[0] = Langs[0].abbrev[0]; | ||
474 | lang[1] = Langs[0].abbrev[1]; | ||
475 | lang[2] = '\0'; | ||
476 | lang[3] = '\0'; | ||
477 | } | ||
478 | } | ||
479 | |||
480 | void CCurrentSettings::Save(void) | ||
481 | { | ||
482 | HKEY key; | ||
483 | if (RegCreateKey(HKEY_CURRENT_USER, "Software\\65\\SpaceMonger\\1.3", &key) != ERROR_SUCCESS) | ||
484 | return; | ||
485 | DWORD size; | ||
486 | size = sizeof(density); | ||
487 | RegSetValueEx(key, "density", NULL, REG_DWORD, (unsigned char *)&density, size); | ||
488 | size = sizeof(file_color); | ||
489 | RegSetValueEx(key, "file_color", NULL, REG_DWORD, (unsigned char *)&file_color, size); | ||
490 | size = sizeof(folder_color); | ||
491 | RegSetValueEx(key, "folder_color", NULL, REG_DWORD, (unsigned char *)&folder_color, size); | ||
492 | size = sizeof(auto_rescan); | ||
493 | RegSetValueEx(key, "auto_rescan", NULL, REG_DWORD, (unsigned char *)&auto_rescan, size); | ||
494 | size = sizeof(animated_zoom); | ||
495 | RegSetValueEx(key, "animated_zoom", NULL, REG_DWORD, (unsigned char *)&animated_zoom, size); | ||
496 | size = sizeof(disable_delete); | ||
497 | RegSetValueEx(key, "disable_delete", NULL, REG_DWORD, (unsigned char *)&disable_delete, size); | ||
498 | size = sizeof(save_pos); | ||
499 | RegSetValueEx(key, "save_pos", NULL, REG_DWORD, (unsigned char *)&save_pos, size); | ||
500 | size = sizeof(bias); | ||
501 | RegSetValueEx(key, "bias", NULL, REG_DWORD, (unsigned char *)&bias, size); | ||
502 | size = sizeof(show_name_tips); | ||
503 | RegSetValueEx(key, "show_name_tips", NULL, REG_DWORD, (unsigned char *)&show_name_tips, size); | ||
504 | size = sizeof(rollover_box); | ||
505 | RegSetValueEx(key, "show_rollover_box", NULL, REG_DWORD, (unsigned char *)&rollover_box, size); | ||
506 | size = sizeof(show_info_tips); | ||
507 | RegSetValueEx(key, "show_info_tips", NULL, REG_DWORD, (unsigned char *)&show_info_tips, size); | ||
508 | size = sizeof(nametip_delay); | ||
509 | RegSetValueEx(key, "nametip_delay", NULL, REG_DWORD, (unsigned char *)&nametip_delay, size); | ||
510 | size = sizeof(infotip_flags); | ||
511 | RegSetValueEx(key, "infotip_flags", NULL, REG_DWORD, (unsigned char *)&infotip_flags, size); | ||
512 | size = sizeof(infotip_delay); | ||
513 | RegSetValueEx(key, "infotip_delay", NULL, REG_DWORD, (unsigned char *)&infotip_delay, size); | ||
514 | size = sizeof(rect.left); | ||
515 | RegSetValueEx(key, "window_rect.left", NULL, REG_DWORD, (unsigned char *)&rect.left, size); | ||
516 | size = sizeof(rect.top); | ||
517 | RegSetValueEx(key, "window_rect.top", NULL, REG_DWORD, (unsigned char *)&rect.top, size); | ||
518 | size = sizeof(rect.right); | ||
519 | RegSetValueEx(key, "window_rect.right", NULL, REG_DWORD, (unsigned char *)&rect.right, size); | ||
520 | size = sizeof(rect.bottom); | ||
521 | RegSetValueEx(key, "window_rect.bottom",NULL, REG_DWORD, (unsigned char *)&rect.bottom, size); | ||
522 | size = sizeof(showcmd); | ||
523 | RegSetValueEx(key, "window_showcmd", NULL, REG_DWORD, (unsigned char *)&showcmd, size); | ||
524 | size = sizeof(lang); | ||
525 | RegSetValueEx(key, "lang", NULL, REG_SZ, (unsigned char *)&lang, 3); | ||
526 | RegCloseKey(key); | ||
527 | } | ||
diff --git a/SpaceMonger.dsp b/SpaceMonger.dsp new file mode 100644 index 0000000..a6bf31c --- /dev/null +++ b/SpaceMonger.dsp | |||
@@ -0,0 +1,249 @@ | |||
1 | # Microsoft Developer Studio Project File - Name="SpaceMonger" - Package Owner=<4> | ||
2 | # Microsoft Developer Studio Generated Build File, Format Version 6.00 | ||
3 | # ** DO NOT EDIT ** | ||
4 | |||
5 | # TARGTYPE "Win32 (x86) Application" 0x0101 | ||
6 | |||
7 | CFG=SpaceMonger - Win32 Release | ||
8 | !MESSAGE This is not a valid makefile. To build this project using NMAKE, | ||
9 | !MESSAGE use the Export Makefile command and run | ||
10 | !MESSAGE | ||
11 | !MESSAGE NMAKE /f "SpaceMonger.mak". | ||
12 | !MESSAGE | ||
13 | !MESSAGE You can specify a configuration when running NMAKE | ||
14 | !MESSAGE by defining the macro CFG on the command line. For example: | ||
15 | !MESSAGE | ||
16 | !MESSAGE NMAKE /f "SpaceMonger.mak" CFG="SpaceMonger - Win32 Release" | ||
17 | !MESSAGE | ||
18 | !MESSAGE Possible choices for configuration are: | ||
19 | !MESSAGE | ||
20 | !MESSAGE "SpaceMonger - Win32 Release" (based on "Win32 (x86) Application") | ||
21 | !MESSAGE "SpaceMonger - Win32 Debug" (based on "Win32 (x86) Application") | ||
22 | !MESSAGE | ||
23 | |||
24 | # Begin Project | ||
25 | # PROP AllowPerConfigDependencies 0 | ||
26 | # PROP Scc_ProjName "" | ||
27 | # PROP Scc_LocalPath "" | ||
28 | CPP=cl.exe | ||
29 | MTL=midl.exe | ||
30 | RSC=rc.exe | ||
31 | |||
32 | !IF "$(CFG)" == "SpaceMonger - Win32 Release" | ||
33 | |||
34 | # PROP BASE Use_MFC 2 | ||
35 | # PROP BASE Use_Debug_Libraries 0 | ||
36 | # PROP BASE Output_Dir ".\Release" | ||
37 | # PROP BASE Intermediate_Dir ".\Release" | ||
38 | # PROP BASE Target_Dir "" | ||
39 | # PROP Use_MFC 1 | ||
40 | # PROP Use_Debug_Libraries 0 | ||
41 | # PROP Output_Dir ".\Release" | ||
42 | # PROP Intermediate_Dir ".\Release" | ||
43 | # PROP Ignore_Export_Lib 0 | ||
44 | # PROP Target_Dir "" | ||
45 | # ADD BASE CPP /nologo /MD /W3 /GX /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Yu"stdafx.h" /c | ||
46 | # ADD CPP /nologo /MT /W3 /Ox /Ot /Og /Oi /Ob2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GF /c | ||
47 | # ADD BASE MTL /nologo /D "NDEBUG" /win32 | ||
48 | # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 | ||
49 | # ADD BASE RSC /l 0x409 /d "NDEBUG" /d "_AFXDLL" | ||
50 | # ADD RSC /l 0x409 /d "NDEBUG" | ||
51 | BSC32=bscmake.exe | ||
52 | # ADD BASE BSC32 /nologo | ||
53 | # ADD BSC32 /nologo | ||
54 | LINK32=link.exe | ||
55 | # ADD BASE LINK32 /nologo /subsystem:windows /machine:I386 | ||
56 | # ADD LINK32 /nologo /subsystem:windows /machine:I386 | ||
57 | # SUBTRACT LINK32 /profile /debug /nodefaultlib | ||
58 | |||
59 | !ELSEIF "$(CFG)" == "SpaceMonger - Win32 Debug" | ||
60 | |||
61 | # PROP BASE Use_MFC 2 | ||
62 | # PROP BASE Use_Debug_Libraries 1 | ||
63 | # PROP BASE Output_Dir ".\Debug" | ||
64 | # PROP BASE Intermediate_Dir ".\Debug" | ||
65 | # PROP BASE Target_Dir "" | ||
66 | # PROP Use_MFC 1 | ||
67 | # PROP Use_Debug_Libraries 1 | ||
68 | # PROP Output_Dir ".\Debug" | ||
69 | # PROP Intermediate_Dir ".\Debug" | ||
70 | # PROP Ignore_Export_Lib 0 | ||
71 | # PROP Target_Dir "" | ||
72 | # ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Yu"stdafx.h" /c | ||
73 | # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c | ||
74 | # ADD BASE MTL /nologo /D "_DEBUG" /win32 | ||
75 | # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 | ||
76 | # ADD BASE RSC /l 0x409 /d "_DEBUG" /d "_AFXDLL" | ||
77 | # ADD RSC /l 0x409 /d "_DEBUG" | ||
78 | BSC32=bscmake.exe | ||
79 | # ADD BASE BSC32 /nologo | ||
80 | # ADD BSC32 /nologo | ||
81 | LINK32=link.exe | ||
82 | # ADD BASE LINK32 /nologo /subsystem:windows /debug /machine:I386 | ||
83 | # ADD LINK32 /nologo /subsystem:windows /profile /debug /machine:I386 | ||
84 | |||
85 | !ENDIF | ||
86 | |||
87 | # Begin Target | ||
88 | |||
89 | # Name "SpaceMonger - Win32 Release" | ||
90 | # Name "SpaceMonger - Win32 Debug" | ||
91 | # Begin Group "Source Files" | ||
92 | |||
93 | # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat;for;f90" | ||
94 | # Begin Source File | ||
95 | |||
96 | SOURCE=.\AboutDialog.cpp | ||
97 | # End Source File | ||
98 | # Begin Source File | ||
99 | |||
100 | SOURCE=.\DriveDialog.cpp | ||
101 | # End Source File | ||
102 | # Begin Source File | ||
103 | |||
104 | SOURCE=.\FolderTree.cpp | ||
105 | # End Source File | ||
106 | # Begin Source File | ||
107 | |||
108 | SOURCE=.\FolderView.cpp | ||
109 | # End Source File | ||
110 | # Begin Source File | ||
111 | |||
112 | SOURCE=.\Freedoc.cpp | ||
113 | # End Source File | ||
114 | # Begin Source File | ||
115 | |||
116 | SOURCE=.\Freeview.cpp | ||
117 | # End Source File | ||
118 | # Begin Source File | ||
119 | |||
120 | SOURCE=.\lang_en.cpp | ||
121 | # End Source File | ||
122 | # Begin Source File | ||
123 | |||
124 | SOURCE=.\lang_fr.cpp | ||
125 | # End Source File | ||
126 | # Begin Source File | ||
127 | |||
128 | SOURCE=.\Mainfrm.cpp | ||
129 | # End Source File | ||
130 | # Begin Source File | ||
131 | |||
132 | SOURCE=.\SetupDlg.cpp | ||
133 | # End Source File | ||
134 | # Begin Source File | ||
135 | |||
136 | SOURCE=.\SpaceMonger.cpp | ||
137 | # End Source File | ||
138 | # Begin Source File | ||
139 | |||
140 | SOURCE=.\SpaceMonger.rc | ||
141 | # End Source File | ||
142 | # Begin Source File | ||
143 | |||
144 | SOURCE=.\StdAfx.cpp | ||
145 | # ADD CPP /Yc"stdafx.h" | ||
146 | # End Source File | ||
147 | # Begin Source File | ||
148 | |||
149 | SOURCE=.\TipWnd.cpp | ||
150 | # End Source File | ||
151 | # End Group | ||
152 | # Begin Group "Header Files" | ||
153 | |||
154 | # PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd" | ||
155 | # Begin Source File | ||
156 | |||
157 | SOURCE=.\AboutDialog.h | ||
158 | # End Source File | ||
159 | # Begin Source File | ||
160 | |||
161 | SOURCE=.\DriveDialog.h | ||
162 | # End Source File | ||
163 | # Begin Source File | ||
164 | |||
165 | SOURCE=.\FolderTree.h | ||
166 | # End Source File | ||
167 | # Begin Source File | ||
168 | |||
169 | SOURCE=.\FolderView.h | ||
170 | # End Source File | ||
171 | # Begin Source File | ||
172 | |||
173 | SOURCE=.\lang.h | ||
174 | # End Source File | ||
175 | # Begin Source File | ||
176 | |||
177 | SOURCE=.\Mainfrm.h | ||
178 | # End Source File | ||
179 | # Begin Source File | ||
180 | |||
181 | SOURCE=.\resource.h | ||
182 | # End Source File | ||
183 | # Begin Source File | ||
184 | |||
185 | SOURCE=.\SetupDlg.h | ||
186 | # End Source File | ||
187 | # Begin Source File | ||
188 | |||
189 | SOURCE=.\SpaceMonger.h | ||
190 | # End Source File | ||
191 | # Begin Source File | ||
192 | |||
193 | SOURCE=.\Stdafx.h | ||
194 | # End Source File | ||
195 | # Begin Source File | ||
196 | |||
197 | SOURCE=.\TipWnd.h | ||
198 | # End Source File | ||
199 | # Begin Source File | ||
200 | |||
201 | SOURCE=.\xapp.h | ||
202 | # End Source File | ||
203 | # End Group | ||
204 | # Begin Group "Resource Files" | ||
205 | |||
206 | # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe" | ||
207 | # Begin Source File | ||
208 | |||
209 | SOURCE=.\res\bitmap1.bmp | ||
210 | # End Source File | ||
211 | # Begin Source File | ||
212 | |||
213 | SOURCE=.\res\bmp00001.bmp | ||
214 | # End Source File | ||
215 | # Begin Source File | ||
216 | |||
217 | SOURCE=.\res\bmp00002.bmp | ||
218 | # End Source File | ||
219 | # Begin Source File | ||
220 | |||
221 | SOURCE=.\res\bmp00003.bmp | ||
222 | # End Source File | ||
223 | # Begin Source File | ||
224 | |||
225 | SOURCE=.\res\scan1.bmp | ||
226 | # End Source File | ||
227 | # Begin Source File | ||
228 | |||
229 | SOURCE=.\Res\SpaceMonger.ico | ||
230 | # End Source File | ||
231 | # Begin Source File | ||
232 | |||
233 | SOURCE=.\res\toolbar1.bmp | ||
234 | # End Source File | ||
235 | # Begin Source File | ||
236 | |||
237 | SOURCE=.\res\toolbar_en.bmp | ||
238 | # End Source File | ||
239 | # Begin Source File | ||
240 | |||
241 | SOURCE=.\res\toolbar_fr.bmp | ||
242 | # End Source File | ||
243 | # Begin Source File | ||
244 | |||
245 | SOURCE=.\res\toolbar_francais.bmp | ||
246 | # End Source File | ||
247 | # End Group | ||
248 | # End Target | ||
249 | # End Project | ||
diff --git a/SpaceMonger.dsw b/SpaceMonger.dsw new file mode 100644 index 0000000..8a53582 --- /dev/null +++ b/SpaceMonger.dsw | |||
@@ -0,0 +1,29 @@ | |||
1 | Microsoft Developer Studio Workspace File, Format Version 6.00 | ||
2 | # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! | ||
3 | |||
4 | ############################################################################### | ||
5 | |||
6 | Project: "SpaceMonger"=.\SpaceMonger.dsp - Package Owner=<4> | ||
7 | |||
8 | Package=<5> | ||
9 | {{{ | ||
10 | }}} | ||
11 | |||
12 | Package=<4> | ||
13 | {{{ | ||
14 | }}} | ||
15 | |||
16 | ############################################################################### | ||
17 | |||
18 | Global: | ||
19 | |||
20 | Package=<5> | ||
21 | {{{ | ||
22 | }}} | ||
23 | |||
24 | Package=<3> | ||
25 | {{{ | ||
26 | }}} | ||
27 | |||
28 | ############################################################################### | ||
29 | |||
diff --git a/SpaceMonger.h b/SpaceMonger.h new file mode 100644 index 0000000..4128282 --- /dev/null +++ b/SpaceMonger.h | |||
@@ -0,0 +1,90 @@ | |||
1 | |||
2 | #ifndef CSPACEMONGER_H | ||
3 | #define CSPACEMONGER_H | ||
4 | |||
5 | #ifndef __AFXWIN_H__ | ||
6 | #error include 'stdafx.h' before including this file for PCH | ||
7 | #endif | ||
8 | |||
9 | #include "resource.h" // main symbols | ||
10 | #include "MainFrm.h" // Main window | ||
11 | |||
12 | enum { | ||
13 | TIP_PATH = 1, // Display full path in tooltip | ||
14 | TIP_NAME = 2, // Display filename in tooltip | ||
15 | TIP_ICON = 4, // Display suitable icon in tooltip | ||
16 | TIP_DATE = 8, // Display file date in tooltip | ||
17 | TIP_SIZE = 16, // Display file size in tooltip | ||
18 | TIP_ATTRIB = 32, // Display file attributes in tooltip | ||
19 | }; | ||
20 | |||
21 | struct CCurrentSettings { | ||
22 | int density; // Density of filenames | ||
23 | int file_color; // Displayed color of files | ||
24 | int folder_color; // Displayed color of folders | ||
25 | BOOL auto_rescan; // Auto-rescan when a file is deleted | ||
26 | BOOL animated_zoom; // Use animated zoom in/out | ||
27 | BOOL disable_delete; // Disallow the deletion of files | ||
28 | BOOL rollover_box; // Show rollover box | ||
29 | int bias; // Display bias, from -20 (vert) to +20 (horz) | ||
30 | |||
31 | BOOL save_pos; // Save this window's position? | ||
32 | RECT rect; // Pluralized window rectangle | ||
33 | int showcmd; // Current show-command | ||
34 | |||
35 | BOOL show_name_tips; // Show tooltips? | ||
36 | int nametip_delay; // Tip delay, in milliseconds | ||
37 | |||
38 | BOOL show_info_tips; // Show tooltips? | ||
39 | int infotip_flags; // Tooltip flags | ||
40 | int infotip_delay; // Tip delay, in milliseconds | ||
41 | |||
42 | char lang[4]; // Language, by two-letter code | ||
43 | |||
44 | void Reset(void); // Reset to default values | ||
45 | void Load(void); // Retrieve current settings from Registry | ||
46 | void Save(void); // Save current settings to Registry | ||
47 | }; | ||
48 | |||
49 | class CSpaceMonger : public CWinApp { | ||
50 | public: | ||
51 | CSpaceMonger(); | ||
52 | ~CSpaceMonger(); | ||
53 | |||
54 | //{{AFX_VIRTUAL(CSpaceMonger) | ||
55 | virtual BOOL InitInstance(); | ||
56 | virtual int ExitInstance(); | ||
57 | //}}AFX_VIRTUAL | ||
58 | |||
59 | //{{AFX_MSG(CSpaceMonger) | ||
60 | afx_msg void OnAbout(); | ||
61 | afx_msg void OnAppExit(void); | ||
62 | afx_msg void OnFileOpen(void); | ||
63 | afx_msg void OnFileRefresh(void); | ||
64 | afx_msg void OnFileRun(void); | ||
65 | afx_msg void OnFileDelete(void); | ||
66 | afx_msg void OnZoomFull(void); | ||
67 | afx_msg void OnZoomIn(void); | ||
68 | afx_msg void OnZoomOut(void); | ||
69 | afx_msg void OnShowFree(void); | ||
70 | afx_msg void OnSettings(void); | ||
71 | afx_msg void OnFileProperties(void); | ||
72 | afx_msg void OnIgnoreUpdate(CCmdUI *ui); | ||
73 | //}}AFX_MSG | ||
74 | DECLARE_MESSAGE_MAP() | ||
75 | |||
76 | public: | ||
77 | CFrameWnd *m_mainframe; | ||
78 | CFreeDoc *m_document; | ||
79 | CFreeView *m_view; | ||
80 | |||
81 | HBITMAP m_scan_animation[4]; | ||
82 | |||
83 | CCurrentSettings m_settings; | ||
84 | }; | ||
85 | |||
86 | void GeneralIgnoreUpdate(CCmdUI *ui); | ||
87 | |||
88 | extern CSpaceMonger theApp; | ||
89 | |||
90 | #endif | ||
diff --git a/SpaceMonger.ncb b/SpaceMonger.ncb new file mode 100644 index 0000000..4cbddaf --- /dev/null +++ b/SpaceMonger.ncb | |||
Binary files differ | |||
diff --git a/SpaceMonger.opt b/SpaceMonger.opt new file mode 100644 index 0000000..48885a1 --- /dev/null +++ b/SpaceMonger.opt | |||
Binary files differ | |||
diff --git a/SpaceMonger.rc b/SpaceMonger.rc new file mode 100644 index 0000000..7171a28 --- /dev/null +++ b/SpaceMonger.rc | |||
@@ -0,0 +1,330 @@ | |||
1 | //Microsoft Developer Studio generated resource script. | ||
2 | // | ||
3 | #include "resource.h" | ||
4 | |||
5 | #define APSTUDIO_READONLY_SYMBOLS | ||
6 | ///////////////////////////////////////////////////////////////////////////// | ||
7 | // | ||
8 | // Generated from the TEXTINCLUDE 2 resource. | ||
9 | // | ||
10 | #include "afxres.h" | ||
11 | |||
12 | ///////////////////////////////////////////////////////////////////////////// | ||
13 | #undef APSTUDIO_READONLY_SYMBOLS | ||
14 | |||
15 | ///////////////////////////////////////////////////////////////////////////// | ||
16 | // English (U.S.) resources | ||
17 | |||
18 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) | ||
19 | #ifdef _WIN32 | ||
20 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US | ||
21 | #pragma code_page(1252) | ||
22 | #endif //_WIN32 | ||
23 | |||
24 | ///////////////////////////////////////////////////////////////////////////// | ||
25 | // | ||
26 | // Dialog | ||
27 | // | ||
28 | |||
29 | IDD_ABOUT DIALOG DISCARDABLE 0, 0, 239, 145 | ||
30 | STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | WS_POPUP | WS_VISIBLE | | ||
31 | WS_CAPTION | WS_SYSMENU | ||
32 | FONT 8, "MS Sans Serif" | ||
33 | BEGIN | ||
34 | DEFPUSHBUTTON "",IDOK,94,124,50,14 | ||
35 | ICON ID_SPACEMONGER,IDC_STATIC,7,9,20,20 | ||
36 | LTEXT "SpaceMonger Version 1.4.0",IDC_STATIC,37,9,95,10 | ||
37 | LTEXT "Copyright © 1998, 1999, 2000 by Sean Werkema", | ||
38 | IDC_STATIC,37,18,168,8 | ||
39 | LTEXT "",IDC_STATIC_FREEWARE,37,41,195,10 | ||
40 | LTEXT "",IDC_STATIC_WARRANTY,37,55,195,34 | ||
41 | CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,37,34,195,1 | ||
42 | LTEXT "",IDC_STATIC_EMAIL,37,93,195,18 | ||
43 | CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,37,115,195,1 | ||
44 | END | ||
45 | |||
46 | IDD_OPEN_DIALOG DIALOG DISCARDABLE 0, 0, 221, 170 | ||
47 | STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | WS_POPUP | WS_VISIBLE | | ||
48 | WS_CAPTION | WS_SYSMENU | ||
49 | FONT 8, "MS Sans Serif" | ||
50 | BEGIN | ||
51 | DEFPUSHBUTTON "",IDOK,113,151,50,14 | ||
52 | PUSHBUTTON "",IDCANCEL,58,151,50,14 | ||
53 | CONTROL "",IDC_DRIVE_LIST,"SysListView32",LVS_SINGLESEL | | ||
54 | LVS_SORTASCENDING | LVS_AUTOARRANGE | WS_BORDER | | ||
55 | WS_TABSTOP,7,5,207,139 | ||
56 | END | ||
57 | |||
58 | IDD_SCAN_DIALOG DIALOGEX 0, 0, 250, 54 | ||
59 | STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | WS_POPUP | WS_VISIBLE | | ||
60 | WS_CAPTION | ||
61 | EXSTYLE WS_EX_TOOLWINDOW | ||
62 | FONT 8, "MS Sans Serif" | ||
63 | BEGIN | ||
64 | PUSHBUTTON "",IDCANCEL,203,24,40,14 | ||
65 | LTEXT "",IDC_STATIC_FILESFOUND,103,21,66,8 | ||
66 | LTEXT "",IDC_STATIC_FOLDERSFOUND,103,30,66,8 | ||
67 | LTEXT "",IDC_PATH,7,4,236,9 | ||
68 | LTEXT "0",IDC_FILES,171,21,30,8 | ||
69 | LTEXT "0",IDC_FOLDERS,171,30,30,8 | ||
70 | CONTROL "",IDC_LOAD_PROGRESS,"msctls_progress32",WS_BORDER,7,44, | ||
71 | 236,6 | ||
72 | END | ||
73 | |||
74 | IDD_SETTINGS DIALOG DISCARDABLE 0, 0, 280, 213 | ||
75 | STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_3DLOOK | WS_POPUP | WS_VISIBLE | | ||
76 | WS_CAPTION | WS_SYSMENU | ||
77 | FONT 8, "MS Sans Serif" | ||
78 | BEGIN | ||
79 | COMBOBOX IDC_LANG,191,8,82,101,CBS_DROPDOWNLIST | WS_VSCROLL | | ||
80 | WS_TABSTOP | ||
81 | COMBOBOX IDC_DENSITY,42,18,90,85,CBS_DROPDOWNLIST | WS_GROUP | | ||
82 | WS_TABSTOP | ||
83 | CONTROL "",IDC_BIAS,"msctls_trackbar32",TBS_AUTOTICKS | TBS_TOP | | ||
84 | WS_TABSTOP,39,49,95,17 | ||
85 | COMBOBOX IDC_FILE_COLOR,191,40,72,143,CBS_DROPDOWNLIST | WS_GROUP | | ||
86 | WS_TABSTOP | ||
87 | COMBOBOX IDC_FOLDER_COLOR,191,55,72,142,CBS_DROPDOWNLIST | | ||
88 | WS_TABSTOP | ||
89 | CONTROL "",IDC_SHOW_NAME_TIPS,"Button",BS_AUTOCHECKBOX | | ||
90 | WS_GROUP | WS_TABSTOP,24,85,104,10 | ||
91 | EDITTEXT IDC_NAMETIP_DELAY,59,96,27,12,ES_NUMBER | WS_GROUP | ||
92 | CONTROL "",IDC_SHOW_ROLLOVER_BOX,"Button",BS_AUTOCHECKBOX | | ||
93 | WS_TABSTOP,24,126,119,8 | ||
94 | CONTROL "",IDC_SHOW_INFO_TIPS,"Button",BS_AUTOCHECKBOX | | ||
95 | WS_GROUP | WS_TABSTOP,144,85,104,10 | ||
96 | CONTROL "",IDC_INFOTIP_PATH,"Button",BS_AUTOCHECKBOX | WS_GROUP | | ||
97 | WS_TABSTOP,153,96,50,10 | ||
98 | CONTROL "",IDC_INFOTIP_DATE,"Button",BS_AUTOCHECKBOX | | ||
99 | WS_TABSTOP,205,96,50,10 | ||
100 | CONTROL "",IDC_INFOTIP_NAME,"Button",BS_AUTOCHECKBOX | | ||
101 | WS_TABSTOP,153,106,50,10 | ||
102 | CONTROL "",IDC_INFOTIP_SIZE,"Button",BS_AUTOCHECKBOX | | ||
103 | WS_TABSTOP,205,106,50,10 | ||
104 | CONTROL "",IDC_INFOTIP_ICON,"Button",BS_AUTOCHECKBOX | | ||
105 | WS_TABSTOP,153,116,50,10 | ||
106 | CONTROL "",IDC_INFOTIP_ATTRIB,"Button",BS_AUTOCHECKBOX | | ||
107 | WS_TABSTOP,205,116,50,10 | ||
108 | EDITTEXT IDC_INFOTIP_DELAY,182,129,27,12,ES_NUMBER | WS_GROUP | ||
109 | CONTROL "",IDC_AUTO_RESCAN,"Button",BS_AUTOCHECKBOX | WS_GROUP | | ||
110 | WS_TABSTOP,24,160,120,10 | ||
111 | CONTROL "",IDC_DISABLE_DELETE,"Button",BS_AUTOCHECKBOX | | ||
112 | WS_TABSTOP,24,171,120,10 | ||
113 | CONTROL "",IDC_ANIMATED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, | ||
114 | 144,160,120,10 | ||
115 | CONTROL "",IDC_SAVE_POS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP, | ||
116 | 144,171,120,10 | ||
117 | PUSHBUTTON "",IDCANCEL,86,194,50,14,WS_GROUP | ||
118 | DEFPUSHBUTTON "",IDOK,142,194,50,14 | ||
119 | LTEXT "",IDC_STATIC_DENSITY,14,20,27,8 | ||
120 | LTEXT "",IDC_STATIC_FILES,160,43,30,8 | ||
121 | LTEXT "",IDC_STATIC_BIAS,14,55,24,8 | ||
122 | CTEXT "",IDC_STATIC_HORZ,35,40,21,8 | ||
123 | CTEXT "",IDC_STATIC_VERT,118,40,21,8 | ||
124 | CTEXT "",IDC_STATIC_EQUAL,76,40,21,8 | ||
125 | LTEXT "",IDC_STATIC_FOLDERS,160,58,30,8 | ||
126 | LTEXT "",IDC_STATIC_INFOTIP1,153,131,28,8 | ||
127 | LTEXT "",IDC_STATIC_INFOTIP2,212,131,25,8 | ||
128 | GROUPBOX "",IDC_STATIC_LAYOUT,7,4,139,68 | ||
129 | GROUPBOX "",IDC_STATIC_DISPLAYCOLORS,153,29,120,43 | ||
130 | GROUPBOX "",IDC_STATIC_TOOLTIPS,7,74,266,73 | ||
131 | GROUPBOX "",IDC_STATIC_MISCOPTIONS,6,149,267,38 | ||
132 | LTEXT "",IDC_STATIC_NAMETIP1,30,98,28,8 | ||
133 | LTEXT "",IDC_STATIC_NAMETIP2,89,98,25,8 | ||
134 | END | ||
135 | |||
136 | |||
137 | ///////////////////////////////////////////////////////////////////////////// | ||
138 | // | ||
139 | // DESIGNINFO | ||
140 | // | ||
141 | |||
142 | #ifdef APSTUDIO_INVOKED | ||
143 | GUIDELINES DESIGNINFO DISCARDABLE | ||
144 | BEGIN | ||
145 | IDD_ABOUT, DIALOG | ||
146 | BEGIN | ||
147 | LEFTMARGIN, 7 | ||
148 | RIGHTMARGIN, 232 | ||
149 | TOPMARGIN, 7 | ||
150 | BOTTOMMARGIN, 138 | ||
151 | END | ||
152 | |||
153 | IDD_OPEN_DIALOG, DIALOG | ||
154 | BEGIN | ||
155 | LEFTMARGIN, 7 | ||
156 | RIGHTMARGIN, 214 | ||
157 | TOPMARGIN, 7 | ||
158 | BOTTOMMARGIN, 163 | ||
159 | END | ||
160 | |||
161 | IDD_SCAN_DIALOG, DIALOG | ||
162 | BEGIN | ||
163 | LEFTMARGIN, 7 | ||
164 | RIGHTMARGIN, 243 | ||
165 | TOPMARGIN, 7 | ||
166 | BOTTOMMARGIN, 50 | ||
167 | END | ||
168 | |||
169 | IDD_SETTINGS, DIALOG | ||
170 | BEGIN | ||
171 | LEFTMARGIN, 6 | ||
172 | RIGHTMARGIN, 273 | ||
173 | TOPMARGIN, 4 | ||
174 | BOTTOMMARGIN, 208 | ||
175 | END | ||
176 | END | ||
177 | #endif // APSTUDIO_INVOKED | ||
178 | |||
179 | |||
180 | #ifdef APSTUDIO_INVOKED | ||
181 | ///////////////////////////////////////////////////////////////////////////// | ||
182 | // | ||
183 | // TEXTINCLUDE | ||
184 | // | ||
185 | |||
186 | 1 TEXTINCLUDE DISCARDABLE | ||
187 | BEGIN | ||
188 | "resource.h\0" | ||
189 | END | ||
190 | |||
191 | 2 TEXTINCLUDE DISCARDABLE | ||
192 | BEGIN | ||
193 | "#include ""afxres.h""\r\n" | ||
194 | "\0" | ||
195 | END | ||
196 | |||
197 | 3 TEXTINCLUDE DISCARDABLE | ||
198 | BEGIN | ||
199 | "\r\n" | ||
200 | "\0" | ||
201 | END | ||
202 | |||
203 | #endif // APSTUDIO_INVOKED | ||
204 | |||
205 | |||
206 | ///////////////////////////////////////////////////////////////////////////// | ||
207 | // | ||
208 | // Icon | ||
209 | // | ||
210 | |||
211 | // Icon with lowest ID value placed first to ensure application icon | ||
212 | // remains consistent on all systems. | ||
213 | ID_SPACEMONGER ICON DISCARDABLE "res\\SpaceMonger.ico" | ||
214 | |||
215 | ///////////////////////////////////////////////////////////////////////////// | ||
216 | // | ||
217 | // Toolbar | ||
218 | // | ||
219 | |||
220 | IDR_TOOLBAR_EN TOOLBAR DISCARDABLE 44, 15 | ||
221 | BEGIN | ||
222 | BUTTON ID_FILE_OPEN | ||
223 | BUTTON ID_FILE_REFRESH | ||
224 | SEPARATOR | ||
225 | BUTTON ID_VIEW_ZOOM_FULL | ||
226 | BUTTON ID_VIEW_ZOOM_IN | ||
227 | BUTTON ID_VIEW_ZOOM_OUT | ||
228 | SEPARATOR | ||
229 | BUTTON ID_VIEW_FREE | ||
230 | SEPARATOR | ||
231 | BUTTON ID_FILE_RUN | ||
232 | BUTTON ID_FILE_DELETE | ||
233 | SEPARATOR | ||
234 | BUTTON ID_SETTINGS | ||
235 | SEPARATOR | ||
236 | BUTTON ID_APP_ABOUT | ||
237 | END | ||
238 | |||
239 | IDR_TOOLBAR_FR TOOLBAR DISCARDABLE 44, 15 | ||
240 | BEGIN | ||
241 | BUTTON ID_FILE_OPEN | ||
242 | BUTTON ID_FILE_REFRESH | ||
243 | SEPARATOR | ||
244 | BUTTON ID_VIEW_ZOOM_FULL | ||
245 | BUTTON ID_VIEW_ZOOM_IN | ||
246 | BUTTON ID_VIEW_ZOOM_OUT | ||
247 | SEPARATOR | ||
248 | BUTTON ID_VIEW_FREE | ||
249 | SEPARATOR | ||
250 | BUTTON ID_FILE_RUN | ||
251 | BUTTON ID_FILE_DELETE | ||
252 | SEPARATOR | ||
253 | BUTTON ID_SETTINGS | ||
254 | SEPARATOR | ||
255 | BUTTON ID_APP_ABOUT | ||
256 | END | ||
257 | |||
258 | |||
259 | ///////////////////////////////////////////////////////////////////////////// | ||
260 | // | ||
261 | // Bitmap | ||
262 | // | ||
263 | |||
264 | IDB_SCAN1 BITMAP DISCARDABLE "res\\scan1.bmp" | ||
265 | IDB_SCAN2 BITMAP DISCARDABLE "res\\scan2.bmp" | ||
266 | IDB_SCAN3 BITMAP DISCARDABLE "res\\scan3.bmp" | ||
267 | IDB_SCAN4 BITMAP DISCARDABLE "res\\scan4.bmp" | ||
268 | IDR_TOOLBAR_EN BITMAP DISCARDABLE "res\\toolbar_en.bmp" | ||
269 | IDR_TOOLBAR_FR BITMAP DISCARDABLE "res\\toolbar_fr.bmp" | ||
270 | |||
271 | #ifndef _MAC | ||
272 | ///////////////////////////////////////////////////////////////////////////// | ||
273 | // | ||
274 | // Version | ||
275 | // | ||
276 | |||
277 | VS_VERSION_INFO VERSIONINFO | ||
278 | FILEVERSION 1,4,0,1 | ||
279 | PRODUCTVERSION 1,4,0,1 | ||
280 | FILEFLAGSMASK 0x3fL | ||
281 | #ifdef _DEBUG | ||
282 | FILEFLAGS 0x1L | ||
283 | #else | ||
284 | FILEFLAGS 0x0L | ||
285 | #endif | ||
286 | FILEOS 0x40004L | ||
287 | FILETYPE 0x1L | ||
288 | FILESUBTYPE 0x0L | ||
289 | BEGIN | ||
290 | BLOCK "StringFileInfo" | ||
291 | BEGIN | ||
292 | BLOCK "040904b0" | ||
293 | BEGIN | ||
294 | VALUE "Comments", "Visit http://www.werkema.com/software/spacemonger.html for the latest version\0" | ||
295 | VALUE "CompanyName", "65 Systems\0" | ||
296 | VALUE "FileDescription", "SpaceMonger Program File\0" | ||
297 | VALUE "FileVersion", "1, 4, 0, 1\0" | ||
298 | VALUE "InternalName", "SpaceMonger\0" | ||
299 | VALUE "LegalCopyright", "Copyright © 1997-2000 Sean Werkema\0" | ||
300 | VALUE "LegalTrademarks", "\0" | ||
301 | VALUE "OriginalFilename", "SpaceMonger.exe\0" | ||
302 | VALUE "PrivateBuild", "\0" | ||
303 | VALUE "ProductName", "SpaceMonger\0" | ||
304 | VALUE "ProductVersion", "1, 4, 0, 1\0" | ||
305 | VALUE "SpecialBuild", "\0" | ||
306 | END | ||
307 | END | ||
308 | BLOCK "VarFileInfo" | ||
309 | BEGIN | ||
310 | VALUE "Translation", 0x409, 1200 | ||
311 | END | ||
312 | END | ||
313 | |||
314 | #endif // !_MAC | ||
315 | |||
316 | #endif // English (U.S.) resources | ||
317 | ///////////////////////////////////////////////////////////////////////////// | ||
318 | |||
319 | |||
320 | |||
321 | #ifndef APSTUDIO_INVOKED | ||
322 | ///////////////////////////////////////////////////////////////////////////// | ||
323 | // | ||
324 | // Generated from the TEXTINCLUDE 3 resource. | ||
325 | // | ||
326 | |||
327 | |||
328 | ///////////////////////////////////////////////////////////////////////////// | ||
329 | #endif // not APSTUDIO_INVOKED | ||
330 | |||
diff --git a/StdAfx.cpp b/StdAfx.cpp new file mode 100644 index 0000000..f36634a --- /dev/null +++ b/StdAfx.cpp | |||
@@ -0,0 +1,5 @@ | |||
1 | // stdafx.cpp : source file that includes just the standard includes | ||
2 | // SpaceMonger.pch will be the pre-compiled header | ||
3 | // stdafx.obj will contain the pre-compiled type information | ||
4 | |||
5 | #include "StdAfx.h" | ||
diff --git a/Stdafx.h b/Stdafx.h new file mode 100644 index 0000000..220fd6a --- /dev/null +++ b/Stdafx.h | |||
@@ -0,0 +1,25 @@ | |||
1 | // stdafx.h : include file for standard system include files, | ||
2 | // or project specific include files that are used frequently, but | ||
3 | // are changed infrequently | ||
4 | // | ||
5 | |||
6 | #define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers | ||
7 | |||
8 | #include <afxwin.h> // MFC core and standard components | ||
9 | #include <afxext.h> // MFC extensions | ||
10 | #include <afxmt.h> // MFC multithreading extensions | ||
11 | #ifndef _AFX_NO_AFXCMN_SUPPORT | ||
12 | #include <afxcmn.h> // MFC support for Windows 95 Common Controls | ||
13 | #endif // _AFX_NO_AFXCMN_SUPPORT | ||
14 | |||
15 | #include <winnetwk.h> // Windows networking subsystem | ||
16 | #include <winsock.h> // Windows sockets | ||
17 | #include <nspapi.h> // Namespace API | ||
18 | #include <shellapi.h> // Shell (Explorer) API | ||
19 | #include <shlobj.h> // Shell object definitions | ||
20 | |||
21 | #include "xapp.h" // Extended MFC utils | ||
22 | #include "e.h" // Enhanced portable types | ||
23 | |||
24 | #define bool char | ||
25 | |||
diff --git a/TipWnd.cpp b/TipWnd.cpp new file mode 100644 index 0000000..623cbd1 --- /dev/null +++ b/TipWnd.cpp | |||
@@ -0,0 +1,789 @@ | |||
1 | |||
2 | #include "stdafx.h" | ||
3 | #include "SpaceMonger.h" | ||
4 | #include "TipWnd.h" | ||
5 | |||
6 | #ifdef _DEBUG | ||
7 | #define new DEBUG_NEW | ||
8 | #undef THIS_FILE | ||
9 | static char THIS_FILE[] = __FILE__; | ||
10 | #endif | ||
11 | |||
12 | /***************************************************************************/ | ||
13 | |||
14 | #define CLASSNAME "TipWnd" | ||
15 | |||
16 | struct TipWndInfo { | ||
17 | HICON icon; | ||
18 | int flags; | ||
19 | char *text; | ||
20 | int textlen; | ||
21 | HFONT font; | ||
22 | COLORREF bgcolor; | ||
23 | COLORREF textcolor; | ||
24 | COLORREF bordercolor; | ||
25 | short int vpadding, hpadding; | ||
26 | unsigned char autoshow; | ||
27 | unsigned char autopos; | ||
28 | short int showdelay; | ||
29 | UINT timer, hidetimer; | ||
30 | HWND owner; | ||
31 | int mousex, mousey; | ||
32 | BOOL hidden; | ||
33 | BOOL enabled; | ||
34 | int ourmousex, ourmousey; | ||
35 | }; | ||
36 | |||
37 | enum { | ||
38 | TIPWND_LARGE_ICON = 1, | ||
39 | |||
40 | TIPWND_ICON_LEFT = 0, | ||
41 | TIPWND_ICON_TOP = 2, | ||
42 | TIPWND_ICON_RIGHT = 4, | ||
43 | TIPWND_ICON_BOTTOM = 6, | ||
44 | |||
45 | TIPWND_ANCHOR_LEFT = 8, | ||
46 | TIPWND_ANCHOR_TOP = 16, | ||
47 | TIPWND_ANCHOR_RIGHT = 32, | ||
48 | TIPWND_ANCHOR_BOTTOM = 64, | ||
49 | |||
50 | TIPWND_ANCHOR_TOPLEFT = 8|16, | ||
51 | TIPWND_ANCHOR_TOPRIGHT = 32|16, | ||
52 | TIPWND_ANCHOR_BOTTOMLEFT = 8|64, | ||
53 | TIPWND_ANCHOR_BOTTOMRIGHT = 32|64, | ||
54 | |||
55 | TIPWND_ALIGN_LEFT = 128, | ||
56 | TIPWND_ALIGN_TOP = 256, | ||
57 | TIPWND_ALIGN_RIGHT = 512, | ||
58 | TIPWND_ALIGN_BOTTOM = 1024, | ||
59 | |||
60 | TIPWND_ALIGN_TOPLEFT = 128|256, | ||
61 | TIPWND_ALIGN_TOPRIGHT = 512|256, | ||
62 | TIPWND_ALIGN_BOTTOMLEFT = 128|1024, | ||
63 | TIPWND_ALIGN_BOTTOMRIGHT = 512|1024, | ||
64 | }; | ||
65 | |||
66 | /***************************************************************************/ | ||
67 | |||
68 | static HFONT SetBestFont(HDC dc, TipWndInfo *info) | ||
69 | { | ||
70 | if (info->font != NULL) | ||
71 | return (HFONT)::SelectObject(dc, info->font); | ||
72 | else return (HFONT)::SelectObject(dc, ::GetStockObject(DEFAULT_GUI_FONT)); | ||
73 | } | ||
74 | |||
75 | static void ComputeTextExtents(HDC dc, TipWndInfo *info, SIZE *size) | ||
76 | { | ||
77 | // Scan the text to determine the longest line (in pixels) and the | ||
78 | // total height in pixels. | ||
79 | const char *start, *end; | ||
80 | int maxlen = 0, height = 0; | ||
81 | SIZE linesize; | ||
82 | TEXTMETRIC tm; | ||
83 | ::GetTextMetrics(dc, &tm); | ||
84 | |||
85 | start = info->text; | ||
86 | if (start != NULL) { | ||
87 | while (*start != '\0') { | ||
88 | end = start; | ||
89 | while (*end != '\0' && *end != '\n') end++; | ||
90 | linesize.cx = linesize.cy = 0; | ||
91 | ::GetTextExtentPoint32(dc, start, end-start, &linesize); | ||
92 | height += tm.tmAscent + tm.tmDescent; | ||
93 | if (linesize.cx > maxlen) maxlen = linesize.cx; | ||
94 | if (*end == '\n') end++; | ||
95 | start = end; | ||
96 | } | ||
97 | } | ||
98 | size->cx = maxlen; | ||
99 | size->cy = height; | ||
100 | } | ||
101 | |||
102 | static void DrawMultilineText(HDC dc, TipWndInfo *info, POINT *point) | ||
103 | { | ||
104 | ::SetTextColor(dc, info->textcolor); | ||
105 | |||
106 | // Scan the text to determine the longest line (in pixels) and the | ||
107 | // total height in pixels. | ||
108 | const char *start, *end; | ||
109 | SIZE linesize; | ||
110 | TEXTMETRIC tm; | ||
111 | ::GetTextMetrics(dc, &tm); | ||
112 | |||
113 | start = info->text; | ||
114 | if (start != NULL) { | ||
115 | while (*start != '\0') { | ||
116 | end = start; | ||
117 | while (*end != '\0' && *end != '\n') end++; | ||
118 | linesize.cx = linesize.cy = 0; | ||
119 | ::TextOut(dc, point->x, point->y, start, end-start); | ||
120 | point->y += tm.tmAscent + tm.tmDescent; | ||
121 | if (*end == '\n') end++; | ||
122 | start = end; | ||
123 | } | ||
124 | } | ||
125 | } | ||
126 | |||
127 | static LRESULT CALLBACK TipWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) | ||
128 | { | ||
129 | TipWndInfo *info = (TipWndInfo *)::GetWindowLong(hwnd, GWL_USERDATA); | ||
130 | if (info == NULL && uMsg != WM_CREATE) | ||
131 | return ::DefWindowProc(hwnd, uMsg, wParam, lParam); | ||
132 | |||
133 | switch (uMsg) { | ||
134 | |||
135 | case WM_CREATE: | ||
136 | info = (TipWndInfo *)malloc(sizeof(TipWndInfo)); | ||
137 | info->icon = NULL; | ||
138 | info->text = NULL; | ||
139 | info->textlen = 0; | ||
140 | info->flags = TIPWND_ANCHOR_TOPLEFT|TIPWND_ALIGN_LEFT; | ||
141 | info->font = NULL; | ||
142 | info->bgcolor = GetSysColor(COLOR_INFOBK); | ||
143 | info->bordercolor = RGB(0,0,0); | ||
144 | info->textcolor = GetSysColor(COLOR_INFOTEXT); | ||
145 | info->hpadding = 2; | ||
146 | info->vpadding = 2; | ||
147 | info->autoshow = 0; | ||
148 | info->autopos = 0; | ||
149 | info->showdelay = 1000; | ||
150 | info->owner = NULL; | ||
151 | info->mousex = info->mousey = -32768; | ||
152 | info->hidden = 0; | ||
153 | info->enabled = 1; | ||
154 | info->ourmousex = info->ourmousey = -32768; | ||
155 | ::SetWindowLong(hwnd, GWL_USERDATA, (LONG)info); | ||
156 | return 0; | ||
157 | |||
158 | case WM_DESTROY: | ||
159 | if (info != NULL) { | ||
160 | if (info->font != NULL) ::DeleteObject(info->font); | ||
161 | if (info->text != NULL) free(info->text); | ||
162 | free(info); | ||
163 | } | ||
164 | return 0; | ||
165 | |||
166 | case WM_PAINT: | ||
167 | { | ||
168 | PAINTSTRUCT ps; | ||
169 | HDC dc = ::BeginPaint(hwnd, &ps); | ||
170 | |||
171 | RECT rect; | ||
172 | ::GetClientRect(hwnd, &rect); | ||
173 | rect.right -= rect.left; | ||
174 | rect.bottom -= rect.top; | ||
175 | rect.top = 0; | ||
176 | rect.left = 0; | ||
177 | |||
178 | ::SetBkMode(dc, TRANSPARENT); | ||
179 | ::SetTextAlign(dc, TA_TOP|TA_LEFT); | ||
180 | |||
181 | HFONT font = SetBestFont(dc, info); | ||
182 | |||
183 | SIZE textsize; | ||
184 | ComputeTextExtents(dc, info, &textsize); | ||
185 | POINT textpoint; | ||
186 | |||
187 | SIZE pad; | ||
188 | pad.cx = pad.cy = 0; | ||
189 | SIZE iconoffset; | ||
190 | iconoffset.cx = iconoffset.cy = 0; | ||
191 | if (info->icon != NULL) { | ||
192 | int delta = (info->flags & 1) ? 32 : 16; | ||
193 | switch (info->flags & 6) { | ||
194 | case TIPWND_ICON_LEFT: | ||
195 | pad.cx = delta + 4; | ||
196 | iconoffset.cx = 0; | ||
197 | textsize.cx += delta + 4; | ||
198 | if (textsize.cy < delta) | ||
199 | pad.cy = (delta-textsize.cy)/2, textsize.cy = delta; | ||
200 | break; | ||
201 | case TIPWND_ICON_RIGHT: | ||
202 | pad.cx = 0; | ||
203 | iconoffset.cx = textsize.cx + 4; | ||
204 | textsize.cx += delta + 4; | ||
205 | if (textsize.cy < delta) | ||
206 | pad.cy = (delta-textsize.cy)/2, textsize.cy = delta; | ||
207 | break; | ||
208 | case TIPWND_ICON_TOP: | ||
209 | pad.cy = delta + 2; | ||
210 | iconoffset.cx = 0; | ||
211 | textsize.cy += delta + 2; | ||
212 | if (textsize.cx < delta) | ||
213 | pad.cx = (delta-textsize.cx)/2, textsize.cx = delta; | ||
214 | break; | ||
215 | case TIPWND_ICON_BOTTOM: | ||
216 | pad.cy = 0; | ||
217 | iconoffset.cy = textsize.cy + 2; | ||
218 | textsize.cy += delta + 2; | ||
219 | if (textsize.cx < delta) | ||
220 | pad.cx = (delta-textsize.cx)/2, textsize.cx = delta; | ||
221 | break; | ||
222 | } | ||
223 | } | ||
224 | |||
225 | if ((info->flags & (TIPWND_ALIGN_LEFT|TIPWND_ALIGN_RIGHT)) == TIPWND_ALIGN_LEFT) | ||
226 | textpoint.x = 1+info->hpadding; | ||
227 | else if ((info->flags & (TIPWND_ALIGN_LEFT|TIPWND_ALIGN_RIGHT)) == TIPWND_ALIGN_RIGHT) | ||
228 | textpoint.x = rect.right - 1 - info->hpadding - textsize.cx; | ||
229 | else textpoint.x = rect.right / 2 - textsize.cx / 2; | ||
230 | |||
231 | if ((info->flags & (TIPWND_ALIGN_TOP|TIPWND_ALIGN_BOTTOM)) == TIPWND_ALIGN_TOP) | ||
232 | textpoint.y = 1+info->vpadding; | ||
233 | else if ((info->flags & (TIPWND_ALIGN_TOP|TIPWND_ALIGN_BOTTOM)) == TIPWND_ALIGN_BOTTOM) | ||
234 | textpoint.y = rect.bottom - 1 - info->vpadding - textsize.cy; | ||
235 | else textpoint.y = rect.bottom / 2 - textsize.cy / 2; | ||
236 | |||
237 | if (info->icon != NULL) | ||
238 | ::DrawIcon(dc, textpoint.x+iconoffset.cx, | ||
239 | textpoint.y+iconoffset.cy, info->icon); | ||
240 | textpoint.x += pad.cx; | ||
241 | textpoint.y += pad.cy; | ||
242 | DrawMultilineText(dc, info, &textpoint); | ||
243 | |||
244 | ::SelectObject(dc, font); | ||
245 | ::EndPaint(hwnd, &ps); | ||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | case WM_ERASEBKGND: | ||
250 | { | ||
251 | HDC dc = (HDC)wParam; | ||
252 | |||
253 | RECT rect; | ||
254 | ::GetClientRect(hwnd, &rect); | ||
255 | rect.right -= rect.left; | ||
256 | rect.bottom -= rect.top; | ||
257 | rect.top = 0; | ||
258 | rect.left = 0; | ||
259 | |||
260 | HBRUSH bgcolor = ::CreateSolidBrush(info->bgcolor); | ||
261 | HBRUSH border = ::CreateSolidBrush(info->bordercolor); | ||
262 | ::FrameRect(dc, &rect, border); | ||
263 | rect.top++, rect.left++; | ||
264 | rect.right--, rect.bottom--; | ||
265 | ::FillRect(dc, &rect, bgcolor); | ||
266 | ::DeleteObject(bgcolor); | ||
267 | ::DeleteObject(border); | ||
268 | } | ||
269 | return 1; | ||
270 | |||
271 | case WM_SETICON: | ||
272 | if (info->icon == (HICON)lParam) return 0; | ||
273 | info->icon = (HICON)lParam; | ||
274 | info->flags &= ~TIPWND_LARGE_ICON; | ||
275 | if (wParam == ICON_BIG) info->flags |= TIPWND_LARGE_ICON; | ||
276 | ::RedrawWindow(hwnd, NULL, NULL, RDW_ERASE|RDW_INTERNALPAINT); | ||
277 | return 0; | ||
278 | |||
279 | case WM_GETICON: | ||
280 | return (LRESULT)info->icon; | ||
281 | |||
282 | case WM_CLEAR: | ||
283 | if (info->text == NULL) return 0; | ||
284 | free(info->text); | ||
285 | info->textlen = 0; | ||
286 | info->text = NULL; | ||
287 | ::RedrawWindow(hwnd, NULL, NULL, RDW_ERASE|RDW_INTERNALPAINT); | ||
288 | return 0; | ||
289 | |||
290 | case WM_SETTEXT: | ||
291 | if ((const char *)lParam == NULL) lParam = (LPARAM)"<null>"; | ||
292 | if (info->text != NULL) { | ||
293 | if (!strcmp(info->text, (const char *)lParam)) return 0; | ||
294 | free(info->text); | ||
295 | } | ||
296 | info->textlen = strlen((const char *)lParam); | ||
297 | info->text = (char *)malloc(info->textlen+1); | ||
298 | strcpy(info->text, (const char *)lParam); | ||
299 | ::RedrawWindow(hwnd, NULL, NULL, RDW_ERASE|RDW_INTERNALPAINT); | ||
300 | return 0; | ||
301 | |||
302 | case WM_GETTEXT: | ||
303 | if (lParam != NULL) { | ||
304 | strncpy((char *)lParam, info->text, (int)wParam); | ||
305 | ((char *)lParam)[wParam-1] = '\0'; | ||
306 | if ((int)wParam > (int)info->textlen) return (LRESULT)info->textlen; | ||
307 | else return (LRESULT)wParam; | ||
308 | } | ||
309 | return 0; | ||
310 | |||
311 | case WM_GETTEXTLENGTH: | ||
312 | return (LRESULT)info->textlen; | ||
313 | |||
314 | case WM_SETFONT: | ||
315 | if (info->font != NULL) ::DeleteObject(info->font); | ||
316 | info->font = (HFONT)wParam; | ||
317 | if (lParam != 0) ::RedrawWindow(hwnd, NULL, NULL, RDW_ERASE|RDW_INTERNALPAINT); | ||
318 | return 0; | ||
319 | |||
320 | case WM_GETFONT: | ||
321 | return (LRESULT)info->font; | ||
322 | |||
323 | case WM_ENABLE: | ||
324 | if (wParam) { | ||
325 | if (!info->enabled) { | ||
326 | info->enabled = 1; | ||
327 | if (info->autoshow) { | ||
328 | if (info->timer == 0) | ||
329 | info->timer = ::SetTimer(hwnd, 1, info->showdelay, NULL); | ||
330 | if (info->hidetimer == 0) | ||
331 | info->hidetimer = ::SetTimer(hwnd, 2, 250, NULL); | ||
332 | } | ||
333 | } | ||
334 | } | ||
335 | else { | ||
336 | if (info->enabled) { | ||
337 | info->enabled = 0; | ||
338 | if (info->timer != 0) ::KillTimer(hwnd, 1); | ||
339 | if (info->hidetimer != 0) ::KillTimer(hwnd, 2); | ||
340 | info->timer = 0; | ||
341 | info->hidetimer = 0; | ||
342 | if (info->autoshow) { | ||
343 | info->mousex = info->mousey = -32768; | ||
344 | info->ourmousex = info->ourmousey = -32768; | ||
345 | if (!info->hidden) info->hidden = 1, ::ShowWindow(hwnd, SW_HIDE); | ||
346 | } | ||
347 | } | ||
348 | } | ||
349 | return 0; | ||
350 | |||
351 | case WM_COMMAND: | ||
352 | switch (wParam) { | ||
353 | |||
354 | case TW_AUTO_SIZE: | ||
355 | { | ||
356 | SIZE size; | ||
357 | HDC dc = ::GetDC(hwnd); | ||
358 | HFONT oldfont = SetBestFont(dc, info); | ||
359 | ComputeTextExtents(dc, info, &size); | ||
360 | ::SelectObject(dc, oldfont); | ||
361 | ::ReleaseDC(hwnd, dc); | ||
362 | if (info->icon != NULL) { | ||
363 | int delta = (info->flags & 1) ? 32 : 16; | ||
364 | switch (info->flags & 6) { | ||
365 | case TIPWND_ICON_LEFT: | ||
366 | case TIPWND_ICON_RIGHT: | ||
367 | size.cx += delta + info->hpadding*2; | ||
368 | if (size.cy < delta) size.cy = delta; | ||
369 | break; | ||
370 | case TIPWND_ICON_TOP: | ||
371 | case TIPWND_ICON_BOTTOM: | ||
372 | size.cy += delta + info->vpadding*2; | ||
373 | if (size.cx < delta) size.cx = delta; | ||
374 | break; | ||
375 | } | ||
376 | } | ||
377 | |||
378 | RECT rect; | ||
379 | ::GetWindowRect(hwnd, &rect); | ||
380 | if (rect.right-rect.left != size.cx+2+info->hpadding*2 | ||
381 | || rect.bottom-rect.top != size.cy+2+info->vpadding*2) | ||
382 | ::SetWindowPos(hwnd, NULL, rect.left, rect.top, | ||
383 | size.cx+2+info->hpadding*2, size.cy+2+info->vpadding*2, | ||
384 | SWP_NOACTIVATE|SWP_NOZORDER); | ||
385 | else ::RedrawWindow(hwnd, NULL, NULL, RDW_ERASE|RDW_INTERNALPAINT); | ||
386 | } | ||
387 | return 0; | ||
388 | |||
389 | case TW_SET_ANCHOR: | ||
390 | info->flags &= ~(8|16|32|64); | ||
391 | info->flags |= ((lParam & 15) << 3); | ||
392 | return 0; | ||
393 | |||
394 | case TW_GET_ANCHOR: | ||
395 | return (LRESULT)((info->flags >> 3) & (8|16|32|64)); | ||
396 | |||
397 | case TW_SET_ICONPOS: | ||
398 | if ((info->flags & 6) != ((lParam & 3) << 1)) { | ||
399 | info->flags &= ~(2|4); | ||
400 | info->flags |= ((lParam & 3) << 1); | ||
401 | ::RedrawWindow(hwnd, NULL, NULL, RDW_ERASE|RDW_INTERNALPAINT); | ||
402 | } | ||
403 | return 0; | ||
404 | |||
405 | case TW_GET_ICONPOS: | ||
406 | return (LRESULT)((info->flags >> 1) & 3); | ||
407 | |||
408 | case TW_SET_BGCOLOR: | ||
409 | if (lParam != (LPARAM)info->bgcolor) { | ||
410 | info->bgcolor = lParam; | ||
411 | ::RedrawWindow(hwnd, NULL, NULL, RDW_ERASE|RDW_INTERNALPAINT); | ||
412 | } | ||
413 | return 0; | ||
414 | |||
415 | case TW_GET_BGCOLOR: | ||
416 | return (LRESULT)info->bgcolor; | ||
417 | |||
418 | case TW_SET_TEXTCOLOR: | ||
419 | if (lParam != (LPARAM)info->textcolor) { | ||
420 | info->textcolor = lParam; | ||
421 | ::RedrawWindow(hwnd, NULL, NULL, RDW_ERASE|RDW_INTERNALPAINT); | ||
422 | } | ||
423 | return 0; | ||
424 | |||
425 | case TW_GET_TEXTCOLOR: | ||
426 | return (LRESULT)info->textcolor; | ||
427 | |||
428 | case TW_SET_BORDERCOLOR: | ||
429 | if (lParam != (LPARAM)info->bordercolor) { | ||
430 | info->bordercolor = lParam; | ||
431 | ::RedrawWindow(hwnd, NULL, NULL, RDW_ERASE|RDW_INTERNALPAINT); | ||
432 | } | ||
433 | return 0; | ||
434 | |||
435 | case TW_GET_BORDERCOLOR: | ||
436 | return (LRESULT)info->bordercolor; | ||
437 | |||
438 | case TW_SET_AUTOSHOW: | ||
439 | if (info->autoshow != lParam) { | ||
440 | info->autoshow = (lParam != 0); | ||
441 | if (info->timer != 0) { | ||
442 | ::KillTimer(hwnd, info->timer); | ||
443 | info->timer = 0; | ||
444 | } | ||
445 | if (info->hidetimer != 0) { | ||
446 | ::KillTimer(hwnd, info->hidetimer); | ||
447 | info->hidetimer = 0; | ||
448 | } | ||
449 | if (info->autoshow) { | ||
450 | info->timer = ::SetTimer(hwnd, 1, info->showdelay, NULL); | ||
451 | info->hidetimer = ::SetTimer(hwnd, 2, 250, NULL); | ||
452 | } | ||
453 | } | ||
454 | return 0; | ||
455 | |||
456 | case TW_GET_AUTOSHOW: | ||
457 | return info->autoshow; | ||
458 | |||
459 | case TW_SET_SHOWDELAY: | ||
460 | if (info->showdelay != lParam) { | ||
461 | info->showdelay = (short int)lParam; | ||
462 | if (info->showdelay < 1) info->showdelay = 1; | ||
463 | if (info->timer != 0) { | ||
464 | ::KillTimer(hwnd, info->timer); | ||
465 | info->timer = 0; | ||
466 | info->hidetimer = 0; | ||
467 | } | ||
468 | if (info->autoshow) { | ||
469 | info->timer = ::SetTimer(hwnd, 1, info->showdelay, NULL); | ||
470 | } | ||
471 | } | ||
472 | return 0; | ||
473 | |||
474 | case TW_GET_SHOWDELAY: | ||
475 | return info->showdelay; | ||
476 | |||
477 | case TW_SET_AUTOPOS: | ||
478 | info->autopos = (lParam != 0); | ||
479 | return 0; | ||
480 | |||
481 | case TW_GET_AUTOPOS: | ||
482 | return info->autopos; | ||
483 | |||
484 | case TW_SET_HPADDING: | ||
485 | if (info->hpadding != (int)lParam) { | ||
486 | info->hpadding = (int)lParam; | ||
487 | ::RedrawWindow(hwnd, NULL, NULL, RDW_ERASE|RDW_INTERNALPAINT); | ||
488 | } | ||
489 | return 0; | ||
490 | |||
491 | case TW_GET_HPADDING: | ||
492 | return info->hpadding; | ||
493 | |||
494 | case TW_SET_VPADDING: | ||
495 | if (info->vpadding != (int)lParam) { | ||
496 | info->vpadding = (int)lParam; | ||
497 | ::RedrawWindow(hwnd, NULL, NULL, RDW_ERASE|RDW_INTERNALPAINT); | ||
498 | } | ||
499 | return 0; | ||
500 | |||
501 | case TW_GET_VPADDING: | ||
502 | return info->vpadding; | ||
503 | |||
504 | case TW_GET_OWNER: | ||
505 | return (LRESULT)info->owner; | ||
506 | |||
507 | case TW_REFLECT_MESSAGE: | ||
508 | { | ||
509 | MSG *msg = (MSG *)lParam; | ||
510 | if (msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONUP | ||
511 | || msg->message == WM_RBUTTONDOWN || msg->message == WM_RBUTTONUP | ||
512 | || msg->message == WM_MBUTTONDOWN || msg->message == WM_MBUTTONUP | ||
513 | || msg->message == WM_MOUSEMOVE || msg->message == WM_KILLFOCUS | ||
514 | || msg->message == WM_SETFOCUS || msg->message == WM_KEYDOWN | ||
515 | || msg->message == WM_KEYUP) { | ||
516 | if (msg->message == WM_MOUSEMOVE) { | ||
517 | if (info->mousex == LOWORD(msg->lParam) | ||
518 | && info->mousey == HIWORD(msg->lParam)) return 0; | ||
519 | info->mousex = LOWORD(msg->lParam); | ||
520 | info->mousey = HIWORD(msg->lParam); | ||
521 | } | ||
522 | if (info->timer != 0 && info->showdelay > 1) { | ||
523 | ::KillTimer(hwnd, info->timer); | ||
524 | info->timer = 0; | ||
525 | info->hidetimer = 0; | ||
526 | info->mousex = info->mousey = -32768; | ||
527 | info->ourmousex = info->ourmousey = -32768; | ||
528 | if (!info->hidden) info->hidden = 1, ::ShowWindow(hwnd, SW_HIDE); | ||
529 | } | ||
530 | if (info->autoshow && msg->message != WM_KILLFOCUS) { | ||
531 | info->timer = ::SetTimer(hwnd, 1, info->showdelay, NULL); | ||
532 | } | ||
533 | } | ||
534 | } | ||
535 | return 0; | ||
536 | |||
537 | default: | ||
538 | return 0; | ||
539 | } | ||
540 | |||
541 | case WM_LBUTTONDOWN: | ||
542 | case WM_LBUTTONUP: | ||
543 | case WM_RBUTTONDOWN: | ||
544 | case WM_RBUTTONUP: | ||
545 | case WM_MBUTTONDOWN: | ||
546 | case WM_MBUTTONUP: | ||
547 | { | ||
548 | POINT point; | ||
549 | point.x = LOWORD(lParam); | ||
550 | point.y = HIWORD(lParam); | ||
551 | ::ClientToScreen(hwnd, &point); | ||
552 | ::ScreenToClient(info->owner, &point); | ||
553 | ::SendMessage(info->owner, uMsg, wParam, MAKELPARAM(point.x, point.y)); | ||
554 | } | ||
555 | return 0; | ||
556 | |||
557 | case WM_MOUSEMOVE: | ||
558 | { | ||
559 | POINT point; | ||
560 | point.x = LOWORD(lParam); | ||
561 | point.y = HIWORD(lParam); | ||
562 | if (point.x != info->ourmousex || point.y != info->ourmousey) { | ||
563 | info->ourmousex = point.x, info->ourmousey = point.y; | ||
564 | ::ClientToScreen(hwnd, &point); | ||
565 | ::ScreenToClient(info->owner, &point); | ||
566 | ::SendMessage(info->owner, uMsg, wParam, MAKELPARAM(point.x, point.y)); | ||
567 | } | ||
568 | } | ||
569 | return 0; | ||
570 | |||
571 | case WM_TIMER: | ||
572 | if (wParam == 1) { | ||
573 | if (info->timer != 0) { | ||
574 | ::KillTimer(hwnd, info->timer); | ||
575 | info->timer = 0; | ||
576 | info->hidetimer = 0; | ||
577 | } | ||
578 | if (info->autoshow) { | ||
579 | if (info->autopos) { | ||
580 | RECT rect; | ||
581 | POINT point; | ||
582 | ::GetWindowRect(hwnd, &rect); | ||
583 | ::GetCursorPos(&point); | ||
584 | if (point.x + (rect.right-rect.left) > GetSystemMetrics(SM_CXSCREEN) - 16) | ||
585 | point.x = GetSystemMetrics(SM_CXSCREEN) - (rect.right-rect.left) - 16; | ||
586 | if (point.y + (rect.bottom-rect.top) > GetSystemMetrics(SM_CYSCREEN) - 16) | ||
587 | point.y = GetSystemMetrics(SM_CYSCREEN) - (rect.bottom-rect.top) - 16; | ||
588 | if (rect.left != point.x+16 || rect.top != point.y+16) { | ||
589 | ::SetWindowPos(hwnd, NULL, point.x+16, point.y+16, | ||
590 | rect.right-rect.left, rect.bottom-rect.top, SWP_NOACTIVATE|SWP_NOZORDER); | ||
591 | info->ourmousex = info->ourmousey = -32768; | ||
592 | } | ||
593 | else ::RedrawWindow(hwnd, NULL, NULL, RDW_ERASE|RDW_INTERNALPAINT); | ||
594 | } | ||
595 | if (::IsWindowEnabled(hwnd)) { | ||
596 | ::BringWindowToTop(hwnd); | ||
597 | if (info->hidden) info->hidden = 0, ::ShowWindow(hwnd, SW_SHOWNOACTIVATE); | ||
598 | ::UpdateWindow(hwnd); | ||
599 | } | ||
600 | if (info->hidetimer == 0) | ||
601 | info->hidetimer = ::SetTimer(hwnd, 2, 250, NULL); | ||
602 | } | ||
603 | } | ||
604 | else if (wParam == 2) { | ||
605 | // If the mouse is no longer in the window and we're using autoshow, | ||
606 | // hide the tip with a quickness. | ||
607 | POINT point; | ||
608 | ::GetCursorPos(&point); | ||
609 | HWND wnd = ::WindowFromPoint(point); | ||
610 | // If the window the mouse is over is a TipWnd, then the mouse is | ||
611 | // really just over that TipWnd's owner. | ||
612 | char cname[32]; | ||
613 | ::GetClassName(wnd, cname, 31); | ||
614 | if (!strcmp(cname, CLASSNAME)) | ||
615 | wnd = (HWND)::SendMessage(wnd, WM_COMMAND, TW_GET_OWNER, 0); | ||
616 | // If the mouse has moved out of this TipWnd's owner, hide the TipWnd. | ||
617 | if (wnd != info->owner) { | ||
618 | ::KillTimer(hwnd, info->timer); | ||
619 | ::KillTimer(hwnd, info->hidetimer); | ||
620 | info->timer = 0; | ||
621 | info->hidetimer = 0; | ||
622 | info->mousex = info->mousey = -32768; | ||
623 | info->ourmousex = info->ourmousey = -32768; | ||
624 | if (!info->hidden) info->hidden = 1, ::ShowWindow(hwnd, SW_HIDE); | ||
625 | } | ||
626 | } | ||
627 | return 0; | ||
628 | |||
629 | default: | ||
630 | return ::DefWindowProc(hwnd, uMsg, wParam, lParam); | ||
631 | } | ||
632 | } | ||
633 | |||
634 | /***************************************************************************/ | ||
635 | |||
636 | static HINSTANCE theInst; | ||
637 | |||
638 | void WINAPI ::InitTipWnd(HINSTANCE inst) | ||
639 | { | ||
640 | static bool initted = 0; | ||
641 | |||
642 | if (initted) return; | ||
643 | |||
644 | WNDCLASSEX wc; | ||
645 | |||
646 | wc.cbSize = sizeof(WNDCLASSEX); | ||
647 | wc.cbClsExtra = 0; | ||
648 | wc.cbWndExtra = sizeof(void *); | ||
649 | wc.hbrBackground = NULL; | ||
650 | wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); | ||
651 | wc.hIcon = NULL; | ||
652 | wc.hIconSm = NULL; | ||
653 | wc.hInstance = theInst; | ||
654 | wc.lpszClassName = CLASSNAME; | ||
655 | wc.lpszMenuName = NULL; | ||
656 | wc.style = CS_VREDRAW|CS_HREDRAW|CS_SAVEBITS; | ||
657 | wc.lpfnWndProc = TipWndProc; | ||
658 | |||
659 | ::RegisterClassEx(&wc); | ||
660 | |||
661 | initted = 1; | ||
662 | } | ||
663 | |||
664 | HWND WINAPI ::CreateTipWnd(HWND owner, const RECT *rect, BOOL showwnd) | ||
665 | { | ||
666 | HWND hwnd = ::CreateWindowEx(WS_EX_TOPMOST, CLASSNAME, "", WS_POPUP, | ||
667 | rect->left, rect->top, rect->right-rect->left, rect->bottom-rect->top, | ||
668 | owner, NULL, theInst, NULL); | ||
669 | TipWndInfo *info = (TipWndInfo *)::GetWindowLong(hwnd, GWL_USERDATA); | ||
670 | if (info != NULL) info->owner = owner; | ||
671 | return hwnd; | ||
672 | } | ||
673 | |||
674 | HWND WINAPI ::CreateTipWndEz(HWND owner, int x, int y, | ||
675 | const char *text, HICON icon, BOOL showwnd) | ||
676 | { | ||
677 | POINT point; | ||
678 | point.x = x, point.y = y; | ||
679 | ::ClientToScreen(owner, &point); | ||
680 | RECT rect; | ||
681 | rect.left = point.x, rect.top = point.y; | ||
682 | rect.right = point.x + 64, rect.bottom = point.y + 16; | ||
683 | |||
684 | HWND wnd = CreateTipWnd(owner, &rect, 0); | ||
685 | if (wnd == NULL) return NULL; | ||
686 | |||
687 | TipWnd_SetText(wnd, text); | ||
688 | TipWnd_SetIcon(wnd, icon, ICON_BIG); | ||
689 | |||
690 | if (showwnd) { | ||
691 | ::BringWindowToTop(wnd); | ||
692 | ::ShowWindow(wnd, SW_SHOWNOACTIVATE); | ||
693 | ::UpdateWindow(wnd); | ||
694 | } | ||
695 | |||
696 | return wnd; | ||
697 | } | ||
698 | |||
699 | /***************************************************************************/ | ||
700 | |||
701 | /* The MFC class wrapper. Very simple, since the Windows HWND does | ||
702 | all the real work. */ | ||
703 | |||
704 | IMPLEMENT_DYNAMIC(CTipWnd, CWnd) | ||
705 | |||
706 | CTipWnd::CTipWnd() | ||
707 | { | ||
708 | } | ||
709 | |||
710 | CTipWnd::~CTipWnd() | ||
711 | { | ||
712 | DestroyWindow(); | ||
713 | } | ||
714 | |||
715 | BOOL CTipWnd::Create(CWnd *owner, const RECT &rect, BOOL showwnd) | ||
716 | { | ||
717 | CWnd *pWnd = this; | ||
718 | if (!pWnd->CreateEx(WS_EX_TOPMOST, _T(CLASSNAME), _T(""), WS_POPUP, rect, owner, 0, NULL)) | ||
719 | return 0; | ||
720 | TipWndInfo *info = (TipWndInfo *)::GetWindowLong(m_hWnd, GWL_USERDATA); | ||
721 | if (info != NULL) info->owner = owner->m_hWnd; | ||
722 | |||
723 | if (showwnd) { | ||
724 | pWnd->BringWindowToTop(); | ||
725 | pWnd->ShowWindow(SW_SHOWNOACTIVATE); | ||
726 | pWnd->UpdateWindow(); | ||
727 | } | ||
728 | |||
729 | return 1; | ||
730 | } | ||
731 | |||
732 | BOOL CTipWnd::CreateEz(CWnd *owner, int x, int y, const CString &text, | ||
733 | HICON icon, BOOL showwnd) | ||
734 | { | ||
735 | CPoint point(x, y); | ||
736 | owner->ClientToScreen(&point); | ||
737 | CRect rect(point.x, point.y, point.x+64, point.y+16); | ||
738 | |||
739 | if (!Create(owner, rect, 0)) return 0; | ||
740 | |||
741 | SetWindowText(text); | ||
742 | SetIcon(icon, 1); | ||
743 | |||
744 | if (showwnd) { | ||
745 | BringWindowToTop(); | ||
746 | ShowWindow(SW_SHOWNOACTIVATE); | ||
747 | UpdateWindow(); | ||
748 | } | ||
749 | |||
750 | return 1; | ||
751 | } | ||
752 | |||
753 | void CTipWnd::MoveWindow(CWnd *owner, int x, int y) | ||
754 | { | ||
755 | CPoint point(x, y); | ||
756 | owner->ClientToScreen(&point); | ||
757 | SetWindowPos(NULL, point.x, point.y, 0, 0, SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE); | ||
758 | } | ||
759 | |||
760 | void CTipWnd::PushOnScreen(void) | ||
761 | { | ||
762 | CRect rect; | ||
763 | GetWindowRect(&rect); | ||
764 | short int scrnwidth = GetSystemMetrics(SM_CXSCREEN); | ||
765 | short int scrnheight = GetSystemMetrics(SM_CYSCREEN); | ||
766 | if (rect.right > scrnwidth) | ||
767 | rect.left -= rect.right-scrnwidth, rect.right = scrnwidth; | ||
768 | if (rect.bottom > scrnheight) | ||
769 | rect.top -= rect.bottom-scrnheight, rect.top = scrnheight; | ||
770 | if (rect.left < 0) | ||
771 | rect.right -= 0-rect.left, rect.left = 0; | ||
772 | if (rect.top < 0) | ||
773 | rect.bottom -= 0-rect.top, rect.top = 0; | ||
774 | SetWindowPos(NULL, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, | ||
775 | SWP_NOACTIVATE|SWP_NOZORDER|SWP_NOSIZE); | ||
776 | } | ||
777 | |||
778 | // MFC's default handling of OnCommand screws up our message-passing, so | ||
779 | // we override to fix it. | ||
780 | BOOL CTipWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT *pResult) | ||
781 | { | ||
782 | if (message == WM_COMMAND) { | ||
783 | *pResult = TipWndProc(m_hWnd, message, wParam, lParam); | ||
784 | return 1; | ||
785 | } | ||
786 | else return CWnd::OnWndMsg(message, wParam, lParam, pResult); | ||
787 | } | ||
788 | |||
789 | /***************************************************************************/ | ||
diff --git a/TipWnd.h b/TipWnd.h new file mode 100644 index 0000000..b40ead0 --- /dev/null +++ b/TipWnd.h | |||
@@ -0,0 +1,203 @@ | |||
1 | #ifndef TIPWND_H | ||
2 | #define TIPWND_H | ||
3 | |||
4 | /* TipWnd messages */ | ||
5 | enum { | ||
6 | TW_AUTO_SIZE = 101, | ||
7 | TW_SET_ANCHOR = 102, | ||
8 | TW_GET_ANCHOR = 103, | ||
9 | TW_SET_ICONPOS = 104, | ||
10 | TW_GET_ICONPOS = 105, | ||
11 | TW_SET_BGCOLOR = 106, | ||
12 | TW_GET_BGCOLOR = 107, | ||
13 | TW_SET_TEXTCOLOR = 108, | ||
14 | TW_GET_TEXTCOLOR = 109, | ||
15 | TW_SET_BORDERCOLOR = 110, | ||
16 | TW_GET_BORDERCOLOR = 111, | ||
17 | TW_SET_AUTOSHOW = 112, | ||
18 | TW_GET_AUTOSHOW = 113, | ||
19 | TW_SET_AUTOPOS = 114, | ||
20 | TW_GET_AUTOPOS = 115, | ||
21 | TW_SET_SHOWDELAY = 116, | ||
22 | TW_GET_SHOWDELAY = 117, | ||
23 | TW_SET_HPADDING = 118, | ||
24 | TW_GET_HPADDING = 119, | ||
25 | TW_SET_VPADDING = 120, | ||
26 | TW_GET_VPADDING = 121, | ||
27 | TW_GET_OWNER = 122, | ||
28 | TW_REFLECT_MESSAGE = 199, | ||
29 | }; | ||
30 | |||
31 | /* TipWnd message parameters */ | ||
32 | enum { | ||
33 | TW_LEFT = 0, | ||
34 | TW_TOP = 1, | ||
35 | TW_RIGHT = 2, | ||
36 | TW_BOTTOM = 3, | ||
37 | |||
38 | TW_ALIGN_LEFT = 1, | ||
39 | TW_ALIGN_TOP = 2, | ||
40 | TW_ALIGN_RIGHT = 4, | ||
41 | TW_ALIGN_BOTTOM = 8, | ||
42 | |||
43 | TW_ALIGN_TOPLEFT = 1|2, | ||
44 | TW_ALIGN_TOPRIGHT = 2|4, | ||
45 | TW_ALIGN_BOTTOMLEFT = 1|8, | ||
46 | TW_ALIGN_BOTTOMRIGHT = 2|8, | ||
47 | }; | ||
48 | |||
49 | /***************************************************************************/ | ||
50 | |||
51 | /* TipWnd helper macros */ | ||
52 | #define TipWnd_AutoSize(hwnd) \ | ||
53 | SendMessage(hwnd, WM_COMMAND, TW_AUTO_SIZE, 0) | ||
54 | #define TipWnd_SetAnchor(hwnd, anchor) \ | ||
55 | SendMessage(hwnd, WM_COMMAND, TW_SET_ANCHOR, (LPARAM)(anchor)) | ||
56 | #define TipWnd_GetAnchor(hwnd) \ | ||
57 | SendMessage(hwnd, WM_COMMAND, TW_GET_ANCHOR, 0) | ||
58 | #define TipWnd_SetIconPos(hwnd, pos) \ | ||
59 | SendMessage(hwnd, WM_COMMAND, TW_SET_ICONPOS, (LPARAM)(pos)) | ||
60 | #define TipWnd_GetIconPos(hwnd) \ | ||
61 | SendMessage(hwnd, WM_COMMAND, TW_GET_ICONPOS, 0) | ||
62 | #define TipWnd_SetBgColor(hwnd, color) \ | ||
63 | SendMessage(hwnd, WM_COMMAND, TW_SET_BGCOLOR, (LPARAM)(color)) | ||
64 | #define TipWnd_GetBgColor(hwnd) \ | ||
65 | SendMessage(hwnd, WM_COMMAND, TW_GET_BGCOLOR, 0) | ||
66 | #define TipWnd_SetTextColor(hwnd, color) \ | ||
67 | SendMessage(hwnd, WM_COMMAND, TW_SET_TEXTCOLOR, (LPARAM)(color)) | ||
68 | #define TipWnd_GetTextColor(hwnd) \ | ||
69 | SendMessage(hwnd, WM_COMMAND, TW_GET_TEXTCOLOR, 0) | ||
70 | #define TipWnd_SetBorderColor(hwnd, color) \ | ||
71 | SendMessage(hwnd, WM_COMMAND, TW_SET_BORDERCOLOR, (LPARAM)(color)) | ||
72 | #define TipWnd_GetBorderColor(hwnd) \ | ||
73 | SendMessage(hwnd, WM_COMMAND, TW_GET_BORDERCOLOR, 0) | ||
74 | #define TipWnd_SetFont(hwnd, font, redraw) \ | ||
75 | SendMessage(hwnd, WM_SETFONT, (WPARAM)(font), (LPARAM)(redraw)) | ||
76 | #define TipWnd_GetFont(hwnd) \ | ||
77 | SendMessage(hwnd, WM_GETFONT, 0, 0) | ||
78 | #define TipWnd_SetText(hwnd, text) \ | ||
79 | SendMessage(hwnd, WM_SETTEXT, 0, (WPARAM)(text)) | ||
80 | #define TipWnd_GetText(hwnd, buffer, buflen) \ | ||
81 | SendMessage(hwnd, WM_GETTEXT, (WPARAM)(buffer), (LPARAM)(buflen)) | ||
82 | #define TipWnd_GetTextLength(wnd) \ | ||
83 | SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0) | ||
84 | #define TipWnd_SetIcon(hwnd, type, icon) \ | ||
85 | SendMessage(hwnd, WM_SETICON, (WPARAM)(type), (LPARAM)(icon)) | ||
86 | #define TipWnd_GetIcon(hwnd) \ | ||
87 | SendMessage(hwnd, WM_GETICON, 0, 0) | ||
88 | #define TipWnd_SetAutoShow(hwnd, enable) \ | ||
89 | SendMessage(hwnd, WM_COMMAND, TW_SET_AUTOSHOW, (LPARAM)(enable)) | ||
90 | #define TipWnd_GetAutoShow(hwnd) \ | ||
91 | SendMessage(hwnd, WM_COMMAND, TW_GET_AUTOSHOW, 0) | ||
92 | #define TipWnd_SetShowDelay(hwnd, delay) \ | ||
93 | SendMessage(hwnd, WM_COMMAND, TW_SET_SHOWDELAY, (LPARAM)(delay)) | ||
94 | #define TipWnd_GetShowDelay(hwnd) \ | ||
95 | SendMessage(hwnd, WM_COMMAND, TW_GET_SHOWDELAY, 0) | ||
96 | #define TipWnd_ReflectMessage(hwnd, pmsg) \ | ||
97 | SendMessage(hwnd, WM_COMMAND, TW_REFLECT_MESSAGE, (LPARAM)(pmsg)) | ||
98 | #define TipWnd_SetAutoPos(hwnd, pos) \ | ||
99 | SendMessage(hwnd, WM_COMMAND, TW_SET_AUTOPOS, (LPARAM)(pos)) | ||
100 | #define TipWnd_GetAutoPos(hwnd) \ | ||
101 | SendMessage(hwnd, WM_COMMAND, TW_GET_AUTOPOS, 0) | ||
102 | #define TipWnd_SetHPadding(hwnd, padding) \ | ||
103 | SendMessage(hwnd, WM_COMMAND, TW_SET_HPADDING, (WPARAM)(padding)) | ||
104 | #define TipWnd_GetHPadding(hwnd) \ | ||
105 | SendMessage(hwnd, WM_COMMAND, TW_GET_HPADDING, 0) | ||
106 | #define TipWnd_SetVPadding(hwnd, padding) \ | ||
107 | SendMessage(hwnd, WM_COMMAND, TW_SET_VPADDING, (WPARAM)(padding)) | ||
108 | #define TipWnd_GetVPadding(hwnd) \ | ||
109 | SendMessage(hwnd, WM_COMMAND, TW_GET_VPADDING, 0) | ||
110 | #define TipWnd_GetOwner(hwnd) \ | ||
111 | SendMessage(hwnd, WM_COMMAND, TW_GET_OWNER, 0) | ||
112 | |||
113 | /***************************************************************************/ | ||
114 | |||
115 | #ifdef __cplusplus | ||
116 | extern "C" { | ||
117 | #endif | ||
118 | |||
119 | // TipWnd functions | ||
120 | void WINAPI InitTipWnd(HINSTANCE inst); | ||
121 | HWND WINAPI CreateTipWnd(HWND owner, const RECT *rect, BOOL showwnd); | ||
122 | HWND WINAPI CreateTipWndEz(HWND owner, int x, int y, | ||
123 | const char *text, HICON icon, BOOL showwnd); | ||
124 | |||
125 | #ifdef __cplusplus | ||
126 | }; | ||
127 | #endif | ||
128 | |||
129 | /***************************************************************************/ | ||
130 | |||
131 | #ifdef __AFXWIN_H__ | ||
132 | |||
133 | /* MFC support class, if they're using MFC. Like most of the MFC classes, | ||
134 | it's just a wrapper around the Windows HWND. You still have to call | ||
135 | InitTipWnd() somewhere at the beginning of your program, though. */ | ||
136 | |||
137 | class CTipWnd : public CWnd { | ||
138 | DECLARE_DYNAMIC(CTipWnd) | ||
139 | |||
140 | public: | ||
141 | CTipWnd(); | ||
142 | virtual ~CTipWnd(); | ||
143 | virtual BOOL Create(CWnd *owner, const RECT &rect, BOOL showwnd = 0); | ||
144 | virtual BOOL CreateEz(CWnd *owner, int x, int y, const CString &text = "", | ||
145 | HICON icon = NULL, BOOL showwnd = 0); | ||
146 | void MoveWindow(CWnd *owner, int x, int y); | ||
147 | void PushOnScreen(void); | ||
148 | |||
149 | protected: | ||
150 | virtual BOOL OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT *pResult); | ||
151 | |||
152 | public: | ||
153 | inline void AutoSize(void) | ||
154 | { SendMessage(WM_COMMAND, TW_AUTO_SIZE); } | ||
155 | inline void SetAnchor(int anchor) | ||
156 | { SendMessage(WM_COMMAND, TW_SET_ANCHOR, (LPARAM)anchor); } | ||
157 | inline int GetAnchor(void) | ||
158 | { return SendMessage(WM_COMMAND, TW_GET_ANCHOR); } | ||
159 | inline void SetIconPos(int iconpos) | ||
160 | { SendMessage(WM_COMMAND, TW_SET_ICONPOS, (LPARAM)iconpos); } | ||
161 | inline int GetIconPos(void) | ||
162 | { return SendMessage(WM_COMMAND, TW_GET_ICONPOS); } | ||
163 | inline void SetBgColor(COLORREF color) | ||
164 | { SendMessage(WM_COMMAND, TW_SET_BGCOLOR, (LPARAM)color); } | ||
165 | inline int GetBgColor(void) | ||
166 | { return SendMessage(WM_COMMAND, TW_GET_BGCOLOR); } | ||
167 | inline void SetTextColor(COLORREF color) | ||
168 | { SendMessage(WM_COMMAND, TW_SET_TEXTCOLOR, (LPARAM)color); } | ||
169 | inline int GetTextColor(void) | ||
170 | { return SendMessage(WM_COMMAND, TW_GET_TEXTCOLOR); } | ||
171 | inline void SetBorderColor(COLORREF color) | ||
172 | { SendMessage(WM_COMMAND, TW_SET_BORDERCOLOR, (LPARAM)color); } | ||
173 | inline int GetBorderColor(void) | ||
174 | { return SendMessage(WM_COMMAND, TW_GET_BORDERCOLOR); } | ||
175 | inline void SetAutoShow(BOOL bEnable) | ||
176 | { SendMessage(WM_COMMAND, TW_SET_AUTOSHOW, (LPARAM)bEnable); } | ||
177 | inline BOOL GetAutoShow(void) | ||
178 | { return (BOOL)SendMessage(WM_COMMAND, TW_GET_AUTOSHOW); } | ||
179 | inline void SetShowDelay(int delay) | ||
180 | { SendMessage(WM_COMMAND, TW_SET_SHOWDELAY, (LPARAM)delay); } | ||
181 | inline int GetShowDelay(void) | ||
182 | { return SendMessage(WM_COMMAND, TW_GET_SHOWDELAY); } | ||
183 | inline void SetAutoPos(BOOL bAutoPos) | ||
184 | { SendMessage(WM_COMMAND, TW_SET_AUTOPOS, (LPARAM)bAutoPos); } | ||
185 | inline int GetAutoPos(void) | ||
186 | { return SendMessage(WM_COMMAND, TW_GET_AUTOPOS); } | ||
187 | inline void ReflectMessage(const MSG *msg) | ||
188 | { SendMessage(WM_COMMAND, TW_REFLECT_MESSAGE, (LPARAM)msg); } | ||
189 | inline void SetHPadding(int padding) | ||
190 | { SendMessage(WM_COMMAND, TW_SET_HPADDING, (LPARAM)padding); } | ||
191 | inline int GetHPadding(void) | ||
192 | { return SendMessage(WM_COMMAND, TW_GET_HPADDING); } | ||
193 | inline void SetVPadding(int padding) | ||
194 | { SendMessage(WM_COMMAND, TW_SET_VPADDING, (LPARAM)padding); } | ||
195 | inline int GetVPadding(void) | ||
196 | { return SendMessage(WM_COMMAND, TW_GET_VPADDING); } | ||
197 | inline CWnd *GetTipWndOwner(void) | ||
198 | { return CWnd::FromHandle((HWND)SendMessage(WM_COMMAND, TW_GET_OWNER)); } | ||
199 | }; | ||
200 | |||
201 | #endif | ||
202 | |||
203 | #endif | ||
@@ -0,0 +1,51 @@ | |||
1 | |||
2 | #ifndef LANG_H | ||
3 | #define LANG_H | ||
4 | |||
5 | struct Lang { | ||
6 | int toolbar_bitmap_id; | ||
7 | const char *about_spacemonger; | ||
8 | const char *freeware; | ||
9 | const char *warranty; | ||
10 | const char *email; | ||
11 | const char *ok, *cancel; | ||
12 | const char *bytes, *kb, *mb, *gb; | ||
13 | const char *freespace_format; | ||
14 | const char *zoomin, *zoomout, *zoomfull, *run, *del; | ||
15 | const char *opendrive, *rescandrive, *showfreespace; | ||
16 | const char *percent_format, *size_format; | ||
17 | const char *total, *free, *files_total, *folders_total, *files_found, *folders_found; | ||
18 | char digitpt, digitcomma; | ||
19 | const char **densitynames; | ||
20 | const char **colornames; | ||
21 | const char **monthnames; | ||
22 | const char **attribnames; | ||
23 | const char *deleting; | ||
24 | const char *selectdrive; | ||
25 | const char *scanning; | ||
26 | const char *settings; | ||
27 | const char *layout, *density, *bias, *horz, *equal, *vert; | ||
28 | const char *displaycolors, *files, *folders; | ||
29 | const char *tooltips, *shownametips, *showinfotips, *delay, *msec; | ||
30 | const char *fullpath, *filename, *smallicon, *icon, *datetime, *filesize, *attrib; | ||
31 | const char *miscoptions; | ||
32 | const char *autorescan, *disabledelete, *animatedzoom, *savepos; | ||
33 | const char *showrolloverbox; | ||
34 | const char *properties; | ||
35 | }; | ||
36 | |||
37 | struct LangEntry { | ||
38 | const char *abbrev; | ||
39 | const char *name; | ||
40 | Lang *text; | ||
41 | }; | ||
42 | |||
43 | extern Lang *CurLang; // Current language | ||
44 | |||
45 | extern Lang LangUs; // English (US) | ||
46 | extern Lang LangUk; // English (UK/Aust.) | ||
47 | extern Lang LangFr; // Français (Nationale) | ||
48 | |||
49 | extern LangEntry Langs[]; // List of languages | ||
50 | |||
51 | #endif | ||
diff --git a/lang_en.cpp b/lang_en.cpp new file mode 100644 index 0000000..cc1f9d3 --- /dev/null +++ b/lang_en.cpp | |||
@@ -0,0 +1,109 @@ | |||
1 | |||
2 | #include "stdafx.h" | ||
3 | #include "SpaceMonger.h" | ||
4 | #include "lang.h" | ||
5 | |||
6 | LangEntry Langs[] = { | ||
7 | { "us", "English (US)", &LangUs }, | ||
8 | { "uk", "English (UK/Aust.)", &LangUk }, | ||
9 | { "fr", "Français (Nationale)", &LangFr }, | ||
10 | { NULL, NULL, NULL }, | ||
11 | }; | ||
12 | |||
13 | Lang *CurLang = &LangUs; | ||
14 | |||
15 | ///////////////////////////////////////////////////////////////////////////// | ||
16 | |||
17 | static const char *densitynames[] = { | ||
18 | "Too Few Files", "Very Few Files", "Normal", "Lots of Files", | ||
19 | "Very Many Files", "Too Many Files", | ||
20 | }; | ||
21 | |||
22 | static const char *uscolornames[] = { | ||
23 | "Rainbow", "Windows Colors", "White", "Light Gray", "Dark Gray", | ||
24 | "Red", "Orange", "Yellow", "Green", "Aqua", "Blue", "Violet", | ||
25 | }; | ||
26 | |||
27 | static const char *monthnames[] = { | ||
28 | "Jan", "Feb", "Mar", "Apr", "May", "Jun", | ||
29 | "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", | ||
30 | }; | ||
31 | |||
32 | static const char *attribnames[] = { | ||
33 | "Arch", "Compress", "Folder", "Encrypt", "Hidden", "Offline", | ||
34 | "Read-Only", "Reparse-Pt", "Sparse", "System", "Temp", | ||
35 | }; | ||
36 | |||
37 | Lang LangUs = { | ||
38 | IDR_TOOLBAR_EN, | ||
39 | "About SpaceMonger", | ||
40 | "THIS PROGRAM IS FREEWARE.", | ||
41 | "You may distribute this program freely. Because this program is" | ||
42 | " free, the author cannot and will not assume responsibility" | ||
43 | " for this program's behavior. There are no warranties of any" | ||
44 | " kind, expressed or implied, on this product.", | ||
45 | "Have questions? Found a bug? Want a feature?\n" | ||
46 | "E-mail to <sean@werkema.com>.", | ||
47 | "OK", "Cancel", | ||
48 | "bytes", "Kb", "Mb", "Gb", | ||
49 | "<Free Space: %d.%d%%>", | ||
50 | "Zoom &In", "Zoom &Out", "Zoom &Full", "&Run / Open", "&Delete", | ||
51 | "&Open Drive...", "&Rescan Drive", "&Show Free Space", | ||
52 | "%lu.%01lu%%", "%lu.%01lu %s", | ||
53 | "Total", "Free", "Files Total:", "Folders Total:", "Files Found:", "Folders Found:", | ||
54 | '.', ',', | ||
55 | densitynames, uscolornames, monthnames, attribnames, | ||
56 | "Deleting...", | ||
57 | "Select Drive to View", | ||
58 | "Scanning Disk...", | ||
59 | "SpaceMonger Settings", | ||
60 | "File Layout", "Density:", "Bias:", "Horz", "Equal", "Vert", | ||
61 | "Display Colors", "Files", "Folders", | ||
62 | "ToolTips", "Show file-name-tips", "Show file-info-tips", "Delay:", "msec", | ||
63 | "Full Path", "Filename", "Small Icon", "Icon", "Date / Time", "File Size", "Attributes", | ||
64 | "Miscellaneous Options", | ||
65 | "Auto Rescan on Delete", "Disable \"Delete\" Command", | ||
66 | "Animated Zoom In / Zoom Out", "Remember Window Position", | ||
67 | "Show Rollover Boxes", | ||
68 | "Properties...", | ||
69 | }; | ||
70 | |||
71 | static const char *ukcolornames[] = { | ||
72 | "Rainbow", "Windows Colours", "White", "Light Gray", "Dark Gray", | ||
73 | "Red", "Orange", "Yellow", "Green", "Aqua", "Blue", "Violet", | ||
74 | }; | ||
75 | |||
76 | Lang LangUk = { | ||
77 | IDR_TOOLBAR_EN, | ||
78 | "About SpaceMonger", | ||
79 | "THIS PROGRAM IS FREEWARE.", | ||
80 | "You may distribute this program freely. Because this program is" | ||
81 | " free, the author cannot and will not assume responsibility" | ||
82 | " for this program's behavior. There are no warranties of any" | ||
83 | " kind, expressed or implied, on this product.", | ||
84 | "Have questions? Found a bug? Want a feature?\n" | ||
85 | "E-mail to <sean@werkema.com>.", | ||
86 | "OK", "Cancel", | ||
87 | "bytes", "Kb", "Mb", "Gb", | ||
88 | "<Free Space: %d.%d%%>", | ||
89 | "Zoom &In", "Zoom &Out", "Zoom &Full", "&Run / Open", "&Delete", | ||
90 | "&Open Drive...", "&Rescan Drive", "&Show Free Space", | ||
91 | "%lu.%01lu%%", "%lu.%01lu %s", | ||
92 | "Total", "Free", "Files Total:", "Folders Total:", "Files Found:", "Folders Found:", | ||
93 | '.', ',', | ||
94 | densitynames, ukcolornames, monthnames, attribnames, | ||
95 | "Deleting...", | ||
96 | "Select Drive to View", | ||
97 | "Scanning Disk...", | ||
98 | "SpaceMonger Settings", | ||
99 | "File Layout", "Density:", "Bias:", "Horz", "Equal", "Vert", | ||
100 | "Display Colours", "Files", "Folders", | ||
101 | "ToolTips", "Show file-name-tips", "Show file-info-tips", "Delay:", "msec", | ||
102 | "Full Path", "Filename", "Small Icon", "Icon", "Date / Time", "File Size", "Attributes", | ||
103 | "Miscellaneous Options", | ||
104 | "Auto Rescan on Delete", "Disable \"Delete\" Command", | ||
105 | "Animated Zoom In / Zoom Out", "Remember Window Position", | ||
106 | "Show Rollover Boxes", | ||
107 | "Properties...", | ||
108 | }; | ||
109 | |||
diff --git a/lang_fr.cpp b/lang_fr.cpp new file mode 100644 index 0000000..78ceea8 --- /dev/null +++ b/lang_fr.cpp | |||
@@ -0,0 +1,58 @@ | |||
1 | |||
2 | #include "stdafx.h" | ||
3 | #include "SpaceMonger.h" | ||
4 | #include "lang.h" | ||
5 | |||
6 | static const char *densitynames[] = { | ||
7 | "Petit Peu de Fichiers", "Peu de Fichiers", "Normal", "Beaucoup de Fichiers", | ||
8 | "Très Beaucoup de Fichiers", "Trop de Fichiers", | ||
9 | }; | ||
10 | |||
11 | static const char *uscolornames[] = { | ||
12 | "Arc-en-Ceil", "Colours de Windows", "Blanc", "Gris Clair", "Gris Foncé", | ||
13 | "Rouge", "Orange", "Jaune", "Vert", "Aqua", "Bleu", "Violette", | ||
14 | }; | ||
15 | |||
16 | static const char *monthnames[] = { | ||
17 | "Jan", "Fev", "Mars", "Avril", "Mai", "Juin", | ||
18 | "Juil", "Août", "Sep", "Oct", "Nov", "Dec", | ||
19 | }; | ||
20 | |||
21 | static const char *attribnames[] = { | ||
22 | "Arch", "Compress", "Dossier", "Encrypt", "Caché", "Pas-au-ligne", | ||
23 | "Lire-Seulement", "Reparse-Pt", "Clairsemé", "Système", "Temp", | ||
24 | }; | ||
25 | |||
26 | Lang LangFr = { | ||
27 | IDR_TOOLBAR_FR, | ||
28 | "De SpaceMonger", | ||
29 | "CE PROGRAMME EST FREEWARE.", | ||
30 | "«You may distribute this program freely. Because this program is" | ||
31 | " free, the author cannot and will not assume responsibility" | ||
32 | " for this program's behavior. There are no warranties of any" | ||
33 | " kind, expressed or implied, on this product.»", | ||
34 | "Vous avez des questions? Trouvez un «bug»? Voudriez quelque-chose? " | ||
35 | "Envoyez e-mail à «sean@werkema.com».", | ||
36 | "D'accord", "Annul", | ||
37 | "octets", "Ko", "Mo", "Go", | ||
38 | "<l'Espace Libre: %d,%d%%>", | ||
39 | "&Vrombir", "&Démarrer", "Voir &Tout", "&Exécuter", "&Effacer", | ||
40 | "&Ouvrir un Disque...", "&Rouvrir", "&Montrer l'Espace Libre", | ||
41 | "%lu,%01lu%%", "%lu,%01lu %s", | ||
42 | "Total", "Libre", "Fichiers Totals:", "Dossiers Totals:", "Fichiers Trouvés:", "Dossiers Trouvés:", | ||
43 | ',', '.', | ||
44 | densitynames, uscolornames, monthnames, attribnames, | ||
45 | "Effacer...", | ||
46 | "Choisir un Disque", | ||
47 | "Scruter le Disque...", | ||
48 | "Configuration de SpaceMonger", | ||
49 | "Orientation des Fichiers", "Densité:", "Orient:", "Horz", "Égale", "Vert", | ||
50 | "Colours", "Fichiers", "Dossiers", | ||
51 | "«ToolTips»", "Montrer Nom «ToolTips»", "Montrer Info «ToolTips»", "Délai:", "msec", | ||
52 | "Sentier", "Nom-fichier", "Petit Icon", "Icon", "Date/Heure", "Octets", "Attributs", | ||
53 | "Autres Options", | ||
54 | "Auto-Rouvrir à Effacer", "Pas de Command «Effacer»", | ||
55 | "Vrombir Animé", "Souvenir Position du Window", | ||
56 | "Montrer les Boites «Rollovers»", | ||
57 | "Properties...", | ||
58 | }; | ||
diff --git a/res/SpaceMonger.ico b/res/SpaceMonger.ico new file mode 100644 index 0000000..123634e --- /dev/null +++ b/res/SpaceMonger.ico | |||
Binary files differ | |||
diff --git a/res/scan1.bmp b/res/scan1.bmp new file mode 100644 index 0000000..588f602 --- /dev/null +++ b/res/scan1.bmp | |||
Binary files differ | |||
diff --git a/res/scan2.bmp b/res/scan2.bmp new file mode 100644 index 0000000..395f963 --- /dev/null +++ b/res/scan2.bmp | |||
Binary files differ | |||
diff --git a/res/scan3.bmp b/res/scan3.bmp new file mode 100644 index 0000000..986c690 --- /dev/null +++ b/res/scan3.bmp | |||
Binary files differ | |||
diff --git a/res/scan4.bmp b/res/scan4.bmp new file mode 100644 index 0000000..9c64ee2 --- /dev/null +++ b/res/scan4.bmp | |||
Binary files differ | |||
diff --git a/res/toolbar_en.bmp b/res/toolbar_en.bmp new file mode 100644 index 0000000..d90739e --- /dev/null +++ b/res/toolbar_en.bmp | |||
Binary files differ | |||
diff --git a/res/toolbar_fr.bmp b/res/toolbar_fr.bmp new file mode 100644 index 0000000..e9a4706 --- /dev/null +++ b/res/toolbar_fr.bmp | |||
Binary files differ | |||
diff --git a/resource.h b/resource.h new file mode 100644 index 0000000..a540764 --- /dev/null +++ b/resource.h | |||
@@ -0,0 +1,99 @@ | |||
1 | //{{NO_DEPENDENCIES}} | ||
2 | // Microsoft Developer Studio generated include file. | ||
3 | // Used by SpaceMonger.rc | ||
4 | // | ||
5 | #define ID_SPACEMONGER 100 | ||
6 | #define IDD_DIALOG1 101 | ||
7 | #define IDD_ABOUT 102 | ||
8 | #define IDD_OPEN_DIALOG 104 | ||
9 | #define IDD_SCAN_DIALOG 105 | ||
10 | #define IDB_SCAN1 114 | ||
11 | #define IDB_SCAN2 115 | ||
12 | #define IDB_SCAN3 116 | ||
13 | #define IDB_SCAN4 117 | ||
14 | #define IDD_INFO_BAR 118 | ||
15 | #define IDD_SETTINGS 119 | ||
16 | #define IDB_BITMAP1 123 | ||
17 | #define IDR_TOOLBAR_EN 200 | ||
18 | #define IDR_TOOLBAR_FR 201 | ||
19 | #define IDC_DRIVE_LIST 1000 | ||
20 | #define IDC_PATH 1001 | ||
21 | #define IDC_FILES 1002 | ||
22 | #define IDC_FOLDERS 1003 | ||
23 | #define IDC_TOTAL 1005 | ||
24 | #define IDC_FREE 1006 | ||
25 | #define IDC_DENSITY 1006 | ||
26 | #define IDC_USED 1007 | ||
27 | #define IDC_ANIMATED 1007 | ||
28 | #define IDC_AUTO_RESCAN 1008 | ||
29 | #define IDC_FILE_COLOR 1009 | ||
30 | #define IDC_BIAS 1010 | ||
31 | #define IDC_FOLDER_COLOR 1011 | ||
32 | #define IDC_LOAD_PROGRESS 1011 | ||
33 | #define IDC_DISABLE_DELETE 1012 | ||
34 | #define IDC_SHOW_TIPS 1013 | ||
35 | #define IDC_SHOW_NAME_TIPS 1013 | ||
36 | #define IDC_TIP_PATH 1014 | ||
37 | #define IDC_NAMETIP_PATH 1014 | ||
38 | #define IDC_TIP_NAME 1015 | ||
39 | #define IDC_NAMETIP_NAME 1015 | ||
40 | #define IDC_TIP_DATE 1016 | ||
41 | #define IDC_INFOTIP_DATE 1016 | ||
42 | #define IDC_TIP_SIZE 1017 | ||
43 | #define IDC_INFOTIP_SIZE 1017 | ||
44 | #define IDC_TIP_ATTRIB 1018 | ||
45 | #define IDC_INFOTIP_ATTRIB 1018 | ||
46 | #define IDC_TIP_ICON 1019 | ||
47 | #define IDC_NAMETIP_ICON 1019 | ||
48 | #define IDC_SAVE_POS 1020 | ||
49 | #define IDC_TIP_DELAY 1021 | ||
50 | #define IDC_INFOTIP_DELAY 1021 | ||
51 | #define IDC_STATIC_TIP1 1022 | ||
52 | #define IDC_STATIC_INFOTIP1 1022 | ||
53 | #define IDC_STATIC_TIP2 1023 | ||
54 | #define IDC_STATIC_INFOTIP2 1023 | ||
55 | #define IDC_SHOW_INFO_TIPS 1024 | ||
56 | #define IDC_STATIC_FREEWARE 1024 | ||
57 | #define IDC_NAMETIP_DELAY 1025 | ||
58 | #define IDC_STATIC_WARRANTY 1025 | ||
59 | #define IDC_STATIC_NAMETIP1 1026 | ||
60 | #define IDC_STATIC_EMAIL 1026 | ||
61 | #define IDC_STATIC_NAMETIP2 1027 | ||
62 | #define IDC_STATIC_FILESFOUND 1027 | ||
63 | #define IDC_INFOTIP_PATH 1028 | ||
64 | #define IDC_STATIC_FOLDERSFOUND 1028 | ||
65 | #define IDC_INFOTIP_NAME 1029 | ||
66 | #define IDC_INFOTIP_ICON 1030 | ||
67 | #define IDC_STATIC_LAYOUT 1031 | ||
68 | #define IDC_STATIC_DISPLAYCOLORS 1032 | ||
69 | #define IDC_STATIC_FILES 1033 | ||
70 | #define IDC_STATIC_FOLDERS 1034 | ||
71 | #define IDC_STATIC_DENSITY 1035 | ||
72 | #define IDC_STATIC_BIAS 1036 | ||
73 | #define IDC_STATIC_HORZ 1037 | ||
74 | #define IDC_STATIC_EQUAL 1038 | ||
75 | #define IDC_STATIC_VERT 1039 | ||
76 | #define IDC_STATIC_TOOLTIPS 1040 | ||
77 | #define IDC_STATIC_MISCOPTIONS 1041 | ||
78 | #define IDC_LANG 1042 | ||
79 | #define IDC_SHOW_ROLLOVER_BOX 1043 | ||
80 | #define ID_FILE_REFRESH 40002 | ||
81 | #define ID_VIEW_FREE 40003 | ||
82 | #define ID_VIEW_ZOOM_IN 40004 | ||
83 | #define ID_VIEW_ZOOM_OUT 40005 | ||
84 | #define ID_VIEW_ZOOM_FULL 40006 | ||
85 | #define ID_FILE_RUN 40013 | ||
86 | #define ID_FILE_DELETE 40014 | ||
87 | #define ID_SETTINGS 40017 | ||
88 | #define ID_FILE_PROPERTIES 40018 | ||
89 | |||
90 | // Next default values for new objects | ||
91 | // | ||
92 | #ifdef APSTUDIO_INVOKED | ||
93 | #ifndef APSTUDIO_READONLY_SYMBOLS | ||
94 | #define _APS_NEXT_RESOURCE_VALUE 124 | ||
95 | #define _APS_NEXT_COMMAND_VALUE 40019 | ||
96 | #define _APS_NEXT_CONTROL_VALUE 1044 | ||
97 | #define _APS_NEXT_SYMED_VALUE 101 | ||
98 | #endif | ||
99 | #endif | ||
@@ -0,0 +1,248 @@ | |||
1 | |||
2 | #ifndef XAPP_H | ||
3 | #define XAPP_H | ||
4 | |||
5 | class CFreeDoc; | ||
6 | class CFreeView; | ||
7 | |||
8 | /****************************************************************************** | ||
9 | ** Painting utility functions | ||
10 | */ | ||
11 | |||
12 | #define ColorWindowBack (GetSysColorBrush(COLOR_APPWORKSPACE)) | ||
13 | #define ColorText (GetSysColorBrush(COLOR_WINDOWTEXT)) | ||
14 | #define ColorTextBack (GetSysColorBrush(COLOR_WINDOW)) | ||
15 | #define ColorBright (GetSysColorBrush(COLOR_3DHIGHLIGHT)) | ||
16 | #define ColorFlat (GetSysColorBrush(COLOR_3DFACE)) | ||
17 | #define ColorDark (GetSysColorBrush(COLOR_3DSHADOW)) | ||
18 | #define ColorBorder (GetSysColorBrush(COLOR_3DDKSHADOW)) | ||
19 | #define ColorActive (GetSysColorBrush(COLOR_ACTIVECAPTION)) | ||
20 | #define ColorInactive (GetSysColorBrush(COLOR_INACTIVECAPTION)) | ||
21 | |||
22 | /* | ||
23 | ** DrawHLine | ||
24 | ** Draw a horizontal line in a given brush. | ||
25 | */ | ||
26 | |||
27 | inline static void DrawHLine(HDC dc, HBRUSH brush, int x, int y, int length) | ||
28 | { | ||
29 | RECT rect; | ||
30 | rect.top = y, rect.bottom = y + 1; | ||
31 | rect.left = x, rect.right = x + length; | ||
32 | FillRect(dc, &rect, brush); | ||
33 | } | ||
34 | |||
35 | /* | ||
36 | ** DrawVLine | ||
37 | ** Draw a vertical line in a given brush. | ||
38 | */ | ||
39 | |||
40 | inline static void DrawVLine(HDC dc, HBRUSH brush, int x, int y, int length) | ||
41 | { | ||
42 | RECT rect; | ||
43 | rect.top = y, rect.bottom = y + length; | ||
44 | rect.left = x, rect.right = x + 1; | ||
45 | FillRect(dc, &rect, brush); | ||
46 | } | ||
47 | |||
48 | /* | ||
49 | ** FillBox | ||
50 | ** Fill a rectangle in a given brush. | ||
51 | */ | ||
52 | |||
53 | inline static void FillBox(HDC dc, HBRUSH brush, int x, int y, int width, int height) | ||
54 | { | ||
55 | RECT rect; | ||
56 | rect.top = y, rect.bottom = y + height; | ||
57 | rect.left = x, rect.right = x + width; | ||
58 | FillRect(dc, &rect, brush); | ||
59 | } | ||
60 | |||
61 | /* | ||
62 | ** DrawBox | ||
63 | ** Draw a rectangle in a given brush. | ||
64 | */ | ||
65 | |||
66 | inline static void DrawBox(HDC dc, HBRUSH brush, int x, int y, int width, int height) | ||
67 | { | ||
68 | RECT rect; | ||
69 | rect.top = y, rect.bottom = y + height; | ||
70 | rect.left = x, rect.right = x + width; | ||
71 | FrameRect(dc, &rect, brush); | ||
72 | } | ||
73 | |||
74 | /* | ||
75 | ** DrawDualBox | ||
76 | ** Draw a two-color rectangle in a given pair of brushes. | ||
77 | */ | ||
78 | |||
79 | inline static void DrawDualBox(HDC dc, HBRUSH topleft, HBRUSH bottomright, | ||
80 | int x, int y, int width, int height) | ||
81 | { | ||
82 | RECT rect; | ||
83 | |||
84 | rect.top = y, rect.bottom = y + 1; | ||
85 | rect.left = x, rect.right = x + width; | ||
86 | FillRect(dc, &rect, topleft); | ||
87 | rect.top = y + height - 1, rect.bottom = y + height; | ||
88 | FillRect(dc, &rect, bottomright); | ||
89 | rect.top = y, rect.bottom = y + height; | ||
90 | rect.left = x, rect.right = x + 1; | ||
91 | FillRect(dc, &rect, topleft); | ||
92 | rect.left = x + width - 1, rect.right = x + width; | ||
93 | FillRect(dc, &rect, bottomright); | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | ** FillDualBox | ||
98 | ** Draw a two-color rectangle in a given pair of brushes, and fill | ||
99 | ** in the area it encloses with a third color. | ||
100 | */ | ||
101 | |||
102 | inline static void FillDualBox(HDC dc, HBRUSH topleft, HBRUSH bottomright, | ||
103 | HBRUSH fill, int x, int y, int width, int height) | ||
104 | { | ||
105 | RECT rect; | ||
106 | |||
107 | rect.top = y, rect.bottom = y + 1; | ||
108 | rect.left = x, rect.right = x + width; | ||
109 | FillRect(dc, &rect, topleft); | ||
110 | rect.top = y + height - 1, rect.bottom = y + height; | ||
111 | FillRect(dc, &rect, bottomright); | ||
112 | rect.top = y, rect.bottom = y + height; | ||
113 | rect.left = x, rect.right = x + 1; | ||
114 | FillRect(dc, &rect, topleft); | ||
115 | rect.left = x + width - 1, rect.right = x + width; | ||
116 | FillRect(dc, &rect, bottomright); | ||
117 | rect.top = y + 1, rect.bottom = y + width - 2; | ||
118 | rect.left = x + 1, rect.right = x + width - 2; | ||
119 | FillRect(dc, &rect, fill); | ||
120 | } | ||
121 | |||
122 | /* | ||
123 | ** Macros to build some common UI objects | ||
124 | */ | ||
125 | |||
126 | #define DrawRaisedBox(dc, x, y, width, height) \ | ||
127 | (DrawDualBox(dc, ColorBright, ColorDark, x, y, width, height)) | ||
128 | |||
129 | #define DrawLoweredBox(dc, x, y, width, height) \ | ||
130 | (DrawDualBox(dc, ColorDark, ColorBright, x, y, width, height)) | ||
131 | |||
132 | #define DrawEditBox(dc, x, y, width, height) \ | ||
133 | (DrawDualBox(dc, ColorDark, ColorBright, x, y, width, height), \ | ||
134 | DrawDualBox(dc, ColorBorder, ColorFlat, (x)+1, (y)+1, (width)-2, (height)-2)) | ||
135 | |||
136 | #define DrawWindowBorder(dc, x, y, width, height) \ | ||
137 | (DrawDualBox(dc, ColorFlat, ColorBorder, x, y, width, height), \ | ||
138 | DrawDualBox(dc, ColorBright, ColorDark, (x)+1, (y)+1, (width)-2, (height)-2)) | ||
139 | |||
140 | #define FillWindowBorder(dc, x, y, width, height) \ | ||
141 | (DrawDualBox(dc, ColorFlat, ColorBorder, x, y, width, height), \ | ||
142 | FillDualBox(dc, ColorBright, ColorDark, ColorFlat, (x)+1, (y)+1, (width)-2, (height)-2)) | ||
143 | |||
144 | #define DrawButtonUp(dc, x, y, width, height) \ | ||
145 | (DrawDualBox(dc, ColorBright, ColorBorder, x, y, width, height), \ | ||
146 | DrawDualBox(dc, ColorFlat, ColorDark, (x)+1, (y)+1, (width)-2, (height)-2)) | ||
147 | |||
148 | #define DrawButtonDown(dc, x, y, width, height) \ | ||
149 | (DrawDualBox(dc, ColorDark, ColorBorder, x, y, width, height), \ | ||
150 | DrawBox(dc, ColorFlat, (x)+1, (y)+1, (width)-2, (height)-2)) | ||
151 | |||
152 | #define FillRaisedBox(dc, x, y, width, height) \ | ||
153 | (FillDualBox(dc, ColorBright, ColorDark, ColorFlat, x, y, width, height)) | ||
154 | |||
155 | #define FillLoweredBox(dc, x, y, width, height) \ | ||
156 | (FillDualBox(dc, ColorDark, ColorBright, ColorFlat, x, y, width, height)) | ||
157 | |||
158 | #define FillButtonUp(dc, x, y, width, height) \ | ||
159 | (DrawDualBox(dc, ColorBright, ColorBorder, x, y, width, height), \ | ||
160 | FillDualBox(dc, ColorFlat, ColorDark, ColorFlat, (x)+1, (y)+1, (width)-2, (height)-2)) | ||
161 | |||
162 | #define FillButtonDown(dc, x, y, width, height) \ | ||
163 | (DrawDualBox(dc, ColorDark, ColorBorder, x, y, width, height), \ | ||
164 | FillBox(dc, ColorFlat, (x)+1, (y)+1, (width)-2, (height)-2)) | ||
165 | |||
166 | |||
167 | /****************************************************************************** | ||
168 | ** The "liberated document" class | ||
169 | */ | ||
170 | |||
171 | class CFreeDoc { | ||
172 | public: | ||
173 | CFreeDoc(); | ||
174 | virtual ~CFreeDoc(); | ||
175 | |||
176 | virtual BOOL Create(void); | ||
177 | |||
178 | virtual const CString &GetTitle(void) const | ||
179 | { return(m_strTitle); } | ||
180 | virtual void SetTitle(const CString &string); | ||
181 | virtual const CString &GetPathName(void) const | ||
182 | { return(m_strPathName); } | ||
183 | virtual void SetPathName(const CString &string); | ||
184 | |||
185 | virtual BOOL IsModified(void) const; | ||
186 | virtual void SetModifiedFlag(const BOOL modified = TRUE); | ||
187 | |||
188 | virtual UINT GetViewCount(void) const; | ||
189 | virtual void AddView(CFreeView *view); | ||
190 | virtual void RemoveView(CFreeView *view); | ||
191 | virtual POSITION GetFirstViewPosition(void) const; | ||
192 | virtual CFreeView *GetNextView(POSITION &position) const; | ||
193 | virtual void UpdateAllViews(void); | ||
194 | virtual void UpdateView(CFreeView *view); | ||
195 | |||
196 | protected: | ||
197 | virtual void OnChangedViewList(CFreeView *view, BOOL added); | ||
198 | virtual BOOL OnCreate(void); | ||
199 | virtual void OnDestroy(void); | ||
200 | |||
201 | protected: | ||
202 | CString m_strTitle, m_strPathName; | ||
203 | BOOL m_bModified, m_bCreated; | ||
204 | CPtrList m_viewList; | ||
205 | }; | ||
206 | |||
207 | |||
208 | /****************************************************************************** | ||
209 | ** The "liberated document view" class | ||
210 | */ | ||
211 | |||
212 | #define AFX_FREEVIEW_ID 0xE888 | ||
213 | |||
214 | class CFreeView : public CWnd { | ||
215 | friend void CFreeDoc::AddView(CFreeView *view); | ||
216 | friend void CFreeDoc::RemoveView(CFreeView *view); | ||
217 | |||
218 | protected: | ||
219 | DECLARE_DYNCREATE(CFreeView) | ||
220 | CFreeView(); | ||
221 | virtual ~CFreeView(); | ||
222 | |||
223 | public: | ||
224 | virtual BOOL Create(CWnd *wnd, BOOL show = 1); | ||
225 | virtual void SetDocument(CFreeDoc *doc = NULL); | ||
226 | virtual CFreeDoc *GetDocument(void); | ||
227 | |||
228 | virtual void OnUpdate(CFreeDoc *doc); | ||
229 | |||
230 | //{{AFX_VIRTUAL(CFreeView) | ||
231 | protected: | ||
232 | virtual void OnDraw(CDC* pDC); | ||
233 | //}}AFX_VIRTUAL | ||
234 | |||
235 | protected: | ||
236 | //{{AFX_MSG(CFreeView) | ||
237 | afx_msg void OnSize(UINT nType, int cx, int cy); | ||
238 | afx_msg void OnPaint(); | ||
239 | //}}AFX_MSG | ||
240 | |||
241 | protected: | ||
242 | DECLARE_MESSAGE_MAP() | ||
243 | |||
244 | int m_width, m_height; // Width and height of view | ||
245 | CFreeDoc *m_document; // Document | ||
246 | }; | ||
247 | |||
248 | #endif | ||