Thankt there are hope :-)
How would this dll look like ?
How would i use the WM_COPY ?
I'm using windows 98.
/Andla
Main Topics
Browse All TopicsDoes anybody know how to get text from a treeview control that does not belong to my process ?
When i run this code i get an access violation in comctl32.dll
Please help me.
int wfp=(int)(hWnd=(HWND)Windo
HTREEITEM hti = TreeView_GetRoot(hWnd);
if(hti)
{
item.mask =TVIF_TEXT;
item.cchTextMax=199;
item.pszText=new char[300];
strcpy(item.pszText,"");
item.hItem = hti;
hti=(HTREEITEM)TreeView_Ge
TreeView_GetItem(hWnd,&ite
int x=0;//Just to stop the debugger inside brackets
x=1;
}
Regards
Andla
This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.
Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.
If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.
Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.
Access the answers to your technology questions today.
30-day free trial. Register in 60 seconds.
Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Try it out and discover for yourself.
30-day free trial. Register in 60 seconds.
Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.
Note I use ListView_GetItem, because it was easier to find a listview on my computer.
//----------
// Main.cpp
//----------
//cl /LD /MD hook.cpp user32.lib kernel32.lib comctl32.lib
//cl main.cpp hook.lib user32.lib
#include <windows.h>
#include <stdlib.h>
#include <iostream.h>
HWND hTV;
bool setHook(HWND hTV,HWND w);
LRESULT CALLBACK wndProc(HWND w,UINT msg,WPARAM wp,LPARAM lp)
{
switch(msg) {
case WM_COPYDATA:
{
PCOPYDATASTRUCT c=(PCOPYDATASTRUCT)lp;
LPSTR t=new CHAR[c->cbData];
memcpy(t,c->lpData,c->cbDa
ReplyMessage(0);
MessageBox(0,t,"Item text",MB_OK);
delete[] t;
SendMessage(w,WM_CLOSE,0,0
break;
}
case WM_USER:
setHook(hTV,w);
break;
case WM_CREATE:
PostMessage(w,WM_USER,0,0)
return 0;
case WM_RBUTTONDOWN:
case WM_CLOSE:
PostQuitMessage(0);
DestroyWindow(w);
return 0;
}
return DefWindowProc(w,msg,wp,lp)
}
//int WINAPI WinMain(HINSTANCE,HINSTANC
void main(int argc,char* argv[])
{
if(argc<2)
{
cout<<"Usage: main.exe <listview handle (eg: 0x123400)>"<<endl;
return;
}
hTV=HWND(strtoul(argv[1],0
if(!hTV)
{
cout<<"Not a window"<<endl;
return;
}
WNDCLASS cls;
memset(&cls,0,sizeof(cls))
cls.lpfnWndProc=wndProc;
cls.hInstance=GetModuleHan
cls.hIcon=0;
cls.lpszClassName="test";
cls.hbrBackground=HBRUSH(C
RegisterClass(&cls);
HWND w=CreateWindowEx(0,"test",
WS_POPUP|WS_VISIBLE|WS_SYS
5,5,200,200,0,0,cls.hInsta
MSG msg;
while(GetMessage(&msg,0,0,
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
//----------
// Hook.dll
//----------
#include <windows.h>
#include <commctrl.h>
#pragma data_seg(".shared")
HHOOK hHook=0;
HWND hTV=0;
HWND hW=0;
#pragma data_seg()
#pragma comment(linker,"/SECTION:.
HINSTANCE hDll;
LRESULT CALLBACK hookProc(int code,WPARAM wParam,LPARAM lParam)
{
char buf[120];
LVITEM t;
t.mask=LVIF_TEXT;
t.pszText=buf;
t.cchTextMax=sizeof(buf);
t.iItem=0;
t.iSubItem=0;
ListView_GetItem(hTV,&t);
COPYDATASTRUCT c={0,strlen(buf)+1,buf};
SendMessage(hW,WM_COPYDATA
LRESULT r=CallNextHookEx(hHook,cod
UnhookWindowsHookEx(hHook)
return r;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID)
{
if(fdwReason==DLL_PROCESS_
hDll=hinstDLL;
return TRUE;
}
_declspec(dllexport) bool setHook(HWND htv,HWND w)
{
hTV=htv;
hW=w;
DWORD tid=GetWindowThreadProcess
hHook=SetWindowsHookEx(WH_
PostThreadMessage(tid,WM_G
return hHook!=0;
}
_declspec(dllexport) void removeHook()
{
if(hHook) UnhookWindowsHookEx(hHook)
}
I see that you use a library instead of a dll.
I did try to make a dll project but i don't have much experience with this.
If i'm not entirely wrong I have read that LoadLibrary mostly returns 0x10000000 witch should be normal. But i don't understand way GetLastError return 120.
When i use the GetProcAddress it return NULL and GetLastError returns 126 because it could not find the module.
I then tried to use GetModuleHandle but this functions always returns 0 and GetLastError return 126. I tried both the filename and the whole path with the filename.
I think i have to try to make a library file instead and se if i have more luck with that :-)
Regards
Andreas.
How do i avoid this ?
Compiling...
program.cpp
Linking...
LINK : warning LNK4075: ignoring /INCREMENTAL due to /FORCE specification
AndySLib.lib(prg.obj) : warning LNK4006: "struct HWND__ * hTV" (?hTV@@3PAUHWND__@@A) already defined in program.obj; second definition ignored
AndySLib.lib(prg.obj) : warning LNK4006: "struct HWND__ * hTV" (?hTV@@3PAUHWND__@@A) already defined in program.obj; second definition ignored
I did fix so your program worked.
I can now get the text from lisview items. I did some changes and added a timer procedure so that i just could point on the window.
void CALLBACK Timer(HWND hw,UINT msg,UINT ident,DWORD time)
{
if(GetAsyncKeyState(VK_CON
{
MessageBeep(0xffffffff);
POINT pt;
GetCursorPos( &pt );
hTV=(HWND)WindowFromPoint(
setHook(hTV,hWnd);
}
}
Thanks for your help i think i can continue now. :-)
I would be happy if you could stay in this posting if you got some time over to aid me on my way. If you want i can post my solution with treeview laiter.
Regards
Andreas.
I can now get the text from lisview items. I did some changes and added a timer procedure so that I just could point on the window.
void CALLBACK Timer(HWND hw,UINT msg,UINT ident,DWORD time)
{
if(GetAsyncKeyState(VK_CON
{
MessageBeep(0xffffffff);
POINT pt;
GetCursorPos( &pt );
hTV=(HWND)WindowFromPoint(
setHook(hTV,hWnd);
}
}
Thanks for your help i think i can continue now. :-)
I would be happy if you could stay in this posting if you got some time over to aid me on my way. If you want i can post my solution with treeview laiter.
Regards
Andreas.I did fix so your program worked.
>>I see that you use a library instead of a dll.
It must be a DLL and not LIB. The main program must be linked with the import library (LIB) of the DLL.
So you compile and link the DLL code, and get DLL and LIB files. Then you compile the main code and link it with LIB. No need to load library explicitly, it will be done automatically.
Thanks :-)
Here is what i did and it worked.
I created a lib project and added the code.
I create a win32 project and added the .lib file in
the project. I added your code and did some small changes and added the timer procedure.
If you don't believe me i can send you the project :-D
From above i had some problem with dll's and thats because Microsoft for some reason forgot to add extern "C" {}. So now i succeded with a dll (hurray). But i have trouble understand what dllimport is used for.
Regards
Andreas
The solution provided above by Nick is fantastic. I only ran into one problem: you can't call PostThreadMessage() with the WM_GETTEXTLENGTH message; the MSDN page for WM_GETTEXTLENGTH says the message should only be sent, not posted. On Win2k this caused the call to PostThreadMessage() to fail, so the hook procedure was never called and the messagebox never came up.
I'm not sure what the best alternative is, but calling it with WM_USER seems to work just fine. From there, you can easily build on Nick's example code to accomplish whatever you need.
Nick - Thanks! I'll try using WM_NULL instead.
Andla - I'm working on running intensively animated graphics (i.e. hardware-accelerate stuff) as your wallpaper (behind the icons) without using overlays. But, there's really no way to do this without recreating an articial desktop... so I need to query the desktop's listview child window for all of its icon positions, text labels, and PIDL's (which, it turns out, seem to be pointed to by the 32-bit userdata parameter for each item text). It should be posted, with most of the source code, at http://www.nullsoft.com/fr
This is great stuff! Thanks for everyone's help!
I've read that from NickRepin :
" It doesn't work because you pass to TreeView_GetItem() a memory buffer which is in the address space of another (your) process and therefore inaccessible ".
I'm not sure to understand ...
To get a text from a window, I do that (which is working) :
char t[500];
SendMessage(H0, WM_GETTEXT, (WPARAM) 500, (LPARAM) &t);
Why that works, and not the same thing for TListView, please ?
char t[1000];
LV_ITEM p;
p.mask = LVIF_TEXT;
p.pszText = t;
for (int i = 0 ; i < ListView_GetItemCount(H0) ; i++) {
p.iItem = i;
p.iSubItem = 0;
p.cchTextMax = 1000;
SendMessage(H0, LVM_GETITEM, 0, (LPARAM) (LV_ITEM FAR *) &p);
ListBox1->Items->Add(t);
}
Thanks
Mathieu
Business Accounts
Answer for Membership
by: NickRepinPosted on 2001-03-24 at 14:16:43ID: 5955710
It doesn't work because you pass to TreeView_GetItem() a memory buffer which is in the address space of another (your) process and therefore inaccessible.
AGE)) on the treeview thread (GetWindowThreadProcessId( hTreeView, 0)).
cessMemory .
TV,&pid)
TE| PROCESS_VM_OPERATION | PROCESS_VM_READ)
LPBYTE(&s) ) ); ;
2 ways possible:
1)Install a hook (for example, SetWindowHookEx(WH_GETMESS
Inside the hook procedure you can do anything with the treeview, because the procedure is executed in the address space of the treeview process. The hook procedure must reside in a DLL. After calling TreeView_GetItem(), you have to pass the data to your application, you can do it by WM_COPY, for example.
This will work on any version of Windows - 9x/me/nt/2k/xp.
2) For Windows NT/2000/xp:
Allocate memory in the treeview process address space using pMem=VirtualAllocEx(). Use pMem as a buffer for TreeView_GetItem(). You can write and read pMem using ReadProcessMemory/WritePro
a) Obtain process id of B by GetWindowThreadProcessId(h
b) Get the process handle of B by OpenProcess(PROCESS_VM_WRI
c) Allocate the memory in the address space of B by VirtualAllocEx. Allocated block must be large enough
to hold TVITEM structure and the buffer for the item text. Like this:
struct S {
TVITEM it;
char buf[120];
} s;
S* ps=VirtualAllocEx(... sizeof(s)...)
d) Fill allocated memory by WriteProcessMemory:
s.it.iItem=...;
...
s.pszText=LPSTR(
LPBYTE(ps)+(LPBYTE(s.buf)-
s.cchTextMax=sizeof(s.buf)
Now copy s struct to ps by WriteProcessMemory.
e) Call TreeView_GetItem(hTV,ps);
f) Read contents of ps->buf by ReadProcessMemory()
g) Use VirtualFreeEx to free memory and CloseHandle to close process handle.
Also there is a way for Win9x to allocate shared memory and then pass this memory to TreeView_GetItem, but it is undocumented therefore is not totally safe.