Skip to content

Commit ba22942

Browse files
committed
Add Generate Report menu item
1 parent 4a7715c commit ba22942

File tree

6 files changed

+177
-4
lines changed

6 files changed

+177
-4
lines changed

Diff for: src/WinWebDiff/Resource.h

+5-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88
#define IDM_ABOUT 104
99
#define IDM_EXIT 105
1010
#define IDM_FILE_NEW 106
11-
#define IDM_FILE_NEW_TAB 107
12-
#define IDM_FILE_CLOSE_TAB 108
13-
#define IDM_FILE_RELOAD 109
11+
#define IDM_FILE_NEW3 107
12+
#define IDM_FILE_NEW_TAB 108
13+
#define IDM_FILE_CLOSE_TAB 109
14+
#define IDM_FILE_RELOAD 110
15+
#define IDM_FILE_GENERATE_REPORT 111
1416
#define IDM_VIEW_SIZE_FIT_TO_WINDOW 120
1517
#define IDM_VIEW_SIZE_320x512 121
1618
#define IDM_VIEW_SIZE_375x600 122

Diff for: src/WinWebDiff/WinWebDiff.cpp

+125
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@
44
#include <combaseapi.h>
55
#include <shellapi.h>
66
#include <CommCtrl.h>
7+
#include <commdlg.h>
8+
#include <Shlwapi.h>
79
#include <string>
810
#include <vector>
911
#include <list>
1012
#include <filesystem>
13+
#include <iostream>
14+
#include <fstream>
1115
#include <wrl.h>
1216

1317
#pragma comment(lib, "comctl32.lib")
@@ -265,6 +269,97 @@ bool CompareFiles(const std::vector<std::wstring>& filenames, const std::wstring
265269
return true;
266270
}
267271

272+
std::string ToUTF8(const wchar_t* text)
273+
{
274+
int size = WideCharToMultiByte(CP_UTF8, 0, text, -1, nullptr, 0, NULL, NULL);
275+
std::string utf8(size, 0);
276+
WideCharToMultiByte(CP_UTF8, 0, text, -1, utf8.data(), static_cast<int>(utf8.size()), NULL, NULL);
277+
utf8.resize(strlen(utf8.c_str()));
278+
return utf8;
279+
}
280+
281+
void AppMsgBox(const std::wstring& text, int types)
282+
{
283+
PostMessage(m_hWnd, WM_USER + 100, reinterpret_cast<WPARAM>(new std::wstring(text)), types);
284+
}
285+
286+
bool GenerateHTMLReport(const wchar_t* filename)
287+
{
288+
const int BUFFER_SIZE = 4096;
289+
wchar_t tmp[BUFFER_SIZE];
290+
wchar_t rptdir_full[BUFFER_SIZE];
291+
std::wstring rptdir;
292+
std::wstring rptfilepath[3];
293+
std::wstring difffilename[3];
294+
std::vector<std::string> rptfilepath_utf8, difffilename_utf8;
295+
wcscpy_s(rptdir_full, filename);
296+
PathRemoveExtensionW(rptdir_full);
297+
PathAddExtensionW(rptdir_full, L".files");
298+
rptdir = PathFindFileName(rptdir_full);
299+
CreateDirectoryW(rptdir_full, nullptr);
300+
const wchar_t* pfilenames[3]{};
301+
std::vector<std::wstring> filenames;
302+
for (int i = 0; i < m_pWebDiffWindow->GetPaneCount(); ++i)
303+
{
304+
rptfilepath[i] = m_pWebDiffWindow->GetCurrentUrl(i);
305+
rptfilepath_utf8.push_back(ToUTF8(rptfilepath[i].c_str()));
306+
wsprintfW(tmp, L"%d.pdf", i + 1);
307+
difffilename[i] = rptdir + L"/" + tmp;
308+
difffilename_utf8.push_back(ToUTF8(difffilename[i].c_str()));
309+
filenames.push_back(std::wstring(rptdir_full) + L"/" + tmp);
310+
pfilenames[i] = filenames[i].c_str();
311+
}
312+
std::ofstream fout;
313+
try
314+
{
315+
fout.open(filename, std::ios::out | std::ios::trunc);
316+
fout <<
317+
"<!DOCTYPE html>" << std::endl <<
318+
"<html>" << std::endl <<
319+
"<head>" << std::endl <<
320+
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">" << std::endl <<
321+
"<title>WinMerge Webpage Compare Report</title>" << std::endl <<
322+
"<style type=\"text/css\">" << std::endl <<
323+
"table { table-layout: fixed; width: 100%; border-collapse: collapse; }" << std::endl <<
324+
"th,td { border: solid 1px black; }" << std::endl <<
325+
"embed { width: 100%; height: calc(100vh - 56px) }" << std::endl <<
326+
".title { color: white; background-color: blue; vertical-align: top; }" << std::endl <<
327+
"</style>" << std::endl <<
328+
"</head>" << std::endl <<
329+
"<body>" << std::endl <<
330+
"<table>" << std::endl <<
331+
"<tr>" << std::endl;
332+
for (int i = 0; i < m_pWebDiffWindow->GetPaneCount(); ++i)
333+
fout << "<th class=\"title\">" << rptfilepath_utf8[i] << "</th>" << std::endl;
334+
fout <<
335+
"</tr>" << std::endl <<
336+
"<tr>" << std::endl;
337+
for (int i = 0; i < m_pWebDiffWindow->GetPaneCount(); ++i)
338+
fout << "<td><embed type=\"application/pdf\" src=\"" << difffilename_utf8[i] <<
339+
"\" title=\"" << difffilename_utf8[i] << "\"></td>" << std::endl;
340+
fout <<
341+
"</tr>" << std::endl <<
342+
"</table>" << std::endl <<
343+
"</body>" << std::endl <<
344+
"</html>" << std::endl;
345+
}
346+
catch (...)
347+
{
348+
return false;
349+
}
350+
m_pWebDiffWindow->SaveDiffFiles(IWebDiffWindow::PDF, pfilenames,
351+
Callback<IWebDiffCallback>([](const WebDiffCallbackResult& result) -> HRESULT
352+
{
353+
if (SUCCEEDED(result.errorCode))
354+
AppMsgBox(L"The report has been created successfully.", MB_OK | MB_ICONINFORMATION);
355+
else
356+
AppMsgBox(L"Failed to create the report", MB_OK | MB_ICONWARNING);
357+
return S_OK;
358+
})
359+
.Get());
360+
return true;
361+
}
362+
268363
void UpdateMenuState(HWND hWnd)
269364
{
270365
HMENU hMenu = GetMenu(hWnd);
@@ -300,6 +395,9 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
300395
case IDM_FILE_NEW:
301396
m_pWebDiffWindow->New(2, nullptr);
302397
break;
398+
case IDM_FILE_NEW3:
399+
m_pWebDiffWindow->New(3, nullptr);
400+
break;
303401
case IDM_FILE_NEW_TAB:
304402
{
305403
int nActivePane = m_pWebDiffWindow->GetActivePane();
@@ -315,6 +413,26 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
315413
case IDM_FILE_RELOAD:
316414
m_pWebDiffWindow->ReloadAll();
317415
break;
416+
case IDM_FILE_GENERATE_REPORT:
417+
{
418+
wchar_t szFileName[MAX_PATH] = {0}, szFile[MAX_PATH] = {0};
419+
OPENFILENAMEW ofn = {0};
420+
ofn.lStructSize = sizeof(OPENFILENAME);
421+
ofn.hwndOwner = hWnd;
422+
ofn.lpstrFilter = L"HTML file(*.html)\0*.html\0\0";
423+
ofn.lpstrFile = szFileName;
424+
ofn.lpstrFileTitle = szFile;
425+
ofn.nMaxFile = MAX_PATH;
426+
ofn.nMaxFileTitle = sizeof(szFile);
427+
ofn.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY;
428+
ofn.lpstrTitle = L"Generate HTML Report File";
429+
ofn.lpstrDefExt = L"html";
430+
if (GetSaveFileNameW(&ofn) != 0)
431+
{
432+
GenerateHTMLReport(ofn.lpstrFile);
433+
}
434+
break;
435+
}
318436
case IDM_EXIT:
319437
DestroyWindow(hWnd);
320438
break;
@@ -482,6 +600,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
482600
}
483601
break;
484602
}
603+
case WM_USER + 100:
604+
{
605+
std::wstring* ptext = reinterpret_cast<std::wstring*>(wParam);
606+
MessageBoxW(m_hWnd, ptext->c_str(), L"WinWebDiff", static_cast<int>(lParam));
607+
delete ptext;
608+
break;
609+
}
485610
case WM_PAINT:
486611
{
487612
PAINTSTRUCT ps;

Diff for: src/WinWebDiff/WinWebDiff.rc

442 Bytes
Binary file not shown.

Diff for: src/WinWebDiffLib/WebDiffWindow.hpp

+16
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,22 @@ class CWebDiffWindow : public IWebDiffWindow
240240
}).Get());
241241
}
242242

243+
HRESULT SaveDiffFiles(FormatType kind, const wchar_t* filenames[], IWebDiffCallback* callback) override
244+
{
245+
auto sfilenames = std::make_shared<std::vector<std::wstring>>();
246+
for (int pane = 0; pane < m_nPanes; ++pane)
247+
sfilenames->push_back(filenames[pane]);
248+
ComPtr<IWebDiffCallback> callback2(callback);
249+
HRESULT hr = saveFilesLoop(kind, sfilenames,
250+
Callback<IWebDiffCallback>([this, sfilenames, callback2](const WebDiffCallbackResult& result) -> HRESULT
251+
{
252+
if (callback2)
253+
return callback2->Invoke({ result.errorCode, nullptr });
254+
return S_OK;
255+
}).Get());
256+
return hr;
257+
}
258+
243259
HRESULT ClearBrowsingData(int pane, BrowsingDataType datakinds) override
244260
{
245261
int spane = pane, epane = pane;

Diff for: src/WinWebDiffLib/WebWindow.hpp

+29
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,8 @@ class CWebWindow
548548
return SaveText(filename, callback);
549549
case IWebDiffWindow::RESOURCETREE:
550550
return SaveResourceTree(filename, callback);
551+
case IWebDiffWindow::PDF:
552+
return SavePDF(filename, callback);
551553
default:
552554
return E_INVALIDARG;
553555
}
@@ -974,6 +976,33 @@ class CWebWindow
974976
return hr;
975977
}
976978

979+
HRESULT SavePDF(const std::wstring& filename, IWebDiffCallback* callback)
980+
{
981+
if (!GetActiveWebView())
982+
return E_FAIL;
983+
ComPtr<IWebDiffCallback> callback2(callback);
984+
wil::com_ptr<ICoreWebView2_7> webview2_7 = GetActiveTab()->m_webview.try_query<ICoreWebView2_7>();
985+
if (!webview2_7)
986+
return E_NOINTERFACE;
987+
wil::com_ptr<ICoreWebView2PrintSettings> printSettings;
988+
wil::com_ptr<ICoreWebView2Environment6> webviewEnvironment6 = m_webviewEnvironment.try_query<ICoreWebView2Environment6>();
989+
if (webviewEnvironment6)
990+
{
991+
webviewEnvironment6->CreatePrintSettings(&printSettings);
992+
printSettings->put_ShouldPrintBackgrounds(true);
993+
}
994+
HRESULT hr = webview2_7->PrintToPdf(filename.c_str(), printSettings.get(),
995+
Callback<ICoreWebView2PrintToPdfCompletedHandler>(
996+
[callback2](HRESULT errorCode, BOOL isSucessful) -> HRESULT {
997+
if (callback2)
998+
return callback2->Invoke({ errorCode, nullptr});
999+
return S_OK;
1000+
}).Get());
1001+
if (FAILED(hr) && callback2)
1002+
return callback2->Invoke({ hr, nullptr });
1003+
return hr;
1004+
}
1005+
9771006
HRESULT CallDevToolsProtocolMethod(const wchar_t* methodName, const wchar_t* params, IWebDiffCallback *callback, bool showError = true)
9781007
{
9791008
if (!GetActiveWebView())

Diff for: src/WinWebDiffLib/WinWebDiffLib.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ struct IWebDiffWindow
3535
};
3636
enum FormatType
3737
{
38-
SCREENSHOT, FULLSIZE_SCREENSHOT, HTML, TEXT, RESOURCETREE
38+
SCREENSHOT, FULLSIZE_SCREENSHOT, HTML, TEXT, RESOURCETREE, PDF
3939
};
4040
enum BrowsingDataType
4141
{
@@ -116,6 +116,7 @@ struct IWebDiffWindow
116116
virtual HRESULT Recompare(IWebDiffCallback* callback) = 0;
117117
virtual HRESULT SaveFile(int pane, FormatType kind, const wchar_t* filename, IWebDiffCallback* callback) = 0;
118118
virtual HRESULT SaveFiles(FormatType kind, const wchar_t* filenames[], IWebDiffCallback* callback) = 0;
119+
virtual HRESULT SaveDiffFiles(FormatType kind, const wchar_t* filenames[], IWebDiffCallback* callback) = 0;
119120
virtual HRESULT ClearBrowsingData(int pane, BrowsingDataType datakinds) = 0;
120121
virtual const wchar_t *GetCurrentUrl(int pane) = 0;
121122
virtual int GetPaneCount() const = 0;

0 commit comments

Comments
 (0)