I would like to select and highlight an item from a list view control and am using the following code
#include <Windows.h>
#include <commctrl.h>
int main() {
//Hardcoded Handle to the ListView Windows of Add Printer Dialog
HWND hwndListView = (HWND)0x000206D6;
DWORD dwProcessID;
::GetWindowThreadProcessId( hwndListView, &dwProcessID );
HANDLE process=OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION, FALSE, dwProcessID);
LVITEM lvi;
LVITEM* _lvi=(LVITEM*)VirtualAllocEx(process, NULL, sizeof(LVITEM), MEM_COMMIT, PAGE_READWRITE);
lvi.state = LVIS_FOCUSED | LVIS_SELECTED ;
lvi.stateMask = LVIS_FOCUSED | LVIS_SELECTED ;
lvi.mask = LVIF_STATE;
WriteProcessMemory(process, _lvi, &lvi, sizeof(LVITEM), NULL);
::SendMessage(hwndListView, LVM_SETITEMSTATE, (WPARAM)0, (LPARAM)_lvi);
VirtualFreeEx(process, _lvi, 0, MEM_RELEASE);
}
The result I am getting is
instead of the item getting selected and highlighted
Please let me know what might be going wrong
There are restrictions on which processes can set focus on a window, and chances are that the app selecting the ListView items does not satisfy those restrictions while the dialog is active. For example, the HWND being focused must be attached to the calling thread's message queue. So the highlighting app will have to use AttachThreadInput() before calling SetFocus() on another app's windows.
Related
CreateWindowEx API really posts WM_SIZE message?
When I create a window via CreateWindowEx as full screen mode,
CreateWindowEx posts WM_SIZE but window mode doesn't.
My code sets the window style like this :
if(bFullscr)
{
//When the window is in full screen mode.
nStyle = WS_POPUP;
nExtraStyle = WS_EX_APPWINDOW;
}
else
{
//Otherwise.
nStyle = WS_OVERLAPPEDWINDOW;
nExtraStyle = (WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
}
And changes display settings like this (full screen mode only) :
if(bFullscr)
{
DEVMODE sScrSet;
memset(&sScrSet, 0, sizeof(DEVMODE));
sScrSet.dmSize = sizeof(DEVMODE);
sScrSet.dmPelsWidth = nWidth;
sScrSet.dmPelsHeight = nHeight;
sScrSet.dmBitsPerPel = nColorBit;
sScrSet.dmFields = (DM_BITSPERPEL | DM_PELSHEIGHT | DM_PELSWIDTH);
if(ChangeDisplaySettings(&sScrSet, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{
//Error routine.
}
}
I'm really wonder why CreateWindowEx posts WM_SIZE message selectively.
If you simply want to resize the window, somewhere in your code you should have ShowWindow(hWnd, nCmdShow); change it as follows:
ShowWindow(hWnd, SW_SHOWDEFAULT);//show normal
ShowWindow(hWnd, SW_SHOWMAXIMIZED);//show maximized (full screen)
SetWindowPos(hWnd, NULL, 10, 10, 300, 300, SWP_SHOWWINDOW);//show at specific position
Also you could use WS_MAXIMIZE in CreateWindow, but that could complicate things. Window usually has WS_OVERLAPPEDWINDOW or WS_POPUP|WS_CAPTION|WS_SYSMENU. You should pick one and keep it simple.
When Window size changes, it receives WM_SIZE, you can catch that and examine it.
I have created TreeView like this:
TreeView=CreateWindowEx(0, WC_TREEVIEW, TEXT("Tree View"), WS_VISIBLE | WS_CHILD, 0, 0, 200, 500, hwnd, (HMENU)ID_TREE_VIEW, GetModuleHandle(NULL), NULL);
Now I added one item to it like shown on this website.
It all okay, but after hours and hours of googling I still didn't found answer to these questions:
How to add subitems (nodes)?
How to add checkbox on each item (how to determine if specified checkbox is checked)?
EDIT #4:
In response to OPs request, I have added an example that removes checkbox from a parent node.
THE PROBLEM IS THAT CHECKBOX STILL APPEARS WHEN USER SELECTS A NODE AND PRESSES SPACEBAR.
This question solves that problem.
EDIT #3:
I have added the code that creates a node that is already checked.
It is the second child bode in the WM_CREATE handler.
END OF EDIT
case WM_CREATE:
{
// this is your treeview
TreeView = CreateWindowEx(0, WC_TREEVIEW,
TEXT("Tree View"), WS_VISIBLE | WS_CHILD,
0, 0, 200, 500,
hwnd, (HMENU)ID_TREE_VIEW, GetModuleHandle(NULL), NULL);
/************ enable checkboxes **************/
DWORD dwStyle = GetWindowLong( TreeView , GWL_STYLE);
dwStyle |= TVS_CHECKBOXES;
SetWindowLongPtr( TreeView , GWL_STYLE, dwStyle );
/************ add items and subitems **********/
// add root item
TVINSERTSTRUCT tvis = {0};
tvis.item.mask = TVIF_TEXT;
tvis.item.pszText = L"This is root item";
tvis.hInsertAfter = TVI_LAST;
tvis.hParent = TVI_ROOT;
HTREEITEM hRootItem = reinterpret_cast<HTREEITEM>( SendMessage( TreeView ,
TVM_INSERTITEM, 0, reinterpret_cast<LPARAM>( &tvis ) ) );
// and here is an example of removing a checkbox
// from a specific item/subitem in case you ever need it
TVITEM tvi;
tvi.hItem = hRootItem ;
tvi.mask = TVIF_STATE;
tvi.stateMask = TVIS_STATEIMAGEMASK;
tvi.state = 0;
TreeView_SetItem( TreeView, &tvi );
// add firts subitem for the hTreeItem
memset( &tvis, 0, sizeof(TVINSERTSTRUCT) );
tvis.item.mask = TVIF_TEXT;
tvis.item.pszText = L"This is first subitem";
tvis.hInsertAfter = TVI_LAST;
tvis.hParent = hRootItem;
HTREEITEM hTreeSubItem1 = reinterpret_cast<HTREEITEM>( SendMessage( TreeView ,
TVM_INSERTITEM, 0, reinterpret_cast<LPARAM>( &tvis ) ) );
// now we insert second subitem for hRootItem
memset( &tvis, 0, sizeof(TVINSERTSTRUCT) );
tvis.item.mask = TVIF_TEXT | TVIF_STATE; // added extra flag
tvis.item.pszText = L"This is second subitem";
tvis.hInsertAfter = TVI_LAST;
tvis.hParent = hRootItem;
// for demonstration purposes let us check this node;
// to do that add the following code, and add the extra flag for
// mask member like above
tvis.item.stateMask = TVIS_STATEIMAGEMASK;
tvis.item.state = 2 << 12;
HTREEITEM hTreeSubItem2 = reinterpret_cast<HTREEITEM>( SendMessage( TreeView ,
TVM_INSERTITEM, 0, reinterpret_cast<LPARAM>( &tvis ) ) );
// let us expand the root node so we can see if checked state is really set
TreeView_Expand( TreeView, hRootItem, TVE_EXPAND );
}
return 0L;
EDIT #2:
Here Is the part that explains how to check if item is checked ( it now properly checks when you click on a checkbox and when you press spacebar! ) :
case WM_NOTIFY:
{
LPNMHDR lpnmh = (LPNMHDR) lParam;
if( lpnmh->idFrom == ID_TREE_VIEW ) // if this is our treeview control
{
switch( lpnmh->code ) // let us filter notifications
{
case TVN_KEYDOWN: // tree has keyboard focus and user pressed a key
{
LPNMTVKEYDOWN ptvkd = (LPNMTVKEYDOWN)lParam;
if( ptvkd->wVKey == VK_SPACE ) // if user pressed spacebar
{
// get the currently selected item
HTREEITEM ht = TreeView_GetSelection( ptvkd->hdr.hwndFrom );
// Prepare to test items state
TVITEM tvItem;
tvItem.mask = TVIF_HANDLE | TVIF_STATE;
tvItem.hItem = (HTREEITEM)ht;
tvItem.stateMask = TVIS_STATEIMAGEMASK;
// Request the information.
TreeView_GetItem( ptvkd->hdr.hwndFrom, &tvItem );
// Return zero if it's not checked, or nonzero otherwise.
if( (BOOL)(tvItem.state >> 12) - 1 )
MessageBox( hwnd, L"Not checked!", L"", MB_OK );
else
MessageBox( hwnd, L"Checked!", L"", MB_OK );
}
}
return 0L; // see the documentation for TVN_KEYDOWN
case NM_CLICK: // user clicked on a tree
{
TVHITTESTINFO ht = {0};
DWORD dwpos = GetMessagePos();
// include <windowsx.h> and <windows.h> header files
ht.pt.x = GET_X_LPARAM(dwpos);
ht.pt.y = GET_Y_LPARAM(dwpos);
MapWindowPoints( HWND_DESKTOP, lpnmh->hwndFrom, &ht.pt, 1 );
TreeView_HitTest(lpnmh->hwndFrom, &ht);
if(TVHT_ONITEMSTATEICON & ht.flags)
{
// Prepare to receive the desired information.
TVITEM tvItem;
tvItem.mask = TVIF_HANDLE | TVIF_STATE;
tvItem.hItem = (HTREEITEM)ht.hItem;
tvItem.stateMask = TVIS_STATEIMAGEMASK;
// Request the information.
TreeView_GetItem( lpnmh->hwndFrom, &tvItem );
// Return zero if it's not checked, or nonzero otherwise.
if( (BOOL)(tvItem.state >> 12) - 1 )
MessageBox( hwnd, L"Not checked!", L"", MB_OK );
else
MessageBox( hwnd, L"Checked!", L"", MB_OK );
}
}
default:
break;
}
}
}
break;
The relevant idea for proper testing when spacebar is pressed is handling of TVN_KEYDOWN message.
We use this message to get NMTVKEYDOWN structure filled, which will give us virtual key code of the pressed button and the HWND of the treeview that sent the notification.
Now we use TreeView_GetItem() macro to get the currently selected node and we check its state the same way we did when we did hit testing.
My only problem is concerning this part from the documentation for TVN_KEYDOWN:
Return value
If the wVKey member of lParam is a character key code, the character
will be used as part of an incremental search. Return nonzero to
exclude the character from the incremental search, or zero to include
the character in the search. For all other keys, the return value is
ignored.
I just do not know what to do with the return result so I have put 0L.
Important note: If you need to return value from dialog box procedure use something like this:
SetWindowLongPtr( hwnd, DWLP_MSGRESULT, (LONG_PTR)1 );
return TRUE;
see the remarks for Return value in this documentation and use SetWindowLongPtr instead of SetWindowLong so you can support both x32 and x64 versions of Windows.
That would be all. Hopefully you have your problem solved. If you need further help leave a comment.
END OF EDIT
I have never done checking if tree item is checked but I believe that accepted answer to this question is the way to go.
NOTE:
I would highly appreciate if there someone who can provide code snippet for showing how to determine if treeview node is checked or not.
I am working on a Win32++ application that has a listview in the main window. This is my code:
HWND CarsListView = NULL;
switch (message)
{
case WM_SHOWWINDOW:
CarsListView = CreateListView(hWnd);
ShowWindow(CarsListView, SW_SHOW);
break;
case WM_SIZING:
{
if(!CarsListView)
MessageBox(hWnd, _T("Null handle."), _T("Error"), MB_ICONERROR | MB_OK);
RECT WindowRect;
GetWindowRect( hWnd, &WindowRect);
SetWindowPos(CarsListView, NULL, 0, 0, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top, SWP_SHOWWINDOW);
}
break;
// ...
}
and the CreateListView definition is this:
HWND CreateListView (HWND hwndParent)
{
INITCOMMONCONTROLSEX icex; // Structure for control initialization.
icex.dwICC = ICC_LISTVIEW_CLASSES;
InitCommonControlsEx(&icex);
RECT rcClient; // The parent window's client area.
GetClientRect (hwndParent, &rcClient);
// Create the list-view window in report view with label editing enabled.
HWND hWndListView = CreateWindow(WC_LISTVIEW,
L"",
WS_CHILD | LVS_REPORT | LVS_EDITLABELS,
0, 0,
rcClient.right - rcClient.left,
rcClient.bottom - rcClient.top,
hwndParent,
/*(HMENU)*/NULL,
hInst,
NULL);
return (hWndListView);
}
When the window receives WM_SIZING, I get that CarsListView = NULL
What can I do to have that handle pointing to my listview?
Three way to do that kind of stuff.
The Ugly
Store your CarsListView HWND in a static. You can't have 2 instance of the parent windows.
The Bad
Use SetWindowsLongPtr(parentHWND,GWLP_USERDATA,CarsListViewHWND) in your init and GetWindowLongPtr when needed. It's fast you can have as many instance as you want, but if you need more than one information I recommend storing a struct with your HWND inside instead of single HWND for future extensibility.
The Good ?
Use SetProp(parentHWND,"Your Unique String",hDataHandle); its by far the more code but with that usage you can use it on every windows without caring if the USERDATA is already used or not. It's the best approach when you need to add personal property to a windows/code you can't be sure how it will be used or change over time
There are two ways to do this: The "good" way and the "bad" way.
The "bad" way is to simply declare the local variable as static, however it means you can't create two windows of this type in the same process.
The "good" way is to memorize it in a heap-allocated structure, and store a pointer to this structure in the Window information using SetWindowLongPtr(). You can then retrieve this structure with GetWindowLongPtr().
I would create the listview in WM_CREATE and not in WM_SHOWWINDOW. Also make the handle either global or static.
Or you can also create the list view globally and keep it hidden and just make it visible and set its position whenever you want it to do.
I'm using the code, from this article to customize the context menu of a webbrowser.
but when i run this code
HRESULT CBrowserHost::ShowContextMenu(DWORD dwID,
POINT *ppt,
IUnknown *pcmdTarget,
IDispatch *pdispObject)
{
#define IDR_BROWSE_CONTEXT_MENU 24641
#define SHDVID_GETMIMECSETMENU 27
#define SHDVID_ADDMENUEXTENSIONS 53
HRESULT hr;
HINSTANCE hinstSHDOCLC;
HWND hwnd;
HMENU hMenu;
CComPtr<IOleCommandTarget> spCT;
CComPtr<IOleWindow> spWnd;
MENUITEMINFO mii = {0};
CComVariant var, var1, var2;
hr = pcmdTarget->QueryInterface(IID_IOleCommandTarget, (void**)&spCT);
hr = pcmdTarget->QueryInterface(IID_IOleWindow, (void**)&spWnd);
hr = spWnd->GetWindow(&hwnd);
hinstSHDOCLC = LoadLibrary(TEXT("SHDOCLC.DLL")); //here the exception is raised
if (hinstSHDOCLC == NULL)
{
// Error loading module -- fail as securely as possible.
return;
}
hMenu = LoadMenu(hinstSHDOCLC,
MAKEINTRESOURCE(IDR_BROWSE_CONTEXT_MENU));
hMenu = GetSubMenu(hMenu, dwID);
// Get the language submenu.
hr = spCT->Exec(&CGID_ShellDocView, SHDVID_GETMIMECSETMENU, 0, NULL, &var);
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_SUBMENU;
mii.hSubMenu = (HMENU) var.byref;
// Add language submenu to Encoding context item.
SetMenuItemInfo(hMenu, IDM_LANGUAGE, FALSE, &mii);
// Insert Shortcut Menu Extensions from registry.
V_VT(&var1) = VT_INT_PTR;
V_BYREF(&var1) = hMenu;
V_VT(&var2) = VT_I4;
V_I4(&var2) = dwID;
hr = spCT->Exec(&CGID_ShellDocView, SHDVID_ADDMENUEXTENSIONS, 0, &var1, &var2);
// Remove View Source.
DeleteMenu(hMenu, IDM_VIEWSOURCE, MF_BYCOMMAND);
// Show shortcut menu.
int iSelection = ::TrackPopupMenu(hMenu,
TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
ppt->x,
ppt->y,
0,
hwnd,
(RECT*)NULL);
// Send selected shortcut menu item command to shell.
LRESULT lr = ::SendMessage(hwnd, WM_COMMAND, iSelection, NULL);
FreeLibrary(hinstSHDOCLC);
return S_OK;
}
This error is raised
"The specified module could not be found"
I search on my system (Windows 7 x64, IE9) and I not found the SHDOCLC.DLL file, the question is exist any replacement for this file in the newers versions of IE or I must use another way to load the context menu and customize it?
You shouldn't use or rely on the Internet Explorer's internal resources anymore. As it's stated in the article you've pointed out:
In Internet Explorer 7, the technique for overriding the context menu
from a DocObject host is the same as Internet Explorer 6; however, the
host must implement its own menu resources. The internal resources of
Internet Explorer should not be used as they may change or move (as
has been done in Internet Explorer 7).
if the Windows version is newer than VISTA(included), try LoadLibrary("IEFRAME.DLL") instead.
And you can find more infomation here
I'm trying to create functionality of the shell context menus despite them being blocked by a group policy for no real reason. One thing this demands is which icon the user is actually right-clicking, or if they are just clicking the desktop. The same thing also applies to explorer windows, although the desktop is where I'm planning on starting.
So far I can get the context menu to show for a specific file with a literal path. I found a nice list of interfaces on msdn, but none of the desktop-related ones I could find had any way of getting the desktop item like this. The closest match I could find was IActiveDesktop::GetDesktopItem with going through every single item and seeing whether the position matches, and then assuming none were clicked if none match.
This approach brings up two new issues, though. Firstly, I'm not sure how to go through every icon. Secondly, I have no clue how to convert this to a PIDL.
Also, even if I got the icons working, how would I extend this to the shell context menu for just the desktop?
Here's the code I use for a specific file:
#define _WIN32_WINNT _WIN32_WINNT_WINXP //going to be using on XP, tested on 7
#include <windows.h> //main header
#include <shellapi.h> //shell headers
#include <shlobj.h>
#include "G:\programming\v1\winwrap.h" //used for the window to display menu on
LPCONTEXTMENU cm; //holds context menu
msgproc (rproc) //this is called when right mouse button is depressed on window
{
//This function shows the context menu of the program on this window
//hwnd() is the HWND of the window involved with the right click
HMENU hMenu = CreatePopupMenu();
DWORD Flags = CMF_EXPLORE;
cm->QueryContextMenu(hMenu, 0, 1, 0x7FFF, Flags);
POINT pt;
GetCursorPos(&pt);
int Cmd = TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, 0, hwnd(), 0);
CMINVOKECOMMANDINFO ci;
if (Cmd)
{
ci.lpVerb = MAKEINTRESOURCE(Cmd - 1);
ci.lpParameters = "";
ci.lpDirectory = "";
ci.nShow = SW_SHOWNORMAL;
cm->InvokeCommand(&ci);
}
}
int main()
{
Window win; //create window for menu to go on, can be invisible, fullscreen later
win.addmsg (WM_RBUTTONUP, rproc); //handle message with previous function
WCHAR fname [MAX_PATH] = L"C:\\Users\\Chris\\Desktop\\context.exe"; //full path
WCHAR path [MAX_PATH] = L"C:\\Users\\Chris\\Desktop"; //path part
WCHAR name [MAX_PATH] = L"context.exe"; //filename part
LPSHELLFOLDER desktopFolder; //get desktop shell folder
SHGetDesktopFolder (&desktopFolder);
LPITEMIDLIST pidl; //tried using this for no icon by changing GetUIObjectOf to this pild to no avail
DWORD eaten;
desktopFolder->ParseDisplayName (0, 0, path, &eaten, &pidl, 0);
LPSHELLFOLDER parent;
desktopFolder->BindToObject (pidl, 0, IID_IShellFolder, (void **)&parent);
LPITEMIDLIST localPidl; //file pidl
parent->ParseDisplayName (0, 0, name, &eaten, &localPidl, 0);
parent->GetUIObjectOf (0, 0, (LPCITEMIDLIST *)&localPidl, IID_IContextMenu, 0, (void **)&cm); //gets context menu
messageLoop(); //window message loop
}
Any help is very appreciated.