From 0cda0baab21d4d4bf40c9459f6f5a7e49aa92492 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Tue, 24 Jul 2012 12:45:18 +0000 Subject: VersionInfo, W7UI, WhoUsesMyFiles, YAPP, ZeroNotification: changed folder structure git-svn-id: http://svn.miranda-ng.org/main/trunk@1161 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/YAPP/src/yapp_history_dlg.cpp | 743 ++++++++++++++++++++++++++++++++++ 1 file changed, 743 insertions(+) create mode 100644 plugins/YAPP/src/yapp_history_dlg.cpp (limited to 'plugins/YAPP/src/yapp_history_dlg.cpp') diff --git a/plugins/YAPP/src/yapp_history_dlg.cpp b/plugins/YAPP/src/yapp_history_dlg.cpp new file mode 100644 index 0000000000..534af1fe0c --- /dev/null +++ b/plugins/YAPP/src/yapp_history_dlg.cpp @@ -0,0 +1,743 @@ +#include "common.h" +#include "resource.h" +#include "yapp_history.h" + +//************ Some helper resize stuff ****************** + +#define MIN_HISTORY_WIDTH 540 +#define MIN_HISTORY_HEIGHT 300 + +#define GAP_SIZE 2 + +#define ANCHOR_LEFT 0x000001 +#define ANCHOR_RIGHT 0x000002 +#define ANCHOR_TOP 0x000004 +#define ANCHOR_BOTTOM 0x000008 +#define ANCHOR_ALL ANCHOR_LEFT | ANCHOR_RIGHT | ANCHOR_TOP | ANCHOR_BOTTOM + +WNDPROC oldPopupsListProc = NULL; + +HWND hHistoryWindow = 0; //the history window +HICON hiPopupHistory; //popup history icon +PopupHistoryList lstPopupHistory; //defined in main.cpp + +const TCHAR *szHistoryColumns[] = {_T("Title"), _T("Message"), _T("Timestamp")}; //need to make sure that the string and size vectors have the same number of elements +const int cxHistoryColumns[] = {100, 450, 115}; +const int cHistoryColumns = sizeof(szHistoryColumns) / sizeof(szHistoryColumns[0]); + +struct PopupHistoryWindowData{ + HWND hIEView; +}; + +void ScreenToClient(HWND hWnd, LPRECT rect) +{ + POINT pt; + int cx = rect->right - rect->left; + int cy = rect->bottom - rect->top; + pt.x = rect->left; + pt.y = rect->top; + ScreenToClient(hWnd, &pt); + rect->left = pt.x; + rect->top = pt.y; + rect->right = pt.x + cx; + rect->bottom = pt.y + cy; +} + +RECT AnchorCalcPos(HWND window, const RECT *rParent, const WINDOWPOS *parentPos, int anchors) +{ + RECT rChild; + RECT rTmp; + + GetWindowRect(window, &rChild); + ScreenToClient(parentPos->hwnd, &rChild); + + int cx = rParent->right - rParent->left; + int cy = rParent->bottom - rParent->top; + if ((cx == parentPos->cx) && (cy == parentPos->cy)) + { + return rChild; + } + if (parentPos->flags & SWP_NOSIZE) + { + return rChild; + } + + rTmp.left = parentPos->x - rParent->left; + rTmp.right = (parentPos->x + parentPos->cx) - rParent->right; + rTmp.bottom = (parentPos->y + parentPos->cy) - rParent->bottom; + rTmp.top = parentPos->y - rParent->top; + + cx = (rTmp.left) ? -rTmp.left : rTmp.right; + cy = (rTmp.top) ? -rTmp.top : rTmp.bottom; + + rChild.right += cx; + rChild.bottom += cy; + //expanded the window accordingly, now we need to enforce the anchors + if ((anchors & ANCHOR_LEFT) && (!(anchors & ANCHOR_RIGHT))) + { + rChild.right -= cx; + } + if ((anchors & ANCHOR_TOP) && (!(anchors & ANCHOR_BOTTOM))) + { + rChild.bottom -= cy; + } + if ((anchors & ANCHOR_RIGHT) && (!(anchors & ANCHOR_LEFT))) + { + rChild.left += cx; + } + if ((anchors & ANCHOR_BOTTOM) && (!(anchors & ANCHOR_TOP))) + { + rChild.top += cy; + } + return rChild; +} + +void AnchorMoveWindow(HWND window, const WINDOWPOS *parentPos, int anchors) +{ + RECT rParent; + RECT rChild; + + if (parentPos->flags & SWP_NOSIZE) + { + return; + } + GetWindowRect(parentPos->hwnd, &rParent); + rChild = AnchorCalcPos(window, &rParent, parentPos, anchors); + MoveWindow(window, rChild.left, rChild.top, rChild.right - rChild.left, rChild.bottom - rChild.top, FALSE); +} + +void AddAnchorWindowToDeferList(HDWP &hdWnds, HWND window, RECT *rParent, WINDOWPOS *wndPos, int anchors) +{ + RECT rChild = AnchorCalcPos(window, rParent, wndPos, anchors); + hdWnds = DeferWindowPos(hdWnds, window, HWND_NOTOPMOST, rChild.left, rChild.top, rChild.right - rChild.left, rChild.bottom - rChild.top, SWP_NOZORDER); +} +//************************************************************ + +//Stucture passed to list sort function +struct SortParams{ + HWND hList; + int column; +}; + +static int lastColumn = -1; //last sort column + +int MatchesFilterCS(const TCHAR *filter, const PopupHistoryData *popupItem) //case sensitive +{ + if (_tcslen(filter) <= 0) { return 1; } //if no filter is set then the popup item matches the filter + int match = 0; + + match = (_tcsstr(popupItem->messageT, filter)) ? 1 : match; //check message part + + if (!match) //check title part of no match has been found + { + match = (_tcsstr(popupItem->titleT, filter)) ? 1 : match; + } + + if (!match) //if no match has been found yet try to match the timestamp + { + TCHAR buffer[1024]; + struct tm *myTime = localtime(&popupItem->timestamp); + _tcsftime(buffer, 1024, _T("%c"), myTime); + match = (_tcsstr(buffer, filter)) ? 1 : match; + } + + return match; +} + +__inline void ConvertCase(TCHAR *dest, const TCHAR *source, size_t size) +{ + _tcsncpy(dest, source, size); + _tcslwr(dest); +} + +int MatchesFilterCI(const TCHAR *filterS, const PopupHistoryData *popupItem) +{ + if (_tcslen(filterS) <= 0) { return 1; } //if no filter is set then the popup item matches the filter + int match = 0; + const int BUFFER_SIZE = 1024; + TCHAR buffer[BUFFER_SIZE]; + TCHAR filterI[BUFFER_SIZE]; + + ConvertCase(filterI, filterS, BUFFER_SIZE); + + ConvertCase(buffer, popupItem->messageT, BUFFER_SIZE); //check message part + match = (_tcsstr(buffer, filterI)) ? 1 : match; + + if (!match) // check title part of no match has been found + { + ConvertCase(buffer, popupItem->titleT, BUFFER_SIZE); + match = (_tcsstr(buffer, filterI)) ? 1 : match; + } + + if (!match) //if no match has been found yet try to match the timestamp + { + struct tm *myTime = localtime(&popupItem->timestamp); + _tcsftime(buffer, 1024, _T("%c"), myTime); + match = (_tcsstr(buffer, filterI)) ? 1 : match; + } + + return match; +} + +int CALLBACK PopupsCompare(LPARAM lParam1, LPARAM lParam2, LPARAM myParam) +{ + SortParams params = *(SortParams *) myParam; + const int MAX_SIZE = 512; + TCHAR text1[MAX_SIZE]; + TCHAR text2[MAX_SIZE]; + int res; + + ListView_GetItemText(params.hList, (int) lParam1, params.column, text1, MAX_SIZE); + ListView_GetItemText(params.hList, (int) lParam2, params.column, text2, MAX_SIZE); + + res = _tcsicmp(text1, text2); + + res = (params.column == lastColumn) ? -res : res; //do reverse search on second click on same column + + return res; +} + + + +int CalcCustomControlPos(IEVIEWWINDOW *ieWnd, HWND hMainWindow) +{ + RECT rect; + GetWindowRect(GetDlgItem(hMainWindow, IDC_LST_HISTORY), &rect); + ScreenToClient(hMainWindow, &rect); + //GetClientRect(hMainWindow, &rect); + + ieWnd->x = rect.left + GAP_SIZE; + ieWnd->y = rect.top + GAP_SIZE; + ieWnd->cx = rect.right - rect.left - (2 * GAP_SIZE); + ieWnd->cy = rect.bottom - rect.top - (2 * GAP_SIZE); + return 0; +} + +void MoveCustomControl(HWND hWnd, int renderer) +{ + switch (renderer) + { + case RENDER_HISTORYPP: + case RENDER_IEVIEW: + { + PopupHistoryWindowData *data = (PopupHistoryWindowData *) GetWindowLongPtr(hWnd, GWLP_USERDATA); + if (data) + { + IEVIEWWINDOW ieWnd = {0}; + ieWnd.cbSize = sizeof(ieWnd); + ieWnd.parent = hWnd; + ieWnd.hwnd = data->hIEView; + ieWnd.iType = IEW_SETPOS; + CalcCustomControlPos(&ieWnd, hWnd); + + CallService((renderer == RENDER_HISTORYPP) ? MS_HPP_EG_WINDOW : MS_IEVIEW_WINDOW, 0, (LPARAM) &ieWnd); + } + + break; + } + } +} + +void LoadRenderer(HWND hWnd, int renderer) +{ + switch (renderer) + { + case RENDER_HISTORYPP: + case RENDER_IEVIEW: + { + IEVIEWWINDOW ieWnd = {0}; + + ieWnd.cbSize = sizeof(ieWnd); + ieWnd.iType = IEW_CREATE; + ieWnd.dwMode = IEWM_HISTORY; + ieWnd.dwFlags = 0; + ieWnd.parent = hWnd; + CalcCustomControlPos(&ieWnd, hWnd); + + CallService((renderer == RENDER_HISTORYPP) ? MS_HPP_EG_WINDOW : MS_IEVIEW_WINDOW, 0, (LPARAM) &ieWnd); //create the IeView or H++ control. + + PopupHistoryWindowData *data = (PopupHistoryWindowData *) mir_alloc(sizeof(PopupHistoryWindowData)); //create custom control data + data->hIEView = ieWnd.hwnd; + ShowWindow(data->hIEView, SW_SHOW); + SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR) data); //set it as the window's user data + ShowWindow(GetDlgItem(hWnd, IDC_LST_HISTORY), SW_HIDE); + //SetWindowPos(GetDlgItem(hWnd, IDC_LST_HISTORY), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + + break; + } + } +} + +void UnloadRenderer(HWND hWnd, int renderer) +{ + switch (renderer) + { + case RENDER_HISTORYPP: + case RENDER_IEVIEW: + { + PopupHistoryWindowData *data = (PopupHistoryWindowData *) GetWindowLongPtr(hWnd, GWLP_USERDATA); + + if (data) + { + IEVIEWWINDOW ieWnd = {0}; + ieWnd.cbSize = sizeof(ieWnd); + ieWnd.parent = hWnd; + ieWnd.hwnd = data->hIEView; + ieWnd.iType = IEW_DESTROY; + CallService((renderer == RENDER_HISTORYPP) ? MS_HPP_EG_WINDOW : MS_IEVIEW_WINDOW, 0, (LPARAM) &ieWnd); + + mir_free(data); + } + + break; + } + } +} + +void DeleteOldEvents(HWND hWnd, int renderer) +{ + switch (renderer) + { + case RENDER_HISTORYPP: + case RENDER_IEVIEW: + { + PopupHistoryWindowData *data = (PopupHistoryWindowData *) GetWindowLongPtr(hWnd, GWLP_USERDATA); + if (data) + { + IEVIEWEVENT ieEvent = {0}; + ieEvent.cbSize = sizeof(IEVIEWEVENT); + ieEvent.hwnd = data->hIEView; + ieEvent.iType = IEE_CLEAR_LOG; + + CallService((renderer == RENDER_HISTORYPP) ? MS_HPP_EG_EVENT : MS_IEVIEW_EVENT, 0, (LPARAM) &ieEvent); + } + + break; + } + + case RENDER_DEFAULT: + default: + { + ListView_DeleteAllItems(GetDlgItem(hWnd, IDC_LST_HISTORY)); + + break; + } + + } +} + +typedef int (*SIG_MATCHESFILTER)(const TCHAR *filter, const PopupHistoryData *popupItem); +typedef void (*SIG_ADDEVENTS)(HWND hWnd, int renderer, TCHAR *filter, SIG_MATCHESFILTER MatchesFilter); + +IEVIEWEVENTDATA *CreateAndFillEventData(PopupHistoryData *popupItem) +{ + IEVIEWEVENTDATA *eventData = (IEVIEWEVENTDATA *) mir_calloc(sizeof(IEVIEWEVENTDATA)); + if (eventData) + { + eventData->cbSize = sizeof(IEVIEWEVENTDATA); + eventData->iType = IEED_EVENT_MESSAGE; + + eventData->dwFlags = IEEDF_UNICODE_NICK | IEEDF_UNICODE_TEXT | IEEDF_UNICODE_TEXT2; + eventData->pszNickW = popupItem->titleT; + eventData->pszTextW = popupItem->messageT; + + eventData->time = (DWORD) popupItem->timestamp; + eventData->next = NULL; + } + + return eventData; +} + +void AddEventsCustomControl(HWND hWnd, int renderer, TCHAR *filter, SIG_MATCHESFILTER MatchesFilter) +{ + PopupHistoryWindowData *pwData = (PopupHistoryWindowData *) GetWindowLongPtr(hWnd, GWLP_USERDATA); + if (pwData) + { + IEVIEWEVENT ieEvent = {0}; + ieEvent.cbSize = sizeof(IEVIEWEVENT); + ieEvent.hwnd = pwData->hIEView; + ieEvent.codepage = CP_ACP; + ieEvent.iType = IEE_LOG_MEM_EVENTS; + ieEvent.hContact = NULL;//(HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); IEVIEW needs a contact handle !! + + IEVIEWEVENTDATA *eventData = NULL; + IEVIEWEVENTDATA *cED = NULL; + IEVIEWEVENTDATA *prevED = NULL; + + int i; + int count = 0; + int size = lstPopupHistory.Count(); + PopupHistoryData *popupItem; + + for (i = 0; i < size; i++) + { + popupItem = lstPopupHistory.Get(i); + if (MatchesFilter(filter, popupItem)) + { + cED = CreateAndFillEventData(popupItem); + if (cED) + { + count++; + if (!eventData) + { + eventData = cED; + } + else{ + prevED->next = cED; + } + + prevED = cED; + } + } + } + ieEvent.count = count; + ieEvent.eventData = eventData; + + CallService((renderer == RENDER_HISTORYPP) ? MS_HPP_EG_EVENT : MS_IEVIEW_EVENT, 0, (LPARAM) &ieEvent); + + while (eventData) + { + cED = eventData; + eventData = eventData->next; + mir_free(cED); + } + } +} + +void AddEventsDefault(HWND hWnd, int renderer, TCHAR *filter, SIG_MATCHESFILTER MatchesFilter) +{ + HWND hHistoryList = GetDlgItem(hWnd, IDC_LST_HISTORY); + TCHAR buffer[1024]; + struct tm *myTime; + + LVITEM item = {0}; + item.mask = LVIF_TEXT; + + int i, lIndex; + lIndex = 0; + PopupHistoryData *popupItem; + for (i = 0; i < lstPopupHistory.Count(); i++) + { + item.iItem = lIndex; + popupItem = lstPopupHistory.Get(i); + if (MatchesFilter(filter, popupItem)) + { + item.pszText = popupItem->titleT; + ListView_InsertItem(hHistoryList, &item); + ListView_SetItemText(hHistoryList, lIndex, 1, popupItem->messageT); + myTime = localtime(&popupItem->timestamp); + _tcsftime(buffer, 1024, _T("%c"), myTime); + ListView_SetItemText(hHistoryList, lIndex++, 2, buffer); + } + } +} + +void RefreshPopupHistory(HWND hWnd, int renderer) +{ + if (!hWnd) { return; } + const int MAX_FILTER_SIZE = 1024; + SIG_MATCHESFILTER MatchesFilter = (IsDlgButtonChecked(hWnd, IDC_HISTORY_FILTER_CASESENSITIVE)) ? MatchesFilterCS : MatchesFilterCI; //case sensitive compare or not ? + + SIG_ADDEVENTS AddEvents = (renderer == RENDER_DEFAULT) ? AddEventsDefault : AddEventsCustomControl; + + TCHAR filter[MAX_FILTER_SIZE]; + DeleteOldEvents(hWnd, renderer); //delete events + + GetWindowText(GetDlgItem(hWnd, IDC_HISTORY_FILTER), filter, MAX_FILTER_SIZE); //get filter text + + AddEvents(hWnd, renderer, filter, MatchesFilter); + + if (renderer == RENDER_DEFAULT) + { + HWND hHistoryList = GetDlgItem(hWnd, IDC_LST_HISTORY); + SortParams params = {0}; + params.hList = hHistoryList; + params.column = lastColumn; + + ListView_SortItemsEx(hHistoryList, PopupsCompare, ¶ms); + } +} + +void CopyPopupDataToClipboard(HWND hList, int selection) +{ + if (!selection) + { + return; + } + + if (!GetOpenClipboardWindow()) + { + if (OpenClipboard(hList)) + { + TCHAR buffer[2048]; + buffer[0] = _T('\0'); + TCHAR *clipboard; + int i; + int found = 0; + int count = ListView_GetItemCount(hList); + int textType; + + textType = CF_UNICODETEXT; + + + for (i = 0; i < count; i++) + { + if (ListView_GetItemState(hList, i, LVIS_SELECTED)) + { + ListView_GetItemText(hList, i, selection - 100, buffer, 2048); + found = 1; + break; + } + } + if (found) + { + EmptyClipboard(); + int len = (int)_tcslen(buffer); + + HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, (len + 2) * sizeof(TCHAR)); + clipboard = (TCHAR *) GlobalLock(hData); + _tcsncpy(clipboard, buffer, len); + clipboard[len] = _T('\0'); + GlobalUnlock(hData); + if (!SetClipboardData(textType, hData)) + { + PUShowMessage("Could not set clipboard data", SM_WARNING); + } + } + CloseClipboard(); + } + else{ + PUShowMessage("Could not open clipboard", SM_WARNING); + } + } + else{ + PUShowMessage("The clipboard is not available", SM_WARNING); + } +} + +//subclass proc for the list view +BOOL CALLBACK PopupsListSubclassProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_CONTEXTMENU: + { + int x = LOWORD(lParam); + int y = HIWORD(lParam); + int selection; + + HMENU hMenu = CreatePopupMenu(); + AppendMenu(hMenu, MF_STRING, POPUPMENU_TITLE, TranslateT("Copy title to clipboard")); + AppendMenu(hMenu, MF_STRING, POPUPMENU_MESSAGE, TranslateT("Copy message to clipboard")); + AppendMenu(hMenu, MF_STRING, POPUPMENU_TIMESTAMP, TranslateT("Copy timestamp to clipboard")); + selection = TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, x, y, 0, hWnd, NULL); + DestroyMenu(hMenu); + if (selection) + { + CopyPopupDataToClipboard(hWnd, selection); + } + + break; + } + + case WM_KEYUP: + { + switch (wParam) + { + case 'C': + { + if (GetKeyState(VK_CONTROL)) + { + CopyPopupDataToClipboard(hWnd, POPUPMENU_MESSAGE); + } + + break; + } + + case VK_ESCAPE: + { + SendMessage(GetParent(hWnd), WM_CLOSE, 0, 0); + + break; + } + + } + + break; + } + + case WM_SYSKEYDOWN: + { + if (wParam == 'X') + { + SendMessage(GetParent(hWnd), WM_CLOSE, 0, 0); + } + + break; + } + } + + return CallWindowProc(oldPopupsListProc, hWnd, msg, wParam, lParam); +} + +//load the columns +void LoadHistoryColumns(HWND hHistoryList) +{ + LVCOLUMN col; + col.mask = LVCF_TEXT | LVCF_WIDTH; + int i; + + for (i = 0; i < cHistoryColumns; i++) + { + col.pszText = TranslateTS(szHistoryColumns[i]); + col.cx = cxHistoryColumns[i]; + ListView_InsertColumn(hHistoryList, i, &col); + } +} + +//this is the history list window handler +INT_PTR CALLBACK DlgProcHistLst(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + static int bInitializing; + + switch (msg) + { + case WM_INITDIALOG: + { + bInitializing = 1; + int renderer = lstPopupHistory.GetRenderer(); + + SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM) hiPopupHistory); + + LoadRenderer(hWnd, renderer); + + TranslateDialogDefault(hWnd); + HWND hHistoryList = GetDlgItem(hWnd, IDC_LST_HISTORY); + + ListView_SetExtendedListViewStyleEx(hHistoryList, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); + + oldPopupsListProc = (WNDPROC) SetWindowLongPtr(hHistoryList, GWLP_WNDPROC, (LONG_PTR) PopupsListSubclassProc); + + LoadHistoryColumns(hHistoryList); + + RefreshPopupHistory(hWnd, renderer); + + bInitializing = 0; + + return TRUE; + } + + case WM_DESTROY: + { + UnloadRenderer(hWnd, lstPopupHistory.GetRenderer()); + hHistoryWindow = NULL; + + break; + } + + case WM_CLOSE: + { + //Utils_SaveWindowPosition(hWnd, 0, MODULE, "history_dlg"); + DestroyWindow(hWnd); + + break; + } + + case WM_WINDOWPOSCHANGING: + { + WINDOWPOS *wndPos = (WINDOWPOS *) lParam; + + if (wndPos->cx < MIN_HISTORY_WIDTH) + { + wndPos->cx = MIN_HISTORY_WIDTH; + } + if (wndPos->cy < MIN_HISTORY_HEIGHT) + { + wndPos->cy = MIN_HISTORY_HEIGHT; + } + + RECT rParent; + GetWindowRect(hWnd, &rParent); + HDWP hdWnds = BeginDeferWindowPos(4); + + AddAnchorWindowToDeferList(hdWnds, GetDlgItem(hWnd, IDC_CLOSE), &rParent, wndPos, ANCHOR_RIGHT | ANCHOR_BOTTOM); + AddAnchorWindowToDeferList(hdWnds, GetDlgItem(hWnd, IDC_HISTORY_FILTER), &rParent, wndPos, ANCHOR_LEFT | ANCHOR_BOTTOM); + AddAnchorWindowToDeferList(hdWnds, GetDlgItem(hWnd, IDC_HISTORY_FILTER_CASESENSITIVE), &rParent, wndPos, ANCHOR_LEFT | ANCHOR_RIGHT | ANCHOR_BOTTOM); + AddAnchorWindowToDeferList(hdWnds, GetDlgItem(hWnd, IDC_LST_HISTORY), &rParent, wndPos, ANCHOR_ALL); + + EndDeferWindowPos(hdWnds); + MoveCustomControl(hWnd, lstPopupHistory.GetRenderer()); //move the custom control too, if any + break; + } + + + case WM_COMMAND: + { + switch (LOWORD(wParam)) + { + case IDC_CLOSE: + { + SendMessage(hWnd, WM_CLOSE, 0, 0); + + break; + } + + case IDC_HISTORY_FILTER_CASESENSITIVE: + { + if (HIWORD(wParam) == BN_CLICKED) + { + RefreshPopupHistory(hWnd, lstPopupHistory.GetRenderer()); + } + } + + case IDC_HISTORY_FILTER: + { + if (HIWORD(wParam) == EN_CHANGE) + { + if (!bInitializing) + { + RefreshPopupHistory(hWnd, lstPopupHistory.GetRenderer()); + } + } + + break; + } + + } + + break; + } + + case WM_NOTIFY: + { + switch(((LPNMHDR)lParam)->idFrom) + { + case IDC_LST_HISTORY: + { + switch (((LPNMHDR)lParam)->code) + { + case LVN_COLUMNCLICK: + { + LPNMLISTVIEW lv = (LPNMLISTVIEW) lParam; + int column = lv->iSubItem; + SortParams params = {0}; + params.hList = GetDlgItem(hWnd, IDC_LST_HISTORY); + params.column = column; + + ListView_SortItemsEx(params.hList, PopupsCompare, (LPARAM) ¶ms); + lastColumn = (params.column == lastColumn) ? -1 : params.column; + + break; + } + } + + break; + } + } + + break; + } + } + + return 0; +} -- cgit v1.2.3