1
2 #include "stdafx.h"
3 #include "NoahApp.h"
4 #include "SubDlg.h"
5
6 int CArcViewDlg::st_nLife;
7
8 BOOL CArcViewDlg::onInit()
9 {
10 char cstr[100];
11 kiStr str;
12 kiPath path;
13 SHFILEINFO sfi,lfi;
14 HIMAGELIST hImS,hImL;
15 kiListView ctrl( this, IDC_FILELIST );
16 __int64 filesize_sum = 0;
17
18 //-- ダイアログ一個生成の印
19 hello();
20 m_bSmallFirst[0] = m_bSmallFirst[1] = m_bSmallFirst[2] =
21 m_bSmallFirst[3] = m_bSmallFirst[4] = m_bSmallFirst[5] = true;
22
23 //-- 真ん中に&前に
24 setCenter( hwnd(), app()->mainhwnd() );
25 setFront( hwnd() );
26
27 //-- アイコン
28 path = m_fname.basedir, path += m_fname.sname;
29 hImS = (HIMAGELIST)::SHGetFileInfo( path, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX | SHGFI_ICON | SHGFI_SMALLICON );
30 hImL = (HIMAGELIST)::SHGetFileInfo( path, 0, &lfi, sizeof(lfi), SHGFI_SYSICONINDEX | SHGFI_ICON | SHGFI_LARGEICON );
31 sendMsg( WM_SETICON, ICON_BIG, (LPARAM)lfi.hIcon );
32 sendMsg( WM_SETICON, ICON_SMALL, (LPARAM)sfi.hIcon );
33
34 //-- タイトル
35 sendMsg( WM_SETTEXT, 0, (LPARAM)kiPath(m_fname.lname).name() );
36
37 //-- 解凍先
38 sendMsgToItem( IDC_DDIR, WM_SETTEXT, 0, (LPARAM)(const char*)m_ddir );
39
40 //-- リスト
41 if( !m_pArc->list( m_fname, m_files ) || m_files.len()==0 )
42 {
43 m_bAble = false;
44 ctrl.insertColumn( 0, "", 510 );
45 ctrl.insertItem( 0, str.loadRsrc(IDS_NOLIST) );
46 }
47 else
48 {
49 m_bAble = ( 0 != (m_pArc->ability() & aMeltEach) );
50
51 ctrl.setImageList( hImL, hImS );
52 ctrl.insertColumn( 0, str.loadRsrc(IDS_FNAME), 110 );
53 ctrl.insertColumn( 1, str.loadRsrc(IDS_SIZE), 70, LVCFMT_RIGHT );
54 ctrl.insertColumn( 2, str.loadRsrc(IDS_DATETIME),100, LVCFMT_RIGHT );
55 ctrl.insertColumn( 3, str.loadRsrc(IDS_RATIO), 55, LVCFMT_RIGHT );
56 ctrl.insertColumn( 4, str.loadRsrc(IDS_METHOD), 50, LVCFMT_RIGHT );
57 ctrl.insertColumn( 5, str.loadRsrc(IDS_PATH), 130 );
58
59 FILETIME ftm;
60 SYSTEMTIME stm;
61
62 //-- アイテム
63 for( unsigned int i=0,k=0; i!=m_files.len(); i++ )
64 if( m_files[i].isfile )
65 {
66 #define usiz (m_files[i].inf.dwOriginalSize)
67 #define csiz (m_files[i].inf.dwCompressedSize)
68 #define method (m_files[i].inf.szMode)
69 #define date (m_files[i].inf.wDate)
70 #define time (m_files[i].inf.wTime)
71 path = m_files[i].inf.szFileName;
72
73 // ファイル名
74 ctrl.insertItem( k, path.name(),
75 (LPARAM)(&m_files[i]), kiSUtil::getSysIcon(path.ext()) );
76
77 // サイズ
78 if( usiz == 0xffffffff )
79 ctrl.setSubItem( k, 1, "????" );
80 else
81 ctrl.setSubItem( k, 1, str.setInt( usiz,true ) );
82
83 // 時間
84 if( ::DosDateTimeToFileTime( date, time, &ftm )
85 && ::FileTimeToSystemTime( &ftm, &stm ) )
86 {
87 *cstr=0;
88 ::GetDateFormat( LOCALE_USER_DEFAULT, 0, &stm,
89 "yy/MM/dd", cstr, sizeof(cstr) );
90 str=cstr;
91 ::GetTimeFormat( LOCALE_USER_DEFAULT, 0, &stm,
92 " HH:mm", cstr, sizeof(cstr) );
93 str+=cstr;
94 ctrl.setSubItem( k, 2, str );
95 }
96
97 // 圧縮率
98 filesize_sum += usiz;
99 if( usiz==0 ) ctrl.setSubItem( k, 3, "100%" );
100 else if( csiz==0 ) ctrl.setSubItem( k, 3, "????" );
101 else ctrl.setSubItem( k, 3, str.setInt( (int)(((__int64)csiz)*100/usiz) )+='%' );
102
103 // メソッド
104 ctrl.setSubItem( k, 4, method );
105
106 // パス
107 path.beDirOnly();
108 ctrl.setSubItem( k, 5, path );
109
110 k++;
111
112 #undef usiz
113 #undef csiz
114 #undef method
115 #undef date
116 #undef time
117 }
118
119 //-- ドラッグ&ドロップフォーマット登録
120 FORMATETC fmt;
121 fmt.cfFormat = CF_HDROP;
122 fmt.ptd = NULL;
123 fmt.dwAspect = DVASPECT_CONTENT;
124 fmt.lindex = -1;
125 fmt.tymed = TYMED_HGLOBAL;
126 addFormat( fmt );
127 }
128
129 //-- 情報 --
130 char tmp[255];
131 kiStr full_filename = m_fname.basedir + m_fname.lname;
132 __int64 filesize_arc = kiFile::getSize64(full_filename);
133 if( filesize_sum==0 ) filesize_sum = 1;
134 wsprintf( tmp, kiStr().loadRsrc(IDS_ARCVIEW_MSG),
135 m_files.len(),
136 (int)(filesize_arc*100 / filesize_sum),
137 (const char*)m_pArc->arctype_name(full_filename)
138 );
139 sendMsgToItem( IDC_STATUSBAR, WM_SETTEXT, 0, (long)tmp );
140
141 if( !m_bAble )
142 {
143 static const UINT items[] = { IDC_SELECTINV,IDC_REF,IDC_MELTEACH,IDC_SHOW,IDC_DDIR };
144 for( int i=0; i!=sizeof(items)/sizeof(UINT); i++ )
145 ::EnableWindow( item(items[i]), FALSE );
146 }
147
148 return FALSE;
149 }
150
151 bool CArcViewDlg::onOK()
152 {
153 setdir();
154 m_pArc->melt( m_fname, m_ddir );
155 myapp().open_folder( m_ddir, 1 );
156 kiSUtil::switchCurDirToExeDir(); // 念のため
157 return onCancel();
158 }
159
160 bool CArcViewDlg::onCancel()
161 {
162 ::SetCurrentDirectory( m_fname.basedir );
163 m_tdir.remove();
164 if( kiSUtil::exist(m_tdir) )
165 {
166 kiStr tmp(600);
167 if( IDNO==app()->msgBox( tmp.loadRsrc(IDS_EXECUTING), NULL, MB_YESNO|MB_DEFBUTTON2 ) )
168 return false;
169 }
170
171 kiListView(this,IDC_FILELIST).setImageList( NULL, NULL );
172 byebye();
173 return true;
174 }
175
176 bool CArcViewDlg::giveData( const FORMATETC& fmt, STGMEDIUM* stg, bool firstcall )
177 {
178 if( firstcall )
179 if( 0x8000<=m_pArc->melt( m_fname, m_tdir, &m_files ) )
180 return false;
181
182 unsigned int i;
183 BOOL fWide = (app()->osver().dwPlatformId==VER_PLATFORM_WIN32_NT);
184 kiArray<kiPath> lst;
185 kiPath tmp;
186 int flen = 0;
187 wchar_t wbuf[600];
188
189 for( i=0; i!=m_files.len(); i++ )
190 if( m_files[i].selected )
191 {
192 tmp = m_tdir;
193 tmp += m_files[i].inf.szFileName;
194
195 lst.add( tmp );
196 if( fWide )
197 flen += (::MultiByteToWideChar( CP_ACP, 0, tmp, -1, wbuf, 600 )+1)*2;
198 else
199 flen += (tmp.len()+1);
200 }
201
202 HDROP hDrop = (HDROP)::GlobalAlloc( GHND, sizeof(DROPFILES)+flen+1 );
203
204 DROPFILES* dr = (DROPFILES*)::GlobalLock( hDrop );
205 dr->pFiles = sizeof(DROPFILES);
206 dr->pt.x = dr->pt.y = 0;
207 dr->fNC = FALSE;
208 dr->fWide = fWide;
209
210 char* buf = (char*)(&dr[1]);
211 for( i=0; i!=lst.len(); i++ )
212 {
213 if( fWide )
214 {
215 flen = ::MultiByteToWideChar( CP_ACP, 0, lst[i], -1, wbuf, 600 );
216 ki_memcpy( buf, wbuf, flen*2 );
217 for( int k=0; k!=flen; k++ )
218 if( ((wchar_t*)buf)[k] == '/' )
219 ((wchar_t*)buf)[k] = '\\';
220 buf += flen*2;
221 }
222 else
223 {
224 ki_strcpy( buf,lst[i] );
225 for( int k=0; k!=lst[i].len(); k++ )
226 if( buf[k] == '/' )
227 buf[k] = '\\';
228 buf += lst[i].len() + 1;
229 }
230 }
231 *buf=0;
232 if( fWide )
233 buf[1]='\0';
234
235 ::GlobalUnlock( hDrop );
236
237 stg->hGlobal = hDrop;
238 stg->tymed = TYMED_HGLOBAL;
239 stg->pUnkForRelease = NULL;
240 return true;
241 }
242
243 BOOL CALLBACK CArcViewDlg::proc( UINT msg, WPARAM wp, LPARAM lp )
244 {
245 switch( msg )
246 {
247 //-- メインウインドウ指定 ---------------------
248 case WM_ACTIVATE:
249 if( LOWORD(wp)==WA_ACTIVE || LOWORD(wp)==WA_CLICKACTIVE )
250 {
251 app()->setMainWnd( this );
252 return TRUE;
253 }
254 break;
255
256 //-- リサイズ関連の処理 ---------------------
257 case WM_GETMINMAXINFO:
258 {
259 RECT self,child;
260 ::GetWindowRect( hwnd(), &self );
261 ::GetWindowRect( item(IDC_REF), &child );
262 POINT& sz = ((MINMAXINFO*)lp)->ptMinTrackSize;
263 sz.x = child.right - self.left + 18;
264 sz.y = child.bottom - self.top + 100;
265 }
266 return TRUE;
267 case WM_SIZE:
268 if( wp!=SIZE_MAXHIDE && wp!=SIZE_MINIMIZED )
269 {
270 RECT self,ref,child,sbar;
271 ::GetWindowRect( hwnd(), &self );
272 ::GetWindowRect( item(IDC_REF), &ref );
273 ::GetWindowRect( item(IDC_FILELIST), &child );
274 ::GetClientRect( item(IDC_STATUSBAR), &sbar );
275
276 ::SetWindowPos( item(IDC_FILELIST), NULL, 0, 0,
277 LOWORD(lp),
278 (self.bottom-ref.bottom)-(child.top-ref.bottom)
279 -(sbar.bottom-sbar.top)-10,
280 SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER );
281
282 ::GetClientRect( hwnd(), &self );
283 ::SetWindowPos( item(IDC_STATUSBAR), NULL, sbar.left,
284 self.bottom - (sbar.bottom-sbar.top),
285 0, 0, SWP_NOSIZE|SWP_NOOWNERZORDER|SWP_NOZORDER );
286 }
287 break;
288
289 case WM_NOTIFY:
290 if( wp==IDC_FILELIST && m_bAble )
291 {
292 NMHDR* phdr=(NMHDR*)lp;
293 if( phdr->code==LVN_BEGINDRAG || phdr->code==LVN_BEGINRDRAG )
294 {
295 if( setSelection() )
296 kiDropSource::DnD( this, DROPEFFECT_COPY );
297 return TRUE;
298 }
299 else if( phdr->code==LVN_COLUMNCLICK )
300 DoSort( ((NMLISTVIEW*)lp)->iSubItem );
301 else if( phdr->code==NM_DBLCLK )
302 sendMsg( WM_COMMAND, IDC_SHOW );
303 else if( phdr->code==NM_RCLICK )
304 {
305 if( setSelection() )
306 DoRMenu();
307 }
308 }
309 break;
310
311 case WM_COMMAND:
312 switch( LOWORD(wp) )
313 {
314 case IDC_SELECTINV: // 選択反転
315 {
316 LVITEM item;
317 item.mask = LVIF_STATE;
318 item.stateMask = LVIS_SELECTED;
319 int j,m=sendMsgToItem( IDC_FILELIST, LVM_GETITEMCOUNT );
320 for( j=0; j!=m; j++ )
321 {
322 item.state = ~sendMsgToItem( IDC_FILELIST, LVM_GETITEMSTATE, j, LVIS_SELECTED );
323 sendMsgToItem( IDC_FILELIST, LVM_SETITEMSTATE, j, (LPARAM)&item );
324 }
325 ::SetFocus( this->item(IDC_FILELIST) );
326 }
327 return TRUE;
328
329 case IDC_REF: // 解凍先設定
330 kiSUtil::getFolderDlgOfEditBox( item(IDC_DDIR), hwnd(), kiStr().loadRsrc(IDS_CHOOSEDIR) );
331 return TRUE;
332
333 case IDC_MELTEACH: // 一部解凍
334 if( setSelection() )
335 {
336 setdir();
337 int result = m_pArc->melt( m_fname, m_ddir, &m_files );
338 if( result<0x8000 )
339 myapp().open_folder( m_ddir, 1 );
340 else if( result != 0x8020 )
341 {
342 char str[255];
343 wsprintf( str, "%s\nError No: [%x]",
344 (const char*)kiStr().loadRsrc( IDS_M_ERROR ), result );
345 app()->msgBox( str );
346 }
347 kiSUtil::switchCurDirToExeDir(); // 念のため
348 }
349 return TRUE;
350
351 case IDC_SHOW: // 表示
352 if( setSelection() )
353 {
354 int assocCnt = hlp_cnt_check();
355 if( 0x8000 > m_pArc->melt( m_fname, m_tdir, &m_files ) )
356 {
357 if( assocCnt != -1 )
358 m_files[assocCnt].selected = false;
359 for( unsigned i=0; i!=m_files.len(); i++ )
360 if( m_files[i].selected )
361 {
362 kiPath tmp(m_tdir);
363 char yen[MAX_PATH];
364 ki_strcpy( yen, m_files[i].inf.szFileName );
365 for( char* p=yen; *p; p=kiStr::next(p) )
366 if( *p=='/' )
367 *p = '\\';
368 tmp += yen;
369 ::ShellExecute( hwnd(), NULL, tmp, NULL, m_tdir, SW_SHOWDEFAULT );
370 }
371 }
372 kiSUtil::switchCurDirToExeDir(); // 念のため
373 }
374 return TRUE;
375 }
376 }
377 return FALSE;
378 }
379
380 int CArcViewDlg::hlp_cnt_check()
381 {
382 // 一個目の選択済みファイルが .hlp か否か
383 for( unsigned i=0; i!=m_files.len(); i++ )
384 if( m_files[i].selected )
385 break;
386 if( i==m_files.len() )
387 return -1;
388 int x = kiPath::ext(m_files[i].inf.szFileName)-m_files[i].inf.szFileName;
389 if( 0!=ki_strcmpi( "hlp", m_files[i].inf.szFileName+x ) )
390 return -1;
391
392 // .cnt のファイル名
393 char cntpath[FNAME_MAX32];
394 ki_strcpy( cntpath, m_files[i].inf.szFileName );
395 cntpath[x]='c', cntpath[x+1]='n', cntpath[x+2]='t';
396
397 // .cntも一時的に選択する
398 for( i=0; i!=m_files.len(); i++ )
399 if( 0==ki_strcmpi( cntpath, m_files[i].inf.szFileName ) )
400 {
401 if( m_files[i].selected )
402 return -1;
403 m_files[i].selected = true;
404 return i;
405 }
406 return -1;
407 }
408
409 int CALLBACK CArcViewDlg::lv_compare( LPARAM p1, LPARAM p2, LPARAM type )
410 {
411 bool rev = false;
412 if( type>=10000 )
413 rev=true, type-=10000;
414 int ans = 0;
415
416 INDIVIDUALINFO *a1=&((arcfile*)p1)->inf, *a2=&((arcfile*)p2)->inf;
417 switch( type )
418 {
419 case 0: //NAME
420 ans = ::lstrcmp( kiPath::name(a1->szFileName),
421 kiPath::name(a2->szFileName) );
422 break;
423 case 1: //SIZE
424 ans = (signed)a1->dwOriginalSize - (signed)a2->dwOriginalSize;
425 break;
426 case 2: //DATE,TIME
427 ans = (signed)a1->wDate - (signed)a2->wDate;
428 if( ans==0 )
429 ans = (signed)a1->wTime - (signed)a2->wTime;
430 break;
431 case 3:{//RATIO
432 int cr1, cr2;
433 if( a1->dwOriginalSize==0 ) cr1=100;
434 else if( a1->dwCompressedSize==0 ) cr1=-1;
435 else cr1 = (a1->dwCompressedSize*100)/(a1->dwOriginalSize);
436 if( a2->dwOriginalSize==0 ) cr2=100;
437 else if( a2->dwCompressedSize==0 ) cr2=-1;
438 else cr2 = (int)((((__int64)a2->dwCompressedSize)*100)/(a2->dwOriginalSize));
439 ans = cr1 - cr2;
440 }break;
441 case 4: //METHOD
442 ans = ::lstrcmp( a1->szMode, a2->szMode );
443 break;
444 case 5:{//PATH
445 kiPath pt1(a1->szFileName), pt2(a2->szFileName);
446 pt1.beDirOnly(), pt2.beDirOnly();
447 ans = ::lstrcmp( pt1, pt2 );
448 }break;
449 }
450
451 return rev ? -ans : ans;
452 }
453
454 void CArcViewDlg::DoSort( int col )
455 {
456 WPARAM p = col + (m_bSmallFirst[col] ? 0 : 10000);
457 sendMsgToItem( IDC_FILELIST, LVM_SORTITEMS, p, (LPARAM)lv_compare );
458 m_bSmallFirst[col] = !m_bSmallFirst[col];
459 }
460
461 void CArcViewDlg::GenerateDirMenu( HMENU m, int& id, StrArray* sx, const kiPath& pth )
462 {
463 // フォルダ内リストアップ
464 kiFindFile ff;
465 ff.begin( kiPath(pth)+="*" );
466 for( WIN32_FIND_DATA fd; ff.next(&fd); )
467 if( fd.cFileName[0]!='.'
468 && !(fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) )
469 {
470 kiPath fullpath(pth); fullpath+=fd.cFileName;
471 const int pID=id;
472 MENUITEMINFO mi = { sizeof(MENUITEMINFO) };
473
474 if( fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
475 {
476 // 再帰的に
477 mi.fMask = MIIM_SUBMENU | 0x00000040;// (MIIM_STRING)
478 mi.hSubMenu = ::CreatePopupMenu();
479 GenerateDirMenu( mi.hSubMenu, id, sx,
480 kiPath(kiPath(fullpath)+="\\") );
481 }
482 else
483 {
484 const char* ext = kiPath::ext(fd.cFileName);
485 if( ::lstrlen(ext) > 4 ) continue;
486 if( 0==::lstrcmpi(ext,"lnk") )
487 *const_cast<char*>(ext-1) = '\0';
488 mi.fMask = MIIM_ID | 0x00000040;// (MIIM_STRING)
489 mi.wID = id++;
490 sx->add( fullpath );
491 }
492
493 mi.dwTypeData = const_cast<char*>((const char*)fd.cFileName);
494 mi.cch = ::lstrlen(fd.cFileName);
495 ::InsertMenuItem( m, pID, FALSE, &mi );
496 }
497 }
498
499 void CArcViewDlg::DoRMenu()
500 {
501 // メニュー作成
502 HMENU m = ::CreatePopupMenu();
503 POINT pt; ::GetCursorPos( &pt );
504 const int IDSTART = 128;
505
506 // フォルダの中身をリストアップしつつメニューに追加
507 int id = IDSTART;
508 StrArray lst;
509 GenerateDirMenu( m, id, &lst, kiPath(CSIDL_SENDTO) );
510
511 // メニュー表示
512 id = ::TrackPopupMenu( m,
513 TPM_LEFTALIGN|TPM_TOPALIGN|TPM_RETURNCMD|TPM_NONOTIFY,
514 pt.x, pt.y, 0, hwnd(), NULL );
515 ::DestroyMenu( m );
516
517 // 結果処理
518 if( id != 0 )
519 {
520 kiStr cmd;
521 if( 0x8000>m_pArc->melt( m_fname, m_tdir, &m_files ) )
522 {
523 for( UINT i=0; i!=m_files.len(); i++ )
524 if( m_files[i].selected )
525 {
526 cmd += "\"";
527 cmd += m_tdir;
528 const char* buf = m_files[i].inf.szFileName;
529 for( int k=0; buf[k]; ++k )
530 cmd += ( buf[k]=='/' ? '\\' : buf[k] );
531 cmd += "\" ";
532 }
533 ShellExecute(hwnd(),NULL,lst[id-IDSTART],cmd,NULL,SW_SHOW);
534 }
535 }
536 }
537