Skip to content

Commit

Permalink
capture screen and generate pdf
Browse files Browse the repository at this point in the history
  • Loading branch information
koyumi0601 committed Mar 8, 2024
1 parent 0534318 commit 09c3863
Show file tree
Hide file tree
Showing 120 changed files with 10,221 additions and 0 deletions.
396 changes: 396 additions & 0 deletions .gitignore

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
---
layout: single
title: "visual studio - capture window using gdiplus and pdf generation using magick++ "
categories: cuda
tags: [language, programming, cpp, magick++]
toc: true
author_profile: false
sidebar:
nav: "docs"
search: true

---

*program, capture window using gdiplus and pdf generation using magick++*

# Brief
- 책 viewer에서 필기하면서 공부하는 것이 되지 않아서, 화면을 캡쳐하여 pdf로 변환하여 사용했다.
- 다음장 클릭은 특정 화면 위치를 하드코딩했다
- 캡쳐 영역도 하드코딩 되어 있다
- doxygen 생성되어 있으니 index.html 참고

# Code
```cpp
// main.cpp
#include <iostream> // Input/output stream
#include <vector> // Dynamic array container
#include <windows.h> // Windows API header
#include <gdiplus.h> // Microsoft GDI+ header
#include <shlwapi.h> // Shell Light-weight Utility Functions header
#include <sstream> // String stream processing
#include <gdiplusheaders.h> // Microsoft GDI+ header (declarations)
#include <Magick++.h> // ImageMagick++ header

#pragma comment(lib, "gdiplus.lib") // Linker directive for GDI+ library
#pragma comment(lib, "shlwapi.lib") // Linker directive for Shell Light-weight API library


/**
* @brief 지정된 폴더에서 특정 확장자를 가진 파일 목록을 검색합니다.
*
* @param folder 검색할 폴더 경로 (유니코드 문자열)
* @param extension 검색할 확장자 (유니코드 문자열)
* @return std::vector<std::string> 검색된 파일 목록 (유니코드 문자열을 ANSI 문자열로 변환하여 반환)
*/
std::vector<std::string> findFilesWithExtension(const std::wstring& folder, const std::wstring& extension) {
std::vector<std::string> files;
WIN32_FIND_DATAW findFileData;
HANDLE hFind = FindFirstFileW((folder + L"\\*" + extension).c_str(), &findFileData);
if (hFind != INVALID_HANDLE_VALUE) {
do {
if (!(findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
std::wstring wideFilePath = folder + L"\\" + findFileData.cFileName;
std::string filePath(wideFilePath.begin(), wideFilePath.end());
files.push_back(filePath);
}
} while (FindNextFileW(hFind, &findFileData) != 0);
FindClose(hFind);
}
else {
std::cerr << "Error: Failed to find files in directory." << std::endl;
}

return files;
}

/**
* @brief 지정된 이미지 형식에 대한 인코더의 CLSID를 검색합니다.
*
* @param format 이미지 형식을 지정하는 문자열 포인터 (널 종료 유니코드 문자열)
* @param pClsid 검색된 인코더의 CLSID를 저장할 CLSID 포인터
* @return int CLSID 검색 결과를 나타내는 정수 값 (-1: 실패, 0 이상: 성공 및 인덱스)
*/
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid) {
UINT num = 0; // Number of image encoders
UINT size = 0; // Size of the image encoder array in bytes
// Get the size of the image encoder array
Gdiplus::GetImageEncodersSize(&num, &size);
if (size == 0)
return -1; // Failure
// Create a buffer to hold the encoder array
Gdiplus::ImageCodecInfo* imageCodecInfo = (Gdiplus::ImageCodecInfo*)(malloc(size));
if (imageCodecInfo == NULL)
return -1; // Failure
// Get the image encoder array
GetImageEncoders(num, size, imageCodecInfo);
// Find the CLSID for the specified format
for (UINT i = 0; i < num; ++i) {
if (wcscmp(imageCodecInfo[i].MimeType, format) == 0) {
*pClsid = imageCodecInfo[i].Clsid;
free(imageCodecInfo);
return i; // Success
}
}
free(imageCodecInfo);
return -1; // Failure
}

/**
* @brief 지정된 화면 좌표에 마우스를 클릭하는 함수입니다.
*
* @param x 클릭할 위치의 x 좌표
* @param y 클릭할 위치의 y 좌표
*/
void ClickMouse(int x, int y) {
INPUT input = { 0 };
input.type = INPUT_MOUSE;
input.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
input.mi.dx = x * (65536 / GetSystemMetrics(SM_CXSCREEN));
input.mi.dy = y * (65536 / GetSystemMetrics(SM_CYSCREEN));
SendInput(1, &input, sizeof(INPUT));
input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
SendInput(1, &input, sizeof(INPUT));
Sleep(10);
input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
SendInput(1, &input, sizeof(INPUT));
}

/**
* @brief 지정된 영역을 캡처하고 각 페이지의 이미지를 저장하는 함수입니다.
*
* @param folder 이미지를 저장할 폴더의 경로
*/
void CaptureRegionFor(const std::wstring& folder) {
RECT region; // 캡처할 영역의 좌표를 저장하는 구조체
std::wstringstream ss; // 문자열 스트림 생성
LPCWSTR filename = ss.str().c_str(); // 파일 이름을 LPCWSTR로 변환
region.left = 280; // 캡처 영역의 왼쪽 좌표
region.top = 80; // 캡처 영역의 상단 좌표
region.right = 1700; // 캡처 영역의 오른쪽 좌표
region.bottom = 980; // 캡처 영역의 하단 좌표
Gdiplus::GdiplusStartupInput gdiplusStartupInput; // GDI+ 초기화 입력 구조체 생성
ULONG_PTR gdiplusToken; // GDI+ 토큰 변수
Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); // GDI+ 초기화
for (int j = 0; j < 156; j++) { // 각 페이지에 대한 반복문
std::cout << "page pair number: " << j << std::endl; // 페이지 번호 출력
int width = region.right - region.left; // 캡처 영역의 너비
int height = region.bottom - region.top; // 캡처 영역의 높이
HDC hdcScreen = GetDC(NULL); // 화면의 디바이스 컨텍스트 핸들 가져오기
HDC hdcMem = CreateCompatibleDC(hdcScreen); // 호환되는 메모리 DC 생성
HBITMAP hBitmap = CreateCompatibleBitmap(hdcScreen, width, height); // 호환되는 비트맵 생성
HGDIOBJ hOldBitmap = SelectObject(hdcMem, hBitmap); // 메모리 DC에 비트맵 선택
BitBlt(hdcMem, 0, 0, width, height, hdcScreen, region.left, region.top, SRCCOPY); // 화면에서 비트맵에 이미지 복사
Gdiplus::Bitmap bitmap(hBitmap, NULL); // GDI+ 비트맵 객체 생성
CLSID clsid; // 이미지 인코더의 CLSID
GetEncoderClsid(L"image/png", &clsid); // PNG 이미지의 인코더 CLSID 가져오기
CHAR exePath[MAX_PATH]; // 실행 파일 경로를 저장할 문자열 버퍼
GetModuleFileNameA(NULL, exePath, MAX_PATH); // 실행 파일 경로 가져오기
PathRemoveFileSpecA(exePath); // 경로에서 파일 이름 제거
WCHAR imagePath[MAX_PATH]; // 이미지 파일 경로를 저장할 유니코드 문자열 버퍼
swprintf_s(imagePath, MAX_PATH, L"%s\\_%03d.png", folder.c_str(), j); // 이미지 파일 경로 생성
bitmap.Save(imagePath, &clsid); // 이미지를 지정된 경로에 저장
SelectObject(hdcMem, hOldBitmap); // 비트맵 선택 해제
DeleteObject(hBitmap); // 비트맵 객체 삭제
DeleteDC(hdcMem); // 메모리 DC 삭제
ReleaseDC(NULL, hdcScreen); // 화면 DC 해제
Sleep(1000); // 1초 대기
int clickX = 1880; // 마우스 클릭 위치의 x 좌표
int clickY = 540; // 마우스 클릭 위치의 y 좌표
ClickMouse(clickX, clickY); // 마우스 클릭 함수 호출
Sleep(1000); // 1초 대기
}
Gdiplus::GdiplusShutdown(gdiplusToken); // GDI+ 종료
std::cout << "Capture Complete\n"; // 캡처 완료 메시지 출력
}

/**
* @brief 여러 이미지 파일을 하나의 PDF 파일로 변환하는 함수입니다.
*
* @param imageFiles 변환할 이미지 파일들의 경로를 포함하는 벡터
* @param pdfFilename PDF 파일의 이름 및 경로
*/
void imagesToPdf(const std::vector<std::string>& imageFiles, const std::string& pdfFilename) {
Magick::InitializeMagick(nullptr); // Magick++ 초기화
std::vector<Magick::Image> images; // Magick++ 이미지 객체를 담을 벡터 생성
for (const auto& file : imageFiles) { // 각 이미지 파일에 대한 반복문
Magick::Image image; // Magick++ 이미지 객체 생성
image.read(file); // 이미지 파일을 읽어들임
images.push_back(image); // 벡터에 이미지 추가
}
Magick::writeImages(images.begin(), images.end(), pdfFilename); // 이미지들을 PDF 파일로 작성
std::cout << "PDF file created successfully: " << pdfFilename << std::endl; // PDF 파일 생성 완료 메시지 출력

}

/**
* @brief 프로그램의 메인 함수입니다.
*
* @details bookviewer의 영역을 캡쳐하고, 다음 페이지 버튼을 클릭한 후, png 파일로 만듭니다. 모든 png 파일을 pdf로 합칩니다.
*
* @return 프로그램 종료 코드
*/
int main() {
std::wstring folderPath = L".\\output"; // 이미지 파일이 저장된 폴더 경로
CaptureRegionFor(folderPath); // 화면 캡처를 통해 이미지를 생성하는 함수 호출
std::wstring extension = L".png"; // 찾고자 하는 이미지 파일의 확장자
std::vector<std::string> pngFiles = findFilesWithExtension(folderPath, extension); // 지정된 폴더에서 확장자가 .png인 파일을 찾아 벡터로 반환
std::string pdfFilename = "output_new.pdf"; // 생성할 PDF 파일의 이름
imagesToPdf(pngFiles, pdfFilename); // 이미지 파일을 PDF 파일로 변환하는 함수 호출
return 0; // 프로그램 종료
}
```
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.8.34408.163
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CaptureMonitorAndPdfGeneration", "CaptureMonitorAndPdfGeneration.vcxproj", "{71CBCEF4-0E0D-427D-8086-67E8DCD04E60}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{71CBCEF4-0E0D-427D-8086-67E8DCD04E60}.Debug|x64.ActiveCfg = Debug|x64
{71CBCEF4-0E0D-427D-8086-67E8DCD04E60}.Debug|x64.Build.0 = Debug|x64
{71CBCEF4-0E0D-427D-8086-67E8DCD04E60}.Release|x64.ActiveCfg = Release|x64
{71CBCEF4-0E0D-427D-8086-67E8DCD04E60}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F0ADAFEE-885F-49CD-AE47-D2B41B3A030E}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{71CBCEF4-0E0D-427D-8086-67E8DCD04E60}</ProjectGuid>
<RootNamespace>CaptureMonitorAndPdfGeneration</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v143</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
<Import Project="$(VCTargetsPath)\BuildCustomizations\CUDA 12.3.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>D:\Program Files\ImageMagick-7.1.1-Q16-HDRI\include;C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt;D:\Github_Blog\Development_libraries\opencv\build\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>D:\Program Files\ImageMagick-7.1.1-Q16-HDRI\include;C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt;D:\Github_Blog\Development_libraries\opencv\build\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>CORE_RL_Magick++_.lib;CORE_RL_MagickCore_.lib;CORE_RL_MagickWand_.lib;opencv_world480d.lib;opencv_world480.lib;cudart_static.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>D:\Program Files\ImageMagick-7.1.1-Q16-HDRI\lib;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.22621.0\ucrt\x64;D:\Github_Blog\Development_libraries\opencv\build\x64\vc16\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<CudaCompile>
<TargetMachinePlatform>64</TargetMachinePlatform>
</CudaCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>CORE_RL_Magick++_.lib;CORE_RL_MagickCore_.lib;CORE_RL_MagickWand_.lib;opencv_world480d.lib;opencv_world480.lib;cudart_static.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>D:\Program Files\ImageMagick-7.1.1-Q16-HDRI\lib;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.22621.0\ucrt\x64;D:\Github_Blog\Development_libraries\opencv\build\x64\vc16\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<CudaCompile>
<TargetMachinePlatform>64</TargetMachinePlatform>
</CudaCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(VCTargetsPath)\BuildCustomizations\CUDA 12.3.targets" />
</ImportGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>
Loading

0 comments on commit 09c3863

Please sign in to comment.