Копирование в буфер обмена

 

Странно, что до сих пор не сделали метода в mql5 для сабжа, но не работает даже обходной путь через WinAPI:

bool CClipboard::CopyTo(string text) {
   bool bReturnvalue = false;
   // Try grabbing ownership of the clipboard 
   if (OpenClipboard(0) != 0) {
      // Try emptying the clipboard
      if (EmptyClipboard() != 0) {
         // Try allocating a block of global memory to hold the text 
         int lnString = StringLen(text);
         int hMem = GlobalAlloc(GMEM_MOVEABLE, (lnString + 1) * 2);
         if (hMem != 0) {
            // Try locking the memory, so that we can copy into it
            int ptrMem = GlobalLock(hMem);
            if (ptrMem != NULL) {
               // Copy the string into the global memory
               lstrcpyW(ptrMem, text);            
               // Release ownership of the global memory (but don't discard it)
               GlobalUnlock(hMem);            

               // Try setting the clipboard contents using the global memory
               if (SetClipboardData(CF_UNICODETEXT, hMem) != 0) {
                  // Okay
                  bReturnvalue = true;   
               } else {
                  PrintFormat("Failed to set the clipboard using the global memory: %d", GetLastError());
                  GlobalFree(hMem);
               }
            } else {
               PrintFormat("Failed to lock memory: %d", GetLastError());
               GlobalFree(hMem);
            }      
         } else {
            PrintFormat("Failed to allocate memory to hold string: %d", GetLastError());
         }
      } else {
            PrintFormat("Failed to empty clipboard: %d", GetLastError());
      }
      // Always release the clipboard, even if the copy failed
      CloseClipboard();
   } else {
      // Failed to open clipboard
   }

   return (bReturnvalue);
}


GlobalLock возвращает NULL, GetLastError: ERROR_HOST_NODE_NOT_RESOURCE_OWNER.

При попытке аллоцировать память через GMEM_FIXED (грязный хак), SetClipboardData также возвращает GetLastError: ERROR_HOST_NODE_NOT_RESOURCE_OWNER

Странно, но на форуме писали что вроде работает этот способ. Может чего поменяли недавно в плане управления процессами выполнения?

 
Andrey Pogoreltsev:

Странно, что до сих пор не сделали метода в mql5 для сабжа, но не работает даже обходной путь через WinAPI:


GlobalLock возвращает NULL, GetLastError: ERROR_HOST_NODE_NOT_RESOURCE_OWNER.

При попытке аллоцировать память через GMEM_FIXED (грязный хак), SetClipboardData также возвращает GetLastError: ERROR_HOST_NODE_NOT_RESOURCE_OWNER

Странно, но на форуме писали что вроде работает этот способ. Может чего поменяли недавно в плане управления процессами выполнения?


Хотите парсить буфер обмена пользователя? 

 
Andrey Pogoreltsev:
приведите весь код, который сразу запустить можно
 

Все работает

#property copyright "Copyright 2013, TheXpert"
#property link      "http://www.trend-lab.ru/"

#import "user32.dll"
   int OpenClipboard(int notUsed); // BOOL
   int CloseClipboard(); // BOOL
   int EmptyClipboard();  // BOOL
   int SetClipboardData(int format, long hMem); // HANDLE
#import "ntdll.dll"
   long memcpy(long dst, uchar& src[], int cnt);

   int RtlGetLastWin32Error();
   int RtlSetLastWin32Error(int dwErrCode);

#import "kernel32.dll"
   long GlobalAlloc(int uFlags, int dwBytes); // HGLOBAL 
   long GlobalLock(long hMem); // void*
   int GlobalUnlock(long hMem); // HGLOBAL 
   int GlobalFree(long hMem); // HGLOBAL 
#import

#define GMEM_MOVEABLE 2
#define GMEM_ZEROINIT 64

#define CF_TEXT 1

void PlaceToClipboard(string toCopy)
{
   uchar buffer[];
   StringToCharArray(toCopy, buffer);
   
   int size = ArraySize(buffer);
   
   RtlSetLastWin32Error(0);
   long hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, size);
   if (hMem == 0)
   {
      Print("Alloc failed, error #", RtlGetLastWin32Error());
      return;
   }
   
   RtlSetLastWin32Error(0);
   long ptr = GlobalLock(hMem);
   
   if (ptr == 0)
   {
      Print("Memory lock failed, error #", RtlGetLastWin32Error());
      return;
   }

   memcpy(ptr, buffer, size);
   GlobalUnlock(hMem);
   
   // now prepare clipboard
   
   long res = OpenClipboard(0);
   if (res == 0)
   {
      Print("Open clipboard failed");
      return;
   }
   
   res = EmptyClipboard();
   if (res == 0)
   {
      Print("Empty clipboard failed");
      CloseClipboard();
      return;
   }
   
   RtlSetLastWin32Error(0);
   res = SetClipboardData(CF_TEXT, hMem);
   if (res == 0)
   {
      Print("Set Data failed, error #", RtlGetLastWin32Error());
   }
   CloseClipboard();
}

void OnStart()
{
   string toClipboard = "toClipboard";
   PlaceToClipboard(toClipboard);
}
 
TheXpert:

Все работает

Спасибо. Помогло выяснить причину. Указатели в х64 8 байтовые. Я брал пример с форума, он под х86.

По идее параметры передаются через стек (_stdcall) и ваш пример не будет работать на х86 для методов, которые используют несколько параметров ( memcpy). Надо проверить)

Причина обращения: