Solved

Help converting C++ Code to Delphi...

Posted on 2002-04-30
7
353 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
  • 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
Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
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

Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

Question has a verified solution.

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

Suggested Solutions

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
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…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

828 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