Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Filter and Sort by column in the grid #76

Open
bencz opened this issue Mar 27, 2020 · 0 comments
Open

[Feature Request] Filter and Sort by column in the grid #76

bencz opened this issue Mar 27, 2020 · 0 comments

Comments

@bencz
Copy link

bencz commented Mar 27, 2020

I would like to use the filter system by column and sorting in the grid

Here, I have a small sample of how to use the ListView Filter:

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <commctrl.h>
#include <string.h>
#include <stdbool.h>

#define WND_CLASS_NAME "CSVVIEW"
#define ID_LISTVIEW    0x8801

char* filename;
HWND  hList, hHeader;
static NMLISTVIEW* nmListView;
static NMHEADER* nmHeader;


int rgb(int r, int g, int b) { return r + (g << 8) + (b << 16); }

bool startsWith(const char* pre, const char* str)
{
	size_t lenpre = strlen(pre),
		lenstr = strlen(str);
	return lenstr < lenpre ? false : memcmp(pre, str, lenpre) == 0;
}

void onCreate(HWND hWnd, LPARAM lParam) {
	LVCOLUMN col;
	LVITEM item;
	int iCol, iCount, dwStyle, dwHeaderStyle;
	CREATESTRUCT* lp = (CREATESTRUCT*)lParam;
	FILE* fp;
	char buf[256];
	char* field;

	memset(&item, 0, sizeof(item));
	hList = CreateWindowEx(0, WC_LISTVIEW, 0, WS_CHILD | WS_VISIBLE | LVS_REPORT, 0, 0, 100, 100, hWnd, (HMENU)ID_LISTVIEW, lp->hInstance, NULL);
	dwStyle = SendMessage(hList, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
	dwStyle = dwStyle | LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_HEADERDRAGDROP | LVS_EX_FLATSB;
	SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, dwStyle);
	col.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;


	nmListView = (NMLISTVIEW*)hList;

	// TEST HEADER

	hHeader = ListView_GetHeader(hList);
	SetWindowLong(hHeader, GWL_ID, ID_LISTVIEW + 1);

	Header_SetFilterChangeTimeout(hHeader, 1000);
	dwHeaderStyle = (GetWindowLongPtr(hHeader, GWL_STYLE) | HDS_FILTERBAR) & ~HDS_BUTTONS;
	SetWindowLong(hHeader, GWL_STYLE, dwHeaderStyle);

	nmHeader = (NMHEADER*)hHeader;
	// END TEST


	fp = fopen(filename, "r");
	if (fp == NULL) {
		sprintf(buf, "Fail to open the file...", filename);
		MessageBox(hWnd, buf, "Error", MB_OK);
		exit(1);
	}
	fgets(buf, 255, fp);
	field = strtok(buf, ",");
	for (iCol = 0; field != NULL; iCol++) {
		if (field[1] != ':') { col.fmt = LVCFMT_LEFT; }
		else if (field[0] == 'l') { col.fmt = LVCFMT_LEFT;   field += 2; }
		else if (field[0] == 'c') { col.fmt = LVCFMT_CENTER; field += 2; }
		else if (field[0] == 'r') { col.fmt = LVCFMT_RIGHT;  field += 2; }
		col.cx = strlen(field) * 13;
		col.iSubItem = iCol;
		col.pszText = field;
		SendMessage(hList, LVM_INSERTCOLUMN, iCol, (LPARAM)&col);
		field = strtok(NULL, ",\n");
	}

	item.mask = LVIF_TEXT;
	for (iCount = 0; fgets(buf, 255, fp) != NULL; iCount++) {
		item.pszText = strtok(buf, ",");
		item.iItem = iCount;
		item.iSubItem = 0;
		SendMessage(hList, LVM_INSERTITEM, 0, (LPARAM)&item);
		for (iCol = 1; (field = strtok(NULL, ",\n")) != NULL; iCol++) {
			item.pszText = field;
			item.iItem = iCount;
			item.iSubItem = iCol;
			SendMessage(hList, LVM_SETITEM, 0, (LPARAM)&item);
		}
	}
}

void onSize(HWND hwnd, WPARAM wp, LPARAM lp) {
	RECT rc;
	GetClientRect(hwnd, &rc);
	MoveWindow(hList, 0, 0, rc.right - rc.left, rc.bottom - rc.top, TRUE);
}

int onNotify(HWND hWnd, WPARAM wp, LPARAM lp) {
	NMHDR* pnmhdr = (NMHDR*)lp;

	if (pnmhdr->code == NM_CUSTOMDRAW)
	{
		NMLVCUSTOMDRAW* lpCustomDraw = (NMLVCUSTOMDRAW*)pnmhdr;
		switch (lpCustomDraw->nmcd.dwDrawStage) {
		case CDDS_PREPAINT:
			return CDRF_NOTIFYITEMDRAW;
		case CDDS_ITEMPREPAINT:
			if (lpCustomDraw->nmcd.dwItemSpec % 2 == 1)
				lpCustomDraw->clrTextBk = rgb(209, 240, 179);
			else
				lpCustomDraw->clrTextBk = rgb(250, 250, 250);
			return CDRF_NEWFONT;
		}
	}

	switch (pnmhdr->code)
	{
	case HDN_FILTERCHANGE:
	{

		HDITEM        hditem;
		HDTEXTFILTER  hdTFilter;
		TCHAR         text[260];
		LRESULT       size;

		NMLISTVIEW* nmListView = (NMLISTVIEW*)GetDlgCtrlID(pnmhdr->hwndFrom);

		//HWND hHeaderTmp = ListView_GetHeader(hList);
		for (int i = 0; i < SendMessageW(hHeader, HDM_GETITEMCOUNT, 0, 0); i++) {
			memset(&hditem, 0, sizeof(HDITEM));
			memset(text,   0, 260);

			hditem.mask = (HDI_FILTER);
			hdTFilter.pszText = text;
			hdTFilter.cchTextMax = 260;
			hditem.type = HDFT_ISSTRING;
			hditem.pvFilter = &hdTFilter;


			SendMessageW(hHeader, HDM_GETITEM, i, (LPARAM)&hditem);

			if (strlen(text) > 0)
			{
				char buf[256];
				char* field;
				LVCOLUMN col;
				LVITEM item;

				ListView_DeleteAllItems(hList);

				FILE* fp = fopen(filename, "r");
				if (fp == NULL) {
					sprintf(buf, "Fail to open the file...", filename);
					MessageBox(hWnd, buf, "Error", MB_OK);
					exit(1);
				}
				fgets(buf, 255, fp); // pula a primeira linha...
				item.mask = LVIF_TEXT;
				for (int iCount = 0; fgets(buf, 255, fp) != NULL; iCount++)
				{
					char* resultTok = strtok(buf, ",");
					if (!startsWith(text, resultTok))
						continue;

					item.pszText = resultTok;
					item.iItem = iCount;
					item.iSubItem = 0;

					SendMessage(hList, LVM_INSERTITEM, 0, (LPARAM)&item);
					for (int iCol = 1; (field = strtok(NULL, ",\n")) != NULL; iCol++) {
						item.pszText = field;
						item.iItem = iCount;
						item.iSubItem = iCol;
						SendMessage(hList, LVM_SETITEM, 0, (LPARAM)&item);
					}
				}

				break;
			}
		}
	}
	break;
	case HDN_FILTERBTNCLICK:
		//MessageBox(hWnd, "otro_oi", "Error", MB_OK);
		break;
	default:
		break;
	}

	return DefWindowProc(hWnd, WM_NOTIFY, wp, lp);
}

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
	switch (uMsg) {
	case WM_CREATE:  onCreate(hWnd, lParam);  break;
	case WM_SIZE:    onSize(hWnd, wParam, lParam);  break;
	case WM_NOTIFY:  return onNotify(hWnd, wParam, lParam);
	case WM_DESTROY: PostQuitMessage(0);  break;
	default: return DefWindowProc(hWnd, uMsg, wParam, lParam);
	}
	return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
	char buf[256];
	HWND hWnd;
	WNDCLASS wcl;
	MSG msg;

	filename = lpCmdLine;
	if (filename == NULL) return FALSE;
	InitCommonControls();

	memset(&wcl, 0, sizeof(wcl));
	wcl.hInstance = hInstance;
	wcl.lpszClassName = WND_CLASS_NAME;
	wcl.lpfnWndProc = WindowProc;
	wcl.hCursor = LoadCursor(NULL, IDC_ARROW);
	wcl.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	if (!RegisterClass(&wcl)) return FALSE;

	wsprintf(buf, "%s - %s", "CSV View", lpCmdLine);
	hWnd = CreateWindowEx(0, WND_CLASS_NAME, buf, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 10, 10, 900, 300, NULL, NULL, hInstance, NULL);
	if (!hWnd) return FALSE;


	//char bufs[256];
	//sprintf(bufs, "%d                            %x", LVM_GETHEADER);
	//MessageBox(hWnd, bufs, "Error", MB_OK);

	while (GetMessage(&msg, NULL, 0, 0) > 0) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant