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+
268363void 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;
0 commit comments