Где воздух гор - там тишина снегов, молчание камней и дремлет сила

Программирование Windows

Пишем собственный screencapturer для Windows

2018-03-09 05:12:16








 В повседневной работе с Windows иногда , однако, все же возникает потребность в получений копий снимков с текущего рабочего стола
Windows. Для этого есть масса свободных или платных программ, а мы напишем свою. Тем боле, займет это очень мало времени. Для этого нам
нужно только работающий компьютер с установленной операционной системой Windows, MicrosoftVisualStudio 2005  и  конечно,  MSDN. Сама процедура разработка будет описана пошагово,  там же  будут  те части программного  кода, которые будут нами созданы.

1. Как обычно, создаем шаблон программы. Для этого запускаем MicrosoftVisualStudio 2003 , выбираем “NewProject…”, затем “VisualC++”. В этом меню выбираем “MFCApplication”. Выбираем путь где будет расположен наш проект и вводим название “screencapture”. (Хотя каждый может ввести любое название J )  Жмем «ОК». Дальше мы выбираем «ApplicationType» - “Dialogbased”. Если кто желает подарить другу или подруге свою программу, то нужно выбрать  “UseMFCinstaticlibrary”. Все остальные настройки можно оставить без изменений.
2. Открываем проект. Компилируем его, чтобы увидеть, то  что мы имеем сейчас.  Для начала удаляем «TODO: Place dialog controls here.» и обе кнопки “OK”  и  “Cancel”.  Увеличим размеры окна, например сделаем их 850x650. Отредактируем заголовок программы и введем туда “Screen Capturer”
       Затем, идем в редактор ресурсом и редактируем иконку «IDR_MAINFRAME»
       Эта   икона в последствии будет нам использована, но поскольку
       стандартный вид не совсем удобный, нам надо то-то специфическое.
      Рисуем иконку новую на основе существующей или создаем новую.
3. Теперь создаем в редакторе ресурсов новое меню. Добавляем «AddResource», там выбираем “New-> Menu”. Переименовываем  его из “IDR_MENU1”  в  “IDR_MENU_TRAY”. Затем займемся редактированием самого меню. Назовем его к примеру “Action”, затем добавляем
в под пункты “Get Screen”, “Hide In Tray”, “Restore” и  “Exit”. Перед последним пунктом  нажмем клавишу «-» для того, чтобы отделить   “Exit” от
остальных команд.
       4.  На этом с ресурсами все, и мы начнем программировать.  По логике работы программы, нам нужно, чтобы  программа была не видна
            в момент  получения снимка экрана. Значит, она должна находится в системном трее, той области, где приложение свернуто до размеров иконки. Сначала создадим  новую переменную типа NOTIFYICONDATA с именем tray_icon для класса CscreencaptureDlg.cpp  Обозначим ее  как  “public”. Это структура, которая будет использована для хранения данных  для обработки сообщений системного трея.
5. Теперь займемся нашим меню. Создадим переменную типа CMenu и назовем ее “menu” опять же  для класса CscreencaptureDlg.cpp. Затем в переходим в этом классе к методу OniInitDialog() и после  комментариев  // TODO: Addextrainitializationhere
пишем такой код
 
            menu.LoadMenu(IDR_MENU_TRAY);
            SetMenu(&menu);
   
           Первая строка загружает в переменную меню из ресурсов, в вторая делает его видимы на окне нашего приложения.
           Компилируем программу и видим результат ее работы, - появляется наше меню.
           Теперь переходим снова в редактор ресурсов и назначаем обработчики событий для пунктов меню. Сначала
           добавляем обработчик к пункту “Exit”. Делаем правый клик мышью на выбранном нами пункте меню и из выпавшего списка опций
           выбираем “AddEventHandler…”. Затем выбираем обработчик типа COMMAND и связываем с классом CscreencaptureDlg.cpp.
          В открывшемся окне нам нужно ввести код обработчика.
 
            void CscreencaptureDlg::OnActionExit(){
            EndDialog(0);
              }
  
    Сперва мы создаем переменную типа int и присваиваем ей значение 1. Это сделано скорее с данью традиции,
     можно присвоить любое значение этого же типа. Потому что метод EndDialog (int someresult);
   принимает  значения этого типа. Сам же метод, согласно его описанию и названию, просто уничтожает модальное
   диалоговое  окно.
 
6. Чтобы создать обработчик сообщений для системного трея, мы должны сделать следующее;  ввести в файл  Ressource.h
       добавляем идентификатор иконки:
 
             #define ID_TrayIcon                135
 
      Число «135» взято произвольно, главное чтобы не совпадало с уже существующими ID ресурсов. Этот ID будет впоследствии использовано для
      обращения к иконке. Затем мы создаем обработчик события для системного трея -  в классу диалогового окна вводим новое сообщение:
   
      #define WM_TRAYICONNOTIFY WM_USER+1
 
            все сообщения типа WM_USER+1 представляют собой частные сообщения, определяемые самим пользователем.
           Затем в карту сообщений  добавляем собственно обработчик сообщений для трея
        
            ON_MESSAGE(WM_ICON, OnTrayIcon)
 
            После чего она будет выглядеть таким образом:
 
            BEGIN_MESSAGE_MAP(CscreencaptureDlg, CDialog)
                 ON_WM_SYSCOMMAND()
                 ON_WM_PAINT()
                ON_WM_QUERYDRAGICON()
                 //}}AFX_MSG_MAP
                 ON_COMMAND(ID_ACTION_EXIT, OnActionExit)
                 ON_COMMAND(ID_ACTION_HIDE, OnActionHide)
                 ON_MESSAGE(WM_ICON, OnTrayIcon)
                 ON_COMMAND(ID_ACTION_RESTORE, OnActionRestore)
             END_MESSAGE_MAP()
    
           И самое главное, надо добавить новый метод, который и собственно  будет обрабатывать это сообщение. Для этого мы добавим к   классу CscreencaptureDlg.cpp.
           такой метод, кликнув мышью на “ClassView” ( « Вид Классов»)  и выбрав класс диалогового окна. В выпавшем меню выберем “Add..-> AddFunction”
           Новый метод  OnTrayIcon будет  возвращать значения типа LRESULT и принимать   WPARAM wp, LPARAM lp. Затем вводим внутрь его такой код:
 
       LRESULT CscreencaptureDlg::OnTrayIcon(WPARAM wp, LPARAM lp) {
             
      if(wp != tray_icon.uID || lp != WM_LBUTTONDBLCLK &&
       lp != WM_RBUTTONUP)
        return 0;
 
       // Получениеподменю
      CMenu *SubMenu = menu.GetSubMenu(0);
   
      // Если была нажата правая кнопка мыши
      if(lp == WM_RBUTTONUP)
       {
        // Первый пункт меню выделяется "жирным" шрифтом
        SubMenu->SetDefaultItem(0, true);
        // Получение позиции курсора
        CPoint mouse;
        GetCursorPos(&mouse);
        // Установка окна, которое будет получать фокус
        // (в данном случае это иконка и связанное с ней меню)
        ::SetForegroundWindow(tray_icon.hWnd);
        // Отображение контекстного меню
        SubMenu->TrackPopupMenu(0, mouse.x, mouse.y, this);
         }
      // Если была дважды нажата левая кнопка мыши
       else if(lp == WM_LBUTTONDBLCLK)
        // Имитация выбора пункта меню по умолчанию
        ::SendMessage(tray_icon.hWnd, WM_COMMAND,
                      SubMenu->GetMenuItemID(0), 0);
          return 1;
           
      }
      
     
 
 
  7.   Далее мы в методе OniInitDialog()  класса CscreencaptureDlg.cpp. инициализируем  переменную структуры  NOTIFYICONDATA
       tray_icon
 
         memset(&tray_icon, 0, sizeof(NOTIFYICONDATA));
      // Размер структуры
      tray_icon.cbSize = sizeof(NOTIFYICONDATA);
      // Иконка
      tray_icon.hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
      // Дескриптор окна, получающего сообщения из трея
      tray_icon.hWnd = m_hWnd;
      // Подсказка
      strcpy(tray_icon.szTip, "Get Screen");
      // Идентификаторобработчика
      tray_icon.uCallbackMessage = WM_ICON;
       // Установкафлагов
      tray_icon.uFlags = NIF_TIP | NIF_MESSAGE | NIF_ICON;
      // Идентификатор иконки
    trya_icon.uID = ID_TrayIcon;
8. Снова возвращаемся в редактор ресурсов к нашему меню и аналогичным способом добавляем обработчик к пункту   “HideInTray”.
           Затем редактируем его код:
 
         voidCscreencaptureDlg::OnActionHide()
        {
           
      ShowWindow(SW_HIDE);
            //окноминимизируется
     
     Shell_NotifyIcon(NIM_ADD, &trray_icon);
     // В трее появляется иконка
 
        }
           
           Затем компилируем программу. Мы видим, что после нажатия на пункт меню “HideInTray” появляется иконка в системном трее и окно исчезает.
          
      9. Аналогичным способом добавляем обработчик к  пункту меню “Restore”:
 
          void CscreencaptureDlg::OnActionRestore()
           {
            // Удалениеиконкиизтрея
           Shell_NotifyIcon(NIM_DELETE, &tray_icon);
  
               // Отображение главного окна
            ShowWindow(SW_NORMAL);
          // Теперь фокус будет получать главное окно
           ::SetForegroundWindow(m_hWnd);        
 
         }
 
10.    Компилируем приложение, пробуем. Если не было синтаксических ошибок, то все работает. J. Теперь перейдем к самому главному, тому, для чего мы создали
       эту  программу.  Нам потребуется использования класса контекста устройства, для чего мы  создаем новую переменную для класса диалогового окна –
       CDC DC. Далее создаем новый метод GetScreen().
 
 
     void CscreencaptureDlg::GetScreen(void)
      {
              int Width=GetSystemMetrics(SM_CXSCREEN);
            //получемширину  экрана
            int Height=GetSystemMetrics(SM_CYSCREEN);
            //получем высоту экрана
            CDC dc;
            //локальная переменная контекста устройства
            HDC h=::GetDC(NULL);
            //получаем дескриптор окна
            dc.Attach(h);
            //присоединемя его к переменной контекста устройства
            DC.CreateCompatibleDC(&dc);
            //размещаем данный контекст устройства в памяти
            CBitmap Win;
            //cоздаем локальную переменную класса CBitmap
            Win.CreateCompatibleBitmap(&dc,Width,Height);
           //cоздаем совместимый с bimap контекст устройства
            DC.SelectObject(&Win);
            //выбираем контекст устройства
            DC.BitBlt(0,0,Width,Height,&dc,0,0,SRCCOPY);
            //копируем указанную область экрана
            dc.Detach();
            //освобождаем локальный контекст устройства
            ::ReleaseDC(NULL, h);
            //SaveBitmap("c:\\bmp\\screen.bmp",(HBITMAP)Win,0);
            DC.DeleteDC();
            //освобождаем глобальный контекст устройства
            MessageBox("This screen was caputered well");
            //сообщение об успешном выполнени задачи
           
    }
 
 
 Теперь добавим новый обработчик сообщений к пункту меню “GetScreen” в редакторе ресурсов.
    
    void CscreencaptureDlg::OnActionGetscreen()
    {
       ShowWindow(SW_HIDE);
        //скрываем основное окно программы
         ::Sleep(1000);
      //задержка исполнения в миллисекундах
       GetScreen();
       //получаем картинку экрана
       Shell_NotifyIcon(NIM_ADD, &tray_icon);
       //убираем программу в трей
    }
Пауза нам нужна, чтобы в наш снимок экрана не попало окно нашей программы.
 
 
11.    Все работает замечательно, только никакой выгодны лично для нас. Потому что мы не можем увидеть то, что сохраняет программа.  Для этого  нам нужно создать новый  служебный метод класса, который будет сохранять полученный результат в файл. Добавляем новый метод SaveBitmap, который возвращает тип BOOL.
  
   
          BOOL CscreencaptureDlg::SaveBitmap(LPCSTR FileName, HBITMAP hBitmap, HPALETTE  hPal)
       {
           BOOL bResult = FALSE;
               //служебная булевая переменная
 
             PICTDESC stPictDesc;
              // переменная структуры  PICTDESC  для описания картинки
             stPictDesc.cbSizeofstruct = sizeof(PICTDESC);
             //задаем размеры переменной этой структуры
              stPictDesc.picType = PICTYPE_BITMAP;
            stPictDesc.bmp.hbitmap = hBitmap;
           //устанавливаемтипкак bitmap
              stPictDesc.bmp.hpal = hPal;
             //выбираем текущую палитру
 
              LPPICTURE pPicture;
            //создаем переменную структуры, содержащую информацию о клиентской области
              HRESULT hr = OleCreatePictureIndirect( &stPictDesc, IID_IPicture, FALSE, reinterpret_cast(&pPicture) );
              //создаем объект  картинку
  
               if ( SUCCEEDED(hr) )
                    {
                  //если картинка создана
                 LPSTREAM pStream;
                    hr = CreateStreamOnHGlobal( NULL, TRUE, &pStream );
 
              //создаем объект Stream  в памяти используя полученный объект hr 
                if ( SUCCEEDED(hr) )
                    {
                         
                  long lBytesStreamed = 0;
                  hr = pPicture->SaveAsFile( pStream, TRUE, &lBytesStreamed );
                         //сохраняем картинку в файле
                  if ( SUCCEEDED(hr) )
                 {
                    HANDLE hFile = CreateFile( FileName,
                                       GENERIC_WRITE,
                                       FILE_SHARE_READ,
                                       NULL,
                                       CREATE_ALWAYS,
                                       FILE_ATTRIBUTE_NORMAL,
                                       NULL );
                  //создаем дескриптор файла
 
                     if ( hFile )
                  {
               HGLOBAL hMem = NULL;
               GetHGlobalFromStream( pStream, &hMem );
               LPVOID lpData = GlobalLock( hMem );
 
               DWORD dwBytesWritten;
               bResult = WriteFile( hFile, lpData, lBytesStreamed, &dwBytesWritten, NULL );
               bResult &= ( dwBytesWritten == (DWORD)lBytesStreamed );
              //записываемданныеизпамятивфайл
            
               GlobalUnlock(hMem);
               CloseHandle(hFile);
 
            }
         }
            
         pStream->Release();
      }
       
      pPicture->Release();
   }
//освобождаемиспользуемыересурсы
   return bResult;  
 
 
}
 
 
12.    После этого редактируем метод GetScreen(), добавив в него код сохранение файла bmp. После правки этот код будет выглядеть таким образом:
 
      void CscreencaptureDlg::GetScreen(void)
        {
            CString path="d:\\myscreens\\current_screen.bmp";
            //задаем путь к файлу, в которм будет храниться картинка
              int Width=GetSystemMetrics(SM_CXSCREEN);
            //получемширину  экрана
            int Height=GetSystemMetrics(SM_CYSCREEN);
            //получем высоту экрана
            CDC dc;
            //локальная переменная контекста устройства
            HDC h=::GetDC(NULL);
            //получаем дескриптор окна
            dc.Attach(h);
            //присоединемя его к переменной контекста устройства
            DC.CreateCompatibleDC(&dc);
            //размещаем данный контекст устройства в памяти
            CBitmap Win;
            //cоздаем локальную переменную класса CBitmap
            Win.CreateCompatibleBitmap(&dc,Width,Height);
             //cоздаем совместимый с bimap контекст устройства
            DC.SelectObject(&Win);
            //выбираем контекст устройства
            DC.BitBlt(0,0,Width,Height,&dc,0,0,SRCCOPY);
            //копируем указанную область экрана
            dc.Detach();
            //освобождаем локальный контекст устройства
            ::ReleaseDC(NULL, h);
            SaveBitmap(path,(HBITMAP)Win,0);
            DC.DeleteDC();
            //освобождаемглобальныйконтекстустройства
            MessageBox("This screen was caputered well");
            //сообщение об успешном выполнении задачи
        }
 
 
Директорий файла, где будет храниться картинка, нужно создать вручную, хотя в дальнейшем можно сделать и программно J. Нам остается  добавить еще  одну опцию в программу. Об этом  ниже.
13.    Несколько неудобно каждый раз, чтобы увидеть снимок экрана ходить в каталог, где храниться текущая версия файла. Мы переопределим  стандартный метод окна
для этой цели. Код будет таким:
 
     void CscreencaptureDlg::OnPaint()
        {
            CPaintDC dc(this);
            // создаем контекст устройства для рисования
            CDC MemDC;
            // создаем локальная переменная контекста устройства
            CString path="C:\\bmp\\screen.bmp";
            //указываем путь к файлу для чтения
             RECT Rect;
            GetClientRect(&Rect);
             //создаем переменную структуры CRECT и заполняем ее.
            HBITMAP hBitmap = (HBITMAP)LoadImage(NULL,path, IMAGE_BITMAP, 0,    0, LR_LOADFROMFILE);
            MemDC.CreateCompatibleDC(&dc);
            MemDC.SelectObject(hBitmap);
            //создаем bitmap и загружаем его в контекст устройства
            dc.StretchBlt(0,0, Rect.right,       Rect.bottom,&MemDC,0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_  CYSCREEN),SRCCOPY);
   //отображаем картинку в нашем окне.
}
 
14.    Компилируем программу и пробуем. Теперь можно получать снимки рабочего стола и тут же просматривать их. Программа очень простая, но в тоже время обладает необходимой функциональностью. В дальнейшем ее можно модифицировать и улучшить, если конечно, это будет нужно J
 
Здесь и далее полный исходный код программы:
 
// screencapture.cpp : Defines the class behaviors for the application.
//
 
#include "stdafx.h"
#include "screencapture.h"
#include "screencaptureDlg.h"
 
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
 
 
// CscreencaptureApp
 
BEGIN_MESSAGE_MAP(CscreencaptureApp, CWinApp)
            ON_COMMAND(ID_HELP, CWinApp::OnHelp)
END_MESSAGE_MAP()
 
 
// CscreencaptureApp construction
 
CscreencaptureApp::CscreencaptureApp()
{
            // TODO: add construction code here,
            // Place all significant initialization in InitInstance
}
 
 
// The one and only CscreencaptureApp object
 
CscreencaptureApp theApp;
 
 
// CscreencaptureApp initialization
 
BOOL CscreencaptureApp::InitInstance()
{
            // InitCommonControls() is required on Windows XP if an application
            // manifest specifies use of ComCtl32.dll version 6 or later to enable
            // visual styles.  Otherwise, any window creation will fail.
            InitCommonControls();
 
            CWinApp::InitInstance();
 
            AfxEnableControlContainer();
 
            // Standard initialization
            // If you are not using these features and wish to reduce the size
            // of your final executable, you should remove from the following
            // the specific initialization routines you do not need
            // Change the registry key under which our settings are stored
            // TODO: You should modify this string to be something appropriate
            // such as the name of your company or organization
            SetRegistryKey(_T("Local AppWizard-Generated Applications"));
 
            CscreencaptureDlg dlg;
            m_pMainWnd = &dlg;
            INT_PTR nResponse = dlg.DoModal();
            if (nResponse == IDOK)
            {
                        // TODO: Place code here to handle when the dialog is
                        //  dismissed with OK
            }
            else if (nResponse == IDCANCEL)
            {
                        // TODO: Place code here to handle when the dialog is
                        //  dismissed with Cancel
            }
 
            // Since the dialog has been closed, return FALSE so that we exit the
            //  application, rather than start the application's message pump.
            return FALSE;
}
 
// screencaptureDlg.cpp : implementation file
//
 
#include "stdafx.h"
#include "screencapture.h"
#include "screencaptureDlg.h"
#include ".\screencapturedlg.h"
 
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
 
 
// CAboutDlg dialog used for App About
 
class CAboutDlg : public CDialog
{
public:
            CAboutDlg();
 
// Dialog Data
            enum { IDD = IDD_ABOUTBOX };
 
            protected:
            virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
 
// Implementation
protected:
            DECLARE_MESSAGE_MAP()
};
 
#define WM_ICON WM_APP + 1
 
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}
 
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
            CDialog::DoDataExchange(pDX);
}
 
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
 
 
// CscreencaptureDlg dialog
 
 
 
CscreencaptureDlg::CscreencaptureDlg(CWnd* pParent /*=NULL*/)
            : CDialog(CscreencaptureDlg::IDD, pParent)
{
            m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
 
void CscreencaptureDlg::DoDataExchange(CDataExchange* pDX)
{
            CDialog::DoDataExchange(pDX);
}
 
BEGIN_MESSAGE_MAP(CscreencaptureDlg, CDialog)
            ON_WM_SYSCOMMAND()
            ON_WM_PAINT()
            ON_WM_QUERYDRAGICON()
            //}}AFX_MSG_MAP
            ON_COMMAND(ID_ACTION_EXIT, OnActionExit)
            ON_COMMAND(ID_ACTION_HIDE, OnActionHide)
            ON_MESSAGE(WM_ICON, OnTrayIcon)
            ON_COMMAND(ID_ACTION_RESTORE, OnActionRestore)
            ON_COMMAND(ID_ACTION_GETSCREEN, OnActionGetscreen)
END_MESSAGE_MAP()
 
 
// CscreencaptureDlg message handlers
 
BOOL CscreencaptureDlg::OnInitDialog()
{
            CDialog::OnInitDialog();
 
            // Add "About..." menu item to system menu.
 
            // IDM_ABOUTBOX must be in the system command range.
            ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
            ASSERT(IDM_ABOUTBOX < 0xF000);
 
            CMenu* pSysMenu = GetSystemMenu(FALSE);
            if (pSysMenu != NULL)
            {
                        CString strAboutMenu;
                        strAboutMenu.LoadString(IDS_ABOUTBOX);
                        if (!strAboutMenu.IsEmpty())
                        {
                                   pSysMenu->AppendMenu(MF_SEPARATOR);
                                   pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
                        }
            }
 
            // Set the icon for this dialog.  The framework does this automatically
            //  when the application's main window is not a dialog
            SetIcon(m_hIcon, TRUE);                            // Set big icon
            SetIcon(m_hIcon, FALSE);              // Set small icon
 
            // TODO: Add extra initialization here
 
    menu.LoadMenu(IDR_MENU_TRAY);
            SetMenu(&menu);
             // Установка всех полей структуры в 0
    memset(&tray_icon, 0, sizeof(NOTIFYICONDATA));
    // Размерструктуры
    tray_icon.cbSize = sizeof(NOTIFYICONDATA);
    // Иконка
    tray_icon.hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    // Дескриптор окна, получающего сообщения из трэя
    tray_icon.hWnd = m_hWnd;
    // Подсказка
    strcpy(tray_icon.szTip, "Get Screen");
    // Идентификаторобработчика
    tray_icon.uCallbackMessage = WM_ICON;
    // Установкафлагов
    tray_icon.uFlags = NIF_TIP | NIF_MESSAGE | NIF_ICON;
    // Идентификаториконки
    tray_icon.uID = ID_TrayIcon;
 
 
 
            return TRUE;  // return TRUE  unless you set the focus to a control
}
 
void CscreencaptureDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
            if ((nID & 0xFFF0) == IDM_ABOUTBOX)
            {
                        CAboutDlg dlgAbout;
                        dlgAbout.DoModal();
            }
            else
            {
                        CDialog::OnSysCommand(nID, lParam);
            }
}
 
// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.
 
 
// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CscreencaptureDlg::OnQueryDragIcon()
{
            return static_cast(m_hIcon);
}
 
void CscreencaptureDlg::OnActionExit()
{
            EndDialog(0);
 
}
 
void CscreencaptureDlg::OnActionHide()
{
                    ShowWindow(SW_HIDE);
                                   //окноминимизируется
     
        Shell_NotifyIcon(NIM_ADD, &tray_icon);
                          // Втреепоявляетсяиконка
 
}
 
LRESULT CscreencaptureDlg::OnTrayIcon(WPARAM wp, LPARAM lp)
{
             if(wp != tray_icon.uID || lp != WM_LBUTTONDBLCLK &&
       lp != WM_RBUTTONUP)
        return 0;
 
    // Получениеподменю
    CMenu *SubMenu = menu.GetSubMenu(0);
   
    // Если была нажата правая кнопка мыши
    if(lp == WM_RBUTTONUP)
    {
        // Первый пункт меню выделяется "жирным" шрифтом
        SubMenu->SetDefaultItem(0, true);
        // Получение позиции курсора
        CPoint mouse;
        GetCursorPos(&mouse);
        // Установка окна, которое будет получать фокус
        // (в данном случае это иконка и связанное с ней меню)
        ::SetForegroundWindow(tray_icon.hWnd);
        // Отображение контекстного меню
        SubMenu->TrackPopupMenu(0, mouse.x, mouse.y, this);
    }
    // Если была дважды нажата левая кнопка мыши
    else if(lp == WM_LBUTTONDBLCLK)
        // Имитация выбора пункта меню по умолчанию
        ::SendMessage(tray_icon.hWnd, WM_COMMAND,
                      SubMenu->GetMenuItemID(0), 0);
    return 1;
           
}
 
void CscreencaptureDlg::OnActionRestore()
{
   // Удалениеиконкиизтрэя
    Shell_NotifyIcon(NIM_DELETE, &tray_icon);
  
    // Отображение главного окна
    ShowWindow(SW_NORMAL);
    // Теперь фокус будет получать главное окно
    ::SetForegroundWindow(m_hWnd);       
 
}
 
void CscreencaptureDlg::GetScreen(void)
{
            CString path="c:\\bmp\\screen.bmp";
            //задаем путь к файлу, в которм будет храниться картинка
    int Width=GetSystemMetrics(SM_CXSCREEN);
            //получемширину  экрана
            int Height=GetSystemMetrics(SM_CYSCREEN);
            //получем высоту экрана
            CDC dc;
            //локальная переменная контекста устройства
            HDC h=::GetDC(NULL);
            //получаем дескриптор окна
            dc.Attach(h);
            //присоединемя его к переменной контекста устройства
            DC.CreateCompatibleDC(&dc);
            //размещаем данный контекст устройства в памяти
            CBitmap Win;
            //cоздаем локальную переменную класса CBitmap
            Win.CreateCompatibleBitmap(&dc,Width,Height);
   //cоздаем совместимый с bimap контекст устройства
            DC.SelectObject(&Win);
            //выбираем контекст устройства
            DC.BitBlt(0,0,Width,Height,&dc,0,0,SRCCOPY);
            //копируем указанную область экрана
            dc.Detach();
            //освобождаем локальный контекст устройства
            ::ReleaseDC(NULL, h);
            SaveBitmap(path,(HBITMAP)Win,0);
            DC.DeleteDC();
            //освобождаемглобальныйконтекстустройства
            MessageBox("This screen was caputered well");
            //сообщение об успешном выполнени задачи
           
 
}
 
void CscreencaptureDlg::OnActionGetscreen()
{
  ShowWindow(SW_HIDE);
  //скрываем основное окно программы
  ::Sleep(1000);
  //задержка исполнения в миллисекундах
  GetScreen();
  //получаем картинку экрана
  Shell_NotifyIcon(NIM_ADD, &tray_icon);
  //убираем программу в трей
 
}
 
BOOL CscreencaptureDlg::SaveBitmap(LPCSTR FileName, HBITMAP hBitmap, HPALETTE  hPal)
{
   BOOL bResult = FALSE;
   //служебная булевая переменная
 
   PICTDESC stPictDesc;
   // переменная структуры  PICTDESC  для описания картинки
   stPictDesc.cbSizeofstruct = sizeof(PICTDESC);
   //задаем размеры переменной этой структуры
   stPictDesc.picType = PICTYPE_BITMAP;
   stPictDesc.bmp.hbitmap = hBitmap;
    //устанавливаемтипкак bitmap
   stPictDesc.bmp.hpal = hPal;
   //выбираем текущую палитру
 
   LPPICTURE pPicture;
   //создаем переменную структуры, содержащую информацию о клиентcкой области
   HRESULT hr = OleCreatePictureIndirect( &stPictDesc, IID_IPicture, FALSE, reinterpret_cast(&pPicture) );
   //создаем объект  картинку
  
   if ( SUCCEEDED(hr) )
   {
   //если картинка создана
      LPSTREAM pStream;
      hr = CreateStreamOnHGlobal( NULL, TRUE, &pStream );
 
              //создаем объект Strem  в памяти используя полученный объект hr 
      if ( SUCCEEDED(hr) )
      {
                         
         long lBytesStreamed = 0;
         hr = pPicture->SaveAsFile( pStream, TRUE, &lBytesStreamed );
                         //сохраняем картинку в файле
         if ( SUCCEEDED(hr) )
         {
            HANDLE hFile = CreateFile( FileName,
                                       GENERIC_WRITE,
                                       FILE_SHARE_READ,
                                       NULL,
                                       CREATE_ALWAYS,
                                       FILE_ATTRIBUTE_NORMAL,
                                       NULL );
           //создаемдескрипторфайла
 
            if ( hFile )
            {
               HGLOBAL hMem = NULL;
               GetHGlobalFromStream( pStream, &hMem );
               LPVOID lpData = GlobalLock( hMem );
 
               DWORD dwBytesWritten;
               bResult = WriteFile( hFile, lpData, lBytesStreamed, &dwBytesWritten, NULL );
               bResult &= ( dwBytesWritten == (DWORD)lBytesStreamed );
              //записываемданныеизпамятивфайл
            
               GlobalUnlock(hMem);
               CloseHandle(hFile);
 
            }
         }
            
         pStream->Release();
      }
       
      pPicture->Release();
   }
//освобождаемиспользуемыересурсы
   return bResult;  
 
 
}
 
// stdafx.cpp : source file that includes just the standard includes
// screencapture.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
 
#include "stdafx.h"

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by screencapture.rc
//
#define IDM_ABOUTBOX                    0x0010
#define IDD_ABOUTBOX                    100
#define IDS_ABOUTBOX                    101
#define IDD_SCREENCAPTURE_DIALOG        102
#define IDR_MAINFRAME                   128
#define IDR_MENU1                       129
#define IDR_MENU_TRAY                   129
#define ID_ACTION_GETSCREEN             32771
#define ID_ACTION_HIDE                  32772
#define ID_ACTION_RESTORE               32773
#define ID_ACTION_EXIT                  32774
#define ID_TrayIcon                     135
 
 
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        130
#define _APS_NEXT_COMMAND_VALUE         32775
#define _APS_NEXT_CONTROL_VALUE         1000
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

// screencapture.h : main header file for the PROJECT_NAME application
//
 
#pragma once
 
#ifndef __AFXWIN_H__
            #error include 'stdafx.h' before including this file for PCH
#endif
 
#include "resource.h"             // main symbols
 
 
// CscreencaptureApp:
// See screencapture.cpp for the implementation of this class
//
 
class CscreencaptureApp : public CWinApp
{
public:
            CscreencaptureApp();
 
// Overrides
            public:
            virtual BOOL InitInstance();
 
// Implementation
 
            DECLARE_MESSAGE_MAP()
};
 
extern CscreencaptureApp theApp;
 
 
 
 
 
// screencaptureDlg.h : header file
//
 
#pragma once
#include "afxwin.h"
 
 
 
 
// CscreencaptureDlg dialog
class CscreencaptureDlg : public CDialog
{
// Construction
public:
            CscreencaptureDlg(CWnd* pParent = NULL);       // standard constructor
 
// Dialog Data
            enum { IDD = IDD_SCREENCAPTURE_DIALOG };
 
            protected:
            virtual void DoDataExchange(CDataExchange* pDX);     // DDX/DDV support
 
 
// Implementation
protected:
            HICON m_hIcon;
 
            // Generated message map functions
            virtual BOOL OnInitDialog();
            afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
            afx_msg void OnPaint();
            afx_msg HCURSOR OnQueryDragIcon();
            DECLARE_MESSAGE_MAP()
public:
            NOTIFYICONDATA tray_icon;
            CMenu menu;
            afx_msg void OnActionExit();
            afx_msg void OnActionHide();
            LRESULT OnTrayIcon(WPARAM wp, LPARAM lp);
            afx_msg void OnActionRestore();
            CDC DC;
            void GetScreen(void);
            afx_msg void OnActionGetscreen();
            BOOL SaveBitmap(LPCSTR FileName, HBITMAP hBitmap, HPALETTE  hPal);
};
 
 
 
 
 
 
 
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently,
// but are changed infrequently
 
#pragma once
 
#ifndef VC_EXTRALEAN
#define VC_EXTRALEAN             // Exclude rarely-used stuff from Windows headers
#endif
 
// Modify the following defines if you have to target a platform prior to the ones specified below.
// Refer to MSDN for the latest info on corresponding values for different platforms.
#ifndef WINVER                                         // Allow use of features specific to Windows 95 and Windows NT 4 or later.
#define WINVER 0x0400                // Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
#endif
 
#ifndef _WIN32_WINNT                // Allow use of features specific to Windows NT 4 or later.
#define _WIN32_WINNT 0x0400               // Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
#endif                                                           
 
#ifndef _WIN32_WINDOWS                     // Allow use of features specific to Windows 98 or later.
#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
#endif
 
#ifndef _WIN32_IE                          // Allow use of features specific to IE 4.0 or later.
#define _WIN32_IE 0x0400// Change this to the appropriate value to target IE 5.0 or later.
#endif
 
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS         // some CString constructors will be explicit
 
// turns off MFC's hiding of some common and often safely ignored warning messages
#define _AFX_ALL_WARNINGS
 
#include          // MFC core and standard components
#include          // MFC extensions
#include         // MFC Automation classes
 
#include                         // MFC support for Internet Explorer 4 Common Controls
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include                          // MFC support for Windows Common Controls
#endif // _AFX_NO_AFXCMN_SUPPORT
 


Здесь нет комментариев


Новый комментарий:
























Яндекс.Метрика