Solved

Help converting C++ Code to Delphi...

Posted on 2002-04-30
7
351 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
Best Practices: Disaster Recovery Testing

Besides backup, any IT division should have a disaster recovery plan. You will find a few tips below relating to the development of such a plan and to what issues one should pay special attention in the course of backup planning.

 
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

PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Sending Gmail through Delphi 3 108
TEMBEDDEDWB how can i change its user agent ? 8 58
firemonkey keyboard covers the controls 1 26
MS Access from Delphi 31 32
The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
In a recent question (https://www.experts-exchange.com/questions/28997919/Pagination-in-Adobe-Acrobat.html) here at Experts Exchange, a member asked how to add page numbers to a PDF file using Adobe Acrobat XI Pro. This short video Micro Tutorial sh…
Email security requires an ever evolving service that stays up to date with counter-evolving threats. The Email Laundry perform Research and Development to ensure their email security service evolves faster than cyber criminals. We apply our Threat…

809 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