SDI interface for lean explorer

svn path=/branches/lean-explorer/; revision=8240
This commit is contained in:
Martin Fuchs
2004-02-18 00:01:02 +00:00
parent 1707fd147a
commit a8cf2dad56
19 changed files with 285 additions and 2643 deletions
-2
View File
@@ -80,8 +80,6 @@ OBJECTS = \
winfs.o \
shellfs.o \
mainframe.o \
filechild.o \
pane.o \
shellbrowser.o \
desktop.o \
desktopbar.o \
@@ -54,8 +54,6 @@ OBJECTS = \
winfs.o \
shellfs.o \
mainframe.o \
filechild.o \
pane.o \
shellbrowser.o \
desktop.o \
desktopbar.o \
@@ -27,18 +27,16 @@
#include "../utility/utility.h"
#include "../utility/shellclasses.h"
#include "../utility/shellbrowserimpl.h"
#include "../utility/dragdropimpl.h"
#include "../utility/window.h"
#include "../explorer.h" // for MainFrame::OpenShellFolders()
#include "desktop.h"
#include "../globals.h"
#include "../externals.h"
#include "../explorer_intres.h"
#include "desktop.h"
#include "../taskbar/desktopbar.h"
#include "../shell/mainframe.h" // for MainFrame::Create()
#include "../explorer_intres.h"
static BOOL (WINAPI*SetShellWindow)(HWND);
+1 -116
View File
@@ -3,8 +3,7 @@
//
// =Memo for future Japanese maintainer=
// For future ease of maintenance, I marked "FIXME?" on strings I suspect I have
// mistranslated or I haven't translated(especially, "IDM_WINEFILE" have many
// suspected strings because I haven't tested under WINE). Others are set as is in
// mistranslated or I haven't translated. Others are set as is in
// purpose. BTW, I feel it strange that the word;"directory" turns into "folder" for
// Japanese Windows(..or English Windows also use "folder" instead of "directory"? I
// have no idea). I obeyed as the MS do. Also, there might be some menus which have
@@ -39,11 +38,6 @@ BEGIN
POPUP "ウィンドウ(&W)"
BEGIN
MENUITEM "新しいウィンドウ(&W)", ID_WINDOW_NEW
MENUITEM "カスケード\tShift+F5", ID_WINDOW_CASCADE
MENUITEM "水平に整列(&H)", ID_WINDOW_TILE_HORZ
MENUITEM "垂直に整列(&V)\tShift+F4", ID_WINDOW_TILE_VERT
MENUITEM "自動整列", ID_WINDOW_AUTOSORT
MENUITEM "最小化された子ウィンドウを整列(&S)", ID_WINDOW_ARRANGE //FIXME?
MENUITEM "最新の情報に更新(&R)\tF5", ID_REFRESH
END
POPUP "ヘルプ(&H)"
@@ -54,115 +48,6 @@ BEGIN
END
END
IDM_WINEFILE MENU FIXED IMPURE
BEGIN
POPUP "ファイル(&F)"
BEGIN
MENUITEM "開く(&O)\tEnter", 101
MENUITEM "移動(&M)...\tF7", 106
MENUITEM "コピー(&C)...\tF8", 107
MENUITEM "クリップボードへ(&I)...\tF9", 118 //FIXME?
MENUITEM "削除(&D)\tDel", 108
MENUITEM "名前の変更(&N)...", 109
MENUITEM "プロパティ(&I)...\tAlt+Enter", ID_EDIT_PROPERTIES
MENUITEM SEPARATOR
MENUITEM "圧縮(&O)...", 119
MENUITEM "展開(&O)...", 120
MENUITEM SEPARATOR
MENUITEM "実行(&R)...", ID_EXECUTE
MENUITEM "印刷(&P)...", 102
MENUITEM "関連付け...", 103 //FIXME?
MENUITEM SEPARATOR
MENUITEM "フォルダを作成(&E)...", ID_EXECUTE //FIXME?
MENUITEM "検索(&H)...", 104
MENUITEM "ファイルを選択(&S)...", 116
MENUITEM SEPARATOR
MENUITEM "終了(&X)\tAlt+X", ID_FILE_EXIT
END
POPUP "ディスク(&D)"
BEGIN
MENUITEM "ディスクをコピー(&C)...", 201
MENUITEM "ディスクにラベルをつける(&L)...", 202
MENUITEM SEPARATOR
MENUITEM "フォーマット(&F)...", 203
MENUITEM SEPARATOR
MENUITEM "ネットワークドライブを接続(&N)", 252
MENUITEM "ネットワークドライブを切断(&D)", 253
MENUITEM SEPARATOR
MENUITEM "名前を付けて共有...", 254
MENUITEM "共有解除(&R)...", 255
MENUITEM SEPARATOR
MENUITEM "ドライブを選択(&S)...", 251
END
POPUP "ディレクトリ(&D)"
BEGIN
MENUITEM "次の階層へ(&N)\t+", 301 //FIXME?
MENUITEM "ツリーを展開(&T)\t*", 302
MENUITEM "全て展開(&A)\tStrg+*", 303
MENUITEM "ツリーを畳む(&T)\t-", 304
MENUITEM SEPARATOR
MENUITEM "子ノードをマーク(&M)", 505 //FIXME?
END
POPUP "表\示(&V)"
BEGIN
MENUITEM "ツリーとフォルダ(&R)", 413
MENUITEM "ツリーのみ(&E)", 411
MENUITEM "フォルダのみ(&O)", 412
MENUITEM SEPARATOR
MENUITEM "分割(&L)", 414 //FIXME?
MENUITEM SEPARATOR
MENUITEM "名前(&N)", ID_VIEW_NAME //FIXME?
MENUITEM "ファイルの全詳細(&A)", ID_VIEW_ALL_ATTRIBUTES
, CHECKED
MENUITEM "詳細を選択表\示(&P)...", ID_VIEW_SELECTED_ATTRIBUTES //FIXME?
MENUITEM SEPARATOR
MENUITEM "名前順に整列(&S)", 404
MENUITEM "種類順に整列(&B)", 405
MENUITEM "サイズ順に整列(&Z)", 406
MENUITEM "日付順に整列(&D)", 407
MENUITEM SEPARATOR
MENUITEM "詳細を指定して整列&...", 409 //FIXME?
END
POPUP "オプション(&O)"
BEGIN
MENUITEM "確認(&C)...", 65535 //FIXME?
MENUITEM "フォント(&F)...", 65535
MENUITEM "ツールバーをカスタマイズ(&B)...", 65535
MENUITEM SEPARATOR
MENUITEM "ツールバー(&T)", ID_VIEW_TOOL_BAR, CHECKED
MENUITEM "ドライブバー(&D)", ID_VIEW_DRIVE_BAR, CHECKED
MENUITEM "ステータスバー(&S)", ID_VIEW_STATUSBAR, CHECKED
MENUITEM "全画面表\示(&U)\tCtrl+Shift+S", ID_VIEW_FULLSCREEN
MENUITEM SEPARATOR
MENUITEM "アプリケーション起動後にエクスプローラを最小化(&S)", 65535 //FIXME?
MENUITEM "終了時の設定を保存(&E)", 511 //FIXME?
END
POPUP "セキュリティ(&S)"
BEGIN
MENUITEM "アクセス(&A)...", 605
MENUITEM "ログ(&L)...", 606 //FIXME?
MENUITEM "所有者(&O)...", 607 //FIXME?
END
POPUP "ウィンドウ(&W)"
BEGIN
MENUITEM "新しいウィンドウ(&W)", ID_WINDOW_NEW
MENUITEM "カスケード\tCtrl+F5", ID_WINDOW_CASCADE
MENUITEM "水平に整列(&H)", ID_WINDOW_TILE_HORZ
MENUITEM "垂直に並列(&V)\tCtrl+F4", ID_WINDOW_TILE_VERT
MENUITEM "自動整列", ID_WINDOW_AUTOSORT
MENUITEM "最小化された子ウィンドウを整列(&S)", ID_WINDOW_ARRANGE
MENUITEM "最新の情報に更新(&R)\tF5", ID_REFRESH
END
POPUP "&?"
BEGIN
MENUITEM "ヘルプトピック(&H)\tF1", ID_HELP
MENUITEM "ヘルプの検索(&S)...\tF1", ID_HELP
MENUITEM "ヘルプの使い方(&U)\tF1", ID_HELP_USING //FIXME?
MENUITEM SEPARATOR
MENUITEM "&Winefileに関する情報...", ID_ABOUT_WINEFILE
END
END
IDM_DESKTOPBAR MENU DISCARDABLE
BEGIN
POPUP ""
@@ -382,14 +382,6 @@ SOURCE=.\shell\entries.h
# End Source File
# Begin Source File
SOURCE=.\shell\filechild.cpp
# End Source File
# Begin Source File
SOURCE=.\shell\filechild.h
# End Source File
# Begin Source File
SOURCE=.\shell\mainframe.cpp
# End Source File
# Begin Source File
@@ -398,14 +390,6 @@ SOURCE=.\shell\mainframe.h
# End Source File
# Begin Source File
SOURCE=.\shell\pane.cpp
# End Source File
# Begin Source File
SOURCE=.\shell\pane.h
# End Source File
# Begin Source File
SOURCE=.\shell\shellbrowser.cpp
# End Source File
# Begin Source File
+1 -6
View File
@@ -42,9 +42,6 @@
#define IDW_FIRST_CHILD 0xC000 /*0x200*/
#define PM_GET_FILEWND_PTR (WM_APP+0x05)
#define PM_GET_SHELLBROWSER_PTR (WM_APP+0x06)
#define PM_GET_CONTROLWINDOW (WM_APP+0x16)
#define PM_RESIZE_CHILDREN (WM_APP+0x17)
@@ -57,7 +54,5 @@
#define CLASSNAME_WINEFILETREE TEXT("WFS_Tree")
#include "shell/mainframe.h"
#include "shell/pane.h"
#include "shell/filechild.h"
#include "shell/shellbrowser.h"
#include "shell/mainframe.h"
@@ -90,7 +90,6 @@
#define ID_VIEW_ALL_ATTRIBUTES 402
#define ID_VIEW_SELECTED_ATTRIBUTES 403
#define ID_VIEW_STATUSBAR 503
#define ID_VIEW_DRIVE_BAR 507
#define ID_VIEW_TOOL_BAR 508
#define IDC_ROS_EXPLORER 1000
#define IDC_WWW 1012
@@ -101,10 +100,7 @@
#define IDC_FILETREE 10001
#define ID_EXPLORER_FAQ 10002
#define ID_WINDOW_AUTOSORT 0x8003
#define ID_VIEW_FULLSCREEN 0x8004
#define ID_PREFERED_SIZES 0x8005
#define ID_DRIVE_DESKTOP 0x9000
#define ID_DRIVE_FIRST 0x9006
#define ID_ABOUT_WINDOWS 40002
#define ID_ABOUT_EXPLORER 40003
#define ID_DESKTOPBAR_SETTINGS 40004
@@ -115,11 +111,6 @@
#define ID_EXPLORE 40011
#define ID_SWITCH_DESKTOP_1 40012
#define ID_WINDOW_NEW 0xE130
#define ID_WINDOW_ARRANGE 0xE131
#define ID_WINDOW_CASCADE 0xE132
#define ID_WINDOW_TILE_HORZ 0xE133
#define ID_WINDOW_TILE_VERT 0xE134
#define ID_WINDOW_SPLIT 0xE135
#define ID_EDIT_PROPERTIES 57656
#define ID_FILE_EXIT 0xE141
#define ID_HELP_USING 0xE144
@@ -130,7 +121,7 @@
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 162
#define _APS_NEXT_RESOURCE_VALUE 165
#define _APS_NEXT_COMMAND_VALUE 40015
#define _APS_NEXT_CONTROL_VALUE 1003
#define _APS_NEXT_SYMED_VALUE 101
@@ -40,11 +40,6 @@ BEGIN
POPUP "&Fereastrã"
BEGIN
MENUITEM "&Fereastrã Nouã", ID_WINDOW_NEW
MENUITEM "Cascading\tShift+F5", ID_WINDOW_CASCADE
MENUITEM "Aliniazã &Orizontal", ID_WINDOW_TILE_HORZ
MENUITEM "Aliniazã &Vertical\tShift+F4", ID_WINDOW_TILE_VERT
MENUITEM "Aranjeazã automat", ID_WINDOW_AUTOSORT
MENUITEM "Aranjeazã &Simbolurile", ID_WINDOW_ARRANGE
MENUITEM "&Resetare\tF5", ID_REFRESH
END
POPUP "&Ajutor"
@@ -160,8 +155,6 @@ IDB_LOGOV16 BITMAP DISCARDABLE "res/logov16.bmp"
IDA_EXPLORER ACCELERATORS DISCARDABLE
BEGIN
"X", ID_FILE_EXIT, VIRTKEY, ALT, NOINVERT
"S", ID_VIEW_FULLSCREEN, VIRTKEY, SHIFT, CONTROL,
NOINVERT
END
IDA_SEARCH_PROGRAM ACCELERATORS DISCARDABLE
@@ -201,11 +194,6 @@ BEGIN
POPUP "&Fenster"
BEGIN
MENUITEM "Neues &Fenster", ID_WINDOW_NEW
MENUITEM "Über&lappend\tUmschalt+F5", ID_WINDOW_CASCADE
MENUITEM "&Untereinander", ID_WINDOW_TILE_HORZ
MENUITEM "&Nebeneinander\tUmschalt+F4", ID_WINDOW_TILE_VERT
MENUITEM "au&tomatisch anordnen", ID_WINDOW_AUTOSORT
MENUITEM "&Symbole anordnen", ID_WINDOW_ARRANGE
MENUITEM "&Aktualisieren\tF5", ID_REFRESH
END
POPUP "&Help"
@@ -407,11 +395,6 @@ BEGIN
POPUP "&Window"
BEGIN
MENUITEM "New &Window", ID_WINDOW_NEW
MENUITEM "Cascading\tShift+F5", ID_WINDOW_CASCADE
MENUITEM "Tile &Horizontally", ID_WINDOW_TILE_HORZ
MENUITEM "Tile &Vertically\tShift+F4", ID_WINDOW_TILE_VERT
MENUITEM "Arrange Automatically", ID_WINDOW_AUTOSORT
MENUITEM "Arrange &Symbols", ID_WINDOW_ARRANGE
MENUITEM "&Refresh\tF5", ID_REFRESH
END
POPUP "&Help"
@@ -591,11 +574,6 @@ BEGIN
POPUP "&Window"
BEGIN
MENUITEM "New &Window", ID_WINDOW_NEW
MENUITEM "Cascading\tShift+F5", ID_WINDOW_CASCADE
MENUITEM "Tile &Horizontally", ID_WINDOW_TILE_HORZ
MENUITEM "Tile &Vertically\tShift+F4", ID_WINDOW_TILE_VERT
MENUITEM "Arrange Automatically", ID_WINDOW_AUTOSORT
MENUITEM "Arrange &Symbols", ID_WINDOW_ARRANGE
MENUITEM "&Refresh\tF5", ID_REFRESH
END
POPUP "A&ide"
@@ -1,524 +0,0 @@
/*
* Copyright 2003 Martin Fuchs
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
//
// Explorer clone
//
// filechild.cpp
//
// Martin Fuchs, 23.07.2003
//
#include "../utility/utility.h"
#include "../explorer.h"
#include "../globals.h"
#include "../explorer_intres.h"
FileChildWndInfo::FileChildWndInfo(HWND hmdiclient, LPCTSTR path, ENTRY_TYPE etype)
: super(hmdiclient),
_etype(etype)
{
if (etype == ET_UNKNOWN)
_etype = ET_WINDOWS;
_path = path;
_pos.length = sizeof(WINDOWPLACEMENT);
_pos.flags = 0;
_pos.showCmd = SW_SHOWNORMAL;
_pos.rcNormalPosition.left = CW_USEDEFAULT;
_pos.rcNormalPosition.top = CW_USEDEFAULT;
_pos.rcNormalPosition.right = CW_USEDEFAULT;
_pos.rcNormalPosition.bottom = CW_USEDEFAULT;
_open_mode = OWM_EXPLORE|OWM_DETAILS;
}
ShellChildWndInfo::ShellChildWndInfo(HWND hmdiclient, LPCTSTR path, const ShellPath& root_shell_path)
: FileChildWndInfo(hmdiclient, path, ET_SHELL),
_shell_path(path&&*path? path: root_shell_path),
_root_shell_path(root_shell_path)
{
}
FileChildWindow::FileChildWindow(HWND hwnd, const FileChildWndInfo& info)
: ChildWindow(hwnd, info)
{
CONTEXT("FileChildWindow::FileChildWindow()");
TCHAR drv[_MAX_DRIVE+1];
Entry* entry;
//assert(info._etype==ET_WINDOWS);
_root._drive_type = GetDriveType(info._path);
_tsplitpath(info._path, drv, NULL, NULL, NULL);
lstrcat(drv, TEXT("\\"));
GetVolumeInformation(drv, _root._volname, _MAX_FNAME, 0, 0, &_root._fs_flags, _root._fs, _MAX_DIR);
lstrcpy(_root._path, drv);
_root._entry = new WinDirectory(_root._path);
entry = _root._entry->read_tree(info._path, SORT_NAME);
if (info._etype != ET_SHELL)
wsprintf(_root._entry->_data.cFileName, TEXT("%s - %s"), drv, _root._fs);
/*@@else
lstrcpy(_root._entry->_data.cFileName, TEXT("GetDesktopFolder"));*/
_root._entry->_data.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
if (info._open_mode & OWM_EXPLORE) ///@todo Is not-explore-mode for FileChildWindow completely implemented?
_left_hwnd = *(_left=new Pane(_hwnd, IDW_TREE_LEFT, IDW_HEADER_LEFT, _root._entry, true, COL_CONTENT));
_right_hwnd = *(_right=new Pane(_hwnd, IDW_TREE_RIGHT, IDW_HEADER_RIGHT, NULL, false,
COL_TYPE|COL_SIZE|COL_DATE|COL_TIME|COL_ATTRIBUTES|COL_INDEX|COL_LINKS|COL_CONTENT));
_sortOrder = SORT_NAME;
_header_wdths_ok = false;
set_curdir(entry, hwnd);
if (_left_hwnd) {
int idx = ListBox_FindItemData(_left_hwnd, ListBox_GetCurSel(_left_hwnd), _left->_cur);
ListBox_SetCurSel(_left_hwnd, idx);
}
///@todo scroll to visibility
}
FileChildWindow::~FileChildWindow()
{
}
void FileChildWindow::set_curdir(Entry* entry, HWND hwnd)
{
CONTEXT("FileChildWindow::set_curdir()");
_path[0] = TEXT('\0');
_left->_cur = entry;
_right->_root = entry&&entry->_down? entry->_down: entry;
_right->_cur = entry;
if (entry) {
if (!entry->_scanned)
scan_entry(entry, hwnd);
else {
ListBox_ResetContent(_right_hwnd);
_right->insert_entries(entry->_down, -1);
_right->calc_widths(false);
_right->set_header();
}
entry->get_path(_path);
}
if (hwnd) // only change window title, if the window already exists
SetWindowText(hwnd, _path);
if (_path[0])
if (!SetCurrentDirectory(_path))
_path[0] = TEXT('\0');
}
// expand a directory entry
bool FileChildWindow::expand_entry(Entry* dir)
{
int idx;
Entry* p;
if (!dir || dir->_expanded || !dir->_down)
return false;
p = dir->_down;
if (p->_data.cFileName[0]=='.' && p->_data.cFileName[1]=='\0' && p->_next) {
p = p->_next;
if (p->_data.cFileName[0]=='.' && p->_data.cFileName[1]=='.' &&
p->_data.cFileName[2]=='\0' && p->_next)
p = p->_next;
}
// no subdirectories ?
if (!(p->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && // not a directory?
!p->_down) // not a file with NTFS sub-streams?
return FALSE;
idx = ListBox_FindItemData(_left_hwnd, 0, dir);
dir->_expanded = true;
// insert entries in left pane
_left->insert_entries(p, idx);
if (!_header_wdths_ok) {
if (_left->calc_widths(false)) {
_left->set_header();
_header_wdths_ok = true;
}
}
return true;
}
void FileChildWindow::collapse_entry(Pane* pane, Entry* dir)
{
int idx = ListBox_FindItemData(*pane, 0, dir);
SendMessage(*pane, WM_SETREDRAW, FALSE, 0); //ShowWindow(*pane, SW_HIDE);
// hide sub entries
for(;;) {
LRESULT res = ListBox_GetItemData(*pane, idx+1);
Entry* sub = (Entry*) res;
if (res==LB_ERR || !sub || sub->_level<=dir->_level)
break;
ListBox_DeleteString(*pane, idx+1);
}
dir->_expanded = false;
SendMessage(*pane, WM_SETREDRAW, TRUE, 0); //ShowWindow(*pane, SW_SHOW);
}
FileChildWindow* FileChildWindow::create(const FileChildWndInfo& info)
{
CONTEXT("FileChildWindow::create()");
MDICREATESTRUCT mcs;
mcs.szClass = CLASSNAME_WINEFILETREE;
mcs.szTitle = (LPTSTR)info._path;
mcs.hOwner = g_Globals._hInstance;
mcs.x = info._pos.rcNormalPosition.left;
mcs.y = info._pos.rcNormalPosition.top;
mcs.cx = info._pos.rcNormalPosition.right - info._pos.rcNormalPosition.left;
mcs.cy = info._pos.rcNormalPosition.bottom - info._pos.rcNormalPosition.top;
mcs.style = 0;
mcs.lParam = 0;
FileChildWindow* child = static_cast<FileChildWindow*>(
create_mdi_child(info, mcs, WINDOW_CREATOR_INFO(FileChildWindow,FileChildWndInfo)));
return child;
}
void FileChildWindow::resize_children(int cx, int cy)
{
HDWP hdwp = BeginDeferWindowPos(4);
RECT rt;
rt.left = 0;
rt.top = 0;
rt.right = cx;
rt.bottom = cy;
cx = _split_pos + SPLIT_WIDTH/2;
{
WINDOWPOS wp;
HD_LAYOUT hdl;
hdl.prc = &rt;
hdl.pwpos = &wp;
Header_Layout(_left->_hwndHeader, &hdl);
hdwp = DeferWindowPos(hdwp, _left->_hwndHeader, wp.hwndInsertAfter,
wp.x-1, wp.y, _split_pos-SPLIT_WIDTH/2+1, wp.cy, wp.flags);
hdwp = DeferWindowPos(hdwp, _right->_hwndHeader, wp.hwndInsertAfter,
rt.left+cx+1, wp.y, wp.cx-cx+2, wp.cy, wp.flags);
}
if (_left_hwnd)
hdwp = DeferWindowPos(hdwp, _left_hwnd, 0, rt.left, rt.top, _split_pos-SPLIT_WIDTH/2-rt.left, rt.bottom-rt.top, SWP_NOZORDER|SWP_NOACTIVATE);
hdwp = DeferWindowPos(hdwp, _right_hwnd, 0, rt.left+cx+1, rt.top, rt.right-cx, rt.bottom-rt.top, SWP_NOZORDER|SWP_NOACTIVATE);
EndDeferWindowPos(hdwp);
}
LRESULT FileChildWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
{
switch(nmsg) {
case WM_DRAWITEM: {
LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lparam;
Entry* entry = (Entry*) dis->itemData;
if (dis->CtlID == IDW_TREE_LEFT)
_left->draw_item(dis, entry);
else
_right->draw_item(dis, entry);
return TRUE;}
case WM_SIZE:
if (wparam != SIZE_MINIMIZED)
resize_children(LOWORD(lparam), HIWORD(lparam));
return DefMDIChildProc(_hwnd, nmsg, wparam, lparam);
case PM_GET_FILEWND_PTR:
return (LRESULT)this;
case WM_SETFOCUS: {
TCHAR path[MAX_PATH];
if (_left->_cur) {
_left->_cur->get_path(path);
SetCurrentDirectory(path);
}
SetFocus(_focus_pane? _right_hwnd: _left_hwnd);
goto def;}
case PM_DISPATCH_COMMAND: {
Pane* pane = GetFocus()==_left_hwnd? _left: _right;
switch(LOWORD(wparam)) {
case ID_WINDOW_NEW: {CONTEXT("FileChildWindow PM_DISPATCH_COMMAND ID_WINDOW_NEW");
if (_root._entry->_etype == ET_SHELL)
FileChildWindow::create(ShellChildWndInfo(GetParent(_hwnd)/*_hmdiclient*/, _path, DesktopFolderPath()));
else
FileChildWindow::create(FileChildWndInfo(GetParent(_hwnd)/*_hmdiclient*/, _path));
break;}
case ID_REFRESH: {CONTEXT("ID_REFRESH");
bool expanded = _left->_cur->_expanded;
scan_entry(_left->_cur, _hwnd);
if (expanded)
expand_entry(_left->_cur);
break;}
case ID_ACTIVATE: {CONTEXT("ID_ACTIVATE");
activate_entry(pane, _hwnd);
break;}
default:
return pane->command(LOWORD(wparam));
}
return TRUE;}
case WM_CONTEXTMENU: {
// first select the current item in the listbox
HWND hpanel = (HWND) wparam;
POINTS& pos = MAKEPOINTS(lparam);
POINT pt; POINTSTOPOINT(pt, pos);
ScreenToClient(hpanel, &pt);
SendMessage(hpanel, WM_LBUTTONDOWN, 0, MAKELONG(pt.x, pt.y));
SendMessage(hpanel, WM_LBUTTONUP, 0, MAKELONG(pt.x, pt.y));
// now create the popup menu using shell namespace and IContextMenu
Pane* pane = GetFocus()==_left_hwnd? _left: _right;
int idx = ListBox_GetCurSel(*pane);
if (idx != -1) {
Entry* entry = (Entry*) ListBox_GetItemData(*pane, idx);
ShellPath shell_path = entry->create_absolute_pidl();
LPCITEMIDLIST pidl_abs = shell_path;
IShellFolder* parentFolder;
LPCITEMIDLIST pidlLast;
static DynamicFct<HRESULT(WINAPI*)(LPCITEMIDLIST, REFIID, LPVOID*, LPCITEMIDLIST*)> SHBindToParent(TEXT("SHELL32"), "SHBindToParent");
if (SHBindToParent) {
// get and use the parent folder to display correct context menu in all cases -> correct "Properties" dialog for directories, ...
if (SUCCEEDED((*SHBindToParent)(pidl_abs, IID_IShellFolder, (LPVOID*)&parentFolder, &pidlLast))) {
HRESULT hr = ShellFolderContextMenu(parentFolder, _hwnd, 1, &pidlLast, pos.x, pos.y);
parentFolder->Release();
CHECKERROR(hr);
}
} else {
CHECKERROR(ShellFolderContextMenu(GetDesktopFolder(), _hwnd, 1, &pidl_abs, pos.x, pos.y));
}
}
break;}
default: def:
return super::WndProc(nmsg, wparam, lparam);
}
return 0;
}
int FileChildWindow::Command(int id, int code)
{
Pane* pane = GetFocus()==_left_hwnd? _left: _right;
switch(code) {
case LBN_SELCHANGE: {
int idx = ListBox_GetCurSel(*pane);
Entry* entry = (Entry*) ListBox_GetItemData(*pane, idx);
if (pane == _left)
set_curdir(entry, _hwnd);
else
pane->_cur = entry;
break;}
case LBN_DBLCLK:
activate_entry(pane, _hwnd);
break;
}
return 0;
}
void FileChildWindow::activate_entry(Pane* pane, HWND hwnd)
{
Entry* entry = pane->_cur;
if (!entry)
return;
if ((entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) || // a directory?
entry->_down) // a file with NTFS sub-streams?
{
int scanned_old = entry->_scanned;
if (!scanned_old)
scan_entry(entry, hwnd);
if (entry->_data.cFileName[0]==TEXT('.') && entry->_data.cFileName[1]==TEXT('\0'))
return;
if (entry->_data.cFileName[0]==TEXT('.') && entry->_data.cFileName[1]==TEXT('.') && entry->_data.cFileName[2]==TEXT('\0')) {
entry = _left->_cur->_up;
collapse_entry(_left, entry);
goto focus_entry;
} else if (entry->_expanded)
collapse_entry(pane, _left->_cur);
else {
expand_entry(_left->_cur);
if (!pane->_treePane) focus_entry: {
int idx = ListBox_FindItemData(_left_hwnd, ListBox_GetCurSel(_left_hwnd), entry);
ListBox_SetCurSel(_left_hwnd, idx);
set_curdir(entry, _hwnd);
}
}
if (!scanned_old) {
pane->calc_widths(FALSE);
pane->set_header();
}
} else {
entry->launch_entry(_hwnd);
}
}
void FileChildWindow::scan_entry(Entry* entry, HWND hwnd)
{
CONTEXT("FileChildWindow::scan_entry()");
int idx = ListBox_GetCurSel(_left_hwnd);
HCURSOR old_cursor = SetCursor(LoadCursor(0, IDC_WAIT));
// delete sub entries in left pane
for(;;) {
LRESULT res = ListBox_GetItemData(_left_hwnd, idx+1);
Entry* sub = (Entry*) res;
if (res==LB_ERR || !sub || sub->_level<=entry->_level)
break;
ListBox_DeleteString(_left_hwnd, idx+1);
}
// empty right pane
ListBox_ResetContent(_right_hwnd);
// release memory
entry->free_subentries();
entry->_expanded = false;
// read contents from disk
entry->read_directory(_sortOrder);
// insert found entries in right pane
_right->insert_entries(entry->_down, -1);
_right->calc_widths(false);
_right->set_header();
_header_wdths_ok = FALSE;
SetCursor(old_cursor);
}
int FileChildWindow::Notify(int id, NMHDR* pnmh)
{
return (pnmh->idFrom==IDW_HEADER_LEFT? _left: _right)->Notify(id, pnmh);
}
BOOL CALLBACK ExecuteDialog::WndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam)
{
static struct ExecuteDialog* dlg;
switch(nmsg) {
case WM_INITDIALOG:
dlg = (struct ExecuteDialog*) lparam;
return 1;
case WM_COMMAND: {
int id = (int)wparam;
if (id == IDOK) {
GetWindowText(GetDlgItem(hwnd, 201), dlg->cmd, MAX_PATH);
dlg->cmdshow = Button_GetState(GetDlgItem(hwnd,214))&BST_CHECKED?
SW_SHOWMINIMIZED: SW_SHOWNORMAL;
EndDialog(hwnd, id);
} else if (id == IDCANCEL)
EndDialog(hwnd, id);
return 1;}
}
return 0;
}
@@ -1,137 +0,0 @@
/*
* Copyright 2003 Martin Fuchs
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
//
// Explorer clone
//
// filechild.h
//
// Martin Fuchs, 23.07.2003
//
/// information structure for creation of FileChildWindow
struct FileChildWndInfo : public ChildWndInfo
{
typedef ChildWndInfo super;
FileChildWndInfo(HWND hmdiclient, LPCTSTR path, ENTRY_TYPE etype=ET_UNKNOWN);
ENTRY_TYPE _etype;
LPCTSTR _path;
WINDOWPLACEMENT _pos;
int _open_mode; //OPEN_WINDOW_MODE
};
/// information structure for creation of ShellBrowserChild
struct ShellChildWndInfo : public FileChildWndInfo
{
typedef FileChildWndInfo super;
ShellChildWndInfo(HWND hmdiclient, LPCTSTR path, const ShellPath& root_shell_path);
ShellPath _shell_path;
ShellPath _root_shell_path;
};
/// information structure for creation of FileChildWindow for NT object namespace
struct NtObjChildWndInfo : public FileChildWndInfo
{
typedef FileChildWndInfo super;
NtObjChildWndInfo(HWND hmdiclient, LPCTSTR path);
};
/// information structure for creation of FileChildWindow for the Registry
struct RegistryChildWndInfo : public FileChildWndInfo
{
typedef FileChildWndInfo super;
RegistryChildWndInfo(HWND hmdiclient, LPCTSTR path);
};
/// information structure for creation of FileChildWindow
struct FATChildWndInfo : public FileChildWndInfo
{
typedef FileChildWndInfo super;
FATChildWndInfo(HWND hmdiclient, LPCTSTR path);
};
/// information structure for creation of WebChildWindow
struct WebChildWndInfo : public FileChildWndInfo
{
typedef FileChildWndInfo super;
WebChildWndInfo(HWND hmdiclient, LPCTSTR url);
};
/// MDI child window displaying file lists
struct FileChildWindow : public ChildWindow
{
typedef ChildWindow super;
FileChildWindow(HWND hwnd, const FileChildWndInfo& info);
~FileChildWindow();
static FileChildWindow* create(const FileChildWndInfo& info);
protected:
LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
int Command(int id, int code);
int Notify(int id, NMHDR* pnmh);
virtual void resize_children(int cx, int cy);
void scan_entry(Entry* entry, HWND hwnd);
bool expand_entry(Entry* dir);
static void collapse_entry(Pane* pane, Entry* dir);
void set_curdir(Entry* entry, HWND hwnd);
void activate_entry(Pane* pane, HWND hwnd);
protected:
Root _root;
Pane* _left;
Pane* _right;
SORT_ORDER _sortOrder;
TCHAR _path[MAX_PATH];
bool _header_wdths_ok;
public:
const Root& get_root() const {return _root;}
void set_focus_pane(Pane* pane)
{_focus_pane = pane==_right? 1: 0;}
void switch_focus_pane()
{SetFocus(_focus_pane? *_left: *_right);}
};
/// The "Execute..."-dialog lets the user enter a command line to launch.
struct ExecuteDialog { ///@todo use class Dialog
TCHAR cmd[MAX_PATH];
int cmdshow;
static BOOL CALLBACK WndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam);
};
@@ -46,25 +46,14 @@ MainFrame::MainFrame(HWND hwnd)
_hAccel = LoadAccelerators(g_Globals._hInstance, MAKEINTRESOURCE(IDA_EXPLORER));
CLIENTCREATESTRUCT ccs;
ccs.hWindowMenu = _hMenuWindow;
ccs.idFirstChild = IDW_FIRST_CHILD;
#ifndef _NO_MDI
_hmdiclient = CreateWindowEx(0, TEXT("MDICLIENT"), NULL,
WS_CHILD|WS_CLIPCHILDREN|WS_VSCROLL|WS_HSCROLL|WS_VISIBLE|WS_BORDER,
0, 0, 0, 0,
hwnd, 0, g_Globals._hInstance, &ccs);
#endif
TBBUTTON toolbarBtns[] = {
{0, 0, 0, BTNS_SEP, {0, 0}, 0, 0},
{0, ID_WINDOW_NEW, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
{1, ID_WINDOW_CASCADE, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
{2, ID_WINDOW_TILE_HORZ, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
{3, ID_WINDOW_TILE_VERT, TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
/*TODO
{4, ID_... , TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
{5, ID_... , TBSTATE_ENABLED, BTNS_BUTTON, {0, 0}, 0, 0},
@@ -81,65 +70,45 @@ MainFrame::MainFrame(HWND hwnd)
CheckMenuItem(_menu_info._hMenuOptions, ID_VIEW_TOOL_BAR, MF_BYCOMMAND|MF_CHECKED);
TBBUTTON drivebarBtn = {0, 0, TBSTATE_ENABLED, BTNS_SEP, {0, 0}, 0, 0};
int btn = 1;
PTSTR p;
_hdrivebar = CreateToolbarEx(hwnd, WS_CHILD|WS_VISIBLE|CCS_NOMOVEY|TBSTYLE_LIST,
IDW_DRIVEBAR, 2, g_Globals._hInstance, IDB_DRIVEBAR, &drivebarBtn,
1, 16, 13, 16, 13, sizeof(TBBUTTON));
CheckMenuItem(_menu_info._hMenuOptions, ID_VIEW_DRIVE_BAR, MF_BYCOMMAND|MF_CHECKED);
GetLogicalDriveStrings(BUFFER_LEN, _drives);
drivebarBtn.fsStyle = BTNS_BUTTON;
// insert explorer window button
SendMessage(_hdrivebar, TB_ADDSTRING, 0, (LPARAM)TEXT("Explore\0"));
drivebarBtn.idCommand = ID_DRIVE_DESKTOP;
SendMessage(_hdrivebar, TB_INSERTBUTTON, btn++, (LPARAM)&drivebarBtn);
++drivebarBtn.iString;
// register windows drive root strings
SendMessage(_hdrivebar, TB_ADDSTRING, 0, (LPARAM)_drives);
drivebarBtn.idCommand = ID_DRIVE_FIRST;
for(p=_drives; *p; ) {
// insert drive letter
TCHAR b[3] = {tolower(*p)};
SendMessage(_hdrivebar, TB_ADDSTRING, 0, (LPARAM)b);
switch(GetDriveType(p)) {
case DRIVE_REMOVABLE: drivebarBtn.iBitmap = 1; break;
case DRIVE_CDROM: drivebarBtn.iBitmap = 3; break;
case DRIVE_REMOTE: drivebarBtn.iBitmap = 4; break;
case DRIVE_RAMDISK: drivebarBtn.iBitmap = 5; break;
default:/*DRIVE_FIXED*/ drivebarBtn.iBitmap = 2;
}
SendMessage(_hdrivebar, TB_INSERTBUTTON, btn++, (LPARAM)&drivebarBtn);
++drivebarBtn.idCommand;
++drivebarBtn.iString;
while(*p++);
}
// address & command bar
WindowCanvas canvas(hwnd);
RECT rect = {0, 0, 0, 0};
DrawText(canvas, TEXT("My"), -1, &rect, DT_SINGLELINE|DT_NOPREFIX|DT_CALCRECT);
/* CreateStatusWindow does not accept WS_BORDER
_hstatusbar = CreateWindowEx(WS_EX_NOPARENTNOTIFY, STATUSCLASSNAME, 0,
WS_CHILD|WS_VISIBLE|WS_CLIPSIBLINGS|WS_BORDER|CCS_NODIVIDER, 0,0,0,0,
hwnd, (HMENU)IDW_STATUSBAR, g_Globals._hInstance, 0);*/
_hstatusbar = CreateStatusWindow(WS_CHILD|WS_VISIBLE, 0, hwnd, IDW_STATUSBAR);
CheckMenuItem(_menu_info._hMenuOptions, ID_VIEW_STATUSBAR, MF_BYCOMMAND|MF_CHECKED);
update_explorer_view();
}
void MainFrame::update_explorer_view()
{
int split_pos = DEFAULT_SPLIT_POS; //@@
if (_shellBrowser.get()) {
split_pos = _shellBrowser->_split_pos;
delete _shellBrowser.release();
}
// create explorer treeview
if (_create_info._open_mode & OWM_EXPLORE) {
if (!_left_hwnd) {
WindowCanvas canvas(_hwnd);
RECT rect = {0, 0, 0, 0};
DrawText(canvas, TEXT("My"), -1, &rect, DT_SINGLELINE|DT_NOPREFIX|DT_CALCRECT);
_left_hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, WC_TREEVIEW, NULL,
WS_CHILD|WS_TABSTOP|WS_VISIBLE|WS_CHILD|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_NOTOOLTIPS|TVS_SHOWSELALWAYS,
0, rect.top, split_pos-SPLIT_WIDTH/2, rect.bottom-rect.top,
_hwnd, (HMENU)IDC_FILETREE, g_Globals._hInstance, 0);
}
} else {
if (_left_hwnd) {
DestroyWindow(_left_hwnd);
_left_hwnd = 0;
}
}
_shellBrowser = auto_ptr<ShellBrowserChild>(new ShellBrowserChild(_hwnd, _left_hwnd, _right_hwnd, _create_info));
// update _shellBrowser->_clnt_rect
ClientRect rect(_hwnd);
resize_frame(rect.right, rect.bottom);
}
@@ -172,7 +141,7 @@ HWND MainFrame::Create(LPCTSTR path, int mode)
MainFrame* pMainFrame = GET_WINDOW(MainFrame, hMainFrame);
if (pMainFrame)
pMainFrame->CreateChild(path, mode);
pMainFrame->jump_to(path, mode);
return hMainFrame;
}
@@ -188,20 +157,28 @@ HWND MainFrame::Create(LPCITEMIDLIST pidl, int mode)
MainFrame* pMainFrame = GET_WINDOW(MainFrame, hMainFrame);
if (pMainFrame)
pMainFrame->CreateChild(pidl, mode);
pMainFrame->jump_to(pidl, mode);
return hMainFrame;
}
ChildWindow* MainFrame::CreateChild(LPCTSTR path, int mode)
void MainFrame::jump_to(LPCTSTR path, int mode)
{
return reinterpret_cast<ChildWindow*>(SendMessage(_hwnd, PM_OPEN_WINDOW, mode, (LPARAM)path));
_create_info._open_mode = mode;
_create_info._shell_path = path;
_create_info._root_shell_path = SpecialFolderPath(CSIDL_DRIVES, _hwnd); //@@
update_explorer_view();
}
ChildWindow* MainFrame::CreateChild(LPCITEMIDLIST pidl, int mode)
void MainFrame::jump_to(LPCITEMIDLIST path, int mode)
{
return reinterpret_cast<ChildWindow*>(SendMessage(_hwnd, PM_OPEN_WINDOW, mode|OWM_PIDL, (LPARAM)pidl));
_create_info._open_mode = mode;
_create_info._shell_path = path;
_create_info._root_shell_path = DesktopFolderPath(); //@@
update_explorer_view();
}
@@ -233,25 +210,7 @@ int MainFrame::OpenShellFolders(LPIDA pida, HWND hFrameWnd)
} catch(COMException& e) {
HandleException(e, g_Globals._hMainWnd);
}
}/*TEST
else { // !(attribs & SFGAO_FOLDER))
SHELLEXECUTEINFOA shexinfo;
shexinfo.cbSize = sizeof(SHELLEXECUTEINFOA);
shexinfo.fMask = SEE_MASK_INVOKEIDLIST;
shexinfo.hwnd = NULL;
shexinfo.lpVerb = NULL;
shexinfo.lpFile = NULL;
shexinfo.lpParameters = NULL;
shexinfo.lpDirectory = NULL;
shexinfo.nShow = SW_NORMAL;
shexinfo.lpIDList = ILCombine(parent_pidl, pidl);
if (ShellExecuteExA(&shexinfo))
++cnt;
ILFree((LPITEMIDLIST)shexinfo.lpIDList);
}*/
}
}
return cnt;
@@ -264,11 +223,6 @@ LRESULT MainFrame::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
case PM_TRANSLATE_MSG: {
MSG* pmsg = (MSG*) lparam;
#ifndef _NO_MDI
if (_hmdiclient && TranslateMDISysAccel(_hmdiclient, pmsg))
return TRUE;
#endif
if (TranslateAccelerator(_hwnd, _hAccel, pmsg))
return TRUE;
@@ -284,7 +238,7 @@ LRESULT MainFrame::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
case WM_SIZE:
resize_frame(LOWORD(lparam), HIWORD(lparam));
break; // do not pass message to DefFrameProc
break;
case WM_GETMINMAXINFO: {
LPMINMAXINFO lpmmi = (LPMINMAXINFO)lparam;
@@ -330,23 +284,7 @@ LRESULT MainFrame::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
path = buffer;
}
{
OBJ_CONTEXT("create ShellChildWndInfo", path);
// Shell Namespace as default view
ShellChildWndInfo create_info(_hmdiclient, path, shell_path);
create_info._pos.showCmd = SW_SHOWMAXIMIZED;
create_info._pos.rcNormalPosition.left = 0;
create_info._pos.rcNormalPosition.top = 0;
create_info._pos.rcNormalPosition.right = 600;
create_info._pos.rcNormalPosition.bottom = 280;
create_info._open_mode = (OPEN_WINDOW_MODE)wparam;
// FileChildWindow::create(_hmdiclient, create_info);
return (LRESULT)ShellBrowserChild::create(create_info);
}
jump_to(shell_path, (OPEN_WINDOW_MODE)wparam);
break;}
case PM_GET_CONTROLWINDOW:
@@ -354,61 +292,31 @@ LRESULT MainFrame::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
return (LRESULT)(HWND)_hstatusbar;
break;
case PM_SETSTATUSTEXT:
SendMessage(_hstatusbar, SB_SETTEXT, 0, lparam);
break;
default:
#ifndef _NO_MDI
return DefFrameProc(_hwnd, _hmdiclient, nmsg, wparam, lparam);
#else
return super::WNdProc(nmsg, wparam, lparam);
#endif
if (_shellBrowser.get())
return _shellBrowser->WndProc(nmsg, wparam, lparam);
else
return super::WndProc(nmsg, wparam, lparam);
}
return 0;
}
int MainFrame::Notify(int id, NMHDR* pnmh)
{
if (_shellBrowser.get())
return _shellBrowser->Notify(id, pnmh);
return super::Notify(id, pnmh);
}
int MainFrame::Command(int id, int code)
{
CONTEXT("MainFrame::Command()");
#ifndef _NO_MDI
HWND hwndClient = (HWND) SendMessage(_hmdiclient, WM_MDIGETACTIVE, 0, 0);
if (SendMessage(hwndClient, PM_DISPATCH_COMMAND, MAKELONG(id,code), 0))
return 0;
#endif
if (id>=ID_DRIVE_FIRST && id<=ID_DRIVE_FIRST+0xFF) {
TCHAR drv[_MAX_DRIVE], path[MAX_PATH];
LPCTSTR root = _drives;
for(int i=id-ID_DRIVE_FIRST; i--; root++)
while(*root)
++root;
if (activate_drive_window(root))
return 0;
_tsplitpath(root, drv, 0, 0, 0);
if (!SetCurrentDirectory(drv)) {
display_error(_hwnd, GetLastError());
return 0;
}
GetCurrentDirectory(MAX_PATH, path); ///@todo store last directory per drive
#ifndef _NO_MDI
FileChildWindow::create(FileChildWndInfo(_hmdiclient, path));
#else
///@todo SDI implementation
#endif
return 1;
}
switch(id) {
case ID_FILE_EXIT:
SendMessage(_hwnd, WM_CLOSE, 0, 0);
@@ -419,39 +327,13 @@ int MainFrame::Command(int id, int code)
GetCurrentDirectory(MAX_PATH, path);
#ifndef _NO_MDI
FileChildWindow::create(FileChildWndInfo(_hmdiclient, path));
#else
///@todo SDI implementation
#endif
MainFrame::Create(path);
break;}
#ifndef _NO_MDI
case ID_WINDOW_CASCADE:
SendMessage(_hmdiclient, WM_MDICASCADE, 0, 0);
break;
case ID_WINDOW_TILE_HORZ:
SendMessage(_hmdiclient, WM_MDITILE, MDITILE_HORIZONTAL, 0);
break;
case ID_WINDOW_TILE_VERT:
SendMessage(_hmdiclient, WM_MDITILE, MDITILE_VERTICAL, 0);
break;
case ID_WINDOW_ARRANGE:
SendMessage(_hmdiclient, WM_MDIICONARRANGE, 0, 0);
break;
#endif
case ID_VIEW_TOOL_BAR:
toggle_child(_hwnd, id, _htoolbar);
break;
case ID_VIEW_DRIVE_BAR:
toggle_child(_hwnd, id, _hdrivebar);
break;
case ID_VIEW_STATUSBAR:
toggle_child(_hwnd, id, _hstatusbar);
break;
@@ -473,21 +355,6 @@ int MainFrame::Command(int id, int code)
WinHelp(_hwnd, TEXT("explorer")/*file explorer.hlp*/, HELP_INDEX, 0);
break;
case ID_VIEW_FULLSCREEN:
CheckMenuItem(_menu_info._hMenuOptions, id, toggle_fullscreen()?MF_CHECKED:0);
break;
case ID_DRIVE_DESKTOP: {
TCHAR path[MAX_PATH];
if (activate_child_window(TEXT("Desktop")))
break;
GetCurrentDirectory(MAX_PATH, path);
ShellBrowserChild::create(ShellChildWndInfo(_hmdiclient, path, DesktopFolderPath()));
break;}
///@todo There are even more menu items!
case ID_ABOUT_WINDOWS:
@@ -503,11 +370,7 @@ int MainFrame::Command(int id, int code)
break;
default:
#ifndef _NO_MDI
return DefFrameProc(_hwnd, _hmdiclient, WM_COMMAND, MAKELONG(id,code), 0);
#else
return 1;
#endif
}
return 0;
@@ -516,21 +379,10 @@ int MainFrame::Command(int id, int code)
void MainFrame::resize_frame_rect(PRECT prect)
{
int new_top;
if (IsWindowVisible(_htoolbar)) {
SendMessage(_htoolbar, WM_SIZE, 0, 0);
ClientRect rt(_htoolbar);
prect->top = rt.bottom+3;
// prect->bottom -= rt.bottom+3;
}
if (IsWindowVisible(_hdrivebar)) {
SendMessage(_hdrivebar, WM_SIZE, 0, 0);
ClientRect rt(_hdrivebar);
new_top = --prect->top + rt.bottom+3;
MoveWindow(_hdrivebar, 0, prect->top, rt.right, new_top, TRUE);
prect->top = new_top;
prect->top = rt.bottom+2;
// prect->bottom -= rt.bottom+2;
}
@@ -542,19 +394,6 @@ void MainFrame::resize_frame_rect(PRECT prect)
ClientRect rt(_hstatusbar);
prect->bottom -= rt.bottom;
}
if (IsWindowVisible(_haddressedit) || IsWindowVisible(_hcommandedit)) {
ClientRect rt(_haddressedit);
prect->bottom -= rt.bottom;
int mid = (prect->right-prect->left) / 2; ///@todo use split bar
SetWindowPos(_haddressedit, 0, 0, prect->bottom, mid, rt.bottom, SWP_NOACTIVATE|SWP_NOZORDER);
SetWindowPos(_hcommandedit, 0, mid+1, prect->bottom, prect->right-(mid+1), rt.bottom, SWP_NOACTIVATE|SWP_NOZORDER);
}
#ifndef _NO_MDI
MoveWindow(_hmdiclient, prect->left-1,prect->top-1,prect->right-prect->left+2,prect->bottom-prect->top+1, TRUE);
#endif
}
void MainFrame::resize_frame(int cx, int cy)
@@ -567,6 +406,11 @@ void MainFrame::resize_frame(int cx, int cy)
rect.bottom = cy;
resize_frame_rect(&rect);
if (_shellBrowser.get()) {
_shellBrowser->_clnt_rect = rect;
_shellBrowser->resize_children();
}
}
void MainFrame::resize_frame_client()
@@ -598,65 +442,12 @@ void MainFrame::frame_get_clientspace(PRECT prect)
prect->top += rt.bottom+2;
}
if (IsWindowVisible(_hdrivebar)) {
ClientRect rt(_hdrivebar);
prect->top += rt.bottom+2;
}
if (IsWindowVisible(_hstatusbar)) {
ClientRect rt(_hstatusbar);
prect->bottom -= rt.bottom;
}
}
BOOL MainFrame::toggle_fullscreen()
{
RECT rt;
if ((_fullscreen._mode=!_fullscreen._mode)) {
GetWindowRect(_hwnd, &_fullscreen._orgPos);
_fullscreen._wasZoomed = IsZoomed(_hwnd);
Frame_CalcFrameClient(_hwnd, &rt);
ClientToScreen(_hwnd, (LPPOINT)&rt.left);
ClientToScreen(_hwnd, (LPPOINT)&rt.right);
rt.left = _fullscreen._orgPos.left-rt.left;
rt.top = _fullscreen._orgPos.top-rt.top;
rt.right = GetSystemMetrics(SM_CXSCREEN)+_fullscreen._orgPos.right-rt.right;
rt.bottom = GetSystemMetrics(SM_CYSCREEN)+_fullscreen._orgPos.bottom-rt.bottom;
MoveWindow(_hwnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE);
} else {
MoveWindow(_hwnd, _fullscreen._orgPos.left, _fullscreen._orgPos.top,
_fullscreen._orgPos.right-_fullscreen._orgPos.left,
_fullscreen._orgPos.bottom-_fullscreen._orgPos.top, TRUE);
if (_fullscreen._wasZoomed)
ShowWindow(_hwnd, WS_MAXIMIZE);
}
return _fullscreen._mode;
}
void MainFrame::fullscreen_move()
{
RECT rt, pos;
GetWindowRect(_hwnd, &pos);
Frame_CalcFrameClient(_hwnd, &rt);
ClientToScreen(_hwnd, (LPPOINT)&rt.left);
ClientToScreen(_hwnd, (LPPOINT)&rt.right);
rt.left = pos.left-rt.left;
rt.top = pos.top-rt.top;
rt.right = GetSystemMetrics(SM_CXSCREEN)+pos.right-rt.right;
rt.bottom = GetSystemMetrics(SM_CYSCREEN)+pos.bottom-rt.bottom;
MoveWindow(_hwnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE);
}
void MainFrame::toggle_child(HWND hwnd, UINT cmd, HWND hchild)
{
BOOL vis = IsWindowVisible(hchild);
@@ -665,74 +456,32 @@ void MainFrame::toggle_child(HWND hwnd, UINT cmd, HWND hchild)
ShowWindow(hchild, vis?SW_HIDE:SW_SHOW);
if (_fullscreen._mode)
fullscreen_move();
resize_frame_client();
}
#ifndef _NO_MDI
bool MainFrame::activate_drive_window(LPCTSTR path)
BOOL CALLBACK ExecuteDialog::WndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam)
{
TCHAR drv1[_MAX_DRIVE], drv2[_MAX_DRIVE];
HWND child_wnd;
static struct ExecuteDialog* dlg;
_tsplitpath(path, drv1, 0, 0, 0);
switch(nmsg) {
case WM_INITDIALOG:
dlg = (struct ExecuteDialog*) lparam;
return 1;
// search for a already open window for the same drive
for(child_wnd=::GetNextWindow(_hmdiclient,GW_CHILD); child_wnd; child_wnd=::GetNextWindow(child_wnd, GW_HWNDNEXT)) {
FileChildWindow* child = (FileChildWindow*) SendMessage(child_wnd, PM_GET_FILEWND_PTR, 0, 0);
case WM_COMMAND: {
int id = (int)wparam;
if (child) {
_tsplitpath(child->get_root()._path, drv2, 0, 0, 0);
if (id == IDOK) {
GetWindowText(GetDlgItem(hwnd, 201), dlg->cmd, MAX_PATH);
dlg->cmdshow = Button_GetState(GetDlgItem(hwnd,214))&BST_CHECKED?
SW_SHOWMINIMIZED: SW_SHOWNORMAL;
EndDialog(hwnd, id);
} else if (id == IDCANCEL)
EndDialog(hwnd, id);
if (!lstrcmpi(drv2, drv1)) {
SendMessage(_hmdiclient, WM_MDIACTIVATE, (WPARAM)child_wnd, 0);
if (IsMinimized(child_wnd))
ShowWindow(child_wnd, SW_SHOWNORMAL);
return true;
}
}
return 1;}
}
return false;
return 0;
}
bool MainFrame::activate_child_window(LPCTSTR filesys)
{
HWND child_wnd;
// search for a already open window of the given file system name
for(child_wnd=::GetNextWindow(_hmdiclient,GW_CHILD); child_wnd; child_wnd=::GetNextWindow(child_wnd, GW_HWNDNEXT)) {
FileChildWindow* child = (FileChildWindow*) SendMessage(child_wnd, PM_GET_FILEWND_PTR, 0, 0);
if (child) {
if (!lstrcmpi(child->get_root()._fs, filesys)) {
SendMessage(_hmdiclient, WM_MDIACTIVATE, (WPARAM)child_wnd, 0);
if (IsMinimized(child_wnd))
ShowWindow(child_wnd, SW_SHOWNORMAL);
return true;
}
} else {
ShellBrowserChild* shell_child = (ShellBrowserChild*) SendMessage(child_wnd, PM_GET_SHELLBROWSER_PTR, 0, 0);
if (shell_child) {
if (!lstrcmpi(shell_child->get_root()._fs, filesys)) {
SendMessage(_hmdiclient, WM_MDIACTIVATE, (WPARAM)child_wnd, 0);
if (IsMinimized(child_wnd))
ShowWindow(child_wnd, SW_SHOWNORMAL);
return true;
}
}
}
}
return false;
}
#endif
@@ -43,42 +43,50 @@ struct MainFrame : public PreTranslateWindow
static HWND Create(LPCITEMIDLIST pidl, int mode=OWM_EXPLORE|OWM_DETAILS|OWM_PIDL);
static int OpenShellFolders(LPIDA pida, HWND hFrameWnd);
ChildWindow* CreateChild(LPCTSTR path=NULL, int mode=OWM_EXPLORE|OWM_DETAILS);
ChildWindow* CreateChild(LPCITEMIDLIST pidl, int mode=OWM_EXPLORE|OWM_DETAILS|OWM_PIDL);
protected:
FullScreenParameters _fullscreen;
#ifndef _NO_MDI
HWND _hmdiclient;
#endif
WindowHandle _hstatusbar;
WindowHandle _htoolbar;
WindowHandle _hdrivebar;
WindowHandle _haddressedit;
WindowHandle _hcommandedit;
HMENU _hMenuFrame;
HMENU _hMenuWindow;
MenuInfo _menu_info;
auto_ptr<ShellBrowserChild> _shellBrowser;
protected:
LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
int Notify(int id, NMHDR* pnmh);
int Command(int id, int code);
void toggle_child(HWND hwnd, UINT cmd, HWND hchild);
bool activate_drive_window(LPCTSTR path);
bool activate_child_window(LPCTSTR filesys);
void resize_frame_rect(PRECT prect);
void resize_frame(int cx, int cy);
void resize_frame_client();
void frame_get_clientspace(PRECT prect);
BOOL toggle_fullscreen();
void fullscreen_move();
HACCEL _hAccel;
TCHAR _drives[BUFFER_LEN];
// SDI integration
ShellPathInfo _create_info;
WindowHandle _left_hwnd;
WindowHandle _right_hwnd;
//@@int _focus_pane; // 0: left 1: right
void update_explorer_view();
void jump_to(LPCTSTR path, int mode);
void jump_to(LPCITEMIDLIST path, int mode);
};
/// The "Execute..."-dialog lets the user enter a command line to launch.
struct ExecuteDialog { ///@todo use class Dialog
TCHAR cmd[MAX_PATH];
int cmdshow;
static BOOL CALLBACK WndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam);
};
@@ -1,990 +0,0 @@
/*
* Copyright 2003 Martin Fuchs
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
//
// Explorer clone
//
// pane.cpp
//
// Martin Fuchs, 23.07.2003
//
#include "../utility/utility.h"
#include "../explorer.h"
#include "../globals.h"
#include "../explorer_intres.h"
enum IMAGE {
IMG_NONE=-1, IMG_FILE=0, IMG_DOCUMENT, IMG_EXECUTABLE,
IMG_FOLDER, IMG_OPEN_FOLDER, IMG_FOLDER_PLUS,IMG_OPEN_PLUS, IMG_OPEN_MINUS,
IMG_FOLDER_UP, IMG_FOLDER_CUR
};
#define IMAGE_WIDTH 16
#define IMAGE_HEIGHT 13
static const LPTSTR g_pos_names[COLUMNS] = {
TEXT(""), /* symbol */
TEXT("Name"),
TEXT("Type"),
TEXT("Size"),
TEXT("CDate"),
TEXT("ADate"),
TEXT("MDate"),
TEXT("Index/Inode"),
TEXT("Links"),
TEXT("Attributes"),
TEXT("Security"),
TEXT("Content")
};
static const int g_pos_align[] = {
0,
HDF_LEFT, /* Name */
HDF_LEFT, /* Type */
HDF_RIGHT, /* Size */
HDF_LEFT, /* CDate */
HDF_LEFT, /* ADate */
HDF_LEFT, /* MDate */
HDF_LEFT, /* Index */
HDF_RIGHT, /* Links */
HDF_CENTER, /* Attributes */
HDF_LEFT, /* Security */
HDF_LEFT /* Content / Description */
};
Pane::Pane(HWND hparent, int id, int id_header, Entry* root, bool treePane, int visible_cols)
: super(CreateWindow(TEXT("ListBox"), TEXT(""), WS_CHILD|WS_VISIBLE|WS_HSCROLL|WS_VSCROLL|
LBS_DISABLENOSCROLL|LBS_NOINTEGRALHEIGHT|LBS_OWNERDRAWFIXED|LBS_NOTIFY,
0, 0, 0, 0, hparent, (HMENU)id, g_Globals._hInstance, 0)),
_root(root),
_visible_cols(visible_cols),
_treePane(treePane)
{
// insert entries into listbox
Entry* entry = _root;
if (entry)
insert_entries(entry, -1);
init();
create_header(hparent, id_header);
}
LRESULT Pane::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
{
switch(nmsg) {
case WM_HSCROLL:
set_header();
break;
case WM_SETFOCUS: {
FileChildWindow* child = (FileChildWindow*) SendMessage(GetParent(_hwnd), PM_GET_FILEWND_PTR, 0, 0);
child->set_focus_pane(this);
ListBox_SetSel(_hwnd, TRUE, 1);
/*@todo check menu items */
break;}
case WM_KEYDOWN: {
FileChildWindow* child = (FileChildWindow*) SendMessage(GetParent(_hwnd), PM_GET_FILEWND_PTR, 0, 0);
if (wparam == VK_TAB) {
/*@todo SetFocus(g_Globals.hdrivebar) */
child->switch_focus_pane();
}
break;}
}
return super::WndProc(nmsg, wparam, lparam);
}
bool Pane::create_header(HWND hparent, int id)
{
HWND hwnd = CreateWindow(WC_HEADER, 0, WS_CHILD|WS_VISIBLE|HDS_HORZ/*@todo |HDS_BUTTONS + sort orders*/,
0, 0, 0, 0, hparent, (HMENU)id, g_Globals._hInstance, 0);
if (!hwnd)
return false;
SetWindowFont(hwnd, GetStockFont(DEFAULT_GUI_FONT), FALSE);
HD_ITEM hdi;
hdi.mask = HDI_TEXT|HDI_WIDTH|HDI_FORMAT;
for(int idx=0; idx<COLUMNS; idx++) {
hdi.pszText = g_pos_names[idx];
hdi.fmt = HDF_STRING | g_pos_align[idx];
hdi.cxy = _widths[idx];
Header_InsertItem(hwnd, idx, &hdi);
}
_hwndHeader = hwnd;
return true;
}
void Pane::init()
{
_himl = ImageList_LoadBitmap(g_Globals._hInstance, MAKEINTRESOURCE(IDB_IMAGES), 16, 0, RGB(0,255,0));
SetWindowFont(_hwnd, _out_wrkr._hfont, FALSE);
// read the color for compressed files from registry
HKEY hkeyExplorer = 0;
DWORD len = sizeof(_clrCompressed);
if (RegOpenKey(HKEY_CURRENT_USER, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"), &hkeyExplorer) ||
RegQueryValueEx(hkeyExplorer, TEXT("AltColor"), 0, NULL, (LPBYTE)&_clrCompressed, &len) || len!=sizeof(_clrCompressed))
_clrCompressed = RGB(0,0,255);
if (hkeyExplorer)
RegCloseKey(hkeyExplorer);
// calculate column widths
_out_wrkr.init_output(_hwnd);
calc_widths(true);
}
// calculate prefered width for all visible columns
bool Pane::calc_widths(bool anyway)
{
int col, x, cx, spc=3*_out_wrkr._spaceSize.cx;
int entries = ListBox_GetCount(_hwnd);
int orgWidths[COLUMNS];
int orgPositions[COLUMNS+1];
HFONT hfontOld;
HDC hdc;
int cnt;
if (!anyway) {
memcpy(orgWidths, _widths, sizeof(orgWidths));
memcpy(orgPositions, _positions, sizeof(orgPositions));
}
for(col=0; col<COLUMNS; col++)
_widths[col] = 0;
hdc = GetDC(_hwnd);
hfontOld = SelectFont(hdc, _out_wrkr._hfont);
for(cnt=0; cnt<entries; cnt++) {
Entry* entry = (Entry*) ListBox_GetItemData(_hwnd, cnt);
DRAWITEMSTRUCT dis;
dis.CtlType = 0;
dis.CtlID = 0;
dis.itemID = 0;
dis.itemAction = 0;
dis.itemState = 0;
dis.hwndItem = _hwnd;
dis.hDC = hdc;
dis.rcItem.left = 0;
dis.rcItem.top = 0;
dis.rcItem.right = 0;
dis.rcItem.bottom = 0;
/*dis.itemData = 0; */
draw_item(&dis, entry, COLUMNS);
}
SelectObject(hdc, hfontOld);
ReleaseDC(_hwnd, hdc);
x = 0;
for(col=0; col<COLUMNS; col++) {
_positions[col] = x;
cx = _widths[col];
if (cx) {
cx += spc;
if (cx < IMAGE_WIDTH)
cx = IMAGE_WIDTH;
_widths[col] = cx;
}
x += cx;
}
_positions[COLUMNS] = x;
ListBox_SetHorizontalExtent(_hwnd, x);
// no change?
if (!memcmp(orgWidths, _widths, sizeof(orgWidths)))
return FALSE;
// don't move, if only collapsing an entry
if (!anyway && _widths[0]<orgWidths[0] &&
!memcmp(orgWidths+1, _widths+1, sizeof(orgWidths)-sizeof(int))) {
_widths[0] = orgWidths[0];
memcpy(_positions, orgPositions, sizeof(orgPositions));
return FALSE;
}
InvalidateRect(_hwnd, 0, TRUE);
return TRUE;
}
static void format_date(const FILETIME* ft, TCHAR* buffer, int visible_cols)
{
SYSTEMTIME systime;
FILETIME lft;
int len = 0;
*buffer = TEXT('\0');
if (!ft->dwLowDateTime && !ft->dwHighDateTime)
return;
if (!FileTimeToLocalFileTime(ft, &lft))
{err: lstrcpy(buffer,TEXT("???")); return;}
if (!FileTimeToSystemTime(&lft, &systime))
goto err;
if (visible_cols & COL_DATE) {
len = GetDateFormat(LOCALE_USER_DEFAULT, 0, &systime, 0, buffer, BUFFER_LEN);
if (!len)
goto err;
}
if (visible_cols & COL_TIME) {
if (len)
buffer[len-1] = ' ';
buffer[len++] = ' ';
if (!GetTimeFormat(LOCALE_USER_DEFAULT, 0, &systime, 0, buffer+len, BUFFER_LEN-len))
buffer[len] = TEXT('\0');
}
}
void Pane::draw_item(LPDRAWITEMSTRUCT dis, Entry* entry, int calcWidthCol)
{
TCHAR buffer[BUFFER_LEN];
DWORD attrs;
int visible_cols = _visible_cols;
COLORREF bkcolor, textcolor;
RECT focusRect = dis->rcItem;
enum IMAGE img;
int img_pos, cx;
int col = 0;
if (entry) {
attrs = entry->_data.dwFileAttributes;
if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
if (entry->_data.cFileName[0]==TEXT('.') && entry->_data.cFileName[1]==TEXT('.')
&& entry->_data.cFileName[2]==TEXT('\0'))
img = IMG_FOLDER_UP;
else if (entry->_data.cFileName[0]==TEXT('.') && entry->_data.cFileName[1]==TEXT('\0'))
img = IMG_FOLDER_CUR;
else if ((_treePane && (dis->itemState&ODS_FOCUS)))
img = IMG_OPEN_FOLDER;
else
img = IMG_FOLDER;
} else {
if (attrs & ATTRIBUTE_EXECUTABLE)
img = IMG_EXECUTABLE;
else if (entry->_type_name)
img = IMG_DOCUMENT;
else
img = IMG_FILE;
}
} else {
attrs = 0;
img = IMG_NONE;
}
if (_treePane) {
if (entry) {
img_pos = dis->rcItem.left + entry->_level*(IMAGE_WIDTH+_out_wrkr._spaceSize.cx);
if (calcWidthCol == -1) {
int x;
int y = dis->rcItem.top + IMAGE_HEIGHT/2;
Entry* up;
RECT rt_clip;
HRGN hrgn_org = CreateRectRgn(0, 0, 0, 0);
HRGN hrgn;
rt_clip.left = dis->rcItem.left;
rt_clip.top = dis->rcItem.top;
rt_clip.right = dis->rcItem.left+_widths[col];
rt_clip.bottom = dis->rcItem.bottom;
hrgn = CreateRectRgnIndirect(&rt_clip);
if (!GetClipRgn(dis->hDC, hrgn_org)) {
DeleteObject(hrgn_org);
hrgn_org = 0;
}
//HGDIOBJ holdPen = SelectObject(dis->hDC, GetStockObject(BLACK_PEN));
ExtSelectClipRgn(dis->hDC, hrgn, RGN_AND);
DeleteObject(hrgn);
if ((up=entry->_up) != NULL) {
MoveToEx(dis->hDC, img_pos-IMAGE_WIDTH/2, y, 0);
LineTo(dis->hDC, img_pos-2, y);
x = img_pos - IMAGE_WIDTH/2;
do {
x -= IMAGE_WIDTH+_out_wrkr._spaceSize.cx;
if (up->_next) {
#ifndef _LEFT_FILES
bool following_child = (up->_next->_data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)!=0; // a directory?
if (!following_child)
for(Entry*n=up->_next; n; n=n->_next)
if (n->_down) { // any file with NTFS sub-streams?
following_child = true;
break;
}
if (following_child)
#endif
{
MoveToEx(dis->hDC, x, dis->rcItem.top, 0);
LineTo(dis->hDC, x, dis->rcItem.bottom);
}
}
} while((up=up->_up) != NULL);
}
x = img_pos - IMAGE_WIDTH/2;
MoveToEx(dis->hDC, x, dis->rcItem.top, 0);
LineTo(dis->hDC, x, y);
if (entry->_next) {
#ifndef _LEFT_FILES
bool following_child = (entry->_next->_data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)!=0; // a directory?
if (!following_child)
for(Entry*n=entry->_next; n; n=n->_next)
if (n->_down) { // any file with NTFS sub-streams?
following_child = true;
break;
}
if (following_child)
#endif
LineTo(dis->hDC, x, dis->rcItem.bottom);
}
if (entry->_down && entry->_expanded) {
x += IMAGE_WIDTH + _out_wrkr._spaceSize.cx;
MoveToEx(dis->hDC, x, dis->rcItem.top+IMAGE_HEIGHT, 0);
LineTo(dis->hDC, x, dis->rcItem.bottom);
}
SelectClipRgn(dis->hDC, hrgn_org);
if (hrgn_org) DeleteObject(hrgn_org);
//SelectObject(dis->hDC, holdPen);
} else if (calcWidthCol==col || calcWidthCol==COLUMNS) {
int right = img_pos + IMAGE_WIDTH - _out_wrkr._spaceSize.cx;
if (right > _widths[col])
_widths[col] = right;
}
} else {
img_pos = dis->rcItem.left;
}
} else {
img_pos = dis->rcItem.left;
if (calcWidthCol==col || calcWidthCol==COLUMNS)
_widths[col] = IMAGE_WIDTH;
}
if (calcWidthCol == -1) {
focusRect.left = img_pos -2;
if (attrs & FILE_ATTRIBUTE_COMPRESSED)
textcolor = _clrCompressed;
else
textcolor = RGB(0,0,0);
if (dis->itemState & ODS_FOCUS) {
textcolor = GetSysColor(COLOR_HIGHLIGHTTEXT);
bkcolor = GetSysColor(COLOR_HIGHLIGHT);
} else {
bkcolor = GetSysColor(COLOR_WINDOW);
}
HBRUSH hbrush = CreateSolidBrush(bkcolor);
FillRect(dis->hDC, &focusRect, hbrush);
DeleteObject(hbrush);
SetBkMode(dis->hDC, TRANSPARENT);
SetTextColor(dis->hDC, textcolor);
cx = _widths[col];
if (cx && img!=IMG_NONE) {
if (cx > IMAGE_WIDTH)
cx = IMAGE_WIDTH;
if (entry->_icon_id > ICID_NONE)
g_Globals._icon_cache.get_icon(entry->_icon_id).draw(dis->hDC, img_pos, dis->rcItem.top, cx, GetSystemMetrics(SM_CYSMICON), bkcolor, 0);
else
ImageList_DrawEx(_himl, img, dis->hDC,
img_pos, dis->rcItem.top, cx,
IMAGE_HEIGHT, bkcolor, CLR_DEFAULT, ILD_NORMAL);
}
}
if (!entry)
return;
++col;
// output file name
if (calcWidthCol == -1)
_out_wrkr.output_text(dis, _positions, col, entry->_display_name, 0);
else if (calcWidthCol==col || calcWidthCol==COLUMNS)
calc_width(dis, col, entry->_display_name);
++col;
// output type/class name
if (visible_cols & COL_TYPE) {
if (calcWidthCol == -1)
_out_wrkr.output_text(dis, _positions, col, entry->_type_name? entry->_type_name: TEXT(""), 0);
else if (calcWidthCol==col || calcWidthCol==COLUMNS)
calc_width(dis, col, entry->_type_name? entry->_type_name: TEXT(""));
}
++col;
// display file size
if (visible_cols & COL_SIZE) {
ULONGLONG size = ((ULONGLONG)entry->_data.nFileSizeHigh << 32) | entry->_data.nFileSizeLow;
_stprintf(buffer, TEXT("%") LONGLONGARG TEXT("d"), size);
if (calcWidthCol == -1)
_out_wrkr.output_number(dis, _positions, col, buffer);
else if (calcWidthCol==col || calcWidthCol==COLUMNS)
calc_width(dis, col, buffer); ///@todo not in every case time enough
}
++col;
// display file date
if (visible_cols & (COL_DATE|COL_TIME)) {
format_date(&entry->_data.ftCreationTime, buffer, visible_cols);
if (calcWidthCol == -1)
_out_wrkr.output_text(dis, _positions, col, buffer, 0);
else if (calcWidthCol==col || calcWidthCol==COLUMNS)
calc_width(dis, col, buffer);
++col;
format_date(&entry->_data.ftLastAccessTime, buffer, visible_cols);
if (calcWidthCol == -1)
_out_wrkr.output_text(dis,_positions, col, buffer, 0);
else if (calcWidthCol==col || calcWidthCol==COLUMNS)
calc_width(dis, col, buffer);
++col;
format_date(&entry->_data.ftLastWriteTime, buffer, visible_cols);
if (calcWidthCol == -1)
_out_wrkr.output_text(dis, _positions, col, buffer, 0);
else if (calcWidthCol==col || calcWidthCol==COLUMNS)
calc_width(dis, col, buffer);
++col;
} else
col += 3;
if (entry->_bhfi_valid) {
ULONGLONG index = ((ULONGLONG)entry->_bhfi.nFileIndexHigh << 32) | entry->_bhfi.nFileIndexLow;
if (visible_cols & COL_INDEX) {
_stprintf(buffer, TEXT("%") LONGLONGARG TEXT("X"), index);
if (calcWidthCol == -1)
_out_wrkr.output_text(dis, _positions, col, buffer, DT_RIGHT);
else if (calcWidthCol==col || calcWidthCol==COLUMNS)
calc_width(dis, col, buffer);
++col;
}
if (visible_cols & COL_LINKS) {
wsprintf(buffer, TEXT("%d"), entry->_bhfi.nNumberOfLinks);
if (calcWidthCol == -1)
_out_wrkr.output_text(dis, _positions, col, buffer, DT_RIGHT);
else if (calcWidthCol==col || calcWidthCol==COLUMNS)
calc_width(dis, col, buffer);
++col;
}
} else
col += 2;
// show file attributes
if (visible_cols & COL_ATTRIBUTES) {
lstrcpy(buffer, TEXT(" \t \t \t \t \t \t \t \t \t \t \t \t \t \t "));
if (attrs & FILE_ATTRIBUTE_NORMAL) buffer[ 0] = 'N';
else {
if (attrs & FILE_ATTRIBUTE_READONLY) buffer[ 2] = 'R';
if (attrs & FILE_ATTRIBUTE_HIDDEN) buffer[ 4] = 'H';
if (attrs & FILE_ATTRIBUTE_SYSTEM) buffer[ 6] = 'S';
if (attrs & FILE_ATTRIBUTE_ARCHIVE) buffer[ 8] = 'A';
if (attrs & FILE_ATTRIBUTE_COMPRESSED) buffer[10] = 'C';
if (attrs & FILE_ATTRIBUTE_DIRECTORY) buffer[12] = 'D';
if (attrs & FILE_ATTRIBUTE_ENCRYPTED) buffer[14] = 'E';
if (attrs & FILE_ATTRIBUTE_TEMPORARY) buffer[16] = 'T';
if (attrs & FILE_ATTRIBUTE_SPARSE_FILE) buffer[18] = 'P';
if (attrs & FILE_ATTRIBUTE_REPARSE_POINT) buffer[20] = 'Q';
if (attrs & FILE_ATTRIBUTE_OFFLINE) buffer[22] = 'O';
if (attrs & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) buffer[24] = 'X';
if (attrs & ATTRIBUTE_EXECUTABLE) buffer[26] = 'x';
if (attrs & ATTRIBUTE_SYMBOLIC_LINK) buffer[28] = 'L';
}
if (calcWidthCol == -1)
_out_wrkr.output_tabbed_text(dis, _positions, col, buffer);
else if (calcWidthCol==col || calcWidthCol==COLUMNS)
calc_tabbed_width(dis, col, buffer);
}
++col;
/*TODO
if (flags.security) {
DWORD rights = get_access_mask();
tcscpy(buffer, TEXT(" \t \t \t \t \t \t \t \t \t \t \t "));
if (rights & FILE_READ_DATA) buffer[ 0] = 'R';
if (rights & FILE_WRITE_DATA) buffer[ 2] = 'W';
if (rights & FILE_APPEND_DATA) buffer[ 4] = 'A';
if (rights & FILE_READ_EA) {buffer[6] = 'entry'; buffer[ 7] = 'R';}
if (rights & FILE_WRITE_EA) {buffer[9] = 'entry'; buffer[10] = 'W';}
if (rights & FILE_EXECUTE) buffer[12] = 'X';
if (rights & FILE_DELETE_CHILD) buffer[14] = 'D';
if (rights & FILE_READ_ATTRIBUTES) {buffer[16] = 'a'; buffer[17] = 'R';}
if (rights & FILE_WRITE_ATTRIBUTES) {buffer[19] = 'a'; buffer[20] = 'W';}
if (rights & WRITE_DAC) buffer[22] = 'C';
if (rights & WRITE_OWNER) buffer[24] = 'O';
if (rights & SYNCHRONIZE) buffer[26] = 'S';
output_text(dis, col++, buffer, DT_LEFT, 3, psize);
}
if (flags.description) {
get_description(buffer);
output_text(dis, col++, buffer, 0, psize);
}
*/
++col;
// output content / symbolic link target / comment
if (visible_cols & COL_CONTENT) {
if (calcWidthCol == -1)
_out_wrkr.output_text(dis, _positions, col, entry->_content? entry->_content: TEXT(""), 0);
else if (calcWidthCol==col || calcWidthCol==COLUMNS)
calc_width(dis, col, entry->_content? entry->_content: TEXT(""));
}
}
void Pane::calc_width(LPDRAWITEMSTRUCT dis, int col, LPCTSTR str)
{
RECT rt = {0, 0, 0, 0};
DrawText(dis->hDC, (LPTSTR)str, -1, &rt, DT_CALCRECT|DT_SINGLELINE|DT_NOPREFIX);
if (rt.right > _widths[col])
_widths[col] = rt.right;
}
void Pane::calc_tabbed_width(LPDRAWITEMSTRUCT dis, int col, LPCTSTR str)
{
RECT rt = {0, 0, 0, 0};
/* DRAWTEXTPARAMS dtp = {sizeof(DRAWTEXTPARAMS), 2};
DrawTextEx(dis->hDC, (LPTSTR)str, -1, &rt, DT_CALCRECT|DT_SINGLELINE|DT_NOPREFIX|DT_EXPANDTABS|DT_TABSTOP, &dtp);*/
DrawText(dis->hDC, (LPTSTR)str, -1, &rt, DT_CALCRECT|DT_SINGLELINE|DT_EXPANDTABS|DT_TABSTOP|(2<<8));
//FIXME rt (0,0) ???
if (rt.right > _widths[col])
_widths[col] = rt.right;
}
// insert listbox entries after index idx
void Pane::insert_entries(Entry* dir, int idx)
{
Entry* entry = dir;
if (!entry)
return;
SendMessage(_hwnd, WM_SETREDRAW, FALSE, 0); //ShowWindow(_hwnd, SW_HIDE);
for(; entry; entry=entry->_next) {
#ifndef _LEFT_FILES
if (_treePane &&
!(entry->_data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) && // not a directory?
!entry->_down) // not a file with NTFS sub-streams?
continue;
#endif
// don't display entries "." and ".." in the left pane
if (_treePane && (entry->_data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
&& entry->_data.cFileName[0]==TEXT('.'))
if (entry->_data.cFileName[1]==TEXT('\0') ||
(entry->_data.cFileName[1]==TEXT('.') && entry->_data.cFileName[2]==TEXT('\0')))
continue;
if (idx != -1)
++idx;
ListBox_InsertItemData(_hwnd, idx, entry);
if (_treePane && entry->_expanded)
insert_entries(entry->_down, idx);
}
SendMessage(_hwnd, WM_SETREDRAW, TRUE, 0); //ShowWindow(_hwnd, SW_SHOW);
}
void Pane::set_header()
{
HD_ITEM item;
int scroll_pos = GetScrollPos(_hwnd, SB_HORZ);
int i=0, x=0;
item.mask = HDI_WIDTH;
item.cxy = 0;
for(; x+_widths[i]<scroll_pos && i<COLUMNS; i++) {
x += _widths[i];
Header_SetItem(_hwndHeader, i, &item);
}
if (i < COLUMNS) {
x += _widths[i];
item.cxy = x - scroll_pos;
Header_SetItem(_hwndHeader, i++, &item);
for(; i<COLUMNS; i++) {
item.cxy = _widths[i];
x += _widths[i];
Header_SetItem(_hwndHeader, i, &item);
}
}
}
// calculate one prefered column width
void Pane::calc_single_width(int col)
{
HFONT hfontOld;
int x, cx;
int cnt;
HDC hdc;
int entries = ListBox_GetCount(_hwnd);
_widths[col] = 0;
hdc = GetDC(_hwnd);
hfontOld = SelectFont(hdc, _out_wrkr._hfont);
for(cnt=0; cnt<entries; cnt++) {
Entry* entry = (Entry*) ListBox_GetItemData(_hwnd, cnt);
DRAWITEMSTRUCT dis;
dis.CtlType = 0;
dis.CtlID = 0;
dis.itemID = 0;
dis.itemAction = 0;
dis.itemState = 0;
dis.hwndItem = _hwnd;
dis.hDC = hdc;
dis.rcItem.left = 0;
dis.rcItem.top = 0;
dis.rcItem.right = 0;
dis.rcItem.bottom = 0;
/*dis.itemData = 0; */
draw_item(&dis, entry, col);
}
SelectObject(hdc, hfontOld);
ReleaseDC(_hwnd, hdc);
cx = _widths[col];
if (cx) {
cx += 3*_out_wrkr._spaceSize.cx;
if (cx < IMAGE_WIDTH)
cx = IMAGE_WIDTH;
}
_widths[col] = cx;
x = _positions[col] + cx;
for(; col<COLUMNS; ) {
_positions[++col] = x;
x += _widths[col];
}
ListBox_SetHorizontalExtent(_hwnd, x);
}
int Pane::Notify(int id, NMHDR* pnmh)
{
switch(pnmh->code) {
case HDN_TRACK:
case HDN_ENDTRACK: {
HD_NOTIFY* phdn = (HD_NOTIFY*) pnmh;
int idx = phdn->iItem;
int dx = phdn->pitem->cxy - _widths[idx];
int i;
ClientRect clnt(_hwnd);
// move immediate to simulate HDS_FULLDRAG (for now [04/2000] not realy needed with WINELIB)
Header_SetItem(_hwndHeader, idx, phdn->pitem);
_widths[idx] += dx;
for(i=idx; ++i<=COLUMNS; )
_positions[i] += dx;
{
int scroll_pos = GetScrollPos(_hwnd, SB_HORZ);
RECT rt_scr;
RECT rt_clip;
rt_scr.left = _positions[idx+1]-scroll_pos;
rt_scr.top = 0;
rt_scr.right = clnt.right;
rt_scr.bottom = clnt.bottom;
rt_clip.left = _positions[idx]-scroll_pos;
rt_clip.top = 0;
rt_clip.right = clnt.right;
rt_clip.bottom = clnt.bottom;
if (rt_scr.left < 0) rt_scr.left = 0;
if (rt_clip.left < 0) rt_clip.left = 0;
ScrollWindowEx(_hwnd, dx, 0, &rt_scr, &rt_clip, 0, 0, SW_INVALIDATE);
rt_clip.right = _positions[idx+1];
RedrawWindow(_hwnd, &rt_clip, 0, RDW_INVALIDATE|RDW_UPDATENOW);
if (pnmh->code == HDN_ENDTRACK) {
ListBox_SetHorizontalExtent(_hwnd, _positions[COLUMNS]);
if (GetScrollPos(_hwnd, SB_HORZ) != scroll_pos)
set_header();
}
}
return 0;
}
case HDN_DIVIDERDBLCLICK: {
HD_NOTIFY* phdn = (HD_NOTIFY*) pnmh;
HD_ITEM item;
calc_single_width(phdn->iItem);
item.mask = HDI_WIDTH;
item.cxy = _widths[phdn->iItem];
Header_SetItem(_hwndHeader, phdn->iItem, &item);
InvalidateRect(_hwnd, 0, TRUE);
break;}
default:
return super::Notify(id, pnmh);
}
return 0;
}
OutputWorker::OutputWorker()
{
_hfont = CreateFont(-MulDiv(8,GetDeviceCaps(WindowCanvas(0),LOGPIXELSY),72), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, TEXT("MS Sans Serif"));
}
void OutputWorker::init_output(HWND hwnd)
{
TCHAR b[16];
WindowCanvas canvas(hwnd);
if (GetNumberFormat(LOCALE_USER_DEFAULT, 0, TEXT("1000"), 0, b, 16) > 4)
_num_sep = b[1];
else
_num_sep = TEXT('.');
FontSelection font(canvas, _hfont);
GetTextExtentPoint32(canvas, TEXT(" "), 1, &_spaceSize);
}
void OutputWorker::output_text(LPDRAWITEMSTRUCT dis, int* positions, int col, LPCTSTR str, DWORD flags)
{
int x = dis->rcItem.left;
RECT rt;
rt.left = x+positions[col]+_spaceSize.cx;
rt.top = dis->rcItem.top;
rt.right = x+positions[col+1]-_spaceSize.cx;
rt.bottom = dis->rcItem.bottom;
DrawText(dis->hDC, (LPTSTR)str, -1, &rt, DT_SINGLELINE|DT_NOPREFIX|flags);
}
void OutputWorker::output_tabbed_text(LPDRAWITEMSTRUCT dis, int* positions, int col, LPCTSTR str)
{
int x = dis->rcItem.left;
RECT rt;
rt.left = x+positions[col]+_spaceSize.cx;
rt.top = dis->rcItem.top;
rt.right = x+positions[col+1]-_spaceSize.cx;
rt.bottom = dis->rcItem.bottom;
/* DRAWTEXTPARAMS dtp = {sizeof(DRAWTEXTPARAMS), 2};
DrawTextEx(dis->hDC, (LPTSTR)str, -1, &rt, DT_SINGLELINE|DT_NOPREFIX|DT_EXPANDTABS|DT_TABSTOP, &dtp);*/
DrawText(dis->hDC, (LPTSTR)str, -1, &rt, DT_SINGLELINE|DT_EXPANDTABS|DT_TABSTOP|(2<<8));
}
void OutputWorker::output_number(LPDRAWITEMSTRUCT dis, int* positions, int col, LPCTSTR str)
{
int x = dis->rcItem.left;
RECT rt;
LPCTSTR s = str;
TCHAR b[128];
LPTSTR d = b;
int pos;
rt.left = x+positions[col]+_spaceSize.cx;
rt.top = dis->rcItem.top;
rt.right = x+positions[col+1]-_spaceSize.cx;
rt.bottom = dis->rcItem.bottom;
if (*s)
*d++ = *s++;
// insert number separator characters
pos = lstrlen(s) % 3;
while(*s)
if (pos--)
*d++ = *s++;
else {
*d++ = _num_sep;
pos = 3;
}
DrawText(dis->hDC, b, d-b, &rt, DT_RIGHT|DT_SINGLELINE|DT_NOPREFIX|DT_END_ELLIPSIS);
}
BOOL Pane::command(UINT cmd)
{
switch(cmd) {
case ID_VIEW_NAME:
if (_visible_cols) {
_visible_cols = 0;
calc_widths(true);
set_header();
InvalidateRect(_hwnd, 0, TRUE);
MenuInfo* menu_info = Frame_GetMenuInfo(GetParent(_hwnd));
if (menu_info) {
CheckMenuItem(menu_info->_hMenuView, ID_VIEW_NAME, MF_BYCOMMAND|MF_CHECKED);
CheckMenuItem(menu_info->_hMenuView, ID_VIEW_ALL_ATTRIBUTES, MF_BYCOMMAND);
CheckMenuItem(menu_info->_hMenuView, ID_VIEW_SELECTED_ATTRIBUTES, MF_BYCOMMAND);
}
}
break;
case ID_VIEW_ALL_ATTRIBUTES:
if (_visible_cols != COL_ALL) {
_visible_cols = COL_ALL;
calc_widths(true);
set_header();
InvalidateRect(_hwnd, 0, TRUE);
MenuInfo* menu_info = Frame_GetMenuInfo(GetParent(_hwnd));
if (menu_info) {
CheckMenuItem(menu_info->_hMenuView, ID_VIEW_NAME, MF_BYCOMMAND);
CheckMenuItem(menu_info->_hMenuView, ID_VIEW_ALL_ATTRIBUTES, MF_BYCOMMAND|MF_CHECKED);
CheckMenuItem(menu_info->_hMenuView, ID_VIEW_SELECTED_ATTRIBUTES, MF_BYCOMMAND);
}
}
break;
case ID_PREFERED_SIZES: {
calc_widths(true);
set_header();
InvalidateRect(_hwnd, 0, TRUE);
break;}
/*@todo more command ids... */
default:
return FALSE;
}
return TRUE;
}
MainFrame* Pane::get_frame()
{
HWND owner = GetParent(_hwnd);
return (MainFrame*)owner;
}
-109
View File
@@ -1,109 +0,0 @@
/*
* Copyright 2003 Martin Fuchs
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
//
// Explorer clone
//
// pane.h
//
// Martin Fuchs, 23.07.2003
//
#define IDW_TREE_LEFT 3
#define IDW_TREE_RIGHT 6
#define IDW_HEADER_LEFT 2
#define IDW_HEADER_RIGHT 5
enum COLUMN_FLAGS {
COL_TYPE = 0x0001,
COL_SIZE = 0x0002,
COL_DATE = 0x0004,
COL_TIME = 0x0008,
COL_ATTRIBUTES = 0x0010,
COL_DOSNAMES = 0x0020,
COL_INDEX = 0x0040,
COL_LINKS = 0x0080,
COL_CONTENT = 0x0100,
COL_ALL = COL_TYPE|COL_SIZE|COL_DATE|COL_TIME|COL_ATTRIBUTES|COL_DOSNAMES|COL_INDEX|COL_LINKS|COL_CONTENT
};
/// Worker for drawing contents of file lists in child pane
struct OutputWorker
{
OutputWorker();
void init_output(HWND hwnd);
void output_text(LPDRAWITEMSTRUCT dis, int* positions, int col, LPCTSTR str, DWORD flags);
void output_tabbed_text(LPDRAWITEMSTRUCT dis, int* positions, int col, LPCTSTR str);
void output_number(LPDRAWITEMSTRUCT dis, int* positions, int col, LPCTSTR str);
SIZE _spaceSize;
TCHAR _num_sep;
HFONT _hfont;
};
/// child window pane for displaying file lists
struct Pane : public SubclassedWindow
{
typedef SubclassedWindow super;
Pane(HWND hparent, int id, int id_header, Entry* rool, bool treePane, int visible_cols);
#define COLUMNS 12
int _widths[COLUMNS];
int _positions[COLUMNS+1];
WindowHandle _hwndHeader;
Entry* _root;
Entry* _cur;
COLORREF _clrCompressed;
int _visible_cols;
bool _treePane;
void init();
void set_header();
bool create_header(HWND parent, int id);
bool calc_widths(bool anyway);
void calc_single_width(int col);
void draw_item(LPDRAWITEMSTRUCT dis, Entry* entry, int calcWidthCol=-1);
void insert_entries(Entry* dir, int idx);
BOOL command(UINT cmd);
int Notify(int id, NMHDR* pnmh);
protected:
LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
void calc_width(LPDRAWITEMSTRUCT dis, int col, LPCTSTR str);
void calc_tabbed_width(LPDRAWITEMSTRUCT dis, int col, LPCTSTR str);
MainFrame* get_frame();
protected:
HIMAGELIST _himl;
OutputWorker _out_wrkr;
};
@@ -48,14 +48,22 @@ static LPARAM TreeView_GetItemData(HWND hwndTreeView, HTREEITEM hItem)
}
ShellBrowserChild::ShellBrowserChild(HWND hwnd, const ShellChildWndInfo& info)
: super(hwnd, info),
_create_info(info)
ShellBrowserChild::ShellBrowserChild(HWND hwnd, HWND left_hwnd, WindowHandle& right_hwnd, ShellPathInfo& create_info)
: _hwnd(hwnd),
_left_hwnd(left_hwnd),
_right_hwnd(right_hwnd),
_create_info(create_info)
{
_pShellView = NULL;
_pDropTarget = NULL;
_himlSmall = 0;
_last_sel = 0;
// SDI integration
_split_pos = DEFAULT_SPLIT_POS;
_last_split = DEFAULT_SPLIT_POS;
Init(hwnd);
}
ShellBrowserChild::~ShellBrowserChild()
@@ -67,17 +75,19 @@ ShellBrowserChild::~ShellBrowserChild()
_pDropTarget->Release();
_pDropTarget = NULL;
}
if (_right_hwnd) {
DestroyWindow(_right_hwnd);
_right_hwnd = 0;
}
}
LRESULT ShellBrowserChild::Init(LPCREATESTRUCT pcs)
LRESULT ShellBrowserChild::Init(HWND hWndFrame)
{
CONTEXT("ShellBrowserChild::Init()");
if (super::Init(pcs))
return 1;
_hWndFrame = GetParent(pcs->hwndParent);
_hWndFrame = hWndFrame;
ClientRect rect(_hwnd);
@@ -87,19 +97,13 @@ LRESULT ShellBrowserChild::Init(LPCREATESTRUCT pcs)
// _himlLarge = (HIMAGELIST)SHGetFileInfo(TEXT("C:\\"), 0, &sfi, sizeof(SHFILEINFO), SHGFI_SYSICONINDEX|SHGFI_LARGEICON);
// create explorer treeview
if (_create_info._open_mode & OWM_EXPLORE)
_left_hwnd = CreateWindowEx(0, WC_TREEVIEW, NULL,
WS_CHILD|WS_TABSTOP|WS_VISIBLE|WS_CHILD|TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_NOTOOLTIPS|TVS_SHOWSELALWAYS,
0, rect.top, _split_pos-SPLIT_WIDTH/2, rect.bottom-rect.top,
_hwnd, (HMENU)IDC_FILETREE, g_Globals._hInstance, 0);
if (_left_hwnd) {
InitializeTree();
InitDragDrop();
} else
UpdateFolderView(_create_info._shell_path.get_folder());
}
UpdateFolderView(_create_info._shell_path.get_folder());
return 0;
}
@@ -379,7 +383,7 @@ void ShellBrowserChild::UpdateFolderView(IShellFolder* folder)
pLastShellView->GetCurrentInfo(&fs);
else {
fs.ViewMode = _create_info._open_mode&OWM_DETAILS? FVM_DETAILS: FVM_ICON;
fs.fFlags = FWF_NOCLIENTEDGE|FWF_BESTFITWINDOW;
fs.fFlags = FWF_BESTFITWINDOW;
}
HRESULT hr = folder->CreateViewObject(_hwnd, IID_IShellView, (void**)&_pShellView);
@@ -398,36 +402,127 @@ void ShellBrowserChild::UpdateFolderView(IShellFolder* folder)
pLastShellView->DestroyViewWindow();
pLastShellView->Release();
ClientRect clnt(_hwnd);
resize_children(clnt.right, clnt.bottom);
resize_children();
}
_pShellView->UIActivate(SVUIA_ACTIVATE_NOFOCUS);
}
void ShellBrowserChild::resize_children()
{
RECT rect = _clnt_rect;
HDWP hdwp = BeginDeferWindowPos(2);
int cx = rect.left;
if (_left_hwnd) {
cx = _split_pos + SPLIT_WIDTH/2;
hdwp = DeferWindowPos(hdwp, _left_hwnd, 0, rect.left, rect.top, _split_pos-SPLIT_WIDTH/2-rect.left, rect.bottom-rect.top, SWP_NOZORDER|SWP_NOACTIVATE);
} else {
_split_pos = 0;
cx = 0;
}
if (_right_hwnd)
hdwp = DeferWindowPos(hdwp, _right_hwnd, 0, rect.left+cx+1, rect.top, rect.right-cx, rect.bottom-rect.top, SWP_NOZORDER|SWP_NOACTIVATE);
EndDeferWindowPos(hdwp);
}
LRESULT ShellBrowserChild::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
{
switch(nmsg) {
case WM_GETISHELLBROWSER: // for Registry Explorer Plugin
return (LRESULT)static_cast<IShellBrowser*>(this);
case PM_GET_SHELLBROWSER_PTR:
return (LRESULT)this;
case PM_DISPATCH_COMMAND: {
switch(LOWORD(wparam)) {
case ID_WINDOW_NEW: {CONTEXT("ShellBrowserChild PM_DISPATCH_COMMAND ID_WINDOW_NEW");
ShellBrowserChild::create(_create_info);
break;}
// SDI integration:
default:
return FALSE;
case WM_PAINT: {
PaintCanvas canvas(_hwnd);
ClientRect rt(_hwnd);
rt.left = _split_pos-SPLIT_WIDTH/2;
rt.right = _split_pos+SPLIT_WIDTH/2+1;
if (_right_hwnd) {
WindowRect right_rect(_right_hwnd);
ScreenToClient(_hwnd, &right_rect);
rt.top = right_rect.top;
rt.bottom = right_rect.bottom;
}
return TRUE;}
default:
return super::WndProc(nmsg, wparam, lparam);
HBRUSH lastBrush = SelectBrush(canvas, GetStockBrush(COLOR_SPLITBAR));
Rectangle(canvas, rt.left, rt.top-1, rt.right, rt.bottom+1);
SelectObject(canvas, lastBrush);
break;}
case WM_SETCURSOR:
if (LOWORD(lparam) == HTCLIENT) {
POINT pt;
GetCursorPos(&pt);
ScreenToClient(_hwnd, &pt);
if (pt.x>=_split_pos-SPLIT_WIDTH/2 && pt.x<_split_pos+SPLIT_WIDTH/2+1) {
SetCursor(LoadCursor(0, IDC_SIZEWE));
return TRUE;
}
}
goto def;
case WM_LBUTTONDOWN: {
int x = GET_X_LPARAM(lparam);
ClientRect rt(_hwnd);
if (x>=_split_pos-SPLIT_WIDTH/2 && x<_split_pos+SPLIT_WIDTH/2+1) {
_last_split = _split_pos;
SetCapture(_hwnd);
}
break;}
case WM_LBUTTONUP:
if (GetCapture() == _hwnd)
ReleaseCapture();
break;
case WM_KEYDOWN:
if (wparam == VK_ESCAPE)
if (GetCapture() == _hwnd) {
_split_pos = _last_split;
resize_children();
_last_split = -1;
ReleaseCapture();
SetCursor(LoadCursor(0, IDC_ARROW));
}
break;
case WM_MOUSEMOVE:
if (GetCapture() == _hwnd) {
int x = LOWORD(lparam);
ClientRect rt(_hwnd);
if (x>=0 && x<rt.right) {
_split_pos = x;
resize_children();
rt.left = x-SPLIT_WIDTH/2;
rt.right = x+SPLIT_WIDTH/2+1;
InvalidateRect(_hwnd, &rt, FALSE);
UpdateWindow(_left_hwnd);
UpdateWindow(_hwnd);
UpdateWindow(_right_hwnd);
}
}
break;
default: def:
return DefWindowProc(_hwnd, nmsg, wparam, lparam);
}
return 0;
@@ -440,7 +535,6 @@ int ShellBrowserChild::Notify(int id, NMHDR* pnmh)
case TVN_ITEMEXPANDING: OnTreeItemExpanding(id, (LPNMTREEVIEW)pnmh); break;
case TVN_SELCHANGED: OnTreeItemSelected(id, (LPNMTREEVIEW)pnmh); break;
case NM_RCLICK: OnTreeItemRClick(id, pnmh); break;
default: return super::Notify(id, pnmh);
}
return 0;
@@ -29,28 +29,24 @@
#include "../utility/shellbrowserimpl.h"
/// Implementation of IShellBrowserImpl interface in explorer child windows
struct ShellBrowserChild : public ChildWindow, public IShellBrowserImpl
/// information structure to hold current shell folder information
struct ShellPathInfo
{
typedef ChildWindow super;
ShellPathInfo(int mode=0) : _open_mode(mode) {}
ShellBrowserChild(HWND hwnd, const ShellChildWndInfo& info);
ShellPath _shell_path;
ShellPath _root_shell_path;
int _open_mode; //OPEN_WINDOW_MODE
};
/// Implementation of IShellBrowserImpl interface in explorer child windows
struct ShellBrowserChild : public IShellBrowserImpl
{
ShellBrowserChild(HWND hwnd, HWND left_hwnd, WindowHandle& right_hwnd, ShellPathInfo& create_info);
~ShellBrowserChild();
static ShellBrowserChild* create(const FileChildWndInfo& info)
{
#ifndef _NO_MDI
ChildWindow* child = ChildWindow::create(info, info._pos.rcNormalPosition,
WINDOW_CREATOR_INFO(ShellBrowserChild,ShellChildWndInfo), CLASSNAME_CHILDWND, NULL);
#else
///@todo SDI implementation
#endif
ShowWindow(*child, info._pos.showCmd);
return static_cast<ShellBrowserChild*>(child);
}
//IOleWindow
virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND* lphwnd)
{
@@ -104,10 +100,14 @@ struct ShellBrowserChild : public ChildWindow, public IShellBrowserImpl
const Root& get_root() const {return _root;}
protected:
Root _root;
HWND _hwnd;
HWND _left_hwnd;
WindowHandle& _right_hwnd;
ShellPathInfo& _create_info;
Root _root;
WindowHandle _hWndFrame;
ShellChildWndInfo _create_info;
ShellFolder _folder;
IShellView* _pShellView; // current hosted shellview
@@ -117,11 +117,12 @@ protected:
HTREEITEM _last_sel;
public:
LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
int Notify(int id, NMHDR* pnmh);
LRESULT Init(LPCREATESTRUCT);
void InitializeTree(/*const FileChildWndInfo& info*/);
LRESULT Init(HWND hWndFrame);
void InitializeTree();
int InsertSubitems(HTREEITEM hParentItem, Entry* entry, IShellFolder* pParentFolder);
bool InitDragDrop();
@@ -135,4 +136,12 @@ protected:
void UpdateFolderView(IShellFolder* folder);
void Tree_DoItemMenu(HWND hwndTreeView, HTREEITEM hItem, LPPOINT pptScreen);
bool expand_folder(ShellDirectory* entry);
// SDI integration
public:
int _split_pos;
int _last_split;
RECT _clnt_rect;
void resize_children();
};
@@ -392,20 +392,6 @@ inline void ScreenToClient(HWND hwnd, RECT* prect)
{::ScreenToClient(hwnd,(LPPOINT)&prect->left); ::ScreenToClient(hwnd,(LPPOINT)&prect->right);}
/// structure containing information about full screen display of the frame window
struct FullScreenParameters
{
FullScreenParameters()
: _mode(FALSE)
{
}
BOOL _mode;
RECT _orgPos;
BOOL _wasZoomed;
};
// drawing utilities
/// PaintCanvas is a encapsulation of device contexts managed by BeginPaint()/EndPaint().
@@ -120,68 +120,6 @@ HWND Window::Create(CREATORFUNC_INFO creator, const void* info, DWORD dwExStyle,
}
Window* Window::create_mdi_child(const ChildWndInfo& info, const MDICREATESTRUCT& mcs, CREATORFUNC_INFO creator)
{
Lock lock(GetStaticWindowData()._create_crit_sect); // protect access to s_window_creator and s_new_info
s_window_creator = (CREATORFUNC) creator;
s_new_info = &info;
s_hcbtHook = SetWindowsHookEx(WH_CBT, MDICBTHookProc, 0, GetCurrentThreadId());
HWND hwnd = (HWND) SendMessage(info._hmdiclient, WM_MDICREATE, 0, (LPARAM)&mcs);
UnhookWindowsHookEx(s_hcbtHook);
Window* child = get_window(hwnd);
s_new_info = NULL;
if (child && (!hwnd || !child->_hwnd))
child = NULL;
return child;
}
LRESULT CALLBACK Window::MDICBTHookProc(int code, WPARAM wparam, LPARAM lparam)
{
if (code == HCBT_CREATEWND) {
HWND hwnd = (HWND)wparam;
// create Window controller and associate it with the window handle
Window* child = get_window(hwnd);
if (!child)
child = create_controller(hwnd);
}
return CallNextHookEx(s_hcbtHook, code, wparam, lparam);
}
/*
Window* Window::create_property_sheet(PropertySheetDialog* ppsd, CREATORFUNC creator, const void* info)
{
Lock lock(GetStaticWindowData()._create_crit_sect); // protect access to s_window_creator and s_new_info
s_window_creator = creator;
s_new_info = info;
s_hcbtHook = SetWindowsHookEx(WH_CBT, PropSheetCBTHookProc, 0, GetCurrentThreadId());
HWND hwnd = (HWND) PropertySheet(ppsd);
UnhookWindowsHookEx(s_hcbtHook);
Window* child = get_window(hwnd);
s_new_info = NULL;
if (child && (!hwnd || !child->_hwnd))
child = NULL;
return child;
}
*/
LRESULT CALLBACK Window::PropSheetCBTHookProc(int code, WPARAM wparam, LPARAM lparam)
{
if (code == HCBT_CREATEWND) {
@@ -368,164 +306,6 @@ int SubclassedWindow::Notify(int id, NMHDR* pnmh)
}
ChildWindow::ChildWindow(HWND hwnd, const ChildWndInfo& info)
: super(hwnd),
_hwndFrame(GetParent(info._hmdiclient))
{
_focus_pane = 0;
_split_pos = DEFAULT_SPLIT_POS;
_last_split = DEFAULT_SPLIT_POS;
}
ChildWindow* ChildWindow::create(const ChildWndInfo& info, const RECT& rect, CREATORFUNC_INFO creator,
LPCTSTR classname, LPCTSTR title)
{
MDICREATESTRUCT mcs;
mcs.szClass = classname;
mcs.szTitle = title;
mcs.hOwner = g_Globals._hInstance;
mcs.x = rect.left,
mcs.y = rect.top;
mcs.cx = rect.right - rect.left;
mcs.cy = rect.bottom - rect.top;
mcs.style = 0;
mcs.lParam = 0;
return static_cast<ChildWindow*>(create_mdi_child(info, mcs, creator));
}
LRESULT ChildWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
{
switch(nmsg) {
case WM_PAINT: {
PaintCanvas canvas(_hwnd);
ClientRect rt(_hwnd);
rt.left = _split_pos-SPLIT_WIDTH/2;
rt.right = _split_pos+SPLIT_WIDTH/2+1;
HBRUSH lastBrush = SelectBrush(canvas, GetStockBrush(COLOR_SPLITBAR));
Rectangle(canvas, rt.left, rt.top-1, rt.right, rt.bottom+1);
SelectObject(canvas, lastBrush);
break;}
case WM_SETCURSOR:
if (LOWORD(lparam) == HTCLIENT) {
POINT pt;
GetCursorPos(&pt);
ScreenToClient(_hwnd, &pt);
if (pt.x>=_split_pos-SPLIT_WIDTH/2 && pt.x<_split_pos+SPLIT_WIDTH/2+1) {
SetCursor(LoadCursor(0, IDC_SIZEWE));
return TRUE;
}
}
goto def;
case WM_SIZE:
if (wparam != SIZE_MINIMIZED)
resize_children(LOWORD(lparam), HIWORD(lparam));
goto def;
case WM_GETMINMAXINFO:
DefMDIChildProc(_hwnd, nmsg, wparam, lparam);
{LPMINMAXINFO lpmmi = (LPMINMAXINFO)lparam;
lpmmi->ptMaxTrackSize.x <<= 1; // 2*GetSystemMetrics(SM_CXSCREEN) / SM_CXVIRTUALSCREEN
lpmmi->ptMaxTrackSize.y <<= 1; // 2*GetSystemMetrics(SM_CYSCREEN) / SM_CYVIRTUALSCREEN
break;}
case WM_LBUTTONDOWN: {
int x = GET_X_LPARAM(lparam);
ClientRect rt(_hwnd);
if (x>=_split_pos-SPLIT_WIDTH/2 && x<_split_pos+SPLIT_WIDTH/2+1) {
_last_split = _split_pos;
SetCapture(_hwnd);
}
break;}
case WM_LBUTTONUP:
if (GetCapture() == _hwnd)
ReleaseCapture();
break;
case WM_KEYDOWN:
if (wparam == VK_ESCAPE)
if (GetCapture() == _hwnd) {
_split_pos = _last_split;
ClientRect rt(_hwnd);
resize_children(rt.right, rt.bottom);
_last_split = -1;
ReleaseCapture();
SetCursor(LoadCursor(0, IDC_ARROW));
}
break;
case WM_MOUSEMOVE:
if (GetCapture() == _hwnd) {
int x = LOWORD(lparam);
ClientRect rt(_hwnd);
if (x>=0 && x<rt.right) {
_split_pos = x;
resize_children(rt.right, rt.bottom);
rt.left = x-SPLIT_WIDTH/2;
rt.right = x+SPLIT_WIDTH/2+1;
InvalidateRect(_hwnd, &rt, FALSE);
UpdateWindow(_left_hwnd);
UpdateWindow(_hwnd);
UpdateWindow(_right_hwnd);
}
}
break;
case PM_DISPATCH_COMMAND:
return FALSE;
case WM_MDIACTIVATE:
if ((HWND)lparam == _hwnd)
SendMessage(_hwndFrame, PM_SETSTATUSTEXT, 0, (LPARAM)_statusText.c_str());
break;
default: def:
return DefMDIChildProc(_hwnd, nmsg, wparam, lparam);
}
return 0;
}
void ChildWindow::resize_children(int cx, int cy)
{
HDWP hdwp = BeginDeferWindowPos(4);
RECT rt;
rt.left = 0;
rt.top = 0;
rt.right = cx;
rt.bottom = cy;
if (_left_hwnd) {
cx = _split_pos + SPLIT_WIDTH/2;
hdwp = DeferWindowPos(hdwp, _left_hwnd, 0, rt.left, rt.top, _split_pos-SPLIT_WIDTH/2-rt.left, rt.bottom-rt.top, SWP_NOZORDER|SWP_NOACTIVATE);
} else {
_split_pos = 0;
cx = 0;
}
hdwp = DeferWindowPos(hdwp, _right_hwnd, 0, rt.left+cx+1, rt.top, rt.right-cx, rt.bottom-rt.top, SWP_NOZORDER|SWP_NOACTIVATE);
EndDeferWindowPos(hdwp);
}
WindowSet Window::s_pretranslate_windows;
void Window::register_pretranslate(HWND hwnd)
@@ -40,16 +40,6 @@ typedef set<HWND> WindowSet;
*/
/// information structure for creation of a MDI child window
struct ChildWndInfo
{
ChildWndInfo(HWND hmdiclient)
: _hmdiclient(hmdiclient) {}
HWND _hmdiclient;
};
/**
Class Window is the base class for several C++ window wrapper classes.
Window objects are allocated from the heap. They are automatically freed
@@ -76,9 +66,6 @@ struct Window : public WindowHandle
DWORD dwStyle, int x, int y, int w, int h,
HWND hwndParent=0, HMENU hMenu=0/*, LPVOID lpParam=0*/);
static Window* create_mdi_child(const ChildWndInfo& info, const MDICREATESTRUCT& mcs, CREATORFUNC_INFO creator);
// static Window* create_property_sheet(struct PropertySheetDialog* ppsd, CREATORFUNC creator, const void* info);
static LRESULT CALLBACK WindowWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam);
static INT_PTR CALLBACK DialogProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam);
@@ -129,9 +116,7 @@ protected:
static StaticWindowData& GetStaticWindowData();
// MDI child creation
static HHOOK s_hcbtHook;
static LRESULT CALLBACK MDICBTHookProc(int code, WPARAM wparam, LPARAM lparam);
static LRESULT CALLBACK PropSheetCBTHookProc(int code, WPARAM wparam, LPARAM lparam);
static WindowSet s_pretranslate_windows;
@@ -256,7 +241,6 @@ struct IconWindowClass : public WindowClass
// private message constants
#define PM_DISPATCH_COMMAND (WM_APP+0x00)
#define PM_TRANSLATE_MSG (WM_APP+0x01)
@@ -265,7 +249,7 @@ struct IconWindowClass : public WindowClass
#define COLOR_SPLITBAR LTGRAY_BRUSH
/// menu info structure for MDI child windows
/// menu info structure
struct MenuInfo
{
HMENU _hMenuView;
@@ -277,41 +261,6 @@ struct MenuInfo
#define Frame_GetMenuInfo(hwnd) ((MenuInfo*)SNDMSG(hwnd, PM_FRM_GET_MENUINFO, 0, 0))
/**
Class ChildWindow represents MDI child windows.
It is used with class MainFrame.
*/
struct ChildWindow : public Window
{
typedef Window super;
ChildWindow(HWND hwnd, const ChildWndInfo& info);
static ChildWindow* create(const ChildWndInfo& info, const RECT& rect, CREATORFUNC_INFO creator,
LPCTSTR classname, LPCTSTR title=NULL);
protected:
LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam);
virtual void resize_children(int cx, int cy);
protected:
MenuInfo*_menu_info;
WindowHandle _left_hwnd;
WindowHandle _right_hwnd;
int _focus_pane; // 0: left 1: right
int _split_pos;
int _last_split;
HWND _hwndFrame;
String _statusText;
};
#define PM_SETSTATUSTEXT (WM_APP+0x1D)
/**
PreTranslateWindow is used to register windows to be called by Window::pretranslate_msg().
This way you get PM_TRANSLATE_MSG messages before the message loop dispatches messages.