C++ ListView hide item - c++

I have created pretty much standard ListView.
RECT rec;
GetClientRect(hwnd, &rec);
ListView = CreateWindow(WC_LISTVIEW, (LPCSTR)L"", (WS_CHILD | WS_VISIBLE | LVS_REPORT), 0, 0, rec.right, rec.bottom-23, hwnd, (HMENU)8553, GetModuleHandle(NULL), NULL);
SendMessage(ListView, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES); // Set style
Now I insert few columns like that:
LVCOLUMNW listColumnW = { 0 };
listColumnW.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
listColumnW.pszText = L"Column1";
listColumnW.cx = 150;
listColumnW.fmt = LVCFMT_LEFT;
SendMessage(ListView,LVM_INSERTCOLUMNW, 0, (LPARAM)&listColumnW);
after that I instert items and subitems
LVITEMW lisW = { 0 };
lisW.mask = LVIF_TEXT | LVIF_PARAM;
lisW.pszText = item_text[i];
lisW.iItem = i;
lisW.lParam = i;
SendMessage(ListView, LVM_INSERTITEMW, 0, (LPARAM)&lisW);
Now I'd like to implement some kind of search / filtering.
I see many people suggest to delete/reinsert items, however as there are quite a number of items in my listview that isn't the best solution.
While googling I learned that it should be possible to set groupid and set state of item (hide it).
However I'm not sure exactly how to do that, lets say I have 10 items in my listview and I want to hide some items, how exactly do I do that?
EDIT:
I have set LVM_ENABLEGROUPVIEW and created two groups, one is supposed to be shown and other one hidden.
LVGROUP group = { 0 };
group.cbSize = sizeof(LVGROUP);
group.mask = LVGF_GROUPID;
group.iGroupId = 10;//shown
ListView_InsertGroup(ListView, -1, &group);
group.iGroupId = 11;//hidden
group.mask = LVGF_GROUPID | LVGF_STATE;
group.stateMask = LVGS_HIDDEN;
group.state = LVGS_HIDDEN;
ListView_InsertGroup(ListView, -1, &group);
Now I have added some items to both groups, only problem is I can see them both (they are separated), while the other one is supposed to be hidden.

Use LVM_SETITEM to assign a list item to a specific group via the LVITEM::iGroupId member:
LVITEMW lisW = { 0 };
lisW.mask = ... | LVIF_GROUPID;
...
lisW.iItem = ...;
lisW.iGroupId = ...;
SendMessage(ListView, 0, (LPARAM)&lisW);
You can use LVM_INSERTGROUP to insert a hidden group, or use LVM_SETGROUPINFO to hide an existing group, by setting its LVGROUP::state member to LVGS_HIDDEN:
LVGROUP grp = { 0 };
grp.cbSize = sizeof(grp);
grp.mask = LVGF_STATE;
grp.iGroupId = ...;
grp.stateMask = LVGS_HIDDEN | LVGS_NOHEADER | LVGS_COLLAPSED;
grp.state = LVGS_HIDDEN | LVGS_NOHEADER | LVGS_COLLAPSED;
SendMessage(ListView, LVM_INSERTGROUP, -1, (LPARAM)&grp);
or:
SendMessage(ListView, LVM_SETGROUPINFO, grp.iGroupId, (LPARAM)&grp);
Make sure you have enabled groups via LVM_ENABLEGROUPVIEW beforehand:
SendMessage(ListView, LVM_ENABLEGROUPVIEW, TRUE, 0);
That being said, when you have lots of items to display/search/filter in a ListView, you are usually better off using the ListView in virtual mode instead. You can pre-filter your data as needed, then use LVM_SETITEMCOUNT to specify the number of items you want to display, and then handle LVN_GETDISPINFO to retrieve data for specific items when the ListView requests them from you. This way, you can do all of your searching/filtering within your datasource directly (in memory, in a database, etc), then simply invalidate the portions of the ListView that need to be refreshed onscreen using LVM_REDRAWITEMS when you have new data to display. When you have items to add/remove, you simply re-send LVM_SETITEMCOUNT. This is a much faster and flexible way to handle lots of list items.
Using virtual lists

Related

IcCube - Treemap Chart with duplicate names

In the Google Treemap Chart every node has to have a unique id, but two nodes can have the same name (https://groups.google.com/d/msg/google-visualization-api/UDLD-a-0PCM/IwVCGzsWOg8J).
I used the schema from the parent/child demo (http://www.iccube.com/support/documentation/user_guide/schemas_cubes/dim_parentchild.php)
Using the following MDX statement in the treemap works, as long as the names of the nodes are unique:
WITH
MEMBER [parent_name] as IIF( [dim (ALL)].[Hierarchy].currentmember
is [dim (ALL)].[Hierarchy].[ALL],'',
[dim (ALL)]. [Hierarchy].currentmember.parent.name )
SELECT
{[parent_name],[Measures].[value]} on 0,
non empty [dim (ALL)].[Hierarchy].members on 1
FROM
[Cube]
If I added the line to the In-memory table in icCube's schema :
7,4,Spain, 2, 32
but the name Spain is double when rendering the Treemap. To support names a child definition in the GVI table should be something like this:
{v:'uniqueID-Spain', f:'Spain'}
As a workaround you can use the following code that modifies GviTable processing for the google tree widget. Check the example here:
https://drive.google.com/file/d/0B3kSph_LgXizSVhvSm15Q1hIdW8/view?usp=sharing
Report JavaScript:
function consumeEvent( context, event ) {
if (event.name == 'ic3-report-init') {
if(!_.isFunction(ic3.originalProcessGviTable)) {
ic3.originalProcessGviTable = viz.charts.GenericGoogleWidget.prototype.processGviTable
}
viz.charts.GenericGoogleWidget.prototype.processGviTable = function(gviTable){
if(this.props.ic3chartType === "TreeMap") {
gviTable = gviTable || this.gviTable();
var underlying = _.cloneDeep(gviTable.getUnderlyingGviTable());
_.each(underlying.rows, function(row){
// Replace id with parent prefixed
if(_.isObject(row.c[0]) && !_.isString(row.c[0].f)) {
row.c[0].f = row.c[0].v;
if(_.isObject(row.c[0].p) && _.isString(row.c[0].p.mun)) {
row.c[0].v = row.c[0].p.mun;
}
}
});
gviTable = viz.GviTable.fromSnapshot(underlying);
this.startColumnSelection = gviTable.getNumberOfHeaderColumns() - 1;
return viz.charts.toGoogleDataTableOneRowHeader(gviTable);
} else {
return ic3.originalProcessGviTable.apply(this, gviTable);
}
}
}
}
For the query like:
WITH
MEMBER [parent_name] as
IIF( [dim (ALL)].[Hierarchy].currentmember.isAll(),
'',
([dim (ALL)].[Hierarchy].currentmember.parent.uniqueName)
)
SELECT
{[parent_name],[Measures].[value]} on 0,
non empty [dim (ALL)].[Hierarchy].members on 1
FROM
[Cube]
This is a limitation of Google Treemap chart that is using the same column for the id and the label. Besides changing the names to ensure they are unique (e.g. adding the parent) I don't see a workaround to this.
An option would be using another Treemap chart (e.g. one from D3) that has not this limitation.
--- icCube Schema ---
The schema is working (just use , instead of ; as separator )
--- icCube Reporting ---
The issue using Treemap is that you've two rows with the same id (Germany), fiddle
This fiddle is a running example of treemap

C++: Disabling RequireCHAP and RequireMsCHAP2 in the Windows RAS API

I am writing a program that will set up a VPN on a user's computer. My sysadmin told me that the security page of the VPN must have these security settings checked, and no others.
I have used this code as a basis for my own. My version sets almost everything correctly, except that it cannot uncheck the 2 boxes titled Challenge Handshake Authentication Protocol (CHAP) and Microsoft CHAP Version 2 (MS-CHAP v2). Is it possible to programmatically uncheck those 2 checkboxes while leaving the Data Encryption dropdown list set as Require Encryption? Here is my code:
void createVPN()
{
DWORD size = 0;
RasGetEntryProperties(NULL, L"", NULL, &size, NULL, NULL);
LPRASENTRY pras = (LPRASENTRY)malloc(size);
memset(pras, 0, size);
pras->dwSize = size;
pras->dwType = RASET_Vpn;
pras->dwRedialCount = 1;
pras->dwRedialPause = 60;
pras->dwfNetProtocols = RASNP_Ip;
pras->dwEncryptionType = ET_Require;
wcscpy_s(pras->szLocalPhoneNumber, L"meraki.companyname.com");
wcscpy_s(pras->szDeviceType, RASDT_Vpn);
pras->dwfOptions = RASEO_RemoteDefaultGateway;
pras->dwVpnStrategy = VS_L2tpOnly;
pras->dwfOptions2 |= RASEO2_UsePreSharedKey;
pras->dwfOptions &= ~(RASEO_RequireCHAP | RASEO_RequireMsCHAP | RASEO_RequireMsCHAP2);//This should unset the CHAP flags, but it doesn't.
RasSetEntryProperties(NULL, L"CompanyName Meraki VPN", pras, pras->dwSize, NULL, 0);
RASCREDENTIALS ras_cre_psk = { 0 };
ras_cre_psk.dwSize = sizeof(ras_cre_psk);
ras_cre_psk.dwMask = RASCM_PreSharedKey;
wcscpy_s(ras_cre_psk.szPassword, L"redacted");
RasSetCredentials(NULL, L"CompanyName Meraki VPN", &ras_cre_psk, FALSE);
free(pras);
}
I am thinking that by setting pras->dwEncryptionType to ET_Require, that prevents RASEO_RequireCHAP and the other CHAP flags from being unset, but in the Windows GUI, it is possible to uncheck them and leave Data Encryption set to Require Encryption. My sysadmin tells me that the connection will not work if either of the CHAP checkboxes are checked, or if Data Encryption is not set to Require Encryption. What can I do?
I have finally figured it out. You have to set the RASEO_RequirePAP switch. Here is the final version of the function:
void createVPN()
{
DWORD size = 0;
RasGetEntryProperties(NULL, L"", NULL, &size, NULL, NULL);
RASENTRY rasEntry = {};
rasEntry.dwSize = sizeof(rasEntry);
rasEntry.dwType = RASET_Vpn;
rasEntry.dwRedialCount = 1;
rasEntry.dwRedialPause = 60;
rasEntry.dwfNetProtocols = RASNP_Ip;
rasEntry.dwEncryptionType = ET_Require;
wcscpy_s(rasEntry.szLocalPhoneNumber, L"meraki.enoble.com");
wcscpy_s(rasEntry.szDeviceType, RASDT_Vpn);
rasEntry.dwfOptions = RASEO_RemoteDefaultGateway;
rasEntry.dwVpnStrategy = VS_L2tpOnly;
rasEntry.dwfOptions2 |= RASEO2_UsePreSharedKey;
rasEntry.dwfOptions |= RASEO_RequirePAP;
RasSetEntryProperties(NULL, L"Enoble Meraki VPN", &rasEntry, rasEntry.dwSize, NULL, 0);
RASCREDENTIALS ras_cre_psk = { 0 };
ras_cre_psk.dwSize = sizeof(ras_cre_psk);
ras_cre_psk.dwMask = RASCM_PreSharedKey;
wcscpy_s(ras_cre_psk.szPassword, L"passport2k");
RasSetCredentials(NULL, L"Enoble Meraki VPN", &ras_cre_psk, FALSE);
}
I hope this helps somebody.

Passing nested tables from Lua to C

I have the following nested table defined in Lua. I need to pass it into my C++ program so that I can accurately read it's values. I know I can pass a single table to Lua using the
lua_getglobal(L, "parameters")
function. But in this case since it is nested, how can I deal with it?
parameters =
{
fuel = 100,
damage = 250,
maxspeed = 250,
levels =
{
{
fuel = 200,
damage = 600,
maxspeed = 300,
},
{
fuel = 300,
damage = 750,
maxspeed = 400,
},
}
}
The lua_getglobal will work for "parameters" just like any other variable. You will receive the table on the top of the stack. Once there, you can use the lua_gettable(), lua_getfield() and lua_rawget*() functions to access its fields. The fact that the table is nested makes no difference in accessing it at all. To access a subtable, push it onto the stack with those functions and access it in the same way as its "parent" table.

How to detect if a given PIDL is actually a .zip file or similar?

VS2010 introduced CMFCShellTreeCtrl which allows for a folder-browser tree ctrl to be dropped into our MFC apps.
However, there seems to be a serious lack of filtering capabilities in this class. i.e. it will build the list of container-objects (IShellFolder). But there doesn't seem to be a way to specify that .zip containers should not be displayed in the folder tree.
It does supply a virtual that could be used crudely for this purpose:
HRESULT CMFCShellTreeCtrl::EnumObjects(HTREEITEM hParentItem, LPSHELLFOLDER pParentFolder, LPITEMIDLIST pidlParent)
{
ASSERT_VALID(this);
ASSERT_VALID(afxShellManager);
LPENUMIDLIST pEnum = NULL;
HRESULT hr = pParentFolder->EnumObjects(NULL, m_dwFlags, &pEnum);
if (FAILED(hr) || pEnum == NULL)
{
return hr;
}
LPITEMIDLIST pidlTemp;
DWORD dwFetched = 1;
// Enumerate the item's PIDLs:
while (SUCCEEDED(pEnum->Next(1, &pidlTemp, &dwFetched)) && dwFetched)
{
TVITEM tvItem;
ZeroMemory(&tvItem, sizeof(tvItem));
// Fill in the TV_ITEM structure for this item:
tvItem.mask = TVIF_PARAM | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN;
// AddRef the parent folder so it's pointer stays valid:
pParentFolder->AddRef();
// Put the private information in the lParam:
LPAFX_SHELLITEMINFO pItem = (LPAFX_SHELLITEMINFO)GlobalAlloc(GPTR, sizeof(AFX_SHELLITEMINFO));
ENSURE(pItem != NULL);
pItem->pidlRel = pidlTemp;
pItem->pidlFQ = afxShellManager->ConcatenateItem(pidlParent, pidlTemp);
pItem->pParentFolder = pParentFolder;
tvItem.lParam = (LPARAM)pItem;
CString strItem = OnGetItemText(pItem);
tvItem.pszText = strItem.GetBuffer(strItem.GetLength());
tvItem.iImage = OnGetItemIcon(pItem, FALSE);
tvItem.iSelectedImage = OnGetItemIcon(pItem, TRUE);
// Determine if the item has children:
DWORD dwAttribs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER | SFGAO_DISPLAYATTRMASK | SFGAO_CANRENAME | SFGAO_FILESYSANCESTOR;
pParentFolder->GetAttributesOf(1, (LPCITEMIDLIST*) &pidlTemp, &dwAttribs);
tvItem.cChildren = (dwAttribs & (SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR));
// Determine if the item is shared:
if (dwAttribs & SFGAO_SHARE)
{
tvItem.mask |= TVIF_STATE;
tvItem.stateMask |= TVIS_OVERLAYMASK;
tvItem.state |= INDEXTOOVERLAYMASK(1); //1 is the index for the shared overlay image
}
// Fill in the TV_INSERTSTRUCT structure for this item:
TVINSERTSTRUCT tvInsert;
tvInsert.item = tvItem;
tvInsert.hInsertAfter = TVI_LAST;
tvInsert.hParent = hParentItem;
InsertItem(&tvInsert);
dwFetched = 0;
}
pEnum->Release();
return S_OK;
}
What I am confused by is the lack of ability to distinguish what type of object this is that is being enumerated (or a better way to control the enumeration in the first place so as to filter out non-filesystem objects such as these).
It's possible to look at the text for the item being enumerated, and simply exclude it if it ends in ".zip". However, this seems wonky to me. After all, an arbitrary folder could be named XYZ.zip (which still being a folder, and not a zip archive). Similarly, there are likely other archive types than just .zip that may be yet supported in the future - or other container types which are nevertheless not really folders.
I don't want to eliminate things like "Network" and "Computer" from being valid nodes. Just ones that are problematic such as "Downloads\Foobar.zip"
I apologize for this question being rambling. Any help in improving my understanding and creative approaches to knowing what sorts of objects are part of Microsoft's shell namespace, and how that they can be gainfully used would be appreciated!
A zip file/folder would have SFGAO_STREAM/SFGAO_DROPTARGET along with SFGAO_FOLDER, so if you can read the shell item as stream, then it probably isn't a directory. Another way to tell is to use SHGetPathFromIDList+PathIsDirectory, however this only works for pidl that have file system paths.
There are other kind of browsable files too, like a saved search (and if you browse into the file it takes like forever to finish enumerating the items), so you probably want to think about how to deal with those files too.

Text from sysListView32 tree

Itrying to get a out of a string sysListView32 from another process.
The list is a tree. And for the first column returns an empty string.
Tell me where is the problem?
Image of tree:
tree
Code:
vProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ |
PROCESS_VM_WRITE, False, vProcessId);
vPointer = VirtualAllocEx(vProcess, NULL, 4096, MEM_RESERVE | MEM_COMMIT,
PAGE_READWRITE);
vItem.mask = LVIF_TEXT;
vItem.iItem = I;
vItem.iSubItem = J;
vItem.cchTextMax = sizeof(vBuffer);
vItem.pszText = (wchar_t*)vPointer +sizeof(TLVItem);
WriteProcessMemory(vProcess, vPointer, &vItem, sizeof(TLVItem),
&vNumberOfBytesRead);
SendMessageW(mHandle, LVM_GETITEMW, I, (LPARAM)vPointer);
ReadProcessMemory(vProcess, (wchar_t*)vPointer +sizeof(TLVItem),
vBuffer, sizeof(vBuffer), &vNumberOfBytesRead);
RESULT = UnicodeString(vBuffer);
VirtualFreeEx(vProcess, vPointer, 0, MEM_RELEASE); // free mem
CloseHandle(vProcess);
You didn't VirtualAlloc the memory block in the target process, so it isn't there.
Instead of using extreme hackery to try to get this, why not use one of the accessibility APIs to get this info cross-process. UIA, for example, goes down to XP and supports this:
http://msdn.microsoft.com/en-us/library/ms726294(VS.85).aspx
Martyn