mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
592 lines
16 KiB
592 lines
16 KiB
#include "priv.h"
|
|
#include "zaxxon.h"
|
|
#include "guids.h"
|
|
#include "shlwapip.h"
|
|
#include "resource.h"
|
|
#include "commdlg.h"
|
|
#include "varutil.h"
|
|
|
|
#define ID_TOOLBAR 100
|
|
#define ID_LISTVIEW 101
|
|
|
|
#define EDIT_NEW 0
|
|
#define EDIT_ADD 1
|
|
#define EDIT_REMOVE 2
|
|
#define EDIT_LOAD 3
|
|
#define EDIT_SAVE 4
|
|
#define EDIT_SORT 5
|
|
|
|
|
|
CSong::CSong():_cRef(1)
|
|
{
|
|
|
|
}
|
|
|
|
void CSong::AddRef()
|
|
{
|
|
InterlockedIncrement((LONG*)&_cRef);
|
|
}
|
|
|
|
void CSong::Release()
|
|
{
|
|
InterlockedDecrement((LONG*)&_cRef);
|
|
if (_cRef == 0)
|
|
delete this;
|
|
}
|
|
|
|
|
|
CZaxxonEditor::CZaxxonEditor(CZaxxon* pz):_pzax(pz)
|
|
{
|
|
WNDCLASS wc = {0};
|
|
wc.lpszClassName = TEXT("ZaxxonEditor");
|
|
wc.lpfnWndProc = CZaxxonEditor::s_WndProc;
|
|
wc.hInstance = HINST_THISDLL;
|
|
wc.hbrBackground = HBRUSH(COLOR_ACTIVECAPTION + 1);
|
|
RegisterClass(&wc);
|
|
|
|
hSongList = DPA_Create(10);
|
|
}
|
|
|
|
int CALLBACK SongDestroyCallback(void* p, void*)
|
|
{
|
|
CSong* psong = (CSong*)p;
|
|
psong->Release();
|
|
return 1;
|
|
}
|
|
|
|
CZaxxonEditor::~CZaxxonEditor()
|
|
{
|
|
if (_hwnd)
|
|
{
|
|
DestroyWindow(_hwnd);
|
|
_hwnd = NULL;
|
|
}
|
|
|
|
DPA_DestroyCallback(hSongList, SongDestroyCallback, NULL);
|
|
}
|
|
|
|
|
|
int ReadLineFromStream(IStream* pstm, LPTSTR pszLine, DWORD cch)
|
|
{
|
|
// Assume this is an ANSI string
|
|
char szLine[MAX_PATH];
|
|
DWORD dwRead;
|
|
int iLine = 0;
|
|
ULARGE_INTEGER UliStartingFrom;
|
|
LARGE_INTEGER liSeek = {0};
|
|
|
|
pstm->Seek(liSeek, STREAM_SEEK_CUR, &UliStartingFrom);
|
|
pstm->Read(szLine, ARRAYSIZE(szLine), &dwRead);
|
|
if (dwRead > 0)
|
|
{
|
|
// Now convert to String
|
|
SHAnsiToUnicode(szLine, pszLine, dwRead);
|
|
|
|
pszLine[MAX_PATH - 1] = '\0'; //Null terminate the string
|
|
|
|
// Get the number of characters in the line
|
|
LPTSTR pszNewLine = StrStr(pszLine, TEXT("\r"));
|
|
|
|
if (pszNewLine)
|
|
{
|
|
*pszNewLine++ = TEXT('\0'); // Nuke \r
|
|
*pszNewLine = TEXT('\0'); // Nuke \n
|
|
}
|
|
else
|
|
{
|
|
pszNewLine = StrStr(pszLine, TEXT("\n"));
|
|
if (pszNewLine)
|
|
*pszNewLine = TEXT('\0'); // Nuke \n
|
|
}
|
|
|
|
|
|
|
|
iLine = lstrlen(pszLine);
|
|
|
|
// Now take that, and set the seek position to 2 more than that (One for the \r and \n
|
|
liSeek.QuadPart = UliStartingFrom.QuadPart + iLine + 1 + 1;
|
|
pstm->Seek(liSeek, STREAM_SEEK_SET, NULL);
|
|
}
|
|
|
|
return iLine;
|
|
}
|
|
|
|
|
|
void CZaxxonEditor::UpdateSong(CSong* psong)
|
|
{
|
|
|
|
int i = ListView_MapIDToIndex(_hwndList, psong->_id);
|
|
if (i >= 0)
|
|
{
|
|
TCHAR szTitle[MAX_PATH];
|
|
wsprintf(szTitle, TEXT("%s - %s"), psong->szArtist, psong->szTitle);
|
|
|
|
|
|
LVITEM lv;
|
|
lv.mask = LVIF_TEXT;
|
|
lv.iItem = i;
|
|
lv.iSubItem = 0;
|
|
lv.pszText = szTitle;
|
|
ListView_SetItem(_hwndList,&lv);
|
|
|
|
lv.iSubItem = 1;
|
|
lv.pszText = psong->szDuration;
|
|
ListView_SetItem(_hwndList,&lv);
|
|
}
|
|
}
|
|
|
|
void CZaxxonEditor::LoadPlaylist()
|
|
{
|
|
TCHAR sz[MAX_PATH];
|
|
TCHAR szInit[MAX_PATH];
|
|
OPENFILENAME of = {0};
|
|
of.lStructSize = sizeof(of);
|
|
of.hwndOwner = _hwnd;
|
|
of.lpstrFilter = TEXT("Playlist\0*.m3u\0\0");
|
|
of.lpstrFile = sz;
|
|
of.nMaxFile = MAX_PATH;
|
|
of.lpstrDefExt = TEXT(".m3u");
|
|
if (FAILED(SHGetFolderPath(NULL, CSIDL_MYMUSIC, NULL, SHGFP_TYPE_CURRENT, szInit)))
|
|
SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, szInit);
|
|
|
|
of.lpstrInitialDir = szInit;
|
|
of.Flags = OFN_ENABLESIZING | OFN_EXPLORER | OFN_FILEMUSTEXIST;
|
|
|
|
if (GetOpenFileName(&of))
|
|
{
|
|
ClearPlaylist();
|
|
IStream* pstm;
|
|
if (SUCCEEDED(SHCreateStreamOnFile(sz, STGM_READ, &pstm)))
|
|
{
|
|
do
|
|
{
|
|
TCHAR szFilename[MAX_PATH];
|
|
if (ReadLineFromStream(pstm, szFilename, ARRAYSIZE(szFilename)) > 0)
|
|
{
|
|
AddFilename(szFilename);
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
while (1);
|
|
|
|
pstm->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
void CZaxxonEditor::SavePlaylist()
|
|
{
|
|
TCHAR sz[MAX_PATH];
|
|
TCHAR szInit[MAX_PATH];
|
|
OPENFILENAME of = {0};
|
|
of.lStructSize = sizeof(of);
|
|
of.hwndOwner = _hwnd;
|
|
of.lpstrFilter = TEXT("Playlist\0*.m3u\0\0");
|
|
of.lpstrFile = sz;
|
|
of.nMaxFile = MAX_PATH;
|
|
of.lpstrDefExt = TEXT(".m3u");
|
|
if (FAILED(SHGetFolderPath(NULL, CSIDL_MYMUSIC, NULL, SHGFP_TYPE_CURRENT, szInit)))
|
|
SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, szInit);
|
|
|
|
of.lpstrInitialDir = szInit;
|
|
of.Flags = OFN_ENABLESIZING | OFN_EXPLORER;
|
|
|
|
if (GetSaveFileName(&of))
|
|
{
|
|
IStream* pstm;
|
|
if (SUCCEEDED(SHCreateStreamOnFile(sz, STGM_CREATE | STGM_WRITE, &pstm)))
|
|
{
|
|
char szLine[MAX_PATH];
|
|
|
|
int cCount = DPA_GetPtrCount(hSongList);
|
|
for (int i=0; i < cCount; i++)
|
|
{
|
|
CSong* psong = (CSong*)DPA_FastGetPtr(hSongList, i);
|
|
SHUnicodeToAnsi(psong->szSong, szLine, MAX_PATH);
|
|
pstm->Write(szLine, lstrlenA(szLine), NULL);
|
|
pstm->Write("\r\n", 2, NULL);
|
|
}
|
|
pstm->Write("\r\n", 2, NULL);
|
|
pstm->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
void CZaxxonEditor::RemoveFromPlaylist()
|
|
{
|
|
int iItem = ListView_GetNextItem(_hwndList, -1, MAKELPARAM(LVNI_SELECTED, 0));
|
|
if (iItem >= 0 && iItem < DPA_GetPtrCount(hSongList))
|
|
{
|
|
_pzax->_pzax->RemoveSong(iItem);
|
|
ListView_DeleteItem(_hwndList, iItem);
|
|
CSong* psong = (CSong*)DPA_DeletePtr(hSongList, iItem);
|
|
psong->Release();
|
|
}
|
|
|
|
}
|
|
|
|
void CZaxxonEditor::ClearPlaylist()
|
|
{
|
|
_pzax->_pzax->ClearPlaylist();
|
|
|
|
DPA_DestroyCallback(hSongList, SongDestroyCallback, NULL);
|
|
hSongList = DPA_Create(10);
|
|
ListView_DeleteAllItems(_hwndList);
|
|
}
|
|
|
|
|
|
void CZaxxonEditor::InsertFilename(int i, PTSTR psz)
|
|
{
|
|
CSong* pzs = new CSong;
|
|
if (pzs)
|
|
{
|
|
StrCpy(pzs->szSong, psz);
|
|
|
|
int iIndex = DPA_InsertPtr(hSongList, i, pzs);
|
|
if (iIndex != -1)
|
|
{
|
|
LVITEM lv;
|
|
lv.mask = LVIF_TEXT;
|
|
lv.iItem = iIndex;
|
|
lv.iSubItem = 0;
|
|
lv.pszText = PathFindFileName(psz);
|
|
ListView_InsertItem(_hwndList, &lv);
|
|
|
|
pzs->_id = ListView_MapIndexToID(_hwndList, iIndex);
|
|
|
|
|
|
_pzax->_pzax->AddSong(psz);
|
|
CSongExtractionTask* pset = new CSongExtractionTask(_hwnd, pzs);
|
|
if (pset)
|
|
{
|
|
if (_pzax->_pScheduler)
|
|
_pzax->_pScheduler->AddTask(pset, CLSID_Zaxxon, 0, ITSAT_MIN_PRIORITY);
|
|
pset->Release();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CZaxxonEditor::AddFilename(PTSTR psz)
|
|
{
|
|
InsertFilename(DSA_APPEND, psz);
|
|
}
|
|
|
|
void CZaxxonEditor::AddToPlaylist()
|
|
{
|
|
OPENFILENAME of = {0};
|
|
PTSTR psz = (PTSTR)LocalAlloc(LPTR, 4096);
|
|
if (psz)
|
|
{
|
|
of.lStructSize = sizeof(of);
|
|
of.hwndOwner = _hwnd;
|
|
of.lpstrFilter = TEXT("Music\0*.mp3;*.wma\0\0");
|
|
of.lpstrFile = psz;
|
|
of.nMaxFile = 4096;
|
|
of.Flags = OFN_ALLOWMULTISELECT | OFN_ENABLESIZING | OFN_EXPLORER | OFN_FILEMUSTEXIST;
|
|
|
|
if (GetOpenFileName(&of))
|
|
{
|
|
TCHAR szName[MAX_PATH];
|
|
PTSTR pszFilename = psz;
|
|
int iLen = lstrlen(pszFilename);
|
|
do
|
|
{
|
|
pszFilename += iLen + 1; // Skip the last filename
|
|
iLen = lstrlen(pszFilename);
|
|
|
|
if (iLen > 0)
|
|
{
|
|
StrCpy(szName, psz); // Copy the path;
|
|
PathAppend(szName, pszFilename); // Append the new name
|
|
AddFilename(szName); // Append to list.
|
|
}
|
|
}
|
|
while (iLen != 0);
|
|
|
|
}
|
|
|
|
LocalFree(psz);
|
|
}
|
|
}
|
|
|
|
int FindSong(void* p1, void* p2, LPARAM lParam)
|
|
{
|
|
PTSTR pszSong = (PTSTR)p1;
|
|
CSong* psong = (CSong*)p2;
|
|
return StrCmpI(pszSong, psong->szSong);
|
|
}
|
|
|
|
void CZaxxonEditor::HighlightSong(PTSTR psz)
|
|
{
|
|
|
|
int iItem = DPA_Search(hSongList, psz, 0, FindSong, 0, NULL);
|
|
if (iItem >= 0)
|
|
{
|
|
ListView_SetItemState(_hwndList, iItem, LVIS_SELECTED, LVIS_SELECTED);
|
|
}
|
|
}
|
|
|
|
|
|
static const TCHAR* g_EditStrings = TEXT("New\0Add\0Delete\0Load\0Save\0Sort\0\0");
|
|
|
|
static const TBBUTTON g_crgEditButtons[] =
|
|
{
|
|
{I_IMAGENONE, EDIT_NEW, TBSTATE_ENABLED, BTNS_BUTTON, 0, 0, 0, 0},
|
|
{I_IMAGENONE, EDIT_ADD, TBSTATE_ENABLED, BTNS_BUTTON, 0, 0, 0, 1},
|
|
{I_IMAGENONE, EDIT_REMOVE, TBSTATE_ENABLED, BTNS_BUTTON, 0, 0, 0, 2},
|
|
{I_IMAGENONE, EDIT_LOAD, TBSTATE_ENABLED, BTNS_BUTTON, 0, 0, 0, 3},
|
|
{I_IMAGENONE, EDIT_SAVE, TBSTATE_ENABLED, BTNS_BUTTON, 0, 0, 0, 4},
|
|
{I_IMAGENONE, EDIT_SORT, TBSTATE_ENABLED, BTNS_BUTTON, 0, 0, 0, 5},
|
|
};
|
|
|
|
BOOL CZaxxonEditor::Initialize()
|
|
{
|
|
int cxInitial = 300;
|
|
int cyInitial = 500;
|
|
_hwnd = CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
|
|
TEXT("ZaxxonEditor"), TEXT("Zaxxon Playlist Editor"),
|
|
WS_CAPTION | WS_POPUPWINDOW | WS_THICKFRAME | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
|
|
0, 0, 0, 0,
|
|
_pzax->GetHWND(), NULL, HINST_THISDLL, this);
|
|
if (_hwnd)
|
|
{
|
|
_pzax->_pzax->Register(_hwnd);
|
|
|
|
_hwndList = CreateWindow(
|
|
TEXT("SysListView32"), TEXT(""),
|
|
WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS,
|
|
0, 0, 0, 0,
|
|
_hwnd, (HMENU)ID_LISTVIEW, NULL, NULL);
|
|
|
|
if (_hwndList)
|
|
{
|
|
RECT rc;
|
|
GetClientRect(_hwnd, &rc);
|
|
LVCOLUMN lvc = {0};
|
|
lvc.mask = LVCF_TEXT | LVCF_WIDTH;
|
|
lvc.cx = 4 * cxInitial / 5 - 10;
|
|
lvc.pszText = TEXT("Song");
|
|
ListView_InsertColumn(_hwndList, 0, &lvc);
|
|
|
|
lvc.mask = LVCF_TEXT | LVCF_WIDTH;
|
|
lvc.cx = cxInitial / 5;
|
|
lvc.pszText = TEXT("Length");
|
|
ListView_InsertColumn(_hwndList, 1, &lvc);
|
|
|
|
ListView_SetExtendedListViewStyle(_hwndList, LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER);
|
|
}
|
|
|
|
_hwndToolbar = CreateWindowEx(WS_EX_TOOLWINDOW, TOOLBARCLASSNAME, NULL,
|
|
WS_VISIBLE | WS_CHILD | TBSTYLE_FLAT | TBSTYLE_LIST |
|
|
WS_CLIPCHILDREN | WS_CLIPSIBLINGS |
|
|
CCS_NODIVIDER | CCS_NOPARENTALIGN |
|
|
CCS_NORESIZE | TBSTYLE_REGISTERDROP,
|
|
0, 0, 0, 0, _hwnd, (HMENU) ID_TOOLBAR, HINST_THISDLL, NULL);
|
|
|
|
if (_hwndToolbar)
|
|
{
|
|
// Set the format to ANSI or UNICODE as appropriate.
|
|
ToolBar_SetUnicodeFormat(_hwndToolbar, TRUE);
|
|
SetWindowTheme(_hwndToolbar, L"TaskBar", NULL);
|
|
SendMessage(_hwndToolbar, CCM_SETVERSION, COMCTL32_VERSION, 0);
|
|
SendMessage(_hwndToolbar, TB_BUTTONSTRUCTSIZE, SIZEOF(TBBUTTON), 0);
|
|
SendMessage(_hwndToolbar, TB_ADDSTRING, NULL, (LPARAM)g_EditStrings);
|
|
SendMessage(_hwndToolbar, TB_ADDBUTTONS, ARRAYSIZE(g_crgEditButtons), (LPARAM)&g_crgEditButtons);
|
|
ToolBar_SetExtendedStyle(_hwndToolbar, TBSTYLE_EX_DOUBLEBUFFER, TBSTYLE_EX_DOUBLEBUFFER);
|
|
}
|
|
|
|
|
|
SetWindowPos(_hwnd, NULL, 0, 0, cxInitial, cyInitial, SWP_NOACTIVATE);
|
|
|
|
}
|
|
|
|
return _hwnd != NULL;
|
|
}
|
|
|
|
BOOL CZaxxonEditor::Show(BOOL fShow)
|
|
{
|
|
ShowWindow(_hwnd, fShow?SW_SHOW:SW_HIDE);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
LRESULT CZaxxonEditor::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_CREATE:
|
|
break;
|
|
|
|
case WM_SONGCHANGE:
|
|
{
|
|
_fIgnoreChange = TRUE;
|
|
HighlightSong((PTSTR)wParam);
|
|
_fIgnoreChange = FALSE;
|
|
}
|
|
break;
|
|
|
|
case WM_UPDATESONG:
|
|
{
|
|
UpdateSong((CSong*)wParam);
|
|
}
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
{
|
|
LPNMHDR pnm = (LPNMHDR)lParam;
|
|
if (pnm->idFrom == ID_TOOLBAR)
|
|
{
|
|
if (pnm->code == NM_CLICK)
|
|
{
|
|
{
|
|
int idCmd = (int)((LPNMCLICK)pnm)->dwItemSpec;
|
|
switch (idCmd)
|
|
{
|
|
case EDIT_NEW:
|
|
ClearPlaylist();
|
|
break;
|
|
case EDIT_ADD:
|
|
AddToPlaylist();
|
|
break;
|
|
|
|
case EDIT_REMOVE:
|
|
RemoveFromPlaylist();
|
|
break;
|
|
|
|
case EDIT_LOAD:
|
|
LoadPlaylist();
|
|
break;
|
|
|
|
case EDIT_SAVE:
|
|
SavePlaylist();
|
|
break;
|
|
|
|
case EDIT_SORT:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (pnm->idFrom == ID_LISTVIEW)
|
|
{
|
|
if (pnm->code == LVN_ITEMCHANGED && !_fIgnoreChange)
|
|
{
|
|
NMLISTVIEW* pnml = (NMLISTVIEW*)pnm;
|
|
int iItem = pnml->iItem;
|
|
if (iItem < DPA_GetPtrCount(hSongList) &&
|
|
pnml->uNewState != pnml->uOldState &&
|
|
pnml->uNewState & LVIS_SELECTED)
|
|
{
|
|
_pzax->_pzax->SetSong(iItem);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
ShowWindow(hwnd, SW_HIDE);
|
|
return 1;
|
|
|
|
case WM_SIZE:
|
|
{
|
|
RECT rc;
|
|
GetClientRect(hwnd, &rc);
|
|
LONG lButton = SendMessage(_hwndToolbar, TB_GETBUTTONSIZE, 0, 0L);
|
|
SetWindowPos(_hwndList, NULL, rc.left, rc.top, RECTWIDTH(rc), RECTHEIGHT(rc) - HIWORD(lButton), SWP_NOZORDER | SWP_NOACTIVATE);
|
|
SetWindowPos(_hwndToolbar, NULL, rc.left, RECTHEIGHT(rc) - HIWORD(lButton), RECTWIDTH(rc), HIWORD(lButton), SWP_NOZORDER | SWP_NOACTIVATE);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
|
|
LRESULT CZaxxonEditor::s_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if (uMsg == WM_CREATE)
|
|
{
|
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, (ULONG_PTR)((CREATESTRUCT*)lParam)->lpCreateParams);
|
|
}
|
|
|
|
CZaxxonEditor* pedit = (CZaxxonEditor*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
|
|
|
|
if (pedit)
|
|
return pedit->WndProc(hwnd, uMsg, wParam, lParam);
|
|
|
|
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
|
|
CSongExtractionTask::CSongExtractionTask(HWND hwnd, CSong* psong)
|
|
: CRunnableTask(RTF_DEFAULT), _hwnd(hwnd)
|
|
{
|
|
_psong = psong;
|
|
_psong->AddRef();
|
|
}
|
|
|
|
CSongExtractionTask::~CSongExtractionTask()
|
|
{
|
|
_psong->Release();
|
|
}
|
|
|
|
STDMETHODIMP CSongExtractionTask::RunInitRT()
|
|
{
|
|
LPITEMIDLIST pidl = ILCreateFromPath(_psong->szSong);
|
|
if (pidl)
|
|
{
|
|
LPCITEMIDLIST pidlChild;
|
|
IShellFolder2* psf;
|
|
|
|
HRESULT hr = SHBindToParent(pidl, IID_PPV_ARG(IShellFolder2, &psf), &pidlChild);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
VARIANT v;
|
|
hr = psf->GetDetailsEx(pidlChild, &SCID_MUSIC_Artist, &v);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
VariantToStr(&v, _psong->szArtist, ARRAYSIZE(_psong->szArtist));
|
|
}
|
|
|
|
hr = psf->GetDetailsEx(pidlChild, &SCID_MUSIC_Album, &v);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
VariantToStr(&v, _psong->szAlbum, ARRAYSIZE(_psong->szAlbum));
|
|
}
|
|
|
|
hr = psf->GetDetailsEx(pidlChild, &SCID_Title, &v);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
VariantToStr(&v, _psong->szTitle, ARRAYSIZE(_psong->szTitle));
|
|
}
|
|
|
|
hr = psf->GetDetailsEx(pidlChild, &SCID_AUDIO_Duration, &v);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
PROPVARIANT pv = *(PROPVARIANT*)&v;
|
|
FILETIME ft = {pv.uhVal.LowPart, pv.uhVal.HighPart};
|
|
SYSTEMTIME st;
|
|
FileTimeToSystemTime(&ft, &st);
|
|
|
|
GetTimeFormat(LOCALE_USER_DEFAULT, TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER,
|
|
&st, NULL, _psong->szDuration, ARRAYSIZE(_psong->szDuration));
|
|
}
|
|
|
|
SendMessage(_hwnd, WM_UPDATESONG, (WPARAM)_psong, 0);
|
|
|
|
psf->Release();
|
|
}
|
|
|
|
ILFree(pidl);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|