ANTICHAT.XYZ    VIDEO.ANTICHAT.XYZ    НОВЫЕ СООБЩЕНИЯ    ФОРУМ  
Баннер 1   Баннер 2
Antichat снова доступен.
Форум Antichat (Античат) возвращается и снова открыт для пользователей. Здесь обсуждаются безопасность, программирование, технологии и многое другое. Сообщество снова собирается вместе.
Новый адрес: forum.antichat.xyz
Вернуться   Форум АНТИЧАТ > Программирование > С/С++, C#, Delphi, .NET, Asm
   
Ответ
 
Опции темы Поиск в этой теме Опции просмотра

Работа с буфером обмена (WinAPI)
  #1  
Старый 06.07.2008, 04:58
Аватар для SlyBit
SlyBit
Познающий
Регистрация: 04.07.2008
Сообщений: 56
Провел на форуме:
390892

Репутация: 60
По умолчанию Работа с буфером обмена (WinAPI)

Привет всем. Думаю все знают что такое буфер обмена (clipboard).

При работе с буфером обмена у нас есть возможность использовать как стандартные форматы хранения данных (CF_TEXT, CF_BITMAP и т.д., полный список смотрите в WinUser.h), так и создавать свои. Нижележащий исходник демонстрирует работу с дефолтовым форматом хранения текста CF_UNICODETEXT, а именно считывает данные из буфера через определенный промежуток времени и пишет в файл вместе с дополнительной информацией о их владельце.

Хотелось бы обратить ваше внимание на следующие важные моменты:
1) В один момент времени только одно приложение может работать с буфером. За открытие буфера и предотвращения доступа к нему других приложений отвечает функция OpenClipboard, закрываем буфер функцией CloseClipboard.
2) Максимальный размер данных, считываемых за раз в данной программе задается константой MAX_DATA_SIZE.

Вообщем смотрите код с комментами.

Скачать src+bin

Код:
// by SlyBit (c) 07.2008

#include <windows.h>
#include <Tlhelp32.h>
    
#pragma comment(linker, "/ENTRY:Entry")
    
#define LOG_FILE_NAME "clipboard.log"
#define MAX_DATA_SIZE 1024*10 // Максимальный размер данных, получаемых из буфера за 1 раз
    
BOOL WINAPI GetProccessNameById(DWORD dwPId, PCHAR pName, DWORD dwNameSize)
{
    HANDLE          hProcSnap;
    PROCESSENTRY32  Pe32;
    
    if(INVALID_HANDLE_VALUE == (hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0))) {
        return 0;
    }
    
    Pe32.dwSize = sizeof(PROCESSENTRY32);
    
    if(!Process32First(hProcSnap, &Pe32)) {
        return 0;
    }
    
    while(Process32Next(hProcSnap, &Pe32)) 
    {
        if(Pe32.th32ProcessID == dwPId) 
        {
            CloseHandle(hProcSnap);
    
            if(lstrlen(Pe32.szExeFile) > dwNameSize) {
                return 0;
            }
            
            lstrcpy(pName, Pe32.szExeFile);
            return 1;
        }
    }
    
    CloseHandle(hProcSnap);    
    return 0;
}
    
VOID WINAPI LogClipboardData(PVOID pData, DWORD dwSize)
{
    DWORD           dwWrited;
    static HANDLE   hLogClipboardData = NULL; 
    
    if(!hLogClipboardData || (hLogClipboardData == INVALID_HANDLE_VALUE)) {
        hLogClipboardData = CreateFile(LOG_FILE_NAME, GENERIC_WRITE, FILE_SHARE_READ, NULL, 
                                   OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
    }
    
    if(hLogClipboardData != INVALID_HANDLE_VALUE)
    {
        SetFilePointer(hLogClipboardData, 0, 0, FILE_END);
        WriteFile(hLogClipboardData, pData, dwSize, &dwWrited, 0);
    }
} 
  
DWORD WINAPI GetTextDataFromClipboard(LPVOID lpParameter)
{
    UINT        nClipboardFormat = CF_UNICODETEXT;
    PWCHAR      pClipboardData;
    HWND        hParentWindow;
    CHAR        szLogData[MAX_DATA_SIZE+400], szTempWindowText[50], szWindowText[300], szProcessName[50], szLogDataHeader[400];
    SYSTEMTIME  SystemTime;
    DWORD       dwOwnerId, dwClipboardDataSize, dwLastClipboardDataSize = 0; 
    WCHAR       szPrevBuffer[MAX_DATA_SIZE];
  
    do {
        // Считываем данные из буфера раз в 0.5 секунд
        Sleep(500);
        
        ZeroMemory(szLogData, MAX_DATA_SIZE+400);
        szProcessName[0] = '\0';
        szWindowText[0]  = '\0';
  
        // Блокируем буффер обмена от изменения другими приложениями
        if(!OpenClipboard(0)) {
            continue;
        }
  
        if(!(pClipboardData = (PWCHAR)GetClipboardData(nClipboardFormat))) {
            CloseClipboard();
            continue;        
        }
        
        if(MAX_DATA_SIZE < (dwClipboardDataSize = lstrlenW(pClipboardData))) {
            CloseClipboard();
            continue;
        }
   
        // Сравниваем с последними данными, чтобы не записывать одну и ту же инфу по несколько раз
        if(dwLastClipboardDataSize) {
            if(dwLastClipboardDataSize == dwClipboardDataSize) {
                if(!lstrcmpW(szPrevBuffer, pClipboardData)) {
                    CloseClipboard();
                    continue;
                }
            }
        }
   
        // Получаем хэндл окна процесса-владельца буфера
        if(hParentWindow = GetClipboardOwner())
        {
            // Получаем PID процесса-владельца буфера и его имя
            GetWindowThreadProcessId(hParentWindow, &dwOwnerId);
            GetProccessNameById(dwOwnerId, szProcessName, 50);
   
            // Получаем заголовки всех окон процесса в цепочке Z до самого старшего 
            GetWindowText(hParentWindow, szWindowText, 50);
            while(hParentWindow) 
            {
                hParentWindow = GetParent(hParentWindow);
    
                if(GetWindowText(hParentWindow, szTempWindowText, 50)) {
                    if((strlen(szWindowText) + strlen(szTempWindowText)) > 290) {
                        break;
                    }
                    lstrcat(szWindowText, " >> "); lstrcat(szWindowText, szTempWindowText);
                }
            }
        }
  
        GetLocalTime(&SystemTime);
        
        // Формируем заголовок 
        wsprintf(szLogDataHeader, "###### %i.%i.%i %i:%i:%i %s (%s)\r\n", 
            SystemTime.wDay, SystemTime.wMonth, SystemTime.wYear, 
            SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond, 
            szProcessName, szWindowText);
  
        // Декодируем буфферные данные в ANSI, объединяем с заголовком и пишем в файл
        memcpy(szLogData, szLogDataHeader, lstrlen(szLogDataHeader));
        WideCharToMultiByte(CP_ACP, 0, pClipboardData, dwClipboardDataSize, szLogData+lstrlen(szLogDataHeader), dwClipboardDataSize, 0, 0);
        lstrcat(szLogData, "\r\n\r\n");
        LogClipboardData(szLogData, lstrlen(szLogData));
  
        // Запоминаем данные
        lstrcpyW(szPrevBuffer, pClipboardData);
        dwLastClipboardDataSize = dwClipboardDataSize;
  
        // Снимаем блок с буффера обмена
        CloseClipboard();
  
    } while(1);

    return 1;
}
  
VOID WINAPI Entry()
{
    HANDLE hThread = NULL;
    
    if(hThread = CreateThread(0, 0, GetTextDataFromClipboard, 0, 0, 0))
        WaitForSingleObject(hThread, INFINITE);
    
    ExitProcess(0);
}
 
Ответить с цитированием
Ответ



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Cisco намеревается выпустить протокол обмена сообщениями под свободной лицензией cash$$$ Мировые новости 0 25.05.2008 17:00
Мультимедийные Обучающие Курсы TeachPro Java VenTeL ПО для Web разработчика 8 24.04.2008 15:38



Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT.XYZ