Solved

Help converting C++ Code to Delphi...

Posted on 2002-04-30
7
354 Views
Last Modified: 2010-04-04
I have this code from one of Jeffrey Richter's articles in
the September version of MSJ {watch for wrap}
(http://www.microsoft.com/msj/defaultframe.asp?
page=/msj/0997/win320997.htm&nav=/msj/0997/newnav.htm)
that will read the contents of another app's Listview to
the clipboard.

I need to be able to read the ItemText to defined class.
Can someone help me out with the conversion process?

Here's the C++ Code, the attempted Delphi conversion is
below...

   // Open a handle to the remote process's kernel object
   DWORD dwProcessId;
   GetWindowThreadProcessId(hwndLV, &dwProcessId);
   HANDLE hProcess = OpenProcess(
      PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE,
      FALSE, dwProcessId);

   if (hProcess == NULL) {
      MessageBox(hwnd, __TEXT("Could not communicate with process"),
         g_szAppName, MB_OK | MB_ICONWARNING);
      return;
   }

   // Prepare a buffer to hold the ListView's data.
   // Note: Hardcoded maximum of 10240 chars for clipboard data.
   // Note: Clipboard only accepts data that is in a block allocated
   //       with GlobalAlloc using the GMEM_MOVEABLE
   //            and GMEM_DDESHARE flags.
   HGLOBAL hClipData = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
                                  sizeof(TCHAR) * 10240);
   LPTSTR pClipData = (LPTSTR) GlobalLock(hClipData);
   pClipData[0] = 0;

   // Allocate memory in the remote process's address space
   LV_ITEM* plvi = (LV_ITEM*) VirtualAllocEx(hProcess,
                    NULL, 4096, MEM_RESERVE | MEM_COMMIT,
                    PAGE_READWRITE);

   // Get each ListView item's text data
   for (int nIndex = 0; nIndex < nCount; nIndex++) {

      // Initialize a local LV_ITEM structure
      LV_ITEM lvi;
      lvi.mask = LVIF_TEXT;
      lvi.iItem = nIndex;
      lvi.iSubItem = 0;
      // NOTE: The text data immediately follows the LV_ITEM structure
      //       in the memory block allocated in the remote process.
      lvi.pszText = (LPTSTR) (plvi + 1);
      lvi.cchTextMax = 100;

      // Write the local LV_ITEM structure to the remote memory block
      WriteProcessMemory(hProcess, plvi, &lvi, sizeof(lvi), NULL);

      // Tell the ListView control to fill the remote LV_ITEM structure
      ListView_GetItem(hwndLV, plvi);

      // If this is not the first item, add a carriage-return/linefeed
      if (nIndex > 0) lstrcat(pClipData, __TEXT("\r\n"));

      // Read the remote text string into the end of our
      // clipboard buffer
      ReadProcessMemory(hProcess, plvi + 1,
         &pClipData[lstrlen(pClipData)], 1024, NULL);
   }

   // Free the memory in the remote process's address space
   VirtualFreeEx(hProcess, plvi, 0, MEM_RELEASE);

   // Cleanup and put our results on the clipboard
   CloseHandle(hProcess);
   OpenClipboard(hwnd);
   EmptyClipboard();
   BOOL fOk = (SetClipboardData(CF_TEXT, hClipData) == hClipData);
   CloseClipboard();
   if (!fOk) {
      GlobalFree(hClipData);
      MessageBox(hwnd, __TEXT("Error putting text on the clipboard"),
             g_szAppName, MB_OK | MB_ICONINFORMATION);
   }


****************** Delphi code *********************

var
  Buffer: PChar;
  Len: Integer;
  dwProcessId, numbytes: DWORD;
  plvi: Pointer;
  lvi: LV_ITEM;
  hProcess : THandle;
  nIndex: Integer;
begin
  // Open a handle to the remote process's kernel object
  // Passing Handle of the listview to this function
  GetWindowThreadProcessId(Handle, @dwProcessId);
  hProcess := OpenProcess(PROCESS_VM_OPERATION or
                          PROCESS_VM_READ or
                          PROCESS_VM_WRITE,FALSE, dwProcessId);
  if hProcess = 0 then
    ShowMessage('Could not communicate with process');
  // Prepare a buffer to hold the ListView's data.
  // Note: Hardcoded maximum of 10240 chars for clipboard data.
  // Note: Clipboard only accepts data that is in a block
  //       allocated with GlobalAlloc using the GMEM_MOVEABLE and    
  //       GMEM_DDESHARE flags.
  // Allocate memory in the remote process's address space
  plvi := VirtualAllocEx(hProcess, 0, 4096,
                         MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);
  // Get each ListView item's text data
  // This class has a Count property that is populated with the
  // count of items in the listview.
  for nIndex := 0 to Count do
  begin
    // Initialize a local LV_ITEM structure
    lvi.mask := LVIF_TEXT;
    lvi.iItem := nIndex;
    lvi.iSubItem := 0;
    // NOTE: The text data immediately follows the LV_ITEM structure
    //       in the memory block allocated in the remote process.
    lvi.pszText := PChar(plvi);
    lvi.cchTextMax := 100;
    // Write the local LV_ITEM structure to the remote memory block
    WriteProcessMemory(hProcess, plvi, @lvi, sizeof(lvi), numbytes);
    // Tell the ListView control to fill the remote LV_ITEM structure
    ListView_GetItem(Handle, lvi);
    // Read the remote text string into the end of our clipboard buffer
    ReadProcessMemory(hProcess, PChar(plvi), @Buffer, 1024, numbytes);
    // Now that we have the text, let's add it to our stringlist.
    Items.Add(String(Buffer); // Items is a TStringList in the class.
  end;
  // Free the memory in the remote process's address space
  VirtualFreeEx(hProcess, plvi, 0, MEM_RELEASE);
  // Cleanup and put our results on the clipboard
  CloseHandle(hProcess);
end;
0
Comment
Question by:EddieShipman
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
7 Comments
 
LVL 20

Accepted Solution

by:
Madshi earned 100 total points
ID: 6981268
Seems like Jeffrey Richter had the same idea that I had, didn't know his article. Anyway, here is a question with the same topic, I answered there with full Delphi code:

http://www.experts-exchange.com/delphi/Q.20288008.html

Please note that both my code there and Jeffrey's code here only works in NT based systems (NT4, 2k, XP), not in win9x/ME. But I've added a comment to the other question about how to do it in win9x/ME. It's possible, there, too. With a bit of hacking...

Regards, Madshi.
0
 
LVL 26

Author Comment

by:EddieShipman
ID: 6981306
I see you only handle subitem 0 in that code. How would I get ALL the subitems. Basically, I want to "clone" the listview from another app to my listview...
0
 
LVL 20

Expert Comment

by:Madshi
ID: 6981344
Well, Jeffrey's code also only handles subitem 0 or am I missing something?   :-)

Anyway, you can give in other subitem indexes, of course, too. No problem...
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 26

Author Comment

by:EddieShipman
ID: 6981576
The GrabListView program from the other thread really worked for me...Thanks for the link...
You get the points...

BTW, do you frequent the Borland NG's? What is your
NG handle?

0
 
LVL 20

Expert Comment

by:Madshi
ID: 6981625
Thanx for the points. What is "Borland NG"?
0
 
LVL 26

Author Comment

by:EddieShipman
ID: 6981639
Borland newsgroups on forums.borland.com.

If not, I think you should, as your knowledge could be very
useful there. You would probably qualify for TeamB admission. TeamB is the group of experts whit very in-depth
knowledge of Delphi...

0
 
LVL 26

Author Comment

by:EddieShipman
ID: 6981643
I'm surprised you didn't know about them, you've posted a few messages there:

"Mathias Rauen" <madshi@gmx.net>

Hey, I'm also surprised you place your bank account info on your web site..
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…

710 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question