📄 openfile_win32.c
字号:
/*****************************************************************************
*
* This program is free software ; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: openfile_win32.c 531 2006-01-04 12:56:13Z picard $
*
* The Core Pocket Media Player
* Copyright (c) 2004-2005 Gabor Kovacs
*
****************************************************************************/
#include "../../common/common.h"
#include "../win.h"
#include "openfile_win32.h"
#include "interface.h"
#include "resource.h"
#if defined(TARGET_WINCE) || defined(TARGET_WIN32)
#ifndef STRICT
#define STRICT
#endif
#include <windows.h>
#if _MSC_VER > 1000
#pragma warning(disable : 4201)
#endif
#include <commctrl.h>
#define OPENFILE_TYPES 50000
#define EM_SETSYMBOLS 0x00DF
#define SYMBOLS T("./:-1\\~?#")
#define MAXHISTORY 20
#define IMG_FILE 0
#define IMG_DIR 1
#define IMG_PLAYLIST 2
#define IMG_VIDEO 3
#define IMG_AUDIO 4
#define IMG_DIRUP 5
typedef struct openitem
{
int Image;
tchar_t FileName[MAXPATH];
tchar_t Name[MAXPATH];
tchar_t Ext[MAXPATH];
filepos_t Size;
int64_t Date;
bool_t DisplayName;
} openitem;
typedef struct openfile
{
win Win;
HWND WndList;
HWND WndURL;
HWND WndGo;
int* CurrentFileType;
int FileType;
int FileTypeSingle;
int FileTypeSave;
int SortCol;
int Class;
int Flags;
int Top;
int TypesMenu;
bool_t SortDir;
bool_t Multiple;
bool_t SelectDir;
bool_t OwnSelect;
bool_t NextFocus;
bool_t OnlyName;
bool_t OnlyNameState;
bool_t KeyClick;
int InUpdate;
int LastClick;
int DlgWidth[4];
tchar_t Path[MAXPATH];
tchar_t Base[MAXPATH];
tchar_t Exts[1024];
tchar_t Last[MAXPATH];
tchar_t SaveName[MAXPATH];
array Types;
int HistoryCount;
tchar_t* History[MAXHISTORY];
} openfile;
static const datatable Params[] =
{
{ OPENFILE_FLAGS, TYPE_INT, DF_HIDDEN },
{ OPENFILE_CLASS, TYPE_INT, DF_HIDDEN },
{ OPENFILE_MULTIPLE, TYPE_BOOL, DF_SETUP|DF_HIDDEN },
{ OPENFILE_FILETYPE, TYPE_INT, DF_SETUP|DF_HIDDEN },
{ OPENFILE_FILETYPE_SINGLE, TYPE_INT, DF_SETUP|DF_HIDDEN },
{ OPENFILE_FILETYPE_SAVE,TYPE_INT, DF_SETUP|DF_HIDDEN },
{ OPENFILE_PATH, TYPE_STRING, DF_SETUP|DF_HIDDEN },
{ OPENFILE_SORTCOL, TYPE_INT, DF_SETUP|DF_HIDDEN },
{ OPENFILE_SORTDIR, TYPE_BOOL, DF_SETUP|DF_HIDDEN },
{ OPENFILE_WIDTH_NAME, TYPE_INT, DF_SETUP|DF_HIDDEN },
{ OPENFILE_WIDTH_TYPE, TYPE_INT, DF_SETUP|DF_HIDDEN },
{ OPENFILE_WIDTH_SIZE, TYPE_INT, DF_SETUP|DF_HIDDEN },
{ OPENFILE_WIDTH_DATE, TYPE_INT, DF_SETUP|DF_HIDDEN },
{ OPENFILE_ONLYNAME, TYPE_BOOL, DF_SETUP|DF_HIDDEN },
{ OPENFILE_HISTORYCOUNT,TYPE_INT, DF_SETUP|DF_HIDDEN },
{ OPENFILE_SAVE_NAME, TYPE_STRING, DF_HIDDEN },
{ OPENFILE_SAVE_TYPE, TYPE_INT, DF_ENUMCLASS|DF_HIDDEN },
{ OPENFILE_URL, TYPE_STRING, DF_HIDDEN },
{ OPENFILE_LIST, 0, DF_HIDDEN },
DATATABLE_END(OPENFILE_ID)
};
static int Enum(openfile* p, int* No, datadef* Param )
{
if (NodeEnumTable(No,Param,Params)==ERR_NONE)
{
if (Param->No == OPENFILE_SAVE_TYPE)
Param->Format1 = p->Class;
return ERR_NONE;
}
if (*No >= 0 && *No < p->HistoryCount)
{
memset(Param,0,sizeof(datadef));
Param->No = OPENFILE_HISTORY + *No;
Param->Type = TYPE_STRING;
Param->Size = MAXDATA;
Param->Flags = DF_HIDDEN | DF_SETUP;
Param->Class = OPENFILE_ID;
return ERR_NONE;
}
return ERR_INVALID_PARAM;
}
static int Get(openfile* p,int No,void* Data,int Size)
{
int Result = ERR_INVALID_PARAM;
switch (No)
{
case OPENFILE_MULTIPLE: GETVALUE(p->Multiple,bool_t); break;
case OPENFILE_CLASS: GETVALUE(p->Class,int); break;
case OPENFILE_FLAGS: GETVALUE(p->Flags,int); break;
case OPENFILE_FILETYPE: GETVALUE(p->FileType,int); break;
case OPENFILE_FILETYPE_SINGLE: GETVALUE(p->FileTypeSingle,int); break;
case OPENFILE_FILETYPE_SAVE: GETVALUE(p->FileTypeSave,int); break;
case OPENFILE_PATH: GETSTRING(p->Path); break;
case OPENFILE_SORTCOL: GETVALUE(p->SortCol,int); break;
case OPENFILE_SORTDIR: GETVALUE(p->SortDir,bool_t); break;
case OPENFILE_WIDTH_NAME: GETVALUE(p->DlgWidth[0],int); break;
case OPENFILE_WIDTH_TYPE: GETVALUE(p->DlgWidth[1],int); break;
case OPENFILE_WIDTH_SIZE: GETVALUE(p->DlgWidth[2],int); break;
case OPENFILE_WIDTH_DATE: GETVALUE(p->DlgWidth[3],int); break;
case OPENFILE_HISTORYCOUNT: GETVALUE(p->HistoryCount,int); break;
case OPENFILE_ONLYNAME: GETVALUE(p->OnlyName,bool_t); break;
case OPENFILE_SAVE_NAME: GETSTRING(p->SaveName); break;
case OPENFILE_SAVE_TYPE: GETVALUE(p->FileTypeSave,int); break;
}
if (No >= OPENFILE_HISTORY && No < OPENFILE_HISTORY+p->HistoryCount && p->History[No-OPENFILE_HISTORY])
GETSTRING(p->History[No-OPENFILE_HISTORY]);
return Result;
}
static void SetColWidth(openfile* p, int Index,int Width)
{
ListView_SetColumnWidth(p->WndList,Index,WinUnitToPixelX(&p->Win,Width));
}
static int GetColWidth(openfile* p, int Index)
{
if (p->Win.Smartphone)
return p->DlgWidth[Index]; // no GUI update possible
return WinPixelToUnitX(&p->Win,ListView_GetColumnWidth(p->WndList,Index));
}
static int UpdateOnlyName(openfile* p)
{
int i;
if (p->OnlyName != p->OnlyNameState)
{
WinMenuCheck(&p->Win,1,OPENFILE_ONLYNAME,p->OnlyName);
p->OnlyNameState = p->OnlyName;
if (p->OnlyName)
{
for (i=0;i<4;++i)
p->DlgWidth[i] = GetColWidth(p,i);
ShowWindow(p->WndList,SW_HIDE);
SetColWidth(p,3,0);
SetColWidth(p,2,0);
SetColWidth(p,1,0);
SetColWidth(p,0,300);
ShowWindow(p->WndList,SW_SHOWNA);
}
else
{
ShowWindow(p->WndList,SW_HIDE);
for (i=3;i>=0;--i)
SetColWidth(p,i,max(15,p->DlgWidth[i]));
ShowWindow(p->WndList,SW_SHOWNA);
}
}
return ERR_NONE;
}
static int Set(openfile* p,int No,const void* Data,int Size)
{
int Result = ERR_INVALID_PARAM;
switch (No)
{
case OPENFILE_MULTIPLE: SETVALUE(p->Multiple,bool_t,ERR_NONE); break;
case OPENFILE_FLAGS: SETVALUE(p->Flags,int,ERR_NONE); break;
case OPENFILE_CLASS: SETVALUE(p->Class,int,ERR_NONE); break;
case OPENFILE_FILETYPE: SETVALUE(p->FileType,int,ERR_NONE); break;
case OPENFILE_FILETYPE_SINGLE: SETVALUE(p->FileTypeSingle,int,ERR_NONE); break;
case OPENFILE_FILETYPE_SAVE: SETVALUE(p->FileTypeSave,int,ERR_NONE); break;
case OPENFILE_PATH: SETSTRING(p->Path); break;
case OPENFILE_SORTCOL: SETVALUE(p->SortCol,int,ERR_NONE); break;
case OPENFILE_SORTDIR: SETVALUE(p->SortDir,bool_t,ERR_NONE); break;
case OPENFILE_WIDTH_NAME: SETVALUE(p->DlgWidth[0],int,ERR_NONE); break;
case OPENFILE_WIDTH_TYPE: SETVALUE(p->DlgWidth[1],int,ERR_NONE); break;
case OPENFILE_WIDTH_SIZE: SETVALUE(p->DlgWidth[2],int,ERR_NONE); break;
case OPENFILE_ONLYNAME: SETVALUE(p->OnlyName,bool_t,UpdateOnlyName(p)); break;
case OPENFILE_HISTORYCOUNT: SETVALUE(p->HistoryCount,int,ERR_NONE); break;
case OPENFILE_SAVE_NAME: SETSTRING(p->SaveName); break;
case OPENFILE_SAVE_TYPE: SETVALUE(p->FileTypeSave,int,ERR_NONE); break;
}
if (No >= OPENFILE_HISTORY && No < OPENFILE_HISTORY+p->HistoryCount)
{
free(p->History[No-OPENFILE_HISTORY]);
p->History[No-OPENFILE_HISTORY] = tcsdup((tchar_t*)Data);
Result = ERR_NONE;
}
return Result;
}
static void AddCol(openfile* p, int Index, const tchar_t* Name, int Width, int Format )
{
LVCOLUMN Col;
Col.mask=LVCF_TEXT | LVCF_WIDTH | LVCF_FMT;
Col.cx=WinUnitToPixelX(&p->Win,Width);
Col.pszText=(tchar_t*)Name;
Col.cchTextMax=tcslen(Name)+1;
Col.fmt=Format;
ListView_InsertColumn(p->WndList,Index,&Col);
}
static int CALLBACK CompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
openfile* p = (openfile*)lParamSort;
openitem* a = (openitem*)lParam1;
openitem* b = (openitem*)lParam2;
int Result = 0;
if (!a) return b?-1:0;
if (!b) return 1;
if (a->Image==IMG_DIR)
if (b->Image==IMG_DIR)
Result = tcsicmp(a->Name,b->Name);
else
Result = -1;
else
if (b->Image==IMG_DIR)
Result = 1;
else
switch(p->SortCol)
{
case 0:
Result = tcsicmp(a->Name,b->Name);
break;
case 1:
Result = tcsicmp(a->Ext,b->Ext);
if (!Result)
Result = tcsicmp(a->Name,b->Name);
break;
case 2:
if (a->Size == b->Size)
Result = tcsicmp(a->Name,b->Name);
else
Result = a->Size > b->Size ? 1:-1;
break;
case 3:
if (a->Date == b->Date)
Result = tcsicmp(a->Name,b->Name);
else
Result = a->Date > b->Date ? 1:-1;
break;
}
if (p->SortDir)
Result = -Result;
return Result;
}
static void SavePos(openfile* p)
{
LVITEM Item;
int n;
p->Last[0] = 0;
for (n=0;n<ListView_GetItemCount(p->WndList);++n)
if (ListView_GetItemState(p->WndList,n,LVIS_FOCUSED)==LVIS_FOCUSED)
{
Item.iItem=n;
Item.iSubItem = 0;
Item.mask=LVIF_PARAM;
ListView_GetItem(p->WndList,&Item);
if (Item.lParam)
tcscpy_s(p->Last,TSIZEOF(p->Last),((openitem*)Item.lParam)->Name);
break;
}
}
static void ClearList(openfile* p)
{
LVITEM Item;
int n;
for (n=0;n<ListView_GetItemCount(p->WndList);++n)
{
Item.iItem=n;
Item.iSubItem=0;
Item.mask=LVIF_PARAM;
ListView_GetItem(p->WndList,&Item);
if (Item.lParam)
free((void*)Item.lParam);
}
ListView_DeleteAllItems(p->WndList);
}
static void SelectAll(openfile* p)
{
LVITEM Item;
int n;
int State;
p->OwnSelect = 1;
for (n=0;n<ListView_GetItemCount(p->WndList);++n)
{
Item.iItem=n;
Item.iSubItem=0;
Item.mask=LVIF_PARAM;
ListView_GetItem(p->WndList,&Item);
State = 0;
if (Item.lParam && (((openitem*)Item.lParam)->Image != IMG_DIR || p->SelectDir))
State = LVIS_SELECTED;
ListView_SetItemState(p->WndList,n,State,LVIS_SELECTED);
}
p->OwnSelect = 0;
}
static void UpdateSelectDir(openfile* p)
{
if (p->Flags & OPENFLAG_SINGLE)
return;
if (p->Win.Smartphone)
{
WinMenuCheck(&p->Win,1,OPENFILE_SELECTDIR2,p->SelectDir);
}
else
{
TBBUTTONINFO Button;
Button.cbSize = sizeof(Button);
Button.dwMask = TBIF_STATE;
Button.fsState = TBSTATE_ENABLED;
if (p->SelectDir)
Button.fsState |= TBSTATE_CHECKED;
SendMessage(p->Win.WndTB,TB_SETBUTTONINFO,OPENFILE_SELECTDIR,(LPARAM)&Button);
}
}
static void UpdateMultiple(openfile* p)
{
int Count,i;
if (p->Flags & OPENFLAG_SINGLE)
return;
if (p->Win.Smartphone)
{
WinMenuCheck(&p->Win,1,OPENFILE_MORE,p->Multiple);
}
else
{
TBBUTTONINFO Button;
Button.cbSize = sizeof(Button);
Button.dwMask = TBIF_STATE;
Button.fsState = TBSTATE_ENABLED;
if (p->Multiple)
Button.fsState |= TBSTATE_CHECKED;
SendMessage(p->Win.WndTB,TB_SETBUTTONINFO,OPENFILE_MORE,(LPARAM)&Button);
}
p->OwnSelect = 1;
Count = ListView_GetItemCount(p->WndList);
for (i=0;i<Count;++i)
{
int State = 0;
if (!p->Multiple && ListView_GetItemState(p->WndList,i,LVIS_FOCUSED)==LVIS_FOCUSED)
State = LVIS_SELECTED;
ListView_SetItemState(p->WndList,i,State,LVIS_SELECTED);
}
p->OwnSelect = 0;
}
static void SetURLText(openfile* p,const tchar_t* s)
{
int Len = tcslen(s);
++p->InUpdate;
SetWindowText(p->WndURL,s);
if (p->Win.Smartphone)
SendMessage(p->WndURL,EM_SETSEL,Len,Len);
else
SendMessage(p->WndURL,CB_SETEDITSEL,0,MAKEWORD(-1,-1));
--p->InUpdate;
}
static void AddHistory(openfile* p,const tchar_t* s)
{
int i;
for (i=0;i<p->HistoryCount;++i)
if (p->History[i] && tcsicmp(p->History[i],s)==0)
{
for (;i>0;--i)
SwapPChar(&p->History[i],&p->History[i-1]);
break;
}
if (i==p->HistoryCount)
{
if (i<MAXHISTORY)
p->HistoryCount++;
else
free(p->History[--i]);
for (;i>0;--i)
p->History[i] = p->History[i-1];
p->History[0] = tcsdup(s);
}
if (!p->Win.Smartphone)
{
int i;
SendMessage(p->WndURL,CB_RESETCONTENT,0,0);
for (i=0;i<p->HistoryCount;++i)
if (p->History[i])
SendMessage(p->WndURL,CB_ADDSTRING,0,(LPARAM)p->History[i]);
}
SetURLText(p,s);
}
static void UpdateList(openfile* p, bool_t Silent, int ListMode)
{
streamdir DirItem;
stream* Stream;
int Result;
openitem New;
LVITEM Item;
int No=0;
int Pos=0;
int State = LVIS_FOCUSED;
int Len;
const tchar_t* s;
bool_t HasHost;
if (!p->Multiple || (p->Flags & OPENFLAG_SINGLE))
State |= LVIS_SELECTED;
Len = tcslen(p->Path);
if (Len && (p->Path[Len-1] == '\\' || p->Path[Len-1] == '/'))
p->Path[--Len] = 0;
tcscpy_s(p->Base,TSIZEOF(p->Base),p->Path);
s = p->Path[0] ? p->Path : T("\\");
AddHistory(p,s);
if (!ListMode)
return;
++p->InUpdate;
WaitBegin();
ShowWindow(p->WndList,SW_HIDE);
ClearList(p);
Item.mask=LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;
Item.pszText=T("");
Item.cchTextMax=1;
Item.iSubItem=0;
Stream = GetStream(p->Path,Silent);
if (Stream)
{
s = GetMime(p->Path,NULL,0,&HasHost);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -