BOOLEAN PhHandleTreeNewColumnMenu( __inout PPH_TN_COLUMN_MENU_DATA Data ) { if (!Data->Selection) return FALSE; switch (Data->Selection->Id) { case PH_TN_COLUMN_MENU_SIZE_COLUMN_TO_FIT_ID: { if (Data->MouseEvent && Data->MouseEvent->Column) { TreeNew_AutoSizeColumn(Data->TreeNewHandle, Data->MouseEvent->Column->Id); } } break; case PH_TN_COLUMN_MENU_SIZE_ALL_COLUMNS_TO_FIT_ID: { ULONG maxId; ULONG id; maxId = TreeNew_GetMaxId(Data->TreeNewHandle); id = 0; while (id <= maxId) { TreeNew_AutoSizeColumn(Data->TreeNewHandle, id); id++; } } break; case PH_TN_COLUMN_MENU_HIDE_COLUMN_ID: { PH_TREENEW_COLUMN column; if (Data->MouseEvent && Data->MouseEvent->Column && !Data->MouseEvent->Column->Fixed) { column.Id = Data->MouseEvent->Column->Id; column.Visible = FALSE; TreeNew_SetColumn(Data->TreeNewHandle, TN_COLUMN_FLAG_VISIBLE, &column); PhpEnsureValidSortColumnTreeNew(Data->TreeNewHandle, Data->DefaultSortColumn, Data->DefaultSortOrder); InvalidateRect(Data->TreeNewHandle, NULL, FALSE); } } break; case PH_TN_COLUMN_MENU_CHOOSE_COLUMNS_ID: { PhShowChooseColumnsDialog(Data->TreeNewHandle, Data->TreeNewHandle, PH_CONTROL_TYPE_TREE_NEW); PhpEnsureValidSortColumnTreeNew(Data->TreeNewHandle, Data->DefaultSortColumn, Data->DefaultSortOrder); } break; default: return FALSE; } Data->ProcessedId = Data->Selection->Id; return TRUE; }
BOOLEAN PhCmLoadSettingsEx( _In_ HWND TreeNewHandle, _In_opt_ PPH_CM_MANAGER Manager, _In_ ULONG Flags, _In_ PPH_STRINGREF Settings, _In_opt_ PPH_STRINGREF SortSettings ) { BOOLEAN result = FALSE; PH_STRINGREF columnPart; PH_STRINGREF remainingColumnPart; PH_STRINGREF valuePart; PH_STRINGREF subPart; ULONG64 integer; ULONG total; BOOLEAN hasFixedColumn; ULONG count; ULONG i; PPH_HASHTABLE columnHashtable; PH_HASHTABLE_ENUM_CONTEXT enumContext; PPH_KEY_VALUE_PAIR pair; LONG orderArray[PH_CM_ORDER_LIMIT]; LONG maxOrder; if (Settings->Length != 0) { columnHashtable = PhCreateSimpleHashtable(20); remainingColumnPart = *Settings; while (remainingColumnPart.Length != 0) { PPH_TREENEW_COLUMN column; ULONG id; ULONG displayIndex; ULONG width; PhSplitStringRefAtChar(&remainingColumnPart, '|', &columnPart, &remainingColumnPart); if (columnPart.Length != 0) { // Id PhSplitStringRefAtChar(&columnPart, ',', &valuePart, &columnPart); if (valuePart.Length == 0) goto CleanupExit; if (valuePart.Buffer[0] == '+') { PH_STRINGREF pluginName; ULONG subId; PPH_CM_COLUMN cmColumn; // This is a plugin-owned column. if (!Manager) continue; if (!PhEmParseCompoundId(&valuePart, &pluginName, &subId)) continue; cmColumn = PhCmFindColumn(Manager, &pluginName, subId); if (!cmColumn) continue; // can't find the column, skip this part id = cmColumn->Id; } else { if (!PhStringToInteger64(&valuePart, 10, &integer)) goto CleanupExit; id = (ULONG)integer; } // Display Index PhSplitStringRefAtChar(&columnPart, ',', &valuePart, &columnPart); if (!(Flags & PH_CM_COLUMN_WIDTHS_ONLY)) { if (valuePart.Length == 0 || !PhStringToInteger64(&valuePart, 10, &integer)) goto CleanupExit; displayIndex = (ULONG)integer; } else { if (valuePart.Length != 0) goto CleanupExit; displayIndex = -1; } // Width if (columnPart.Length == 0 || !PhStringToInteger64(&columnPart, 10, &integer)) goto CleanupExit; width = (ULONG)integer; column = PhAllocate(sizeof(PH_TREENEW_COLUMN)); column->Id = id; column->DisplayIndex = displayIndex; column->Width = width; PhAddItemSimpleHashtable(columnHashtable, (PVOID)column->Id, column); } } TreeNew_SetRedraw(TreeNewHandle, FALSE); // Set visibility and width. i = 0; count = 0; total = TreeNew_GetColumnCount(TreeNewHandle); hasFixedColumn = !!TreeNew_GetFixedColumn(TreeNewHandle); memset(orderArray, 0, sizeof(orderArray)); maxOrder = 0; while (count < total) { PH_TREENEW_COLUMN setColumn; PPH_TREENEW_COLUMN *columnPtr; if (TreeNew_GetColumn(TreeNewHandle, i, &setColumn)) { columnPtr = (PPH_TREENEW_COLUMN *)PhFindItemSimpleHashtable(columnHashtable, (PVOID)i); if (!(Flags & PH_CM_COLUMN_WIDTHS_ONLY)) { if (columnPtr) { setColumn.Visible = TRUE; setColumn.Width = (*columnPtr)->Width; TreeNew_SetColumn(TreeNewHandle, TN_COLUMN_FLAG_VISIBLE | TN_COLUMN_WIDTH, &setColumn); if (!setColumn.Fixed) { // For compatibility reasons, normal columns have their display indicies stored // one higher than usual (so they start from 1, not 0). Fix that here. if (hasFixedColumn && (*columnPtr)->DisplayIndex != 0) (*columnPtr)->DisplayIndex--; if ((*columnPtr)->DisplayIndex < PH_CM_ORDER_LIMIT) { orderArray[(*columnPtr)->DisplayIndex] = i; if ((ULONG)maxOrder < (*columnPtr)->DisplayIndex + 1) maxOrder = (*columnPtr)->DisplayIndex + 1; } } } else if (!setColumn.Fixed) // never hide the fixed column { setColumn.Visible = FALSE; TreeNew_SetColumn(TreeNewHandle, TN_COLUMN_FLAG_VISIBLE, &setColumn); } } else { if (columnPtr) { setColumn.Width = (*columnPtr)->Width; TreeNew_SetColumn(TreeNewHandle, TN_COLUMN_WIDTH, &setColumn); } } count++; } i++; } if (!(Flags & PH_CM_COLUMN_WIDTHS_ONLY)) { // Set the order array. TreeNew_SetColumnOrderArray(TreeNewHandle, maxOrder, orderArray); } TreeNew_SetRedraw(TreeNewHandle, TRUE); result = TRUE; CleanupExit: PhBeginEnumHashtable(columnHashtable, &enumContext); while (pair = PhNextEnumHashtable(&enumContext)) PhFree(pair->Value); PhDereferenceObject(columnHashtable); } // Load sort settings. if (SortSettings && SortSettings->Length != 0) { PhSplitStringRefAtChar(SortSettings, ',', &valuePart, &subPart); if (valuePart.Length != 0 && subPart.Length != 0) { ULONG sortColumn; PH_SORT_ORDER sortOrder; sortColumn = -1; if (valuePart.Buffer[0] == '+') { PH_STRINGREF pluginName; ULONG subId; PPH_CM_COLUMN cmColumn; if ( Manager && PhEmParseCompoundId(&valuePart, &pluginName, &subId) && (cmColumn = PhCmFindColumn(Manager, &pluginName, subId)) ) { sortColumn = cmColumn->Id; } } else { PhStringToInteger64(&valuePart, 10, &integer); sortColumn = (ULONG)integer; } PhStringToInteger64(&subPart, 10, &integer); sortOrder = (PH_SORT_ORDER)integer; if (sortColumn != -1 && sortOrder <= DescendingSortOrder) { TreeNew_SetSort(TreeNewHandle, sortColumn, sortOrder); } } } return result; }
INT_PTR CALLBACK PhpColumnsDlgProc( __in HWND hwndDlg, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam ) { PCOLUMNS_DIALOG_CONTEXT context = NULL; if (uMsg == WM_INITDIALOG) { context = (PCOLUMNS_DIALOG_CONTEXT)lParam; SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context); } else { context = (PCOLUMNS_DIALOG_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { ULONG count; ULONG total; ULONG i; PPH_LIST displayOrderList; context->InactiveList = GetDlgItem(hwndDlg, IDC_INACTIVE); context->ActiveList = GetDlgItem(hwndDlg, IDC_ACTIVE); if (context->Type == PH_CONTROL_TYPE_TREE_NEW) { PH_TREENEW_COLUMN column; count = 0; total = TreeNew_GetColumnCount(context->ControlHandle); i = 0; displayOrderList = PhCreateList(total); while (count < total) { if (TreeNew_GetColumn(context->ControlHandle, i, &column)) { PPH_TREENEW_COLUMN copy; if (column.Fixed) { i++; total--; continue; } copy = PhAllocateCopy(&column, sizeof(PH_TREENEW_COLUMN)); PhAddItemList(context->Columns, copy); count++; if (column.Visible) { PhAddItemList(displayOrderList, copy); } else { ListBox_AddString(context->InactiveList, column.Text); } } i++; } qsort(displayOrderList->Items, displayOrderList->Count, sizeof(PVOID), PhpColumnsCompareDisplayIndexTn); } for (i = 0; i < displayOrderList->Count; i++) { if (context->Type == PH_CONTROL_TYPE_TREE_NEW) { PPH_TREENEW_COLUMN copy = displayOrderList->Items[i]; ListBox_AddString(context->ActiveList, copy->Text); } } PhDereferenceObject(displayOrderList); SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_INACTIVE, LBN_SELCHANGE), (LPARAM)context->InactiveList); SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_ACTIVE, LBN_SELCHANGE), (LPARAM)context->ActiveList); } break; case WM_DESTROY: { ULONG i; for (i = 0; i < context->Columns->Count; i++) PhFree(context->Columns->Items[i]); RemoveProp(hwndDlg, PhMakeContextAtom()); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: EndDialog(hwndDlg, IDCANCEL); break; case IDOK: { #define ORDER_LIMIT 100 PPH_LIST activeList; ULONG activeCount; ULONG i; INT orderArray[ORDER_LIMIT]; INT maxOrder; memset(orderArray, 0, sizeof(orderArray)); maxOrder = 0; activeCount = ListBox_GetCount(context->ActiveList); activeList = PhCreateList(activeCount); for (i = 0; i < activeCount; i++) PhAddItemList(activeList, PhGetListBoxString(context->ActiveList, i)); if (context->Type == PH_CONTROL_TYPE_TREE_NEW) { // Apply visiblity settings. TreeNew_SetRedraw(context->ControlHandle, FALSE); for (i = 0; i < context->Columns->Count; i++) { PPH_TREENEW_COLUMN column = context->Columns->Items[i]; ULONG index; index = IndexOfStringInList(activeList, column->Text); column->Visible = index != -1; column->DisplayIndex = index; // the active list box order is the actual display order TreeNew_SetColumn(context->ControlHandle, TN_COLUMN_FLAG_VISIBLE, column); } // Do a second pass to create the order array. This is because the ViewIndex of each column // were unstable in the previous pass since we were both adding and removing columns. for (i = 0; i < context->Columns->Count; i++) { PPH_TREENEW_COLUMN column = context->Columns->Items[i]; PH_TREENEW_COLUMN tempColumn; if (column->Visible) { if (column->DisplayIndex < ORDER_LIMIT) { TreeNew_GetColumn(context->ControlHandle, column->Id, &tempColumn); orderArray[column->DisplayIndex] = tempColumn.s.ViewIndex; if ((ULONG)maxOrder < column->DisplayIndex + 1) maxOrder = column->DisplayIndex + 1; } } } // Apply display order. TreeNew_SetColumnOrderArray(context->ControlHandle, maxOrder, orderArray); TreeNew_SetRedraw(context->ControlHandle, TRUE); PhDereferenceObject(activeList); InvalidateRect(context->ControlHandle, NULL, FALSE); } EndDialog(hwndDlg, IDOK); } break; case IDC_INACTIVE: { switch (HIWORD(wParam)) { case LBN_DBLCLK: { SendMessage(hwndDlg, WM_COMMAND, IDC_SHOW, 0); } break; case LBN_SELCHANGE: { INT sel = ListBox_GetCurSel(context->InactiveList); EnableWindow(GetDlgItem(hwndDlg, IDC_SHOW), sel != -1); } break; } } break; case IDC_ACTIVE: { switch (HIWORD(wParam)) { case LBN_DBLCLK: { SendMessage(hwndDlg, WM_COMMAND, IDC_HIDE, 0); } break; case LBN_SELCHANGE: { INT sel = ListBox_GetCurSel(context->ActiveList); INT count = ListBox_GetCount(context->ActiveList); EnableWindow(GetDlgItem(hwndDlg, IDC_HIDE), sel != -1 && count != 1); EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEUP), sel != 0 && sel != -1); EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEDOWN), sel != count - 1 && sel != -1); } break; } } break; case IDC_SHOW: { INT sel; INT count; PPH_STRING string; sel = ListBox_GetCurSel(context->InactiveList); count = ListBox_GetCount(context->InactiveList); if (string = PhGetListBoxString(context->InactiveList, sel)) { ListBox_DeleteString(context->InactiveList, sel); ListBox_AddString(context->ActiveList, string->Buffer); PhDereferenceObject(string); count--; if (sel >= count - 1) sel = count - 1; ListBox_SetCurSel(context->InactiveList, sel); SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_INACTIVE, LBN_SELCHANGE), (LPARAM)context->InactiveList); SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_ACTIVE, LBN_SELCHANGE), (LPARAM)context->ActiveList); } } break; case IDC_HIDE: { INT sel; INT count; PPH_STRING string; sel = ListBox_GetCurSel(context->ActiveList); count = ListBox_GetCount(context->ActiveList); if (count != 1) { if (string = PhGetListBoxString(context->ActiveList, sel)) { ListBox_DeleteString(context->ActiveList, sel); ListBox_AddString(context->InactiveList, string->Buffer); PhDereferenceObject(string); count--; if (sel >= count - 1) sel = count - 1; ListBox_SetCurSel(context->ActiveList, sel); SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_INACTIVE, LBN_SELCHANGE), (LPARAM)context->InactiveList); SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_ACTIVE, LBN_SELCHANGE), (LPARAM)context->ActiveList); } } } break; case IDC_MOVEUP: { INT sel; INT count; PPH_STRING string; sel = ListBox_GetCurSel(context->ActiveList); count = ListBox_GetCount(context->ActiveList); if (sel != 0) { if (string = PhGetListBoxString(context->ActiveList, sel)) { ListBox_DeleteString(context->ActiveList, sel); ListBox_InsertString(context->ActiveList, sel - 1, string->Buffer); PhDereferenceObject(string); sel -= 1; ListBox_SetCurSel(context->ActiveList, sel); EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEUP), sel != 0); EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEDOWN), sel != count - 1); } } } break; case IDC_MOVEDOWN: { INT sel; INT count; PPH_STRING string; sel = ListBox_GetCurSel(context->ActiveList); count = ListBox_GetCount(context->ActiveList); if (sel != count - 1) { if (string = PhGetListBoxString(context->ActiveList, sel)) { ListBox_DeleteString(context->ActiveList, sel); ListBox_InsertString(context->ActiveList, sel + 1, string->Buffer); PhDereferenceObject(string); sel += 1; ListBox_SetCurSel(context->ActiveList, sel); EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEUP), sel != 0); EnableWindow(GetDlgItem(hwndDlg, IDC_MOVEDOWN), sel != count - 1); } } } break; } } break; } return FALSE; }