Help converting C++ Code to Delphi...

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;
LVL 26
Eddie ShipmanAll-around developerAsked:
Who is Participating?

Improve company productivity with a Business Account.Sign Up

x
 
MadshiConnect With a Mentor Commented:
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
 
Eddie ShipmanAll-around developerAuthor Commented:
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
 
MadshiCommented:
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
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
Eddie ShipmanAll-around developerAuthor Commented:
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
 
MadshiCommented:
Thanx for the points. What is "Borland NG"?
0
 
Eddie ShipmanAll-around developerAuthor Commented:
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
 
Eddie ShipmanAll-around developerAuthor Commented:
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
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.