1 /* 2 * Copyright 2003, 2004, 2005 Martin Fuchs 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19 20 // 21 // Explorer clone 22 // 23 // pane.cpp 24 // 25 // Martin Fuchs, 23.07.2003 26 // 27 28 29 #include <precomp.h> 30 31 enum IMAGE { 32 IMG_NONE=-1, IMG_FILE=0, IMG_DOCUMENT, IMG_EXECUTABLE, 33 IMG_FOLDER, IMG_OPEN_FOLDER, IMG_FOLDER_PLUS,IMG_OPEN_PLUS, IMG_OPEN_MINUS, 34 IMG_FOLDER_UP, IMG_FOLDER_CUR 35 }; 36 37 38 #define IMAGE_WIDTH 16 39 #define IMAGE_HEIGHT 13 40 41 42 static const TCHAR* g_pos_names[COLUMNS] = { 43 TEXT(""), /* symbol */ 44 TEXT("Name"), 45 TEXT("Type"), 46 TEXT("Size"), 47 TEXT("CDate"), 48 TEXT("ADate"), 49 TEXT("MDate"), 50 TEXT("Index/Inode"), 51 TEXT("Links"), 52 TEXT("Attributes"), 53 TEXT("Security"), 54 TEXT("Content") 55 }; 56 57 static const int g_pos_align[] = { 58 0, 59 HDF_LEFT, /* Name */ 60 HDF_LEFT, /* Type */ 61 HDF_RIGHT, /* Size */ 62 HDF_LEFT, /* CDate */ 63 HDF_LEFT, /* ADate */ 64 HDF_LEFT, /* MDate */ 65 HDF_LEFT, /* Index */ 66 HDF_RIGHT, /* Links */ 67 HDF_CENTER, /* Attributes */ 68 HDF_LEFT, /* Security */ 69 HDF_LEFT /* Content / Description */ 70 }; 71 72 73 Pane::Pane(HWND hparent, int id, int id_header, Entry* root, bool treePane, int visible_cols) 74 : super(CreateWindow(TEXT("ListBox"), TEXT(""), WS_CHILD|WS_VISIBLE|WS_HSCROLL|WS_VSCROLL| 75 LBS_DISABLENOSCROLL|LBS_NOINTEGRALHEIGHT|LBS_OWNERDRAWFIXED|LBS_NOTIFY, 76 0, 0, 0, 0, hparent, (HMENU)id, g_Globals._hInstance, 0)), 77 _root(root), 78 _visible_cols(visible_cols), 79 _treePane(treePane) 80 { 81 // insert entries into listbox 82 Entry* entry = _root; 83 84 if (entry) 85 insert_entries(entry); 86 87 init(); 88 89 create_header(hparent, id_header); 90 } 91 92 Pane::~Pane() 93 { 94 ImageList_Destroy(_himl); 95 } 96 97 98 LRESULT Pane::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) 99 { 100 switch(nmsg) { 101 case WM_HSCROLL: 102 set_header(); 103 break; 104 105 case WM_SETFOCUS: { 106 FileChildWindow* child = (FileChildWindow*) SendMessage(GetParent(_hwnd), PM_GET_FILEWND_PTR, 0, 0); 107 108 child->set_focus_pane(this); 109 ListBox_SetSel(_hwnd, TRUE, 1); 110 /*@todo check menu items */ 111 break;} 112 113 case WM_KEYDOWN: { 114 FileChildWindow* child = (FileChildWindow*) SendMessage(GetParent(_hwnd), PM_GET_FILEWND_PTR, 0, 0); 115 116 if (wparam == VK_TAB) { 117 /*@todo SetFocus(g_Globals.hdrivebar) */ 118 child->switch_focus_pane(); 119 } 120 break;} 121 } 122 123 return super::WndProc(nmsg, wparam, lparam); 124 } 125 126 127 bool Pane::create_header(HWND hparent, int id) 128 { 129 HWND hwnd = CreateWindow(WC_HEADER, 0, WS_CHILD|WS_VISIBLE|HDS_HORZ/*@todo |HDS_BUTTONS + sort orders*/, 130 0, 0, 0, 0, hparent, (HMENU)id, g_Globals._hInstance, 0); 131 if (!hwnd) 132 return false; 133 134 SetWindowFont(hwnd, GetStockFont(DEFAULT_GUI_FONT), FALSE); 135 136 HD_ITEM hdi; 137 138 hdi.mask = HDI_TEXT|HDI_WIDTH|HDI_FORMAT; 139 140 for(int idx=0; idx<COLUMNS; idx++) { 141 hdi.pszText = (TCHAR*)g_pos_names[idx]; 142 hdi.fmt = HDF_STRING | g_pos_align[idx]; 143 hdi.cxy = _widths[idx]; 144 Header_InsertItem(hwnd, idx, &hdi); 145 } 146 147 _hwndHeader = hwnd; 148 149 return true; 150 } 151 152 153 void Pane::init() 154 { 155 _himl = ImageList_LoadBitmap(g_Globals._hInstance, MAKEINTRESOURCE(IDB_IMAGES), 16, 0, RGB(0,255,0)); 156 157 SetWindowFont(_hwnd, _out_wrkr._hfont, FALSE); 158 159 // read the color for compressed files from registry 160 HKEY hkeyExplorer = 0; 161 DWORD len = sizeof(_clrCompressed); 162 163 if (RegOpenKey(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer"), &hkeyExplorer) || 164 RegQueryValueEx(hkeyExplorer, TEXT("AltColor"), 0, NULL, (LPBYTE)&_clrCompressed, &len) || len!=sizeof(_clrCompressed)) 165 _clrCompressed = RGB(0,0,255); 166 167 if (hkeyExplorer) 168 RegCloseKey(hkeyExplorer); 169 170 // calculate column widths 171 _out_wrkr.init_output(_hwnd); 172 calc_widths(true); 173 } 174 175 176 // calculate prefered width for all visible columns 177 178 bool Pane::calc_widths(bool anyway) 179 { 180 int col, x, cx, spc=3*_out_wrkr._spaceSize.cx; 181 int entries = ListBox_GetCount(_hwnd); 182 int orgWidths[COLUMNS]; 183 int orgPositions[COLUMNS+1]; 184 HFONT hfontOld; 185 HDC hdc; 186 int cnt; 187 188 if (!anyway) { 189 memcpy(orgWidths, _widths, sizeof(orgWidths)); 190 memcpy(orgPositions, _positions, sizeof(orgPositions)); 191 } 192 193 for(col=0; col<COLUMNS; col++) 194 _widths[col] = 0; 195 196 hdc = GetDC(_hwnd); 197 hfontOld = SelectFont(hdc, _out_wrkr._hfont); 198 199 for(cnt=0; cnt<entries; cnt++) { 200 Entry* entry = (Entry*) ListBox_GetItemData(_hwnd, cnt); 201 202 DRAWITEMSTRUCT dis; 203 204 dis.CtlType = 0; 205 dis.CtlID = 0; 206 dis.itemID = 0; 207 dis.itemAction = 0; 208 dis.itemState = 0; 209 dis.hwndItem = _hwnd; 210 dis.hDC = hdc; 211 dis.rcItem.left = 0; 212 dis.rcItem.top = 0; 213 dis.rcItem.right = 0; 214 dis.rcItem.bottom = 0; 215 /*dis.itemData = 0; */ 216 217 draw_item(&dis, entry, COLUMNS); 218 } 219 220 SelectObject(hdc, hfontOld); 221 ReleaseDC(_hwnd, hdc); 222 223 x = 0; 224 for(col=0; col<COLUMNS; col++) { 225 _positions[col] = x; 226 cx = _widths[col]; 227 228 if (cx) { 229 cx += spc; 230 231 if (cx < IMAGE_WIDTH) 232 cx = IMAGE_WIDTH; 233 234 _widths[col] = cx; 235 } 236 237 x += cx; 238 } 239 240 _positions[COLUMNS] = x; 241 242 ListBox_SetHorizontalExtent(_hwnd, x); 243 244 // no change? 245 if (!memcmp(orgWidths, _widths, sizeof(orgWidths))) 246 return FALSE; 247 248 // don't move, if only collapsing an entry 249 if (!anyway && _widths[0]<orgWidths[0] && 250 !memcmp(orgWidths+1, _widths+1, sizeof(orgWidths)-sizeof(int))) { 251 _widths[0] = orgWidths[0]; 252 memcpy(_positions, orgPositions, sizeof(orgPositions)); 253 254 return FALSE; 255 } 256 257 InvalidateRect(_hwnd, 0, TRUE); 258 259 return TRUE; 260 } 261 262 263 static void format_date(const FILETIME* ft, TCHAR* buffer, int visible_cols) 264 { 265 SYSTEMTIME systime; 266 FILETIME lft; 267 int len = 0; 268 269 *buffer = TEXT('\0'); 270 271 if (!ft->dwLowDateTime && !ft->dwHighDateTime) 272 return; 273 274 if (!FileTimeToLocalFileTime(ft, &lft)) 275 {err: lstrcpy(buffer,TEXT("???")); return;} 276 277 if (!FileTimeToSystemTime(&lft, &systime)) 278 goto err; 279 280 if (visible_cols & COL_DATE) { 281 len = GetDateFormat(LOCALE_USER_DEFAULT, 0, &systime, 0, buffer, BUFFER_LEN); 282 if (!len) 283 goto err; 284 } 285 286 if (visible_cols & COL_TIME) { 287 if (len) 288 buffer[len-1] = ' '; 289 290 buffer[len++] = ' '; 291 292 if (!GetTimeFormat(LOCALE_USER_DEFAULT, 0, &systime, 0, buffer+len, BUFFER_LEN-len)) 293 buffer[len] = TEXT('\0'); 294 } 295 } 296 297 298 void Pane::draw_item(LPDRAWITEMSTRUCT dis, Entry* entry, int calcWidthCol) 299 { 300 TCHAR buffer[BUFFER_LEN]; 301 DWORD attrs; 302 int visible_cols = _visible_cols; 303 COLORREF bkcolor, textcolor; 304 RECT focusRect = dis->rcItem; 305 enum IMAGE img; 306 int img_pos, cx; 307 int col = 0; 308 309 if (entry) { 310 attrs = entry->_data.dwFileAttributes; 311 312 if (attrs & FILE_ATTRIBUTE_DIRECTORY) { 313 if (entry->_data.cFileName[0]==TEXT('.') && entry->_data.cFileName[1]==TEXT('.') 314 && entry->_data.cFileName[2]==TEXT('\0')) 315 img = IMG_FOLDER_UP; 316 else if (entry->_data.cFileName[0]==TEXT('.') && entry->_data.cFileName[1]==TEXT('\0')) 317 img = IMG_FOLDER_CUR; 318 else if ((_treePane && (dis->itemState&ODS_FOCUS))) 319 img = IMG_OPEN_FOLDER; 320 else 321 img = IMG_FOLDER; 322 } else { 323 if (attrs & ATTRIBUTE_EXECUTABLE) 324 img = IMG_EXECUTABLE; 325 else if (entry->_type_name) 326 img = IMG_DOCUMENT; 327 else 328 img = IMG_FILE; 329 } 330 } else { 331 attrs = 0; 332 img = IMG_NONE; 333 } 334 335 if (_treePane) { 336 if (entry) { 337 img_pos = dis->rcItem.left + entry->_level*(IMAGE_WIDTH+_out_wrkr._spaceSize.cx); 338 339 if (calcWidthCol == -1) { 340 int x; 341 int y = dis->rcItem.top + IMAGE_HEIGHT/2; 342 Entry* up; 343 RECT rt_clip; 344 HRGN hrgn_org = CreateRectRgn(0, 0, 0, 0); 345 HRGN hrgn; 346 347 rt_clip.left = dis->rcItem.left; 348 rt_clip.top = dis->rcItem.top; 349 rt_clip.right = dis->rcItem.left+_widths[col]; 350 rt_clip.bottom = dis->rcItem.bottom; 351 352 hrgn = CreateRectRgnIndirect(&rt_clip); 353 354 if (!GetClipRgn(dis->hDC, hrgn_org)) { 355 DeleteObject(hrgn_org); 356 hrgn_org = 0; 357 } 358 359 //HGDIOBJ holdPen = SelectObject(dis->hDC, GetStockObject(BLACK_PEN)); 360 ExtSelectClipRgn(dis->hDC, hrgn, RGN_AND); 361 DeleteObject(hrgn); 362 363 if ((up=entry->_up) != NULL) { 364 MoveToEx(dis->hDC, img_pos-IMAGE_WIDTH/2, y, 0); 365 LineTo(dis->hDC, img_pos-2, y); 366 367 x = img_pos - IMAGE_WIDTH/2; 368 369 do { 370 x -= IMAGE_WIDTH+_out_wrkr._spaceSize.cx; 371 372 if (up->_next) { 373 #ifndef _LEFT_FILES 374 bool following_child = (up->_next->_data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)!=0; // a directory? 375 376 if (!following_child) 377 { 378 for(Entry*n=up->_next; n; n=n->_next) 379 if (n->_down) { // any file with NTFS sub-streams? 380 following_child = true; 381 break; 382 } 383 } 384 if (following_child) 385 #endif 386 { 387 MoveToEx(dis->hDC, x, dis->rcItem.top, 0); 388 LineTo(dis->hDC, x, dis->rcItem.bottom); 389 } 390 } 391 } while((up=up->_up) != NULL); 392 } 393 394 x = img_pos - IMAGE_WIDTH/2; 395 396 MoveToEx(dis->hDC, x, dis->rcItem.top, 0); 397 LineTo(dis->hDC, x, y); 398 399 if (entry->_next) { 400 #ifndef _LEFT_FILES 401 bool following_child = (entry->_next->_data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)!=0; // a directory? 402 403 if (!following_child) 404 { 405 for(Entry*n=entry->_next; n; n=n->_next) 406 if (n->_down) { // any file with NTFS sub-streams? 407 following_child = true; 408 break; 409 } 410 } 411 if (following_child) 412 #endif 413 LineTo(dis->hDC, x, dis->rcItem.bottom); 414 } 415 416 if (entry->_down && entry->_expanded) { 417 x += IMAGE_WIDTH + _out_wrkr._spaceSize.cx; 418 MoveToEx(dis->hDC, x, dis->rcItem.top+IMAGE_HEIGHT, 0); 419 LineTo(dis->hDC, x, dis->rcItem.bottom); 420 } 421 422 SelectClipRgn(dis->hDC, hrgn_org); 423 if (hrgn_org) DeleteObject(hrgn_org); 424 //SelectObject(dis->hDC, holdPen); 425 } else if (calcWidthCol==col || calcWidthCol==COLUMNS) { 426 int right = img_pos + IMAGE_WIDTH - _out_wrkr._spaceSize.cx; 427 428 if (right > _widths[col]) 429 _widths[col] = right; 430 } 431 } else { 432 img_pos = dis->rcItem.left; 433 } 434 } else { 435 img_pos = dis->rcItem.left; 436 437 if (calcWidthCol==col || calcWidthCol==COLUMNS) 438 _widths[col] = IMAGE_WIDTH; 439 } 440 441 if (calcWidthCol == -1) { 442 focusRect.left = img_pos -2; 443 444 if (attrs & FILE_ATTRIBUTE_COMPRESSED) 445 textcolor = _clrCompressed; 446 else 447 textcolor = RGB(0,0,0); 448 449 if (dis->itemState & ODS_FOCUS) { 450 textcolor = GetSysColor(COLOR_HIGHLIGHTTEXT); 451 bkcolor = GetSysColor(COLOR_HIGHLIGHT); 452 } else { 453 bkcolor = GetSysColor(COLOR_WINDOW); 454 } 455 456 HBRUSH hbrush = CreateSolidBrush(bkcolor); 457 FillRect(dis->hDC, &focusRect, hbrush); 458 DeleteObject(hbrush); 459 460 SetBkMode(dis->hDC, TRANSPARENT); 461 SetTextColor(dis->hDC, textcolor); 462 463 cx = _widths[col]; 464 465 if (cx && img!=IMG_NONE) { 466 if (cx > IMAGE_WIDTH) 467 cx = IMAGE_WIDTH; 468 469 if (entry->_icon_id > ICID_NONE) 470 g_Globals._icon_cache.get_icon(entry->_icon_id).draw(dis->hDC, img_pos, dis->rcItem.top, cx, GetSystemMetrics(SM_CYSMICON), bkcolor, 0); 471 else 472 ImageList_DrawEx(_himl, img, dis->hDC, 473 img_pos, dis->rcItem.top, cx, 474 IMAGE_HEIGHT, bkcolor, CLR_DEFAULT, ILD_NORMAL); 475 } 476 } 477 478 if (!entry) 479 return; 480 481 ++col; 482 483 // output file name 484 if (calcWidthCol == -1) 485 _out_wrkr.output_text(dis, _positions, col, entry->_display_name, 0); 486 else if (calcWidthCol==col || calcWidthCol==COLUMNS) 487 calc_width(dis, col, entry->_display_name); 488 ++col; 489 490 // output type/class name 491 if (visible_cols & COL_TYPE) { 492 if (calcWidthCol == -1) 493 _out_wrkr.output_text(dis, _positions, col, entry->_type_name? entry->_type_name: TEXT(""), 0); 494 else if (calcWidthCol==col || calcWidthCol==COLUMNS) 495 calc_width(dis, col, entry->_type_name? entry->_type_name: TEXT("")); 496 } 497 ++col; 498 499 // display file size 500 if (visible_cols & COL_SIZE) { 501 ULONGLONG size = ((ULONGLONG)entry->_data.nFileSizeHigh << 32) | entry->_data.nFileSizeLow; 502 503 _stprintf(buffer, TEXT("%") LONGLONGARG TEXT("d"), size); 504 505 if (calcWidthCol == -1) 506 _out_wrkr.output_number(dis, _positions, col, buffer); 507 else if (calcWidthCol==col || calcWidthCol==COLUMNS) 508 calc_width(dis, col, buffer); ///@todo not in every case time enough 509 } 510 ++col; 511 512 // display file date 513 if (visible_cols & (COL_DATE|COL_TIME)) { 514 format_date(&entry->_data.ftCreationTime, buffer, visible_cols); 515 if (calcWidthCol == -1) 516 _out_wrkr.output_text(dis, _positions, col, buffer, 0); 517 else if (calcWidthCol==col || calcWidthCol==COLUMNS) 518 calc_width(dis, col, buffer); 519 ++col; 520 521 format_date(&entry->_data.ftLastAccessTime, buffer, visible_cols); 522 if (calcWidthCol == -1) 523 _out_wrkr.output_text(dis,_positions, col, buffer, 0); 524 else if (calcWidthCol==col || calcWidthCol==COLUMNS) 525 calc_width(dis, col, buffer); 526 ++col; 527 528 format_date(&entry->_data.ftLastWriteTime, buffer, visible_cols); 529 if (calcWidthCol == -1) 530 _out_wrkr.output_text(dis, _positions, col, buffer, 0); 531 else if (calcWidthCol==col || calcWidthCol==COLUMNS) 532 calc_width(dis, col, buffer); 533 ++col; 534 } else 535 col += 3; 536 537 if (entry->_bhfi_valid) { 538 ULONGLONG index = ((ULONGLONG)entry->_bhfi.nFileIndexHigh << 32) | entry->_bhfi.nFileIndexLow; 539 540 if (visible_cols & COL_INDEX) { 541 _stprintf(buffer, TEXT("%") LONGLONGARG TEXT("X"), index); 542 543 if (calcWidthCol == -1) 544 _out_wrkr.output_text(dis, _positions, col, buffer, DT_RIGHT); 545 else if (calcWidthCol==col || calcWidthCol==COLUMNS) 546 calc_width(dis, col, buffer); 547 548 ++col; 549 } 550 551 if (visible_cols & COL_LINKS) { 552 wsprintf(buffer, TEXT("%d"), entry->_bhfi.nNumberOfLinks); 553 554 if (calcWidthCol == -1) 555 _out_wrkr.output_text(dis, _positions, col, buffer, DT_RIGHT); 556 else if (calcWidthCol==col || calcWidthCol==COLUMNS) 557 calc_width(dis, col, buffer); 558 559 ++col; 560 } 561 } else 562 col += 2; 563 564 // show file attributes 565 if (visible_cols & COL_ATTRIBUTES) { 566 lstrcpy(buffer, TEXT(" \t \t \t \t \t \t \t \t \t \t \t \t \t \t ")); 567 568 if (attrs & FILE_ATTRIBUTE_NORMAL) buffer[ 0] = 'N'; 569 else { 570 if (attrs & FILE_ATTRIBUTE_READONLY) buffer[ 2] = 'R'; 571 if (attrs & FILE_ATTRIBUTE_HIDDEN) buffer[ 4] = 'H'; 572 if (attrs & FILE_ATTRIBUTE_SYSTEM) buffer[ 6] = 'S'; 573 if (attrs & FILE_ATTRIBUTE_ARCHIVE) buffer[ 8] = 'A'; 574 if (attrs & FILE_ATTRIBUTE_COMPRESSED) buffer[10] = 'C'; 575 if (attrs & FILE_ATTRIBUTE_DIRECTORY) buffer[12] = 'D'; 576 if (attrs & FILE_ATTRIBUTE_ENCRYPTED) buffer[14] = 'E'; 577 if (attrs & FILE_ATTRIBUTE_TEMPORARY) buffer[16] = 'T'; 578 if (attrs & FILE_ATTRIBUTE_SPARSE_FILE) buffer[18] = 'P'; 579 if (attrs & FILE_ATTRIBUTE_REPARSE_POINT) buffer[20] = 'Q'; 580 if (attrs & FILE_ATTRIBUTE_OFFLINE) buffer[22] = 'O'; 581 if (attrs & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) buffer[24] = 'X'; 582 if (attrs & ATTRIBUTE_EXECUTABLE) buffer[26] = 'x'; 583 if (attrs & ATTRIBUTE_SYMBOLIC_LINK) buffer[28] = 'L'; 584 } 585 586 if (calcWidthCol == -1) 587 _out_wrkr.output_tabbed_text(dis, _positions, col, buffer); 588 else if (calcWidthCol==col || calcWidthCol==COLUMNS) 589 calc_tabbed_width(dis, col, buffer); 590 } 591 ++col; 592 593 /*TODO 594 if (flags.security) { 595 DWORD rights = get_access_mask(); 596 597 tcscpy(buffer, TEXT(" \t \t \t \t \t \t \t \t \t \t \t ")); 598 599 if (rights & FILE_READ_DATA) buffer[ 0] = 'R'; 600 if (rights & FILE_WRITE_DATA) buffer[ 2] = 'W'; 601 if (rights & FILE_APPEND_DATA) buffer[ 4] = 'A'; 602 if (rights & FILE_READ_EA) {buffer[6] = 'entry'; buffer[ 7] = 'R';} 603 if (rights & FILE_WRITE_EA) {buffer[9] = 'entry'; buffer[10] = 'W';} 604 if (rights & FILE_EXECUTE) buffer[12] = 'X'; 605 if (rights & FILE_DELETE_CHILD) buffer[14] = 'D'; 606 if (rights & FILE_READ_ATTRIBUTES) {buffer[16] = 'a'; buffer[17] = 'R';} 607 if (rights & FILE_WRITE_ATTRIBUTES) {buffer[19] = 'a'; buffer[20] = 'W';} 608 if (rights & WRITE_DAC) buffer[22] = 'C'; 609 if (rights & WRITE_OWNER) buffer[24] = 'O'; 610 if (rights & SYNCHRONIZE) buffer[26] = 'S'; 611 612 output_text(dis, col++, buffer, DT_LEFT, 3, psize); 613 } 614 615 if (flags.description) { 616 get_description(buffer); 617 output_text(dis, col++, buffer, 0, psize); 618 } 619 */ 620 ++col; 621 622 // output content / symbolic link target / comment 623 if (visible_cols & COL_CONTENT) { 624 if (calcWidthCol == -1) 625 _out_wrkr.output_text(dis, _positions, col, entry->_content? entry->_content: TEXT(""), 0); 626 else if (calcWidthCol==col || calcWidthCol==COLUMNS) 627 calc_width(dis, col, entry->_content? entry->_content: TEXT("")); 628 } 629 } 630 631 632 void Pane::calc_width(LPDRAWITEMSTRUCT dis, int col, LPCTSTR str) 633 { 634 RECT rt = {0, 0, 0, 0}; 635 636 DrawText(dis->hDC, (LPTSTR)str, -1, &rt, DT_CALCRECT|DT_SINGLELINE|DT_NOPREFIX); 637 638 if (rt.right > _widths[col]) 639 _widths[col] = rt.right; 640 } 641 642 void Pane::calc_tabbed_width(LPDRAWITEMSTRUCT dis, int col, LPCTSTR str) 643 { 644 RECT rt = {0, 0, 0, 0}; 645 646 /* DRAWTEXTPARAMS dtp = {sizeof(DRAWTEXTPARAMS), 2}; 647 DrawTextEx(dis->hDC, (LPTSTR)str, -1, &rt, DT_CALCRECT|DT_SINGLELINE|DT_NOPREFIX|DT_EXPANDTABS|DT_TABSTOP, &dtp);*/ 648 649 DrawText(dis->hDC, (LPTSTR)str, -1, &rt, DT_CALCRECT|DT_SINGLELINE|DT_EXPANDTABS|DT_TABSTOP|(2<<8)); 650 651 if (rt.right > _widths[col]) 652 _widths[col] = rt.right; 653 } 654 655 656 // insert listbox entries after index idx 657 658 int Pane::insert_entries(Entry* dir, int idx) 659 { 660 Entry* entry = dir; 661 662 if (!entry) 663 return idx; 664 665 for(; entry; entry=entry->_next) { 666 #ifndef _LEFT_FILES 667 if (_treePane && 668 !(entry->_data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) && // not a directory? 669 !entry->_down) // not a file with NTFS sub-streams? 670 continue; 671 #endif 672 673 // don't display entries "." and ".." in the left pane 674 if (_treePane && (entry->_data.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) 675 && entry->_data.cFileName[0]==TEXT('.')) 676 if (entry->_data.cFileName[1]==TEXT('\0') || 677 (entry->_data.cFileName[1]==TEXT('.') && entry->_data.cFileName[2]==TEXT('\0'))) 678 continue; 679 680 if (idx != -1) 681 ++idx; 682 683 ListBox_InsertItemData(_hwnd, idx, entry); 684 685 if (_treePane && entry->_expanded) 686 idx = insert_entries(entry->_down, idx); 687 } 688 689 return idx; 690 } 691 692 693 void Pane::set_header() 694 { 695 HD_ITEM item; 696 int scroll_pos = GetScrollPos(_hwnd, SB_HORZ); 697 int i=0, x=0; 698 699 item.mask = HDI_WIDTH; 700 item.cxy = 0; 701 702 for(; i<COLUMNS; i++) { 703 if (x + _widths[i] >= scroll_pos) 704 break; 705 706 x += _widths[i]; 707 Header_SetItem(_hwndHeader, i, &item); 708 } 709 710 if (i < COLUMNS) { 711 x += _widths[i]; 712 item.cxy = x - scroll_pos; 713 Header_SetItem(_hwndHeader, i++, &item); 714 715 for(; i<COLUMNS; i++) { 716 item.cxy = _widths[i]; 717 x += _widths[i]; 718 Header_SetItem(_hwndHeader, i, &item); 719 } 720 } 721 } 722 723 724 // calculate one prefered column width 725 726 void Pane::calc_single_width(int col) 727 { 728 HFONT hfontOld; 729 int x, cx; 730 int cnt; 731 HDC hdc; 732 733 int entries = ListBox_GetCount(_hwnd); 734 735 _widths[col] = 0; 736 737 hdc = GetDC(_hwnd); 738 hfontOld = SelectFont(hdc, _out_wrkr._hfont); 739 740 for(cnt=0; cnt<entries; cnt++) { 741 Entry* entry = (Entry*) ListBox_GetItemData(_hwnd, cnt); 742 743 DRAWITEMSTRUCT dis; 744 745 dis.CtlType = 0; 746 dis.CtlID = 0; 747 dis.itemID = 0; 748 dis.itemAction = 0; 749 dis.itemState = 0; 750 dis.hwndItem = _hwnd; 751 dis.hDC = hdc; 752 dis.rcItem.left = 0; 753 dis.rcItem.top = 0; 754 dis.rcItem.right = 0; 755 dis.rcItem.bottom = 0; 756 /*dis.itemData = 0; */ 757 758 draw_item(&dis, entry, col); 759 } 760 761 SelectObject(hdc, hfontOld); 762 ReleaseDC(_hwnd, hdc); 763 764 cx = _widths[col]; 765 766 if (cx) { 767 cx += 3*_out_wrkr._spaceSize.cx; 768 769 if (cx < IMAGE_WIDTH) 770 cx = IMAGE_WIDTH; 771 } 772 773 _widths[col] = cx; 774 775 x = _positions[col] + cx; 776 777 for(; col<COLUMNS; col++) { 778 _positions[col+1] = x; 779 x += _widths[col]; 780 } 781 782 ListBox_SetHorizontalExtent(_hwnd, x); 783 } 784 785 786 int Pane::Notify(int id, NMHDR* pnmh) 787 { 788 switch(pnmh->code) { 789 case HDN_TRACK: 790 case HDN_ENDTRACK: { 791 HD_NOTIFY* phdn = (HD_NOTIFY*) pnmh; 792 int idx = phdn->iItem; 793 int dx = phdn->pitem->cxy - _widths[idx]; 794 int i; 795 796 ClientRect clnt(_hwnd); 797 798 // move immediate to simulate HDS_FULLDRAG (for now [04/2000] not realy needed with WINELIB) 799 Header_SetItem(_hwndHeader, idx, phdn->pitem); 800 801 _widths[idx] += dx; 802 803 for(i=idx; ++i<=COLUMNS; ) 804 _positions[i] += dx; 805 806 { 807 int scroll_pos = GetScrollPos(_hwnd, SB_HORZ); 808 RECT rt_scr; 809 RECT rt_clip; 810 811 rt_scr.left = _positions[idx+1]-scroll_pos; 812 rt_scr.top = 0; 813 rt_scr.right = clnt.right; 814 rt_scr.bottom = clnt.bottom; 815 816 rt_clip.left = _positions[idx]-scroll_pos; 817 rt_clip.top = 0; 818 rt_clip.right = clnt.right; 819 rt_clip.bottom = clnt.bottom; 820 821 if (rt_scr.left < 0) rt_scr.left = 0; 822 if (rt_clip.left < 0) rt_clip.left = 0; 823 824 ScrollWindowEx(_hwnd, dx, 0, &rt_scr, &rt_clip, 0, 0, SW_INVALIDATE); 825 826 rt_clip.right = _positions[idx+1]; 827 RedrawWindow(_hwnd, &rt_clip, 0, RDW_INVALIDATE|RDW_UPDATENOW); 828 829 if (pnmh->code == HDN_ENDTRACK) { 830 ListBox_SetHorizontalExtent(_hwnd, _positions[COLUMNS]); 831 832 if (GetScrollPos(_hwnd, SB_HORZ) != scroll_pos) 833 set_header(); 834 } 835 } 836 837 return 0; 838 } 839 840 case HDN_DIVIDERDBLCLICK: { 841 HD_NOTIFY* phdn = (HD_NOTIFY*) pnmh; 842 HD_ITEM item; 843 844 calc_single_width(phdn->iItem); 845 item.mask = HDI_WIDTH; 846 item.cxy = _widths[phdn->iItem]; 847 848 Header_SetItem(_hwndHeader, phdn->iItem, &item); 849 InvalidateRect(_hwnd, 0, TRUE); 850 break;} 851 852 default: 853 return super::Notify(id, pnmh); 854 } 855 856 return 0; 857 } 858 859 860 OutputWorker::OutputWorker() 861 { 862 _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")); 863 } 864 865 void OutputWorker::init_output(HWND hwnd) 866 { 867 TCHAR b[16]; 868 869 WindowCanvas canvas(hwnd); 870 871 if (GetNumberFormat(LOCALE_USER_DEFAULT, 0, TEXT("1000"), 0, b, 16) > 4) 872 _num_sep = b[1]; 873 else 874 _num_sep = TEXT('.'); 875 876 FontSelection font(canvas, _hfont); 877 GetTextExtentPoint32(canvas, TEXT(" "), 1, &_spaceSize); 878 } 879 880 881 void OutputWorker::output_text(LPDRAWITEMSTRUCT dis, int* positions, int col, LPCTSTR str, DWORD flags) 882 { 883 int x = dis->rcItem.left; 884 RECT rt; 885 886 rt.left = x+positions[col]+_spaceSize.cx; 887 rt.top = dis->rcItem.top; 888 rt.right = x+positions[col+1]-_spaceSize.cx; 889 rt.bottom = dis->rcItem.bottom; 890 891 DrawText(dis->hDC, (LPTSTR)str, -1, &rt, DT_SINGLELINE|DT_NOPREFIX|flags); 892 } 893 894 void OutputWorker::output_tabbed_text(LPDRAWITEMSTRUCT dis, int* positions, int col, LPCTSTR str) 895 { 896 int x = dis->rcItem.left; 897 RECT rt; 898 899 rt.left = x+positions[col]+_spaceSize.cx; 900 rt.top = dis->rcItem.top; 901 rt.right = x+positions[col+1]-_spaceSize.cx; 902 rt.bottom = dis->rcItem.bottom; 903 904 /* DRAWTEXTPARAMS dtp = {sizeof(DRAWTEXTPARAMS), 2}; 905 DrawTextEx(dis->hDC, (LPTSTR)str, -1, &rt, DT_SINGLELINE|DT_NOPREFIX|DT_EXPANDTABS|DT_TABSTOP, &dtp);*/ 906 907 DrawText(dis->hDC, (LPTSTR)str, -1, &rt, DT_SINGLELINE|DT_EXPANDTABS|DT_TABSTOP|(2<<8)); 908 } 909 910 void OutputWorker::output_number(LPDRAWITEMSTRUCT dis, int* positions, int col, LPCTSTR str) 911 { 912 int x = dis->rcItem.left; 913 RECT rt; 914 LPCTSTR s = str; 915 TCHAR b[128]; 916 LPTSTR d = b; 917 int pos; 918 919 rt.left = x+positions[col]+_spaceSize.cx; 920 rt.top = dis->rcItem.top; 921 rt.right = x+positions[col+1]-_spaceSize.cx; 922 rt.bottom = dis->rcItem.bottom; 923 924 if (*s) 925 *d++ = *s++; 926 927 // insert number separator characters 928 pos = lstrlen(s) % 3; 929 930 while(*s) 931 if (pos--) 932 *d++ = *s++; 933 else { 934 *d++ = _num_sep; 935 pos = 3; 936 } 937 938 DrawText(dis->hDC, b, d-b, &rt, DT_RIGHT|DT_SINGLELINE|DT_NOPREFIX|DT_END_ELLIPSIS); 939 } 940 941 942 BOOL Pane::command(UINT cmd) 943 { 944 switch(cmd) { 945 case ID_VIEW_NAME: 946 if (_visible_cols) { 947 _visible_cols = 0; 948 calc_widths(true); 949 set_header(); 950 InvalidateRect(_hwnd, 0, TRUE); 951 MenuInfo* menu_info = Frame_GetMenuInfo(GetParent(_hwnd)); 952 if (menu_info) { 953 CheckMenuItem(menu_info->_hMenuView, ID_VIEW_NAME, MF_BYCOMMAND|MF_CHECKED); 954 CheckMenuItem(menu_info->_hMenuView, ID_VIEW_ALL_ATTRIBUTES, MF_BYCOMMAND); 955 CheckMenuItem(menu_info->_hMenuView, ID_VIEW_SELECTED_ATTRIBUTES, MF_BYCOMMAND); 956 } 957 } 958 break; 959 960 case ID_VIEW_ALL_ATTRIBUTES: 961 if (_visible_cols != COL_ALL) { 962 _visible_cols = COL_ALL; 963 calc_widths(true); 964 set_header(); 965 InvalidateRect(_hwnd, 0, TRUE); 966 MenuInfo* menu_info = Frame_GetMenuInfo(GetParent(_hwnd)); 967 if (menu_info) { 968 CheckMenuItem(menu_info->_hMenuView, ID_VIEW_NAME, MF_BYCOMMAND); 969 CheckMenuItem(menu_info->_hMenuView, ID_VIEW_ALL_ATTRIBUTES, MF_BYCOMMAND|MF_CHECKED); 970 CheckMenuItem(menu_info->_hMenuView, ID_VIEW_SELECTED_ATTRIBUTES, MF_BYCOMMAND); 971 } 972 } 973 break; 974 975 case ID_PREFERED_SIZES: { 976 calc_widths(true); 977 set_header(); 978 InvalidateRect(_hwnd, 0, TRUE); 979 break;} 980 981 /*@todo more command ids... */ 982 983 default: 984 return FALSE; 985 } 986 987 return TRUE; 988 } 989 990 MainFrameBase* Pane::get_frame() 991 { 992 HWND owner = GetParent(_hwnd); 993 994 return (MainFrameBase*)owner; 995 } 996